Whamcloud - gitweb
LU-9597 ofd: fix race for project setattr 74/28274/7
authorWang Shilong <wshilong@ddn.com>
Sat, 29 Jul 2017 13:54:30 +0000 (21:54 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Sat, 5 Aug 2017 05:11:18 +0000 (05:11 +0000)
sanity-quota 33 exposed an intresting project quota bug,
problem is we could hit following condition:

step 1: create an empty file
step 2: buffer write data to file, at this time project id 0 is packed.
step 3: chattr file's project id

If write RPC is generated on client but not reaching OST yet, and step 3
chattr is issued in this time window and chattr on OST is done before
write PRC being processed on OST:

That means we have changed file's project ID, but ofd_attr_handle_id()
did not clear S_ISUID and S_ISGID for this case. Write RPC arrived on
OST, first write RPC will call ofd_attr_handle_id() to set attribute.
Unfortunately it will think this is first write as S_ISUID and S_ISGID
is set, project id will be reset with packed id 0, thus we got wrong
project accounting.

We should use another file mode to indicate whether
project id has been initialized, this patch tries to
fix this problem.

Change-Id: Ie2f9ce5b662c3011aa1cd2f59e1fb20526a3e3d7
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-on: https://review.whamcloud.com/28274
Tested-by: Jenkins
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/ofd/ofd_objects.c

index 7f328ee..eb959e4 100644 (file)
@@ -225,7 +225,7 @@ int ofd_precreate_objects(const struct lu_env *env, struct ofd_device *ofd,
                RETURN(-ENOMEM);
 
        info->fti_attr.la_valid = LA_TYPE | LA_MODE;
-       info->fti_attr.la_mode = S_IFREG | S_ISUID | S_ISGID | 0666;
+       info->fti_attr.la_mode = S_IFREG | S_ISUID | S_ISGID | S_ISVTX | 0666;
        info->fti_dof.dof_type = dt_mode_to_dft(S_IFREG);
 
        info->fti_attr.la_valid |= LA_ATIME | LA_MTIME | LA_CTIME;
@@ -449,9 +449,11 @@ int ofd_attr_handle_id(const struct lu_env *env, struct ofd_object *fo,
         */
        if (!is_setattr) {
                if (!(ln->la_mode & S_ISUID))
-                       la->la_valid &= ~(LA_UID | LA_PROJID);
+                       la->la_valid &= ~LA_UID;
                if (!(ln->la_mode & S_ISGID))
-                       la->la_valid &= ~(LA_GID | LA_PROJID);
+                       la->la_valid &= ~LA_GID;
+               if (!(ln->la_mode & S_ISVTX))
+                       la->la_valid &= ~LA_PROJID;
        }
 
        /* Initialize ownership of this object, clear SUID+SGID bits*/
@@ -459,6 +461,8 @@ int ofd_attr_handle_id(const struct lu_env *env, struct ofd_object *fo,
                mask |= S_ISUID;
        if ((la->la_valid & LA_GID) && (ln->la_mode & S_ISGID))
                mask |= S_ISGID;
+       if ((la->la_valid & LA_PROJID) && (ln->la_mode & S_ISVTX))
+               mask |= S_ISVTX;
        if (mask != 0) {
                if (!(la->la_valid & LA_MODE) || !is_setattr) {
                        la->la_mode = ln->la_mode;