aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/clnt4xdr.c2
-rw-r--r--fs/lockd/clntxdr.c2
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/lockd/svcsubs.c3
-rw-r--r--fs/lockd/xdr.c2
-rw-r--r--fs/nfsd/export.h109
-rw-r--r--fs/nfsd/fault_inject.c15
-rw-r--r--fs/nfsd/nfs4acl.c1
-rw-r--r--fs/nfsd/nfs4proc.c11
-rw-r--r--fs/nfsd/nfs4state.c84
-rw-r--r--fs/nfsd/nfsctl.c1
-rw-r--r--fs/nfsd/nfsd.h17
-rw-r--r--fs/nfsd/nfsfh.c20
-rw-r--r--fs/nfsd/nfsfh.h59
-rw-r--r--fs/nfsd/state.h3
-rw-r--r--fs/nfsd/stats.c1
-rw-r--r--fs/nfsd/stats.h43
-rw-r--r--fs/nfsd/vfs.c18
18 files changed, 275 insertions, 118 deletions
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 00ec0b9c94d1..d3e40db28930 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -14,6 +14,8 @@
14#include <linux/sunrpc/stats.h> 14#include <linux/sunrpc/stats.h>
15#include <linux/lockd/lockd.h> 15#include <linux/lockd/lockd.h>
16 16
17#include <uapi/linux/nfs3.h>
18
17#define NLMDBG_FACILITY NLMDBG_XDR 19#define NLMDBG_FACILITY NLMDBG_XDR
18 20
19#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 21#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 9a55797a1cd4..3e9f7874b975 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -15,6 +15,8 @@
15#include <linux/sunrpc/stats.h> 15#include <linux/sunrpc/stats.h>
16#include <linux/lockd/lockd.h> 16#include <linux/lockd/lockd.h>
17 17
18#include <uapi/linux/nfs2.h>
19
18#define NLMDBG_FACILITY NLMDBG_XDR 20#define NLMDBG_FACILITY NLMDBG_XDR
19 21
20#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 22#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 6bf06a07f3e0..2b431f7266c3 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -622,8 +622,8 @@ static int __init init_nlm(void)
622err_pernet: 622err_pernet:
623#ifdef CONFIG_SYSCTL 623#ifdef CONFIG_SYSCTL
624 unregister_sysctl_table(nlm_sysctl_table); 624 unregister_sysctl_table(nlm_sysctl_table);
625#endif
626err_sysctl: 625err_sysctl:
626#endif
627 return err; 627 return err;
628} 628}
629 629
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dc5c75930f0f..b6f3b84b6e99 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -14,12 +14,11 @@
14#include <linux/mutex.h> 14#include <linux/mutex.h>
15#include <linux/sunrpc/svc.h> 15#include <linux/sunrpc/svc.h>
16#include <linux/sunrpc/addr.h> 16#include <linux/sunrpc/addr.h>
17#include <linux/nfsd/nfsfh.h>
18#include <linux/nfsd/export.h>
19#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
20#include <linux/lockd/share.h> 18#include <linux/lockd/share.h>
21#include <linux/module.h> 19#include <linux/module.h>
22#include <linux/mount.h> 20#include <linux/mount.h>
21#include <uapi/linux/nfs2.h>
23 22
24#define NLMDBG_FACILITY NLMDBG_SVCSUBS 23#define NLMDBG_FACILITY NLMDBG_SVCSUBS
25 24
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index 964666c68a86..9340e7e10ef6 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -16,6 +16,8 @@
16#include <linux/sunrpc/stats.h> 16#include <linux/sunrpc/stats.h>
17#include <linux/lockd/lockd.h> 17#include <linux/lockd/lockd.h>
18 18
19#include <uapi/linux/nfs2.h>
20
19#define NLMDBG_FACILITY NLMDBG_XDR 21#define NLMDBG_FACILITY NLMDBG_XDR
20 22
21 23
diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
new file mode 100644
index 000000000000..d7939a62a0ae
--- /dev/null
+++ b/fs/nfsd/export.h
@@ -0,0 +1,109 @@
1/*
2 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
3 */
4#ifndef NFSD_EXPORT_H
5#define NFSD_EXPORT_H
6
7#include <linux/sunrpc/cache.h>
8#include <uapi/linux/nfsd/export.h>
9
10struct knfsd_fh;
11struct svc_fh;
12struct svc_rqst;
13
14/*
15 * FS Locations
16 */
17
18#define MAX_FS_LOCATIONS 128
19
20struct nfsd4_fs_location {
21 char *hosts; /* colon separated list of hosts */
22 char *path; /* slash separated list of path components */
23};
24
25struct nfsd4_fs_locations {
26 uint32_t locations_count;
27 struct nfsd4_fs_location *locations;
28/* If we're not actually serving this data ourselves (only providing a
29 * list of replicas that do serve it) then we set "migrated": */
30 int migrated;
31};
32
33/*
34 * We keep an array of pseudoflavors with the export, in order from most
35 * to least preferred. For the foreseeable future, we don't expect more
36 * than the eight pseudoflavors null, unix, krb5, krb5i, krb5p, skpm3,
37 * spkm3i, and spkm3p (and using all 8 at once should be rare).
38 */
39#define MAX_SECINFO_LIST 8
40
41struct exp_flavor_info {
42 u32 pseudoflavor;
43 u32 flags;
44};
45
46struct svc_export {
47 struct cache_head h;
48 struct auth_domain * ex_client;
49 int ex_flags;
50 struct path ex_path;
51 kuid_t ex_anon_uid;
52 kgid_t ex_anon_gid;
53 int ex_fsid;
54 unsigned char * ex_uuid; /* 16 byte fsid */
55 struct nfsd4_fs_locations ex_fslocs;
56 int ex_nflavors;
57 struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST];
58 struct cache_detail *cd;
59};
60
61/* an "export key" (expkey) maps a filehandlefragement to an
62 * svc_export for a given client. There can be several per export,
63 * for the different fsid types.
64 */
65struct svc_expkey {
66 struct cache_head h;
67
68 struct auth_domain * ek_client;
69 int ek_fsidtype;
70 u32 ek_fsid[6];
71
72 struct path ek_path;
73};
74
75#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
76#define EX_NOHIDE(exp) ((exp)->ex_flags & NFSEXP_NOHIDE)
77#define EX_WGATHER(exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
78
79int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp);
80__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
81
82/*
83 * Function declarations
84 */
85int nfsd_export_init(struct net *);
86void nfsd_export_shutdown(struct net *);
87void nfsd_export_flush(struct net *);
88struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
89 struct path *);
90struct svc_export * rqst_exp_parent(struct svc_rqst *,
91 struct path *);
92struct svc_export * rqst_find_fsidzero_export(struct svc_rqst *);
93int exp_rootfh(struct net *, struct auth_domain *,
94 char *path, struct knfsd_fh *, int maxsize);
95__be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *);
96__be32 nfserrno(int errno);
97
98static inline void exp_put(struct svc_export *exp)
99{
100 cache_put(&exp->h, exp->cd);
101}
102
103static inline void exp_get(struct svc_export *exp)
104{
105 cache_get(&exp->h);
106}
107struct svc_export * rqst_exp_find(struct svc_rqst *, int, u32 *);
108
109#endif /* NFSD_EXPORT_H */
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c
index d620e7f81429..2ed05c3cd43d 100644
--- a/fs/nfsd/fault_inject.c
+++ b/fs/nfsd/fault_inject.c
@@ -97,25 +97,14 @@ static ssize_t fault_inject_read(struct file *file, char __user *buf,
97{ 97{
98 static u64 val; 98 static u64 val;
99 char read_buf[25]; 99 char read_buf[25];
100 size_t size, ret; 100 size_t size;
101 loff_t pos = *ppos; 101 loff_t pos = *ppos;
102 102
103 if (!pos) 103 if (!pos)
104 nfsd_inject_get(file_inode(file)->i_private, &val); 104 nfsd_inject_get(file_inode(file)->i_private, &val);
105 size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val); 105 size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);
106 106
107 if (pos < 0) 107 return simple_read_from_buffer(buf, len, ppos, read_buf, size);
108 return -EINVAL;
109 if (pos >= size || !len)
110 return 0;
111 if (len > size - pos)
112 len = size - pos;
113 ret = copy_to_user(buf, read_buf + pos, len);
114 if (ret == len)
115 return -EFAULT;
116 len -= ret;
117 *ppos = pos + len;
118 return len;
119} 108}
120 109
121static ssize_t fault_inject_write(struct file *file, const char __user *buf, 110static ssize_t fault_inject_write(struct file *file, const char __user *buf,
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index f66c66b9f182..7c7c02554a81 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -36,7 +36,6 @@
36 36
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/nfs_fs.h> 38#include <linux/nfs_fs.h>
39#include <linux/export.h>
40#include "nfsfh.h" 39#include "nfsfh.h"
41#include "nfsd.h" 40#include "nfsd.h"
42#include "acl.h" 41#include "acl.h"
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index d543222babf3..ac837783b37d 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -786,7 +786,6 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
786 if (!nfsd4_last_compound_op(rqstp)) 786 if (!nfsd4_last_compound_op(rqstp))
787 rqstp->rq_splice_ok = false; 787 rqstp->rq_splice_ok = false;
788 788
789 nfs4_lock_state();
790 /* check stateid */ 789 /* check stateid */
791 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 790 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
792 cstate, &read->rd_stateid, 791 cstate, &read->rd_stateid,
@@ -794,11 +793,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
794 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 793 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
795 goto out; 794 goto out;
796 } 795 }
797 if (read->rd_filp)
798 get_file(read->rd_filp);
799 status = nfs_ok; 796 status = nfs_ok;
800out: 797out:
801 nfs4_unlock_state();
802 read->rd_rqstp = rqstp; 798 read->rd_rqstp = rqstp;
803 read->rd_fhp = &cstate->current_fh; 799 read->rd_fhp = &cstate->current_fh;
804 return status; 800 return status;
@@ -937,10 +933,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
937 int err; 933 int err;
938 934
939 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 935 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
940 nfs4_lock_state();
941 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, 936 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
942 &setattr->sa_stateid, WR_STATE, NULL); 937 &setattr->sa_stateid, WR_STATE, NULL);
943 nfs4_unlock_state();
944 if (status) { 938 if (status) {
945 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); 939 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
946 return status; 940 return status;
@@ -1006,17 +1000,12 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1006 if (write->wr_offset >= OFFSET_MAX) 1000 if (write->wr_offset >= OFFSET_MAX)
1007 return nfserr_inval; 1001 return nfserr_inval;
1008 1002
1009 nfs4_lock_state();
1010 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 1003 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
1011 cstate, stateid, WR_STATE, &filp); 1004 cstate, stateid, WR_STATE, &filp);
1012 if (status) { 1005 if (status) {
1013 nfs4_unlock_state();
1014 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 1006 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
1015 return status; 1007 return status;
1016 } 1008 }
1017 if (filp)
1018 get_file(filp);
1019 nfs4_unlock_state();
1020 1009
1021 cnt = write->wr_buflen; 1010 cnt = write->wr_buflen;
1022 write->wr_how_written = write->wr_stable_how; 1011 write->wr_how_written = write->wr_stable_how;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9a77a5a21557..a037627ce5c7 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -418,6 +418,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
418 418
419static void nfs4_put_deleg_lease(struct nfs4_file *fp) 419static void nfs4_put_deleg_lease(struct nfs4_file *fp)
420{ 420{
421 if (!fp->fi_lease)
422 return;
421 if (atomic_dec_and_test(&fp->fi_delegees)) { 423 if (atomic_dec_and_test(&fp->fi_delegees)) {
422 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); 424 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
423 fp->fi_lease = NULL; 425 fp->fi_lease = NULL;
@@ -440,9 +442,11 @@ unhash_delegation(struct nfs4_delegation *dp)
440 list_del_init(&dp->dl_perfile); 442 list_del_init(&dp->dl_perfile);
441 list_del_init(&dp->dl_recall_lru); 443 list_del_init(&dp->dl_recall_lru);
442 spin_unlock(&recall_lock); 444 spin_unlock(&recall_lock);
443 nfs4_put_deleg_lease(dp->dl_file); 445 if (dp->dl_file) {
444 put_nfs4_file(dp->dl_file); 446 nfs4_put_deleg_lease(dp->dl_file);
445 dp->dl_file = NULL; 447 put_nfs4_file(dp->dl_file);
448 dp->dl_file = NULL;
449 }
446} 450}
447 451
448 452
@@ -645,6 +649,12 @@ static void unhash_lockowner(struct nfs4_lockowner *lo)
645 } 649 }
646} 650}
647 651
652static void nfs4_free_lockowner(struct nfs4_lockowner *lo)
653{
654 kfree(lo->lo_owner.so_owner.data);
655 kmem_cache_free(lockowner_slab, lo);
656}
657
648static void release_lockowner(struct nfs4_lockowner *lo) 658static void release_lockowner(struct nfs4_lockowner *lo)
649{ 659{
650 unhash_lockowner(lo); 660 unhash_lockowner(lo);
@@ -699,6 +709,12 @@ static void release_last_closed_stateid(struct nfs4_openowner *oo)
699 } 709 }
700} 710}
701 711
712static void nfs4_free_openowner(struct nfs4_openowner *oo)
713{
714 kfree(oo->oo_owner.so_owner.data);
715 kmem_cache_free(openowner_slab, oo);
716}
717
702static void release_openowner(struct nfs4_openowner *oo) 718static void release_openowner(struct nfs4_openowner *oo)
703{ 719{
704 unhash_openowner(oo); 720 unhash_openowner(oo);
@@ -1093,7 +1109,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
1093 return clp; 1109 return clp;
1094} 1110}
1095 1111
1096static inline void 1112static void
1097free_client(struct nfs4_client *clp) 1113free_client(struct nfs4_client *clp)
1098{ 1114{
1099 struct nfsd_net __maybe_unused *nn = net_generic(clp->net, nfsd_net_id); 1115 struct nfsd_net __maybe_unused *nn = net_generic(clp->net, nfsd_net_id);
@@ -2553,18 +2569,6 @@ out_nomem:
2553 return -ENOMEM; 2569 return -ENOMEM;
2554} 2570}
2555 2571
2556void nfs4_free_openowner(struct nfs4_openowner *oo)
2557{
2558 kfree(oo->oo_owner.so_owner.data);
2559 kmem_cache_free(openowner_slab, oo);
2560}
2561
2562void nfs4_free_lockowner(struct nfs4_lockowner *lo)
2563{
2564 kfree(lo->lo_owner.so_owner.data);
2565 kmem_cache_free(lockowner_slab, lo);
2566}
2567
2568static void init_nfs4_replay(struct nfs4_replay *rp) 2572static void init_nfs4_replay(struct nfs4_replay *rp)
2569{ 2573{
2570 rp->rp_status = nfserr_serverfault; 2574 rp->rp_status = nfserr_serverfault;
@@ -3060,33 +3064,22 @@ out_free:
3060 3064
3061static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) 3065static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
3062{ 3066{
3063 int status;
3064
3065 if (fp->fi_had_conflict) 3067 if (fp->fi_had_conflict)
3066 return -EAGAIN; 3068 return -EAGAIN;
3067 get_nfs4_file(fp); 3069 get_nfs4_file(fp);
3068 dp->dl_file = fp; 3070 dp->dl_file = fp;
3069 if (!fp->fi_lease) { 3071 if (!fp->fi_lease)
3070 status = nfs4_setlease(dp); 3072 return nfs4_setlease(dp);
3071 if (status)
3072 goto out_free;
3073 return 0;
3074 }
3075 spin_lock(&recall_lock); 3073 spin_lock(&recall_lock);
3074 atomic_inc(&fp->fi_delegees);
3076 if (fp->fi_had_conflict) { 3075 if (fp->fi_had_conflict) {
3077 spin_unlock(&recall_lock); 3076 spin_unlock(&recall_lock);
3078 status = -EAGAIN; 3077 return -EAGAIN;
3079 goto out_free;
3080 } 3078 }
3081 atomic_inc(&fp->fi_delegees);
3082 list_add(&dp->dl_perfile, &fp->fi_delegations); 3079 list_add(&dp->dl_perfile, &fp->fi_delegations);
3083 spin_unlock(&recall_lock); 3080 spin_unlock(&recall_lock);
3084 list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); 3081 list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
3085 return 0; 3082 return 0;
3086out_free:
3087 put_nfs4_file(fp);
3088 dp->dl_file = fp;
3089 return status;
3090} 3083}
3091 3084
3092static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) 3085static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
@@ -3173,8 +3166,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3173 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; 3166 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
3174 return; 3167 return;
3175out_free: 3168out_free:
3176 remove_stid(&dp->dl_stid); 3169 destroy_delegation(dp);
3177 nfs4_put_delegation(dp);
3178out_no_deleg: 3170out_no_deleg:
3179 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; 3171 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
3180 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && 3172 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
@@ -3654,6 +3646,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3654 struct svc_fh *current_fh = &cstate->current_fh; 3646 struct svc_fh *current_fh = &cstate->current_fh;
3655 struct inode *ino = current_fh->fh_dentry->d_inode; 3647 struct inode *ino = current_fh->fh_dentry->d_inode;
3656 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 3648 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
3649 struct file *file = NULL;
3657 __be32 status; 3650 __be32 status;
3658 3651
3659 if (filpp) 3652 if (filpp)
@@ -3665,10 +3658,12 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3665 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3658 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3666 return check_special_stateids(net, current_fh, stateid, flags); 3659 return check_special_stateids(net, current_fh, stateid, flags);
3667 3660
3661 nfs4_lock_state();
3662
3668 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, 3663 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
3669 &s, cstate->minorversion, nn); 3664 &s, cstate->minorversion, nn);
3670 if (status) 3665 if (status)
3671 return status; 3666 goto out;
3672 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); 3667 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
3673 if (status) 3668 if (status)
3674 goto out; 3669 goto out;
@@ -3679,8 +3674,8 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3679 if (status) 3674 if (status)
3680 goto out; 3675 goto out;
3681 if (filpp) { 3676 if (filpp) {
3682 *filpp = dp->dl_file->fi_deleg_file; 3677 file = dp->dl_file->fi_deleg_file;
3683 if (!*filpp) { 3678 if (!file) {
3684 WARN_ON_ONCE(1); 3679 WARN_ON_ONCE(1);
3685 status = nfserr_serverfault; 3680 status = nfserr_serverfault;
3686 goto out; 3681 goto out;
@@ -3701,16 +3696,20 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3701 goto out; 3696 goto out;
3702 if (filpp) { 3697 if (filpp) {
3703 if (flags & RD_STATE) 3698 if (flags & RD_STATE)
3704 *filpp = find_readable_file(stp->st_file); 3699 file = find_readable_file(stp->st_file);
3705 else 3700 else
3706 *filpp = find_writeable_file(stp->st_file); 3701 file = find_writeable_file(stp->st_file);
3707 } 3702 }
3708 break; 3703 break;
3709 default: 3704 default:
3710 return nfserr_bad_stateid; 3705 status = nfserr_bad_stateid;
3706 goto out;
3711 } 3707 }
3712 status = nfs_ok; 3708 status = nfs_ok;
3709 if (file)
3710 *filpp = get_file(file);
3713out: 3711out:
3712 nfs4_unlock_state();
3714 return status; 3713 return status;
3715} 3714}
3716 3715
@@ -4983,13 +4982,6 @@ struct nfs4_client *nfsd_find_client(struct sockaddr_storage *addr, size_t addr_
4983 4982
4984#endif /* CONFIG_NFSD_FAULT_INJECTION */ 4983#endif /* CONFIG_NFSD_FAULT_INJECTION */
4985 4984
4986/* initialization to perform at module load time: */
4987
4988void
4989nfs4_state_init(void)
4990{
4991}
4992
4993/* 4985/*
4994 * Since the lifetime of a delegation isn't limited to that of an open, a 4986 * Since the lifetime of a delegation isn't limited to that of an open, a
4995 * client may quite reasonably hang on to a delegation as long as it has 4987 * client may quite reasonably hang on to a delegation as long as it has
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index f34d9de802ab..51844048937f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1179,7 +1179,6 @@ static int __init init_nfsd(void)
1179 retval = nfsd4_init_slabs(); 1179 retval = nfsd4_init_slabs();
1180 if (retval) 1180 if (retval)
1181 goto out_unregister_pernet; 1181 goto out_unregister_pernet;
1182 nfs4_state_init();
1183 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */ 1182 retval = nfsd_fault_inject_init(); /* nfsd fault injection controls */
1184 if (retval) 1183 if (retval)
1185 goto out_free_slabs; 1184 goto out_free_slabs;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 479eb681c27c..847daf37e566 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -15,11 +15,20 @@
15#include <linux/nfs2.h> 15#include <linux/nfs2.h>
16#include <linux/nfs3.h> 16#include <linux/nfs3.h>
17#include <linux/nfs4.h> 17#include <linux/nfs4.h>
18#include <linux/sunrpc/svc.h>
18#include <linux/sunrpc/msg_prot.h> 19#include <linux/sunrpc/msg_prot.h>
19 20
20#include <linux/nfsd/debug.h> 21#include <uapi/linux/nfsd/debug.h>
21#include <linux/nfsd/export.h> 22
22#include <linux/nfsd/stats.h> 23#include "stats.h"
24#include "export.h"
25
26#undef ifdebug
27#ifdef NFSD_DEBUG
28# define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag)
29#else
30# define ifdebug(flag) if (0)
31#endif
23 32
24/* 33/*
25 * nfsd version 34 * nfsd version
@@ -106,7 +115,6 @@ static inline int nfsd_v4client(struct svc_rqst *rq)
106 */ 115 */
107#ifdef CONFIG_NFSD_V4 116#ifdef CONFIG_NFSD_V4
108extern unsigned long max_delegations; 117extern unsigned long max_delegations;
109void nfs4_state_init(void);
110int nfsd4_init_slabs(void); 118int nfsd4_init_slabs(void);
111void nfsd4_free_slabs(void); 119void nfsd4_free_slabs(void);
112int nfs4_state_start(void); 120int nfs4_state_start(void);
@@ -117,7 +125,6 @@ void nfs4_reset_lease(time_t leasetime);
117int nfs4_reset_recoverydir(char *recdir); 125int nfs4_reset_recoverydir(char *recdir);
118char * nfs4_recoverydir(void); 126char * nfs4_recoverydir(void);
119#else 127#else
120static inline void nfs4_state_init(void) { }
121static inline int nfsd4_init_slabs(void) { return 0; } 128static inline int nfsd4_init_slabs(void) { return 0; }
122static inline void nfsd4_free_slabs(void) { } 129static inline void nfsd4_free_slabs(void) { }
123static inline int nfs4_state_start(void) { return 0; } 130static inline int nfs4_state_start(void) { return 0; }
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 3c37b160dcad..a337106d6875 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -169,8 +169,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
169 data_left -= len; 169 data_left -= len;
170 if (data_left < 0) 170 if (data_left < 0)
171 return error; 171 return error;
172 exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_auth); 172 exp = rqst_exp_find(rqstp, fh->fh_fsid_type, fh->fh_fsid);
173 fid = (struct fid *)(fh->fh_auth + len); 173 fid = (struct fid *)(fh->fh_fsid + len);
174 } else { 174 } else {
175 __u32 tfh[2]; 175 __u32 tfh[2];
176 dev_t xdev; 176 dev_t xdev;
@@ -385,7 +385,7 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
385{ 385{
386 if (dentry != exp->ex_path.dentry) { 386 if (dentry != exp->ex_path.dentry) {
387 struct fid *fid = (struct fid *) 387 struct fid *fid = (struct fid *)
388 (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); 388 (fhp->fh_handle.fh_fsid + fhp->fh_handle.fh_size/4 - 1);
389 int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; 389 int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
390 int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); 390 int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
391 391
@@ -513,7 +513,6 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
513 */ 513 */
514 514
515 struct inode * inode = dentry->d_inode; 515 struct inode * inode = dentry->d_inode;
516 __u32 *datap;
517 dev_t ex_dev = exp_sb(exp)->s_dev; 516 dev_t ex_dev = exp_sb(exp)->s_dev;
518 517
519 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %pd2, ino=%ld)\n", 518 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %pd2, ino=%ld)\n",
@@ -557,17 +556,16 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
557 if (inode) 556 if (inode)
558 _fh_update_old(dentry, exp, &fhp->fh_handle); 557 _fh_update_old(dentry, exp, &fhp->fh_handle);
559 } else { 558 } else {
560 int len; 559 fhp->fh_handle.fh_size =
560 key_len(fhp->fh_handle.fh_fsid_type) + 4;
561 fhp->fh_handle.fh_auth_type = 0; 561 fhp->fh_handle.fh_auth_type = 0;
562 datap = fhp->fh_handle.fh_auth+0; 562
563 mk_fsid(fhp->fh_handle.fh_fsid_type, datap, ex_dev, 563 mk_fsid(fhp->fh_handle.fh_fsid_type,
564 fhp->fh_handle.fh_fsid,
565 ex_dev,
564 exp->ex_path.dentry->d_inode->i_ino, 566 exp->ex_path.dentry->d_inode->i_ino,
565 exp->ex_fsid, exp->ex_uuid); 567 exp->ex_fsid, exp->ex_uuid);
566 568
567 len = key_len(fhp->fh_handle.fh_fsid_type);
568 datap += len/4;
569 fhp->fh_handle.fh_size = 4 + len;
570
571 if (inode) 569 if (inode)
572 _fh_update(fhp, exp, dentry); 570 _fh_update(fhp, exp, dentry);
573 if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { 571 if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) {
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index ad67964d0bb1..2e89e70ac15c 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -1,9 +1,58 @@
1/* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */ 1/*
2 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
3 *
4 * This file describes the layout of the file handles as passed
5 * over the wire.
6 */
7#ifndef _LINUX_NFSD_NFSFH_H
8#define _LINUX_NFSD_NFSFH_H
9
10#include <linux/sunrpc/svc.h>
11#include <uapi/linux/nfsd/nfsfh.h>
12
13static inline __u32 ino_t_to_u32(ino_t ino)
14{
15 return (__u32) ino;
16}
17
18static inline ino_t u32_to_ino_t(__u32 uino)
19{
20 return (ino_t) uino;
21}
2 22
3#ifndef _LINUX_NFSD_FH_INT_H 23/*
4#define _LINUX_NFSD_FH_INT_H 24 * This is the internal representation of an NFS handle used in knfsd.
25 * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
26 */
27typedef struct svc_fh {
28 struct knfsd_fh fh_handle; /* FH data */
29 struct dentry * fh_dentry; /* validated dentry */
30 struct svc_export * fh_export; /* export pointer */
31 int fh_maxsize; /* max size for fh_handle */
32
33 unsigned char fh_locked; /* inode locked by us */
34 unsigned char fh_want_write; /* remount protection taken */
35
36#ifdef CONFIG_NFSD_V3
37 unsigned char fh_post_saved; /* post-op attrs saved */
38 unsigned char fh_pre_saved; /* pre-op attrs saved */
39
40 /* Pre-op attributes saved during fh_lock */
41 __u64 fh_pre_size; /* size before operation */
42 struct timespec fh_pre_mtime; /* mtime before oper */
43 struct timespec fh_pre_ctime; /* ctime before oper */
44 /*
45 * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
46 * to find out if it is valid.
47 */
48 u64 fh_pre_change;
49
50 /* Post-op attributes saved in fh_unlock */
51 struct kstat fh_post_attr; /* full attrs after operation */
52 u64 fh_post_change; /* nfsv4 change; see above */
53#endif /* CONFIG_NFSD_V3 */
5 54
6#include <linux/nfsd/nfsfh.h> 55} svc_fh;
7 56
8enum nfsd_fsid { 57enum nfsd_fsid {
9 FSID_DEV = 0, 58 FSID_DEV = 0,
@@ -215,4 +264,4 @@ fh_unlock(struct svc_fh *fhp)
215 } 264 }
216} 265}
217 266
218#endif /* _LINUX_NFSD_FH_INT_H */ 267#endif /* _LINUX_NFSD_NFSFH_H */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 424d8f5f2317..fda9ce28b1b2 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -37,7 +37,6 @@
37 37
38#include <linux/idr.h> 38#include <linux/idr.h>
39#include <linux/sunrpc/svc_xprt.h> 39#include <linux/sunrpc/svc_xprt.h>
40#include <linux/nfsd/nfsfh.h>
41#include "nfsfh.h" 40#include "nfsfh.h"
42 41
43typedef struct { 42typedef struct {
@@ -464,8 +463,6 @@ extern void nfs4_release_reclaim(struct nfsd_net *);
464extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, 463extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
465 struct nfsd_net *nn); 464 struct nfsd_net *nn);
466extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn); 465extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn);
467extern void nfs4_free_openowner(struct nfs4_openowner *);
468extern void nfs4_free_lockowner(struct nfs4_lockowner *);
469extern int set_callback_cred(void); 466extern int set_callback_cred(void);
470extern void nfsd4_init_callback(struct nfsd4_callback *); 467extern void nfsd4_init_callback(struct nfsd4_callback *);
471extern void nfsd4_probe_callback(struct nfs4_client *clp); 468extern void nfsd4_probe_callback(struct nfs4_client *clp);
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 6d4521feb6e3..cd90878a76aa 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -24,7 +24,6 @@
24#include <linux/seq_file.h> 24#include <linux/seq_file.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/sunrpc/stats.h> 26#include <linux/sunrpc/stats.h>
27#include <linux/nfsd/stats.h>
28#include <net/net_namespace.h> 27#include <net/net_namespace.h>
29 28
30#include "nfsd.h" 29#include "nfsd.h"
diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
new file mode 100644
index 000000000000..a5c944b771c6
--- /dev/null
+++ b/fs/nfsd/stats.h
@@ -0,0 +1,43 @@
1/*
2 * Statistics for NFS server.
3 *
4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
5 */
6#ifndef _NFSD_STATS_H
7#define _NFSD_STATS_H
8
9#include <uapi/linux/nfsd/stats.h>
10
11
12struct nfsd_stats {
13 unsigned int rchits; /* repcache hits */
14 unsigned int rcmisses; /* repcache hits */
15 unsigned int rcnocache; /* uncached reqs */
16 unsigned int fh_stale; /* FH stale error */
17 unsigned int fh_lookup; /* dentry cached */
18 unsigned int fh_anon; /* anon file dentry returned */
19 unsigned int fh_nocache_dir; /* filehandle not found in dcache */
20 unsigned int fh_nocache_nondir; /* filehandle not found in dcache */
21 unsigned int io_read; /* bytes returned to read requests */
22 unsigned int io_write; /* bytes passed in write requests */
23 unsigned int th_cnt; /* number of available threads */
24 unsigned int th_usage[10]; /* number of ticks during which n perdeciles
25 * of available threads were in use */
26 unsigned int th_fullcnt; /* number of times last free thread was used */
27 unsigned int ra_size; /* size of ra cache */
28 unsigned int ra_depth[11]; /* number of times ra entry was found that deep
29 * in the cache (10percentiles). [10] = not found */
30#ifdef CONFIG_NFSD_V4
31 unsigned int nfs4_opcount[LAST_NFS4_OP + 1]; /* count of individual nfsv4 operations */
32#endif
33
34};
35
36
37extern struct nfsd_stats nfsdstats;
38extern struct svc_stat nfsd_svcstats;
39
40void nfsd_stat_init(void);
41void nfsd_stat_shutdown(void);
42
43#endif /* _NFSD_STATS_H */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 16f0673a423c..6aaa3057683a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -857,20 +857,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
857 return err; 857 return err;
858} 858}
859 859
860static void kill_suid(struct dentry *dentry)
861{
862 struct iattr ia;
863 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
864
865 mutex_lock(&dentry->d_inode->i_mutex);
866 /*
867 * Note we call this on write, so notify_change will not
868 * encounter any conflicting delegations:
869 */
870 notify_change(dentry, &ia, NULL);
871 mutex_unlock(&dentry->d_inode->i_mutex);
872}
873
874/* 860/*
875 * Gathered writes: If another process is currently writing to the file, 861 * Gathered writes: If another process is currently writing to the file,
876 * there's a high chance this is another nfsd (triggered by a bulk write 862 * there's a high chance this is another nfsd (triggered by a bulk write
@@ -942,10 +928,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
942 nfsdstats.io_write += host_err; 928 nfsdstats.io_write += host_err;
943 fsnotify_modify(file); 929 fsnotify_modify(file);
944 930
945 /* clear setuid/setgid flag after write */
946 if (inode->i_mode & (S_ISUID | S_ISGID))
947 kill_suid(dentry);
948
949 if (stable) { 931 if (stable) {
950 if (use_wgather) 932 if (use_wgather)
951 host_err = wait_for_concurrent_writes(file); 933 host_err = wait_for_concurrent_writes(file);