fat: Fix corrupt inode flags when remove ATTR_SYS flag
[pandora-kernel.git] / fs / fat / file.c
index 990dfae..7018e1d 100644 (file)
@@ -102,7 +102,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
                if (attr & ATTR_SYS)
                        inode->i_flags |= S_IMMUTABLE;
                else
-                       inode->i_flags &= S_IMMUTABLE;
+                       inode->i_flags &= ~S_IMMUTABLE;
        }
 
        fat_save_attrs(inode, attr);
@@ -364,18 +364,6 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
        return 0;
 }
 
-int fat_setsize(struct inode *inode, loff_t offset)
-{
-       int error;
-
-       error = simple_setsize(inode, offset);
-       if (error)
-               return error;
-       fat_truncate_blocks(inode, offset);
-
-       return error;
-}
-
 #define TIMES_SET_FLAGS        (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
 /* valid file mode bits */
 #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO)
@@ -387,21 +375,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
        unsigned int ia_valid;
        int error;
 
-       /*
-        * Expand the file. Since inode_setattr() updates ->i_size
-        * before calling the ->truncate(), but FAT needs to fill the
-        * hole before it. XXX: this is no longer true with new truncate
-        * sequence.
-        */
-       if (attr->ia_valid & ATTR_SIZE) {
-               if (attr->ia_size > inode->i_size) {
-                       error = fat_cont_expand(inode, attr->ia_size);
-                       if (error || attr->ia_valid == ATTR_SIZE)
-                               goto out;
-                       attr->ia_valid &= ~ATTR_SIZE;
-               }
-       }
-
        /* Check for setting the inode time. */
        ia_valid = attr->ia_valid;
        if (ia_valid & TIMES_SET_FLAGS) {
@@ -417,6 +390,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
                goto out;
        }
 
+       /*
+        * Expand the file. Since inode_setattr() updates ->i_size
+        * before calling the ->truncate(), but FAT needs to fill the
+        * hole before it. XXX: this is no longer true with new truncate
+        * sequence.
+        */
+       if (attr->ia_valid & ATTR_SIZE) {
+               if (attr->ia_size > inode->i_size) {
+                       error = fat_cont_expand(inode, attr->ia_size);
+                       if (error || attr->ia_valid == ATTR_SIZE)
+                               goto out;
+                       attr->ia_valid &= ~ATTR_SIZE;
+               }
+       }
+
        if (((attr->ia_valid & ATTR_UID) &&
             (attr->ia_uid != sbi->options.fs_uid)) ||
            ((attr->ia_valid & ATTR_GID) &&
@@ -441,12 +429,11 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        if (attr->ia_valid & ATTR_SIZE) {
-               error = fat_setsize(inode, attr->ia_size);
-               if (error)
-                       goto out;
+               truncate_setsize(inode, attr->ia_size);
+               fat_truncate_blocks(inode, attr->ia_size);
        }
 
-       generic_setattr(inode, attr);
+       setattr_copy(inode, attr);
        mark_inode_dirty(inode);
 out:
        return error;