From 0cbfea914754f41e2b968b64c8f872f5bd963444 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Mon, 22 Apr 2013 21:50:06 +0800 Subject: [PATCH] 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: I1b0468fe1d3bed5b3563b17c9722009514bbea2e Reviewed-on: http://review.whamcloud.com/6176 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Ned Bass Reviewed-by: Prakash Surya --- lustre/osd-ldiskfs/osd_handler.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 1d95255..2efde09 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -3380,6 +3380,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; @@ -3394,17 +3395,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); } /** -- 1.8.3.1