Skip to content

Commit

Permalink
[PATCH] r/o bind mounts: elevate write count for rmdir and unlink.
Browse files Browse the repository at this point in the history
Elevate the write count during the vfs_rmdir() and vfs_unlink().

[AV: merged rmdir and unlink parts, added missing pieces in nfsd]

Acked-by: Serge Hallyn <[email protected]>
Acked-by: Al Viro <[email protected]>
Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Dave Hansen <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
hansendc authored and Al Viro committed Apr 19, 2008
1 parent 49e0d02 commit 0622753
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
9 changes: 9 additions & 0 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,12 @@ static long do_rmdir(int dfd, const char __user *pathname)
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit2;
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit3;
error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
mnt_drop_write(nd.path.mnt);
exit3:
dput(dentry);
exit2:
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
Expand Down Expand Up @@ -2271,7 +2276,11 @@ static long do_unlinkat(int dfd, const char __user *pathname)
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit2;
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
mnt_drop_write(nd.path.mnt);
exit2:
dput(dentry);
}
Expand Down
12 changes: 11 additions & 1 deletion fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <linux/sched.h>
#include <linux/mount.h>

#define NFSDDBG_FACILITY NFSDDBG_PROC

Expand Down Expand Up @@ -313,12 +314,17 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (!rec_dir_init || !clp->cl_firststate)
return;

status = mnt_want_write(rec_dir.path.mnt);
if (status)
goto out;
clp->cl_firststate = 0;
nfs4_save_user(&uid, &gid);
status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
nfs4_reset_user(uid, gid);
if (status == 0)
nfsd4_sync_rec_dir();
mnt_drop_write(rec_dir.path.mnt);
out:
if (status)
printk("NFSD: Failed to remove expired client state directory"
" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
Expand Down Expand Up @@ -347,13 +353,17 @@ nfsd4_recdir_purge_old(void) {

if (!rec_dir_init)
return;
status = mnt_want_write(rec_dir.path.mnt);
if (status)
goto out;
status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old);
if (status == 0)
nfsd4_sync_rec_dir();
mnt_drop_write(rec_dir.path.mnt);
out:
if (status)
printk("nfsd4: failed to purge old clients from recovery"
" directory %s\n", rec_dir.path.dentry->d_name.name);
return;
}

static int
Expand Down
8 changes: 7 additions & 1 deletion fs/nfsd/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if (!type)
type = rdentry->d_inode->i_mode & S_IFMT;

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

if (type != S_IFDIR) { /* It's UNLINK */
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
Expand All @@ -1765,10 +1769,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dput(rdentry);

if (host_err)
goto out_nfserr;
goto out_drop;
if (EX_ISSYNC(fhp->fh_export))
host_err = nfsd_sync_dir(dentry);

out_drop:
mnt_drop_write(fhp->fh_export->ex_path.mnt);
out_nfserr:
err = nfserrno(host_err);
out:
Expand Down
5 changes: 4 additions & 1 deletion ipc/mqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,11 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);

err = mnt_want_write(mqueue_mnt);
if (err)
goto out_err;
err = vfs_unlink(dentry->d_parent->d_inode, dentry);
mnt_drop_write(mqueue_mnt);
out_err:
dput(dentry);

Expand Down

0 comments on commit 0622753

Please sign in to comment.