From: Fan Yong Date: Mon, 22 Apr 2013 05:31:20 +0000 (+0800) Subject: LU-3029 osd-ldiskfs: clear old FMODE_32BITHASH for readdir X-Git-Tag: 2.3.65~65 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=7ef817c9af35fa8fe56ea911afa1e54d6db71c9b LU-3029 osd-ldiskfs: clear old FMODE_32BITHASH for readdir 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 thread1. 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 Change-Id: I3b9aaede0bccab900f1d198c7093b98f0fc48945 Reviewed-on: http://review.whamcloud.com/6138 Reviewed-by: Andreas Dilger Tested-by: Hudson Reviewed-by: Ned Bass Reviewed-by: Lai Siyao Reviewed-by: Prakash Surya Tested-by: Maloo --- diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index fe8dc3c..8dbcf11 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -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; ENTRY; @@ -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); } /**