Whamcloud - gitweb
b=18233 fix read+truncate livelock
[fs/lustre-release.git] / lustre / llite / file.c
index 7cb5232..7107e81 100644 (file)
@@ -856,8 +856,11 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
 #endif
                         if ((iot == CIT_WRITE) &&
                             !(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
-                                cfs_down(&lli->lli_write_sem);
+                                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:
@@ -875,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;
@@ -884,8 +889,10 @@ static ssize_t ll_file_io_generic(const struct lu_env *env,
                 result = io->ci_nob;
                 *ppos = io->u.ci_wr.wr.crw_pos;
         }
+        GOTO(out, result);
+out:
         cl_io_fini(env, io);
-        RETURN(result);
+        return result;
 }
 
 
@@ -2076,10 +2083,12 @@ int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock)
         RETURN(-ENOSYS);
 }
 
-int ll_have_md_lock(struct inode *inode, __u64 bits)
+int ll_have_md_lock(struct inode *inode, __u64 bits,  ldlm_mode_t l_req_mode)
 {
         struct lustre_handle lockh;
         ldlm_policy_data_t policy = { .l_inodebits = {bits}};
+        ldlm_mode_t mode = (l_req_mode == LCK_MINMODE) ?
+                                (LCK_CR|LCK_CW|LCK_PR|LCK_PW) : l_req_mode;
         struct lu_fid *fid;
         int flags;
         ENTRY;
@@ -2088,11 +2097,12 @@ int ll_have_md_lock(struct inode *inode, __u64 bits)
                RETURN(0);
 
         fid = &ll_i2info(inode)->lli_fid;
-        CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
+        CDEBUG(D_INFO, "trying to match res "DFID" mode %s\n", PFID(fid),
+               ldlm_lockname[mode]);
 
         flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK;
         if (md_lock_match(ll_i2mdexp(inode), flags, fid, LDLM_IBITS, &policy,
-                          LCK_CR|LCK_CW|LCK_PR|LCK_PW, &lockh)) {
+                          mode, &lockh)) {
                 RETURN(1);
         }
         RETURN(0);
@@ -2201,7 +2211,7 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it,
                 }
 
                 ll_lookup_finish_locks(&oit, dentry);
-        } else if (!ll_have_md_lock(dentry->d_inode, ibits)) {
+        } else if (!ll_have_md_lock(dentry->d_inode, ibits, LCK_MINMODE)) {
                 struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
                 obd_valid valid = OBD_MD_FLGETATTR;
                 struct md_op_data *op_data;
@@ -2422,7 +2432,7 @@ int ll_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
                 return -EROFS;
         if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
                 return -EACCES;
-        if (current->fsuid == inode->i_uid) {
+        if (cfs_curproc_fsuid() == inode->i_uid) {
                 mode >>= 6;
         } else if (1) {
                 if (((mode >> 3) & mask & S_IRWXO) != mask)