Whamcloud - gitweb
LU-9874 osd-ldiskfs: simplify project transfer codes 10/28510/4
authorWang Shilong <wshilong@ddn.com>
Tue, 27 Jun 2017 05:51:09 +0000 (13:51 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 28 Aug 2017 06:27:09 +0000 (06:27 +0000)
Currently, osd-ldiskfs call __ldiskfs_ioctl_project()
to transfer project quota which is user ioctl for ext4 which
will start a transaction, and reserve credits, this is not
right logic with Lustre.

Lustre have started a transaction handle and credits should be
reserved during declare phase, so calling _ldiskfs_ioctl_project()
here will cause nested handle starting, which is not a problem for
JBD2 because it will attach current thread's handle if transaction
have been started, but in this case it will ignore credits
reservation.

Also Lustre don't need inode mutex protection for
project transfer, we don't need write inode in transfer codes,
it will be done when dirty inode is called. Setting attr
have reserved enough credits for project transfer, we need
fix agent inode transfering.

This patch makes codes logic clear, also fix credits
reservation for DNE agent inode transfering.

Change-Id: I6ab3c0fdc4cf456b102e49d9326840fd0e12ade0
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-on: https://review.whamcloud.com/28510
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Hongchao Zhang <hongchao.zhang@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
ldiskfs/kernel_patches/patches/rhel7/ext4-projid-xfs-ioctls.patch
lustre/osd-ldiskfs/osd_handler.c

index a3ef640..5e7939a 100644 (file)
@@ -1,8 +1,8 @@
 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
-index 31317c9..39b31aa 100644
+index ce3b85f..29db502 100644
 --- a/fs/ext4/ext4.h
 +++ b/fs/ext4/ext4.h
-@@ -398,6 +398,13 @@ struct flex_groups {
+@@ -395,6 +395,13 @@ struct flex_groups {
  #define EXT4_FL_USER_VISIBLE          0x304BDFFF /* User visible flags */
  #define EXT4_FL_USER_MODIFIABLE               0x204380FF /* User modifiable flags */
  
@@ -16,7 +16,7 @@ index 31317c9..39b31aa 100644
  /* Flags that should be inherited by new inodes from their parent. */
  #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
                           EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
-@@ -621,6 +628,44 @@ enum {
+@@ -620,6 +627,44 @@ enum {
  #define EXT4_IOC_SWAP_BOOT            _IO('f', 17)
  #define EXT4_IOC_PRECACHE_EXTENTS     _IO('f', 18)
  
@@ -61,16 +61,16 @@ index 31317c9..39b31aa 100644
  #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
  /*
   * ioctl commands in 32 bit emulation
-@@ -2336,6 +2381,7 @@ extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
+@@ -2347,6 +2392,7 @@ extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
  /* ioctl.c */
  extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
  extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
-+extern int __ext4_ioctl_setproject(struct inode *inode, __u32 projid);
++extern int ext4_transfer_project(struct inode *inode, __u32 projid);
  
  /* migrate.c */
  extern int ext4_ext_migrate(struct inode *);
 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
-index bfda18a..a4443e9 100644
+index 70c66d3..276d33d 100644
 --- a/fs/ext4/ioctl.c
 +++ b/fs/ext4/ioctl.c
 @@ -15,6 +15,7 @@
@@ -81,7 +81,7 @@ index bfda18a..a4443e9 100644
  #include "ext4_jbd2.h"
  #include "ext4.h"
  
-@@ -198,6 +199,251 @@ journal_err_out:
+@@ -198,6 +199,294 @@ journal_err_out:
        return err;
  }
  
@@ -180,8 +180,9 @@ index bfda18a..a4443e9 100644
 +}
 +
 +#ifdef CONFIG_QUOTA
-+int __ext4_ioctl_setproject(struct inode *inode, __u32 projid)
++static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
 +{
++      struct inode *inode = file_inode(filp);
 +      struct super_block *sb = inode->i_sb;
 +      struct ext4_inode_info *ei = EXT4_I(inode);
 +      int err, rc;
@@ -202,13 +203,17 @@ index bfda18a..a4443e9 100644
 +      }
 +
 +      if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
-+              return -EOPNOTSUPP;
++              return -EOPNOTSUPP;
 +
 +      kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
 +
 +      if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
 +              return 0;
 +
++      err = mnt_want_write_file(filp);
++      if (err)
++              return err;
++
 +      err = -EPERM;
 +      mutex_lock(&inode->i_mutex);
 +      /* Is it quota file? Do not allow user to mess with it */
@@ -221,9 +226,9 @@ index bfda18a..a4443e9 100644
 +
 +      raw_inode = ext4_raw_inode(&iloc);
 +      if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
-+              err = -EOVERFLOW;
-+              brelse(iloc.bh);
-+              goto out_unlock;
++              err = -EOVERFLOW;
++              brelse(iloc.bh);
++              goto out_unlock;
 +      }
 +      brelse(iloc.bh);
 +
@@ -259,26 +264,64 @@ index bfda18a..a4443e9 100644
 +      ext4_journal_stop(handle);
 +out_unlock:
 +      mutex_unlock(&inode->i_mutex);
++      mnt_drop_write_file(filp);
 +      return err;
 +
 +
 +}
-+EXPORT_SYMBOL(__ext4_ioctl_setproject);
 +
-+static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
++int ext4_transfer_project(struct inode *inode, __u32 projid)
 +{
++      struct super_block *sb = inode->i_sb;
++      struct ext4_inode_info *ei = EXT4_I(inode);
 +      int err;
-+      struct inode *inode = file_inode(filp);
++      kprojid_t kprojid;
++      struct ext4_iloc iloc;
++      struct ext4_inode *raw_inode;
++      struct dquot *transfer_to[EXT4_MAXQUOTAS] = { };
 +
-+      err = mnt_want_write_file(filp);
++      if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
++                      EXT4_FEATURE_RO_COMPAT_PROJECT)) {
++              BUG_ON(__kprojid_val(EXT4_I(inode)->i_projid)
++                     != EXT4_DEF_PROJID);
++              if (projid != EXT4_DEF_PROJID)
++                      return -EOPNOTSUPP;
++              else
++                      return 0;
++      }
++
++      if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
++              return -EOPNOTSUPP;
++
++      kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
++      if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
++              return 0;
++
++      err = ext4_get_inode_loc(inode, &iloc);
 +      if (err)
 +              return err;
 +
-+      err = __ext4_ioctl_setproject(inode, projid);
++      raw_inode = ext4_raw_inode(&iloc);
++      if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
++              err = -EOVERFLOW;
++              brelse(iloc.bh);
++              return err;
++      }
++      brelse(iloc.bh);
++
++      dquot_initialize(inode);
++      transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
++      if (transfer_to[PRJQUOTA]) {
++              err = __dquot_transfer(inode, transfer_to);
++              dqput(transfer_to[PRJQUOTA]);
++              if (err)
++                      return err;
++      }
 +
-+      mnt_drop_write_file(filp);
 +      return err;
 +}
++EXPORT_SYMBOL(ext4_transfer_project);
++
 +#else
 +static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
 +{
@@ -333,7 +376,7 @@ index bfda18a..a4443e9 100644
  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
        struct inode *inode = file_inode(filp);
-@@ -213,11 +459,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+@@ -213,11 +502,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
                return put_user(flags, (int __user *) arg);
        case EXT4_IOC_SETFLAGS: {
@@ -346,7 +389,7 @@ index bfda18a..a4443e9 100644
  
                if (!inode_owner_or_capable(inode))
                        return -EACCES;
-@@ -231,89 +473,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+@@ -231,89 +516,8 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  
                flags = ext4_mask_flags(inode->i_mode, flags);
  
@@ -437,7 +480,7 @@ index bfda18a..a4443e9 100644
                mutex_unlock(&inode->i_mutex);
                mnt_drop_write_file(filp);
                return err;
-@@ -617,6 +778,62 @@ resizefs_out:
+@@ -622,6 +826,62 @@ resizefs_out:
        }
        case EXT4_IOC_PRECACHE_EXTENTS:
                return ext4_ext_precache(inode);
index 1a82aee..35fb2fc 100644 (file)
@@ -2626,19 +2626,21 @@ static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr)
                }
        }
 
-#ifdef HAVE_PROJECT_QUOTA
        /* Handle project id transfer here properly */
        if (attr->la_valid & LA_PROJID &&
            attr->la_projid != i_projid_read(inode)) {
-               rc = __ldiskfs_ioctl_setproject(inode, attr->la_projid);
+#ifdef HAVE_PROJECT_QUOTA
+               rc = ldiskfs_transfer_project(inode, attr->la_projid);
+#else
+               rc = -ENOTSUPP;
+#endif
                if (rc) {
-                       CERROR("%s: quota transfer failed: rc = %d. Is quota "
+                       CERROR("%s: quota transfer failed: rc = %d. Is project "
                               "enforcement enabled on the ldiskfs "
                               "filesystem?\n", inode->i_sb->s_id, rc);
                        return rc;
                }
        }
-#endif
        return 0;
 }
 
@@ -3423,8 +3425,9 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env,
 
        /* Agent inode should not have project ID */
 #ifdef HAVE_PROJECT_QUOTA
-       if (LDISKFS_I(pobj->oo_inode)->i_flags & LUSTRE_PROJINHERIT_FL) {
-               rc = __ldiskfs_ioctl_setproject(local, 0);
+       if (LDISKFS_I(pobj->oo_inode)->i_flags & LUSTRE_PROJINHERIT_FL &&
+           i_projid_read(pobj->oo_inode) != 0) {
+               rc = ldiskfs_transfer_project(local, 0);
                if (rc) {
                        CERROR("%s: quota transfer failed: rc = %d. Is project "
                               "quota enforcement enabled on the ldiskfs "
@@ -5367,8 +5370,23 @@ static int osd_index_declare_ea_insert(const struct lu_env *env,
                                           i_projid_read(inode), 0,
                                           oh, osd_dt_obj(dt), NULL,
                                           OSD_QID_BLK);
+               if (rc)
+                       RETURN(rc);
+
+#ifdef HAVE_PROJECT_QUOTA
+               /* Reserve credits for local agent inode to transfer
+                * to 0, quota enforcement is ignored in this case.
+                */
+               if (idc->oic_remote &&
+                   LDISKFS_I(inode)->i_flags & LUSTRE_PROJINHERIT_FL &&
+                   i_projid_read(inode) != 0)
+                       rc = osd_declare_attr_qid(env, osd_dt_obj(dt), oh,
+                                                 0, i_projid_read(inode),
+                                                 0, false, PRJQUOTA);
+#endif
        }
 
+
        RETURN(rc);
 }