These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / ext2 / inode.c
index f460ae3..0aa9bf6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/time.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
+#include <linux/dax.h>
 #include <linux/quotaops.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>
@@ -1084,6 +1085,7 @@ static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int de
                ext2_free_data(inode, p, q);
 }
 
+/* dax_sem must be held when calling this function */
 static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
 {
        __le32 *i_data = EXT2_I(inode)->i_data;
@@ -1099,6 +1101,10 @@ static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
        blocksize = inode->i_sb->s_blocksize;
        iblock = (offset + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
 
+#ifdef CONFIG_FS_DAX
+       WARN_ON(!rwsem_is_locked(&ei->dax_sem));
+#endif
+
        n = ext2_block_to_path(inode, iblock, offsets, NULL);
        if (n == 0)
                return;
@@ -1184,7 +1190,10 @@ static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
                return;
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                return;
+
+       dax_sem_down_write(EXT2_I(inode));
        __ext2_truncate_blocks(inode, offset);
+       dax_sem_up_write(EXT2_I(inode));
 }
 
 static int ext2_setsize(struct inode *inode, loff_t newsize)
@@ -1212,8 +1221,10 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
        if (error)
                return error;
 
+       dax_sem_down_write(EXT2_I(inode));
        truncate_setsize(inode, newsize);
        __ext2_truncate_blocks(inode, newsize);
+       dax_sem_up_write(EXT2_I(inode));
 
        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
        if (inode_needs_sync(inode)) {
@@ -1403,6 +1414,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
                        inode->i_mapping->a_ops = &ext2_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                if (ext2_inode_is_fast_symlink(inode)) {
+                       inode->i_link = (char *)ei->i_data;
                        inode->i_op = &ext2_fast_symlink_inode_operations;
                        nd_terminate_link(ei->i_data, inode->i_size,
                                sizeof(ei->i_data) - 1);
@@ -1551,8 +1563,11 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
        if (error)
                return error;
 
-       if (is_quota_modification(inode, iattr))
-               dquot_initialize(inode);
+       if (is_quota_modification(inode, iattr)) {
+               error = dquot_initialize(inode);
+               if (error)
+                       return error;
+       }
        if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
            (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
                error = dquot_transfer(inode, iattr);