summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfsfh.c5
-rw-r--r--fs/nfsd/vfs.c106
2 files changed, 37 insertions, 74 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index aa03c0a16..084a17d9b 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -63,7 +63,10 @@ dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
}
/*
- * Read a directory and return the name of the specified entry. i_sem is already down().
+ * Read a directory and return the name of the specified entry.
+ * i_sem is already down().
+ * The whole thing is a total BS. It should not be done via readdir(), damnit!
+ * Oh, well, as soon as it will be in filesystems...
*/
static int get_ino_name(struct dentry *dentry, struct qstr *name, unsigned long ino)
{
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 55c351852..c8389381f 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -801,7 +801,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
{
struct dentry *dentry, *dchild;
struct inode *dirp;
- nfsd_dirop_t opfunc = NULL;
int err;
err = nfserr_perm;
@@ -856,45 +855,31 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
}
+ if (!(iap->ia_valid & ATTR_MODE))
+ iap->ia_mode = 0;
+ iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
+
/*
* Get the dir op function pointer.
*/
err = nfserr_perm;
switch (type) {
case S_IFREG:
- opfunc = (nfsd_dirop_t) dirp->i_op->create;
+ err = vfs_create(dirp, dchild, iap->ia_mode);
break;
case S_IFDIR:
- opfunc = (nfsd_dirop_t) dirp->i_op->mkdir;
+ err = vfs_mkdir(dirp, dchild, iap->ia_mode);
break;
case S_IFCHR:
case S_IFBLK:
- /* The client is _NOT_ required to do security enforcement */
- if(!capable(CAP_SYS_ADMIN))
- {
- err = -EPERM;
- goto out;
- }
case S_IFIFO:
case S_IFSOCK:
- opfunc = dirp->i_op->mknod;
+ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
break;
default:
printk("nfsd: bad file type %o in nfsd_create\n", type);
- err = nfserr_inval;
+ err = -EINVAL;
}
- if (!opfunc)
- goto out;
-
- if (!(iap->ia_valid & ATTR_MODE))
- iap->ia_mode = 0;
- iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
-
- /*
- * Call the dir op function to create the object.
- */
- DQUOT_INIT(dirp);
- err = opfunc(dirp, dchild, iap->ia_mode, rdev);
if (err < 0)
goto out_nfserr;
@@ -954,9 +939,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = nfserr_notdir;
if(!dirp->i_op || !dirp->i_op->lookup)
goto out;
- err = nfserr_perm;
- if(!dirp->i_op->create)
- goto out;
/*
* Compose the response file handle.
@@ -1003,7 +985,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
}
- err = dirp->i_op->create(dirp, dchild, iap->ia_mode);
+ err = vfs_create(dirp, dchild, iap->ia_mode);
if (err < 0)
goto out_nfserr;
@@ -1101,7 +1083,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct iattr *iap)
{
struct dentry *dentry, *dnew;
- struct inode *dirp;
int err;
err = nfserr_noent;
@@ -1113,11 +1094,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
dentry = fhp->fh_dentry;
- err = nfserr_perm;
- dirp = dentry->d_inode;
- if (!dirp->i_op || !dirp->i_op->symlink)
- goto out;
-
dnew = lookup_dentry(fname, dget(dentry), 0);
err = PTR_ERR(dnew);
if (IS_ERR(dnew))
@@ -1130,27 +1106,23 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (err)
goto out_compose;
- err = nfserr_exist;
- if (!dnew->d_inode) {
- DQUOT_INIT(dirp);
- err = dirp->i_op->symlink(dirp, dnew, path);
- if (!err) {
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
- if (iap) {
- iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
- if (iap->ia_valid) {
- iap->ia_valid |= ATTR_CTIME;
- iap->ia_mode = (iap->ia_mode&S_IALLUGO)
- | S_IFLNK;
- err = notify_change(dnew, iap);
- if (!err && EX_ISSYNC(fhp->fh_export))
- write_inode_now(dentry->d_inode);
- }
- }
- } else
- err = nfserrno(-err);
- }
+ err = vfs_symlink(dentry->d_inode, dnew, path);
+ if (!err) {
+ if (EX_ISSYNC(fhp->fh_export))
+ nfsd_sync_dir(dentry);
+ if (iap) {
+ iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
+ if (iap->ia_valid) {
+ iap->ia_valid |= ATTR_CTIME;
+ iap->ia_mode = (iap->ia_mode&S_IALLUGO)
+ | S_IFLNK;
+ err = notify_change(dnew, iap);
+ if (!err && EX_ISSYNC(fhp->fh_export))
+ write_inode_now(dentry->d_inode);
+ }
+ }
+ } else
+ err = nfserrno(-err);
fh_unlock(fhp);
/* Compose the fh so the dentry will be freed ... */
@@ -1201,34 +1173,22 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
if (err)
goto out_dput;
- err = nfserr_exist;
- if (dnew->d_inode)
- goto out_unlock;
-
dold = tfhp->fh_dentry;
dest = dold->d_inode;
- err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
- if (dirp->i_dev != dest->i_dev)
- goto out_unlock;
-
- err = nfserr_perm;
- if (IS_IMMUTABLE(dest) || IS_APPEND(dest))
- goto out_unlock;
- if (!dirp->i_op || !dirp->i_op->link)
- goto out_unlock;
-
- DQUOT_INIT(dirp);
- err = dirp->i_op->link(dold, dirp, dnew);
+ err = vfs_link(dold, dirp, dnew);
if (!err) {
if (EX_ISSYNC(ffhp->fh_export)) {
nfsd_sync_dir(ddir);
write_inode_now(dest);
}
- } else
- err = nfserrno(-err);
+ } else {
+ if (err == -EXDEV && rqstp->rq_vers == 2)
+ err = nfserr_acces;
+ else
+ err = nfserrno(-err);
+ }
-out_unlock:
fh_unlock(ffhp);
out_dput:
dput(dnew);