summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-28 16:54:49 +0100
committerIngo Molnar <mingo@elte.hu>2008-10-28 16:54:49 +0100
commitd1a76187a5be4f89c6cb19d800cb5fb7aac735c5 (patch)
tree2fac3ffbfffc7560eeef8364b541d0d7a0057920 /fs/nfsd
parentc7e78cff6b7518212247fb20b1dc6411540dc9af (diff)
parent0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff)
downloadop-kernel-dev-d1a76187a5be4f89c6cb19d800cb5fb7aac735c5.zip
op-kernel-dev-d1a76187a5be4f89c6cb19d800cb5fb7aac735c5.tar.gz
Merge commit 'v2.6.28-rc2' into core/locking
Conflicts: arch/um/include/asm/system.h
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c144
-rw-r--r--fs/nfsd/lockd.c1
-rw-r--r--fs/nfsd/nfs3proc.c8
-rw-r--r--fs/nfsd/nfs4callback.c7
-rw-r--r--fs/nfsd/nfs4proc.c8
-rw-r--r--fs/nfsd/nfs4recover.c50
-rw-r--r--fs/nfsd/nfs4state.c42
-rw-r--r--fs/nfsd/nfs4xdr.c171
-rw-r--r--fs/nfsd/nfsctl.c13
-rw-r--r--fs/nfsd/nfsfh.c30
-rw-r--r--fs/nfsd/nfsproc.c6
-rw-r--r--fs/nfsd/nfssvc.c24
-rw-r--r--fs/nfsd/vfs.c195
13 files changed, 406 insertions, 293 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 9dc036f..5839b22 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -99,7 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
int fsidtype;
char *ep;
struct svc_expkey key;
- struct svc_expkey *ek;
+ struct svc_expkey *ek = NULL;
if (mesg[mlen-1] != '\n')
return -EINVAL;
@@ -107,7 +107,8 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
err = -ENOMEM;
- if (!buf) goto out;
+ if (!buf)
+ goto out;
err = -EINVAL;
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
@@ -151,34 +152,32 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
/* now we want a pathname, or empty meaning NEGATIVE */
err = -EINVAL;
- if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
+ len = qword_get(&mesg, buf, PAGE_SIZE);
+ if (len < 0)
goto out;
dprintk("Path seems to be <%s>\n", buf);
err = 0;
if (len == 0) {
set_bit(CACHE_NEGATIVE, &key.h.flags);
ek = svc_expkey_update(&key, ek);
- if (ek)
- cache_put(&ek->h, &svc_expkey_cache);
- else err = -ENOMEM;
+ if (!ek)
+ err = -ENOMEM;
} else {
- struct nameidata nd;
- err = path_lookup(buf, 0, &nd);
+ err = kern_path(buf, 0, &key.ek_path);
if (err)
goto out;
dprintk("Found the path %s\n", buf);
- key.ek_path = nd.path;
ek = svc_expkey_update(&key, ek);
- if (ek)
- cache_put(&ek->h, &svc_expkey_cache);
- else
+ if (!ek)
err = -ENOMEM;
- path_put(&nd.path);
+ path_put(&key.ek_path);
}
cache_flush();
out:
+ if (ek)
+ cache_put(&ek->h, &svc_expkey_cache);
if (dom)
auth_domain_put(dom);
kfree(buf);
@@ -500,35 +499,22 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
int len;
int err;
struct auth_domain *dom = NULL;
- struct nameidata nd;
- struct svc_export exp, *expp;
+ struct svc_export exp = {}, *expp;
int an_int;
- nd.path.dentry = NULL;
- exp.ex_pathname = NULL;
-
- /* fs locations */
- exp.ex_fslocs.locations = NULL;
- exp.ex_fslocs.locations_count = 0;
- exp.ex_fslocs.migrated = 0;
-
- exp.ex_uuid = NULL;
-
- /* secinfo */
- exp.ex_nflavors = 0;
-
if (mesg[mlen-1] != '\n')
return -EINVAL;
mesg[mlen-1] = 0;
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- err = -ENOMEM;
- if (!buf) goto out;
+ if (!buf)
+ return -ENOMEM;
/* client */
- len = qword_get(&mesg, buf, PAGE_SIZE);
err = -EINVAL;
- if (len <= 0) goto out;
+ len = qword_get(&mesg, buf, PAGE_SIZE);
+ if (len <= 0)
+ goto out;
err = -ENOENT;
dom = auth_domain_find(buf);
@@ -537,25 +523,25 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
/* path */
err = -EINVAL;
- if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
- goto out;
- err = path_lookup(buf, 0, &nd);
- if (err) goto out_no_path;
+ if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
+ goto out1;
+
+ err = kern_path(buf, 0, &exp.ex_path);
+ if (err)
+ goto out1;
- exp.h.flags = 0;
exp.ex_client = dom;
- exp.ex_path.mnt = nd.path.mnt;
- exp.ex_path.dentry = nd.path.dentry;
- exp.ex_pathname = kstrdup(buf, GFP_KERNEL);
+
err = -ENOMEM;
+ exp.ex_pathname = kstrdup(buf, GFP_KERNEL);
if (!exp.ex_pathname)
- goto out;
+ goto out2;
/* expiry */
err = -EINVAL;
exp.h.expiry_time = get_expiry(&mesg);
if (exp.h.expiry_time == 0)
- goto out;
+ goto out3;
/* flags */
err = get_int(&mesg, &an_int);
@@ -563,22 +549,26 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
err = 0;
set_bit(CACHE_NEGATIVE, &exp.h.flags);
} else {
- if (err || an_int < 0) goto out;
+ if (err || an_int < 0)
+ goto out3;
exp.ex_flags= an_int;
/* anon uid */
err = get_int(&mesg, &an_int);
- if (err) goto out;
+ if (err)
+ goto out3;
exp.ex_anon_uid= an_int;
/* anon gid */
err = get_int(&mesg, &an_int);
- if (err) goto out;
+ if (err)
+ goto out3;
exp.ex_anon_gid= an_int;
/* fsid */
err = get_int(&mesg, &an_int);
- if (err) goto out;
+ if (err)
+ goto out3;
exp.ex_fsid = an_int;
while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
@@ -604,12 +594,13 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
*/
break;
if (err)
- goto out;
+ goto out4;
}
- err = check_export(nd.path.dentry->d_inode, exp.ex_flags,
+ err = check_export(exp.ex_path.dentry->d_inode, exp.ex_flags,
exp.ex_uuid);
- if (err) goto out;
+ if (err)
+ goto out4;
}
expp = svc_export_lookup(&exp);
@@ -622,15 +613,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
err = -ENOMEM;
else
exp_put(expp);
- out:
+out4:
nfsd4_fslocs_free(&exp.ex_fslocs);
kfree(exp.ex_uuid);
+out3:
kfree(exp.ex_pathname);
- if (nd.path.dentry)
- path_put(&nd.path);
- out_no_path:
- if (dom)
- auth_domain_put(dom);
+out2:
+ path_put(&exp.ex_path);
+out1:
+ auth_domain_put(dom);
+out:
kfree(buf);
return err;
}
@@ -998,7 +990,7 @@ exp_export(struct nfsctl_export *nxp)
struct svc_export *exp = NULL;
struct svc_export new;
struct svc_expkey *fsid_key = NULL;
- struct nameidata nd;
+ struct path path;
int err;
/* Consistency check */
@@ -1021,12 +1013,12 @@ exp_export(struct nfsctl_export *nxp)
/* Look up the dentry */
- err = path_lookup(nxp->ex_path, 0, &nd);
+ err = kern_path(nxp->ex_path, 0, &path);
if (err)
goto out_put_clp;
err = -EINVAL;
- exp = exp_get_by_name(clp, nd.path.mnt, nd.path.dentry, NULL);
+ exp = exp_get_by_name(clp, path.mnt, path.dentry, NULL);
memset(&new, 0, sizeof(new));
@@ -1034,8 +1026,8 @@ exp_export(struct nfsctl_export *nxp)
if ((nxp->ex_flags & NFSEXP_FSID) &&
(!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
fsid_key->ek_path.mnt &&
- (fsid_key->ek_path.mnt != nd.path.mnt ||
- fsid_key->ek_path.dentry != nd.path.dentry))
+ (fsid_key->ek_path.mnt != path.mnt ||
+ fsid_key->ek_path.dentry != path.dentry))
goto finish;
if (!IS_ERR(exp)) {
@@ -1051,7 +1043,7 @@ exp_export(struct nfsctl_export *nxp)
goto finish;
}
- err = check_export(nd.path.dentry->d_inode, nxp->ex_flags, NULL);
+ err = check_export(path.dentry->d_inode, nxp->ex_flags, NULL);
if (err) goto finish;
err = -ENOMEM;
@@ -1064,7 +1056,7 @@ exp_export(struct nfsctl_export *nxp)
if (!new.ex_pathname)
goto finish;
new.ex_client = clp;
- new.ex_path = nd.path;
+ new.ex_path = path;
new.ex_flags = nxp->ex_flags;
new.ex_anon_uid = nxp->ex_anon_uid;
new.ex_anon_gid = nxp->ex_anon_gid;
@@ -1090,7 +1082,7 @@ finish:
exp_put(exp);
if (fsid_key && !IS_ERR(fsid_key))
cache_put(&fsid_key->h, &svc_expkey_cache);
- path_put(&nd.path);
+ path_put(&path);
out_put_clp:
auth_domain_put(clp);
out_unlock:
@@ -1121,7 +1113,7 @@ exp_unexport(struct nfsctl_export *nxp)
{
struct auth_domain *dom;
svc_export *exp;
- struct nameidata nd;
+ struct path path;
int err;
/* Consistency check */
@@ -1138,13 +1130,13 @@ exp_unexport(struct nfsctl_export *nxp)
goto out_unlock;
}
- err = path_lookup(nxp->ex_path, 0, &nd);
+ err = kern_path(nxp->ex_path, 0, &path);
if (err)
goto out_domain;
err = -EINVAL;
- exp = exp_get_by_name(dom, nd.path.mnt, nd.path.dentry, NULL);
- path_put(&nd.path);
+ exp = exp_get_by_name(dom, path.mnt, path.dentry, NULL);
+ path_put(&path);
if (IS_ERR(exp))
goto out_domain;
@@ -1166,26 +1158,26 @@ out_unlock:
* since its harder to fool a kernel module than a user space program.
*/
int
-exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
+exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
- struct nameidata nd;
+ struct path path;
struct inode *inode;
struct svc_fh fh;
int err;
err = -EPERM;
/* NB: we probably ought to check that it's NUL-terminated */
- if (path_lookup(path, 0, &nd)) {
- printk("nfsd: exp_rootfh path not found %s", path);
+ if (kern_path(name, 0, &path)) {
+ printk("nfsd: exp_rootfh path not found %s", name);
return err;
}
- inode = nd.path.dentry->d_inode;
+ inode = path.dentry->d_inode;
dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
- path, nd.path.dentry, clp->name,
+ name, path.dentry, clp->name,
inode->i_sb->s_id, inode->i_ino);
- exp = exp_parent(clp, nd.path.mnt, nd.path.dentry, NULL);
+ exp = exp_parent(clp, path.mnt, path.dentry, NULL);
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
goto out;
@@ -1195,7 +1187,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
* fh must be initialized before calling fh_compose
*/
fh_init(&fh, maxsize);
- if (fh_compose(&fh, exp, nd.path.dentry, NULL))
+ if (fh_compose(&fh, exp, path.dentry, NULL))
err = -EINVAL;
else
err = 0;
@@ -1203,7 +1195,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
fh_put(&fh);
exp_put(exp);
out:
- path_put(&nd.path);
+ path_put(&path);
return err;
}
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 15c6fae..b2786a5 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -70,7 +70,6 @@ nlm_fclose(struct file *filp)
static struct nlmsvc_binding nfsd_nlm_ops = {
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
- .get_grace_period = get_nfs4_grace_period,
};
void
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 4d617ea..9dbd2eb 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -63,7 +63,8 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0,
+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
if (nfserr)
RETURN_STATUS(nfserr);
@@ -530,7 +531,7 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
dprintk("nfsd: FSSTAT(3) %s\n",
SVCFH_fmt(&argp->fh));
- nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
+ nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
fh_put(&argp->fh);
RETURN_STATUS(nfserr);
}
@@ -558,7 +559,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
resp->f_maxfilesize = ~(u32) 0;
resp->f_properties = NFS3_FSF_DEFAULT;
- nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
+ nfserr = fh_verify(rqstp, &argp->fh, 0,
+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
/* Check special features of the file system. May request
* different read/write sizes for file systems known to have
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 702fa57..094747a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -225,7 +225,8 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
WRITE32(OP_CB_RECALL);
- WRITEMEM(&cb_rec->cbr_stateid, sizeof(stateid_t));
+ WRITE32(cb_rec->cbr_stateid.si_generation);
+ WRITEMEM(&cb_rec->cbr_stateid.si_opaque, sizeof(stateid_opaque_t));
WRITE32(cb_rec->cbr_trunc);
WRITE32(len);
WRITEMEM(cb_rec->cbr_fhval, len);
@@ -379,6 +380,7 @@ static int do_probe_callback(void *data)
.addrsize = sizeof(addr),
.timeout = &timeparms,
.program = &cb_program,
+ .prognumber = cb->cb_prog,
.version = nfs_cb_version[1]->number,
.authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
.flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
@@ -396,9 +398,6 @@ static int do_probe_callback(void *data)
addr.sin_port = htons(cb->cb_port);
addr.sin_addr.s_addr = htonl(cb->cb_addr);
- /* Initialize rpc_stat */
- memset(args.program->stats, 0, sizeof(struct rpc_stat));
-
/* Create RPC client */
client = rpc_create(&args);
if (IS_ERR(client)) {
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e5b51ff..669461e 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -201,10 +201,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
/* Openowner is now set, so sequence id will get bumped. Now we need
* these checks before we do any creates: */
status = nfserr_grace;
- if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
status = nfserr_no_grace;
- if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
goto out;
switch (open->op_claim_type) {
@@ -575,7 +575,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
__be32 status;
- if (nfs4_in_grace())
+ if (locks_in_grace())
return nfserr_grace;
status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
remove->rm_name, remove->rm_namelen);
@@ -596,7 +596,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (!cstate->save_fh.fh_dentry)
return status;
- if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
+ if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
& NFSEXP_NOSUBTREECHECK))
return nfserr_grace;
status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 145b3c8..bb93946 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -51,7 +51,7 @@
#define NFSDDBG_FACILITY NFSDDBG_PROC
/* Globals */
-static struct nameidata rec_dir;
+static struct path rec_dir;
static int rec_dir_init = 0;
static void
@@ -121,9 +121,9 @@ out_no_tfm:
static void
nfsd4_sync_rec_dir(void)
{
- mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex);
- nfsd_sync_dir(rec_dir.path.dentry);
- mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
+ nfsd_sync_dir(rec_dir.dentry);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
}
int
@@ -143,9 +143,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
nfs4_save_user(&uid, &gid);
/* lock the parent */
- mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
- dentry = lookup_one_len(dname, rec_dir.path.dentry, HEXDIR_LEN-1);
+ dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
if (IS_ERR(dentry)) {
status = PTR_ERR(dentry);
goto out_unlock;
@@ -155,15 +155,15 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
goto out_put;
}
- status = mnt_want_write(rec_dir.path.mnt);
+ status = mnt_want_write(rec_dir.mnt);
if (status)
goto out_put;
- status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU);
- mnt_drop_write(rec_dir.path.mnt);
+ status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
+ mnt_drop_write(rec_dir.mnt);
out_put:
dput(dentry);
out_unlock:
- mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
if (status == 0) {
clp->cl_firststate = 1;
nfsd4_sync_rec_dir();
@@ -226,7 +226,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
nfs4_save_user(&uid, &gid);
- filp = dentry_open(dget(dir), mntget(rec_dir.path.mnt), O_RDONLY);
+ filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
@@ -291,9 +291,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
- mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex);
- dentry = lookup_one_len(name, rec_dir.path.dentry, namlen);
- mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
+ dentry = lookup_one_len(name, rec_dir.dentry, namlen);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
if (IS_ERR(dentry)) {
status = PTR_ERR(dentry);
return status;
@@ -302,7 +302,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
if (!dentry->d_inode)
goto out;
- status = nfsd4_clear_clid_dir(rec_dir.path.dentry, dentry);
+ status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
out:
dput(dentry);
return status;
@@ -318,7 +318,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
if (!rec_dir_init || !clp->cl_firststate)
return;
- status = mnt_want_write(rec_dir.path.mnt);
+ status = mnt_want_write(rec_dir.mnt);
if (status)
goto out;
clp->cl_firststate = 0;
@@ -327,7 +327,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
nfs4_reset_user(uid, gid);
if (status == 0)
nfsd4_sync_rec_dir();
- mnt_drop_write(rec_dir.path.mnt);
+ mnt_drop_write(rec_dir.mnt);
out:
if (status)
printk("NFSD: Failed to remove expired client state directory"
@@ -357,17 +357,17 @@ nfsd4_recdir_purge_old(void) {
if (!rec_dir_init)
return;
- status = mnt_want_write(rec_dir.path.mnt);
+ status = mnt_want_write(rec_dir.mnt);
if (status)
goto out;
- status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old);
+ status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
if (status == 0)
nfsd4_sync_rec_dir();
- mnt_drop_write(rec_dir.path.mnt);
+ mnt_drop_write(rec_dir.mnt);
out:
if (status)
printk("nfsd4: failed to purge old clients from recovery"
- " directory %s\n", rec_dir.path.dentry->d_name.name);
+ " directory %s\n", rec_dir.dentry->d_name.name);
}
static int
@@ -387,10 +387,10 @@ int
nfsd4_recdir_load(void) {
int status;
- status = nfsd4_list_rec_dir(rec_dir.path.dentry, load_recdir);
+ status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
if (status)
printk("nfsd4: failed loading clients from recovery"
- " directory %s\n", rec_dir.path.dentry->d_name.name);
+ " directory %s\n", rec_dir.dentry->d_name.name);
return status;
}
@@ -412,7 +412,7 @@ nfsd4_init_recdir(char *rec_dirname)
nfs4_save_user(&uid, &gid);
- status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+ status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
&rec_dir);
if (status)
printk("NFSD: unable to find recovery directory %s\n",
@@ -429,5 +429,5 @@ nfsd4_shutdown_recdir(void)
if (!rec_dir_init)
return;
rec_dir_init = 0;
- path_put(&rec_dir.path);
+ path_put(&rec_dir);
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1578d7a..b0bebc5 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -61,7 +61,6 @@
static time_t lease_time = 90; /* default lease time */
static time_t user_lease_time = 90;
static time_t boot_time;
-static int in_grace = 1;
static u32 current_ownerid = 1;
static u32 current_fileid = 1;
static u32 current_delegid = 1;
@@ -1640,7 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
case NFS4_OPEN_CLAIM_NULL:
/* Let's not give out any delegations till everyone's
* had the chance to reclaim theirs.... */
- if (nfs4_in_grace())
+ if (locks_in_grace())
goto out;
if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
goto out;
@@ -1816,12 +1815,15 @@ out:
return status;
}
+struct lock_manager nfsd4_manager = {
+};
+
static void
-end_grace(void)
+nfsd4_end_grace(void)
{
dprintk("NFSD: end of grace period\n");
nfsd4_recdir_purge_old();
- in_grace = 0;
+ locks_end_grace(&nfsd4_manager);
}
static time_t
@@ -1838,8 +1840,8 @@ nfs4_laundromat(void)
nfs4_lock_state();
dprintk("NFSD: laundromat service - starting\n");
- if (in_grace)
- end_grace();
+ if (locks_in_grace())
+ nfsd4_end_grace();
list_for_each_safe(pos, next, &client_lru) {
clp = list_entry(pos, struct nfs4_client, cl_lru);
if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1974,7 +1976,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
return nfserr_bad_stateid;
else if (ONE_STATEID(stateid) && (flags & RD_STATE))
return nfs_ok;
- else if (nfs4_in_grace()) {
+ else if (locks_in_grace()) {
/* Answer in remaining cases depends on existance of
* conflicting state; so we must wait out the grace period. */
return nfserr_grace;
@@ -1993,7 +1995,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
static inline int
io_during_grace_disallowed(struct inode *inode, int flags)
{
- return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
+ return locks_in_grace() && (flags & (RD_STATE | WR_STATE))
&& mandatory_lock(inode);
}
@@ -2693,10 +2695,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
filp = lock_stp->st_vfs_file;
status = nfserr_grace;
- if (nfs4_in_grace() && !lock->lk_reclaim)
+ if (locks_in_grace() && !lock->lk_reclaim)
goto out;
status = nfserr_no_grace;
- if (!nfs4_in_grace() && lock->lk_reclaim)
+ if (!locks_in_grace() && lock->lk_reclaim)
goto out;
locks_init_lock(&file_lock);
@@ -2779,7 +2781,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
int error;
__be32 status;
- if (nfs4_in_grace())
+ if (locks_in_grace())
return nfserr_grace;
if (check_lock_length(lockt->lt_offset, lockt->lt_length))
@@ -3192,9 +3194,9 @@ __nfs4_state_start(void)
unsigned long grace_time;
boot_time = get_seconds();
- grace_time = get_nfs_grace_period();
+ grace_time = get_nfs4_grace_period();
lease_time = user_lease_time;
- in_grace = 1;
+ locks_start_grace(&nfsd4_manager);
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
grace_time/HZ);
laundry_wq = create_singlethread_workqueue("nfsd4");
@@ -3213,12 +3215,6 @@ nfs4_state_start(void)
return;
}
-int
-nfs4_in_grace(void)
-{
- return in_grace;
-}
-
time_t
nfs4_lease_time(void)
{
@@ -3288,17 +3284,17 @@ int
nfs4_reset_recoverydir(char *recdir)
{
int status;
- struct nameidata nd;
+ struct path path;
- status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
+ status = kern_path(recdir, LOOKUP_FOLLOW, &path);
if (status)
return status;
status = -ENOTDIR;
- if (S_ISDIR(nd.path.dentry->d_inode->i_mode)) {
+ if (S_ISDIR(path.dentry->d_inode->i_mode)) {
nfs4_set_recdir(recdir);
status = 0;
}
- path_put(&nd.path);
+ path_put(&path);
return status;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 14ba4d9..afcdf4b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -413,6 +413,18 @@ out_nfserr:
}
static __be32
+nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
+{
+ DECODE_HEAD;
+
+ READ_BUF(sizeof(stateid_t));
+ READ32(sid->si_generation);
+ COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
+
+ DECODE_TAIL;
+}
+
+static __be32
nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
{
DECODE_HEAD;
@@ -429,10 +441,9 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
DECODE_HEAD;
close->cl_stateowner = NULL;
- READ_BUF(4 + sizeof(stateid_t));
+ READ_BUF(4);
READ32(close->cl_seqid);
- READ32(close->cl_stateid.si_generation);
- COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
+ return nfsd4_decode_stateid(argp, &close->cl_stateid);
DECODE_TAIL;
}
@@ -493,13 +504,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
static inline __be32
nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
{
- DECODE_HEAD;
-
- READ_BUF(sizeof(stateid_t));
- READ32(dr->dr_stateid.si_generation);
- COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t));
-
- DECODE_TAIL;
+ return nfsd4_decode_stateid(argp, &dr->dr_stateid);
}
static inline __be32
@@ -542,20 +547,22 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
READ32(lock->lk_is_new);
if (lock->lk_is_new) {
- READ_BUF(36);
+ READ_BUF(4);
READ32(lock->lk_new_open_seqid);
- READ32(lock->lk_new_open_stateid.si_generation);
-
- COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
+ if (status)
+ return status;
+ READ_BUF(8 + sizeof(clientid_t));
READ32(lock->lk_new_lock_seqid);
COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
READ32(lock->lk_new_owner.len);
READ_BUF(lock->lk_new_owner.len);
READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
} else {
- READ_BUF(20);
- READ32(lock->lk_old_lock_stateid.si_generation);
- COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
+ if (status)
+ return status;
+ READ_BUF(4);
READ32(lock->lk_old_lock_seqid);
}
@@ -587,13 +594,15 @@ nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
DECODE_HEAD;
locku->lu_stateowner = NULL;
- READ_BUF(24 + sizeof(stateid_t));
+ READ_BUF(8);
READ32(locku->lu_type);
if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
goto xdr_error;
READ32(locku->lu_seqid);
- READ32(locku->lu_stateid.si_generation);
- COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
+ if (status)
+ return status;
+ READ_BUF(16);
READ64(locku->lu_offset);
READ64(locku->lu_length);
@@ -678,8 +687,10 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
READ32(open->op_delegate_type);
break;
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
- READ_BUF(sizeof(stateid_t) + 4);
- COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+ status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
+ if (status)
+ return status;
+ READ_BUF(4);
READ32(open->op_fname.len);
READ_BUF(open->op_fname.len);
SAVEMEM(open->op_fname.data, open->op_fname.len);
@@ -699,9 +710,10 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
DECODE_HEAD;
open_conf->oc_stateowner = NULL;
- READ_BUF(4 + sizeof(stateid_t));
- READ32(open_conf->oc_req_stateid.si_generation);
- COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
+ if (status)
+ return status;
+ READ_BUF(4);
READ32(open_conf->oc_seqid);
DECODE_TAIL;
@@ -713,9 +725,10 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
DECODE_HEAD;
open_down->od_stateowner = NULL;
- READ_BUF(12 + sizeof(stateid_t));
- READ32(open_down->od_stateid.si_generation);
- COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
+ if (status)
+ return status;
+ READ_BUF(12);
READ32(open_down->od_seqid);
READ32(open_down->od_share_access);
READ32(open_down->od_share_deny);
@@ -743,9 +756,10 @@ nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
{
DECODE_HEAD;
- READ_BUF(sizeof(stateid_t) + 12);
- READ32(read->rd_stateid.si_generation);
- COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &read->rd_stateid);
+ if (status)
+ return status;
+ READ_BUF(12);
READ64(read->rd_offset);
READ32(read->rd_length);
@@ -834,15 +848,13 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
static __be32
nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
{
- DECODE_HEAD;
-
- READ_BUF(sizeof(stateid_t));
- READ32(setattr->sa_stateid.si_generation);
- COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
- if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
- goto out;
+ __be32 status;
- DECODE_TAIL;
+ status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
+ if (status)
+ return status;
+ return nfsd4_decode_fattr(argp, setattr->sa_bmval,
+ &setattr->sa_iattr, &setattr->sa_acl);
}
static __be32
@@ -927,9 +939,10 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
int len;
DECODE_HEAD;
- READ_BUF(sizeof(stateid_opaque_t) + 20);
- READ32(write->wr_stateid.si_generation);
- COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
+ status = nfsd4_decode_stateid(argp, &write->wr_stateid);
+ if (status)
+ return status;
+ READ_BUF(16);
READ64(write->wr_offset);
READ32(write->wr_stable_how);
if (write->wr_stable_how > 2)
@@ -1183,7 +1196,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
* Header routine to setup seqid operation replay cache
*/
#define ENCODE_SEQID_OP_HEAD \
- __be32 *p; \
__be32 *save; \
\
save = resp->p;
@@ -1950,6 +1962,17 @@ fail:
return -EINVAL;
}
+static void
+nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
+{
+ ENCODE_HEAD;
+
+ RESERVE_SPACE(sizeof(stateid_t));
+ WRITE32(sid->si_generation);
+ WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
+ ADJUST_ARGS();
+}
+
static __be32
nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
{
@@ -1969,12 +1992,9 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
{
ENCODE_SEQID_OP_HEAD;
- if (!nfserr) {
- RESERVE_SPACE(sizeof(stateid_t));
- WRITE32(close->cl_stateid.si_generation);
- WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
- ADJUST_ARGS();
- }
+ if (!nfserr)
+ nfsd4_encode_stateid(resp, &close->cl_stateid);
+
ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
return nfserr;
}
@@ -2074,12 +2094,9 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo
{
ENCODE_SEQID_OP_HEAD;
- if (!nfserr) {
- RESERVE_SPACE(4 + sizeof(stateid_t));
- WRITE32(lock->lk_resp_stateid.si_generation);
- WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
- ADJUST_ARGS();
- } else if (nfserr == nfserr_denied)
+ if (!nfserr)
+ nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
+ else if (nfserr == nfserr_denied)
nfsd4_encode_lock_denied(resp, &lock->lk_denied);
ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
@@ -2099,13 +2116,9 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
{
ENCODE_SEQID_OP_HEAD;
- if (!nfserr) {
- RESERVE_SPACE(sizeof(stateid_t));
- WRITE32(locku->lu_stateid.si_generation);
- WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
- ADJUST_ARGS();
- }
-
+ if (!nfserr)
+ nfsd4_encode_stateid(resp, &locku->lu_stateid);
+
ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
return nfserr;
}
@@ -2128,14 +2141,14 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
static __be32
nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
{
+ ENCODE_HEAD;
ENCODE_SEQID_OP_HEAD;
if (nfserr)
goto out;
- RESERVE_SPACE(36 + sizeof(stateid_t));
- WRITE32(open->op_stateid.si_generation);
- WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
+ nfsd4_encode_stateid(resp, &open->op_stateid);
+ RESERVE_SPACE(40);
WRITECINFO(open->op_cinfo);
WRITE32(open->op_rflags);
WRITE32(2);
@@ -2148,8 +2161,8 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
case NFS4_OPEN_DELEGATE_NONE:
break;
case NFS4_OPEN_DELEGATE_READ:
- RESERVE_SPACE(20 + sizeof(stateid_t));
- WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+ nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
+ RESERVE_SPACE(20);
WRITE32(open->op_recall);
/*
@@ -2162,8 +2175,8 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
ADJUST_ARGS();
break;
case NFS4_OPEN_DELEGATE_WRITE:
- RESERVE_SPACE(32 + sizeof(stateid_t));
- WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+ nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
+ RESERVE_SPACE(32);
WRITE32(0);
/*
@@ -2195,13 +2208,9 @@ static __be32
nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
{
ENCODE_SEQID_OP_HEAD;
-
- if (!nfserr) {
- RESERVE_SPACE(sizeof(stateid_t));
- WRITE32(oc->oc_resp_stateid.si_generation);
- WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
- ADJUST_ARGS();
- }
+
+ if (!nfserr)
+ nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
return nfserr;
@@ -2211,13 +2220,9 @@ static __be32
nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
{
ENCODE_SEQID_OP_HEAD;
-
- if (!nfserr) {
- RESERVE_SPACE(sizeof(stateid_t));
- WRITE32(od->od_stateid.si_generation);
- WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
- ADJUST_ARGS();
- }
+
+ if (!nfserr)
+ nfsd4_encode_stateid(resp, &od->od_stateid);
ENCODE_SEQID_OP_TAIL(od->od_stateowner);
return nfserr;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c53e65f..e3f9783 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -341,7 +341,7 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
{
- struct nameidata nd;
+ struct path path;
char *fo_path;
int error;
@@ -356,13 +356,13 @@ static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
if (qword_get(&buf, fo_path, size) < 0)
return -EINVAL;
- error = path_lookup(fo_path, 0, &nd);
+ error = kern_path(fo_path, 0, &path);
if (error)
return error;
- error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb);
+ error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
- path_put(&nd.path);
+ path_put(&path);
return error;
}
@@ -614,10 +614,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
return -EINVAL;
err = nfsd_create_serv();
if (!err) {
- int proto = 0;
- err = svc_addsock(nfsd_serv, fd, buf, &proto);
+ err = svc_addsock(nfsd_serv, fd, buf);
if (err >= 0) {
- err = lockd_up(proto);
+ err = lockd_up();
if (err < 0)
svc_sock_names(buf+strlen(buf)+1, nfsd_serv, buf);
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index ea37c96..cd25d91 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -302,17 +302,27 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
if (error)
goto out;
- if (!(access & NFSD_MAY_LOCK)) {
- /*
- * pseudoflavor restrictions are not enforced on NLM,
- * which clients virtually always use auth_sys for,
- * even while using RPCSEC_GSS for NFS.
- */
- error = check_nfsd_access(exp, rqstp);
- if (error)
- goto out;
- }
+ /*
+ * pseudoflavor restrictions are not enforced on NLM,
+ * which clients virtually always use auth_sys for,
+ * even while using RPCSEC_GSS for NFS.
+ */
+ if (access & NFSD_MAY_LOCK)
+ goto skip_pseudoflavor_check;
+ /*
+ * Clients may expect to be able to use auth_sys during mount,
+ * even if they use gss for everything else; see section 2.3.2
+ * of rfc 2623.
+ */
+ if (access & NFSD_MAY_BYPASS_GSS_ON_ROOT
+ && exp->ex_path.dentry == dentry)
+ goto skip_pseudoflavor_check;
+
+ error = check_nfsd_access(exp, rqstp);
+ if (error)
+ goto out;
+skip_pseudoflavor_check:
/* Finally, check access permissions. */
error = nfsd_permission(rqstp, exp, dentry, access);
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0766f95..5cffeca 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -65,7 +65,8 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0,
+ NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
return nfsd_return_attrs(nfserr, resp);
}
@@ -521,7 +522,8 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
- nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
+ nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
+ NFSD_MAY_BYPASS_GSS_ON_ROOT);
fh_put(&argp->fh);
return nfserr;
}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 80292ff..07e4f5d 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -229,6 +229,7 @@ int nfsd_create_serv(void)
atomic_set(&nfsd_busy, 0);
nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
+ AF_INET,
nfsd_last_thread, nfsd, THIS_MODULE);
if (nfsd_serv == NULL)
err = -ENOMEM;
@@ -243,25 +244,24 @@ static int nfsd_init_socks(int port)
if (!list_empty(&nfsd_serv->sv_permsocks))
return 0;
- error = lockd_up(IPPROTO_UDP);
- if (error >= 0) {
- error = svc_create_xprt(nfsd_serv, "udp", port,
+ error = svc_create_xprt(nfsd_serv, "udp", port,
SVC_SOCK_DEFAULTS);
- if (error < 0)
- lockd_down();
- }
if (error < 0)
return error;
- error = lockd_up(IPPROTO_TCP);
- if (error >= 0) {
- error = svc_create_xprt(nfsd_serv, "tcp", port,
+ error = lockd_up();
+ if (error < 0)
+ return error;
+
+ error = svc_create_xprt(nfsd_serv, "tcp", port,
SVC_SOCK_DEFAULTS);
- if (error < 0)
- lockd_down();
- }
if (error < 0)
return error;
+
+ error = lockd_up();
+ if (error < 0)
+ return error;
+
return 0;
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 18060be..0bc56f6 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -83,7 +83,6 @@ struct raparm_hbucket {
spinlock_t pb_lock;
} ____cacheline_aligned_in_smp;
-static struct raparms * raparml;
#define RAPARM_HASH_BITS 4
#define RAPARM_HASH_SIZE (1<<RAPARM_HASH_BITS)
#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
@@ -411,6 +410,7 @@ out_nfserr:
static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
{
ssize_t buflen;
+ ssize_t ret;
buflen = vfs_getxattr(dentry, key, NULL, 0);
if (buflen <= 0)
@@ -420,7 +420,10 @@ static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
if (!*buf)
return -ENOMEM;
- return vfs_getxattr(dentry, key, *buf, buflen);
+ ret = vfs_getxattr(dentry, key, *buf, buflen);
+ if (ret < 0)
+ kfree(*buf);
+ return ret;
}
#endif
@@ -1815,6 +1818,115 @@ out:
}
/*
+ * We do this buffering because we must not call back into the file
+ * system's ->lookup() method from the filldir callback. That may well
+ * deadlock a number of file systems.
+ *
+ * This is based heavily on the implementation of same in XFS.
+ */
+struct buffered_dirent {
+ u64 ino;
+ loff_t offset;
+ int namlen;
+ unsigned int d_type;
+ char name[];
+};
+
+struct readdir_data {
+ char *dirent;
+ size_t used;
+ int full;
+};
+
+static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ struct readdir_data *buf = __buf;
+ struct buffered_dirent *de = (void *)(buf->dirent + buf->used);
+ unsigned int reclen;
+
+ reclen = ALIGN(sizeof(struct buffered_dirent) + namlen, sizeof(u64));
+ if (buf->used + reclen > PAGE_SIZE) {
+ buf->full = 1;
+ return -EINVAL;
+ }
+
+ de->namlen = namlen;
+ de->offset = offset;
+ de->ino = ino;
+ de->d_type = d_type;
+ memcpy(de->name, name, namlen);
+ buf->used += reclen;
+
+ return 0;
+}
+
+static int nfsd_buffered_readdir(struct file *file, filldir_t func,
+ struct readdir_cd *cdp, loff_t *offsetp)
+{
+ struct readdir_data buf;
+ struct buffered_dirent *de;
+ int host_err;
+ int size;
+ loff_t offset;
+
+ buf.dirent = (void *)__get_free_page(GFP_KERNEL);
+ if (!buf.dirent)
+ return -ENOMEM;
+
+ offset = *offsetp;
+ cdp->err = nfserr_eof; /* will be cleared on successful read */
+
+ while (1) {
+ unsigned int reclen;
+
+ buf.used = 0;
+ buf.full = 0;
+
+ host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf);
+ if (buf.full)
+ host_err = 0;
+
+ if (host_err < 0)
+ break;
+
+ size = buf.used;
+
+ if (!size)
+ break;
+
+ de = (struct buffered_dirent *)buf.dirent;
+ while (size > 0) {
+ offset = de->offset;
+
+ if (func(cdp, de->name, de->namlen, de->offset,
+ de->ino, de->d_type))
+ goto done;
+
+ if (cdp->err != nfs_ok)
+ goto done;
+
+ reclen = ALIGN(sizeof(*de) + de->namlen,
+ sizeof(u64));
+ size -= reclen;
+ de = (struct buffered_dirent *)((char *)de + reclen);
+ }
+ offset = vfs_llseek(file, 0, SEEK_CUR);
+ if (!buf.full)
+ break;
+ }
+
+ done:
+ free_page((unsigned long)(buf.dirent));
+
+ if (host_err)
+ return nfserrno(host_err);
+
+ *offsetp = offset;
+ return cdp->err;
+}
+
+/*
* Read entries from a directory.
* The NFSv3/4 verifier we ignore for now.
*/
@@ -1823,7 +1935,6 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
struct readdir_cd *cdp, filldir_t func)
{
__be32 err;
- int host_err;
struct file *file;
loff_t offset = *offsetp;
@@ -1837,21 +1948,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
goto out_close;
}
- /*
- * Read the directory entries. This silly loop is necessary because
- * readdir() is not guaranteed to fill up the entire buffer, but
- * may choose to do less.
- */
-
- do {
- cdp->err = nfserr_eof; /* will be cleared on successful read */
- host_err = vfs_readdir(file, func, cdp);
- } while (host_err >=0 && cdp->err == nfs_ok);
- if (host_err)
- err = nfserrno(host_err);
- else
- err = cdp->err;
- *offsetp = vfs_llseek(file, 0, 1);
+ err = nfsd_buffered_readdir(file, func, cdp, offsetp);
if (err == nfserr_eof || err == nfserr_toosmall)
err = nfs_ok; /* can still be found in ->err */
@@ -1866,9 +1963,9 @@ out:
* N.B. After this call fhp needs an fh_put
*/
__be32
-nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
+nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
{
- __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
+ __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
if (!err && vfs_statfs(fhp->fh_dentry,stat))
err = nfserr_io;
return err;
@@ -1966,11 +2063,20 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
void
nfsd_racache_shutdown(void)
{
- if (!raparml)
- return;
+ struct raparms *raparm, *last_raparm;
+ unsigned int i;
+
dprintk("nfsd: freeing readahead buffers.\n");
- kfree(raparml);
- raparml = NULL;
+
+ for (i = 0; i < RAPARM_HASH_SIZE; i++) {
+ raparm = raparm_hash[i].pb_head;
+ while(raparm) {
+ last_raparm = raparm;
+ raparm = raparm->p_next;
+ kfree(last_raparm);
+ }
+ raparm_hash[i].pb_head = NULL;
+ }
}
/*
* Initialize readahead param cache
@@ -1981,35 +2087,38 @@ nfsd_racache_init(int cache_size)
int i;
int j = 0;
int nperbucket;
+ struct raparms **raparm = NULL;
- if (raparml)
+ if (raparm_hash[0].pb_head)
return 0;
- if (cache_size < 2*RAPARM_HASH_SIZE)
- cache_size = 2*RAPARM_HASH_SIZE;
- raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL);
-
- if (!raparml) {
- printk(KERN_WARNING
- "nfsd: Could not allocate memory read-ahead cache.\n");
- return -ENOMEM;
- }
+ nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
+ if (nperbucket < 2)
+ nperbucket = 2;
+ cache_size = nperbucket * RAPARM_HASH_SIZE;
dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
- for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
- raparm_hash[i].pb_head = NULL;
+
+ for (i = 0; i < RAPARM_HASH_SIZE; i++) {
spin_lock_init(&raparm_hash[i].pb_lock);
- }
- nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
- for (i = 0; i < cache_size - 1; i++) {
- if (i % nperbucket == 0)
- raparm_hash[j++].pb_head = raparml + i;
- if (i % nperbucket < nperbucket-1)
- raparml[i].p_next = raparml + i + 1;
+
+ raparm = &raparm_hash[i].pb_head;
+ for (j = 0; j < nperbucket; j++) {
+ *raparm = kzalloc(sizeof(struct raparms), GFP_KERNEL);
+ if (!*raparm)
+ goto out_nomem;
+ raparm = &(*raparm)->p_next;
+ }
+ *raparm = NULL;
}
nfsdstats.ra_size = cache_size;
return 0;
+
+out_nomem:
+ dprintk("nfsd: kmalloc failed, freeing readahead buffers\n");
+ nfsd_racache_shutdown();
+ return -ENOMEM;
}
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
OpenPOWER on IntegriCloud