Whamcloud - gitweb
b=18233
authoranserper <anserper>
Thu, 19 Feb 2009 19:13:23 +0000 (19:13 +0000)
committeranserper <anserper>
Thu, 19 Feb 2009 19:13:23 +0000 (19:13 +0000)
i=Oleg Drokin (green)
i=Johann Lombardi (johann)

implement rw lock so that vmtruncate could not race with reads

lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/tests/sanity.sh

index 30ef5cc..87875ca 100644 (file)
@@ -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
                  *
index 1a7977b..60d5256 100644 (file)
@@ -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;
index 41a34a9..ea496de 100644 (file)
@@ -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);
 }
 
index 9aca6e4..6c9d04a 100644 (file)
@@ -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
 #