]> err.no Git - linux-2.6/blobdiff - fs/ntfs/inode.c
Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
[linux-2.6] / fs / ntfs / inode.c
index a1682342baa6cf3517074db66c6068146f6e0d45..ea1bd3feea1b7dac830a03fd55ef41d2dfe15a9b 100644 (file)
@@ -2125,13 +2125,13 @@ void ntfs_put_inode(struct inode *vi)
                ntfs_inode *ni = NTFS_I(vi);
                if (NInoIndexAllocPresent(ni)) {
                        struct inode *bvi = NULL;
-                       down(&vi->i_sem);
+                       mutex_lock(&vi->i_mutex);
                        if (atomic_read(&vi->i_count) == 2) {
                                bvi = ni->itype.index.bmp_ino;
                                if (bvi)
                                        ni->itype.index.bmp_ino = NULL;
                        }
-                       up(&vi->i_sem);
+                       mutex_unlock(&vi->i_mutex);
                        if (bvi)
                                iput(bvi);
                }
@@ -2311,7 +2311,7 @@ static const char *es = "  Leaving inconsistent metadata.  Unmount and run "
  *
  * Returns 0 on success or -errno on error.
  *
- * Called with ->i_sem held.  In all but one case ->i_alloc_sem is held for
+ * Called with ->i_mutex held.  In all but one case ->i_alloc_sem is held for
  * writing.  The only case in the kernel where ->i_alloc_sem is not held is
  * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
  * with the current i_size as the offset.  The analogous place in NTFS is in
@@ -2767,7 +2767,25 @@ unm_done:
        up_write(&ni->runlist.lock);
 done:
        /* Update the mtime and ctime on the base inode. */
-       inode_update_time(VFS_I(base_ni), 1);
+       /* normally ->truncate shouldn't update ctime or mtime,
+        * but ntfs did before so it got a copy & paste version
+        * of file_update_time.  one day someone should fix this
+        * for real.
+        */
+       if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
+               struct timespec now = current_fs_time(VFS_I(base_ni)->i_sb);
+               int sync_it = 0;
+
+               if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
+                   !timespec_equal(&VFS_I(base_ni)->i_ctime, &now))
+                       sync_it = 1;
+               VFS_I(base_ni)->i_mtime = now;
+               VFS_I(base_ni)->i_ctime = now;
+
+               if (sync_it)
+                       mark_inode_dirty_sync(VFS_I(base_ni));
+       }
+
        if (likely(!err)) {
                NInoClearTruncateFailed(ni);
                ntfs_debug("Done.");
@@ -2831,7 +2849,7 @@ void ntfs_truncate_vfs(struct inode *vi) {
  * We also abort all changes of user, group, and mode as we do not implement
  * the NTFS ACLs yet.
  *
- * Called with ->i_sem held.  For the ATTR_SIZE (i.e. ->truncate) case, also
+ * Called with ->i_mutex held.  For the ATTR_SIZE (i.e. ->truncate) case, also
  * called with ->i_alloc_sem held for writing.
  *
  * Basically this is a copy of generic notify_change() and inode_setattr()
@@ -2845,8 +2863,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
 
        err = inode_change_ok(vi, attr);
        if (err)
-               return err;
-
+               goto out;
        /* We do not support NTFS ACLs yet. */
        if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) {
                ntfs_warning(vi->i_sb, "Changes in user/group/mode are not "
@@ -2854,14 +2871,22 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
                err = -EOPNOTSUPP;
                goto out;
        }
-
        if (ia_valid & ATTR_SIZE) {
                if (attr->ia_size != i_size_read(vi)) {
-                       ntfs_warning(vi->i_sb, "Changes in inode size are not "
-                                       "supported yet, ignoring.");
-                       err = -EOPNOTSUPP;
-                       // TODO: Implement...
-                       // err = vmtruncate(vi, attr->ia_size);
+                       ntfs_inode *ni = NTFS_I(vi);
+                       /*
+                        * FIXME: For now we do not support resizing of
+                        * compressed or encrypted files yet.
+                        */
+                       if (NInoCompressed(ni) || NInoEncrypted(ni)) {
+                               ntfs_warning(vi->i_sb, "Changes in inode size "
+                                               "are not supported yet for "
+                                               "%s files, ignoring.",
+                                               NInoCompressed(ni) ?
+                                               "compressed" : "encrypted");
+                               err = -EOPNOTSUPP;
+                       } else
+                               err = vmtruncate(vi, attr->ia_size);
                        if (err || ia_valid == ATTR_SIZE)
                                goto out;
                } else {