Unionfs: ->setattr fixes
authorErez Zadok <ezk@cs.sunysb.edu>
Sat, 30 Apr 2011 05:31:29 +0000 (01:31 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Fri, 12 Aug 2011 02:39:25 +0000 (22:39 -0400)
Call inode_check_ok first thing on our inode.
Pass lower_file in struct iattr to lower file system.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/inode.c

index 4c36f16b4d233ce6a599e8e29cf72ce5e5f5c474..cc994bdb348cb253c684123ad4350ef66698949c 100644 (file)
@@ -901,6 +901,12 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
        struct inode *lower_inode;
        int bstart, bend, bindex;
        loff_t size;
+       struct iattr lower_ia;
+
+       /* check if user has permission to change inode */
+       err = inode_change_ok(dentry->d_inode, ia);
+       if (err)
+               goto out_err;
 
        unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
        parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
@@ -988,8 +994,15 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
         * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
         * tries to open(), unlink(), then ftruncate() a file.
         */
+       /* prepare our own lower struct iattr (with our own lower file) */
+       memcpy(&lower_ia, ia, sizeof(lower_ia));
+       if (ia->ia_valid & ATTR_FILE) {
+               lower_ia.ia_file = unionfs_lower_file(ia->ia_file);
+               BUG_ON(!lower_ia.ia_file); // XXX?
+       }
+
        mutex_lock(&lower_dentry->d_inode->i_mutex);
-       err = notify_change(lower_dentry, ia);
+       err = notify_change(lower_dentry, &lower_ia);
        mutex_unlock(&lower_dentry->d_inode->i_mutex);
        if (err)
                goto out;
@@ -1017,7 +1030,7 @@ out:
        unionfs_unlock_dentry(dentry);
        unionfs_unlock_parent(dentry, parent);
        unionfs_read_unlock(dentry->d_sb);
-
+out_err:
        return err;
 }