net/mlx4: Fix firmware command timeout during interrupt test
[cascardo/linux.git] / fs / open.c
index 4fd6e25..d3ed817 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -68,6 +68,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 long vfs_truncate(const struct path *path, loff_t length)
 {
        struct inode *inode;
+       struct dentry *upperdentry;
        long error;
 
        inode = path->dentry->d_inode;
@@ -90,7 +91,17 @@ long vfs_truncate(const struct path *path, loff_t length)
        if (IS_APPEND(inode))
                goto mnt_drop_write_and_out;
 
-       error = get_write_access(inode);
+       /*
+        * If this is an overlayfs then do as if opening the file so we get
+        * write access on the upper inode, not on the overlay inode.  For
+        * non-overlay filesystems d_real() is an identity function.
+        */
+       upperdentry = d_real(path->dentry, NULL, O_WRONLY);
+       error = PTR_ERR(upperdentry);
+       if (IS_ERR(upperdentry))
+               goto mnt_drop_write_and_out;
+
+       error = get_write_access(upperdentry->d_inode);
        if (error)
                goto mnt_drop_write_and_out;
 
@@ -109,7 +120,7 @@ long vfs_truncate(const struct path *path, loff_t length)
                error = do_truncate(path->dentry, length, 0, NULL);
 
 put_write_and_out:
-       put_write_access(inode);
+       put_write_access(upperdentry->d_inode);
 mnt_drop_write_and_out:
        mnt_drop_write(path->mnt);
 out:
@@ -256,6 +267,11 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
            (mode & ~FALLOC_FL_INSERT_RANGE))
                return -EINVAL;
 
+       /* Unshare range should only be used with allocate mode. */
+       if ((mode & FALLOC_FL_UNSHARE_RANGE) &&
+           (mode & ~(FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_KEEP_SIZE)))
+               return -EINVAL;
+
        if (!(file->f_mode & FMODE_WRITE))
                return -EBADF;
 
@@ -289,7 +305,8 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         * Let individual file system decide if it supports preallocation
         * for directories or not.
         */
-       if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
+       if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
+           !S_ISBLK(inode->i_mode))
                return -ENODEV;
 
        /* Check for wrap through zero too */
@@ -726,7 +743,7 @@ static int do_dentry_open(struct file *f,
        if (error)
                goto cleanup_all;
 
-       error = break_lease(inode, f->f_flags);
+       error = break_lease(locks_inode(f), f->f_flags);
        if (error)
                goto cleanup_all;