ANDROID: sdcardfs: Hold i_mutex for i_size_write
authorDaniel Rosenberg <drosen@google.com>
Wed, 21 Feb 2018 04:25:45 +0000 (20:25 -0800)
committerDaniel Rosenberg <drosen@google.com>
Fri, 23 Feb 2018 22:51:17 +0000 (14:51 -0800)
When we call i_size_write, we must be holding i_mutex to avoid
possible lockups on 32 bit/SMP architectures. This is not
necessary on 64 bit architectures.

Change-Id: Ic3b946507c54d81b5c9046f9b57d25d4b0f9feef
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Bug: 73287721

fs/sdcardfs/file.c

index 5ac0b0bbb0ec1c10092e3b19bb272d24ad6bdd82..2879d1291a11cb21ff66f97d2799ff475c7a708f 100644 (file)
@@ -62,6 +62,7 @@ static ssize_t sdcardfs_write(struct file *file, const char __user *buf,
        int err;
        struct file *lower_file;
        struct dentry *dentry = file->f_path.dentry;
+       struct inode *inode = d_inode(dentry);
 
        /* check disk space */
        if (!check_min_free_space(dentry, count, 0)) {
@@ -73,10 +74,12 @@ static ssize_t sdcardfs_write(struct file *file, const char __user *buf,
        err = vfs_write(lower_file, buf, count, ppos);
        /* update our inode times+sizes upon a successful lower write */
        if (err >= 0) {
-               fsstack_copy_inode_size(d_inode(dentry),
-                                       file_inode(lower_file));
-               fsstack_copy_attr_times(d_inode(dentry),
-                                       file_inode(lower_file));
+               if (sizeof(loff_t) > sizeof(long))
+                       inode_lock(inode);
+               fsstack_copy_inode_size(inode, file_inode(lower_file));
+               fsstack_copy_attr_times(inode, file_inode(lower_file));
+               if (sizeof(loff_t) > sizeof(long))
+                       inode_unlock(inode);
        }
 
        return err;
@@ -391,6 +394,7 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
        int err;
        struct file *file = iocb->ki_filp, *lower_file;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        lower_file = sdcardfs_lower_file(file);
        if (!lower_file->f_op->write_iter) {
@@ -405,10 +409,12 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
        fput(lower_file);
        /* update upper inode times/sizes as needed */
        if (err >= 0 || err == -EIOCBQUEUED) {
-               fsstack_copy_inode_size(file->f_path.dentry->d_inode,
-                                       file_inode(lower_file));
-               fsstack_copy_attr_times(file->f_path.dentry->d_inode,
-                                       file_inode(lower_file));
+               if (sizeof(loff_t) > sizeof(long))
+                       inode_lock(inode);
+               fsstack_copy_inode_size(inode, file_inode(lower_file));
+               fsstack_copy_attr_times(inode, file_inode(lower_file));
+               if (sizeof(loff_t) > sizeof(long))
+                       inode_lock(inode);
        }
 out:
        return err;