aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/attr.c12
-rw-r--r--fs/inode.c6
-rw-r--r--fs/open.c19
-rw-r--r--fs/utimes.c2
-rw-r--r--include/linux/fs.h4
5 files changed, 31 insertions, 12 deletions
diff --git a/fs/attr.c b/fs/attr.c
index 66fa6251c..64fc5985c 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -167,7 +167,7 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
}
EXPORT_SYMBOL(setattr_copy);
-int notify_change(struct dentry * dentry, struct iattr * attr)
+int notify_change2(struct vfsmount *mnt, struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
@@ -239,7 +239,9 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
if (error)
return error;
- if (inode->i_op->setattr)
+ if (mnt && inode->i_op->setattr2)
+ error = inode->i_op->setattr2(mnt, dentry, attr);
+ else if (inode->i_op->setattr)
error = inode->i_op->setattr(dentry, attr);
else
error = simple_setattr(dentry, attr);
@@ -252,4 +254,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
return error;
}
+EXPORT_SYMBOL(notify_change2);
+
+int notify_change(struct dentry * dentry, struct iattr * attr)
+{
+ return notify_change2(NULL, dentry, attr);
+}
EXPORT_SYMBOL(notify_change);
diff --git a/fs/inode.c b/fs/inode.c
index 1d2ce8351..9cd3598d7 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1602,12 +1602,12 @@ int should_remove_suid(struct dentry *dentry)
}
EXPORT_SYMBOL(should_remove_suid);
-static int __remove_suid(struct dentry *dentry, int kill)
+static int __remove_suid(struct vfsmount *mnt, struct dentry *dentry, int kill)
{
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
- return notify_change(dentry, &newattrs);
+ return notify_change2(mnt, dentry, &newattrs);
}
int file_remove_suid(struct file *file)
@@ -1630,7 +1630,7 @@ int file_remove_suid(struct file *file)
if (killpriv)
error = security_inode_killpriv(dentry);
if (!error && killsuid)
- error = __remove_suid(dentry, killsuid);
+ error = __remove_suid(file->f_path.mnt, dentry, killsuid);
if (!error)
inode_has_no_xattr(inode);
diff --git a/fs/open.c b/fs/open.c
index cadec0ccd..3b2a9cfbf 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -34,8 +34,8 @@
#include "internal.h"
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
- struct file *filp)
+int do_truncate2(struct vfsmount *mnt, struct dentry *dentry, loff_t length,
+ unsigned int time_attrs, struct file *filp)
{
int ret;
struct iattr newattrs;
@@ -57,10 +57,15 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
newattrs.ia_valid |= ret | ATTR_FORCE;
mutex_lock(&dentry->d_inode->i_mutex);
- ret = notify_change(dentry, &newattrs);
+ ret = notify_change2(mnt, dentry, &newattrs);
mutex_unlock(&dentry->d_inode->i_mutex);
return ret;
}
+int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+ struct file *filp)
+{
+ return do_truncate2(NULL, dentry, length, time_attrs, filp);
+}
long vfs_truncate(struct path *path, loff_t length)
{
@@ -105,7 +110,7 @@ long vfs_truncate(struct path *path, loff_t length)
if (!error)
error = security_path_truncate(path);
if (!error)
- error = do_truncate(path->dentry, length, 0, NULL);
+ error = do_truncate2(mnt, path->dentry, length, 0, NULL);
put_write_and_out:
put_write_access(inode);
@@ -154,6 +159,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
{
struct inode *inode;
struct dentry *dentry;
+ struct vfsmount *mnt;
struct fd f;
int error;
@@ -170,6 +176,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
small = 0;
dentry = f.file->f_path.dentry;
+ mnt = f.file->f_path.mnt;
inode = dentry->d_inode;
error = -EINVAL;
if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
@@ -482,7 +489,7 @@ static int chmod_common(struct path *path, umode_t mode)
goto out_unlock;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- error = notify_change(path->dentry, &newattrs);
+ error = notify_change2(path->mnt, path->dentry, &newattrs);
out_unlock:
mutex_unlock(&inode->i_mutex);
mnt_drop_write(path->mnt);
@@ -556,7 +563,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
mutex_lock(&inode->i_mutex);
error = security_path_chown(path, uid, gid);
if (!error)
- error = notify_change(path->dentry, &newattrs);
+ error = notify_change2(path->mnt, path->dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
return error;
diff --git a/fs/utimes.c b/fs/utimes.c
index 67250973d..7216a079d 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -102,7 +102,7 @@ static int utimes_common(struct path *path, struct timespec *times)
}
}
mutex_lock(&inode->i_mutex);
- error = notify_change(path->dentry, &newattrs);
+ error = notify_change2(path->mnt, path->dentry, &newattrs);
mutex_unlock(&inode->i_mutex);
mnt_drop_write_and_out:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d248a4e0d..3b0a8ab85 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1583,6 +1583,7 @@ struct inode_operations {
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*setattr) (struct dentry *, struct iattr *);
+ int (*setattr2) (struct vfsmount *, struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
@@ -2028,6 +2029,8 @@ struct filename {
extern long vfs_truncate(struct path *, loff_t);
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
struct file *filp);
+extern int do_truncate2(struct vfsmount *, struct dentry *, loff_t start,
+ unsigned int time_attrs, struct file *filp);
extern int do_fallocate(struct file *file, int mode, loff_t offset,
loff_t len);
extern long do_sys_open(int dfd, const char __user *filename, int flags,
@@ -2242,6 +2245,7 @@ extern void emergency_remount(void);
extern sector_t bmap(struct inode *, sector_t);
#endif
extern int notify_change(struct dentry *, struct iattr *);
+extern int notify_change2(struct vfsmount *, struct dentry *, struct iattr *);
extern int inode_permission(struct inode *, int);
extern int generic_permission(struct inode *, int);
extern int inode_permission2(struct vfsmount *, struct inode *, int);