patch-2.1.65 linux/fs/nfsd/vfs.c
Next file: linux/fs/select.c
Previous file: linux/fs/nfsd/nfsxdr.c
Back to the patch index
Back to the overall index
- Lines: 358
- Date:
Mon Nov 17 15:14:48 1997
- Orig file:
v2.1.64/linux/fs/nfsd/vfs.c
- Orig date:
Sat Oct 25 02:44:18 1997
diff -u --recursive --new-file v2.1.64/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -36,6 +36,8 @@
#include <asm/uaccess.h>
#endif
+extern void fh_update(struct svc_fh*);
+
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
/* Open mode for nfsd_open */
@@ -108,10 +110,11 @@
dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name);
/* Obtain dentry and export. */
- if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_NOP)) != 0)
- return err;
+ err = fh_verify(rqstp, fhp, S_IFDIR, MAY_NOP);
+ if (err)
+ goto out;
- dparent = fhp->fh_handle.fh_dentry;
+ dparent = fhp->fh_dentry;
exp = fhp->fh_export;
/* Fast path... */
@@ -121,11 +124,16 @@
!nfsd_iscovered(dparent, exp)) {
struct dentry *dchild;
- dchild = lookup_dentry(name, dget(dparent), 1);
+ /* Lookup the name, but don't follow links */
+ dchild = lookup_dentry(name, dget(dparent), 0);
err = PTR_ERR(dchild);
if (IS_ERR(dchild))
return nfserrno(-err);
+ /*
+ * Note: we compose the filehandle now, but as the
+ * dentry may be negative, it may need to be updated.
+ */
fh_compose(resfh, exp, dchild);
return (dchild->d_inode ? 0 : nfserr_noent);
}
@@ -135,6 +143,7 @@
return nfserr_noent;
if (nfsd_iscovered(dparent, exp))
return nfserr_acces;
+out:
return err;
}
@@ -158,10 +167,11 @@
ftype = S_IFREG;
/* Get inode */
- if ((err = fh_verify(rqstp, fhp, ftype, accmode)) != 0)
- return err;
+ err = fh_verify(rqstp, fhp, ftype, accmode);
+ if (err)
+ goto out;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
inode = dentry->d_inode;
/* The size case is special... */
@@ -169,7 +179,7 @@
if (iap->ia_size < inode->i_size) {
err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC);
if (err != 0)
- return err;
+ goto out;
}
if ((err = get_write_access(inode)) != 0)
return nfserrno(-err);
@@ -211,8 +221,9 @@
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(inode);
}
-
- return 0;
+ err = 0;
+out:
+ return err;
}
/*
@@ -230,20 +241,23 @@
access = wflag? MAY_WRITE : MAY_READ;
if ((err = fh_verify(rqstp, fhp, type, access)) != 0)
- return err;
+ goto out;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
inode = dentry->d_inode;
/* Disallow access to files with the append-only bit set or
* with mandatory locking enabled */
+ err = nfserr_perm;
if (IS_APPEND(inode) || IS_ISMNDLK(inode))
- return nfserr_perm;
+ goto out;
if (!inode->i_op || !inode->i_op->default_file_ops)
- return nfserr_perm;
+ goto out;
- if (wflag && (err = get_write_access(inode)) != 0)
- return nfserrno(-err);
+ if (wflag && (err = get_write_access(inode)) != 0) {
+ err = nfserrno(-err);
+ goto out;
+ }
memset(filp, 0, sizeof(*filp));
filp->f_op = inode->i_op->default_file_ops;
@@ -252,6 +266,7 @@
filp->f_mode = wflag? FMODE_WRITE : FMODE_READ;
filp->f_dentry = dentry;
+ err = 0;
if (filp->f_op->open) {
err = filp->f_op->open(inode, filp);
if (err) {
@@ -262,11 +277,11 @@
* is really on callers stack frame. -DaveM
*/
filp->f_count--;
- return nfserrno(-err);
+ err = nfserrno(-err);
}
}
-
- return 0;
+out:
+ return err;
}
/*
@@ -281,7 +296,8 @@
if (!inode->i_count)
printk(KERN_WARNING "nfsd: inode count == 0!\n");
if (!dentry->d_count)
- printk(KERN_WARNING "nfsd: wheee, dentry count == 0!\n");
+ printk(KERN_WARNING "nfsd: wheee, %s/%s d_count == 0!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
if (filp->f_op && filp->f_op->release)
filp->f_op->release(inode, filp);
if (filp->f_mode & FMODE_WRITE)
@@ -299,6 +315,9 @@
/*
* Obtain the readahead parameters for the given file
+ *
+ * N.B. is raparm cache for a file cleared when the file closes??
+ * (dentry might be reused later.)
*/
static inline struct raparms *
nfsd_get_raparms(struct dentry *dentry)
@@ -506,39 +525,53 @@
struct inode *dirp;
int err;
+ err = nfserr_perm;
if (!flen)
- return nfserr_perm;
+ goto out;
if (!(iap->ia_valid & ATTR_MODE))
iap->ia_mode = 0;
- if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE)) != 0)
- return err;
+ err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
+ if (err)
+ goto out;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
dirp = dentry->d_inode;
/* Get all the sanity checks out of the way before we lock the parent. */
- if(!dirp->i_op || !dirp->i_op->lookup) {
- return nfserrno(-ENOTDIR);
- } else if(type == S_IFREG) {
+ err = nfserr_notdir;
+ if(!dirp->i_op || !dirp->i_op->lookup)
+ goto out;
+ err = nfserr_perm;
+ if (type == S_IFREG) {
if(!dirp->i_op->create)
- return nfserr_perm;
+ goto out;
} else if(type == S_IFDIR) {
if(!dirp->i_op->mkdir)
- return nfserr_perm;
+ goto out;
} else if((type == S_IFCHR) || (type == S_IFBLK) || (type == S_IFIFO)) {
if(!dirp->i_op->mknod)
- return nfserr_perm;
+ goto out;
} else {
- return nfserr_perm;
+ goto out;
}
- if(!resfhp->fh_dverified) {
+ /*
+ * The response filehandle may have been setup already ...
+ */
+ if (!resfhp->fh_dverified) {
dchild = lookup_dentry(fname, dget(dentry), 0);
err = PTR_ERR(dchild);
if(IS_ERR(dchild))
return nfserrno(-err);
} else
- dchild = resfhp->fh_handle.fh_dentry;
+ dchild = resfhp->fh_dentry;
+ /*
+ * Make sure the child dentry is still negative ...
+ */
+ if (dchild->d_inode) {
+ printk("nfsd_create: dentry %s/%s not negative!\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ }
/* Looks good, lock the directory. */
fh_lock(fhp);
@@ -562,9 +595,15 @@
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(dirp);
- /* If needed, assemble the file handle for the newly created file. */
- if(!resfhp->fh_dverified)
+ /*
+ * Assemble the file handle for the newly created file,
+ * or update the filehandle to get the new inode info.
+ */
+ if (!resfhp->fh_dverified) {
fh_compose(resfhp, fhp->fh_export, dchild);
+ } else {
+ fh_update(resfhp);
+ }
/* Set file attributes. Mode has already been set and
* setting uid/gid works only for root. Irix appears to
@@ -574,7 +613,7 @@
err = 0;
if ((iap->ia_valid &= (ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
err = nfsd_setattr(rqstp, resfhp, iap);
-
+out:
return err;
}
@@ -597,7 +636,7 @@
if ((err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE|MAY_TRUNC)) != 0)
return err;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
inode = dentry->d_inode;
if ((err = get_write_access(inode)) != 0)
@@ -635,7 +674,7 @@
if ((err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ)) != 0)
return err;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
inode = dentry->d_inode;
if (!inode->i_op || !inode->i_op->readlink)
@@ -673,7 +712,7 @@
if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE)) != 0)
return err;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
dirp = dentry->d_inode;
if (nfsd_iscovered(dentry, fhp->fh_export) ||
@@ -720,7 +759,7 @@
(err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP)) != 0)
return err;
- ddir = ffhp->fh_handle.fh_dentry;
+ ddir = ffhp->fh_dentry;
dirp = ddir->d_inode;
dnew = lookup_dentry(fname, dget(ddir), 1);
@@ -731,7 +770,7 @@
err = -EEXIST;
if (dnew->d_inode)
goto dput_and_out;
- dest = tfhp->fh_handle.fh_dentry->d_inode;
+ dest = tfhp->fh_dentry->d_inode;
err = -EPERM;
if (!len)
@@ -794,10 +833,10 @@
|| (err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE)) != 0)
return err;
- fdentry = ffhp->fh_handle.fh_dentry;
+ fdentry = ffhp->fh_dentry;
fdir = fdentry->d_inode;
- tdentry = tfhp->fh_handle.fh_dentry;
+ tdentry = tfhp->fh_dentry;
tdir = tdentry->d_inode;
if (!flen || (fname[0] == '.' &&
@@ -816,6 +855,7 @@
if (IS_ERR(ndentry))
goto out_dput_old;
+ /* N.B. check this ... problems in locking?? */
nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
err = -EXDEV;
if (fdir->i_dev != tdir->i_dev)
@@ -856,7 +896,7 @@
if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE)) != 0)
return err;
- dentry = fhp->fh_handle.fh_dentry;
+ dentry = fhp->fh_dentry;
dirp = dentry->d_inode;
rdentry = lookup_dentry(fname, dget(dentry), 0);
@@ -975,20 +1015,24 @@
unsigned long oldfs;
int err;
- if ((err = fh_verify(rqstp, fhp, 0, MAY_NOP)) != 0)
- return err;
- dentry = fhp->fh_handle.fh_dentry;
+ err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (err)
+ goto out;
+ dentry = fhp->fh_dentry;
inode = dentry->d_inode;
+ err = nfserr_io;
if (!(sb = inode->i_sb) || !sb->s_op->statfs)
- return nfserr_io;
+ goto out;
oldfs = get_fs();
set_fs (KERNEL_DS);
sb->s_op->statfs(sb, stat, sizeof(*stat));
set_fs (oldfs);
+ err = 0;
- return 0;
+out:
+ return err;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov