]> git.ipfire.org Git - thirdparty/kernel/linux.git/blobdiff - fs/open.c
fs: get mnt_writers count for an open backing file's real path
[thirdparty/kernel/linux.git] / fs / open.c
index a65ce47810cfc033e21d71836288633a44772ff0..fe63e236da2225e1ac4579d8b5b41dea06cd51a3 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -870,6 +870,30 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
        return ksys_fchown(fd, user, group);
 }
 
+static inline int file_get_write_access(struct file *f)
+{
+       int error;
+
+       error = get_write_access(f->f_inode);
+       if (unlikely(error))
+               return error;
+       error = mnt_get_write_access(f->f_path.mnt);
+       if (unlikely(error))
+               goto cleanup_inode;
+       if (unlikely(f->f_mode & FMODE_BACKING)) {
+               error = mnt_get_write_access(backing_file_real_path(f)->mnt);
+               if (unlikely(error))
+                       goto cleanup_mnt;
+       }
+       return 0;
+
+cleanup_mnt:
+       mnt_put_write_access(f->f_path.mnt);
+cleanup_inode:
+       put_write_access(f->f_inode);
+       return error;
+}
+
 static int do_dentry_open(struct file *f,
                          struct inode *inode,
                          int (*open)(struct inode *, struct file *))
@@ -892,14 +916,9 @@ static int do_dentry_open(struct file *f,
        if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
                i_readcount_inc(inode);
        } else if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
-               error = get_write_access(inode);
+               error = file_get_write_access(f);
                if (unlikely(error))
                        goto cleanup_file;
-               error = mnt_get_write_access(f->f_path.mnt);
-               if (unlikely(error)) {
-                       put_write_access(inode);
-                       goto cleanup_file;
-               }
                f->f_mode |= FMODE_WRITER;
        }