From d8ac05a4c2cd4ba1af686e99e87225b22e44c299 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 19 Mar 2010 11:19:17 -0700 Subject: [PATCH] b=20989 Atomically check-update inode lli_smd to prevent updated race There was a possible scenario during NFS use where multiple NFS requests would try to refresh a dentry and will call ll_prep_inode with different requests. ll_update_inode's ll_smd updating code would then race after a check for ll_smd being non-NULL and we endup with an lsm leak and some processes possibly usign stale copy of lsm data. i=adilger i=rread --- lustre/llite/llite_internal.h | 4 +++- lustre/llite/llite_lib.c | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index cff3891..9741c44 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -149,7 +149,9 @@ struct ll_inode_info { cfs_list_t lli_dead_list; cfs_semaphore_t lli_och_sem; /* Protects access to och pointers - and their usage counters */ + and their usage counters, also + atomicity of check-update of + lli_smd */ /* We need all three because every inode may be opened in different modes */ struct obd_client_handle *lli_mds_read_och; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 0a959a8..59a1ce5 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -1539,6 +1539,7 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) LASSERT ((lsm != NULL) == ((body->valid & OBD_MD_FLEASIZE) != 0)); if (lsm != NULL) { + cfs_down(&lli->lli_och_sem); if (lli->lli_smd == NULL) { if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { @@ -1547,16 +1548,18 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) } CDEBUG(D_INODE, "adding lsm %p to inode %lu/%u(%p)\n", lsm, inode->i_ino, inode->i_generation, inode); + /* cl_inode_init must go before lli_smd or a race is + * possible where client thinks the file has stripes, + * but lov raid0 is not setup yet and parallel e.g. + * glimpse would try to use uninitialized lov */ cl_inode_init(inode, md); - /* ll_inode_size_lock() requires it is only - * called with lli_smd != NULL or lock_lsm == 0 - * or we can race between lock/unlock. - * bug 9547 */ lli->lli_smd = lsm; + cfs_up(&lli->lli_och_sem); lli->lli_maxbytes = lsm->lsm_maxbytes; if (lli->lli_maxbytes > PAGE_CACHE_MAXBYTES) lli->lli_maxbytes = PAGE_CACHE_MAXBYTES; } else { + cfs_up(&lli->lli_och_sem); LASSERT(lli->lli_smd->lsm_magic == lsm->lsm_magic && lli->lli_smd->lsm_stripe_count == lsm->lsm_stripe_count); -- 1.8.3.1