[RFC] Add "reason" parameter to mnt_want_write().

From: Tetsuo Handa
Date: Sat Dec 06 2008 - 00:25:38 EST


We want to allow LSM modules to perform MAC which takes an absolute pathname of
a requested file into account. Since we can't pass "struct vfsmount" to VFS
helper functions, we are trying to somehow pass "struct vfsmount"'s pathnames
instead of "struct vfsmount" itself.

The mnt_want_write() and mnt_drop_write() hooks are inserted around VFS helper
functions call. Thus, I think we can insert security_path_set() into
mnt_want_write() and secuity_path_clear() into mnt_drop_write() rather than
scattering security_path_set() and security_path_clear() all around the places.

But, mnt_want_write() and mnt_drop_write() are used for not only VFS helper
functions call but also various places. Thus, honestly calculating vfsmount's
pathnames for touch_atime()/file_update_time() operations triggers measurable
performance regression.

We want to skip calculating vfsmount's pathnames when the mnt_want_write()
call is not interested for the LSM modules.
This patch adds "reason" parameter to mnt_want_write() so that LSM modules can
calculate vfsmount's pathnames only when needed. The "reason" parameter is one
of constants listed below.

/* For subsequent VFS helper functions call. */
MNT_WANT_FOR_VFS_REQUEST, /* vfs_create()/vfs_mkdir() etc. */
/* For implicit write of inode's timestamps. */
MNT_WANT_FOR_UPDATE_ACMTIME, /* touch_atime()/file_update_time() */
/* For explicit write of inode's attributes and timestamps. */
MNT_WANT_FOR_UPDATE_ATTR, /* chmod()/chown()/utimes() etc. */
/* For filesystem's ioctl. */
MNT_WANT_FOR_FS_IOCTL, /* ext3_ioctl() etc. */
/* For opening a file for writing. */
MNT_WANT_FOR_OPEN_WRITE, /* __get_file_write_access() */
/* Needs to be granted since the caller doesn't check errors. */
MNT_WANT_ANYWAY /* init_file() */

Please review.

Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx>
---
fs/ext2/ioctl.c | 6 +++---
fs/ext3/ioctl.c | 10 +++++-----
fs/ext4/ioctl.c | 10 +++++-----
fs/fat/file.c | 2 +-
fs/file_table.c | 2 +-
fs/gfs2/ops_file.c | 2 +-
fs/hfsplus/ioctl.c | 2 +-
fs/inode.c | 4 ++--
fs/jfs/ioctl.c | 2 +-
fs/namei.c | 18 +++++++++---------
fs/namespace.c | 15 ++++++++++++++-
fs/ncpfs/ioctl.c | 2 +-
fs/nfsd/nfs4proc.c | 3 ++-
fs/nfsd/nfs4recover.c | 6 +++---
fs/nfsd/nfs4state.c | 3 ++-
fs/nfsd/vfs.c | 21 ++++++++++++++-------
fs/ocfs2/ioctl.c | 3 ++-
fs/open.c | 16 ++++++++--------
fs/reiserfs/ioctl.c | 5 +++--
fs/ubifs/ioctl.c | 2 +-
fs/utimes.c | 2 +-
fs/xattr.c | 12 ++++++------
fs/xfs/linux-2.6/xfs_ioctl.c | 6 ++++--
fs/xfs/linux-2.6/xfs_lrw.c | 3 ++-
include/linux/mount.h | 17 ++++++++++++++++-
ipc/mqueue.c | 4 ++--
net/unix/af_unix.c | 2 +-
27 files changed, 111 insertions(+), 69 deletions(-)

--- linux-2.6.28-rc7-mm1.orig/fs/ext2/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ext2/ioctl.c
@@ -36,7 +36,7 @@ long ext2_ioctl(struct file *filp, unsig
case EXT2_IOC_SETFLAGS: {
unsigned int oldflags;

- ret = mnt_want_write(filp->f_path.mnt);
+ ret = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (ret)
return ret;

@@ -93,7 +93,7 @@ setflags_out:
case EXT2_IOC_SETVERSION:
if (!is_owner_or_cap(inode))
return -EPERM;
- ret = mnt_want_write(filp->f_path.mnt);
+ ret = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (ret)
return ret;
if (get_user(inode->i_generation, (int __user *) arg)) {
@@ -123,7 +123,7 @@ setflags_out:
if (get_user(rsv_window_size, (int __user *)arg))
return -EFAULT;

- ret = mnt_want_write(filp->f_path.mnt);
+ ret = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (ret)
return ret;

--- linux-2.6.28-rc7-mm1.orig/fs/ext3/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ext3/ioctl.c
@@ -39,7 +39,7 @@ int ext3_ioctl (struct inode * inode, st
unsigned int oldflags;
unsigned int jflag;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -141,7 +141,7 @@ flags_out:

if (!is_owner_or_cap(inode))
return -EPERM;
- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;
if (get_user(generation, (int __user *) arg)) {
@@ -202,7 +202,7 @@ setversion_out:
if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
return -ENOTTY;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -244,7 +244,7 @@ setrsvsz_out:
if (!capable(CAP_SYS_RESOURCE))
return -EPERM;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -270,7 +270,7 @@ group_extend_out:
if (!capable(CAP_SYS_RESOURCE))
return -EPERM;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

--- linux-2.6.28-rc7-mm1.orig/fs/ext4/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ext4/ioctl.c
@@ -44,7 +44,7 @@ long ext4_ioctl(struct file *filp, unsig
if (get_user(flags, (int __user *) arg))
return -EFAULT;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -141,7 +141,7 @@ flags_out:
if (!is_owner_or_cap(inode))
return -EPERM;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;
if (get_user(generation, (int __user *) arg)) {
@@ -200,7 +200,7 @@ setversion_out:
if (get_user(n_blocks_count, (__u32 __user *)arg))
return -EFAULT;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -226,7 +226,7 @@ setversion_out:
sizeof(input)))
return -EFAULT;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -247,7 +247,7 @@ setversion_out:
if (!is_owner_or_cap(inode))
return -EACCES;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;
/*
--- linux-2.6.28-rc7-mm1.orig/fs/fat/file.c
+++ linux-2.6.28-rc7-mm1/fs/fat/file.c
@@ -47,7 +47,7 @@ int fat_generic_ioctl(struct inode *inod

mutex_lock(&inode->i_mutex);

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
goto up_no_drop_write;

--- linux-2.6.28-rc7-mm1.orig/fs/file_table.c
+++ linux-2.6.28-rc7-mm1/fs/file_table.c
@@ -210,7 +210,7 @@ int init_file(struct file *file, struct
*/
if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
file_take_write(file);
- error = mnt_want_write(mnt);
+ error = mnt_want_write(mnt, MNT_WANT_ANYWAY);
WARN_ON(error);
}
return error;
--- linux-2.6.28-rc7-mm1.orig/fs/gfs2/ops_file.c
+++ linux-2.6.28-rc7-mm1/fs/gfs2/ops_file.c
@@ -211,7 +211,7 @@ static int do_gfs2_set_flags(struct file
int error;
u32 new_flags, flags;

- error = mnt_want_write(filp->f_path.mnt);
+ error = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (error)
return error;

--- linux-2.6.28-rc7-mm1.orig/fs/hfsplus/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/hfsplus/ioctl.c
@@ -37,7 +37,7 @@ int hfsplus_ioctl(struct inode *inode, s
return put_user(flags, (int __user *)arg);
case HFSPLUS_IOC_EXT2_SETFLAGS: {
int err = 0;
- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

--- linux-2.6.28-rc7-mm1.orig/fs/inode.c
+++ linux-2.6.28-rc7-mm1/fs/inode.c
@@ -1235,7 +1235,7 @@ void touch_atime(struct vfsmount *mnt, s
struct inode *inode = dentry->d_inode;
struct timespec now;

- if (mnt_want_write(mnt))
+ if (mnt_want_write(mnt, MNT_WANT_FOR_UPDATE_ACMTIME))
return;
if (inode->i_flags & S_NOATIME)
goto out;
@@ -1291,7 +1291,7 @@ void file_update_time(struct file *file)
if (IS_NOCMTIME(inode))
return;

- err = mnt_want_write(file->f_path.mnt);
+ err = mnt_want_write(file->f_path.mnt, MNT_WANT_FOR_UPDATE_ACMTIME);
if (err)
return;

--- linux-2.6.28-rc7-mm1.orig/fs/jfs/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/jfs/ioctl.c
@@ -68,7 +68,7 @@ long jfs_ioctl(struct file *filp, unsign
unsigned int oldflags;
int err;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

--- linux-2.6.28-rc7-mm1.orig/fs/namei.c
+++ linux-2.6.28-rc7-mm1/fs/namei.c
@@ -1723,7 +1723,7 @@ do_last:
* a permanent write count is taken through
* the 'struct file' in nameidata_to_filp().
*/
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto exit_mutex_unlock;
error = __open_namei_create(&nd, &path, flag, mode);
@@ -1775,7 +1775,7 @@ ok:
*/
will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
if (will_write) {
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto exit;
}
@@ -1996,7 +1996,7 @@ asmlinkage long sys_mknodat(int dfd, con
error = may_mknod(mode);
if (error)
goto out_dput;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto out_dput;
switch (mode & S_IFMT) {
@@ -2067,7 +2067,7 @@ asmlinkage long sys_mkdirat(int dfd, con

if (!IS_POSIXACL(nd.path.dentry->d_inode))
mode &= ~current->fs->umask;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto out_dput;
error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
@@ -2177,7 +2177,7 @@ static long do_rmdir(int dfd, const char
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit2;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto exit3;
error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
@@ -2262,7 +2262,7 @@ static long do_unlinkat(int dfd, const c
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto exit2;
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
@@ -2343,7 +2343,7 @@ asmlinkage long sys_symlinkat(const char
if (IS_ERR(dentry))
goto out_unlock;

- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto out_dput;
error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
@@ -2440,7 +2440,7 @@ asmlinkage long sys_linkat(int olddfd, c
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto out_unlock;
- error = mnt_want_write(nd.path.mnt);
+ error = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto out_dput;
error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
@@ -2674,7 +2674,7 @@ asmlinkage long sys_renameat(int olddfd,
if (new_dentry == trap)
goto exit5;

- error = mnt_want_write(oldnd.path.mnt);
+ error = mnt_want_write(oldnd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto exit5;
error = vfs_rename(old_dir->d_inode, old_dentry,
--- linux-2.6.28-rc7-mm1.orig/fs/namespace.c
+++ linux-2.6.28-rc7-mm1/fs/namespace.c
@@ -242,6 +242,7 @@ static inline void use_cpu_writer_for_mo
/**
* mnt_want_write - get write access to a mount
* @mnt: the mount on which to take a write
+ * @reason: reason for this call
*
* This tells the low-level filesystem that a write is
* about to be performed to it, and makes sure that
@@ -249,11 +250,16 @@ static inline void use_cpu_writer_for_mo
* the write operation is finished, mnt_drop_write()
* must be called. This is effectively a refcount.
*/
-int mnt_want_write(struct vfsmount *mnt)
+int mnt_want_write(struct vfsmount *mnt, const int reason)
{
int ret = 0;
struct mnt_writer *cpu_writer;

+ /*
+ ret = security_path_set(mnt, reason);
+ if (ret)
+ return ret;
+ */
cpu_writer = &get_cpu_var(mnt_writers);
spin_lock(&cpu_writer->lock);
if (__mnt_is_readonly(mnt)) {
@@ -265,6 +271,10 @@ int mnt_want_write(struct vfsmount *mnt)
out:
spin_unlock(&cpu_writer->lock);
put_cpu_var(mnt_writers);
+ /*
+ if (ret)
+ security_path_clear();
+ */
return ret;
}
EXPORT_SYMBOL_GPL(mnt_want_write);
@@ -362,6 +372,9 @@ void mnt_drop_write(struct vfsmount *mnt
* we could theoretically wrap __mnt_writers.
*/
put_cpu_var(mnt_writers);
+ /*
+ security_path_clear();
+ */
}
EXPORT_SYMBOL_GPL(mnt_drop_write);

--- linux-2.6.28-rc7-mm1.orig/fs/ncpfs/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ncpfs/ioctl.c
@@ -861,7 +861,7 @@ int ncp_ioctl(struct inode *inode, struc
* -EACCESS, so it seems consistent to keep
* that here.
*/
- if (mnt_want_write(filp->f_path.mnt))
+ if (mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL))
return -EACCES;
}
ret = __ncp_ioctl(inode, filp, cmd, arg);
--- linux-2.6.28-rc7-mm1.orig/fs/nfsd/nfs4proc.c
+++ linux-2.6.28-rc7-mm1/fs/nfsd/nfs4proc.c
@@ -661,7 +661,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
return status;
}
}
- status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
+ status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (status)
return status;
status = nfs_ok;
--- linux-2.6.28-rc7-mm1.orig/fs/nfsd/nfs4recover.c
+++ linux-2.6.28-rc7-mm1/fs/nfsd/nfs4recover.c
@@ -162,7 +162,7 @@ nfsd4_create_clid_dir(struct nfs4_client
dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
goto out_put;
}
- status = mnt_want_write(rec_dir.mnt);
+ status = mnt_want_write(rec_dir.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (status)
goto out_put;
status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
@@ -326,7 +326,7 @@ nfsd4_remove_clid_dir(struct nfs4_client
if (!rec_dir_init || !clp->cl_firststate)
return;

- status = mnt_want_write(rec_dir.mnt);
+ status = mnt_want_write(rec_dir.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (status)
goto out;
clp->cl_firststate = 0;
@@ -369,7 +369,7 @@ nfsd4_recdir_purge_old(void) {

if (!rec_dir_init)
return;
- status = mnt_want_write(rec_dir.mnt);
+ status = mnt_want_write(rec_dir.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (status)
goto out;
status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
--- linux-2.6.28-rc7-mm1.orig/fs/nfsd/nfs4state.c
+++ linux-2.6.28-rc7-mm1/fs/nfsd/nfs4state.c
@@ -1587,7 +1587,8 @@ nfs4_upgrade_open(struct svc_rqst *rqstp
int err = get_write_access(inode);
if (err)
return nfserrno(err);
- err = mnt_want_write(cur_fh->fh_export->ex_path.mnt);
+ err = mnt_want_write(cur_fh->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (err)
return nfserrno(err);
file_take_write(filp);
--- linux-2.6.28-rc7-mm1.orig/fs/nfsd/vfs.c
+++ linux-2.6.28-rc7-mm1/fs/nfsd/vfs.c
@@ -1261,7 +1261,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
goto out;
}

- host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err)
goto out_nfserr;

@@ -1374,7 +1375,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
v_atime = verifier[1]&0x7fffffff;
}

- host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err)
goto out_nfserr;
if (dchild->d_inode) {
@@ -1538,7 +1540,8 @@ nfsd_symlink(struct svc_rqst *rqstp, str
if (IS_ERR(dnew))
goto out_nfserr;

- host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err)
goto out_nfserr;

@@ -1614,7 +1617,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
dold = tfhp->fh_dentry;
dest = dold->d_inode;

- host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err) {
err = nfserrno(host_err);
goto out_dput;
@@ -1716,7 +1720,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
host_err = -EXDEV;
if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
goto out_dput_new;
- host_err = mnt_want_write(ffhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(ffhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err)
goto out_dput_new;

@@ -1787,7 +1792,8 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
if (!type)
type = rdentry->d_inode->i_mode & S_IFMT;

- host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
+ host_err = mnt_want_write(fhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (host_err)
goto out_nfserr;

@@ -2188,7 +2194,8 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
} else
size = 0;

- error = mnt_want_write(fhp->fh_export->ex_path.mnt);
+ error = mnt_want_write(fhp->fh_export->ex_path.mnt,
+ MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto getout;
if (size)
--- linux-2.6.28-rc7-mm1.orig/fs/ocfs2/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ocfs2/ioctl.c
@@ -129,7 +129,8 @@ long ocfs2_ioctl(struct file *filp, unsi
if (get_user(flags, (int __user *) arg))
return -EFAULT;

- status = mnt_want_write(filp->f_path.mnt);
+ status = mnt_want_write(filp->f_path.mnt,
+ MNT_WANT_FOR_FS_IOCTL);
if (status)
return status;
status = ocfs2_set_inode_attr(inode, flags,
--- linux-2.6.28-rc7-mm1.orig/fs/open.c
+++ linux-2.6.28-rc7-mm1/fs/open.c
@@ -247,7 +247,7 @@ static long do_sys_truncate(const char _
if (!S_ISREG(inode->i_mode))
goto dput_and_out;

- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (error)
goto dput_and_out;

@@ -587,7 +587,7 @@ asmlinkage long sys_fchmod(unsigned int

audit_inode(NULL, dentry);

- err = mnt_want_write(file->f_path.mnt);
+ err = mnt_want_write(file->f_path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (err)
goto out_putf;
mutex_lock(&inode->i_mutex);
@@ -617,7 +617,7 @@ asmlinkage long sys_fchmodat(int dfd, co
goto out;
inode = path.dentry->d_inode;

- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto dput_and_out;
mutex_lock(&inode->i_mutex);
@@ -672,7 +672,7 @@ asmlinkage long sys_chown(const char __u
error = user_path(filename, &path);
if (error)
goto out;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
@@ -697,7 +697,7 @@ asmlinkage long sys_fchownat(int dfd, co
error = user_path_at(dfd, filename, follow, &path);
if (error)
goto out;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
@@ -716,7 +716,7 @@ asmlinkage long sys_lchown(const char __
error = user_lpath(filename, &path);
if (error)
goto out;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto out_release;
error = chown_common(path.dentry, user, group);
@@ -738,7 +738,7 @@ asmlinkage long sys_fchown(unsigned int
if (!file)
goto out;

- error = mnt_want_write(file->f_path.mnt);
+ error = mnt_want_write(file->f_path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto out_fput;
dentry = file->f_path.dentry;
@@ -773,7 +773,7 @@ static inline int __get_file_write_acces
/*
* Balanced in __fput()
*/
- error = mnt_want_write(mnt);
+ error = mnt_want_write(mnt, MNT_WANT_FOR_OPEN_WRITE);
if (error)
put_write_access(inode);
}
--- linux-2.6.28-rc7-mm1.orig/fs/reiserfs/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/reiserfs/ioctl.c
@@ -48,7 +48,8 @@ int reiserfs_ioctl(struct inode *inode,
if (!reiserfs_attrs(inode->i_sb))
return -ENOTTY;

- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt,
+ MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;

@@ -97,7 +98,7 @@ setflags_out:
case REISERFS_IOC_SETVERSION:
if (!is_owner_or_cap(inode))
return -EPERM;
- err = mnt_want_write(filp->f_path.mnt);
+ err = mnt_want_write(filp->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;
if (get_user(inode->i_generation, (int __user *)arg)) {
--- linux-2.6.28-rc7-mm1.orig/fs/ubifs/ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/ubifs/ioctl.c
@@ -173,7 +173,7 @@ long ubifs_ioctl(struct file *file, unsi
* Make sure the file-system is read-write and make sure it
* will not become read-only while we are changing the flags.
*/
- err = mnt_want_write(file->f_path.mnt);
+ err = mnt_want_write(file->f_path.mnt, MNT_WANT_FOR_FS_IOCTL);
if (err)
return err;
err = setflags(inode, flags);
--- linux-2.6.28-rc7-mm1.orig/fs/utimes.c
+++ linux-2.6.28-rc7-mm1/fs/utimes.c
@@ -54,7 +54,7 @@ static int utimes_common(struct path *pa
struct iattr newattrs;
struct inode *inode = path->dentry->d_inode;

- error = mnt_want_write(path->mnt);
+ error = mnt_want_write(path->mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (error)
goto out;

--- linux-2.6.28-rc7-mm1.orig/fs/xattr.c
+++ linux-2.6.28-rc7-mm1/fs/xattr.c
@@ -261,7 +261,7 @@ sys_setxattr(const char __user *pathname
error = user_path(pathname, &path);
if (error)
return error;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = setxattr(path.dentry, name, value, size, flags);
mnt_drop_write(path.mnt);
@@ -280,7 +280,7 @@ sys_lsetxattr(const char __user *pathnam
error = user_lpath(pathname, &path);
if (error)
return error;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = setxattr(path.dentry, name, value, size, flags);
mnt_drop_write(path.mnt);
@@ -302,7 +302,7 @@ sys_fsetxattr(int fd, const char __user
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write(f->f_path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = setxattr(dentry, name, value, size, flags);
mnt_drop_write(f->f_path.mnt);
@@ -494,7 +494,7 @@ sys_removexattr(const char __user *pathn
error = user_path(pathname, &path);
if (error)
return error;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = removexattr(path.dentry, name);
mnt_drop_write(path.mnt);
@@ -512,7 +512,7 @@ sys_lremovexattr(const char __user *path
error = user_lpath(pathname, &path);
if (error)
return error;
- error = mnt_want_write(path.mnt);
+ error = mnt_want_write(path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = removexattr(path.dentry, name);
mnt_drop_write(path.mnt);
@@ -533,7 +533,7 @@ sys_fremovexattr(int fd, const char __us
return error;
dentry = f->f_path.dentry;
audit_inode(NULL, dentry);
- error = mnt_want_write(f->f_path.mnt);
+ error = mnt_want_write(f->f_path.mnt, MNT_WANT_FOR_UPDATE_ATTR);
if (!error) {
error = removexattr(dentry, name);
mnt_drop_write(f->f_path.mnt);
--- linux-2.6.28-rc7-mm1.orig/fs/xfs/linux-2.6/xfs_ioctl.c
+++ linux-2.6.28-rc7-mm1/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -629,7 +629,8 @@ xfs_attrmulti_by_handle(
&ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_SET:
- ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
+ ops[i].am_error = mnt_want_write(parfilp->f_path.mnt,
+ MNT_WANT_FOR_FS_IOCTL);
if (ops[i].am_error)
break;
ops[i].am_error = xfs_attrmulti_attr_set(inode,
@@ -638,7 +639,8 @@ xfs_attrmulti_by_handle(
mnt_drop_write(parfilp->f_path.mnt);
break;
case ATTR_OP_REMOVE:
- ops[i].am_error = mnt_want_write(parfilp->f_path.mnt);
+ ops[i].am_error = mnt_want_write(parfilp->f_path.mnt,
+ MNT_WANT_FOR_FS_IOCTL);
if (ops[i].am_error)
break;
ops[i].am_error = xfs_attrmulti_attr_remove(inode,
--- linux-2.6.28-rc7-mm1.orig/fs/xfs/linux-2.6/xfs_lrw.c
+++ linux-2.6.28-rc7-mm1/fs/xfs/linux-2.6/xfs_lrw.c
@@ -673,7 +673,8 @@ start:
* filesystems. Throw it away if anyone asks us.
*/
if (likely(!(ioflags & IO_INVIS) &&
- !mnt_want_write(file->f_path.mnt))) {
+ !mnt_want_write(file->f_path.mnt,
+ MNT_WANT_FOR_UPDATE_ACMTIME))) {
xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
mnt_drop_write(file->f_path.mnt);
}
--- linux-2.6.28-rc7-mm1.orig/include/linux/mount.h
+++ linux-2.6.28-rc7-mm1/include/linux/mount.h
@@ -78,7 +78,22 @@ static inline struct vfsmount *mntget(st
return mnt;
}

-extern int mnt_want_write(struct vfsmount *mnt);
+enum mnt_want_reasons {
+ /* For subsequent VFS helper functions call. */
+ MNT_WANT_FOR_VFS_REQUEST, /* vfs_create()/vfs_mkdir() etc. */
+ /* For implicit write of inode's timestamps. */
+ MNT_WANT_FOR_UPDATE_ACMTIME, /* touch_atime()/file_update_time() */
+ /* For explicit write of inode's attributes and timestamps. */
+ MNT_WANT_FOR_UPDATE_ATTR, /* chmod()/chown()/utimes() etc. */
+ /* For filesystem's ioctl. */
+ MNT_WANT_FOR_FS_IOCTL, /* ext3_ioctl() etc. */
+ /* For opening a file for writing. */
+ MNT_WANT_FOR_OPEN_WRITE, /* __get_file_write_access() */
+ /* Needs to be granted since the caller doesn't check errors. */
+ MNT_WANT_ANYWAY /* init_file() */
+};
+
+extern int mnt_want_write(struct vfsmount *mnt, const int reason);
extern void mnt_drop_write(struct vfsmount *mnt);
extern void mntput_no_expire(struct vfsmount *mnt);
extern void mnt_pin(struct vfsmount *mnt);
--- linux-2.6.28-rc7-mm1.orig/ipc/mqueue.c
+++ linux-2.6.28-rc7-mm1/ipc/mqueue.c
@@ -611,7 +611,7 @@ static struct file *do_create(struct den
}

mode &= ~current->fs->umask;
- ret = mnt_want_write(mqueue_mnt);
+ ret = mnt_want_write(mqueue_mnt, MNT_WANT_FOR_VFS_REQUEST);
if (ret)
goto out;
ret = vfs_create(dir->d_inode, dentry, mode, NULL);
@@ -753,7 +753,7 @@ asmlinkage long sys_mq_unlink(const char
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
- err = mnt_want_write(mqueue_mnt);
+ err = mnt_want_write(mqueue_mnt, MNT_WANT_FOR_VFS_REQUEST);
if (err)
goto out_err;
err = vfs_unlink(dentry->d_parent->d_inode, dentry);
--- linux-2.6.28-rc7-mm1.orig/net/unix/af_unix.c
+++ linux-2.6.28-rc7-mm1/net/unix/af_unix.c
@@ -833,7 +833,7 @@ static int unix_bind(struct socket *sock
*/
mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current->fs->umask);
- err = mnt_want_write(nd.path.mnt);
+ err = mnt_want_write(nd.path.mnt, MNT_WANT_FOR_VFS_REQUEST);
if (err)
goto out_mknod_dput;
err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/