Whamcloud - gitweb
LU-3029 osd-ldiskfs: clear old FMODE_32BITHASH for readdir
authorFan Yong <yong.fan@whamcloud.com>
Mon, 22 Apr 2013 05:31:20 +0000 (13:31 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 26 Apr 2013 01:14:34 +0000 (21:14 -0400)
On MDS, the RPC service thread's "osd_thread_info" will be reused
without completely reset when switches from one RPC processing to
another RPC processing.

Some old client may not claim "OBD_CONNECT_64BITHASH" when connect
to the MDS, then it will be regarded as 32-bit client. For readdir
RPC from such old client, the MDS will use 32-bit dirhash, the RPC
service thread's "osd_thread_info::oti_it_ea::oie_file::f_mode" is
set as "FMODE_32BITHASH", which will not be dropped until restart.

If some RPC service threads (for readdir) are "FMODE_32BITHASH",
but some NOT, then for new client, which support 64-bit dirhash,
it may get trouble when traverses large directroy as following:

1) The first readdir RPC is served by the RPC service thread1,
   which is marked as "FMODE_32BITHASH" because it ever served
   readdir RPC from old client. So the thread1 still generates
   32-bit dirhash (major hash only) for the new client readdir.

2) The new client triggers another readdir RPC for the same dir
   with the 32-bit dirhash as cookie, which was returned by the

3) This time, the readdir RPC is served by another RPC service
   thread2, which is NOT marked as "FMODE_32BITHASH". Then the
   thread2 explains the readdir cookie as 64-bit dirhash, It's
   wrong. So the thread2 can NOT locate the position correctly.

So we need to clear some fields in "osd_thread_info" to avoid
to be reused when switch from one RPC processing to another.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I3b9aaede0bccab900f1d198c7093b98f0fc48945
Reviewed-on: http://review.whamcloud.com/6138
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Hudson
Reviewed-by: Ned Bass <bass6@llnl.gov>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Prakash Surya <surya1@llnl.gov>
Tested-by: Maloo <whamcloud.maloo@gmail.com>

index fe8dc3c..8dbcf11 100644 (file)
@@ -4324,6 +4324,7 @@ static struct dt_it *osd_it_ea_init(const struct lu_env *env,
         struct osd_object       *obj  = osd_dt_obj(dt);
         struct osd_thread_info  *info = osd_oti_get(env);
         struct osd_it_ea        *it   = &info->oti_it_ea;
+       struct file             *file = &it->oie_file;
         struct lu_object        *lo   = &dt->do_lu;
         struct dentry           *obj_dentry = &info->oti_it_dentry;
@@ -4338,17 +4339,20 @@ static struct dt_it *osd_it_ea_init(const struct lu_env *env,
         it->oie_dirent          = NULL;
         it->oie_buf             = info->oti_it_ea_buf;
         it->oie_obj             = obj;
-        it->oie_file.f_pos      = 0;
-        it->oie_file.f_dentry   = obj_dentry;
-        if (attr & LUDA_64BITHASH)
-               it->oie_file.f_mode |= FMODE_64BITHASH;
-        else
-               it->oie_file.f_mode |= FMODE_32BITHASH;
-        it->oie_file.f_mapping    = obj->oo_inode->i_mapping;
-        it->oie_file.f_op         = obj->oo_inode->i_fop;
-        it->oie_file.private_data = NULL;
-        lu_object_get(lo);
-        RETURN((struct dt_it *) it);
+       /* Reset the "file" totally to avoid to reuse any old value from
+        * former readdir handling, the "file->f_pos" should be zero. */
+       memset(file, 0, sizeof(*file));
+       /* Only FMODE_64BITHASH or FMODE_32BITHASH should be set, NOT both. */
+       if (attr & LUDA_64BITHASH)
+               file->f_mode    = FMODE_64BITHASH;
+       else
+               file->f_mode    = FMODE_32BITHASH;
+       file->f_dentry          = obj_dentry;
+       file->f_mapping         = obj->oo_inode->i_mapping;
+       file->f_op              = obj->oo_inode->i_fop;
+       lu_object_get(lo);
+       RETURN((struct dt_it *) it);