From: Jan Kara Date: Thu, 26 May 2016 14:55:18 +0000 (+0200) Subject: fs: Give dentry to inode_change_ok() instead of inode X-Git-Tag: v3.2.84~8 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=44b25c3e25af81daebf188ba1bc94b123ea40138 fs: Give dentry to inode_change_ok() instead of inode commit 31051c85b5e2aaaf6315f74c72a732673632a905 upstream. inode_change_ok() will be resposible for clearing capabilities and IMA extended attributes and as such will need dentry. Give it as an argument to inode_change_ok() instead of an inode. Also rename inode_change_ok() to setattr_prepare() to better relect that it does also some modifications in addition to checks. Reviewed-by: Christoph Hellwig Signed-off-by: Jan Kara [bwh: Backported to 3.2: - Drop changes to f2fs, lustre, orangefs, overlayfs - Adjust filenames, context - In nfsd, pass dentry to nfsd_sanitize_attrs() - In xfs, pass dentry to xfs_change_file_space(), xfs_set_mode(), xfs_setattr_nonsize(), and xfs_setattr_size() - Update ext3 as well - Mark pohmelfs as BROKEN; it's long dead upstream] Signed-off-by: Ben Hutchings --- diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index b4a3d765ff9a..56a9c6eab33f 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -288,8 +288,8 @@ implementing on-disk size changes. Start with a copy of the old inode_setattr and vmtruncate, and the reorder the vmtruncate + foofs_vmtruncate sequence to be in order of zeroing blocks using block_truncate_page or similar helpers, size update and on finally on-disk truncation which should not fail. -inode_change_ok now includes the size checks for ATTR_SIZE and must be called -in the beginning of ->setattr unconditionally. +setattr_prepare (which used to be inode_change_ok) now includes the size checks +for ATTR_SIZE and must be called in the beginning of ->setattr unconditionally. [mandatory] diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig index 8d53b1a1e715..b88769c03ccb 100644 --- a/drivers/staging/pohmelfs/Kconfig +++ b/drivers/staging/pohmelfs/Kconfig @@ -1,5 +1,6 @@ config POHMELFS tristate "POHMELFS filesystem support" + depends on BROKEN depends on NET select CONNECTOR select CRYPTO diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index adedfd401a30..34defa195a80 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1068,7 +1068,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) struct p9_wstat wstat; P9_DPRINTK(P9_DEBUG_VFS, "\n"); - retval = inode_change_ok(dentry->d_inode, iattr); + retval = setattr_prepare(dentry, iattr); if (retval) return retval; diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index dbbc83f6dc3b..781e56e328eb 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -538,7 +538,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) P9_DPRINTK(P9_DEBUG_VFS, "\n"); - retval = inode_change_ok(dentry->d_inode, iattr); + retval = setattr_prepare(dentry, iattr); if (retval) return retval; diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 1dab6a174d6a..c5e42d8c06a1 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -298,7 +298,7 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr) unsigned int ia_valid = attr->ia_valid; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); /* * we can't change the UID or GID of any file - diff --git a/fs/affs/inode.c b/fs/affs/inode.c index 88a4b0b50058..abda0dc63ec3 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -222,7 +222,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid); - error = inode_change_ok(inode,attr); + error = setattr_prepare(dentry, attr); if (error) goto out; diff --git a/fs/attr.c b/fs/attr.c index b8f55c40fb1d..0006fdeb721f 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -16,19 +16,22 @@ #include /** - * inode_change_ok - check if attribute changes to an inode are allowed - * @inode: inode to check + * setattr_prepare - check if attribute changes to a dentry are allowed + * @dentry: dentry to check * @attr: attributes to change * * Check if we are allowed to change the attributes contained in @attr - * in the given inode. This includes the normal unix access permission - * checks, as well as checks for rlimits and others. + * in the given dentry. This includes the normal unix access permission + * checks, as well as checks for rlimits and others. The function also clears + * SGID bit from mode if user is not allowed to set it. Also file capabilities + * and IMA extended attributes are cleared if ATTR_KILL_PRIV is set. * * Should be called as the first thing in ->setattr implementations, * possibly after taking additional locks. */ -int inode_change_ok(const struct inode *inode, struct iattr *attr) +int setattr_prepare(struct dentry *dentry, struct iattr *attr) { + struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; /* @@ -76,7 +79,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) return 0; } -EXPORT_SYMBOL(inode_change_ok); +EXPORT_SYMBOL(setattr_prepare); /** * inode_newsize_ok - may this inode be truncated to a given size diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9a7efbec8c63..d84977d16b02 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3533,7 +3533,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) if (btrfs_root_readonly(root)) return -EROFS; - err = inode_change_ok(inode, attr); + err = setattr_prepare(dentry, attr); if (err) return err; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8e889b773d24..6a6c2e3f99ad 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1541,7 +1541,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) __ceph_do_pending_vmtruncate(inode); - err = inode_change_ok(inode, attr); + err = setattr_prepare(dentry, attr); if (err != 0) return err; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1dc0af7f34c0..91f66c518a54 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1948,7 +1948,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) attrs->ia_valid |= ATTR_FORCE; - rc = inode_change_ok(inode, attrs); + rc = setattr_prepare(direntry, attrs); if (rc < 0) goto out; @@ -2089,7 +2089,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) attrs->ia_valid |= ATTR_FORCE; - rc = inode_change_ok(inode, attrs); + rc = setattr_prepare(direntry, attrs); if (rc < 0) { FreeXid(xid); return rc; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 782569be0bb4..03935798a45e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -1026,7 +1026,7 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) } mutex_unlock(&crypt_stat->cs_mutex); - rc = inode_change_ok(inode, ia); + rc = setattr_prepare(dentry, ia); if (rc) goto out; if (ia->ia_valid & ATTR_SIZE) { diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index f6dbf7768ce6..b43884261c48 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1018,7 +1018,7 @@ int exofs_setattr(struct dentry *dentry, struct iattr *iattr) if (unlikely(error)) return error; - error = inode_change_ok(inode, iattr); + error = setattr_prepare(dentry, iattr); if (unlikely(error)) return error; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 5a45b8fef4e6..0d0f1a63b691 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1530,7 +1530,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, iattr); + error = setattr_prepare(dentry, iattr); if (error) return error; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 71b263fbca32..d12f961b8ae5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3271,7 +3271,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr) int error, rc = 0; const unsigned int ia_valid = attr->ia_valid; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2b534b539ddc..ff2e369de040 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4291,7 +4291,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) int orphan = 0; const unsigned int ia_valid = attr->ia_valid; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/fat/file.c b/fs/fat/file.c index c118acf16e43..ef4753ee220d 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -382,7 +382,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) attr->ia_valid &= ~TIMES_SET_FLAGS; } - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); attr->ia_valid = ia_valid; if (error) { if (sbi->options.quiet) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e13558ca4b09..15c1d2948f4a 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1298,7 +1298,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) attr->ia_valid |= ATTR_FORCE; - err = inode_change_ok(inode, attr); + err = setattr_prepare(entry, attr); if (err) return err; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index cfd4959b218c..d4f83804b008 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1646,7 +1646,7 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) goto out; diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index a1a9fdcd2a00..532d6cb2dca8 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -588,7 +588,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) struct hfs_sb_info *hsb = HFS_SB(inode->i_sb); int error; - error = inode_change_ok(inode, attr); /* basic permission checks */ + error = setattr_prepare(dentry, attr); /* basic permission checks */ if (error) return error; diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 40e1413be4cf..63a252428370 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -292,7 +292,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 066b478459dc..3f3b1bd7d751 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -792,7 +792,7 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) int fd = HOSTFS_I(inode)->fd; - err = inode_change_ok(inode, attr); + err = setattr_prepare(dentry, attr); if (err) return err; diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 3b2cec29972b..00fc9434501a 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -268,7 +268,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) goto out_unlock; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) goto out_unlock; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index ebab116b0779..55573322d1bb 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -422,7 +422,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr) BUG_ON(!inode); - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 4b8afe39a87f..73652b2093b4 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -186,7 +186,7 @@ int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) { int rc; - rc = inode_change_ok(dentry->d_inode, iattr); + rc = setattr_prepare(dentry, iattr); if (rc) return rc; diff --git a/fs/jfs/file.c b/fs/jfs/file.c index 844f9460cb11..5ab3a0c214b5 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c @@ -102,7 +102,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr) struct inode *inode = dentry->d_inode; int rc; - rc = inode_change_ok(inode, iattr); + rc = setattr_prepare(dentry, iattr); if (rc) return rc; diff --git a/fs/libfs.c b/fs/libfs.c index ce85edf8aca5..d2f43c9068d2 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -364,7 +364,7 @@ int simple_setattr(struct dentry *dentry, struct iattr *iattr) WARN_ON_ONCE(inode->i_op->truncate); - error = inode_change_ok(inode, iattr); + error = setattr_prepare(dentry, iattr); if (error) return error; diff --git a/fs/logfs/file.c b/fs/logfs/file.c index b548c87a86f1..562bbc62bec2 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -241,7 +241,7 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int err = 0; - err = inode_change_ok(inode, attr); + err = setattr_prepare(dentry, attr); if (err) return err; diff --git a/fs/minix/file.c b/fs/minix/file.c index 4493ce695ab8..d23e13cbfb0c 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c @@ -28,7 +28,7 @@ static int minix_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index cbd1a61c110a..dce88e9399a4 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -880,7 +880,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) /* ageing the dentry to force validation */ ncp_age_dentry(server, dentry); - result = inode_change_ok(inode, attr); + result = setattr_prepare(dentry, attr); if (result < 0) goto out; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index e2e7914aff3b..855e3f80e4e1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -301,17 +301,19 @@ commit_metadata(struct svc_fh *fhp) * NFS semantics and what Linux expects. */ static void -nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) +nfsd_sanitize_attrs(struct dentry *dentry, struct iattr *iap) { + struct inode *inode = dentry->d_inode; + /* * NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which * requires ownership. * So if it looks like it might be "set both to the same time which - * is close to now", and if inode_change_ok fails, then we + * is close to now", and if setattr_prepare fails, then we * convert to "set to now" instead of "set to explicit time" * - * We only call inode_change_ok as the last test as technically + * We only call setattr_prepare as the last test as technically * it is not an interface that we should be using. */ #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) @@ -329,7 +331,7 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) if (delta < 0) delta = -delta; if (delta < MAX_TOUCH_TIME_ERROR && - inode_change_ok(inode, iap) != 0) { + setattr_prepare(dentry, iap) != 0) { /* * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. * This will cause notify_change to set these times @@ -437,7 +439,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, if (!iap->ia_valid) goto out; - nfsd_sanitize_attrs(inode, iap); + nfsd_sanitize_attrs(dentry, iap); /* * The size case is special, it changes the file in addition to the diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index b2d8a967d1d6..3a708189e7a9 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -792,7 +792,7 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) struct super_block *sb = inode->i_sb; int err; - err = inode_change_ok(inode, iattr); + err = setattr_prepare(dentry, iattr); if (err) return err; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 97e2dacbc867..c84f026c79ab 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -2890,7 +2890,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) int err; unsigned int ia_valid = attr->ia_valid; - err = inode_change_ok(vi, attr); + err = setattr_prepare(dentry, attr); if (err) goto out; /* We do not support NTFS ACLs yet. */ diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index b42076797049..d0ab0bfd1efa 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c @@ -212,7 +212,7 @@ static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; attr->ia_valid &= ~ATTR_SIZE; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index daf52d5709f5..a678e2287f52 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1127,7 +1127,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) return 0; - status = inode_change_ok(inode, attr); + status = setattr_prepare(dentry, attr); if (status) return status; diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 2c6d95257a4d..26972e74b9aa 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -345,7 +345,7 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/proc/base.c b/fs/proc/base.c index 402976ab746a..2c38a3e4fa51 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -558,7 +558,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid & ATTR_MODE) return -EPERM; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 10090d9c7ad5..d0d6bb6e62c8 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -257,7 +257,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) struct proc_dir_entry *de = PDE(inode); int error; - error = inode_change_ok(inode, iattr); + error = setattr_prepare(dentry, iattr); if (error) return error; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 0be1aa46d9d1..ec205953fd58 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -387,7 +387,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) return -EPERM; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index d5378d028589..b79c545340a7 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -164,7 +164,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) int ret = 0; /* POSIX UID/GID verification for setting inode attributes */ - ret = inode_change_ok(inode, ia); + ret = setattr_prepare(dentry, ia); if (ret) return ret; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index fcb07e5a5159..ff10dda73bb5 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -3107,7 +3107,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) int depth; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 9db61a41c1ad..6f54e62f464e 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -114,7 +114,7 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr) return -EINVAL; mutex_lock(&sysfs_mutex); - error = inode_change_ok(inode, iattr); + error = setattr_prepare(dentry, iattr); if (error) goto out; diff --git a/fs/sysv/file.c b/fs/sysv/file.c index 0a65939508e9..e48fe258479f 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c @@ -35,7 +35,7 @@ static int sysv_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 9df621795ed2..3cc9067b714e 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1260,7 +1260,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr) dbg_gen("ino %lu, mode %#x, ia_valid %#x", inode->i_ino, inode->i_mode, attr->ia_valid); - err = inode_change_ok(inode, attr); + err = setattr_prepare(dentry, attr); if (err) return err; diff --git a/fs/udf/file.c b/fs/udf/file.c index 874c9e3c0686..26f9b5206a78 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -251,7 +251,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index f04f89fbd4d9..92cde998aead 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -496,7 +496,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr) unsigned int ia_valid = attr->ia_valid; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error; diff --git a/fs/utimes.c b/fs/utimes.c index ba653f3dc1bc..cc428b21d789 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -80,7 +80,7 @@ static int utimes_common(struct path *path, struct timespec *times) newattrs.ia_valid |= ATTR_MTIME_SET; } /* - * Tell inode_change_ok(), that this is an explicit time + * Tell setattr_prepare(), that this is an explicit time * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET * were used. */ @@ -89,7 +89,7 @@ static int utimes_common(struct path *path, struct timespec *times) /* * If times is NULL (or both times are UTIME_NOW), * then we need to check permissions, because - * inode_change_ok() won't do it. + * setattr_prepare() won't do it. */ error = -EACCES; if (IS_IMMUTABLE(inode)) diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index ac702a6eab9b..f2243131a3a3 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -223,7 +223,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) } static int -xfs_set_mode(struct inode *inode, umode_t mode) +xfs_set_mode(struct dentry *dentry, struct inode *inode, umode_t mode) { int error = 0; @@ -234,7 +234,8 @@ xfs_set_mode(struct inode *inode, umode_t mode) iattr.ia_mode = mode; iattr.ia_ctime = current_fs_time(inode->i_sb); - error = -xfs_setattr_nonsize(XFS_I(inode), &iattr, XFS_ATTR_NOACL); + error = -xfs_setattr_nonsize(dentry, XFS_I(inode), &iattr, + XFS_ATTR_NOACL); } return error; @@ -290,7 +291,7 @@ xfs_inherit_acl(struct inode *inode, struct posix_acl *acl) if (error > 0) inherit = 1; - error = xfs_set_mode(inode, mode); + error = xfs_set_mode(NULL, inode, mode); if (error) goto out; @@ -394,7 +395,7 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name, return error; } - error = xfs_set_mode(inode, mode); + error = xfs_set_mode(dentry, inode, mode); if (error) goto out_release; } diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 8ae937a18da3..ba1d4779ece6 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1026,7 +1026,8 @@ xfs_file_fallocate( if (file->f_flags & O_DSYNC) attr_flags |= XFS_ATTR_SYNC; - error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); + error = -xfs_change_file_space(file->f_dentry, cmd, &bf, 0, + attr_flags); if (error) goto out_unlock; @@ -1036,7 +1037,8 @@ xfs_file_fallocate( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = new_size; - error = -xfs_setattr_size(ip, &iattr, XFS_ATTR_NOLOCK); + error = -xfs_setattr_size(file->f_dentry, &iattr, + XFS_ATTR_NOLOCK); } out_unlock: diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index eb519de68047..5a213c96d51f 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -632,7 +632,8 @@ xfs_ioc_space( if (ioflags & IO_INVIS) attr_flags |= XFS_ATTR_DMI; - error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); + error = xfs_change_file_space(filp->f_dentry, cmd, bf, filp->f_pos, + attr_flags); return -error; } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 1c01f04f46d2..a20378e34122 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -531,6 +531,7 @@ xfs_setattr_mode( int xfs_setattr_nonsize( + struct dentry *dentry, struct xfs_inode *ip, struct iattr *iattr, int flags) @@ -553,9 +554,15 @@ xfs_setattr_nonsize( if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - error = -inode_change_ok(inode, iattr); - if (error) - return XFS_ERROR(error); + /* + * dentry can be NULL only when we're called from xfs_inherit_acl(), + * in which case no permission checks are needed + */ + if (dentry) { + error = -setattr_prepare(dentry, iattr); + if (error) + return XFS_ERROR(error); + } ASSERT((mask & ATTR_SIZE) == 0); @@ -755,12 +762,13 @@ out_dqrele: */ int xfs_setattr_size( - struct xfs_inode *ip, + struct dentry *dentry, struct iattr *iattr, int flags) { + struct inode *inode = dentry->d_inode; + struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; - struct inode *inode = VFS_I(ip); int mask = iattr->ia_valid; struct xfs_trans *tp; int error; @@ -776,7 +784,7 @@ xfs_setattr_size( if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - error = -inode_change_ok(inode, iattr); + error = -setattr_prepare(dentry, iattr); if (error) return XFS_ERROR(error); @@ -802,7 +810,7 @@ xfs_setattr_size( */ xfs_iunlock(ip, lock_flags); iattr->ia_valid &= ~ATTR_SIZE; - return xfs_setattr_nonsize(ip, iattr, 0); + return xfs_setattr_nonsize(dentry, ip, iattr, 0); } /* @@ -950,8 +958,8 @@ xfs_vn_setattr( struct iattr *iattr) { if (iattr->ia_valid & ATTR_SIZE) - return -xfs_setattr_size(XFS_I(dentry->d_inode), iattr, 0); - return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0); + return -xfs_setattr_size(dentry, iattr, 0); + return -xfs_setattr_nonsize(dentry, XFS_I(dentry->d_inode), iattr, 0); } #define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index ee98d0bf0f6a..feb9e7556829 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -2234,12 +2234,13 @@ xfs_free_file_space( */ int xfs_change_file_space( - xfs_inode_t *ip, + struct dentry *dentry, int cmd, xfs_flock64_t *bf, xfs_off_t offset, int attr_flags) { + xfs_inode_t *ip = XFS_I(dentry->d_inode); xfs_mount_t *mp = ip->i_mount; int clrprealloc; int error; @@ -2329,7 +2330,7 @@ xfs_change_file_space( iattr.ia_valid = ATTR_SIZE; iattr.ia_size = startoffset; - error = xfs_setattr_size(ip, &iattr, attr_flags); + error = xfs_setattr_size(dentry, &iattr, attr_flags); if (error) return error; diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index c0f7714b98d0..938c4267d44b 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h @@ -13,8 +13,9 @@ struct xfs_inode; struct xfs_iomap; -int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap, int flags); -int xfs_setattr_size(struct xfs_inode *ip, struct iattr *vap, int flags); +int xfs_setattr_nonsize(struct dentry *dentry, struct xfs_inode *ip, + struct iattr *vap, int flags); +int xfs_setattr_size(struct dentry *dentry, struct iattr *vap, int flags); #define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ #define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */ #define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */ @@ -37,7 +38,7 @@ int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, const char *target_path, mode_t mode, struct xfs_inode **ipp); int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); -int xfs_change_file_space(struct xfs_inode *ip, int cmd, +int xfs_change_file_space(struct dentry *dentry, int cmd, xfs_flock64_t *bf, xfs_off_t offset, int attr_flags); int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name, struct xfs_inode *src_ip, struct xfs_inode *target_dp, diff --git a/include/linux/fs.h b/include/linux/fs.h index a509bee30c50..8c63ec58b015 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2615,7 +2615,7 @@ extern int buffer_migrate_page(struct address_space *, #define buffer_migrate_page NULL #endif -extern int inode_change_ok(const struct inode *, struct iattr *); +extern int setattr_prepare(struct dentry *, struct iattr *); extern int inode_newsize_ok(const struct inode *, loff_t offset); extern void setattr_copy(struct inode *inode, const struct iattr *attr); diff --git a/mm/shmem.c b/mm/shmem.c index 83efac6ddef0..0a9d8919ddfa 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -562,7 +562,7 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - error = inode_change_ok(inode, attr); + error = setattr_prepare(dentry, attr); if (error) return error;