aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2012-10-09 15:20:05 -0400
committerThomas Gleixner <tglx@linutronix.de>2012-10-09 15:20:05 -0400
commitdb8c246937713e60b7628661ccc187eeb81f2bae (patch)
tree6351e8bca23eef40fce85396d1c6f6cfffbd4b66 /fs/nfsd
parentc5f66e99b7cb091e3d51ae8e8156892e8feb7fa3 (diff)
parent28f2b02bc581ffc835bc1691b18d03f62fcf0395 (diff)
Merge branch 'fortglx/3.7/time' of git://git.linaro.org/people/jstultz/linux into timers/core
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c10
-rw-r--r--fs/nfsd/netns.h4
-rw-r--r--fs/nfsd/nfs4callback.c5
-rw-r--r--fs/nfsd/nfs4idmap.c4
-rw-r--r--fs/nfsd/nfs4proc.c18
-rw-r--r--fs/nfsd/nfs4recover.c9
-rw-r--r--fs/nfsd/nfs4state.c201
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c8
-rw-r--r--fs/nfsd/nfsd.h13
-rw-r--r--fs/nfsd/nfsfh.c1
-rw-r--r--fs/nfsd/nfsproc.c9
-rw-r--r--fs/nfsd/nfssvc.c24
-rw-r--r--fs/nfsd/state.h6
-rw-r--r--fs/nfsd/vfs.c103
-rw-r--r--fs/nfsd/vfs.h11
16 files changed, 247 insertions, 181 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index ba233499b9a..a3946cf13fc 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -398,7 +398,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
398 int migrated, i, err; 398 int migrated, i, err;
399 399
400 /* listsize */ 400 /* listsize */
401 err = get_int(mesg, &fsloc->locations_count); 401 err = get_uint(mesg, &fsloc->locations_count);
402 if (err) 402 if (err)
403 return err; 403 return err;
404 if (fsloc->locations_count > MAX_FS_LOCATIONS) 404 if (fsloc->locations_count > MAX_FS_LOCATIONS)
@@ -456,7 +456,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
456 return -EINVAL; 456 return -EINVAL;
457 457
458 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { 458 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
459 err = get_int(mesg, &f->pseudoflavor); 459 err = get_uint(mesg, &f->pseudoflavor);
460 if (err) 460 if (err)
461 return err; 461 return err;
462 /* 462 /*
@@ -465,7 +465,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
465 * problem at export time instead of when a client fails 465 * problem at export time instead of when a client fails
466 * to authenticate. 466 * to authenticate.
467 */ 467 */
468 err = get_int(mesg, &f->flags); 468 err = get_uint(mesg, &f->flags);
469 if (err) 469 if (err)
470 return err; 470 return err;
471 /* Only some flags are allowed to differ between flavors: */ 471 /* Only some flags are allowed to differ between flavors: */
@@ -929,7 +929,7 @@ struct svc_export *
929rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) 929rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
930{ 930{
931 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 931 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
932 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 932 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
933 struct cache_detail *cd = nn->svc_export_cache; 933 struct cache_detail *cd = nn->svc_export_cache;
934 934
935 if (rqstp->rq_client == NULL) 935 if (rqstp->rq_client == NULL)
@@ -960,7 +960,7 @@ struct svc_export *
960rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) 960rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
961{ 961{
962 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 962 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
963 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 963 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
964 struct cache_detail *cd = nn->svc_export_cache; 964 struct cache_detail *cd = nn->svc_export_cache;
965 965
966 if (rqstp->rq_client == NULL) 966 if (rqstp->rq_client == NULL)
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 39365636b24..65c2431ea32 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -34,6 +34,10 @@ struct nfsd_net {
34 34
35 struct cache_detail *idtoname_cache; 35 struct cache_detail *idtoname_cache;
36 struct cache_detail *nametoid_cache; 36 struct cache_detail *nametoid_cache;
37
38 struct lock_manager nfsd4_manager;
39 bool grace_ended;
40 time_t boot_time;
37}; 41};
38 42
39extern int nfsd_net_id; 43extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index a5fd6b982f2..4c7bd35b187 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -651,12 +651,12 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
651 651
652 if (clp->cl_minorversion == 0) { 652 if (clp->cl_minorversion == 0) {
653 if (!clp->cl_cred.cr_principal && 653 if (!clp->cl_cred.cr_principal &&
654 (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) 654 (clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5))
655 return -EINVAL; 655 return -EINVAL;
656 args.client_name = clp->cl_cred.cr_principal; 656 args.client_name = clp->cl_cred.cr_principal;
657 args.prognumber = conn->cb_prog, 657 args.prognumber = conn->cb_prog,
658 args.protocol = XPRT_TRANSPORT_TCP; 658 args.protocol = XPRT_TRANSPORT_TCP;
659 args.authflavor = clp->cl_flavor; 659 args.authflavor = clp->cl_cred.cr_flavor;
660 clp->cl_cb_ident = conn->cb_ident; 660 clp->cl_cb_ident = conn->cb_ident;
661 } else { 661 } else {
662 if (!conn->cb_xprt) 662 if (!conn->cb_xprt)
@@ -756,7 +756,6 @@ static void do_probe_callback(struct nfs4_client *clp)
756 */ 756 */
757void nfsd4_probe_callback(struct nfs4_client *clp) 757void nfsd4_probe_callback(struct nfs4_client *clp)
758{ 758{
759 /* XXX: atomicity? Also, should we be using cl_flags? */
760 clp->cl_cb_state = NFSD4_CB_UNKNOWN; 759 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
761 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); 760 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
762 do_probe_callback(clp); 761 do_probe_callback(clp);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index dae36f1dee9..fdc91a6fc9c 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -546,7 +546,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
546 .type = type, 546 .type = type,
547 }; 547 };
548 int ret; 548 int ret;
549 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 549 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
550 550
551 if (namelen + 1 > sizeof(key.name)) 551 if (namelen + 1 > sizeof(key.name))
552 return nfserr_badowner; 552 return nfserr_badowner;
@@ -571,7 +571,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
571 .type = type, 571 .type = type,
572 }; 572 };
573 int ret; 573 int ret;
574 struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 574 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
575 575
576 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 576 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
577 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 577 ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 987e719fbae..c9c1c0a2541 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -354,10 +354,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
354 /* Openowner is now set, so sequence id will get bumped. Now we need 354 /* Openowner is now set, so sequence id will get bumped. Now we need
355 * these checks before we do any creates: */ 355 * these checks before we do any creates: */
356 status = nfserr_grace; 356 status = nfserr_grace;
357 if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 357 if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
358 goto out; 358 goto out;
359 status = nfserr_no_grace; 359 status = nfserr_no_grace;
360 if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 360 if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
361 goto out; 361 goto out;
362 362
363 switch (open->op_claim_type) { 363 switch (open->op_claim_type) {
@@ -686,7 +686,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
686 686
687 nfs4_lock_state(); 687 nfs4_lock_state();
688 /* check stateid */ 688 /* check stateid */
689 if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid, 689 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
690 cstate, &read->rd_stateid,
690 RD_STATE, &read->rd_filp))) { 691 RD_STATE, &read->rd_filp))) {
691 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 692 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
692 goto out; 693 goto out;
@@ -741,7 +742,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
741{ 742{
742 __be32 status; 743 __be32 status;
743 744
744 if (locks_in_grace()) 745 if (locks_in_grace(SVC_NET(rqstp)))
745 return nfserr_grace; 746 return nfserr_grace;
746 status = nfsd_unlink(rqstp, &cstate->current_fh, 0, 747 status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
747 remove->rm_name, remove->rm_namelen); 748 remove->rm_name, remove->rm_namelen);
@@ -760,8 +761,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
760 761
761 if (!cstate->save_fh.fh_dentry) 762 if (!cstate->save_fh.fh_dentry)
762 return status; 763 return status;
763 if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags 764 if (locks_in_grace(SVC_NET(rqstp)) &&
764 & NFSEXP_NOSUBTREECHECK)) 765 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
765 return nfserr_grace; 766 return nfserr_grace;
766 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, 767 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
767 rename->rn_snamelen, &cstate->current_fh, 768 rename->rn_snamelen, &cstate->current_fh,
@@ -845,7 +846,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
845 846
846 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 847 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
847 nfs4_lock_state(); 848 nfs4_lock_state();
848 status = nfs4_preprocess_stateid_op(cstate, 849 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
849 &setattr->sa_stateid, WR_STATE, NULL); 850 &setattr->sa_stateid, WR_STATE, NULL);
850 nfs4_unlock_state(); 851 nfs4_unlock_state();
851 if (status) { 852 if (status) {
@@ -890,7 +891,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
890 return nfserr_inval; 891 return nfserr_inval;
891 892
892 nfs4_lock_state(); 893 nfs4_lock_state();
893 status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp); 894 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
895 cstate, stateid, WR_STATE, &filp);
894 if (filp) 896 if (filp)
895 get_file(filp); 897 get_file(filp);
896 nfs4_unlock_state(); 898 nfs4_unlock_state();
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5ff0b7b9fc0..43295d45cc2 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -154,6 +154,10 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
154 if (status < 0) 154 if (status < 0)
155 return; 155 return;
156 156
157 status = mnt_want_write_file(rec_file);
158 if (status)
159 return;
160
157 dir = rec_file->f_path.dentry; 161 dir = rec_file->f_path.dentry;
158 /* lock the parent */ 162 /* lock the parent */
159 mutex_lock(&dir->d_inode->i_mutex); 163 mutex_lock(&dir->d_inode->i_mutex);
@@ -173,11 +177,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
173 * as well be forgiving and just succeed silently. 177 * as well be forgiving and just succeed silently.
174 */ 178 */
175 goto out_put; 179 goto out_put;
176 status = mnt_want_write_file(rec_file);
177 if (status)
178 goto out_put;
179 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); 180 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU);
180 mnt_drop_write_file(rec_file);
181out_put: 181out_put:
182 dput(dentry); 182 dput(dentry);
183out_unlock: 183out_unlock:
@@ -189,6 +189,7 @@ out_unlock:
189 " (err %d); please check that %s exists" 189 " (err %d); please check that %s exists"
190 " and is writeable", status, 190 " and is writeable", status,
191 user_recovery_dirname); 191 user_recovery_dirname);
192 mnt_drop_write_file(rec_file);
192 nfs4_reset_creds(original_cred); 193 nfs4_reset_creds(original_cred);
193} 194}
194 195
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 94effd5bc4a..cc894eda385 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -38,18 +38,21 @@
38#include <linux/namei.h> 38#include <linux/namei.h>
39#include <linux/swap.h> 39#include <linux/swap.h>
40#include <linux/pagemap.h> 40#include <linux/pagemap.h>
41#include <linux/ratelimit.h>
41#include <linux/sunrpc/svcauth_gss.h> 42#include <linux/sunrpc/svcauth_gss.h>
42#include <linux/sunrpc/clnt.h> 43#include <linux/sunrpc/clnt.h>
43#include "xdr4.h" 44#include "xdr4.h"
44#include "vfs.h" 45#include "vfs.h"
45#include "current_stateid.h" 46#include "current_stateid.h"
47#include "fault_inject.h"
48
49#include "netns.h"
46 50
47#define NFSDDBG_FACILITY NFSDDBG_PROC 51#define NFSDDBG_FACILITY NFSDDBG_PROC
48 52
49/* Globals */ 53/* Globals */
50time_t nfsd4_lease = 90; /* default lease time */ 54time_t nfsd4_lease = 90; /* default lease time */
51time_t nfsd4_grace = 90; 55time_t nfsd4_grace = 90;
52static time_t boot_time;
53 56
54#define all_ones {{~0,~0},~0} 57#define all_ones {{~0,~0},~0}
55static const stateid_t one_stateid = { 58static const stateid_t one_stateid = {
@@ -862,6 +865,11 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses,
862 if (ret) 865 if (ret)
863 /* oops; xprt is already down: */ 866 /* oops; xprt is already down: */
864 nfsd4_conn_lost(&conn->cn_xpt_user); 867 nfsd4_conn_lost(&conn->cn_xpt_user);
868 if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN &&
869 dir & NFS4_CDFC4_BACK) {
870 /* callback channel may be back up */
871 nfsd4_probe_callback(ses->se_client);
872 }
865 return nfs_ok; 873 return nfs_ok;
866} 874}
867 875
@@ -1047,12 +1055,12 @@ renew_client(struct nfs4_client *clp)
1047 1055
1048/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ 1056/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
1049static int 1057static int
1050STALE_CLIENTID(clientid_t *clid) 1058STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
1051{ 1059{
1052 if (clid->cl_boot == boot_time) 1060 if (clid->cl_boot == nn->boot_time)
1053 return 0; 1061 return 0;
1054 dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", 1062 dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
1055 clid->cl_boot, clid->cl_id, boot_time); 1063 clid->cl_boot, clid->cl_id, nn->boot_time);
1056 return 1; 1064 return 1;
1057} 1065}
1058 1066
@@ -1215,7 +1223,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
1215 return true; 1223 return true;
1216} 1224}
1217 1225
1218static int 1226static bool
1219same_creds(struct svc_cred *cr1, struct svc_cred *cr2) 1227same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1220{ 1228{
1221 if ((cr1->cr_flavor != cr2->cr_flavor) 1229 if ((cr1->cr_flavor != cr2->cr_flavor)
@@ -1227,14 +1235,15 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1227 return true; 1235 return true;
1228 if (!cr1->cr_principal || !cr2->cr_principal) 1236 if (!cr1->cr_principal || !cr2->cr_principal)
1229 return false; 1237 return false;
1230 return 0 == strcmp(cr1->cr_principal, cr1->cr_principal); 1238 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
1231} 1239}
1232 1240
1233static void gen_clid(struct nfs4_client *clp) 1241static void gen_clid(struct nfs4_client *clp)
1234{ 1242{
1235 static u32 current_clientid = 1; 1243 static u32 current_clientid = 1;
1244 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
1236 1245
1237 clp->cl_clientid.cl_boot = boot_time; 1246 clp->cl_clientid.cl_boot = nn->boot_time;
1238 clp->cl_clientid.cl_id = current_clientid++; 1247 clp->cl_clientid.cl_id = current_clientid++;
1239} 1248}
1240 1249
@@ -2217,8 +2226,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2217 nfs4_verifier confirm = setclientid_confirm->sc_confirm; 2226 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
2218 clientid_t * clid = &setclientid_confirm->sc_clientid; 2227 clientid_t * clid = &setclientid_confirm->sc_clientid;
2219 __be32 status; 2228 __be32 status;
2229 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
2220 2230
2221 if (STALE_CLIENTID(clid)) 2231 if (STALE_CLIENTID(clid, nn))
2222 return nfserr_stale_clientid; 2232 return nfserr_stale_clientid;
2223 nfs4_lock_state(); 2233 nfs4_lock_state();
2224 2234
@@ -2577,8 +2587,9 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2577 unsigned int strhashval; 2587 unsigned int strhashval;
2578 struct nfs4_openowner *oo = NULL; 2588 struct nfs4_openowner *oo = NULL;
2579 __be32 status; 2589 __be32 status;
2590 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
2580 2591
2581 if (STALE_CLIENTID(&open->op_clientid)) 2592 if (STALE_CLIENTID(&open->op_clientid, nn))
2582 return nfserr_stale_clientid; 2593 return nfserr_stale_clientid;
2583 /* 2594 /*
2584 * In case we need it later, after we've already created the 2595 * In case we need it later, after we've already created the
@@ -2876,7 +2887,8 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
2876 * Attempt to hand out a delegation. 2887 * Attempt to hand out a delegation.
2877 */ 2888 */
2878static void 2889static void
2879nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_stateid *stp) 2890nfs4_open_delegation(struct net *net, struct svc_fh *fh,
2891 struct nfsd4_open *open, struct nfs4_ol_stateid *stp)
2880{ 2892{
2881 struct nfs4_delegation *dp; 2893 struct nfs4_delegation *dp;
2882 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 2894 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
@@ -2897,7 +2909,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
2897 case NFS4_OPEN_CLAIM_NULL: 2909 case NFS4_OPEN_CLAIM_NULL:
2898 /* Let's not give out any delegations till everyone's 2910 /* Let's not give out any delegations till everyone's
2899 * had the chance to reclaim theirs.... */ 2911 * had the chance to reclaim theirs.... */
2900 if (locks_in_grace()) 2912 if (locks_in_grace(net))
2901 goto out; 2913 goto out;
2902 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) 2914 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
2903 goto out; 2915 goto out;
@@ -3007,14 +3019,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
3007 status = nfs4_get_vfs_file(rqstp, fp, current_fh, open); 3019 status = nfs4_get_vfs_file(rqstp, fp, current_fh, open);
3008 if (status) 3020 if (status)
3009 goto out; 3021 goto out;
3022 status = nfsd4_truncate(rqstp, current_fh, open);
3023 if (status)
3024 goto out;
3010 stp = open->op_stp; 3025 stp = open->op_stp;
3011 open->op_stp = NULL; 3026 open->op_stp = NULL;
3012 init_open_stateid(stp, fp, open); 3027 init_open_stateid(stp, fp, open);
3013 status = nfsd4_truncate(rqstp, current_fh, open);
3014 if (status) {
3015 release_open_stateid(stp);
3016 goto out;
3017 }
3018 } 3028 }
3019 update_stateid(&stp->st_stid.sc_stateid); 3029 update_stateid(&stp->st_stid.sc_stateid);
3020 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3030 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
@@ -3033,7 +3043,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
3033 * Attempt to hand out a delegation. No error return, because the 3043 * Attempt to hand out a delegation. No error return, because the
3034 * OPEN succeeds even if we fail. 3044 * OPEN succeeds even if we fail.
3035 */ 3045 */
3036 nfs4_open_delegation(current_fh, open, stp); 3046 nfs4_open_delegation(SVC_NET(rqstp), current_fh, open, stp);
3037nodeleg: 3047nodeleg:
3038 status = nfs_ok; 3048 status = nfs_ok;
3039 3049
@@ -3087,12 +3097,13 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3087{ 3097{
3088 struct nfs4_client *clp; 3098 struct nfs4_client *clp;
3089 __be32 status; 3099 __be32 status;
3100 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
3090 3101
3091 nfs4_lock_state(); 3102 nfs4_lock_state();
3092 dprintk("process_renew(%08x/%08x): starting\n", 3103 dprintk("process_renew(%08x/%08x): starting\n",
3093 clid->cl_boot, clid->cl_id); 3104 clid->cl_boot, clid->cl_id);
3094 status = nfserr_stale_clientid; 3105 status = nfserr_stale_clientid;
3095 if (STALE_CLIENTID(clid)) 3106 if (STALE_CLIENTID(clid, nn))
3096 goto out; 3107 goto out;
3097 clp = find_confirmed_client(clid); 3108 clp = find_confirmed_client(clid);
3098 status = nfserr_expired; 3109 status = nfserr_expired;
@@ -3111,22 +3122,19 @@ out:
3111 return status; 3122 return status;
3112} 3123}
3113 3124
3114static struct lock_manager nfsd4_manager = {
3115};
3116
3117static bool grace_ended;
3118
3119static void 3125static void
3120nfsd4_end_grace(void) 3126nfsd4_end_grace(struct net *net)
3121{ 3127{
3128 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
3129
3122 /* do nothing if grace period already ended */ 3130 /* do nothing if grace period already ended */
3123 if (grace_ended) 3131 if (nn->grace_ended)
3124 return; 3132 return;
3125 3133
3126 dprintk("NFSD: end of grace period\n"); 3134 dprintk("NFSD: end of grace period\n");
3127 grace_ended = true; 3135 nn->grace_ended = true;
3128 nfsd4_record_grace_done(&init_net, boot_time); 3136 nfsd4_record_grace_done(net, nn->boot_time);
3129 locks_end_grace(&nfsd4_manager); 3137 locks_end_grace(&nn->nfsd4_manager);
3130 /* 3138 /*
3131 * Now that every NFSv4 client has had the chance to recover and 3139 * Now that every NFSv4 client has had the chance to recover and
3132 * to see the (possibly new, possibly shorter) lease time, we 3140 * to see the (possibly new, possibly shorter) lease time, we
@@ -3149,7 +3157,7 @@ nfs4_laundromat(void)
3149 nfs4_lock_state(); 3157 nfs4_lock_state();
3150 3158
3151 dprintk("NFSD: laundromat service - starting\n"); 3159 dprintk("NFSD: laundromat service - starting\n");
3152 nfsd4_end_grace(); 3160 nfsd4_end_grace(&init_net);
3153 INIT_LIST_HEAD(&reaplist); 3161 INIT_LIST_HEAD(&reaplist);
3154 spin_lock(&client_lock); 3162 spin_lock(&client_lock);
3155 list_for_each_safe(pos, next, &client_lru) { 3163 list_for_each_safe(pos, next, &client_lru) {
@@ -3231,9 +3239,9 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *s
3231} 3239}
3232 3240
3233static int 3241static int
3234STALE_STATEID(stateid_t *stateid) 3242STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn)
3235{ 3243{
3236 if (stateid->si_opaque.so_clid.cl_boot == boot_time) 3244 if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time)
3237 return 0; 3245 return 0;
3238 dprintk("NFSD: stale stateid " STATEID_FMT "!\n", 3246 dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
3239 STATEID_VAL(stateid)); 3247 STATEID_VAL(stateid));
@@ -3273,11 +3281,11 @@ out:
3273} 3281}
3274 3282
3275static inline __be32 3283static inline __be32
3276check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) 3284check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags)
3277{ 3285{
3278 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 3286 if (ONE_STATEID(stateid) && (flags & RD_STATE))
3279 return nfs_ok; 3287 return nfs_ok;
3280 else if (locks_in_grace()) { 3288 else if (locks_in_grace(net)) {
3281 /* Answer in remaining cases depends on existence of 3289 /* Answer in remaining cases depends on existence of
3282 * conflicting state; so we must wait out the grace period. */ 3290 * conflicting state; so we must wait out the grace period. */
3283 return nfserr_grace; 3291 return nfserr_grace;
@@ -3294,9 +3302,9 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
3294 * that are not able to provide mandatory locking. 3302 * that are not able to provide mandatory locking.
3295 */ 3303 */
3296static inline int 3304static inline int
3297grace_disallows_io(struct inode *inode) 3305grace_disallows_io(struct net *net, struct inode *inode)
3298{ 3306{
3299 return locks_in_grace() && mandatory_lock(inode); 3307 return locks_in_grace(net) && mandatory_lock(inode);
3300} 3308}
3301 3309
3302/* Returns true iff a is later than b: */ 3310/* Returns true iff a is later than b: */
@@ -3333,18 +3341,26 @@ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_s
3333 return nfserr_old_stateid; 3341 return nfserr_old_stateid;
3334} 3342}
3335 3343
3336__be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) 3344static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3337{ 3345{
3338 struct nfs4_stid *s; 3346 struct nfs4_stid *s;
3339 struct nfs4_ol_stateid *ols; 3347 struct nfs4_ol_stateid *ols;
3340 __be32 status; 3348 __be32 status;
3341 3349
3342 if (STALE_STATEID(stateid)) 3350 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3343 return nfserr_stale_stateid; 3351 return nfserr_bad_stateid;
3344 3352 /* Client debugging aid. */
3353 if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
3354 char addr_str[INET6_ADDRSTRLEN];
3355 rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
3356 sizeof(addr_str));
3357 pr_warn_ratelimited("NFSD: client %s testing state ID "
3358 "with incorrect client ID\n", addr_str);
3359 return nfserr_bad_stateid;
3360 }
3345 s = find_stateid(cl, stateid); 3361 s = find_stateid(cl, stateid);
3346 if (!s) 3362 if (!s)
3347 return nfserr_stale_stateid; 3363 return nfserr_bad_stateid;
3348 status = check_stateid_generation(stateid, &s->sc_stateid, 1); 3364 status = check_stateid_generation(stateid, &s->sc_stateid, 1);
3349 if (status) 3365 if (status)
3350 return status; 3366 return status;
@@ -3360,10 +3376,11 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3360static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) 3376static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
3361{ 3377{
3362 struct nfs4_client *cl; 3378 struct nfs4_client *cl;
3379 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
3363 3380
3364 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3381 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3365 return nfserr_bad_stateid; 3382 return nfserr_bad_stateid;
3366 if (STALE_STATEID(stateid)) 3383 if (STALE_STATEID(stateid, nn))
3367 return nfserr_stale_stateid; 3384 return nfserr_stale_stateid;
3368 cl = find_confirmed_client(&stateid->si_opaque.so_clid); 3385 cl = find_confirmed_client(&stateid->si_opaque.so_clid);
3369 if (!cl) 3386 if (!cl)
@@ -3379,7 +3396,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
3379* Checks for stateid operations 3396* Checks for stateid operations
3380*/ 3397*/
3381__be32 3398__be32
3382nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, 3399nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3383 stateid_t *stateid, int flags, struct file **filpp) 3400 stateid_t *stateid, int flags, struct file **filpp)
3384{ 3401{
3385 struct nfs4_stid *s; 3402 struct nfs4_stid *s;
@@ -3392,11 +3409,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
3392 if (filpp) 3409 if (filpp)
3393 *filpp = NULL; 3410 *filpp = NULL;
3394 3411
3395 if (grace_disallows_io(ino)) 3412 if (grace_disallows_io(net, ino))
3396 return nfserr_grace; 3413 return nfserr_grace;
3397 3414
3398 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3415 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3399 return check_special_stateids(current_fh, stateid, flags); 3416 return check_special_stateids(net, current_fh, stateid, flags);
3400 3417
3401 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); 3418 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s);
3402 if (status) 3419 if (status)
@@ -3463,7 +3480,8 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3463 3480
3464 nfs4_lock_state(); 3481 nfs4_lock_state();
3465 list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list) 3482 list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
3466 stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid); 3483 stateid->ts_id_status =
3484 nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
3467 nfs4_unlock_state(); 3485 nfs4_unlock_state();
3468 3486
3469 return nfs_ok; 3487 return nfs_ok;
@@ -3750,12 +3768,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3750 nfsd4_close_open_stateid(stp); 3768 nfsd4_close_open_stateid(stp);
3751 oo->oo_last_closed_stid = stp; 3769 oo->oo_last_closed_stid = stp;
3752 3770
3753 /* place unused nfs4_stateowners on so_close_lru list to be 3771 if (list_empty(&oo->oo_owner.so_stateids)) {
3754 * released by the laundromat service after the lease period 3772 if (cstate->minorversion) {
3755 * to enable us to handle CLOSE replay 3773 release_openowner(oo);
3756 */ 3774 cstate->replay_owner = NULL;
3757 if (list_empty(&oo->oo_owner.so_stateids)) 3775 } else {
3758 move_to_close_lru(oo); 3776 /*
3777 * In the 4.0 case we need to keep the owners around a
3778 * little while to handle CLOSE replay.
3779 */
3780 if (list_empty(&oo->oo_owner.so_stateids))
3781 move_to_close_lru(oo);
3782 }
3783 }
3759out: 3784out:
3760 if (!cstate->replay_owner) 3785 if (!cstate->replay_owner)
3761 nfs4_unlock_state(); 3786 nfs4_unlock_state();
@@ -4027,6 +4052,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4027 bool new_state = false; 4052 bool new_state = false;
4028 int lkflg; 4053 int lkflg;
4029 int err; 4054 int err;
4055 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4030 4056
4031 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 4057 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
4032 (long long) lock->lk_offset, 4058 (long long) lock->lk_offset,
@@ -4044,11 +4070,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4044 nfs4_lock_state(); 4070 nfs4_lock_state();
4045 4071
4046 if (lock->lk_is_new) { 4072 if (lock->lk_is_new) {
4047 /*
4048 * Client indicates that this is a new lockowner.
4049 * Use open owner and open stateid to create lock owner and
4050 * lock stateid.
4051 */
4052 struct nfs4_ol_stateid *open_stp = NULL; 4073 struct nfs4_ol_stateid *open_stp = NULL;
4053 4074
4054 if (nfsd4_has_session(cstate)) 4075 if (nfsd4_has_session(cstate))
@@ -4058,7 +4079,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4058 sizeof(clientid_t)); 4079 sizeof(clientid_t));
4059 4080
4060 status = nfserr_stale_clientid; 4081 status = nfserr_stale_clientid;
4061 if (STALE_CLIENTID(&lock->lk_new_clientid)) 4082 if (STALE_CLIENTID(&lock->lk_new_clientid, nn))
4062 goto out; 4083 goto out;
4063 4084
4064 /* validate and update open stateid and open seqid */ 4085 /* validate and update open stateid and open seqid */
@@ -4075,17 +4096,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4075 goto out; 4096 goto out;
4076 status = lookup_or_create_lock_state(cstate, open_stp, lock, 4097 status = lookup_or_create_lock_state(cstate, open_stp, lock,
4077 &lock_stp, &new_state); 4098 &lock_stp, &new_state);
4078 if (status) 4099 } else
4079 goto out;
4080 } else {
4081 /* lock (lock owner + lock stateid) already exists */
4082 status = nfs4_preprocess_seqid_op(cstate, 4100 status = nfs4_preprocess_seqid_op(cstate,
4083 lock->lk_old_lock_seqid, 4101 lock->lk_old_lock_seqid,
4084 &lock->lk_old_lock_stateid, 4102 &lock->lk_old_lock_stateid,
4085 NFS4_LOCK_STID, &lock_stp); 4103 NFS4_LOCK_STID, &lock_stp);
4086 if (status) 4104 if (status)
4087 goto out; 4105 goto out;
4088 }
4089 lock_sop = lockowner(lock_stp->st_stateowner); 4106 lock_sop = lockowner(lock_stp->st_stateowner);
4090 4107
4091 lkflg = setlkflg(lock->lk_type); 4108 lkflg = setlkflg(lock->lk_type);
@@ -4094,10 +4111,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4094 goto out; 4111 goto out;
4095 4112
4096 status = nfserr_grace; 4113 status = nfserr_grace;
4097 if (locks_in_grace() && !lock->lk_reclaim) 4114 if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
4098 goto out; 4115 goto out;
4099 status = nfserr_no_grace; 4116 status = nfserr_no_grace;
4100 if (!locks_in_grace() && lock->lk_reclaim) 4117 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
4101 goto out; 4118 goto out;
4102 4119
4103 locks_init_lock(&file_lock); 4120 locks_init_lock(&file_lock);
@@ -4196,8 +4213,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4196 struct file_lock file_lock; 4213 struct file_lock file_lock;
4197 struct nfs4_lockowner *lo; 4214 struct nfs4_lockowner *lo;
4198 __be32 status; 4215 __be32 status;
4216 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4199 4217
4200 if (locks_in_grace()) 4218 if (locks_in_grace(SVC_NET(rqstp)))
4201 return nfserr_grace; 4219 return nfserr_grace;
4202 4220
4203 if (check_lock_length(lockt->lt_offset, lockt->lt_length)) 4221 if (check_lock_length(lockt->lt_offset, lockt->lt_length))
@@ -4206,7 +4224,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4206 nfs4_lock_state(); 4224 nfs4_lock_state();
4207 4225
4208 status = nfserr_stale_clientid; 4226 status = nfserr_stale_clientid;
4209 if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid)) 4227 if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn))
4210 goto out; 4228 goto out;
4211 4229
4212 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) 4230 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
@@ -4355,6 +4373,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4355 struct list_head matches; 4373 struct list_head matches;
4356 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); 4374 unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
4357 __be32 status; 4375 __be32 status;
4376 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
4358 4377
4359 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 4378 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
4360 clid->cl_boot, clid->cl_id); 4379 clid->cl_boot, clid->cl_id);
@@ -4362,7 +4381,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
4362 /* XXX check for lease expiration */ 4381 /* XXX check for lease expiration */
4363 4382
4364 status = nfserr_stale_clientid; 4383 status = nfserr_stale_clientid;
4365 if (STALE_CLIENTID(clid)) 4384 if (STALE_CLIENTID(clid, nn))
4366 return status; 4385 return status;
4367 4386
4368 nfs4_lock_state(); 4387 nfs4_lock_state();
@@ -4564,7 +4583,7 @@ void nfsd_forget_openowners(u64 num)
4564 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4583 printk(KERN_INFO "NFSD: Forgot %d open owners", count);
4565} 4584}
4566 4585
4567int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *)) 4586int nfsd_process_n_delegations(u64 num, struct list_head *list)
4568{ 4587{
4569 int i, count = 0; 4588 int i, count = 0;
4570 struct nfs4_file *fp, *fnext; 4589 struct nfs4_file *fp, *fnext;
@@ -4573,7 +4592,7 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
4573 for (i = 0; i < FILE_HASH_SIZE; i++) { 4592 for (i = 0; i < FILE_HASH_SIZE; i++) {
4574 list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) { 4593 list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) {
4575 list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) { 4594 list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) {
4576 deleg_func(dp); 4595 list_move(&dp->dl_recall_lru, list);
4577 if (++count == num) 4596 if (++count == num)
4578 return count; 4597 return count;
4579 } 4598 }
@@ -4586,9 +4605,16 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
4586void nfsd_forget_delegations(u64 num) 4605void nfsd_forget_delegations(u64 num)
4587{ 4606{
4588 unsigned int count; 4607 unsigned int count;
4608 LIST_HEAD(victims);
4609 struct nfs4_delegation *dp, *dnext;
4610
4611 spin_lock(&recall_lock);
4612 count = nfsd_process_n_delegations(num, &victims);
4613 spin_unlock(&recall_lock);
4589 4614
4590 nfs4_lock_state(); 4615 nfs4_lock_state();
4591 count = nfsd_process_n_delegations(num, unhash_delegation); 4616 list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru)
4617 unhash_delegation(dp);
4592 nfs4_unlock_state(); 4618 nfs4_unlock_state();
4593 4619
4594 printk(KERN_INFO "NFSD: Forgot %d delegations", count); 4620 printk(KERN_INFO "NFSD: Forgot %d delegations", count);
@@ -4597,12 +4623,16 @@ void nfsd_forget_delegations(u64 num)
4597void nfsd_recall_delegations(u64 num) 4623void nfsd_recall_delegations(u64 num)
4598{ 4624{
4599 unsigned int count; 4625 unsigned int count;
4626 LIST_HEAD(victims);
4627 struct nfs4_delegation *dp, *dnext;
4600 4628
4601 nfs4_lock_state();
4602 spin_lock(&recall_lock); 4629 spin_lock(&recall_lock);
4603 count = nfsd_process_n_delegations(num, nfsd_break_one_deleg); 4630 count = nfsd_process_n_delegations(num, &victims);
4631 list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) {
4632 list_del(&dp->dl_recall_lru);
4633 nfsd_break_one_deleg(dp);
4634 }
4604 spin_unlock(&recall_lock); 4635 spin_unlock(&recall_lock);
4605 nfs4_unlock_state();
4606 4636
4607 printk(KERN_INFO "NFSD: Recalled %d delegations", count); 4637 printk(KERN_INFO "NFSD: Recalled %d delegations", count);
4608} 4638}
@@ -4665,6 +4695,8 @@ set_max_delegations(void)
4665int 4695int
4666nfs4_state_start(void) 4696nfs4_state_start(void)
4667{ 4697{
4698 struct net *net = &init_net;
4699 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4668 int ret; 4700 int ret;
4669 4701
4670 /* 4702 /*
@@ -4674,11 +4706,11 @@ nfs4_state_start(void)
4674 * to that instead and then do most of the rest of this on a per-net 4706 * to that instead and then do most of the rest of this on a per-net
4675 * basis. 4707 * basis.
4676 */ 4708 */
4677 get_net(&init_net); 4709 get_net(net);
4678 nfsd4_client_tracking_init(&init_net); 4710 nfsd4_client_tracking_init(net);
4679 boot_time = get_seconds(); 4711 nn->boot_time = get_seconds();
4680 locks_start_grace(&nfsd4_manager); 4712 locks_start_grace(net, &nn->nfsd4_manager);
4681 grace_ended = false; 4713 nn->grace_ended = false;
4682 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 4714 printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
4683 nfsd4_grace); 4715 nfsd4_grace);
4684 ret = set_callback_cred(); 4716 ret = set_callback_cred();
@@ -4700,8 +4732,8 @@ nfs4_state_start(void)
4700out_free_laundry: 4732out_free_laundry:
4701 destroy_workqueue(laundry_wq); 4733 destroy_workqueue(laundry_wq);
4702out_recovery: 4734out_recovery:
4703 nfsd4_client_tracking_exit(&init_net); 4735 nfsd4_client_tracking_exit(net);
4704 put_net(&init_net); 4736 put_net(net);
4705 return ret; 4737 return ret;
4706} 4738}
4707 4739
@@ -4742,9 +4774,12 @@ __nfs4_state_shutdown(void)
4742void 4774void
4743nfs4_state_shutdown(void) 4775nfs4_state_shutdown(void)
4744{ 4776{
4777 struct net *net = &init_net;
4778 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4779
4745 cancel_delayed_work_sync(&laundromat_work); 4780 cancel_delayed_work_sync(&laundromat_work);
4746 destroy_workqueue(laundry_wq); 4781 destroy_workqueue(laundry_wq);
4747 locks_end_grace(&nfsd4_manager); 4782 locks_end_grace(&nn->nfsd4_manager);
4748 nfs4_lock_state(); 4783 nfs4_lock_state();
4749 __nfs4_state_shutdown(); 4784 __nfs4_state_shutdown();
4750 nfs4_unlock_state(); 4785 nfs4_unlock_state();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4949667c84e..6322df36031 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2259,7 +2259,7 @@ out_acl:
2259 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 2259 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
2260 if ((buflen -= 4) < 0) 2260 if ((buflen -= 4) < 0)
2261 goto out_resource; 2261 goto out_resource;
2262 WRITE32(1); 2262 WRITE32(0);
2263 } 2263 }
2264 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 2264 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
2265 if ((buflen -= 4) < 0) 2265 if ((buflen -= 4) < 0)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index c55298ed577..fa49cff5ee6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -673,9 +673,7 @@ static ssize_t __write_ports_addfd(char *buf)
673 673
674 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 674 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
675 if (err < 0) { 675 if (err < 0) {
676 if (nfsd_serv->sv_nrthreads == 1) 676 nfsd_destroy(net);
677 svc_shutdown_net(nfsd_serv, net);
678 svc_destroy(nfsd_serv);
679 return err; 677 return err;
680 } 678 }
681 679
@@ -744,9 +742,7 @@ out_close:
744 svc_xprt_put(xprt); 742 svc_xprt_put(xprt);
745 } 743 }
746out_err: 744out_err:
747 if (nfsd_serv->sv_nrthreads == 1) 745 nfsd_destroy(net);
748 svc_shutdown_net(nfsd_serv, net);
749 svc_destroy(nfsd_serv);
750 return err; 746 return err;
751} 747}
752 748
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 1671429ffa6..2244222368a 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -72,6 +72,19 @@ int nfsd_nrthreads(void);
72int nfsd_nrpools(void); 72int nfsd_nrpools(void);
73int nfsd_get_nrthreads(int n, int *); 73int nfsd_get_nrthreads(int n, int *);
74int nfsd_set_nrthreads(int n, int *); 74int nfsd_set_nrthreads(int n, int *);
75int nfsd_pool_stats_open(struct inode *, struct file *);
76int nfsd_pool_stats_release(struct inode *, struct file *);
77
78static inline void nfsd_destroy(struct net *net)
79{
80 int destroy = (nfsd_serv->sv_nrthreads == 1);
81
82 if (destroy)
83 svc_shutdown_net(nfsd_serv, net);
84 svc_destroy(nfsd_serv);
85 if (destroy)
86 nfsd_serv = NULL;
87}
75 88
76#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 89#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
77#ifdef CONFIG_NFSD_V2_ACL 90#ifdef CONFIG_NFSD_V2_ACL
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index cc793005a87..032af381b3a 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -635,6 +635,7 @@ fh_put(struct svc_fh *fhp)
635 fhp->fh_post_saved = 0; 635 fhp->fh_post_saved = 0;
636#endif 636#endif
637 } 637 }
638 fh_drop_write(fhp);
638 if (exp) { 639 if (exp) {
639 exp_put(exp); 640 exp_put(exp);
640 fhp->fh_export = NULL; 641 fhp->fh_export = NULL;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index e15dc45fc5e..aad6d457b9e 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -196,6 +196,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
196 struct dentry *dchild; 196 struct dentry *dchild;
197 int type, mode; 197 int type, mode;
198 __be32 nfserr; 198 __be32 nfserr;
199 int hosterr;
199 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); 200 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);
200 201
201 dprintk("nfsd: CREATE %s %.*s\n", 202 dprintk("nfsd: CREATE %s %.*s\n",
@@ -214,6 +215,12 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
214 nfserr = nfserr_exist; 215 nfserr = nfserr_exist;
215 if (isdotent(argp->name, argp->len)) 216 if (isdotent(argp->name, argp->len))
216 goto done; 217 goto done;
218 hosterr = fh_want_write(dirfhp);
219 if (hosterr) {
220 nfserr = nfserrno(hosterr);
221 goto done;
222 }
223
217 fh_lock_nested(dirfhp, I_MUTEX_PARENT); 224 fh_lock_nested(dirfhp, I_MUTEX_PARENT);
218 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); 225 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
219 if (IS_ERR(dchild)) { 226 if (IS_ERR(dchild)) {
@@ -330,7 +337,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
330out_unlock: 337out_unlock:
331 /* We don't really need to unlock, as fh_put does it. */ 338 /* We don't really need to unlock, as fh_put does it. */
332 fh_unlock(dirfhp); 339 fh_unlock(dirfhp);
333 340 fh_drop_write(dirfhp);
334done: 341done:
335 fh_put(dirfhp); 342 fh_put(dirfhp);
336 return nfsd_return_dirop(nfserr, resp); 343 return nfsd_return_dirop(nfserr, resp);
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ee709fc8f58..240473cb708 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -254,8 +254,6 @@ static void nfsd_shutdown(void)
254 254
255static void nfsd_last_thread(struct svc_serv *serv, struct net *net) 255static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
256{ 256{
257 /* When last nfsd thread exits we need to do some clean-up */
258 nfsd_serv = NULL;
259 nfsd_shutdown(); 257 nfsd_shutdown();
260 258
261 svc_rpcb_cleanup(serv, net); 259 svc_rpcb_cleanup(serv, net);
@@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void)
332int nfsd_create_serv(void) 330int nfsd_create_serv(void)
333{ 331{
334 int error; 332 int error;
333 struct net *net = current->nsproxy->net_ns;
335 334
336 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 335 WARN_ON(!mutex_is_locked(&nfsd_mutex));
337 if (nfsd_serv) { 336 if (nfsd_serv) {
@@ -346,7 +345,7 @@ int nfsd_create_serv(void)
346 if (nfsd_serv == NULL) 345 if (nfsd_serv == NULL)
347 return -ENOMEM; 346 return -ENOMEM;
348 347
349 error = svc_bind(nfsd_serv, current->nsproxy->net_ns); 348 error = svc_bind(nfsd_serv, net);
350 if (error < 0) { 349 if (error < 0) {
351 svc_destroy(nfsd_serv); 350 svc_destroy(nfsd_serv);
352 return error; 351 return error;
@@ -427,11 +426,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
427 if (err) 426 if (err)
428 break; 427 break;
429 } 428 }
430 429 nfsd_destroy(net);
431 if (nfsd_serv->sv_nrthreads == 1)
432 svc_shutdown_net(nfsd_serv, net);
433 svc_destroy(nfsd_serv);
434
435 return err; 430 return err;
436} 431}
437 432
@@ -478,9 +473,7 @@ out_shutdown:
478 if (error < 0 && !nfsd_up_before) 473 if (error < 0 && !nfsd_up_before)
479 nfsd_shutdown(); 474 nfsd_shutdown();
480out_destroy: 475out_destroy:
481 if (nfsd_serv->sv_nrthreads == 1) 476 nfsd_destroy(net); /* Release server */
482 svc_shutdown_net(nfsd_serv, net);
483 svc_destroy(nfsd_serv); /* Release server */
484out: 477out:
485 mutex_unlock(&nfsd_mutex); 478 mutex_unlock(&nfsd_mutex);
486 return error; 479 return error;
@@ -563,12 +556,13 @@ nfsd(void *vrqstp)
563 nfsdstats.th_cnt --; 556 nfsdstats.th_cnt --;
564 557
565out: 558out:
566 if (rqstp->rq_server->sv_nrthreads == 1) 559 rqstp->rq_server = NULL;
567 svc_shutdown_net(rqstp->rq_server, &init_net);
568 560
569 /* Release the thread */ 561 /* Release the thread */
570 svc_exit_thread(rqstp); 562 svc_exit_thread(rqstp);
571 563
564 nfsd_destroy(&init_net);
565
572 /* Release module */ 566 /* Release module */
573 mutex_unlock(&nfsd_mutex); 567 mutex_unlock(&nfsd_mutex);
574 module_put_and_exit(0); 568 module_put_and_exit(0);
@@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file)
682 676
683 mutex_lock(&nfsd_mutex); 677 mutex_lock(&nfsd_mutex);
684 /* this function really, really should have been called svc_put() */ 678 /* this function really, really should have been called svc_put() */
685 if (nfsd_serv->sv_nrthreads == 1) 679 nfsd_destroy(net);
686 svc_shutdown_net(nfsd_serv, net);
687 svc_destroy(nfsd_serv);
688 mutex_unlock(&nfsd_mutex); 680 mutex_unlock(&nfsd_mutex);
689 return ret; 681 return ret;
690} 682}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 849091e16ea..22bd0a66c35 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -231,7 +231,6 @@ struct nfs4_client {
231 nfs4_verifier cl_verifier; /* generated by client */ 231 nfs4_verifier cl_verifier; /* generated by client */
232 time_t cl_time; /* time of last lease renewal */ 232 time_t cl_time; /* time of last lease renewal */
233 struct sockaddr_storage cl_addr; /* client ipaddress */ 233 struct sockaddr_storage cl_addr; /* client ipaddress */
234 u32 cl_flavor; /* setclientid pseudoflavor */
235 struct svc_cred cl_cred; /* setclientid principal */ 234 struct svc_cred cl_cred; /* setclientid principal */
236 clientid_t cl_clientid; /* generated by server */ 235 clientid_t cl_clientid; /* generated by server */
237 nfs4_verifier cl_confirm; /* generated by server */ 236 nfs4_verifier cl_confirm; /* generated by server */
@@ -450,8 +449,10 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
450#define WR_STATE 0x00000020 449#define WR_STATE 0x00000020
451 450
452struct nfsd4_compound_state; 451struct nfsd4_compound_state;
452struct nfsd_net;
453 453
454extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, 454extern __be32 nfs4_preprocess_stateid_op(struct net *net,
455 struct nfsd4_compound_state *cstate,
455 stateid_t *stateid, int flags, struct file **filp); 456 stateid_t *stateid, int flags, struct file **filp);
456extern void nfs4_lock_state(void); 457extern void nfs4_lock_state(void);
457extern void nfs4_unlock_state(void); 458extern void nfs4_unlock_state(void);
@@ -475,7 +476,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
475extern int nfs4_client_to_reclaim(const char *name); 476extern int nfs4_client_to_reclaim(const char *name);
476extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); 477extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
477extern void release_session_client(struct nfsd4_session *); 478extern void release_session_client(struct nfsd4_session *);
478extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
479extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); 479extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
480 480
481/* nfs4recover operations */ 481/* nfs4recover operations */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c8bd9c3be7f..a9269f142cc 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -745,7 +745,7 @@ __be32
745nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, 745nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
746 int may_flags, struct file **filp) 746 int may_flags, struct file **filp)
747{ 747{
748 struct dentry *dentry; 748 struct path path;
749 struct inode *inode; 749 struct inode *inode;
750 int flags = O_RDONLY|O_LARGEFILE; 750 int flags = O_RDONLY|O_LARGEFILE;
751 __be32 err; 751 __be32 err;
@@ -757,13 +757,22 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
757 * If we get here, then the client has already done an "open", 757 * If we get here, then the client has already done an "open",
758 * and (hopefully) checked permission - so allow OWNER_OVERRIDE 758 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
759 * in case a chmod has now revoked permission. 759 * in case a chmod has now revoked permission.
760 *
761 * Arguably we should also allow the owner override for
762 * directories, but we never have and it doesn't seem to have
763 * caused anyone a problem. If we were to change this, note
764 * also that our filldir callbacks would need a variant of
765 * lookup_one_len that doesn't check permissions.
760 */ 766 */
761 err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE); 767 if (type == S_IFREG)
768 may_flags |= NFSD_MAY_OWNER_OVERRIDE;
769 err = fh_verify(rqstp, fhp, type, may_flags);
762 if (err) 770 if (err)
763 goto out; 771 goto out;
764 772
765 dentry = fhp->fh_dentry; 773 path.mnt = fhp->fh_export->ex_path.mnt;
766 inode = dentry->d_inode; 774 path.dentry = fhp->fh_dentry;
775 inode = path.dentry->d_inode;
767 776
768 /* Disallow write access to files with the append-only bit set 777 /* Disallow write access to files with the append-only bit set
769 * or any access when mandatory locking enabled 778 * or any access when mandatory locking enabled
@@ -792,8 +801,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
792 else 801 else
793 flags = O_WRONLY|O_LARGEFILE; 802 flags = O_WRONLY|O_LARGEFILE;
794 } 803 }
795 *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), 804 *filp = dentry_open(&path, flags, current_cred());
796 flags, current_cred());
797 if (IS_ERR(*filp)) 805 if (IS_ERR(*filp))
798 host_err = PTR_ERR(*filp); 806 host_err = PTR_ERR(*filp);
799 else { 807 else {
@@ -1276,6 +1284,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1276 * If it has, the parent directory should already be locked. 1284 * If it has, the parent directory should already be locked.
1277 */ 1285 */
1278 if (!resfhp->fh_dentry) { 1286 if (!resfhp->fh_dentry) {
1287 host_err = fh_want_write(fhp);
1288 if (host_err)
1289 goto out_nfserr;
1290
1279 /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */ 1291 /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
1280 fh_lock_nested(fhp, I_MUTEX_PARENT); 1292 fh_lock_nested(fhp, I_MUTEX_PARENT);
1281 dchild = lookup_one_len(fname, dentry, flen); 1293 dchild = lookup_one_len(fname, dentry, flen);
@@ -1319,17 +1331,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1319 goto out; 1331 goto out;
1320 } 1332 }
1321 1333
1322 host_err = fh_want_write(fhp);
1323 if (host_err)
1324 goto out_nfserr;
1325
1326 /* 1334 /*
1327 * Get the dir op function pointer. 1335 * Get the dir op function pointer.
1328 */ 1336 */
1329 err = 0; 1337 err = 0;
1338 host_err = 0;
1330 switch (type) { 1339 switch (type) {
1331 case S_IFREG: 1340 case S_IFREG:
1332 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); 1341 host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
1333 if (!host_err) 1342 if (!host_err)
1334 nfsd_check_ignore_resizing(iap); 1343 nfsd_check_ignore_resizing(iap);
1335 break; 1344 break;
@@ -1343,10 +1352,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1343 host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); 1352 host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
1344 break; 1353 break;
1345 } 1354 }
1346 if (host_err < 0) { 1355 if (host_err < 0)
1347 fh_drop_write(fhp);
1348 goto out_nfserr; 1356 goto out_nfserr;
1349 }
1350 1357
1351 err = nfsd_create_setattr(rqstp, resfhp, iap); 1358 err = nfsd_create_setattr(rqstp, resfhp, iap);
1352 1359
@@ -1358,7 +1365,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1358 err2 = nfserrno(commit_metadata(fhp)); 1365 err2 = nfserrno(commit_metadata(fhp));
1359 if (err2) 1366 if (err2)
1360 err = err2; 1367 err = err2;
1361 fh_drop_write(fhp);
1362 /* 1368 /*
1363 * Update the file handle to get the new inode info. 1369 * Update the file handle to get the new inode info.
1364 */ 1370 */
@@ -1417,6 +1423,11 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1417 err = nfserr_notdir; 1423 err = nfserr_notdir;
1418 if (!dirp->i_op->lookup) 1424 if (!dirp->i_op->lookup)
1419 goto out; 1425 goto out;
1426
1427 host_err = fh_want_write(fhp);
1428 if (host_err)
1429 goto out_nfserr;
1430
1420 fh_lock_nested(fhp, I_MUTEX_PARENT); 1431 fh_lock_nested(fhp, I_MUTEX_PARENT);
1421 1432
1422 /* 1433 /*
@@ -1449,9 +1460,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1449 v_atime = verifier[1]&0x7fffffff; 1460 v_atime = verifier[1]&0x7fffffff;
1450 } 1461 }
1451 1462
1452 host_err = fh_want_write(fhp);
1453 if (host_err)
1454 goto out_nfserr;
1455 if (dchild->d_inode) { 1463 if (dchild->d_inode) {
1456 err = 0; 1464 err = 0;
1457 1465
@@ -1492,7 +1500,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1492 goto out; 1500 goto out;
1493 } 1501 }
1494 1502
1495 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); 1503 host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
1496 if (host_err < 0) { 1504 if (host_err < 0) {
1497 fh_drop_write(fhp); 1505 fh_drop_write(fhp);
1498 goto out_nfserr; 1506 goto out_nfserr;
@@ -1522,7 +1530,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1522 if (!err) 1530 if (!err)
1523 err = nfserrno(commit_metadata(fhp)); 1531 err = nfserrno(commit_metadata(fhp));
1524 1532
1525 fh_drop_write(fhp);
1526 /* 1533 /*
1527 * Update the filehandle to get the new inode info. 1534 * Update the filehandle to get the new inode info.
1528 */ 1535 */
@@ -1533,6 +1540,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1533 fh_unlock(fhp); 1540 fh_unlock(fhp);
1534 if (dchild && !IS_ERR(dchild)) 1541 if (dchild && !IS_ERR(dchild))
1535 dput(dchild); 1542 dput(dchild);
1543 fh_drop_write(fhp);
1536 return err; 1544 return err;
1537 1545
1538 out_nfserr: 1546 out_nfserr:
@@ -1613,6 +1621,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1613 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); 1621 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1614 if (err) 1622 if (err)
1615 goto out; 1623 goto out;
1624
1625 host_err = fh_want_write(fhp);
1626 if (host_err)
1627 goto out_nfserr;
1628
1616 fh_lock(fhp); 1629 fh_lock(fhp);
1617 dentry = fhp->fh_dentry; 1630 dentry = fhp->fh_dentry;
1618 dnew = lookup_one_len(fname, dentry, flen); 1631 dnew = lookup_one_len(fname, dentry, flen);
@@ -1620,10 +1633,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1620 if (IS_ERR(dnew)) 1633 if (IS_ERR(dnew))
1621 goto out_nfserr; 1634 goto out_nfserr;
1622 1635
1623 host_err = fh_want_write(fhp);
1624 if (host_err)
1625 goto out_nfserr;
1626
1627 if (unlikely(path[plen] != 0)) { 1636 if (unlikely(path[plen] != 0)) {
1628 char *path_alloced = kmalloc(plen+1, GFP_KERNEL); 1637 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1629 if (path_alloced == NULL) 1638 if (path_alloced == NULL)
@@ -1683,6 +1692,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1683 if (isdotent(name, len)) 1692 if (isdotent(name, len))
1684 goto out; 1693 goto out;
1685 1694
1695 host_err = fh_want_write(tfhp);
1696 if (host_err) {
1697 err = nfserrno(host_err);
1698 goto out;
1699 }
1700
1686 fh_lock_nested(ffhp, I_MUTEX_PARENT); 1701 fh_lock_nested(ffhp, I_MUTEX_PARENT);
1687 ddir = ffhp->fh_dentry; 1702 ddir = ffhp->fh_dentry;
1688 dirp = ddir->d_inode; 1703 dirp = ddir->d_inode;
@@ -1694,18 +1709,13 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1694 1709
1695 dold = tfhp->fh_dentry; 1710 dold = tfhp->fh_dentry;
1696 1711
1697 host_err = fh_want_write(tfhp);
1698 if (host_err) {
1699 err = nfserrno(host_err);
1700 goto out_dput;
1701 }
1702 err = nfserr_noent; 1712 err = nfserr_noent;
1703 if (!dold->d_inode) 1713 if (!dold->d_inode)
1704 goto out_drop_write; 1714 goto out_dput;
1705 host_err = nfsd_break_lease(dold->d_inode); 1715 host_err = nfsd_break_lease(dold->d_inode);
1706 if (host_err) { 1716 if (host_err) {
1707 err = nfserrno(host_err); 1717 err = nfserrno(host_err);
1708 goto out_drop_write; 1718 goto out_dput;
1709 } 1719 }
1710 host_err = vfs_link(dold, dirp, dnew); 1720 host_err = vfs_link(dold, dirp, dnew);
1711 if (!host_err) { 1721 if (!host_err) {
@@ -1718,12 +1728,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1718 else 1728 else
1719 err = nfserrno(host_err); 1729 err = nfserrno(host_err);
1720 } 1730 }
1721out_drop_write:
1722 fh_drop_write(tfhp);
1723out_dput: 1731out_dput:
1724 dput(dnew); 1732 dput(dnew);
1725out_unlock: 1733out_unlock:
1726 fh_unlock(ffhp); 1734 fh_unlock(ffhp);
1735 fh_drop_write(tfhp);
1727out: 1736out:
1728 return err; 1737 return err;
1729 1738
@@ -1766,6 +1775,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1766 if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) 1775 if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
1767 goto out; 1776 goto out;
1768 1777
1778 host_err = fh_want_write(ffhp);
1779 if (host_err) {
1780 err = nfserrno(host_err);
1781 goto out;
1782 }
1783
1769 /* cannot use fh_lock as we need deadlock protective ordering 1784 /* cannot use fh_lock as we need deadlock protective ordering
1770 * so do it by hand */ 1785 * so do it by hand */
1771 trap = lock_rename(tdentry, fdentry); 1786 trap = lock_rename(tdentry, fdentry);
@@ -1796,17 +1811,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1796 host_err = -EXDEV; 1811 host_err = -EXDEV;
1797 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) 1812 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
1798 goto out_dput_new; 1813 goto out_dput_new;
1799 host_err = fh_want_write(ffhp);
1800 if (host_err)
1801 goto out_dput_new;
1802 1814
1803 host_err = nfsd_break_lease(odentry->d_inode); 1815 host_err = nfsd_break_lease(odentry->d_inode);
1804 if (host_err) 1816 if (host_err)
1805 goto out_drop_write; 1817 goto out_dput_new;
1806 if (ndentry->d_inode) { 1818 if (ndentry->d_inode) {
1807 host_err = nfsd_break_lease(ndentry->d_inode); 1819 host_err = nfsd_break_lease(ndentry->d_inode);
1808 if (host_err) 1820 if (host_err)
1809 goto out_drop_write; 1821 goto out_dput_new;
1810 } 1822 }
1811 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1823 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1812 if (!host_err) { 1824 if (!host_err) {
@@ -1814,8 +1826,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1814 if (!host_err) 1826 if (!host_err)
1815 host_err = commit_metadata(ffhp); 1827 host_err = commit_metadata(ffhp);
1816 } 1828 }
1817out_drop_write:
1818 fh_drop_write(ffhp);
1819 out_dput_new: 1829 out_dput_new:
1820 dput(ndentry); 1830 dput(ndentry);
1821 out_dput_old: 1831 out_dput_old:
@@ -1831,6 +1841,7 @@ out_drop_write:
1831 fill_post_wcc(tfhp); 1841 fill_post_wcc(tfhp);
1832 unlock_rename(tdentry, fdentry); 1842 unlock_rename(tdentry, fdentry);
1833 ffhp->fh_locked = tfhp->fh_locked = 0; 1843 ffhp->fh_locked = tfhp->fh_locked = 0;
1844 fh_drop_write(ffhp);
1834 1845
1835out: 1846out:
1836 return err; 1847 return err;
@@ -1856,6 +1867,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1856 if (err) 1867 if (err)
1857 goto out; 1868 goto out;
1858 1869
1870 host_err = fh_want_write(fhp);
1871 if (host_err)
1872 goto out_nfserr;
1873
1859 fh_lock_nested(fhp, I_MUTEX_PARENT); 1874 fh_lock_nested(fhp, I_MUTEX_PARENT);
1860 dentry = fhp->fh_dentry; 1875 dentry = fhp->fh_dentry;
1861 dirp = dentry->d_inode; 1876 dirp = dentry->d_inode;
@@ -1874,21 +1889,15 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1874 if (!type) 1889 if (!type)
1875 type = rdentry->d_inode->i_mode & S_IFMT; 1890 type = rdentry->d_inode->i_mode & S_IFMT;
1876 1891
1877 host_err = fh_want_write(fhp);
1878 if (host_err)
1879 goto out_put;
1880
1881 host_err = nfsd_break_lease(rdentry->d_inode); 1892 host_err = nfsd_break_lease(rdentry->d_inode);
1882 if (host_err) 1893 if (host_err)
1883 goto out_drop_write; 1894 goto out_put;
1884 if (type != S_IFDIR) 1895 if (type != S_IFDIR)
1885 host_err = vfs_unlink(dirp, rdentry); 1896 host_err = vfs_unlink(dirp, rdentry);
1886 else 1897 else
1887 host_err = vfs_rmdir(dirp, rdentry); 1898 host_err = vfs_rmdir(dirp, rdentry);
1888 if (!host_err) 1899 if (!host_err)
1889 host_err = commit_metadata(fhp); 1900 host_err = commit_metadata(fhp);
1890out_drop_write:
1891 fh_drop_write(fhp);
1892out_put: 1901out_put:
1893 dput(rdentry); 1902 dput(rdentry);
1894 1903
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index ec0611b2b73..359594c393d 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -110,12 +110,19 @@ int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
110 110
111static inline int fh_want_write(struct svc_fh *fh) 111static inline int fh_want_write(struct svc_fh *fh)
112{ 112{
113 return mnt_want_write(fh->fh_export->ex_path.mnt); 113 int ret = mnt_want_write(fh->fh_export->ex_path.mnt);
114
115 if (!ret)
116 fh->fh_want_write = 1;
117 return ret;
114} 118}
115 119
116static inline void fh_drop_write(struct svc_fh *fh) 120static inline void fh_drop_write(struct svc_fh *fh)
117{ 121{
118 mnt_drop_write(fh->fh_export->ex_path.mnt); 122 if (fh->fh_want_write) {
123 fh->fh_want_write = 0;
124 mnt_drop_write(fh->fh_export->ex_path.mnt);
125 }
119} 126}
120 127
121#endif /* LINUX_NFSD_VFS_H */ 128#endif /* LINUX_NFSD_VFS_H */