From: anserper Date: Thu, 19 Feb 2009 19:13:23 +0000 (+0000) Subject: b=18233 X-Git-Tag: v1_8_0_110~246 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=4362c7d542603949645460b6e6e6558fe7661748;p=fs%2Flustre-release.git b=18233 i=Oleg Drokin (green) i=Johann Lombardi (johann) implement rw lock so that vmtruncate could not race with reads --- diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 30ef5cc..87875ca 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1504,9 +1504,13 @@ repeat: nrsegs_copy = nr_segs; } + down_read(&lli->lli_truncate_rwsem); /* Bug 18233 */ + lock_style = ll_file_get_lock(file, (obd_off)(*ppos), end, iov_copy, nrsegs_copy, &cookie, &tree, OBD_BRW_READ); + if (lock_style < 0 || lock_style == LL_LOCK_STYLE_NOLOCK) + up_read(&lli->lli_truncate_rwsem); if (lock_style < 0) GOTO(out, retval = lock_style); @@ -1539,9 +1543,11 @@ repeat: ll_inode_size_unlock(inode, 1); retval = ll_glimpse_size(inode, LDLM_FL_BLOCK_GRANTED); if (retval) { - if (lock_style != LL_LOCK_STYLE_NOLOCK) + if (lock_style != LL_LOCK_STYLE_NOLOCK) { ll_file_put_lock(inode, end, lock_style, cookie, &tree, OBD_BRW_READ); + up_read(&lli->lli_truncate_rwsem); + } goto out; } } else { @@ -1597,6 +1603,7 @@ repeat: #endif ll_file_put_lock(inode, end, lock_style, cookie, &tree, OBD_BRW_READ); + up_read(&lli->lli_truncate_rwsem); } else { /* lockless read * diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 1a7977b..60d5256 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -179,6 +179,7 @@ struct ll_inode_info { * before child -- it is me should cleanup the dir readahead. */ void *lli_opendir_key; struct ll_statahead_info *lli_sai; + struct rw_semaphore lli_truncate_rwsem; /* the most recent attributes from mds, it is used for timestampts * only so far */ struct ost_lvb lli_lvb; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 41a34a9..ea496de 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -900,6 +900,7 @@ void ll_lli_init(struct ll_inode_info *lli) #ifdef HAVE_CLOSE_THREAD INIT_LIST_HEAD(&lli->lli_pending_write_llaps); #endif + init_rwsem(&lli->lli_truncate_rwsem); } /* COMPAT_146 */ @@ -1429,6 +1430,7 @@ static int ll_setattr_do_truncate(struct inode *inode, loff_t new_size) UNLOCK_INODE_MUTEX(inode); UP_WRITE_I_ALLOC_SEM(inode); + down_write(&lli->lli_truncate_rwsem); if (sbi->ll_lockless_truncate_enable && (sbi->ll_lco.lco_flags & OBD_CONNECT_TRUNCLOCK)) { int n_matches = 0; @@ -1491,6 +1493,7 @@ static int ll_setattr_do_truncate(struct inode *inode, loff_t new_size) rc = err; } } + up_write(&lli->lli_truncate_rwsem); RETURN(rc); } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 9aca6e4..6c9d04a 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -5863,6 +5863,23 @@ test_200i() { } run_test 200i "Remove a pool ============================================" +test_154() { + # do directio so as not to populate the page cache + log "creating a 10 Mb file" + multiop $DIR/$tfile oO_CREAT:O_DIRECT:O_RDWR:w$((10*1048576))c || error "multiop failed while creating a file" + log "starting reads" + dd if=$DIR/$tfile of=/dev/null bs=4096 & + log "truncating the file" + multiop $DIR/$tfile oO_TRUNC:c || error "multiop failed while truncating the file" + log "killing dd" + kill %+ || true # reads might have finished + echo "wait until dd is finished" + wait + log "removing the temporary file" + rm -rf $DIR/$tfile || error "tmp file removal failed" +} +run_test 154 "parallel read and truncate should not deadlock =======================" + # # tests that do cleanup/setup should be run at the end #