Whamcloud - gitweb
b=18233 fix read+truncate livelock
authorAndrew Perepechko <andrew.perepechko@oracle.com>
Thu, 11 Nov 2010 13:47:30 +0000 (16:47 +0300)
committerVitaly Fertman <vitaly.fertman@sun.com>
Fri, 12 Nov 2010 20:27:38 +0000 (23:27 +0300)
The race fix for ll_readpage which creates new (just truncated) pages
and truncate which truncates these pages.

i=Vitaly Fertman
i=Mike Pershin

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

index 05daf03..7107e81 100644 (file)
@@ -859,6 +859,8 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                                 if(cfs_down_interruptible(&lli->lli_write_sem))
                                         GOTO(out, result = -ERESTARTSYS);
                                 write_sem_locked = 1;
+                        } else if (iot == CIT_READ) {
+                                cfs_down_read(&lli->lli_trunc_sem);
                         }
                         break;
                 case IO_SENDFILE:
@@ -876,6 +878,8 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                 result = cl_io_loop(env, io);
                 if (write_sem_locked)
                         cfs_up(&lli->lli_write_sem);
+                else if (args->via_io_subtype == IO_NORMAL && iot == CIT_READ)
+                        cfs_up_read(&lli->lli_trunc_sem);
         } else {
                 /* cl_io_rw_init() handled IO */
                 result = io->ci_result;
index 9ca31dc..f5d36c5 100644 (file)
@@ -121,7 +121,7 @@ struct ll_inode_info {
         cfs_semaphore_t         lli_size_sem;           /* protect open and change size */
         void                   *lli_size_sem_owner;
         cfs_semaphore_t         lli_write_sem;
-        cfs_semaphore_t         lli_trunc_sem;
+        cfs_rw_semaphore_t      lli_trunc_sem;
         char                   *lli_symlink_name;
         __u64                   lli_maxbytes;
         __u64                   lli_ioepoch;
index c3e66ba..73170fc 100644 (file)
@@ -798,7 +798,7 @@ void ll_lli_init(struct ll_inode_info *lli)
         lli->lli_inode_magic = LLI_INODE_MAGIC;
         cfs_sema_init(&lli->lli_size_sem, 1);
         cfs_sema_init(&lli->lli_write_sem, 1);
-        cfs_sema_init(&lli->lli_trunc_sem, 1);
+        cfs_init_rwsem(&lli->lli_trunc_sem);
         lli->lli_flags = 0;
         lli->lli_maxbytes = PAGE_CACHE_MAXBYTES;
         cfs_spin_lock_init(&lli->lli_lock);
@@ -1270,7 +1270,7 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
         UNLOCK_INODE_MUTEX(inode);
         if (ia_valid & ATTR_SIZE)
                 UP_WRITE_I_ALLOC_SEM(inode);
-        cfs_down(&lli->lli_trunc_sem);
+        cfs_down_write(&lli->lli_trunc_sem);
         LOCK_INODE_MUTEX(inode);
         if (ia_valid & ATTR_SIZE)
                 DOWN_WRITE_I_ALLOC_SEM(inode);
@@ -1311,7 +1311,7 @@ out:
                         rc1 = ll_setattr_done_writing(inode, op_data, mod);
                 ll_finish_md_op_data(op_data);
         }
-        cfs_up(&lli->lli_trunc_sem);
+        cfs_up_write(&lli->lli_trunc_sem);
         return rc ? rc : rc1;
 }
 
index ae7e8e9..18ee710 100755 (executable)
@@ -7706,6 +7706,23 @@ test_217() { # bug 22430
 }
 run_test 217 "check lctl ping for hostnames with hiphen ('-')"
 
+test_218() {
+       # 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 218 "parallel read and truncate should not deadlock ======================="
+
 #
 # tests that do cleanup/setup should be run at the end
 #