These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / ocfs2 / file.c
index d8b670c..0e5b451 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/falloc.h>
 #include <linux/quotaops.h>
 #include <linux/blkdev.h>
+#include <linux/backing-dev.h>
 
 #include <cluster/masklog.h>
 
@@ -104,8 +105,11 @@ static int ocfs2_file_open(struct inode *inode, struct file *file)
                              file->f_path.dentry->d_name.len,
                              file->f_path.dentry->d_name.name, mode);
 
-       if (file->f_mode & FMODE_WRITE)
-               dquot_initialize(inode);
+       if (file->f_mode & FMODE_WRITE) {
+               status = dquot_initialize(inode);
+               if (status)
+                       goto leave;
+       }
 
        spin_lock(&oi->ip_lock);
 
@@ -1126,6 +1130,7 @@ out:
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int status = 0, size_change;
+       int inode_locked = 0;
        struct inode *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        struct ocfs2_super *osb = OCFS2_SB(sb);
@@ -1154,8 +1159,11 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
        if (status)
                return status;
 
-       if (is_quota_modification(inode, attr))
-               dquot_initialize(inode);
+       if (is_quota_modification(inode, attr)) {
+               status = dquot_initialize(inode);
+               if (status)
+                       return status;
+       }
        size_change = S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE;
        if (size_change) {
                status = ocfs2_rw_lock(inode, 1);
@@ -1171,6 +1179,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                        mlog_errno(status);
                goto bail_unlock_rw;
        }
+       inode_locked = 1;
 
        if (size_change) {
                status = inode_newsize_ok(inode, attr->ia_size);
@@ -1208,8 +1217,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                    && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
                    OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
                        transfer_to[USRQUOTA] = dqget(sb, make_kqid_uid(attr->ia_uid));
-                       if (!transfer_to[USRQUOTA]) {
-                               status = -ESRCH;
+                       if (IS_ERR(transfer_to[USRQUOTA])) {
+                               status = PTR_ERR(transfer_to[USRQUOTA]);
                                goto bail_unlock;
                        }
                }
@@ -1217,8 +1226,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                    && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
                    OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
                        transfer_to[GRPQUOTA] = dqget(sb, make_kqid_gid(attr->ia_gid));
-                       if (!transfer_to[GRPQUOTA]) {
-                               status = -ESRCH;
+                       if (IS_ERR(transfer_to[GRPQUOTA])) {
+                               status = PTR_ERR(transfer_to[GRPQUOTA]);
                                goto bail_unlock;
                        }
                }
@@ -1251,7 +1260,10 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 bail_commit:
        ocfs2_commit_trans(osb, handle);
 bail_unlock:
-       ocfs2_inode_unlock(inode, 1);
+       if (status) {
+               ocfs2_inode_unlock(inode, 1);
+               inode_locked = 0;
+       }
 bail_unlock_rw:
        if (size_change)
                ocfs2_rw_unlock(inode, 1);
@@ -1267,6 +1279,8 @@ bail:
                if (status < 0)
                        mlog_errno(status);
        }
+       if (inode_locked)
+               ocfs2_inode_unlock(inode, 1);
 
        return status;
 }
@@ -2250,13 +2264,11 @@ out:
 static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
                                    struct iov_iter *from)
 {
-       int direct_io, appending, rw_level, have_alloc_sem  = 0;
+       int direct_io, appending, rw_level;
        int can_do_direct, has_refcount = 0;
        ssize_t written = 0;
        ssize_t ret;
        size_t count = iov_iter_count(from), orig_count;
-       loff_t old_size;
-       u32 old_clusters;
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
@@ -2264,6 +2276,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
                               OCFS2_MOUNT_COHERENCY_BUFFERED);
        int unaligned_dio = 0;
        int dropped_dio = 0;
+       int append_write = ((iocb->ki_pos + count) >=
+                       i_size_read(inode) ? 1 : 0);
 
        trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
                (unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -2279,26 +2293,18 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
 
        mutex_lock(&inode->i_mutex);
 
-       ocfs2_iocb_clear_sem_locked(iocb);
-
 relock:
-       /* to match setattr's i_mutex -> rw_lock ordering */
-       if (direct_io) {
-               have_alloc_sem = 1;
-               /* communicate with ocfs2_dio_end_io */
-               ocfs2_iocb_set_sem_locked(iocb);
-       }
-
        /*
         * Concurrent O_DIRECT writes are allowed with
         * mount_option "coherency=buffered".
+        * For append write, we must take rw EX.
         */
-       rw_level = (!direct_io || full_coherency);
+       rw_level = (!direct_io || full_coherency || append_write);
 
        ret = ocfs2_rw_lock(inode, rw_level);
        if (ret < 0) {
                mlog_errno(ret);
-               goto out_sems;
+               goto out_mutex;
        }
 
        /*
@@ -2347,7 +2353,6 @@ relock:
        if (direct_io && !can_do_direct) {
                ocfs2_rw_unlock(inode, rw_level);
 
-               have_alloc_sem = 0;
                rw_level = -1;
 
                direct_io = 0;
@@ -2367,13 +2372,6 @@ relock:
                ocfs2_iocb_set_unaligned_aio(iocb);
        }
 
-       /*
-        * To later detect whether a journal commit for sync writes is
-        * necessary, we sample i_size, and cluster count here.
-        */
-       old_size = i_size_read(inode);
-       old_clusters = OCFS2_I(inode)->ip_clusters;
-
        /* communicate with ocfs2_dio_end_io */
        ocfs2_iocb_set_rw_locked(iocb, rw_level);
 
@@ -2381,6 +2379,20 @@ relock:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(written == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
 
+       /*
+        * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
+        * function pointer which is called when o_direct io completes so that
+        * it can unlock our rw lock.
+        * Unfortunately there are error cases which call end_io and others
+        * that don't.  so we don't have to unlock the rw_lock if either an
+        * async dio is going to do it in the future or an end_io after an
+        * error has already done it.
+        */
+       if ((written == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
+               rw_level = -1;
+               unaligned_dio = 0;
+       }
+
        if (unlikely(written <= 0))
                goto no_sync;
 
@@ -2405,22 +2417,7 @@ relock:
        }
 
 no_sync:
-       /*
-        * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
-        * function pointer which is called when o_direct io completes so that
-        * it can unlock our rw lock.
-        * Unfortunately there are error cases which call end_io and others
-        * that don't.  so we don't have to unlock the rw_lock if either an
-        * async dio is going to do it in the future or an end_io after an
-        * error has already done it.
-        */
-       if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
-               rw_level = -1;
-               have_alloc_sem = 0;
-               unaligned_dio = 0;
-       }
-
-       if (unaligned_dio) {
+       if (unaligned_dio && ocfs2_iocb_is_unaligned_aio(iocb)) {
                ocfs2_iocb_clear_unaligned_aio(iocb);
                mutex_unlock(&OCFS2_I(inode)->ip_unaligned_aio);
        }
@@ -2429,10 +2426,7 @@ out:
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);
 
-out_sems:
-       if (have_alloc_sem)
-               ocfs2_iocb_clear_sem_locked(iocb);
-
+out_mutex:
        mutex_unlock(&inode->i_mutex);
 
        if (written)
@@ -2473,7 +2467,7 @@ bail:
 static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
                                   struct iov_iter *to)
 {
-       int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
+       int ret = 0, rw_level = -1, lock_level = 0;
        struct file *filp = iocb->ki_filp;
        struct inode *inode = file_inode(filp);
 
@@ -2490,16 +2484,11 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
                goto bail;
        }
 
-       ocfs2_iocb_clear_sem_locked(iocb);
-
        /*
         * buffered reads protect themselves in ->readpage().  O_DIRECT reads
         * need locks to protect pending reads from racing with truncate.
         */
        if (iocb->ki_flags & IOCB_DIRECT) {
-               have_alloc_sem = 1;
-               ocfs2_iocb_set_sem_locked(iocb);
-
                ret = ocfs2_rw_lock(inode, 0);
                if (ret < 0) {
                        mlog_errno(ret);
@@ -2535,13 +2524,9 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
        /* see ocfs2_file_write_iter */
        if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
                rw_level = -1;
-               have_alloc_sem = 0;
        }
 
 bail:
-       if (have_alloc_sem)
-               ocfs2_iocb_clear_sem_locked(iocb);
-
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);