summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8b398112d..72d67a13a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -14,6 +14,7 @@
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/
+#include <linux/config.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/errno.h>
@@ -39,6 +40,7 @@
#endif
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
+#define NFSD_PARANOIA
/* Open mode for nfsd_open */
#define OPEN_READ 0
@@ -168,13 +170,19 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
if (IS_ERR(dchild))
goto out_nfserr;
/*
- * Make sure we haven't crossed a mount point ...
+ * check if we have crossed a mount point ...
*/
if (dchild->d_sb != dparent->d_sb) {
-#ifdef NFSD_PARANOIA
-printk("nfsd_lookup: %s/%s crossed mount point!\n", dparent->d_name.name, name);
-#endif
- goto out_dput;
+ struct dentry *tdentry;
+ tdentry = dchild->d_covers;
+ if (tdentry == dchild)
+ goto out_dput;
+ dput(dchild);
+ dchild = dget(tdentry);
+ if (dchild->d_sb != dparent->d_sb) {
+printk("nfsd_lookup: %s/%s crossed mount point!\n", dparent->d_name.name, dchild->d_name.name);
+ goto out_dput;
+ }
}
/*
@@ -416,8 +424,8 @@ found:
* N.B. After this call fhp needs an fh_put
*/
int
-nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, char *buf,
- unsigned long *count)
+nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
+ char *buf, unsigned long *count)
{
struct raparms *ra;
mm_segment_t oldfs;
@@ -547,13 +555,10 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (EX_WGATHER(exp) && (inode->i_writecount > 1
|| (last_ino == inode->i_ino && last_dev == inode->i_dev))) {
#if 0
- current->timeout = jiffies + 10 * HZ / 1000;
- interruptible_sleep_on(&inode->i_wait);
+ interruptible_sleep_on_timeout(&inode->i_wait, 10 * HZ / 1000);
#else
dprintk("nfsd: write defer %d\n", current->pid);
- current->need_resched = 1;
- current->timeout = jiffies + HZ / 100;
- schedule();
+ schedule_timeout((HZ+99)/100);
dprintk("nfsd: write resume %d\n", current->pid);
#endif
}
@@ -1067,6 +1072,11 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if (IS_ERR(rdentry))
goto out_nfserr;
+ /*
+ * FIXME!!
+ *
+ * This should do a double-lock on both rdentry and the parent
+ */
err = fh_lock_parent(fhp, rdentry);
if (err)
goto out;
@@ -1240,6 +1250,12 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
*/
+#ifndef CONFIG_NFSD_SUN
+ if (dentry->d_mounts != dentry) {
+ return nfserr_perm;
+ }
+#endif
+
if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
if (EX_RDONLY(exp) || IS_RDONLY(inode))
return nfserr_rofs;