* [PATCH 0/4] second batch of new truncate sequence preparations
@ 2010-05-31 9:39 Christoph Hellwig
2010-05-31 9:40 ` [PATCH 1/4] add missing setattr methods Christoph Hellwig
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 9:39 UTC (permalink / raw)
To: viro, npiggin; +Cc: jack, linux-fsdevel
Shift all calls of vmtruncate from generic setattr code into the
filesystem instances. This implies making ->setattr mandatory for
filesystems that need to update disk state.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] add missing setattr methods
2010-05-31 9:39 [PATCH 0/4] second batch of new truncate sequence preparations Christoph Hellwig
@ 2010-05-31 9:40 ` Christoph Hellwig
2010-05-31 9:40 ` [PATCH 2/4] rename generic_setattr Christoph Hellwig
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 9:40 UTC (permalink / raw)
To: viro, npiggin; +Cc: jack, linux-fsdevel
For the new truncate sequence every filesystem that wants to truncate on-disk
state needs a seattr method. Convert the remaining filesystems that implement
the truncate inode operation to have it's own setattr method.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6/fs/hfsplus/inode.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/inode.c 2010-05-30 23:27:41.305253681 +0200
+++ linux-2.6/fs/hfsplus/inode.c 2010-05-30 23:27:48.000000000 +0200
@@ -290,9 +290,21 @@ static int hfsplus_file_release(struct i
return 0;
}
+static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+ return inode_setattr(inode, attr);
+}
+
static const struct inode_operations hfsplus_file_inode_operations = {
.lookup = hfsplus_file_lookup,
.truncate = hfsplus_file_truncate,
+ .setattr = hfsplus_setattr,
.setxattr = hfsplus_setxattr,
.getxattr = hfsplus_getxattr,
.listxattr = hfsplus_listxattr,
Index: linux-2.6/fs/minix/file.c
===================================================================
--- linux-2.6.orig/fs/minix/file.c 2010-05-30 22:27:14.761016568 +0200
+++ linux-2.6/fs/minix/file.c 2010-05-30 23:27:48.000000000 +0200
@@ -23,7 +23,19 @@ const struct file_operations minix_file_
.splice_read = generic_file_splice_read,
};
+static int minix_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+ return inode_setattr(inode, attr);
+}
+
const struct inode_operations minix_file_inode_operations = {
.truncate = minix_truncate,
+ .setattr = minix_setattr,
.getattr = minix_getattr,
};
Index: linux-2.6/fs/omfs/file.c
===================================================================
--- linux-2.6.orig/fs/omfs/file.c 2010-05-30 23:27:45.963253961 +0200
+++ linux-2.6/fs/omfs/file.c 2010-05-30 23:27:48.000000000 +0200
@@ -341,7 +341,19 @@ const struct file_operations omfs_file_o
.splice_read = generic_file_splice_read,
};
+static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+ return inode_setattr(inode, attr);
+}
+
const struct inode_operations omfs_file_inops = {
+ .setattr = omfs_setattr,
.truncate = omfs_truncate
};
Index: linux-2.6/fs/sysv/file.c
===================================================================
--- linux-2.6.orig/fs/sysv/file.c 2010-05-30 22:27:14.730255707 +0200
+++ linux-2.6/fs/sysv/file.c 2010-05-30 23:27:48.000000000 +0200
@@ -30,7 +30,19 @@ const struct file_operations sysv_file_o
.splice_read = generic_file_splice_read,
};
+static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+ return inode_setattr(inode, attr);
+}
+
const struct inode_operations sysv_file_inode_operations = {
.truncate = sysv_truncate,
+ .setattr = sysv_setattr,
.getattr = sysv_getattr,
};
Index: linux-2.6/fs/udf/file.c
===================================================================
--- linux-2.6.orig/fs/udf/file.c 2010-05-31 08:43:43.475253891 +0200
+++ linux-2.6/fs/udf/file.c 2010-05-31 08:44:11.428301463 +0200
@@ -228,6 +228,18 @@ const struct file_operations udf_file_op
.llseek = generic_file_llseek,
};
+static int udf_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = inode_change_ok(inode, attr);
+ if (error)
+ return error;
+ return inode_setattr(inode, attr);
+}
+
const struct inode_operations udf_file_inode_operations = {
+ .setattr = udf_setattr,
.truncate = udf_truncate,
};
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/4] rename generic_setattr
2010-05-31 9:39 [PATCH 0/4] second batch of new truncate sequence preparations Christoph Hellwig
2010-05-31 9:40 ` [PATCH 1/4] add missing setattr methods Christoph Hellwig
@ 2010-05-31 9:40 ` Christoph Hellwig
2010-05-31 9:40 ` [PATCH 3/4] default to simple_setattr Christoph Hellwig
2010-05-31 9:40 ` [PATCH 4/4] remove inode_setattr Christoph Hellwig
3 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 9:40 UTC (permalink / raw)
To: viro, npiggin; +Cc: jack, linux-fsdevel
Despite it's name it's now a generic implementation of ->setattr, but
rather a helper to copy attributes from a struct iattr to the inode.
Rename it to setattr_copy to reflect this fact.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c 2010-05-31 10:16:11.000000000 +0200
+++ linux-2.6/fs/attr.c 2010-05-31 10:17:30.331254661 +0200
@@ -105,13 +105,13 @@ out_big:
EXPORT_SYMBOL(inode_newsize_ok);
/**
- * generic_setattr - copy simple metadata updates into the generic inode
+ * setattr_copy - copy simple metadata updates into the generic inode
* @inode: the inode to be updated
* @attr: the new attributes
*
- * generic_setattr must be called with i_mutex held.
+ * setattr_copy must be called with i_mutex held.
*
- * generic_setattr updates the inode's metadata with that specified
+ * setattr_copy updates the inode's metadata with that specified
* in attr. Noticably missing is inode size update, which is more complex
* as it requires pagecache updates. See simple_setsize.
*
@@ -119,7 +119,7 @@ EXPORT_SYMBOL(inode_newsize_ok);
* that for "simple" filesystems, the struct inode is the inode storage.
* The caller is free to mark the inode dirty afterwards if needed.
*/
-void generic_setattr(struct inode *inode, const struct iattr *attr)
+void setattr_copy(struct inode *inode, const struct iattr *attr)
{
unsigned int ia_valid = attr->ia_valid;
@@ -144,11 +144,11 @@ void generic_setattr(struct inode *inode
inode->i_mode = mode;
}
}
-EXPORT_SYMBOL(generic_setattr);
+EXPORT_SYMBOL(setattr_copy);
/*
* note this function is deprecated, the new truncate sequence should be
- * used instead -- see eg. simple_setsize, generic_setattr.
+ * used instead -- see eg. simple_setsize, setattr_copy.
*/
int inode_setattr(struct inode *inode, const struct iattr *attr)
{
@@ -163,7 +163,7 @@ int inode_setattr(struct inode *inode, c
return error;
}
- generic_setattr(inode, attr);
+ setattr_copy(inode, attr);
mark_inode_dirty(inode);
Index: linux-2.6/fs/ext2/inode.c
===================================================================
--- linux-2.6.orig/fs/ext2/inode.c 2010-05-31 10:16:08.000000000 +0200
+++ linux-2.6/fs/ext2/inode.c 2010-05-31 10:17:30.332254940 +0200
@@ -1544,7 +1544,7 @@ int ext2_setattr(struct dentry *dentry,
if (error)
return error;
}
- generic_setattr(inode, iattr);
+ setattr_copy(inode, iattr);
if (iattr->ia_valid & ATTR_MODE)
error = ext2_acl_chmod(inode);
mark_inode_dirty(inode);
Index: linux-2.6/fs/fat/file.c
===================================================================
--- linux-2.6.orig/fs/fat/file.c 2010-05-31 10:15:57.000000000 +0200
+++ linux-2.6/fs/fat/file.c 2010-05-31 10:17:30.345254940 +0200
@@ -446,7 +446,7 @@ int fat_setattr(struct dentry *dentry, s
goto out;
}
- generic_setattr(inode, attr);
+ setattr_copy(inode, attr);
mark_inode_dirty(inode);
out:
return error;
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c 2010-05-31 10:16:11.000000000 +0200
+++ linux-2.6/fs/libfs.c 2010-05-31 10:18:04.781254519 +0200
@@ -395,8 +395,7 @@ int simple_setattr(struct dentry *dentry
return error;
}
- generic_setattr(inode, iattr);
-
+ setattr_copy(inode, iattr);
return error;
}
EXPORT_SYMBOL(simple_setattr);
Index: linux-2.6/fs/ramfs/file-nommu.c
===================================================================
--- linux-2.6.orig/fs/ramfs/file-nommu.c 2010-05-31 10:15:57.000000000 +0200
+++ linux-2.6/fs/ramfs/file-nommu.c 2010-05-31 10:17:30.353254032 +0200
@@ -183,7 +183,7 @@ static int ramfs_nommu_setattr(struct de
}
}
- generic_setattr(inode, ia);
+ setattr_copy(inode, ia);
out:
ia->ia_valid = old_ia_valid;
return ret;
Index: linux-2.6/fs/sysfs/inode.c
===================================================================
--- linux-2.6.orig/fs/sysfs/inode.c 2010-05-31 10:15:57.000000000 +0200
+++ linux-2.6/fs/sysfs/inode.c 2010-05-31 10:17:30.358254172 +0200
@@ -118,7 +118,7 @@ int sysfs_setattr(struct dentry *dentry,
goto out;
/* this ignores size changes */
- generic_setattr(inode, iattr);
+ setattr_copy(inode, iattr);
error = sysfs_sd_setattr(sd, iattr);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h 2010-05-31 10:15:57.000000000 +0200
+++ linux-2.6/include/linux/fs.h 2010-05-31 10:17:30.363254032 +0200
@@ -2379,7 +2379,7 @@ extern int buffer_migrate_page(struct ad
extern int inode_change_ok(const struct inode *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset);
extern int __must_check inode_setattr(struct inode *, const struct iattr *);
-extern void generic_setattr(struct inode *inode, const struct iattr *attr);
+extern void setattr_copy(struct inode *inode, const struct iattr *attr);
extern void file_update_time(struct file *file);
Index: linux-2.6/mm/shmem.c
===================================================================
--- linux-2.6.orig/mm/shmem.c 2010-05-31 10:15:57.000000000 +0200
+++ linux-2.6/mm/shmem.c 2010-05-31 10:17:30.368253403 +0200
@@ -810,7 +810,7 @@ static int shmem_notify_change(struct de
error = inode_change_ok(inode, attr);
if (!error)
- generic_setattr(inode, attr);
+ setattr_copy(inode, attr);
#ifdef CONFIG_TMPFS_POSIX_ACL
if (!error && (attr->ia_valid & ATTR_MODE))
error = generic_acl_chmod(inode);
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/4] default to simple_setattr
2010-05-31 9:39 [PATCH 0/4] second batch of new truncate sequence preparations Christoph Hellwig
2010-05-31 9:40 ` [PATCH 1/4] add missing setattr methods Christoph Hellwig
2010-05-31 9:40 ` [PATCH 2/4] rename generic_setattr Christoph Hellwig
@ 2010-05-31 9:40 ` Christoph Hellwig
2010-05-31 9:40 ` [PATCH 4/4] remove inode_setattr Christoph Hellwig
3 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 9:40 UTC (permalink / raw)
To: viro, npiggin; +Cc: jack, linux-fsdevel
With the new truncate sequence every filesystem that wants to support file
size changes on disk needs to implement it's own ->setattr. So instead
of calling inode_setattr which supports size changes call into a simple
method that doesn't support this. simple_setattr is almost what we
want except that it does not mark the inode dirty after changes. Given
that marking the inode dirty is a no-op for the simple in-memory filesystems
that use simple_setattr currently just add the mark_inode_dirty call.
Also add a WARN_ON for the presence of a truncate method to simple_setattr
to catch new instances of it during the transition period.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c 2010-05-31 10:17:30.000000000 +0200
+++ linux-2.6/fs/attr.c 2010-05-31 10:18:23.508254171 +0200
@@ -237,13 +237,10 @@ int notify_change(struct dentry * dentry
if (ia_valid & ATTR_SIZE)
down_write(&dentry->d_inode->i_alloc_sem);
- if (inode->i_op && inode->i_op->setattr) {
+ if (inode->i_op->setattr)
error = inode->i_op->setattr(dentry, attr);
- } else {
- error = inode_change_ok(inode, attr);
- if (!error)
- error = inode_setattr(inode, attr);
- }
+ else
+ error = simple_setattr(dentry, attr);
if (ia_valid & ATTR_SIZE)
up_write(&dentry->d_inode->i_alloc_sem);
Index: linux-2.6/fs/libfs.c
===================================================================
--- linux-2.6.orig/fs/libfs.c 2010-05-31 10:18:04.000000000 +0200
+++ linux-2.6/fs/libfs.c 2010-05-31 10:22:31.102254031 +0200
@@ -370,21 +370,26 @@ int simple_setsize(struct inode *inode,
EXPORT_SYMBOL(simple_setsize);
/**
- * simple_setattr - setattr for simple in-memory filesystem
+ * simple_setattr - setattr for simple filesystem
* @dentry: dentry
* @iattr: iattr structure
*
* Returns 0 on success, -error on failure.
*
- * simple_setattr implements setattr for an in-memory filesystem which
- * does not store its own file data or metadata (eg. uses the page cache
- * and inode cache as its data store).
+ * simple_setattr is a simple ->setattr implementation without a proper
+ * implementation of size changes.
+ *
+ * It can either be used for in-memory filesystems or special files
+ * on simple regular filesystems. Anything that needs to change on-disk
+ * or wire state on size changes needs it's own setattr method.
*/
int simple_setattr(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry->d_inode;
int error;
+ WARN_ON_ONCE(inode->i_op->truncate);
+
error = inode_change_ok(inode, iattr);
if (error)
return error;
@@ -396,7 +401,8 @@ int simple_setattr(struct dentry *dentry
}
setattr_copy(inode, iattr);
- return error;
+ mark_inode_dirty(inode);
+ return 0;
}
EXPORT_SYMBOL(simple_setattr);
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/4] remove inode_setattr
2010-05-31 9:39 [PATCH 0/4] second batch of new truncate sequence preparations Christoph Hellwig
` (2 preceding siblings ...)
2010-05-31 9:40 ` [PATCH 3/4] default to simple_setattr Christoph Hellwig
@ 2010-05-31 9:40 ` Christoph Hellwig
2010-05-31 10:36 ` Boaz Harrosh
2010-05-31 14:04 ` Nick Piggin
3 siblings, 2 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 9:40 UTC (permalink / raw)
To: viro, npiggin; +Cc: jack, linux-fsdevel
Replace inode_setattr with opencoded variants of it in all callers. This
moves the remaining call to vmtruncate into the filesystem methods where it
can be replaced with the proper truncate sequence.
In a few cases it was obvious that we would never end up calling vmtruncate
so it was left out in the opencoded variant:
spufs: explicitly checks for ATTR_SIZE earlier
btrfs,hugetlbfs,logfs,dlmfs: explicitly clears ATTR_SIZE earlier
ufs: contains an opencoded simple_seattr + truncate that sets the filesize just above
In addition to that ncpfs called inode_setattr with handcrafted iattrs,
which allowed to trim down the opencoded variant.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/inode.c 2010-05-31 10:15:55.725273307 +0200
+++ linux-2.6/arch/powerpc/platforms/cell/spufs/inode.c 2010-05-31 10:22:36.923254241 +0200
@@ -110,7 +110,9 @@ spufs_setattr(struct dentry *dentry, str
if ((attr->ia_valid & ATTR_SIZE) &&
(attr->ia_size != inode->i_size))
return -EINVAL;
- return inode_setattr(inode, attr);
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
Index: linux-2.6/drivers/staging/pohmelfs/inode.c
===================================================================
--- linux-2.6.orig/drivers/staging/pohmelfs/inode.c 2010-05-31 10:15:55.739254519 +0200
+++ linux-2.6/drivers/staging/pohmelfs/inode.c 2010-05-31 10:22:36.924254171 +0200
@@ -968,12 +968,18 @@ int pohmelfs_setattr_raw(struct inode *i
goto err_out_exit;
}
- err = inode_setattr(inode, attr);
- if (err) {
- dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
- goto err_out_exit;
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ err = vmtruncate(inode, attr->ia_size);
+ if (err) {
+ dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino);
+ goto err_out_exit;
+ }
}
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n",
__func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode,
inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size);
Index: linux-2.6/fs/9p/vfs_inode.c
===================================================================
--- linux-2.6.orig/fs/9p/vfs_inode.c 2010-05-31 10:15:55.749253821 +0200
+++ linux-2.6/fs/9p/vfs_inode.c 2010-05-31 10:22:36.929253961 +0200
@@ -896,10 +896,19 @@ static int v9fs_vfs_setattr(struct dentr
}
retval = p9_client_wstat(fid, &wstat);
- if (retval >= 0)
- retval = inode_setattr(dentry->d_inode, iattr);
+ if (retval < 0)
+ return retval;
- return retval;
+ if ((iattr->ia_valid & ATTR_SIZE) &&
+ iattr->ia_size != i_size_read(dentry->d_inode)) {
+ retval = vmtruncate(dentry->d_inode, iattr->ia_size);
+ if (retval)
+ return retval;
+ }
+
+ setattr_copy(dentry->d_inode, iattr);
+ mark_inode_dirty(dentry->d_inode);
+ return 0;
}
/**
Index: linux-2.6/fs/affs/inode.c
===================================================================
--- linux-2.6.orig/fs/affs/inode.c 2010-05-31 10:15:55.757254170 +0200
+++ linux-2.6/fs/affs/inode.c 2010-05-31 10:22:36.934254590 +0200
@@ -235,8 +235,17 @@ affs_notify_change(struct dentry *dentry
goto out;
}
- error = inode_setattr(inode, attr);
- if (!error && (attr->ia_valid & ATTR_MODE))
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
+ if (attr->ia_valid & ATTR_MODE)
mode_to_prot(inode);
out:
return error;
Index: linux-2.6/fs/attr.c
===================================================================
--- linux-2.6.orig/fs/attr.c 2010-05-31 10:18:23.508254171 +0200
+++ linux-2.6/fs/attr.c 2010-05-31 10:22:36.939253752 +0200
@@ -146,31 +146,6 @@ void setattr_copy(struct inode *inode, c
}
EXPORT_SYMBOL(setattr_copy);
-/*
- * note this function is deprecated, the new truncate sequence should be
- * used instead -- see eg. simple_setsize, setattr_copy.
- */
-int inode_setattr(struct inode *inode, const struct iattr *attr)
-{
- unsigned int ia_valid = attr->ia_valid;
-
- if (ia_valid & ATTR_SIZE &&
- attr->ia_size != i_size_read(inode)) {
- int error;
-
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- return error;
- }
-
- setattr_copy(inode, attr);
-
- mark_inode_dirty(inode);
-
- return 0;
-}
-EXPORT_SYMBOL(inode_setattr);
-
int notify_change(struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
Index: linux-2.6/fs/btrfs/inode.c
===================================================================
--- linux-2.6.orig/fs/btrfs/inode.c 2010-05-31 10:15:55.774254240 +0200
+++ linux-2.6/fs/btrfs/inode.c 2010-05-31 10:22:36.945254660 +0200
@@ -3656,13 +3656,15 @@ static int btrfs_setattr(struct dentry *
if (err)
return err;
}
- attr->ia_valid &= ~ATTR_SIZE;
- if (attr->ia_valid)
- err = inode_setattr(inode, attr);
+ if (attr->ia_valid) {
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
+ if (attr->ia_valid & ATTR_MODE)
+ err = btrfs_acl_chmod(inode);
+ }
- if (!err && ((attr->ia_valid & ATTR_MODE)))
- err = btrfs_acl_chmod(inode);
return err;
}
Index: linux-2.6/fs/cifs/inode.c
===================================================================
--- linux-2.6.orig/fs/cifs/inode.c 2010-05-31 10:15:55.783253961 +0200
+++ linux-2.6/fs/cifs/inode.c 2010-05-31 10:22:36.954254939 +0200
@@ -1869,18 +1869,27 @@ cifs_setattr_unix(struct dentry *direntr
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- if (!rc) {
- rc = inode_setattr(inode, attrs);
+ if (rc)
+ goto out;
- /* force revalidate when any of these times are set since some
- of the fs types (eg ext3, fat) do not have fine enough
- time granularity to match protocol, and we do not have a
- a way (yet) to query the server fs's time granularity (and
- whether it rounds times down).
- */
- if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
- cifsInode->time = 0;
- }
+ if ((attrs->ia_valid & ATTR_SIZE) &&
+ attrs->ia_size != i_size_read(inode)) {
+ rc = vmtruncate(inode, attrs->ia_size);
+ if (rc)
+ goto out;
+ }
+
+ setattr_copy(inode, attrs);
+ mark_inode_dirty(inode);
+
+ /* force revalidate when any of these times are set since some
+ of the fs types (eg ext3, fat) do not have fine enough
+ time granularity to match protocol, and we do not have a
+ a way (yet) to query the server fs's time granularity (and
+ whether it rounds times down).
+ */
+ if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))
+ cifsInode->time = 0;
out:
kfree(args);
kfree(full_path);
@@ -2020,8 +2029,20 @@ cifs_setattr_nounix(struct dentry *diren
/* do not need local check to inode_check_ok since the server does
that */
- if (!rc)
- rc = inode_setattr(inode, attrs);
+ if (rc)
+ goto cifs_setattr_exit;
+
+ if ((attrs->ia_valid & ATTR_SIZE) &&
+ attrs->ia_size != i_size_read(inode)) {
+ rc = vmtruncate(inode, attrs->ia_size);
+ if (rc)
+ goto cifs_setattr_exit;
+ }
+
+ setattr_copy(inode, attrs);
+ mark_inode_dirty(inode);
+ return 0;
+
cifs_setattr_exit:
kfree(full_path);
FreeXid(xid);
Index: linux-2.6/fs/exofs/inode.c
===================================================================
--- linux-2.6.orig/fs/exofs/inode.c 2010-05-31 10:15:55.792254729 +0200
+++ linux-2.6/fs/exofs/inode.c 2010-05-31 10:22:36.959254590 +0200
@@ -887,8 +887,18 @@ int exofs_setattr(struct dentry *dentry,
if (error)
return error;
- error = inode_setattr(inode, iattr);
- return error;
+ if ((iattr->ia_valid & ATTR_SIZE) &&
+ iattr->ia_size != i_size_read(inode)) {
+ int error;
+
+ error = vmtruncate(inode, iattr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, iattr);
+ mark_inode_dirty(inode);
+ return 0;
}
static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF(
Index: linux-2.6/fs/ext3/inode.c
===================================================================
--- linux-2.6.orig/fs/ext3/inode.c 2010-05-31 10:16:06.183003857 +0200
+++ linux-2.6/fs/ext3/inode.c 2010-05-31 10:22:36.965254730 +0200
@@ -3208,9 +3208,17 @@ int ext3_setattr(struct dentry *dentry,
ext3_journal_stop(handle);
}
- rc = inode_setattr(inode, attr);
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ rc = vmtruncate(inode, attr->ia_size);
+ if (rc)
+ goto err_out;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
- if (!rc && (ia_valid & ATTR_MODE))
+ if (ia_valid & ATTR_MODE)
rc = ext3_acl_chmod(inode);
err_out:
Index: linux-2.6/fs/ext4/inode.c
===================================================================
--- linux-2.6.orig/fs/ext4/inode.c 2010-05-31 10:16:06.187004834 +0200
+++ linux-2.6/fs/ext4/inode.c 2010-05-31 10:22:36.972254380 +0200
@@ -5529,11 +5529,19 @@ int ext4_setattr(struct dentry *dentry,
ext4_truncate(inode);
}
- rc = inode_setattr(inode, attr);
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode))
+ rc = vmtruncate(inode, attr->ia_size);
- /* If inode_setattr's call to ext4_truncate failed to get a
- * transaction handle at all, we need to clean up the in-core
- * orphan list manually. */
+ if (!rc) {
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ }
+
+ /*
+ * If the call to ext4_truncate failed to get a transaction handle at
+ * all, we need to clean up the in-core orphan list manually.
+ */
if (inode->i_nlink)
ext4_orphan_del(NULL, inode);
Index: linux-2.6/fs/hfs/inode.c
===================================================================
--- linux-2.6.orig/fs/hfs/inode.c 2010-05-31 10:15:55.819254170 +0200
+++ linux-2.6/fs/hfs/inode.c 2010-05-31 10:22:36.974253961 +0200
@@ -612,10 +612,16 @@ int hfs_inode_setattr(struct dentry *den
attr->ia_mode = inode->i_mode & ~S_IWUGO;
attr->ia_mode &= S_ISDIR(inode->i_mode) ? ~hsb->s_dir_umask: ~hsb->s_file_umask;
}
- error = inode_setattr(inode, attr);
- if (error)
- return error;
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
return 0;
}
Index: linux-2.6/fs/hfsplus/inode.c
===================================================================
--- linux-2.6.orig/fs/hfsplus/inode.c 2010-05-31 10:17:21.728253961 +0200
+++ linux-2.6/fs/hfsplus/inode.c 2010-05-31 10:22:36.978253961 +0200
@@ -298,7 +298,17 @@ static int hfsplus_setattr(struct dentry
error = inode_change_ok(inode, attr);
if (error)
return error;
- return inode_setattr(inode, attr);
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static const struct inode_operations hfsplus_file_inode_operations = {
Index: linux-2.6/fs/hpfs/inode.c
===================================================================
--- linux-2.6.orig/fs/hpfs/inode.c 2010-05-31 10:15:55.843254449 +0200
+++ linux-2.6/fs/hpfs/inode.c 2010-05-31 10:22:36.984254660 +0200
@@ -277,9 +277,15 @@ int hpfs_setattr(struct dentry *dentry,
if (error)
goto out_unlock;
- error = inode_setattr(inode, attr);
- if (error)
- goto out_unlock;
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
hpfs_write_inode(inode);
Index: linux-2.6/fs/hugetlbfs/inode.c
===================================================================
--- linux-2.6.orig/fs/hugetlbfs/inode.c 2010-05-31 10:15:55.852260596 +0200
+++ linux-2.6/fs/hugetlbfs/inode.c 2010-05-31 10:22:36.991253822 +0200
@@ -448,19 +448,20 @@ static int hugetlbfs_setattr(struct dent
error = inode_change_ok(inode, attr);
if (error)
- goto out;
+ return error;
if (ia_valid & ATTR_SIZE) {
error = -EINVAL;
- if (!(attr->ia_size & ~huge_page_mask(h)))
- error = hugetlb_vmtruncate(inode, attr->ia_size);
+ if (attr->ia_size & ~huge_page_mask(h))
+ return -EINVAL;
+ error = hugetlb_vmtruncate(inode, attr->ia_size);
if (error)
- goto out;
- attr->ia_valid &= ~ATTR_SIZE;
+ return error;
}
- error = inode_setattr(inode, attr);
-out:
- return error;
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
Index: linux-2.6/fs/logfs/file.c
===================================================================
--- linux-2.6.orig/fs/logfs/file.c 2010-05-31 10:15:55.862275053 +0200
+++ linux-2.6/fs/logfs/file.c 2010-05-31 10:22:36.998253961 +0200
@@ -232,15 +232,19 @@ static int logfs_setattr(struct dentry *
struct inode *inode = dentry->d_inode;
int err = 0;
- if (attr->ia_valid & ATTR_SIZE)
+ if (attr->ia_valid & ATTR_SIZE) {
err = logfs_truncate(inode, attr->ia_size);
- attr->ia_valid &= ~ATTR_SIZE;
+ if (err)
+ return err;
+ }
- if (!err)
- err = inode_change_ok(inode, attr);
- if (!err)
- err = inode_setattr(inode, attr);
- return err;
+ err = inode_change_ok(inode, attr);
+ if (err)
+ return err;
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations logfs_reg_iops = {
Index: linux-2.6/fs/minix/file.c
===================================================================
--- linux-2.6.orig/fs/minix/file.c 2010-05-31 10:17:21.729254031 +0200
+++ linux-2.6/fs/minix/file.c 2010-05-31 10:22:37.003254101 +0200
@@ -31,7 +31,17 @@ static int minix_setattr(struct dentry *
error = inode_change_ok(inode, attr);
if (error)
return error;
- return inode_setattr(inode, attr);
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations minix_file_inode_operations = {
Index: linux-2.6/fs/ocfs2/dlmfs/dlmfs.c
===================================================================
--- linux-2.6.orig/fs/ocfs2/dlmfs/dlmfs.c 2010-05-31 10:15:55.885254869 +0200
+++ linux-2.6/fs/ocfs2/dlmfs/dlmfs.c 2010-05-31 10:22:37.009255288 +0200
@@ -214,10 +214,12 @@ static int dlmfs_file_setattr(struct den
attr->ia_valid &= ~ATTR_SIZE;
error = inode_change_ok(inode, attr);
- if (!error)
- error = inode_setattr(inode, attr);
+ if (error)
+ return error;
- return error;
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait)
Index: linux-2.6/fs/omfs/file.c
===================================================================
--- linux-2.6.orig/fs/omfs/file.c 2010-05-31 10:17:21.731259688 +0200
+++ linux-2.6/fs/omfs/file.c 2010-05-31 10:22:37.015253822 +0200
@@ -349,7 +349,17 @@ static int omfs_setattr(struct dentry *d
error = inode_change_ok(inode, attr);
if (error)
return error;
- return inode_setattr(inode, attr);
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations omfs_file_inops = {
Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c 2010-05-31 10:15:55.912011189 +0200
+++ linux-2.6/fs/proc/base.c 2010-05-31 10:22:37.022254101 +0200
@@ -561,9 +561,19 @@ static int proc_setattr(struct dentry *d
return -EPERM;
error = inode_change_ok(inode, attr);
- if (!error)
- error = inode_setattr(inode, attr);
- return error;
+ if (error)
+ return error;
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static const struct inode_operations proc_def_inode_operations = {
Index: linux-2.6/fs/proc/generic.c
===================================================================
--- linux-2.6.orig/fs/proc/generic.c 2010-05-31 10:15:55.918005043 +0200
+++ linux-2.6/fs/proc/generic.c 2010-05-31 10:22:37.028254520 +0200
@@ -12,6 +12,7 @@
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mount.h>
@@ -258,17 +259,22 @@ static int proc_notify_change(struct den
error = inode_change_ok(inode, iattr);
if (error)
- goto out;
+ return error;
- error = inode_setattr(inode, iattr);
- if (error)
- goto out;
+ if ((iattr->ia_valid & ATTR_SIZE) &&
+ iattr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, iattr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, iattr);
+ mark_inode_dirty(inode);
de->uid = inode->i_uid;
de->gid = inode->i_gid;
de->mode = inode->i_mode;
-out:
- return error;
+ return 0;
}
static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
Index: linux-2.6/fs/proc/proc_sysctl.c
===================================================================
--- linux-2.6.orig/fs/proc/proc_sysctl.c 2010-05-31 10:15:55.925004484 +0200
+++ linux-2.6/fs/proc/proc_sysctl.c 2010-05-31 10:22:37.033254799 +0200
@@ -329,10 +329,19 @@ static int proc_sys_setattr(struct dentr
return -EPERM;
error = inode_change_ok(inode, attr);
- if (!error)
- error = inode_setattr(inode, attr);
+ if (error)
+ return error;
- return error;
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
Index: linux-2.6/fs/sysv/file.c
===================================================================
--- linux-2.6.orig/fs/sysv/file.c 2010-05-31 10:17:21.732272539 +0200
+++ linux-2.6/fs/sysv/file.c 2010-05-31 10:22:37.038254730 +0200
@@ -38,7 +38,17 @@ static int sysv_setattr(struct dentry *d
error = inode_change_ok(inode, attr);
if (error)
return error;
- return inode_setattr(inode, attr);
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations sysv_file_inode_operations = {
Index: linux-2.6/fs/udf/file.c
===================================================================
--- linux-2.6.orig/fs/udf/file.c 2010-05-31 10:17:21.733264088 +0200
+++ linux-2.6/fs/udf/file.c 2010-05-31 10:22:37.040257663 +0200
@@ -236,7 +236,17 @@ static int udf_setattr(struct dentry *de
error = inode_change_ok(inode, attr);
if (error)
return error;
- return inode_setattr(inode, attr);
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations udf_file_inode_operations = {
Index: linux-2.6/fs/ufs/truncate.c
===================================================================
--- linux-2.6.orig/fs/ufs/truncate.c 2010-05-31 10:15:55.955004345 +0200
+++ linux-2.6/fs/ufs/truncate.c 2010-05-31 10:22:37.045254171 +0200
@@ -525,7 +525,10 @@ int ufs_setattr(struct dentry *dentry, s
if (error)
return error;
}
- return inode_setattr(inode, attr);
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
const struct inode_operations ufs_file_inode_operations = {
Index: linux-2.6/fs/jfs/file.c
===================================================================
--- linux-2.6.orig/fs/jfs/file.c 2010-05-31 10:15:55.963004205 +0200
+++ linux-2.6/fs/jfs/file.c 2010-05-31 10:22:37.050253891 +0200
@@ -17,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
@@ -107,11 +108,18 @@ int jfs_setattr(struct dentry *dentry, s
return rc;
}
- rc = inode_setattr(inode, iattr);
+ if ((iattr->ia_valid & ATTR_SIZE) &&
+ iattr->ia_size != i_size_read(inode)) {
+ rc = vmtruncate(inode, iattr->ia_size);
+ if (rc)
+ return rc;
+ }
- if (!rc && (iattr->ia_valid & ATTR_MODE))
- rc = jfs_acl_chmod(inode);
+ setattr_copy(inode, iattr);
+ mark_inode_dirty(inode);
+ if (iattr->ia_valid & ATTR_MODE)
+ rc = jfs_acl_chmod(inode);
return rc;
}
Index: linux-2.6/fs/ncpfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ncpfs/inode.c 2010-05-31 10:15:55.970004484 +0200
+++ linux-2.6/fs/ncpfs/inode.c 2010-05-31 10:22:37.055253891 +0200
@@ -924,9 +924,8 @@ int ncp_notify_change(struct dentry *den
tmpattr.ia_valid = ATTR_MODE;
tmpattr.ia_mode = attr->ia_mode;
- result = inode_setattr(inode, &tmpattr);
- if (result)
- goto out;
+ setattr_copy(inode, &tmpattr);
+ mark_inode_dirty(inode);
}
}
#endif
@@ -954,15 +953,12 @@ int ncp_notify_change(struct dentry *den
result = ncp_make_closed(inode);
if (result)
goto out;
- {
- struct iattr tmpattr;
-
- tmpattr.ia_valid = ATTR_SIZE;
- tmpattr.ia_size = attr->ia_size;
-
- result = inode_setattr(inode, &tmpattr);
+
+ if (attr->ia_size != i_size_read(inode)) {
+ result = vmtruncate(inode, attr->ia_size);
if (result)
goto out;
+ mark_inode_dirty(inode);
}
}
if ((attr->ia_valid & ATTR_CTIME) != 0) {
@@ -1002,8 +998,12 @@ int ncp_notify_change(struct dentry *den
NCP_FINFO(inode)->nwattr = info.attributes;
#endif
}
- if (!result)
- result = inode_setattr(inode, attr);
+ if (result)
+ goto out;
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
out:
unlock_kernel();
return result;
Index: linux-2.6/fs/gfs2/inode.c
===================================================================
--- linux-2.6.orig/fs/gfs2/inode.c 2010-05-31 10:15:55.976004065 +0200
+++ linux-2.6/fs/gfs2/inode.c 2010-05-31 10:22:37.063254590 +0200
@@ -987,18 +987,29 @@ fail:
static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
{
+ struct inode *inode = &ip->i_inode;
struct buffer_head *dibh;
int error;
error = gfs2_meta_inode_buffer(ip, &dibh);
- if (!error) {
- error = inode_setattr(&ip->i_inode, attr);
- gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
- gfs2_trans_add_bh(ip->i_gl, dibh, 1);
- gfs2_dinode_out(ip, dibh->b_data);
- brelse(dibh);
+ if (error)
+ return error;
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
}
- return error;
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
+ gfs2_assert_warn(GFS2_SB(inode), !error);
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ gfs2_dinode_out(ip, dibh->b_data);
+ brelse(dibh);
+ return 0;
}
/**
Index: linux-2.6/fs/gfs2/ops_inode.c
===================================================================
--- linux-2.6.orig/fs/gfs2/ops_inode.c 2010-05-31 10:15:55.983004065 +0200
+++ linux-2.6/fs/gfs2/ops_inode.c 2010-05-31 10:22:37.070253472 +0200
@@ -1136,8 +1136,16 @@ static int setattr_chown(struct inode *i
if (error)
goto out_end_trans;
- error = inode_setattr(inode, attr);
- gfs2_assert_warn(sdp, !error);
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ int error;
+
+ error = vmtruncate(inode, attr->ia_size);
+ gfs2_assert_warn(sdp, !error);
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
Index: linux-2.6/fs/gfs2/xattr.c
===================================================================
--- linux-2.6.orig/fs/gfs2/xattr.c 2010-05-31 10:15:55.991004834 +0200
+++ linux-2.6/fs/gfs2/xattr.c 2010-05-31 10:22:37.078253542 +0200
@@ -1296,6 +1296,7 @@ fail:
int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
{
+ struct inode *inode = &ip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_ea_location el;
struct buffer_head *dibh;
@@ -1321,14 +1322,25 @@ int gfs2_xattr_acl_chmod(struct gfs2_ino
return error;
error = gfs2_meta_inode_buffer(ip, &dibh);
- if (!error) {
- error = inode_setattr(&ip->i_inode, attr);
- gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
- gfs2_trans_add_bh(ip->i_gl, dibh, 1);
- gfs2_dinode_out(ip, dibh->b_data);
- brelse(dibh);
+ if (error)
+ goto out_trans_end;
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ int error;
+
+ error = vmtruncate(inode, attr->ia_size);
+ gfs2_assert_warn(GFS2_SB(inode), !error);
}
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ gfs2_dinode_out(ip, dibh->b_data);
+ brelse(dibh);
+
+out_trans_end:
gfs2_trans_end(sdp);
return error;
}
Index: linux-2.6/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.orig/fs/hostfs/hostfs_kern.c 2010-05-31 10:15:56.000253751 +0200
+++ linux-2.6/fs/hostfs/hostfs_kern.c 2010-05-31 10:22:37.082254590 +0200
@@ -849,13 +849,14 @@ int hostfs_permission(struct inode *ino,
int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = dentry->d_inode;
struct hostfs_iattr attrs;
char *name;
int err;
- int fd = HOSTFS_I(dentry->d_inode)->fd;
+ int fd = HOSTFS_I(inode)->fd;
- err = inode_change_ok(dentry->d_inode, attr);
+ err = inode_change_ok(inode, attr);
if (err)
return err;
@@ -905,7 +906,18 @@ int hostfs_setattr(struct dentry *dentry
if (err)
return err;
- return inode_setattr(dentry->d_inode, attr);
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ int error;
+
+ error = vmtruncate(inode, attr->ia_size);
+ if (err)
+ return err;
+ }
+
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+ return 0;
}
static const struct inode_operations hostfs_iops = {
Index: linux-2.6/fs/nilfs2/inode.c
===================================================================
--- linux-2.6.orig/fs/nilfs2/inode.c 2010-05-31 10:16:08.091253822 +0200
+++ linux-2.6/fs/nilfs2/inode.c 2010-05-31 10:22:37.089253891 +0200
@@ -656,14 +656,27 @@ int nilfs_setattr(struct dentry *dentry,
err = nilfs_transaction_begin(sb, &ti, 0);
if (unlikely(err))
return err;
- err = inode_setattr(inode, iattr);
- if (!err && (iattr->ia_valid & ATTR_MODE))
+
+ if ((iattr->ia_valid & ATTR_SIZE) &&
+ iattr->ia_size != i_size_read(inode)) {
+ err = vmtruncate(inode, iattr->ia_size);
+ if (unlikely(err))
+ goto out_err;
+ }
+
+ setattr_copy(inode, iattr);
+ mark_inode_dirty(inode);
+
+ if (iattr->ia_valid & ATTR_MODE) {
err = nilfs_acl_chmod(inode);
- if (likely(!err))
- err = nilfs_transaction_commit(sb);
- else
- nilfs_transaction_abort(sb);
+ if (unlikely(err))
+ goto out_err;
+ }
+
+ return nilfs_transaction_commit(sb);
+out_err:
+ nilfs_transaction_abort(sb);
return err;
}
Index: linux-2.6/fs/ntfs/inode.c
===================================================================
--- linux-2.6.orig/fs/ntfs/inode.c 2010-05-31 10:15:56.015254100 +0200
+++ linux-2.6/fs/ntfs/inode.c 2010-05-31 10:22:37.095254450 +0200
@@ -2879,9 +2879,6 @@ void ntfs_truncate_vfs(struct inode *vi)
*
* 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()
- * functionality, except we intercept and abort changes in i_size.
*/
int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
{
Index: linux-2.6/fs/ocfs2/file.c
===================================================================
--- linux-2.6.orig/fs/ocfs2/file.c 2010-05-31 10:15:55.892254659 +0200
+++ linux-2.6/fs/ocfs2/file.c 2010-05-31 10:36:19.166254101 +0200
@@ -1057,13 +1057,21 @@ int ocfs2_setattr(struct dentry *dentry,
* Otherwise, we could get into problems with truncate as
* ip_alloc_sem is used there to protect against i_size
* changes.
+ *
+ * XXX: this means the conditional below can probably be removed.
*/
- status = inode_setattr(inode, attr);
- if (status < 0) {
- mlog_errno(status);
- goto bail_commit;
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode)) {
+ status = vmtruncate(inode, attr->ia_size);
+ if (status) {
+ mlog_errno(status);
+ goto bail_commit;
+ }
}
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
+
status = ocfs2_mark_inode_dirty(handle, inode, bh);
if (status < 0)
mlog_errno(status);
Index: linux-2.6/fs/reiserfs/inode.c
===================================================================
--- linux-2.6.orig/fs/reiserfs/inode.c 2010-05-31 10:16:06.192003298 +0200
+++ linux-2.6/fs/reiserfs/inode.c 2010-05-31 10:22:37.106254590 +0200
@@ -3136,54 +3136,61 @@ int reiserfs_setattr(struct dentry *dent
}
error = inode_change_ok(inode, attr);
- if (!error) {
- if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
- (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
- error = reiserfs_chown_xattrs(inode, attr);
-
- if (!error) {
- struct reiserfs_transaction_handle th;
- int jbegin_count =
- 2 *
- (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) +
- REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) +
- 2;
-
- /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
- error =
- journal_begin(&th, inode->i_sb,
- jbegin_count);
- if (error)
- goto out;
- error = dquot_transfer(inode, attr);
- if (error) {
- journal_end(&th, inode->i_sb,
- jbegin_count);
- goto out;
- }
- /* Update corresponding info in inode so that everything is in
- * one transaction */
- if (attr->ia_valid & ATTR_UID)
- inode->i_uid = attr->ia_uid;
- if (attr->ia_valid & ATTR_GID)
- inode->i_gid = attr->ia_gid;
- mark_inode_dirty(inode);
- error =
- journal_end(&th, inode->i_sb, jbegin_count);
- }
- }
- if (!error) {
- /*
- * Relax the lock here, as it might truncate the
- * inode pages and wait for inode pages locks.
- * To release such page lock, the owner needs the
- * reiserfs lock
- */
- reiserfs_write_unlock_once(inode->i_sb, depth);
- error = inode_setattr(inode, attr);
- depth = reiserfs_write_lock_once(inode->i_sb);
+ if (error)
+ goto out;
+
+ if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+ (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+ struct reiserfs_transaction_handle th;
+ int jbegin_count =
+ 2 *
+ (REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb) +
+ REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)) +
+ 2;
+
+ error = reiserfs_chown_xattrs(inode, attr);
+
+ if (error)
+ return error;
+
+ /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
+ error = journal_begin(&th, inode->i_sb, jbegin_count);
+ if (error)
+ goto out;
+ error = dquot_transfer(inode, attr);
+ if (error) {
+ journal_end(&th, inode->i_sb, jbegin_count);
+ goto out;
}
+
+ /* Update corresponding info in inode so that everything is in
+ * one transaction */
+ if (attr->ia_valid & ATTR_UID)
+ inode->i_uid = attr->ia_uid;
+ if (attr->ia_valid & ATTR_GID)
+ inode->i_gid = attr->ia_gid;
+ mark_inode_dirty(inode);
+ error = journal_end(&th, inode->i_sb, jbegin_count);
+ if (error)
+ goto out;
+ }
+
+ /*
+ * Relax the lock here, as it might truncate the
+ * inode pages and wait for inode pages locks.
+ * To release such page lock, the owner needs the
+ * reiserfs lock
+ */
+ reiserfs_write_unlock_once(inode->i_sb, depth);
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size != i_size_read(inode))
+ error = vmtruncate(inode, attr->ia_size);
+
+ if (!error) {
+ setattr_copy(inode, attr);
+ mark_inode_dirty(inode);
}
+ depth = reiserfs_write_lock_once(inode->i_sb);
if (!error && reiserfs_posixacl(inode->i_sb)) {
if (attr->ia_valid & ATTR_MODE)
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h 2010-05-31 10:17:30.363254032 +0200
+++ linux-2.6/include/linux/fs.h 2010-05-31 10:22:37.113253891 +0200
@@ -2378,7 +2378,6 @@ extern int buffer_migrate_page(struct ad
extern int inode_change_ok(const struct inode *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset);
-extern int __must_check inode_setattr(struct inode *, const struct iattr *);
extern void setattr_copy(struct inode *inode, const struct iattr *attr);
extern void file_update_time(struct file *file);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] remove inode_setattr
2010-05-31 9:40 ` [PATCH 4/4] remove inode_setattr Christoph Hellwig
@ 2010-05-31 10:36 ` Boaz Harrosh
2010-05-31 14:04 ` Nick Piggin
1 sibling, 0 replies; 8+ messages in thread
From: Boaz Harrosh @ 2010-05-31 10:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: viro, npiggin, jack, linux-fsdevel
On 05/31/2010 12:40 PM, Christoph Hellwig wrote:
> Replace inode_setattr with opencoded variants of it in all callers. This
> moves the remaining call to vmtruncate into the filesystem methods where it
> can be replaced with the proper truncate sequence.
>
> In a few cases it was obvious that we would never end up calling vmtruncate
> so it was left out in the opencoded variant:
>
> spufs: explicitly checks for ATTR_SIZE earlier
> btrfs,hugetlbfs,logfs,dlmfs: explicitly clears ATTR_SIZE earlier
> ufs: contains an opencoded simple_seattr + truncate that sets the filesize just above
>
> In addition to that ncpfs called inode_setattr with handcrafted iattrs,
> which allowed to trim down the opencoded variant.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
>
<snip>
> Index: linux-2.6/fs/exofs/inode.c
> ===================================================================
> --- linux-2.6.orig/fs/exofs/inode.c 2010-05-31 10:15:55.792254729 +0200
> +++ linux-2.6/fs/exofs/inode.c 2010-05-31 10:22:36.959254590 +0200
> @@ -887,8 +887,18 @@ int exofs_setattr(struct dentry *dentry,
> if (error)
> return error;
>
> - error = inode_setattr(inode, iattr);
> - return error;
> + if ((iattr->ia_valid & ATTR_SIZE) &&
> + iattr->ia_size != i_size_read(inode)) {
> + int error;
> +
> + error = vmtruncate(inode, iattr->ia_size);
> + if (error)
> + return error;
> + }
> +
> + setattr_copy(inode, iattr);
> + mark_inode_dirty(inode);
> + return 0;
> }
>
> static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF(
Hold on to this for just a sec. I'm already testing a proper conversion
replaying the conversion done to ext2. I'll send it your way so it can
get together with this patchset. (give me couple hours)
Boaz
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] remove inode_setattr
2010-05-31 9:40 ` [PATCH 4/4] remove inode_setattr Christoph Hellwig
2010-05-31 10:36 ` Boaz Harrosh
@ 2010-05-31 14:04 ` Nick Piggin
2010-05-31 14:08 ` Christoph Hellwig
1 sibling, 1 reply; 8+ messages in thread
From: Nick Piggin @ 2010-05-31 14:04 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: viro, jack, linux-fsdevel
On Mon, May 31, 2010 at 11:40:30AM +0200, Christoph Hellwig wrote:
> Replace inode_setattr with opencoded variants of it in all callers. This
> moves the remaining call to vmtruncate into the filesystem methods where it
> can be replaced with the proper truncate sequence.
>
> In a few cases it was obvious that we would never end up calling vmtruncate
> so it was left out in the opencoded variant:
>
> spufs: explicitly checks for ATTR_SIZE earlier
> btrfs,hugetlbfs,logfs,dlmfs: explicitly clears ATTR_SIZE earlier
> ufs: contains an opencoded simple_seattr + truncate that sets the filesize just above
>
> In addition to that ncpfs called inode_setattr with handcrafted iattrs,
> which allowed to trim down the opencoded variant.
The series all looks pretty good, ends up being quite a lot cleaner
in the core code.
This last patch is a question of a bit of churn and duplicated code
with the result of cleaner core code, and more explicitly putting
vmtruncate in the hands of the fs maintainers.
I have a bunch of fs conversions (several from you) I was going to
send to maintainers, they'll clash a bit. I'll see what ends up being
merged in 2.6.35 and try to fix up what I've got.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] remove inode_setattr
2010-05-31 14:04 ` Nick Piggin
@ 2010-05-31 14:08 ` Christoph Hellwig
0 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2010-05-31 14:08 UTC (permalink / raw)
To: Nick Piggin; +Cc: Christoph Hellwig, viro, jack, linux-fsdevel
On Tue, Jun 01, 2010 at 12:04:12AM +1000, Nick Piggin wrote:
> I have a bunch of fs conversions (several from you) I was going to
> send to maintainers, they'll clash a bit. I'll see what ends up being
> merged in 2.6.35 and try to fix up what I've got.
I'll help with the FS conversions, but I really wanted to get the
core code into shape first. One other thing that might be worth
doing before the mass FS conversions is moving the swapfile and
rlimit checks into the beginning of ->setattr instead of doing
them late as pointed out by Dimitri a while ago. I've started looking
into that.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-05-31 14:08 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-31 9:39 [PATCH 0/4] second batch of new truncate sequence preparations Christoph Hellwig
2010-05-31 9:40 ` [PATCH 1/4] add missing setattr methods Christoph Hellwig
2010-05-31 9:40 ` [PATCH 2/4] rename generic_setattr Christoph Hellwig
2010-05-31 9:40 ` [PATCH 3/4] default to simple_setattr Christoph Hellwig
2010-05-31 9:40 ` [PATCH 4/4] remove inode_setattr Christoph Hellwig
2010-05-31 10:36 ` Boaz Harrosh
2010-05-31 14:04 ` Nick Piggin
2010-05-31 14:08 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).