diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
commit | 85004cc367abc000aa36c0d0e270ab609a68b0cb (patch) | |
tree | 5739aae778d67b6d119fe5c668313fc2823e9836 | |
parent | 149a051f82d2b3860fe32fa182dbc83a66274894 (diff) | |
parent | 3fbd67ad61f6d5a09ea717b56c50bc5c3d8042a8 (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (118 commits)
NFSv4: Iterate through all nfs_clients when the server recalls a delegation
NFSv4: Deal more correctly with duplicate delegations
NFS: Fix a potential race between umount and nfs_access_cache_shrinker()
NFS: Add an asynchronous delegreturn operation for use in nfs_clear_inode
nfs: convert NFS_*(inode) helpers to static inline
nfs: obliterate NFS_FLAGS macro
NFS: Address memory leaks in the NFS client mount option parser
nfs4: allow nfsv4 acls on non-regular-files
NFS: Optimise away the sigmask code in aio/dio reads and writes
SUNRPC: Don't bother changing the sigmask for asynchronous RPC calls
SUNRPC: rpcb_getport_sync() passes incorrect address size to rpc_create()
SUNRPC: Clean up block comment preceding rpcb_getport_sync()
SUNRPC: Use appropriate argument types in rpcb client
SUNRPC: rpcb_getport_sync() should use built-in hostname generator
SUNRPC: Clean up functions that free address_strings array
NFS: NFS version number is unsigned
NLM: Fix a bogus 'return' in nlmclnt_rpc_release
NLM: Introduce an arguments structure for nlmclnt_init()
NLM/NFS: Use cached nlm_host when calling nlmclnt_proc()
NFS: Invoke nlmclnt_init during NFS mount processing
...
55 files changed, 1910 insertions, 1293 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index d070b18e539d..0b45fd3a4bfd 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -41,6 +41,48 @@ struct nlm_wait { | |||
41 | 41 | ||
42 | static LIST_HEAD(nlm_blocked); | 42 | static LIST_HEAD(nlm_blocked); |
43 | 43 | ||
44 | /** | ||
45 | * nlmclnt_init - Set up per-NFS mount point lockd data structures | ||
46 | * @nlm_init: pointer to arguments structure | ||
47 | * | ||
48 | * Returns pointer to an appropriate nlm_host struct, | ||
49 | * or an ERR_PTR value. | ||
50 | */ | ||
51 | struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) | ||
52 | { | ||
53 | struct nlm_host *host; | ||
54 | u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; | ||
55 | int status; | ||
56 | |||
57 | status = lockd_up(nlm_init->protocol); | ||
58 | if (status < 0) | ||
59 | return ERR_PTR(status); | ||
60 | |||
61 | host = nlmclnt_lookup_host((struct sockaddr_in *)nlm_init->address, | ||
62 | nlm_init->protocol, nlm_version, | ||
63 | nlm_init->hostname, | ||
64 | strlen(nlm_init->hostname)); | ||
65 | if (host == NULL) { | ||
66 | lockd_down(); | ||
67 | return ERR_PTR(-ENOLCK); | ||
68 | } | ||
69 | |||
70 | return host; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(nlmclnt_init); | ||
73 | |||
74 | /** | ||
75 | * nlmclnt_done - Release resources allocated by nlmclnt_init() | ||
76 | * @host: nlm_host structure reserved by nlmclnt_init() | ||
77 | * | ||
78 | */ | ||
79 | void nlmclnt_done(struct nlm_host *host) | ||
80 | { | ||
81 | nlm_release_host(host); | ||
82 | lockd_down(); | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(nlmclnt_done); | ||
85 | |||
44 | /* | 86 | /* |
45 | * Queue up a lock for blocking so that the GRANTED request can see it | 87 | * Queue up a lock for blocking so that the GRANTED request can see it |
46 | */ | 88 | */ |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index a10343bed160..b6b74a60e1eb 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -145,34 +145,21 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) | |||
145 | BUG_ON(req->a_args.lock.fl.fl_ops != NULL); | 145 | BUG_ON(req->a_args.lock.fl.fl_ops != NULL); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* | 148 | /** |
149 | * This is the main entry point for the NLM client. | 149 | * nlmclnt_proc - Perform a single client-side lock request |
150 | * @host: address of a valid nlm_host context representing the NLM server | ||
151 | * @cmd: fcntl-style file lock operation to perform | ||
152 | * @fl: address of arguments for the lock operation | ||
153 | * | ||
150 | */ | 154 | */ |
151 | int | 155 | int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl) |
152 | nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | ||
153 | { | 156 | { |
154 | struct rpc_clnt *client = NFS_CLIENT(inode); | ||
155 | struct sockaddr_in addr; | ||
156 | struct nfs_server *nfssrv = NFS_SERVER(inode); | ||
157 | struct nlm_host *host; | ||
158 | struct nlm_rqst *call; | 157 | struct nlm_rqst *call; |
159 | sigset_t oldset; | 158 | sigset_t oldset; |
160 | unsigned long flags; | 159 | unsigned long flags; |
161 | int status, vers; | 160 | int status; |
162 | |||
163 | vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; | ||
164 | if (NFS_PROTO(inode)->version > 3) { | ||
165 | printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); | ||
166 | return -ENOLCK; | ||
167 | } | ||
168 | |||
169 | rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); | ||
170 | host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers, | ||
171 | nfssrv->nfs_client->cl_hostname, | ||
172 | strlen(nfssrv->nfs_client->cl_hostname)); | ||
173 | if (host == NULL) | ||
174 | return -ENOLCK; | ||
175 | 161 | ||
162 | nlm_get_host(host); | ||
176 | call = nlm_alloc_call(host); | 163 | call = nlm_alloc_call(host); |
177 | if (call == NULL) | 164 | if (call == NULL) |
178 | return -ENOMEM; | 165 | return -ENOMEM; |
@@ -219,7 +206,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | |||
219 | dprintk("lockd: clnt proc returns %d\n", status); | 206 | dprintk("lockd: clnt proc returns %d\n", status); |
220 | return status; | 207 | return status; |
221 | } | 208 | } |
222 | EXPORT_SYMBOL(nlmclnt_proc); | 209 | EXPORT_SYMBOL_GPL(nlmclnt_proc); |
223 | 210 | ||
224 | /* | 211 | /* |
225 | * Allocate an NLM RPC call struct | 212 | * Allocate an NLM RPC call struct |
@@ -257,7 +244,7 @@ void nlm_release_call(struct nlm_rqst *call) | |||
257 | 244 | ||
258 | static void nlmclnt_rpc_release(void *data) | 245 | static void nlmclnt_rpc_release(void *data) |
259 | { | 246 | { |
260 | return nlm_release_call(data); | 247 | nlm_release_call(data); |
261 | } | 248 | } |
262 | 249 | ||
263 | static int nlm_wait_on_grace(wait_queue_head_t *queue) | 250 | static int nlm_wait_on_grace(wait_queue_head_t *queue) |
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 633653bff944..3e459e18cc31 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c | |||
@@ -612,8 +612,7 @@ const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie) | |||
612 | * called with BKL held. | 612 | * called with BKL held. |
613 | */ | 613 | */ |
614 | static char buf[2*NLM_MAXCOOKIELEN+1]; | 614 | static char buf[2*NLM_MAXCOOKIELEN+1]; |
615 | int i; | 615 | unsigned int i, len = sizeof(buf); |
616 | int len = sizeof(buf); | ||
617 | char *p = buf; | 616 | char *p = buf; |
618 | 617 | ||
619 | len--; /* allow for trailing \0 */ | 618 | len--; /* allow for trailing \0 */ |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index a796be5051bf..9b6bbf1b9787 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -73,8 +73,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
73 | complete(&nfs_callback_info.started); | 73 | complete(&nfs_callback_info.started); |
74 | 74 | ||
75 | for(;;) { | 75 | for(;;) { |
76 | char buf[RPC_MAX_ADDRBUFLEN]; | ||
77 | |||
78 | if (signalled()) { | 76 | if (signalled()) { |
79 | if (nfs_callback_info.users == 0) | 77 | if (nfs_callback_info.users == 0) |
80 | break; | 78 | break; |
@@ -92,8 +90,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
92 | __FUNCTION__, -err); | 90 | __FUNCTION__, -err); |
93 | break; | 91 | break; |
94 | } | 92 | } |
95 | dprintk("%s: request from %s\n", __FUNCTION__, | ||
96 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
97 | svc_process(rqstp); | 93 | svc_process(rqstp); |
98 | } | 94 | } |
99 | 95 | ||
@@ -168,12 +164,11 @@ void nfs_callback_down(void) | |||
168 | 164 | ||
169 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) | 165 | static int nfs_callback_authenticate(struct svc_rqst *rqstp) |
170 | { | 166 | { |
171 | struct sockaddr_in *addr = svc_addr_in(rqstp); | ||
172 | struct nfs_client *clp; | 167 | struct nfs_client *clp; |
173 | char buf[RPC_MAX_ADDRBUFLEN]; | 168 | char buf[RPC_MAX_ADDRBUFLEN]; |
174 | 169 | ||
175 | /* Don't talk to strangers */ | 170 | /* Don't talk to strangers */ |
176 | clp = nfs_find_client(addr, 4); | 171 | clp = nfs_find_client(svc_addr(rqstp), 4); |
177 | if (clp == NULL) | 172 | if (clp == NULL) |
178 | return SVC_DROP; | 173 | return SVC_DROP; |
179 | 174 | ||
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index c2bb14e053e1..bb25d2135ff1 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h | |||
@@ -38,7 +38,7 @@ struct cb_compound_hdr_res { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct cb_getattrargs { | 40 | struct cb_getattrargs { |
41 | struct sockaddr_in *addr; | 41 | struct sockaddr *addr; |
42 | struct nfs_fh fh; | 42 | struct nfs_fh fh; |
43 | uint32_t bitmap[2]; | 43 | uint32_t bitmap[2]; |
44 | }; | 44 | }; |
@@ -53,7 +53,7 @@ struct cb_getattrres { | |||
53 | }; | 53 | }; |
54 | 54 | ||
55 | struct cb_recallargs { | 55 | struct cb_recallargs { |
56 | struct sockaddr_in *addr; | 56 | struct sockaddr *addr; |
57 | struct nfs_fh fh; | 57 | struct nfs_fh fh; |
58 | nfs4_stateid stateid; | 58 | nfs4_stateid stateid; |
59 | uint32_t truncate; | 59 | uint32_t truncate; |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 72e55d83756d..15f7785048d3 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -12,7 +12,9 @@ | |||
12 | #include "delegation.h" | 12 | #include "delegation.h" |
13 | #include "internal.h" | 13 | #include "internal.h" |
14 | 14 | ||
15 | #ifdef NFS_DEBUG | ||
15 | #define NFSDBG_FACILITY NFSDBG_CALLBACK | 16 | #define NFSDBG_FACILITY NFSDBG_CALLBACK |
17 | #endif | ||
16 | 18 | ||
17 | __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) | 19 | __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) |
18 | { | 20 | { |
@@ -20,12 +22,16 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres * | |||
20 | struct nfs_delegation *delegation; | 22 | struct nfs_delegation *delegation; |
21 | struct nfs_inode *nfsi; | 23 | struct nfs_inode *nfsi; |
22 | struct inode *inode; | 24 | struct inode *inode; |
23 | 25 | ||
24 | res->bitmap[0] = res->bitmap[1] = 0; | 26 | res->bitmap[0] = res->bitmap[1] = 0; |
25 | res->status = htonl(NFS4ERR_BADHANDLE); | 27 | res->status = htonl(NFS4ERR_BADHANDLE); |
26 | clp = nfs_find_client(args->addr, 4); | 28 | clp = nfs_find_client(args->addr, 4); |
27 | if (clp == NULL) | 29 | if (clp == NULL) |
28 | goto out; | 30 | goto out; |
31 | |||
32 | dprintk("NFS: GETATTR callback request from %s\n", | ||
33 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); | ||
34 | |||
29 | inode = nfs_delegation_find_inode(clp, &args->fh); | 35 | inode = nfs_delegation_find_inode(clp, &args->fh); |
30 | if (inode == NULL) | 36 | if (inode == NULL) |
31 | goto out_putclient; | 37 | goto out_putclient; |
@@ -65,23 +71,32 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) | |||
65 | clp = nfs_find_client(args->addr, 4); | 71 | clp = nfs_find_client(args->addr, 4); |
66 | if (clp == NULL) | 72 | if (clp == NULL) |
67 | goto out; | 73 | goto out; |
68 | inode = nfs_delegation_find_inode(clp, &args->fh); | 74 | |
69 | if (inode == NULL) | 75 | dprintk("NFS: RECALL callback request from %s\n", |
70 | goto out_putclient; | 76 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); |
71 | /* Set up a helper thread to actually return the delegation */ | 77 | |
72 | switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { | 78 | do { |
73 | case 0: | 79 | struct nfs_client *prev = clp; |
74 | res = 0; | 80 | |
75 | break; | 81 | inode = nfs_delegation_find_inode(clp, &args->fh); |
76 | case -ENOENT: | 82 | if (inode != NULL) { |
77 | res = htonl(NFS4ERR_BAD_STATEID); | 83 | /* Set up a helper thread to actually return the delegation */ |
78 | break; | 84 | switch(nfs_async_inode_return_delegation(inode, &args->stateid)) { |
79 | default: | 85 | case 0: |
80 | res = htonl(NFS4ERR_RESOURCE); | 86 | res = 0; |
81 | } | 87 | break; |
82 | iput(inode); | 88 | case -ENOENT: |
83 | out_putclient: | 89 | if (res != 0) |
84 | nfs_put_client(clp); | 90 | res = htonl(NFS4ERR_BAD_STATEID); |
91 | break; | ||
92 | default: | ||
93 | res = htonl(NFS4ERR_RESOURCE); | ||
94 | } | ||
95 | iput(inode); | ||
96 | } | ||
97 | clp = nfs_find_client_next(prev); | ||
98 | nfs_put_client(prev); | ||
99 | } while (clp != NULL); | ||
85 | out: | 100 | out: |
86 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res)); | 101 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res)); |
87 | return res; | 102 | return res; |
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index 058ade7efe79..c63eb720b68b 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
@@ -139,7 +139,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound | |||
139 | if (unlikely(status != 0)) | 139 | if (unlikely(status != 0)) |
140 | return status; | 140 | return status; |
141 | /* We do not like overly long tags! */ | 141 | /* We do not like overly long tags! */ |
142 | if (hdr->taglen > CB_OP_TAGLEN_MAXSZ-12 || hdr->taglen < 0) { | 142 | if (hdr->taglen > CB_OP_TAGLEN_MAXSZ - 12) { |
143 | printk("NFSv4 CALLBACK %s: client sent tag of length %u\n", | 143 | printk("NFSv4 CALLBACK %s: client sent tag of length %u\n", |
144 | __FUNCTION__, hdr->taglen); | 144 | __FUNCTION__, hdr->taglen); |
145 | return htonl(NFS4ERR_RESOURCE); | 145 | return htonl(NFS4ERR_RESOURCE); |
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr | |||
176 | status = decode_fh(xdr, &args->fh); | 176 | status = decode_fh(xdr, &args->fh); |
177 | if (unlikely(status != 0)) | 177 | if (unlikely(status != 0)) |
178 | goto out; | 178 | goto out; |
179 | args->addr = svc_addr_in(rqstp); | 179 | args->addr = svc_addr(rqstp); |
180 | status = decode_bitmap(xdr, args->bitmap); | 180 | status = decode_bitmap(xdr, args->bitmap); |
181 | out: | 181 | out: |
182 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status)); | 182 | dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status)); |
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, | |||
188 | __be32 *p; | 188 | __be32 *p; |
189 | __be32 status; | 189 | __be32 status; |
190 | 190 | ||
191 | args->addr = svc_addr_in(rqstp); | 191 | args->addr = svc_addr(rqstp); |
192 | status = decode_stateid(xdr, &args->stateid); | 192 | status = decode_stateid(xdr, &args->stateid); |
193 | if (unlikely(status != 0)) | 193 | if (unlikely(status != 0)) |
194 | goto out; | 194 | goto out; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a6f625497612..685c43f810c1 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/nfs_idmap.h> | 34 | #include <linux/nfs_idmap.h> |
35 | #include <linux/vfs.h> | 35 | #include <linux/vfs.h> |
36 | #include <linux/inet.h> | 36 | #include <linux/inet.h> |
37 | #include <linux/in6.h> | ||
38 | #include <net/ipv6.h> | ||
37 | #include <linux/nfs_xdr.h> | 39 | #include <linux/nfs_xdr.h> |
38 | 40 | ||
39 | #include <asm/system.h> | 41 | #include <asm/system.h> |
@@ -93,22 +95,30 @@ struct rpc_program nfsacl_program = { | |||
93 | }; | 95 | }; |
94 | #endif /* CONFIG_NFS_V3_ACL */ | 96 | #endif /* CONFIG_NFS_V3_ACL */ |
95 | 97 | ||
98 | struct nfs_client_initdata { | ||
99 | const char *hostname; | ||
100 | const struct sockaddr *addr; | ||
101 | size_t addrlen; | ||
102 | const struct nfs_rpc_ops *rpc_ops; | ||
103 | int proto; | ||
104 | }; | ||
105 | |||
96 | /* | 106 | /* |
97 | * Allocate a shared client record | 107 | * Allocate a shared client record |
98 | * | 108 | * |
99 | * Since these are allocated/deallocated very rarely, we don't | 109 | * Since these are allocated/deallocated very rarely, we don't |
100 | * bother putting them in a slab cache... | 110 | * bother putting them in a slab cache... |
101 | */ | 111 | */ |
102 | static struct nfs_client *nfs_alloc_client(const char *hostname, | 112 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
103 | const struct sockaddr_in *addr, | ||
104 | int nfsversion) | ||
105 | { | 113 | { |
106 | struct nfs_client *clp; | 114 | struct nfs_client *clp; |
107 | 115 | ||
108 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | 116 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
109 | goto error_0; | 117 | goto error_0; |
110 | 118 | ||
111 | if (nfsversion == 4) { | 119 | clp->rpc_ops = cl_init->rpc_ops; |
120 | |||
121 | if (cl_init->rpc_ops->version == 4) { | ||
112 | if (nfs_callback_up() < 0) | 122 | if (nfs_callback_up() < 0) |
113 | goto error_2; | 123 | goto error_2; |
114 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); | 124 | __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); |
@@ -117,11 +127,11 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, | |||
117 | atomic_set(&clp->cl_count, 1); | 127 | atomic_set(&clp->cl_count, 1); |
118 | clp->cl_cons_state = NFS_CS_INITING; | 128 | clp->cl_cons_state = NFS_CS_INITING; |
119 | 129 | ||
120 | clp->cl_nfsversion = nfsversion; | 130 | memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen); |
121 | memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); | 131 | clp->cl_addrlen = cl_init->addrlen; |
122 | 132 | ||
123 | if (hostname) { | 133 | if (cl_init->hostname) { |
124 | clp->cl_hostname = kstrdup(hostname, GFP_KERNEL); | 134 | clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL); |
125 | if (!clp->cl_hostname) | 135 | if (!clp->cl_hostname) |
126 | goto error_3; | 136 | goto error_3; |
127 | } | 137 | } |
@@ -129,6 +139,8 @@ static struct nfs_client *nfs_alloc_client(const char *hostname, | |||
129 | INIT_LIST_HEAD(&clp->cl_superblocks); | 139 | INIT_LIST_HEAD(&clp->cl_superblocks); |
130 | clp->cl_rpcclient = ERR_PTR(-EINVAL); | 140 | clp->cl_rpcclient = ERR_PTR(-EINVAL); |
131 | 141 | ||
142 | clp->cl_proto = cl_init->proto; | ||
143 | |||
132 | #ifdef CONFIG_NFS_V4 | 144 | #ifdef CONFIG_NFS_V4 |
133 | init_rwsem(&clp->cl_sem); | 145 | init_rwsem(&clp->cl_sem); |
134 | INIT_LIST_HEAD(&clp->cl_delegations); | 146 | INIT_LIST_HEAD(&clp->cl_delegations); |
@@ -166,7 +178,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
166 | */ | 178 | */ |
167 | static void nfs_free_client(struct nfs_client *clp) | 179 | static void nfs_free_client(struct nfs_client *clp) |
168 | { | 180 | { |
169 | dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); | 181 | dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); |
170 | 182 | ||
171 | nfs4_shutdown_client(clp); | 183 | nfs4_shutdown_client(clp); |
172 | 184 | ||
@@ -203,76 +215,148 @@ void nfs_put_client(struct nfs_client *clp) | |||
203 | } | 215 | } |
204 | } | 216 | } |
205 | 217 | ||
218 | static int nfs_sockaddr_match_ipaddr4(const struct sockaddr_in *sa1, | ||
219 | const struct sockaddr_in *sa2) | ||
220 | { | ||
221 | return sa1->sin_addr.s_addr == sa2->sin_addr.s_addr; | ||
222 | } | ||
223 | |||
224 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr_in6 *sa1, | ||
225 | const struct sockaddr_in6 *sa2) | ||
226 | { | ||
227 | return ipv6_addr_equal(&sa1->sin6_addr, &sa2->sin6_addr); | ||
228 | } | ||
229 | |||
230 | static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1, | ||
231 | const struct sockaddr *sa2) | ||
232 | { | ||
233 | switch (sa1->sa_family) { | ||
234 | case AF_INET: | ||
235 | return nfs_sockaddr_match_ipaddr4((const struct sockaddr_in *)sa1, | ||
236 | (const struct sockaddr_in *)sa2); | ||
237 | case AF_INET6: | ||
238 | return nfs_sockaddr_match_ipaddr6((const struct sockaddr_in6 *)sa1, | ||
239 | (const struct sockaddr_in6 *)sa2); | ||
240 | } | ||
241 | BUG(); | ||
242 | } | ||
243 | |||
206 | /* | 244 | /* |
207 | * Find a client by address | 245 | * Find a client by IP address and protocol version |
208 | * - caller must hold nfs_client_lock | 246 | * - returns NULL if no such client |
209 | */ | 247 | */ |
210 | static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion, int match_port) | 248 | struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion) |
211 | { | 249 | { |
212 | struct nfs_client *clp; | 250 | struct nfs_client *clp; |
213 | 251 | ||
252 | spin_lock(&nfs_client_lock); | ||
214 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | 253 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { |
254 | struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; | ||
255 | |||
215 | /* Don't match clients that failed to initialise properly */ | 256 | /* Don't match clients that failed to initialise properly */ |
216 | if (clp->cl_cons_state < 0) | 257 | if (clp->cl_cons_state != NFS_CS_READY) |
217 | continue; | 258 | continue; |
218 | 259 | ||
219 | /* Different NFS versions cannot share the same nfs_client */ | 260 | /* Different NFS versions cannot share the same nfs_client */ |
220 | if (clp->cl_nfsversion != nfsversion) | 261 | if (clp->rpc_ops->version != nfsversion) |
221 | continue; | 262 | continue; |
222 | 263 | ||
223 | if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr, | 264 | if (addr->sa_family != clap->sa_family) |
224 | sizeof(clp->cl_addr.sin_addr)) != 0) | 265 | continue; |
266 | /* Match only the IP address, not the port number */ | ||
267 | if (!nfs_sockaddr_match_ipaddr(addr, clap)) | ||
225 | continue; | 268 | continue; |
226 | 269 | ||
227 | if (!match_port || clp->cl_addr.sin_port == addr->sin_port) | 270 | atomic_inc(&clp->cl_count); |
228 | goto found; | 271 | spin_unlock(&nfs_client_lock); |
272 | return clp; | ||
229 | } | 273 | } |
230 | 274 | spin_unlock(&nfs_client_lock); | |
231 | return NULL; | 275 | return NULL; |
232 | |||
233 | found: | ||
234 | atomic_inc(&clp->cl_count); | ||
235 | return clp; | ||
236 | } | 276 | } |
237 | 277 | ||
238 | /* | 278 | /* |
239 | * Find a client by IP address and protocol version | 279 | * Find a client by IP address and protocol version |
240 | * - returns NULL if no such client | 280 | * - returns NULL if no such client |
241 | */ | 281 | */ |
242 | struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) | 282 | struct nfs_client *nfs_find_client_next(struct nfs_client *clp) |
243 | { | 283 | { |
244 | struct nfs_client *clp; | 284 | struct sockaddr *sap = (struct sockaddr *)&clp->cl_addr; |
285 | u32 nfsvers = clp->rpc_ops->version; | ||
245 | 286 | ||
246 | spin_lock(&nfs_client_lock); | 287 | spin_lock(&nfs_client_lock); |
247 | clp = __nfs_find_client(addr, nfsversion, 0); | 288 | list_for_each_entry_continue(clp, &nfs_client_list, cl_share_link) { |
289 | struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; | ||
290 | |||
291 | /* Don't match clients that failed to initialise properly */ | ||
292 | if (clp->cl_cons_state != NFS_CS_READY) | ||
293 | continue; | ||
294 | |||
295 | /* Different NFS versions cannot share the same nfs_client */ | ||
296 | if (clp->rpc_ops->version != nfsvers) | ||
297 | continue; | ||
298 | |||
299 | if (sap->sa_family != clap->sa_family) | ||
300 | continue; | ||
301 | /* Match only the IP address, not the port number */ | ||
302 | if (!nfs_sockaddr_match_ipaddr(sap, clap)) | ||
303 | continue; | ||
304 | |||
305 | atomic_inc(&clp->cl_count); | ||
306 | spin_unlock(&nfs_client_lock); | ||
307 | return clp; | ||
308 | } | ||
248 | spin_unlock(&nfs_client_lock); | 309 | spin_unlock(&nfs_client_lock); |
249 | if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) { | 310 | return NULL; |
250 | nfs_put_client(clp); | 311 | } |
251 | clp = NULL; | 312 | |
313 | /* | ||
314 | * Find an nfs_client on the list that matches the initialisation data | ||
315 | * that is supplied. | ||
316 | */ | ||
317 | static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data) | ||
318 | { | ||
319 | struct nfs_client *clp; | ||
320 | |||
321 | list_for_each_entry(clp, &nfs_client_list, cl_share_link) { | ||
322 | /* Don't match clients that failed to initialise properly */ | ||
323 | if (clp->cl_cons_state < 0) | ||
324 | continue; | ||
325 | |||
326 | /* Different NFS versions cannot share the same nfs_client */ | ||
327 | if (clp->rpc_ops != data->rpc_ops) | ||
328 | continue; | ||
329 | |||
330 | if (clp->cl_proto != data->proto) | ||
331 | continue; | ||
332 | |||
333 | /* Match the full socket address */ | ||
334 | if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0) | ||
335 | continue; | ||
336 | |||
337 | atomic_inc(&clp->cl_count); | ||
338 | return clp; | ||
252 | } | 339 | } |
253 | return clp; | 340 | return NULL; |
254 | } | 341 | } |
255 | 342 | ||
256 | /* | 343 | /* |
257 | * Look up a client by IP address and protocol version | 344 | * Look up a client by IP address and protocol version |
258 | * - creates a new record if one doesn't yet exist | 345 | * - creates a new record if one doesn't yet exist |
259 | */ | 346 | */ |
260 | static struct nfs_client *nfs_get_client(const char *hostname, | 347 | static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init) |
261 | const struct sockaddr_in *addr, | ||
262 | int nfsversion) | ||
263 | { | 348 | { |
264 | struct nfs_client *clp, *new = NULL; | 349 | struct nfs_client *clp, *new = NULL; |
265 | int error; | 350 | int error; |
266 | 351 | ||
267 | dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", | 352 | dprintk("--> nfs_get_client(%s,v%u)\n", |
268 | hostname ?: "", NIPQUAD(addr->sin_addr), | 353 | cl_init->hostname ?: "", cl_init->rpc_ops->version); |
269 | addr->sin_port, nfsversion); | ||
270 | 354 | ||
271 | /* see if the client already exists */ | 355 | /* see if the client already exists */ |
272 | do { | 356 | do { |
273 | spin_lock(&nfs_client_lock); | 357 | spin_lock(&nfs_client_lock); |
274 | 358 | ||
275 | clp = __nfs_find_client(addr, nfsversion, 1); | 359 | clp = nfs_match_client(cl_init); |
276 | if (clp) | 360 | if (clp) |
277 | goto found_client; | 361 | goto found_client; |
278 | if (new) | 362 | if (new) |
@@ -280,7 +364,7 @@ static struct nfs_client *nfs_get_client(const char *hostname, | |||
280 | 364 | ||
281 | spin_unlock(&nfs_client_lock); | 365 | spin_unlock(&nfs_client_lock); |
282 | 366 | ||
283 | new = nfs_alloc_client(hostname, addr, nfsversion); | 367 | new = nfs_alloc_client(cl_init); |
284 | } while (new); | 368 | } while (new); |
285 | 369 | ||
286 | return ERR_PTR(-ENOMEM); | 370 | return ERR_PTR(-ENOMEM); |
@@ -344,12 +428,16 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
344 | switch (proto) { | 428 | switch (proto) { |
345 | case XPRT_TRANSPORT_TCP: | 429 | case XPRT_TRANSPORT_TCP: |
346 | case XPRT_TRANSPORT_RDMA: | 430 | case XPRT_TRANSPORT_RDMA: |
347 | if (!to->to_initval) | 431 | if (to->to_initval == 0) |
348 | to->to_initval = 60 * HZ; | 432 | to->to_initval = 60 * HZ; |
349 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | 433 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) |
350 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | 434 | to->to_initval = NFS_MAX_TCP_TIMEOUT; |
351 | to->to_increment = to->to_initval; | 435 | to->to_increment = to->to_initval; |
352 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | 436 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); |
437 | if (to->to_maxval > NFS_MAX_TCP_TIMEOUT) | ||
438 | to->to_maxval = NFS_MAX_TCP_TIMEOUT; | ||
439 | if (to->to_maxval < to->to_initval) | ||
440 | to->to_maxval = to->to_initval; | ||
353 | to->to_exponential = 0; | 441 | to->to_exponential = 0; |
354 | break; | 442 | break; |
355 | case XPRT_TRANSPORT_UDP: | 443 | case XPRT_TRANSPORT_UDP: |
@@ -367,19 +455,17 @@ static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, | |||
367 | /* | 455 | /* |
368 | * Create an RPC client handle | 456 | * Create an RPC client handle |
369 | */ | 457 | */ |
370 | static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | 458 | static int nfs_create_rpc_client(struct nfs_client *clp, |
371 | unsigned int timeo, | 459 | const struct rpc_timeout *timeparms, |
372 | unsigned int retrans, | 460 | rpc_authflavor_t flavor, |
373 | rpc_authflavor_t flavor, | 461 | int flags) |
374 | int flags) | ||
375 | { | 462 | { |
376 | struct rpc_timeout timeparms; | ||
377 | struct rpc_clnt *clnt = NULL; | 463 | struct rpc_clnt *clnt = NULL; |
378 | struct rpc_create_args args = { | 464 | struct rpc_create_args args = { |
379 | .protocol = proto, | 465 | .protocol = clp->cl_proto, |
380 | .address = (struct sockaddr *)&clp->cl_addr, | 466 | .address = (struct sockaddr *)&clp->cl_addr, |
381 | .addrsize = sizeof(clp->cl_addr), | 467 | .addrsize = clp->cl_addrlen, |
382 | .timeout = &timeparms, | 468 | .timeout = timeparms, |
383 | .servername = clp->cl_hostname, | 469 | .servername = clp->cl_hostname, |
384 | .program = &nfs_program, | 470 | .program = &nfs_program, |
385 | .version = clp->rpc_ops->version, | 471 | .version = clp->rpc_ops->version, |
@@ -390,10 +476,6 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |||
390 | if (!IS_ERR(clp->cl_rpcclient)) | 476 | if (!IS_ERR(clp->cl_rpcclient)) |
391 | return 0; | 477 | return 0; |
392 | 478 | ||
393 | nfs_init_timeout_values(&timeparms, proto, timeo, retrans); | ||
394 | clp->retrans_timeo = timeparms.to_initval; | ||
395 | clp->retrans_count = timeparms.to_retries; | ||
396 | |||
397 | clnt = rpc_create(&args); | 479 | clnt = rpc_create(&args); |
398 | if (IS_ERR(clnt)) { | 480 | if (IS_ERR(clnt)) { |
399 | dprintk("%s: cannot create RPC client. Error = %ld\n", | 481 | dprintk("%s: cannot create RPC client. Error = %ld\n", |
@@ -411,7 +493,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |||
411 | static void nfs_destroy_server(struct nfs_server *server) | 493 | static void nfs_destroy_server(struct nfs_server *server) |
412 | { | 494 | { |
413 | if (!(server->flags & NFS_MOUNT_NONLM)) | 495 | if (!(server->flags & NFS_MOUNT_NONLM)) |
414 | lockd_down(); /* release rpc.lockd */ | 496 | nlmclnt_done(server->nlm_host); |
415 | } | 497 | } |
416 | 498 | ||
417 | /* | 499 | /* |
@@ -419,20 +501,29 @@ static void nfs_destroy_server(struct nfs_server *server) | |||
419 | */ | 501 | */ |
420 | static int nfs_start_lockd(struct nfs_server *server) | 502 | static int nfs_start_lockd(struct nfs_server *server) |
421 | { | 503 | { |
422 | int error = 0; | 504 | struct nlm_host *host; |
505 | struct nfs_client *clp = server->nfs_client; | ||
506 | struct nlmclnt_initdata nlm_init = { | ||
507 | .hostname = clp->cl_hostname, | ||
508 | .address = (struct sockaddr *)&clp->cl_addr, | ||
509 | .addrlen = clp->cl_addrlen, | ||
510 | .protocol = server->flags & NFS_MOUNT_TCP ? | ||
511 | IPPROTO_TCP : IPPROTO_UDP, | ||
512 | .nfs_version = clp->rpc_ops->version, | ||
513 | }; | ||
423 | 514 | ||
424 | if (server->nfs_client->cl_nfsversion > 3) | 515 | if (nlm_init.nfs_version > 3) |
425 | goto out; | 516 | return 0; |
426 | if (server->flags & NFS_MOUNT_NONLM) | 517 | if (server->flags & NFS_MOUNT_NONLM) |
427 | goto out; | 518 | return 0; |
428 | error = lockd_up((server->flags & NFS_MOUNT_TCP) ? | 519 | |
429 | IPPROTO_TCP : IPPROTO_UDP); | 520 | host = nlmclnt_init(&nlm_init); |
430 | if (error < 0) | 521 | if (IS_ERR(host)) |
431 | server->flags |= NFS_MOUNT_NONLM; | 522 | return PTR_ERR(host); |
432 | else | 523 | |
433 | server->destroy = nfs_destroy_server; | 524 | server->nlm_host = host; |
434 | out: | 525 | server->destroy = nfs_destroy_server; |
435 | return error; | 526 | return 0; |
436 | } | 527 | } |
437 | 528 | ||
438 | /* | 529 | /* |
@@ -441,7 +532,7 @@ out: | |||
441 | #ifdef CONFIG_NFS_V3_ACL | 532 | #ifdef CONFIG_NFS_V3_ACL |
442 | static void nfs_init_server_aclclient(struct nfs_server *server) | 533 | static void nfs_init_server_aclclient(struct nfs_server *server) |
443 | { | 534 | { |
444 | if (server->nfs_client->cl_nfsversion != 3) | 535 | if (server->nfs_client->rpc_ops->version != 3) |
445 | goto out_noacl; | 536 | goto out_noacl; |
446 | if (server->flags & NFS_MOUNT_NOACL) | 537 | if (server->flags & NFS_MOUNT_NOACL) |
447 | goto out_noacl; | 538 | goto out_noacl; |
@@ -468,7 +559,9 @@ static inline void nfs_init_server_aclclient(struct nfs_server *server) | |||
468 | /* | 559 | /* |
469 | * Create a general RPC client | 560 | * Create a general RPC client |
470 | */ | 561 | */ |
471 | static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) | 562 | static int nfs_init_server_rpcclient(struct nfs_server *server, |
563 | const struct rpc_timeout *timeo, | ||
564 | rpc_authflavor_t pseudoflavour) | ||
472 | { | 565 | { |
473 | struct nfs_client *clp = server->nfs_client; | 566 | struct nfs_client *clp = server->nfs_client; |
474 | 567 | ||
@@ -478,6 +571,11 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t | |||
478 | return PTR_ERR(server->client); | 571 | return PTR_ERR(server->client); |
479 | } | 572 | } |
480 | 573 | ||
574 | memcpy(&server->client->cl_timeout_default, | ||
575 | timeo, | ||
576 | sizeof(server->client->cl_timeout_default)); | ||
577 | server->client->cl_timeout = &server->client->cl_timeout_default; | ||
578 | |||
481 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { | 579 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { |
482 | struct rpc_auth *auth; | 580 | struct rpc_auth *auth; |
483 | 581 | ||
@@ -502,6 +600,7 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t | |||
502 | * Initialise an NFS2 or NFS3 client | 600 | * Initialise an NFS2 or NFS3 client |
503 | */ | 601 | */ |
504 | static int nfs_init_client(struct nfs_client *clp, | 602 | static int nfs_init_client(struct nfs_client *clp, |
603 | const struct rpc_timeout *timeparms, | ||
505 | const struct nfs_parsed_mount_data *data) | 604 | const struct nfs_parsed_mount_data *data) |
506 | { | 605 | { |
507 | int error; | 606 | int error; |
@@ -512,18 +611,11 @@ static int nfs_init_client(struct nfs_client *clp, | |||
512 | return 0; | 611 | return 0; |
513 | } | 612 | } |
514 | 613 | ||
515 | /* Check NFS protocol revision and initialize RPC op vector */ | ||
516 | clp->rpc_ops = &nfs_v2_clientops; | ||
517 | #ifdef CONFIG_NFS_V3 | ||
518 | if (clp->cl_nfsversion == 3) | ||
519 | clp->rpc_ops = &nfs_v3_clientops; | ||
520 | #endif | ||
521 | /* | 614 | /* |
522 | * Create a client RPC handle for doing FSSTAT with UNIX auth only | 615 | * Create a client RPC handle for doing FSSTAT with UNIX auth only |
523 | * - RFC 2623, sec 2.3.2 | 616 | * - RFC 2623, sec 2.3.2 |
524 | */ | 617 | */ |
525 | error = nfs_create_rpc_client(clp, data->nfs_server.protocol, | 618 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0); |
526 | data->timeo, data->retrans, RPC_AUTH_UNIX, 0); | ||
527 | if (error < 0) | 619 | if (error < 0) |
528 | goto error; | 620 | goto error; |
529 | nfs_mark_client_ready(clp, NFS_CS_READY); | 621 | nfs_mark_client_ready(clp, NFS_CS_READY); |
@@ -541,25 +633,34 @@ error: | |||
541 | static int nfs_init_server(struct nfs_server *server, | 633 | static int nfs_init_server(struct nfs_server *server, |
542 | const struct nfs_parsed_mount_data *data) | 634 | const struct nfs_parsed_mount_data *data) |
543 | { | 635 | { |
636 | struct nfs_client_initdata cl_init = { | ||
637 | .hostname = data->nfs_server.hostname, | ||
638 | .addr = (const struct sockaddr *)&data->nfs_server.address, | ||
639 | .addrlen = data->nfs_server.addrlen, | ||
640 | .rpc_ops = &nfs_v2_clientops, | ||
641 | .proto = data->nfs_server.protocol, | ||
642 | }; | ||
643 | struct rpc_timeout timeparms; | ||
544 | struct nfs_client *clp; | 644 | struct nfs_client *clp; |
545 | int error, nfsvers = 2; | 645 | int error; |
546 | 646 | ||
547 | dprintk("--> nfs_init_server()\n"); | 647 | dprintk("--> nfs_init_server()\n"); |
548 | 648 | ||
549 | #ifdef CONFIG_NFS_V3 | 649 | #ifdef CONFIG_NFS_V3 |
550 | if (data->flags & NFS_MOUNT_VER3) | 650 | if (data->flags & NFS_MOUNT_VER3) |
551 | nfsvers = 3; | 651 | cl_init.rpc_ops = &nfs_v3_clientops; |
552 | #endif | 652 | #endif |
553 | 653 | ||
554 | /* Allocate or find a client reference we can use */ | 654 | /* Allocate or find a client reference we can use */ |
555 | clp = nfs_get_client(data->nfs_server.hostname, | 655 | clp = nfs_get_client(&cl_init); |
556 | &data->nfs_server.address, nfsvers); | ||
557 | if (IS_ERR(clp)) { | 656 | if (IS_ERR(clp)) { |
558 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); | 657 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); |
559 | return PTR_ERR(clp); | 658 | return PTR_ERR(clp); |
560 | } | 659 | } |
561 | 660 | ||
562 | error = nfs_init_client(clp, data); | 661 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, |
662 | data->timeo, data->retrans); | ||
663 | error = nfs_init_client(clp, &timeparms, data); | ||
563 | if (error < 0) | 664 | if (error < 0) |
564 | goto error; | 665 | goto error; |
565 | 666 | ||
@@ -583,7 +684,7 @@ static int nfs_init_server(struct nfs_server *server, | |||
583 | if (error < 0) | 684 | if (error < 0) |
584 | goto error; | 685 | goto error; |
585 | 686 | ||
586 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); | 687 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
587 | if (error < 0) | 688 | if (error < 0) |
588 | goto error; | 689 | goto error; |
589 | 690 | ||
@@ -729,6 +830,9 @@ static struct nfs_server *nfs_alloc_server(void) | |||
729 | INIT_LIST_HEAD(&server->client_link); | 830 | INIT_LIST_HEAD(&server->client_link); |
730 | INIT_LIST_HEAD(&server->master_link); | 831 | INIT_LIST_HEAD(&server->master_link); |
731 | 832 | ||
833 | init_waitqueue_head(&server->active_wq); | ||
834 | atomic_set(&server->active, 0); | ||
835 | |||
732 | server->io_stats = nfs_alloc_iostats(); | 836 | server->io_stats = nfs_alloc_iostats(); |
733 | if (!server->io_stats) { | 837 | if (!server->io_stats) { |
734 | kfree(server); | 838 | kfree(server); |
@@ -840,7 +944,7 @@ error: | |||
840 | * Initialise an NFS4 client record | 944 | * Initialise an NFS4 client record |
841 | */ | 945 | */ |
842 | static int nfs4_init_client(struct nfs_client *clp, | 946 | static int nfs4_init_client(struct nfs_client *clp, |
843 | int proto, int timeo, int retrans, | 947 | const struct rpc_timeout *timeparms, |
844 | const char *ip_addr, | 948 | const char *ip_addr, |
845 | rpc_authflavor_t authflavour) | 949 | rpc_authflavor_t authflavour) |
846 | { | 950 | { |
@@ -855,7 +959,7 @@ static int nfs4_init_client(struct nfs_client *clp, | |||
855 | /* Check NFS protocol revision and initialize RPC op vector */ | 959 | /* Check NFS protocol revision and initialize RPC op vector */ |
856 | clp->rpc_ops = &nfs_v4_clientops; | 960 | clp->rpc_ops = &nfs_v4_clientops; |
857 | 961 | ||
858 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, | 962 | error = nfs_create_rpc_client(clp, timeparms, authflavour, |
859 | RPC_CLNT_CREATE_DISCRTRY); | 963 | RPC_CLNT_CREATE_DISCRTRY); |
860 | if (error < 0) | 964 | if (error < 0) |
861 | goto error; | 965 | goto error; |
@@ -882,23 +986,32 @@ error: | |||
882 | * Set up an NFS4 client | 986 | * Set up an NFS4 client |
883 | */ | 987 | */ |
884 | static int nfs4_set_client(struct nfs_server *server, | 988 | static int nfs4_set_client(struct nfs_server *server, |
885 | const char *hostname, const struct sockaddr_in *addr, | 989 | const char *hostname, |
990 | const struct sockaddr *addr, | ||
991 | const size_t addrlen, | ||
886 | const char *ip_addr, | 992 | const char *ip_addr, |
887 | rpc_authflavor_t authflavour, | 993 | rpc_authflavor_t authflavour, |
888 | int proto, int timeo, int retrans) | 994 | int proto, const struct rpc_timeout *timeparms) |
889 | { | 995 | { |
996 | struct nfs_client_initdata cl_init = { | ||
997 | .hostname = hostname, | ||
998 | .addr = addr, | ||
999 | .addrlen = addrlen, | ||
1000 | .rpc_ops = &nfs_v4_clientops, | ||
1001 | .proto = proto, | ||
1002 | }; | ||
890 | struct nfs_client *clp; | 1003 | struct nfs_client *clp; |
891 | int error; | 1004 | int error; |
892 | 1005 | ||
893 | dprintk("--> nfs4_set_client()\n"); | 1006 | dprintk("--> nfs4_set_client()\n"); |
894 | 1007 | ||
895 | /* Allocate or find a client reference we can use */ | 1008 | /* Allocate or find a client reference we can use */ |
896 | clp = nfs_get_client(hostname, addr, 4); | 1009 | clp = nfs_get_client(&cl_init); |
897 | if (IS_ERR(clp)) { | 1010 | if (IS_ERR(clp)) { |
898 | error = PTR_ERR(clp); | 1011 | error = PTR_ERR(clp); |
899 | goto error; | 1012 | goto error; |
900 | } | 1013 | } |
901 | error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); | 1014 | error = nfs4_init_client(clp, timeparms, ip_addr, authflavour); |
902 | if (error < 0) | 1015 | if (error < 0) |
903 | goto error_put; | 1016 | goto error_put; |
904 | 1017 | ||
@@ -919,10 +1032,26 @@ error: | |||
919 | static int nfs4_init_server(struct nfs_server *server, | 1032 | static int nfs4_init_server(struct nfs_server *server, |
920 | const struct nfs_parsed_mount_data *data) | 1033 | const struct nfs_parsed_mount_data *data) |
921 | { | 1034 | { |
1035 | struct rpc_timeout timeparms; | ||
922 | int error; | 1036 | int error; |
923 | 1037 | ||
924 | dprintk("--> nfs4_init_server()\n"); | 1038 | dprintk("--> nfs4_init_server()\n"); |
925 | 1039 | ||
1040 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, | ||
1041 | data->timeo, data->retrans); | ||
1042 | |||
1043 | /* Get a client record */ | ||
1044 | error = nfs4_set_client(server, | ||
1045 | data->nfs_server.hostname, | ||
1046 | (const struct sockaddr *)&data->nfs_server.address, | ||
1047 | data->nfs_server.addrlen, | ||
1048 | data->client_address, | ||
1049 | data->auth_flavors[0], | ||
1050 | data->nfs_server.protocol, | ||
1051 | &timeparms); | ||
1052 | if (error < 0) | ||
1053 | goto error; | ||
1054 | |||
926 | /* Initialise the client representation from the mount data */ | 1055 | /* Initialise the client representation from the mount data */ |
927 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1056 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; |
928 | server->caps |= NFS_CAP_ATOMIC_OPEN; | 1057 | server->caps |= NFS_CAP_ATOMIC_OPEN; |
@@ -937,8 +1066,9 @@ static int nfs4_init_server(struct nfs_server *server, | |||
937 | server->acdirmin = data->acdirmin * HZ; | 1066 | server->acdirmin = data->acdirmin * HZ; |
938 | server->acdirmax = data->acdirmax * HZ; | 1067 | server->acdirmax = data->acdirmax * HZ; |
939 | 1068 | ||
940 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); | 1069 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
941 | 1070 | ||
1071 | error: | ||
942 | /* Done */ | 1072 | /* Done */ |
943 | dprintk("<-- nfs4_init_server() = %d\n", error); | 1073 | dprintk("<-- nfs4_init_server() = %d\n", error); |
944 | return error; | 1074 | return error; |
@@ -961,17 +1091,6 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
961 | if (!server) | 1091 | if (!server) |
962 | return ERR_PTR(-ENOMEM); | 1092 | return ERR_PTR(-ENOMEM); |
963 | 1093 | ||
964 | /* Get a client record */ | ||
965 | error = nfs4_set_client(server, | ||
966 | data->nfs_server.hostname, | ||
967 | &data->nfs_server.address, | ||
968 | data->client_address, | ||
969 | data->auth_flavors[0], | ||
970 | data->nfs_server.protocol, | ||
971 | data->timeo, data->retrans); | ||
972 | if (error < 0) | ||
973 | goto error; | ||
974 | |||
975 | /* set up the general RPC client */ | 1094 | /* set up the general RPC client */ |
976 | error = nfs4_init_server(server, data); | 1095 | error = nfs4_init_server(server, data); |
977 | if (error < 0) | 1096 | if (error < 0) |
@@ -1039,12 +1158,13 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1039 | 1158 | ||
1040 | /* Get a client representation. | 1159 | /* Get a client representation. |
1041 | * Note: NFSv4 always uses TCP, */ | 1160 | * Note: NFSv4 always uses TCP, */ |
1042 | error = nfs4_set_client(server, data->hostname, data->addr, | 1161 | error = nfs4_set_client(server, data->hostname, |
1043 | parent_client->cl_ipaddr, | 1162 | data->addr, |
1044 | data->authflavor, | 1163 | data->addrlen, |
1045 | parent_server->client->cl_xprt->prot, | 1164 | parent_client->cl_ipaddr, |
1046 | parent_client->retrans_timeo, | 1165 | data->authflavor, |
1047 | parent_client->retrans_count); | 1166 | parent_server->client->cl_xprt->prot, |
1167 | parent_server->client->cl_timeout); | ||
1048 | if (error < 0) | 1168 | if (error < 0) |
1049 | goto error; | 1169 | goto error; |
1050 | 1170 | ||
@@ -1052,7 +1172,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1052 | nfs_server_copy_userdata(server, parent_server); | 1172 | nfs_server_copy_userdata(server, parent_server); |
1053 | server->caps |= NFS_CAP_ATOMIC_OPEN; | 1173 | server->caps |= NFS_CAP_ATOMIC_OPEN; |
1054 | 1174 | ||
1055 | error = nfs_init_server_rpcclient(server, data->authflavor); | 1175 | error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); |
1056 | if (error < 0) | 1176 | if (error < 0) |
1057 | goto error; | 1177 | goto error; |
1058 | 1178 | ||
@@ -1121,7 +1241,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1121 | 1241 | ||
1122 | server->fsid = fattr->fsid; | 1242 | server->fsid = fattr->fsid; |
1123 | 1243 | ||
1124 | error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); | 1244 | error = nfs_init_server_rpcclient(server, |
1245 | source->client->cl_timeout, | ||
1246 | source->client->cl_auth->au_flavor); | ||
1125 | if (error < 0) | 1247 | if (error < 0) |
1126 | goto out_free_server; | 1248 | goto out_free_server; |
1127 | if (!IS_ERR(source->client_acl)) | 1249 | if (!IS_ERR(source->client_acl)) |
@@ -1263,10 +1385,10 @@ static int nfs_server_list_show(struct seq_file *m, void *v) | |||
1263 | /* display one transport per line on subsequent lines */ | 1385 | /* display one transport per line on subsequent lines */ |
1264 | clp = list_entry(v, struct nfs_client, cl_share_link); | 1386 | clp = list_entry(v, struct nfs_client, cl_share_link); |
1265 | 1387 | ||
1266 | seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", | 1388 | seq_printf(m, "v%u %s %s %3d %s\n", |
1267 | clp->cl_nfsversion, | 1389 | clp->rpc_ops->version, |
1268 | NIPQUAD(clp->cl_addr.sin_addr), | 1390 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1269 | ntohs(clp->cl_addr.sin_port), | 1391 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1270 | atomic_read(&clp->cl_count), | 1392 | atomic_read(&clp->cl_count), |
1271 | clp->cl_hostname); | 1393 | clp->cl_hostname); |
1272 | 1394 | ||
@@ -1342,10 +1464,10 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) | |||
1342 | (unsigned long long) server->fsid.major, | 1464 | (unsigned long long) server->fsid.major, |
1343 | (unsigned long long) server->fsid.minor); | 1465 | (unsigned long long) server->fsid.minor); |
1344 | 1466 | ||
1345 | seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", | 1467 | seq_printf(m, "v%u %s %s %-7s %-17s\n", |
1346 | clp->cl_nfsversion, | 1468 | clp->rpc_ops->version, |
1347 | NIPQUAD(clp->cl_addr.sin_addr), | 1469 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1348 | ntohs(clp->cl_addr.sin_port), | 1470 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1349 | dev, | 1471 | dev, |
1350 | fsid); | 1472 | fsid); |
1351 | 1473 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 11833f4caeaa..b9eadd18ba70 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -125,6 +125,32 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st | |||
125 | put_rpccred(oldcred); | 125 | put_rpccred(oldcred); |
126 | } | 126 | } |
127 | 127 | ||
128 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) | ||
129 | { | ||
130 | int res = 0; | ||
131 | |||
132 | res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); | ||
133 | nfs_free_delegation(delegation); | ||
134 | return res; | ||
135 | } | ||
136 | |||
137 | static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) | ||
138 | { | ||
139 | struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); | ||
140 | |||
141 | if (delegation == NULL) | ||
142 | goto nomatch; | ||
143 | if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, | ||
144 | sizeof(delegation->stateid.data)) != 0) | ||
145 | goto nomatch; | ||
146 | list_del_rcu(&delegation->super_list); | ||
147 | nfsi->delegation_state = 0; | ||
148 | rcu_assign_pointer(nfsi->delegation, NULL); | ||
149 | return delegation; | ||
150 | nomatch: | ||
151 | return NULL; | ||
152 | } | ||
153 | |||
128 | /* | 154 | /* |
129 | * Set up a delegation on an inode | 155 | * Set up a delegation on an inode |
130 | */ | 156 | */ |
@@ -133,6 +159,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
133 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 159 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
134 | struct nfs_inode *nfsi = NFS_I(inode); | 160 | struct nfs_inode *nfsi = NFS_I(inode); |
135 | struct nfs_delegation *delegation; | 161 | struct nfs_delegation *delegation; |
162 | struct nfs_delegation *freeme = NULL; | ||
136 | int status = 0; | 163 | int status = 0; |
137 | 164 | ||
138 | delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); | 165 | delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); |
@@ -147,41 +174,45 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
147 | delegation->inode = inode; | 174 | delegation->inode = inode; |
148 | 175 | ||
149 | spin_lock(&clp->cl_lock); | 176 | spin_lock(&clp->cl_lock); |
150 | if (rcu_dereference(nfsi->delegation) == NULL) { | 177 | if (rcu_dereference(nfsi->delegation) != NULL) { |
151 | list_add_rcu(&delegation->super_list, &clp->cl_delegations); | ||
152 | nfsi->delegation_state = delegation->type; | ||
153 | rcu_assign_pointer(nfsi->delegation, delegation); | ||
154 | delegation = NULL; | ||
155 | } else { | ||
156 | if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, | 178 | if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, |
157 | sizeof(delegation->stateid)) != 0 || | 179 | sizeof(delegation->stateid)) == 0 && |
158 | delegation->type != nfsi->delegation->type) { | 180 | delegation->type == nfsi->delegation->type) { |
159 | printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n", | 181 | goto out; |
160 | __FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr)); | 182 | } |
161 | status = -EIO; | 183 | /* |
184 | * Deal with broken servers that hand out two | ||
185 | * delegations for the same file. | ||
186 | */ | ||
187 | dfprintk(FILE, "%s: server %s handed out " | ||
188 | "a duplicate delegation!\n", | ||
189 | __FUNCTION__, clp->cl_hostname); | ||
190 | if (delegation->type <= nfsi->delegation->type) { | ||
191 | freeme = delegation; | ||
192 | delegation = NULL; | ||
193 | goto out; | ||
162 | } | 194 | } |
195 | freeme = nfs_detach_delegation_locked(nfsi, NULL); | ||
163 | } | 196 | } |
197 | list_add_rcu(&delegation->super_list, &clp->cl_delegations); | ||
198 | nfsi->delegation_state = delegation->type; | ||
199 | rcu_assign_pointer(nfsi->delegation, delegation); | ||
200 | delegation = NULL; | ||
164 | 201 | ||
165 | /* Ensure we revalidate the attributes and page cache! */ | 202 | /* Ensure we revalidate the attributes and page cache! */ |
166 | spin_lock(&inode->i_lock); | 203 | spin_lock(&inode->i_lock); |
167 | nfsi->cache_validity |= NFS_INO_REVAL_FORCED; | 204 | nfsi->cache_validity |= NFS_INO_REVAL_FORCED; |
168 | spin_unlock(&inode->i_lock); | 205 | spin_unlock(&inode->i_lock); |
169 | 206 | ||
207 | out: | ||
170 | spin_unlock(&clp->cl_lock); | 208 | spin_unlock(&clp->cl_lock); |
171 | if (delegation != NULL) | 209 | if (delegation != NULL) |
172 | nfs_free_delegation(delegation); | 210 | nfs_free_delegation(delegation); |
211 | if (freeme != NULL) | ||
212 | nfs_do_return_delegation(inode, freeme, 0); | ||
173 | return status; | 213 | return status; |
174 | } | 214 | } |
175 | 215 | ||
176 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation) | ||
177 | { | ||
178 | int res = 0; | ||
179 | |||
180 | res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); | ||
181 | nfs_free_delegation(delegation); | ||
182 | return res; | ||
183 | } | ||
184 | |||
185 | /* Sync all data to disk upon delegation return */ | 216 | /* Sync all data to disk upon delegation return */ |
186 | static void nfs_msync_inode(struct inode *inode) | 217 | static void nfs_msync_inode(struct inode *inode) |
187 | { | 218 | { |
@@ -207,24 +238,28 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat | |||
207 | up_read(&clp->cl_sem); | 238 | up_read(&clp->cl_sem); |
208 | nfs_msync_inode(inode); | 239 | nfs_msync_inode(inode); |
209 | 240 | ||
210 | return nfs_do_return_delegation(inode, delegation); | 241 | return nfs_do_return_delegation(inode, delegation, 1); |
211 | } | 242 | } |
212 | 243 | ||
213 | static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) | 244 | /* |
245 | * This function returns the delegation without reclaiming opens | ||
246 | * or protecting against delegation reclaims. | ||
247 | * It is therefore really only safe to be called from | ||
248 | * nfs4_clear_inode() | ||
249 | */ | ||
250 | void nfs_inode_return_delegation_noreclaim(struct inode *inode) | ||
214 | { | 251 | { |
215 | struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); | 252 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
253 | struct nfs_inode *nfsi = NFS_I(inode); | ||
254 | struct nfs_delegation *delegation; | ||
216 | 255 | ||
217 | if (delegation == NULL) | 256 | if (rcu_dereference(nfsi->delegation) != NULL) { |
218 | goto nomatch; | 257 | spin_lock(&clp->cl_lock); |
219 | if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, | 258 | delegation = nfs_detach_delegation_locked(nfsi, NULL); |
220 | sizeof(delegation->stateid.data)) != 0) | 259 | spin_unlock(&clp->cl_lock); |
221 | goto nomatch; | 260 | if (delegation != NULL) |
222 | list_del_rcu(&delegation->super_list); | 261 | nfs_do_return_delegation(inode, delegation, 0); |
223 | nfsi->delegation_state = 0; | 262 | } |
224 | rcu_assign_pointer(nfsi->delegation, NULL); | ||
225 | return delegation; | ||
226 | nomatch: | ||
227 | return NULL; | ||
228 | } | 263 | } |
229 | 264 | ||
230 | int nfs_inode_return_delegation(struct inode *inode) | 265 | int nfs_inode_return_delegation(struct inode *inode) |
@@ -314,8 +349,9 @@ void nfs_expire_all_delegations(struct nfs_client *clp) | |||
314 | __module_get(THIS_MODULE); | 349 | __module_get(THIS_MODULE); |
315 | atomic_inc(&clp->cl_count); | 350 | atomic_inc(&clp->cl_count); |
316 | task = kthread_run(nfs_do_expire_all_delegations, clp, | 351 | task = kthread_run(nfs_do_expire_all_delegations, clp, |
317 | "%u.%u.%u.%u-delegreturn", | 352 | "%s-delegreturn", |
318 | NIPQUAD(clp->cl_addr.sin_addr)); | 353 | rpc_peeraddr2str(clp->cl_rpcclient, |
354 | RPC_DISPLAY_ADDR)); | ||
319 | if (!IS_ERR(task)) | 355 | if (!IS_ERR(task)) |
320 | return; | 356 | return; |
321 | nfs_put_client(clp); | 357 | nfs_put_client(clp); |
@@ -386,7 +422,7 @@ static int recall_thread(void *data) | |||
386 | nfs_msync_inode(inode); | 422 | nfs_msync_inode(inode); |
387 | 423 | ||
388 | if (delegation != NULL) | 424 | if (delegation != NULL) |
389 | nfs_do_return_delegation(inode, delegation); | 425 | nfs_do_return_delegation(inode, delegation, 1); |
390 | iput(inode); | 426 | iput(inode); |
391 | module_put_and_exit(0); | 427 | module_put_and_exit(0); |
392 | } | 428 | } |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 5874ce7fdbae..f1c5e2a5d88e 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -29,6 +29,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
29 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 29 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
30 | int nfs_inode_return_delegation(struct inode *inode); | 30 | int nfs_inode_return_delegation(struct inode *inode); |
31 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); | 31 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
32 | void nfs_inode_return_delegation_noreclaim(struct inode *inode); | ||
32 | 33 | ||
33 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); | 34 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); |
34 | void nfs_return_all_delegations(struct super_block *sb); | 35 | void nfs_return_all_delegations(struct super_block *sb); |
@@ -39,7 +40,7 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp); | |||
39 | void nfs_delegation_reap_unclaimed(struct nfs_client *clp); | 40 | void nfs_delegation_reap_unclaimed(struct nfs_client *clp); |
40 | 41 | ||
41 | /* NFSv4 delegation-related procedures */ | 42 | /* NFSv4 delegation-related procedures */ |
42 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); | 43 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync); |
43 | int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid); | 44 | int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid); |
44 | int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl); | 45 | int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl); |
45 | int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode); | 46 | int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index f697b5c74b7c..476cb0f837fd 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -192,7 +192,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
192 | /* We requested READDIRPLUS, but the server doesn't grok it */ | 192 | /* We requested READDIRPLUS, but the server doesn't grok it */ |
193 | if (error == -ENOTSUPP && desc->plus) { | 193 | if (error == -ENOTSUPP && desc->plus) { |
194 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; | 194 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; |
195 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 195 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
196 | desc->plus = 0; | 196 | desc->plus = 0; |
197 | goto again; | 197 | goto again; |
198 | } | 198 | } |
@@ -537,12 +537,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
537 | 537 | ||
538 | lock_kernel(); | 538 | lock_kernel(); |
539 | 539 | ||
540 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); | ||
541 | if (res < 0) { | ||
542 | unlock_kernel(); | ||
543 | return res; | ||
544 | } | ||
545 | |||
546 | /* | 540 | /* |
547 | * filp->f_pos points to the dirent entry number. | 541 | * filp->f_pos points to the dirent entry number. |
548 | * *desc->dir_cookie has the cookie for the next entry. We have | 542 | * *desc->dir_cookie has the cookie for the next entry. We have |
@@ -564,6 +558,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
564 | desc->entry = &my_entry; | 558 | desc->entry = &my_entry; |
565 | 559 | ||
566 | nfs_block_sillyrename(dentry); | 560 | nfs_block_sillyrename(dentry); |
561 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); | ||
562 | if (res < 0) | ||
563 | goto out; | ||
564 | |||
567 | while(!desc->entry->eof) { | 565 | while(!desc->entry->eof) { |
568 | res = readdir_search_pagecache(desc); | 566 | res = readdir_search_pagecache(desc); |
569 | 567 | ||
@@ -579,7 +577,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
579 | break; | 577 | break; |
580 | } | 578 | } |
581 | if (res == -ETOOSMALL && desc->plus) { | 579 | if (res == -ETOOSMALL && desc->plus) { |
582 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 580 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
583 | nfs_zap_caches(inode); | 581 | nfs_zap_caches(inode); |
584 | desc->plus = 0; | 582 | desc->plus = 0; |
585 | desc->entry->eof = 0; | 583 | desc->entry->eof = 0; |
@@ -594,6 +592,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
594 | break; | 592 | break; |
595 | } | 593 | } |
596 | } | 594 | } |
595 | out: | ||
597 | nfs_unblock_sillyrename(dentry); | 596 | nfs_unblock_sillyrename(dentry); |
598 | unlock_kernel(); | 597 | unlock_kernel(); |
599 | if (res > 0) | 598 | if (res > 0) |
@@ -639,6 +638,21 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
639 | return 0; | 638 | return 0; |
640 | } | 639 | } |
641 | 640 | ||
641 | /** | ||
642 | * nfs_force_lookup_revalidate - Mark the directory as having changed | ||
643 | * @dir - pointer to directory inode | ||
644 | * | ||
645 | * This forces the revalidation code in nfs_lookup_revalidate() to do a | ||
646 | * full lookup on all child dentries of 'dir' whenever a change occurs | ||
647 | * on the server that might have invalidated our dcache. | ||
648 | * | ||
649 | * The caller should be holding dir->i_lock | ||
650 | */ | ||
651 | void nfs_force_lookup_revalidate(struct inode *dir) | ||
652 | { | ||
653 | NFS_I(dir)->cache_change_attribute = jiffies; | ||
654 | } | ||
655 | |||
642 | /* | 656 | /* |
643 | * A check for whether or not the parent directory has changed. | 657 | * A check for whether or not the parent directory has changed. |
644 | * In the case it has, we assume that the dentries are untrustworthy | 658 | * In the case it has, we assume that the dentries are untrustworthy |
@@ -827,6 +841,10 @@ static int nfs_dentry_delete(struct dentry *dentry) | |||
827 | dentry->d_parent->d_name.name, dentry->d_name.name, | 841 | dentry->d_parent->d_name.name, dentry->d_name.name, |
828 | dentry->d_flags); | 842 | dentry->d_flags); |
829 | 843 | ||
844 | /* Unhash any dentry with a stale inode */ | ||
845 | if (dentry->d_inode != NULL && NFS_STALE(dentry->d_inode)) | ||
846 | return 1; | ||
847 | |||
830 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { | 848 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { |
831 | /* Unhash it, so that ->d_iput() would be called */ | 849 | /* Unhash it, so that ->d_iput() would be called */ |
832 | return 1; | 850 | return 1; |
@@ -846,7 +864,6 @@ static int nfs_dentry_delete(struct dentry *dentry) | |||
846 | */ | 864 | */ |
847 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 865 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) |
848 | { | 866 | { |
849 | nfs_inode_return_delegation(inode); | ||
850 | if (S_ISDIR(inode->i_mode)) | 867 | if (S_ISDIR(inode->i_mode)) |
851 | /* drop any readdir cache as it could easily be old */ | 868 | /* drop any readdir cache as it could easily be old */ |
852 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; | 869 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; |
@@ -1268,6 +1285,12 @@ out_err: | |||
1268 | return error; | 1285 | return error; |
1269 | } | 1286 | } |
1270 | 1287 | ||
1288 | static void nfs_dentry_handle_enoent(struct dentry *dentry) | ||
1289 | { | ||
1290 | if (dentry->d_inode != NULL && !d_unhashed(dentry)) | ||
1291 | d_delete(dentry); | ||
1292 | } | ||
1293 | |||
1271 | static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | 1294 | static int nfs_rmdir(struct inode *dir, struct dentry *dentry) |
1272 | { | 1295 | { |
1273 | int error; | 1296 | int error; |
@@ -1280,6 +1303,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1280 | /* Ensure the VFS deletes this inode */ | 1303 | /* Ensure the VFS deletes this inode */ |
1281 | if (error == 0 && dentry->d_inode != NULL) | 1304 | if (error == 0 && dentry->d_inode != NULL) |
1282 | clear_nlink(dentry->d_inode); | 1305 | clear_nlink(dentry->d_inode); |
1306 | else if (error == -ENOENT) | ||
1307 | nfs_dentry_handle_enoent(dentry); | ||
1283 | unlock_kernel(); | 1308 | unlock_kernel(); |
1284 | 1309 | ||
1285 | return error; | 1310 | return error; |
@@ -1386,6 +1411,8 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1386 | nfs_mark_for_revalidate(inode); | 1411 | nfs_mark_for_revalidate(inode); |
1387 | } else | 1412 | } else |
1388 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1413 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1414 | if (error == -ENOENT) | ||
1415 | nfs_dentry_handle_enoent(dentry); | ||
1389 | out: | 1416 | out: |
1390 | return error; | 1417 | return error; |
1391 | } | 1418 | } |
@@ -1422,7 +1449,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1422 | spin_unlock(&dentry->d_lock); | 1449 | spin_unlock(&dentry->d_lock); |
1423 | spin_unlock(&dcache_lock); | 1450 | spin_unlock(&dcache_lock); |
1424 | error = nfs_safe_remove(dentry); | 1451 | error = nfs_safe_remove(dentry); |
1425 | if (!error) { | 1452 | if (!error || error == -ENOENT) { |
1426 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1453 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1427 | } else if (need_rehash) | 1454 | } else if (need_rehash) |
1428 | d_rehash(dentry); | 1455 | d_rehash(dentry); |
@@ -1635,7 +1662,8 @@ out: | |||
1635 | d_move(old_dentry, new_dentry); | 1662 | d_move(old_dentry, new_dentry); |
1636 | nfs_set_verifier(new_dentry, | 1663 | nfs_set_verifier(new_dentry, |
1637 | nfs_save_change_attribute(new_dir)); | 1664 | nfs_save_change_attribute(new_dir)); |
1638 | } | 1665 | } else if (error == -ENOENT) |
1666 | nfs_dentry_handle_enoent(old_dentry); | ||
1639 | 1667 | ||
1640 | /* new dentry created? */ | 1668 | /* new dentry created? */ |
1641 | if (dentry) | 1669 | if (dentry) |
@@ -1666,13 +1694,19 @@ int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | |||
1666 | restart: | 1694 | restart: |
1667 | spin_lock(&nfs_access_lru_lock); | 1695 | spin_lock(&nfs_access_lru_lock); |
1668 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { | 1696 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { |
1697 | struct rw_semaphore *s_umount; | ||
1669 | struct inode *inode; | 1698 | struct inode *inode; |
1670 | 1699 | ||
1671 | if (nr_to_scan-- == 0) | 1700 | if (nr_to_scan-- == 0) |
1672 | break; | 1701 | break; |
1702 | s_umount = &nfsi->vfs_inode.i_sb->s_umount; | ||
1703 | if (!down_read_trylock(s_umount)) | ||
1704 | continue; | ||
1673 | inode = igrab(&nfsi->vfs_inode); | 1705 | inode = igrab(&nfsi->vfs_inode); |
1674 | if (inode == NULL) | 1706 | if (inode == NULL) { |
1707 | up_read(s_umount); | ||
1675 | continue; | 1708 | continue; |
1709 | } | ||
1676 | spin_lock(&inode->i_lock); | 1710 | spin_lock(&inode->i_lock); |
1677 | if (list_empty(&nfsi->access_cache_entry_lru)) | 1711 | if (list_empty(&nfsi->access_cache_entry_lru)) |
1678 | goto remove_lru_entry; | 1712 | goto remove_lru_entry; |
@@ -1691,6 +1725,7 @@ remove_lru_entry: | |||
1691 | spin_unlock(&inode->i_lock); | 1725 | spin_unlock(&inode->i_lock); |
1692 | spin_unlock(&nfs_access_lru_lock); | 1726 | spin_unlock(&nfs_access_lru_lock); |
1693 | iput(inode); | 1727 | iput(inode); |
1728 | up_read(s_umount); | ||
1694 | goto restart; | 1729 | goto restart; |
1695 | } | 1730 | } |
1696 | spin_unlock(&nfs_access_lru_lock); | 1731 | spin_unlock(&nfs_access_lru_lock); |
@@ -1731,7 +1766,7 @@ static void __nfs_access_zap_cache(struct inode *inode) | |||
1731 | void nfs_access_zap_cache(struct inode *inode) | 1766 | void nfs_access_zap_cache(struct inode *inode) |
1732 | { | 1767 | { |
1733 | /* Remove from global LRU init */ | 1768 | /* Remove from global LRU init */ |
1734 | if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | 1769 | if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { |
1735 | spin_lock(&nfs_access_lru_lock); | 1770 | spin_lock(&nfs_access_lru_lock); |
1736 | list_del_init(&NFS_I(inode)->access_cache_inode_lru); | 1771 | list_del_init(&NFS_I(inode)->access_cache_inode_lru); |
1737 | spin_unlock(&nfs_access_lru_lock); | 1772 | spin_unlock(&nfs_access_lru_lock); |
@@ -1845,7 +1880,7 @@ static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *s | |||
1845 | smp_mb__after_atomic_inc(); | 1880 | smp_mb__after_atomic_inc(); |
1846 | 1881 | ||
1847 | /* Add inode to global LRU list */ | 1882 | /* Add inode to global LRU list */ |
1848 | if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { | 1883 | if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_I(inode)->flags)) { |
1849 | spin_lock(&nfs_access_lru_lock); | 1884 | spin_lock(&nfs_access_lru_lock); |
1850 | list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); | 1885 | list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); |
1851 | spin_unlock(&nfs_access_lru_lock); | 1886 | spin_unlock(&nfs_access_lru_lock); |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 3c9d16b4f80c..f8e165c7d5a6 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -188,12 +188,17 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq) | |||
188 | static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) | 188 | static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) |
189 | { | 189 | { |
190 | ssize_t result = -EIOCBQUEUED; | 190 | ssize_t result = -EIOCBQUEUED; |
191 | struct rpc_clnt *clnt; | ||
192 | sigset_t oldset; | ||
191 | 193 | ||
192 | /* Async requests don't wait here */ | 194 | /* Async requests don't wait here */ |
193 | if (dreq->iocb) | 195 | if (dreq->iocb) |
194 | goto out; | 196 | goto out; |
195 | 197 | ||
198 | clnt = NFS_CLIENT(dreq->inode); | ||
199 | rpc_clnt_sigmask(clnt, &oldset); | ||
196 | result = wait_for_completion_interruptible(&dreq->completion); | 200 | result = wait_for_completion_interruptible(&dreq->completion); |
201 | rpc_clnt_sigunmask(clnt, &oldset); | ||
197 | 202 | ||
198 | if (!result) | 203 | if (!result) |
199 | result = dreq->error; | 204 | result = dreq->error; |
@@ -272,6 +277,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | 277 | unsigned long user_addr = (unsigned long)iov->iov_base; |
273 | size_t count = iov->iov_len; | 278 | size_t count = iov->iov_len; |
274 | size_t rsize = NFS_SERVER(inode)->rsize; | 279 | size_t rsize = NFS_SERVER(inode)->rsize; |
280 | struct rpc_task *task; | ||
281 | struct rpc_message msg = { | ||
282 | .rpc_cred = ctx->cred, | ||
283 | }; | ||
284 | struct rpc_task_setup task_setup_data = { | ||
285 | .rpc_client = NFS_CLIENT(inode), | ||
286 | .rpc_message = &msg, | ||
287 | .callback_ops = &nfs_read_direct_ops, | ||
288 | .flags = RPC_TASK_ASYNC, | ||
289 | }; | ||
275 | unsigned int pgbase; | 290 | unsigned int pgbase; |
276 | int result; | 291 | int result; |
277 | ssize_t started = 0; | 292 | ssize_t started = 0; |
@@ -311,7 +326,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
311 | 326 | ||
312 | data->req = (struct nfs_page *) dreq; | 327 | data->req = (struct nfs_page *) dreq; |
313 | data->inode = inode; | 328 | data->inode = inode; |
314 | data->cred = ctx->cred; | 329 | data->cred = msg.rpc_cred; |
315 | data->args.fh = NFS_FH(inode); | 330 | data->args.fh = NFS_FH(inode); |
316 | data->args.context = ctx; | 331 | data->args.context = ctx; |
317 | data->args.offset = pos; | 332 | data->args.offset = pos; |
@@ -321,14 +336,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
321 | data->res.fattr = &data->fattr; | 336 | data->res.fattr = &data->fattr; |
322 | data->res.eof = 0; | 337 | data->res.eof = 0; |
323 | data->res.count = bytes; | 338 | data->res.count = bytes; |
339 | msg.rpc_argp = &data->args; | ||
340 | msg.rpc_resp = &data->res; | ||
324 | 341 | ||
325 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 342 | task_setup_data.task = &data->task; |
326 | &nfs_read_direct_ops, data); | 343 | task_setup_data.callback_data = data; |
327 | NFS_PROTO(inode)->read_setup(data); | 344 | NFS_PROTO(inode)->read_setup(data, &msg); |
328 | |||
329 | data->task.tk_cookie = (unsigned long) inode; | ||
330 | 345 | ||
331 | rpc_execute(&data->task); | 346 | task = rpc_run_task(&task_setup_data); |
347 | if (!IS_ERR(task)) | ||
348 | rpc_put_task(task); | ||
332 | 349 | ||
333 | dprintk("NFS: %5u initiated direct read call " | 350 | dprintk("NFS: %5u initiated direct read call " |
334 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 351 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -391,9 +408,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
391 | unsigned long nr_segs, loff_t pos) | 408 | unsigned long nr_segs, loff_t pos) |
392 | { | 409 | { |
393 | ssize_t result = 0; | 410 | ssize_t result = 0; |
394 | sigset_t oldset; | ||
395 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 411 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
396 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
397 | struct nfs_direct_req *dreq; | 412 | struct nfs_direct_req *dreq; |
398 | 413 | ||
399 | dreq = nfs_direct_req_alloc(); | 414 | dreq = nfs_direct_req_alloc(); |
@@ -405,11 +420,9 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
405 | if (!is_sync_kiocb(iocb)) | 420 | if (!is_sync_kiocb(iocb)) |
406 | dreq->iocb = iocb; | 421 | dreq->iocb = iocb; |
407 | 422 | ||
408 | rpc_clnt_sigmask(clnt, &oldset); | ||
409 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); | 423 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
410 | if (!result) | 424 | if (!result) |
411 | result = nfs_direct_wait(dreq); | 425 | result = nfs_direct_wait(dreq); |
412 | rpc_clnt_sigunmask(clnt, &oldset); | ||
413 | nfs_direct_req_release(dreq); | 426 | nfs_direct_req_release(dreq); |
414 | 427 | ||
415 | return result; | 428 | return result; |
@@ -431,6 +444,15 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
431 | struct inode *inode = dreq->inode; | 444 | struct inode *inode = dreq->inode; |
432 | struct list_head *p; | 445 | struct list_head *p; |
433 | struct nfs_write_data *data; | 446 | struct nfs_write_data *data; |
447 | struct rpc_task *task; | ||
448 | struct rpc_message msg = { | ||
449 | .rpc_cred = dreq->ctx->cred, | ||
450 | }; | ||
451 | struct rpc_task_setup task_setup_data = { | ||
452 | .rpc_client = NFS_CLIENT(inode), | ||
453 | .callback_ops = &nfs_write_direct_ops, | ||
454 | .flags = RPC_TASK_ASYNC, | ||
455 | }; | ||
434 | 456 | ||
435 | dreq->count = 0; | 457 | dreq->count = 0; |
436 | get_dreq(dreq); | 458 | get_dreq(dreq); |
@@ -440,6 +462,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
440 | 462 | ||
441 | get_dreq(dreq); | 463 | get_dreq(dreq); |
442 | 464 | ||
465 | /* Use stable writes */ | ||
466 | data->args.stable = NFS_FILE_SYNC; | ||
467 | |||
443 | /* | 468 | /* |
444 | * Reset data->res. | 469 | * Reset data->res. |
445 | */ | 470 | */ |
@@ -451,17 +476,18 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
451 | * Reuse data->task; data->args should not have changed | 476 | * Reuse data->task; data->args should not have changed |
452 | * since the original request was sent. | 477 | * since the original request was sent. |
453 | */ | 478 | */ |
454 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 479 | task_setup_data.task = &data->task; |
455 | &nfs_write_direct_ops, data); | 480 | task_setup_data.callback_data = data; |
456 | NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); | 481 | msg.rpc_argp = &data->args; |
457 | 482 | msg.rpc_resp = &data->res; | |
458 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 483 | NFS_PROTO(inode)->write_setup(data, &msg); |
459 | data->task.tk_cookie = (unsigned long) inode; | ||
460 | 484 | ||
461 | /* | 485 | /* |
462 | * We're called via an RPC callback, so BKL is already held. | 486 | * We're called via an RPC callback, so BKL is already held. |
463 | */ | 487 | */ |
464 | rpc_execute(&data->task); | 488 | task = rpc_run_task(&task_setup_data); |
489 | if (!IS_ERR(task)) | ||
490 | rpc_put_task(task); | ||
465 | 491 | ||
466 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 492 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
467 | data->task.tk_pid, | 493 | data->task.tk_pid, |
@@ -504,9 +530,23 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { | |||
504 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 530 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
505 | { | 531 | { |
506 | struct nfs_write_data *data = dreq->commit_data; | 532 | struct nfs_write_data *data = dreq->commit_data; |
533 | struct rpc_task *task; | ||
534 | struct rpc_message msg = { | ||
535 | .rpc_argp = &data->args, | ||
536 | .rpc_resp = &data->res, | ||
537 | .rpc_cred = dreq->ctx->cred, | ||
538 | }; | ||
539 | struct rpc_task_setup task_setup_data = { | ||
540 | .task = &data->task, | ||
541 | .rpc_client = NFS_CLIENT(dreq->inode), | ||
542 | .rpc_message = &msg, | ||
543 | .callback_ops = &nfs_commit_direct_ops, | ||
544 | .callback_data = data, | ||
545 | .flags = RPC_TASK_ASYNC, | ||
546 | }; | ||
507 | 547 | ||
508 | data->inode = dreq->inode; | 548 | data->inode = dreq->inode; |
509 | data->cred = dreq->ctx->cred; | 549 | data->cred = msg.rpc_cred; |
510 | 550 | ||
511 | data->args.fh = NFS_FH(data->inode); | 551 | data->args.fh = NFS_FH(data->inode); |
512 | data->args.offset = 0; | 552 | data->args.offset = 0; |
@@ -515,18 +555,16 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
515 | data->res.fattr = &data->fattr; | 555 | data->res.fattr = &data->fattr; |
516 | data->res.verf = &data->verf; | 556 | data->res.verf = &data->verf; |
517 | 557 | ||
518 | rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC, | 558 | NFS_PROTO(data->inode)->commit_setup(data, &msg); |
519 | &nfs_commit_direct_ops, data); | ||
520 | NFS_PROTO(data->inode)->commit_setup(data, 0); | ||
521 | 559 | ||
522 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | ||
523 | data->task.tk_cookie = (unsigned long)data->inode; | ||
524 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ | 560 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ |
525 | dreq->commit_data = NULL; | 561 | dreq->commit_data = NULL; |
526 | 562 | ||
527 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 563 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
528 | 564 | ||
529 | rpc_execute(&data->task); | 565 | task = rpc_run_task(&task_setup_data); |
566 | if (!IS_ERR(task)) | ||
567 | rpc_put_task(task); | ||
530 | } | 568 | } |
531 | 569 | ||
532 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 570 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
@@ -641,6 +679,16 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
641 | struct inode *inode = ctx->path.dentry->d_inode; | 679 | struct inode *inode = ctx->path.dentry->d_inode; |
642 | unsigned long user_addr = (unsigned long)iov->iov_base; | 680 | unsigned long user_addr = (unsigned long)iov->iov_base; |
643 | size_t count = iov->iov_len; | 681 | size_t count = iov->iov_len; |
682 | struct rpc_task *task; | ||
683 | struct rpc_message msg = { | ||
684 | .rpc_cred = ctx->cred, | ||
685 | }; | ||
686 | struct rpc_task_setup task_setup_data = { | ||
687 | .rpc_client = NFS_CLIENT(inode), | ||
688 | .rpc_message = &msg, | ||
689 | .callback_ops = &nfs_write_direct_ops, | ||
690 | .flags = RPC_TASK_ASYNC, | ||
691 | }; | ||
644 | size_t wsize = NFS_SERVER(inode)->wsize; | 692 | size_t wsize = NFS_SERVER(inode)->wsize; |
645 | unsigned int pgbase; | 693 | unsigned int pgbase; |
646 | int result; | 694 | int result; |
@@ -683,25 +731,27 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
683 | 731 | ||
684 | data->req = (struct nfs_page *) dreq; | 732 | data->req = (struct nfs_page *) dreq; |
685 | data->inode = inode; | 733 | data->inode = inode; |
686 | data->cred = ctx->cred; | 734 | data->cred = msg.rpc_cred; |
687 | data->args.fh = NFS_FH(inode); | 735 | data->args.fh = NFS_FH(inode); |
688 | data->args.context = ctx; | 736 | data->args.context = ctx; |
689 | data->args.offset = pos; | 737 | data->args.offset = pos; |
690 | data->args.pgbase = pgbase; | 738 | data->args.pgbase = pgbase; |
691 | data->args.pages = data->pagevec; | 739 | data->args.pages = data->pagevec; |
692 | data->args.count = bytes; | 740 | data->args.count = bytes; |
741 | data->args.stable = sync; | ||
693 | data->res.fattr = &data->fattr; | 742 | data->res.fattr = &data->fattr; |
694 | data->res.count = bytes; | 743 | data->res.count = bytes; |
695 | data->res.verf = &data->verf; | 744 | data->res.verf = &data->verf; |
696 | 745 | ||
697 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 746 | task_setup_data.task = &data->task; |
698 | &nfs_write_direct_ops, data); | 747 | task_setup_data.callback_data = data; |
699 | NFS_PROTO(inode)->write_setup(data, sync); | 748 | msg.rpc_argp = &data->args; |
700 | 749 | msg.rpc_resp = &data->res; | |
701 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 750 | NFS_PROTO(inode)->write_setup(data, &msg); |
702 | data->task.tk_cookie = (unsigned long) inode; | ||
703 | 751 | ||
704 | rpc_execute(&data->task); | 752 | task = rpc_run_task(&task_setup_data); |
753 | if (!IS_ERR(task)) | ||
754 | rpc_put_task(task); | ||
705 | 755 | ||
706 | dprintk("NFS: %5u initiated direct write call " | 756 | dprintk("NFS: %5u initiated direct write call " |
707 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 757 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -767,12 +817,10 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
767 | size_t count) | 817 | size_t count) |
768 | { | 818 | { |
769 | ssize_t result = 0; | 819 | ssize_t result = 0; |
770 | sigset_t oldset; | ||
771 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 820 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
772 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
773 | struct nfs_direct_req *dreq; | 821 | struct nfs_direct_req *dreq; |
774 | size_t wsize = NFS_SERVER(inode)->wsize; | 822 | size_t wsize = NFS_SERVER(inode)->wsize; |
775 | int sync = 0; | 823 | int sync = NFS_UNSTABLE; |
776 | 824 | ||
777 | dreq = nfs_direct_req_alloc(); | 825 | dreq = nfs_direct_req_alloc(); |
778 | if (!dreq) | 826 | if (!dreq) |
@@ -780,18 +828,16 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
780 | nfs_alloc_commit_data(dreq); | 828 | nfs_alloc_commit_data(dreq); |
781 | 829 | ||
782 | if (dreq->commit_data == NULL || count < wsize) | 830 | if (dreq->commit_data == NULL || count < wsize) |
783 | sync = FLUSH_STABLE; | 831 | sync = NFS_FILE_SYNC; |
784 | 832 | ||
785 | dreq->inode = inode; | 833 | dreq->inode = inode; |
786 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 834 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
787 | if (!is_sync_kiocb(iocb)) | 835 | if (!is_sync_kiocb(iocb)) |
788 | dreq->iocb = iocb; | 836 | dreq->iocb = iocb; |
789 | 837 | ||
790 | rpc_clnt_sigmask(clnt, &oldset); | ||
791 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); | 838 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
792 | if (!result) | 839 | if (!result) |
793 | result = nfs_direct_wait(dreq); | 840 | result = nfs_direct_wait(dreq); |
794 | rpc_clnt_sigunmask(clnt, &oldset); | ||
795 | nfs_direct_req_release(dreq); | 841 | nfs_direct_req_release(dreq); |
796 | 842 | ||
797 | return result; | 843 | return result; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index b3bb89f7d5d2..ef57a5ae5904 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -349,7 +349,9 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
349 | unlock_page(page); | 349 | unlock_page(page); |
350 | page_cache_release(page); | 350 | page_cache_release(page); |
351 | 351 | ||
352 | return status < 0 ? status : copied; | 352 | if (status < 0) |
353 | return status; | ||
354 | return copied; | ||
353 | } | 355 | } |
354 | 356 | ||
355 | static void nfs_invalidate_page(struct page *page, unsigned long offset) | 357 | static void nfs_invalidate_page(struct page *page, unsigned long offset) |
@@ -392,35 +394,27 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
392 | struct file *filp = vma->vm_file; | 394 | struct file *filp = vma->vm_file; |
393 | unsigned pagelen; | 395 | unsigned pagelen; |
394 | int ret = -EINVAL; | 396 | int ret = -EINVAL; |
395 | void *fsdata; | ||
396 | struct address_space *mapping; | 397 | struct address_space *mapping; |
397 | loff_t offset; | ||
398 | 398 | ||
399 | lock_page(page); | 399 | lock_page(page); |
400 | mapping = page->mapping; | 400 | mapping = page->mapping; |
401 | if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) { | 401 | if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) |
402 | unlock_page(page); | 402 | goto out_unlock; |
403 | return -EINVAL; | 403 | |
404 | } | 404 | ret = 0; |
405 | pagelen = nfs_page_length(page); | 405 | pagelen = nfs_page_length(page); |
406 | offset = (loff_t)page->index << PAGE_CACHE_SHIFT; | 406 | if (pagelen == 0) |
407 | unlock_page(page); | 407 | goto out_unlock; |
408 | 408 | ||
409 | /* | 409 | ret = nfs_flush_incompatible(filp, page); |
410 | * we can use mapping after releasing the page lock, because: | 410 | if (ret != 0) |
411 | * we hold mmap_sem on the fault path, which should pin the vma | 411 | goto out_unlock; |
412 | * which should pin the file, which pins the dentry which should | ||
413 | * hold a reference on inode. | ||
414 | */ | ||
415 | 412 | ||
416 | if (pagelen) { | 413 | ret = nfs_updatepage(filp, page, 0, pagelen); |
417 | struct page *page2 = NULL; | 414 | if (ret == 0) |
418 | ret = nfs_write_begin(filp, mapping, offset, pagelen, | 415 | ret = pagelen; |
419 | 0, &page2, &fsdata); | 416 | out_unlock: |
420 | if (!ret) | 417 | unlock_page(page); |
421 | ret = nfs_write_end(filp, mapping, offset, pagelen, | ||
422 | pagelen, page2, fsdata); | ||
423 | } | ||
424 | return ret; | 418 | return ret; |
425 | } | 419 | } |
426 | 420 | ||
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index d11eb055265c..8ae5dba2d4e5 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -72,39 +72,39 @@ module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, | |||
72 | &nfs_idmap_cache_timeout, 0644); | 72 | &nfs_idmap_cache_timeout, 0644); |
73 | 73 | ||
74 | struct idmap_hashent { | 74 | struct idmap_hashent { |
75 | unsigned long ih_expires; | 75 | unsigned long ih_expires; |
76 | __u32 ih_id; | 76 | __u32 ih_id; |
77 | int ih_namelen; | 77 | size_t ih_namelen; |
78 | char ih_name[IDMAP_NAMESZ]; | 78 | char ih_name[IDMAP_NAMESZ]; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct idmap_hashtable { | 81 | struct idmap_hashtable { |
82 | __u8 h_type; | 82 | __u8 h_type; |
83 | struct idmap_hashent h_entries[IDMAP_HASH_SZ]; | 83 | struct idmap_hashent h_entries[IDMAP_HASH_SZ]; |
84 | }; | 84 | }; |
85 | 85 | ||
86 | struct idmap { | 86 | struct idmap { |
87 | struct dentry *idmap_dentry; | 87 | struct dentry *idmap_dentry; |
88 | wait_queue_head_t idmap_wq; | 88 | wait_queue_head_t idmap_wq; |
89 | struct idmap_msg idmap_im; | 89 | struct idmap_msg idmap_im; |
90 | struct mutex idmap_lock; /* Serializes upcalls */ | 90 | struct mutex idmap_lock; /* Serializes upcalls */ |
91 | struct mutex idmap_im_lock; /* Protects the hashtable */ | 91 | struct mutex idmap_im_lock; /* Protects the hashtable */ |
92 | struct idmap_hashtable idmap_user_hash; | 92 | struct idmap_hashtable idmap_user_hash; |
93 | struct idmap_hashtable idmap_group_hash; | 93 | struct idmap_hashtable idmap_group_hash; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, | 96 | static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, |
97 | char __user *, size_t); | 97 | char __user *, size_t); |
98 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, | 98 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, |
99 | size_t); | 99 | size_t); |
100 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | 100 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); |
101 | 101 | ||
102 | static unsigned int fnvhash32(const void *, size_t); | 102 | static unsigned int fnvhash32(const void *, size_t); |
103 | 103 | ||
104 | static struct rpc_pipe_ops idmap_upcall_ops = { | 104 | static struct rpc_pipe_ops idmap_upcall_ops = { |
105 | .upcall = idmap_pipe_upcall, | 105 | .upcall = idmap_pipe_upcall, |
106 | .downcall = idmap_pipe_downcall, | 106 | .downcall = idmap_pipe_downcall, |
107 | .destroy_msg = idmap_pipe_destroy_msg, | 107 | .destroy_msg = idmap_pipe_destroy_msg, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | int | 110 | int |
@@ -115,19 +115,20 @@ nfs_idmap_new(struct nfs_client *clp) | |||
115 | 115 | ||
116 | BUG_ON(clp->cl_idmap != NULL); | 116 | BUG_ON(clp->cl_idmap != NULL); |
117 | 117 | ||
118 | if ((idmap = kzalloc(sizeof(*idmap), GFP_KERNEL)) == NULL) | 118 | idmap = kzalloc(sizeof(*idmap), GFP_KERNEL); |
119 | return -ENOMEM; | 119 | if (idmap == NULL) |
120 | return -ENOMEM; | ||
120 | 121 | ||
121 | idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, "idmap", | 122 | idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, "idmap", |
122 | idmap, &idmap_upcall_ops, 0); | 123 | idmap, &idmap_upcall_ops, 0); |
123 | if (IS_ERR(idmap->idmap_dentry)) { | 124 | if (IS_ERR(idmap->idmap_dentry)) { |
124 | error = PTR_ERR(idmap->idmap_dentry); | 125 | error = PTR_ERR(idmap->idmap_dentry); |
125 | kfree(idmap); | 126 | kfree(idmap); |
126 | return error; | 127 | return error; |
127 | } | 128 | } |
128 | 129 | ||
129 | mutex_init(&idmap->idmap_lock); | 130 | mutex_init(&idmap->idmap_lock); |
130 | mutex_init(&idmap->idmap_im_lock); | 131 | mutex_init(&idmap->idmap_im_lock); |
131 | init_waitqueue_head(&idmap->idmap_wq); | 132 | init_waitqueue_head(&idmap->idmap_wq); |
132 | idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER; | 133 | idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER; |
133 | idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; | 134 | idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; |
@@ -192,7 +193,7 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id) | |||
192 | * pretty trivial. | 193 | * pretty trivial. |
193 | */ | 194 | */ |
194 | static inline struct idmap_hashent * | 195 | static inline struct idmap_hashent * |
195 | idmap_alloc_name(struct idmap_hashtable *h, char *name, unsigned len) | 196 | idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len) |
196 | { | 197 | { |
197 | return idmap_name_hash(h, name, len); | 198 | return idmap_name_hash(h, name, len); |
198 | } | 199 | } |
@@ -285,7 +286,7 @@ nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h, | |||
285 | memset(im, 0, sizeof(*im)); | 286 | memset(im, 0, sizeof(*im)); |
286 | mutex_unlock(&idmap->idmap_im_lock); | 287 | mutex_unlock(&idmap->idmap_im_lock); |
287 | mutex_unlock(&idmap->idmap_lock); | 288 | mutex_unlock(&idmap->idmap_lock); |
288 | return (ret); | 289 | return ret; |
289 | } | 290 | } |
290 | 291 | ||
291 | /* | 292 | /* |
@@ -354,42 +355,40 @@ nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h, | |||
354 | /* RPC pipefs upcall/downcall routines */ | 355 | /* RPC pipefs upcall/downcall routines */ |
355 | static ssize_t | 356 | static ssize_t |
356 | idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | 357 | idmap_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, |
357 | char __user *dst, size_t buflen) | 358 | char __user *dst, size_t buflen) |
358 | { | 359 | { |
359 | char *data = (char *)msg->data + msg->copied; | 360 | char *data = (char *)msg->data + msg->copied; |
360 | ssize_t mlen = msg->len - msg->copied; | 361 | size_t mlen = min(msg->len, buflen); |
361 | ssize_t left; | 362 | unsigned long left; |
362 | 363 | ||
363 | if (mlen > buflen) | 364 | left = copy_to_user(dst, data, mlen); |
364 | mlen = buflen; | 365 | if (left == mlen) { |
365 | 366 | msg->errno = -EFAULT; | |
366 | left = copy_to_user(dst, data, mlen); | 367 | return -EFAULT; |
367 | if (left < 0) { | ||
368 | msg->errno = left; | ||
369 | return left; | ||
370 | } | 368 | } |
369 | |||
371 | mlen -= left; | 370 | mlen -= left; |
372 | msg->copied += mlen; | 371 | msg->copied += mlen; |
373 | msg->errno = 0; | 372 | msg->errno = 0; |
374 | return mlen; | 373 | return mlen; |
375 | } | 374 | } |
376 | 375 | ||
377 | static ssize_t | 376 | static ssize_t |
378 | idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | 377 | idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) |
379 | { | 378 | { |
380 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); | 379 | struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); |
381 | struct idmap *idmap = (struct idmap *)rpci->private; | 380 | struct idmap *idmap = (struct idmap *)rpci->private; |
382 | struct idmap_msg im_in, *im = &idmap->idmap_im; | 381 | struct idmap_msg im_in, *im = &idmap->idmap_im; |
383 | struct idmap_hashtable *h; | 382 | struct idmap_hashtable *h; |
384 | struct idmap_hashent *he = NULL; | 383 | struct idmap_hashent *he = NULL; |
385 | int namelen_in; | 384 | size_t namelen_in; |
386 | int ret; | 385 | int ret; |
387 | 386 | ||
388 | if (mlen != sizeof(im_in)) | 387 | if (mlen != sizeof(im_in)) |
389 | return (-ENOSPC); | 388 | return -ENOSPC; |
390 | 389 | ||
391 | if (copy_from_user(&im_in, src, mlen) != 0) | 390 | if (copy_from_user(&im_in, src, mlen) != 0) |
392 | return (-EFAULT); | 391 | return -EFAULT; |
393 | 392 | ||
394 | mutex_lock(&idmap->idmap_im_lock); | 393 | mutex_lock(&idmap->idmap_im_lock); |
395 | 394 | ||
@@ -487,7 +486,7 @@ static unsigned int fnvhash32(const void *buf, size_t buflen) | |||
487 | hash ^= (unsigned int)*p; | 486 | hash ^= (unsigned int)*p; |
488 | } | 487 | } |
489 | 488 | ||
490 | return (hash); | 489 | return hash; |
491 | } | 490 | } |
492 | 491 | ||
493 | int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) | 492 | int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index db5d96dc6107..3f332e54e760 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -192,7 +192,7 @@ void nfs_invalidate_atime(struct inode *inode) | |||
192 | */ | 192 | */ |
193 | static void nfs_invalidate_inode(struct inode *inode) | 193 | static void nfs_invalidate_inode(struct inode *inode) |
194 | { | 194 | { |
195 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | 195 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
196 | nfs_zap_caches_locked(inode); | 196 | nfs_zap_caches_locked(inode); |
197 | } | 197 | } |
198 | 198 | ||
@@ -229,7 +229,7 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
229 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; | 229 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; |
230 | struct nfs_fattr *fattr = desc->fattr; | 230 | struct nfs_fattr *fattr = desc->fattr; |
231 | 231 | ||
232 | NFS_FILEID(inode) = fattr->fileid; | 232 | set_nfs_fileid(inode, fattr->fileid); |
233 | nfs_copy_fh(NFS_FH(inode), desc->fh); | 233 | nfs_copy_fh(NFS_FH(inode), desc->fh); |
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
@@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
291 | inode->i_fop = &nfs_dir_operations; | 291 | inode->i_fop = &nfs_dir_operations; |
292 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) | 292 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) |
293 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 293 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
294 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 294 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
295 | /* Deal with crossing mountpoints */ | 295 | /* Deal with crossing mountpoints */ |
296 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 296 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { |
297 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 297 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
@@ -461,9 +461,18 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
461 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; | 461 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
462 | int err; | 462 | int err; |
463 | 463 | ||
464 | /* Flush out writes to the server in order to update c/mtime */ | 464 | /* |
465 | if (S_ISREG(inode->i_mode)) | 465 | * Flush out writes to the server in order to update c/mtime. |
466 | * | ||
467 | * Hold the i_mutex to suspend application writes temporarily; | ||
468 | * this prevents long-running writing applications from blocking | ||
469 | * nfs_wb_nocommit. | ||
470 | */ | ||
471 | if (S_ISREG(inode->i_mode)) { | ||
472 | mutex_lock(&inode->i_mutex); | ||
466 | nfs_wb_nocommit(inode); | 473 | nfs_wb_nocommit(inode); |
474 | mutex_unlock(&inode->i_mutex); | ||
475 | } | ||
467 | 476 | ||
468 | /* | 477 | /* |
469 | * We may force a getattr if the user cares about atime. | 478 | * We may force a getattr if the user cares about atime. |
@@ -659,7 +668,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
659 | if (status == -ESTALE) { | 668 | if (status == -ESTALE) { |
660 | nfs_zap_caches(inode); | 669 | nfs_zap_caches(inode); |
661 | if (!S_ISDIR(inode->i_mode)) | 670 | if (!S_ISDIR(inode->i_mode)) |
662 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | 671 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
663 | } | 672 | } |
664 | goto out; | 673 | goto out; |
665 | } | 674 | } |
@@ -814,8 +823,9 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
814 | if (S_ISDIR(inode->i_mode)) | 823 | if (S_ISDIR(inode->i_mode)) |
815 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 824 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
816 | } | 825 | } |
817 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) | 826 | if (inode->i_size == nfs_size_to_loff_t(fattr->pre_size) && |
818 | inode->i_size = fattr->size; | 827 | nfsi->npages == 0) |
828 | inode->i_size = nfs_size_to_loff_t(fattr->size); | ||
819 | } | 829 | } |
820 | } | 830 | } |
821 | 831 | ||
@@ -1019,7 +1029,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1019 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1029 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1020 | inode->i_sb->s_id, inode->i_ino); | 1030 | inode->i_sb->s_id, inode->i_ino); |
1021 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1031 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1022 | nfsi->cache_change_attribute = now; | 1032 | if (S_ISDIR(inode->i_mode)) |
1033 | nfs_force_lookup_revalidate(inode); | ||
1023 | } | 1034 | } |
1024 | /* If ctime has changed we should definitely clear access+acl caches */ | 1035 | /* If ctime has changed we should definitely clear access+acl caches */ |
1025 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1036 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) |
@@ -1028,7 +1039,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1028 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1039 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1029 | inode->i_sb->s_id, inode->i_ino); | 1040 | inode->i_sb->s_id, inode->i_ino); |
1030 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1041 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1031 | nfsi->cache_change_attribute = now; | 1042 | if (S_ISDIR(inode->i_mode)) |
1043 | nfs_force_lookup_revalidate(inode); | ||
1032 | } | 1044 | } |
1033 | 1045 | ||
1034 | /* Check if our cached file size is stale */ | 1046 | /* Check if our cached file size is stale */ |
@@ -1133,7 +1145,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1133 | void nfs4_clear_inode(struct inode *inode) | 1145 | void nfs4_clear_inode(struct inode *inode) |
1134 | { | 1146 | { |
1135 | /* If we are holding a delegation, return it! */ | 1147 | /* If we are holding a delegation, return it! */ |
1136 | nfs_inode_return_delegation(inode); | 1148 | nfs_inode_return_delegation_noreclaim(inode); |
1137 | /* First call standard NFS clear_inode() code */ | 1149 | /* First call standard NFS clear_inode() code */ |
1138 | nfs_clear_inode(inode); | 1150 | nfs_clear_inode(inode); |
1139 | } | 1151 | } |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index f3acf48412be..0f5619611b8d 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -21,7 +21,8 @@ struct nfs_clone_mount { | |||
21 | struct nfs_fattr *fattr; | 21 | struct nfs_fattr *fattr; |
22 | char *hostname; | 22 | char *hostname; |
23 | char *mnt_path; | 23 | char *mnt_path; |
24 | struct sockaddr_in *addr; | 24 | struct sockaddr *addr; |
25 | size_t addrlen; | ||
25 | rpc_authflavor_t authflavor; | 26 | rpc_authflavor_t authflavor; |
26 | }; | 27 | }; |
27 | 28 | ||
@@ -41,19 +42,19 @@ struct nfs_parsed_mount_data { | |||
41 | char *client_address; | 42 | char *client_address; |
42 | 43 | ||
43 | struct { | 44 | struct { |
44 | struct sockaddr_in address; | 45 | struct sockaddr_storage address; |
46 | size_t addrlen; | ||
45 | char *hostname; | 47 | char *hostname; |
46 | unsigned int program; | ||
47 | unsigned int version; | 48 | unsigned int version; |
48 | unsigned short port; | 49 | unsigned short port; |
49 | int protocol; | 50 | int protocol; |
50 | } mount_server; | 51 | } mount_server; |
51 | 52 | ||
52 | struct { | 53 | struct { |
53 | struct sockaddr_in address; | 54 | struct sockaddr_storage address; |
55 | size_t addrlen; | ||
54 | char *hostname; | 56 | char *hostname; |
55 | char *export_path; | 57 | char *export_path; |
56 | unsigned int program; | ||
57 | int protocol; | 58 | int protocol; |
58 | } nfs_server; | 59 | } nfs_server; |
59 | }; | 60 | }; |
@@ -62,7 +63,8 @@ struct nfs_parsed_mount_data { | |||
62 | extern struct rpc_program nfs_program; | 63 | extern struct rpc_program nfs_program; |
63 | 64 | ||
64 | extern void nfs_put_client(struct nfs_client *); | 65 | extern void nfs_put_client(struct nfs_client *); |
65 | extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); | 66 | extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32); |
67 | extern struct nfs_client *nfs_find_client_next(struct nfs_client *); | ||
66 | extern struct nfs_server *nfs_create_server( | 68 | extern struct nfs_server *nfs_create_server( |
67 | const struct nfs_parsed_mount_data *, | 69 | const struct nfs_parsed_mount_data *, |
68 | struct nfs_fh *); | 70 | struct nfs_fh *); |
@@ -160,6 +162,8 @@ extern struct rpc_stat nfs_rpcstat; | |||
160 | 162 | ||
161 | extern int __init register_nfs_fs(void); | 163 | extern int __init register_nfs_fs(void); |
162 | extern void __exit unregister_nfs_fs(void); | 164 | extern void __exit unregister_nfs_fs(void); |
165 | extern void nfs_sb_active(struct nfs_server *server); | ||
166 | extern void nfs_sb_deactive(struct nfs_server *server); | ||
163 | 167 | ||
164 | /* namespace.c */ | 168 | /* namespace.c */ |
165 | extern char *nfs_path(const char *base, | 169 | extern char *nfs_path(const char *base, |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index acfc56f9edc0..be4ce1c3a3d8 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -188,7 +188,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, | |||
188 | { | 188 | { |
189 | #ifdef CONFIG_NFS_V4 | 189 | #ifdef CONFIG_NFS_V4 |
190 | struct vfsmount *mnt = NULL; | 190 | struct vfsmount *mnt = NULL; |
191 | switch (server->nfs_client->cl_nfsversion) { | 191 | switch (server->nfs_client->rpc_ops->version) { |
192 | case 2: | 192 | case 2: |
193 | case 3: | 193 | case 3: |
194 | mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); | 194 | mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 668ab96c7b59..1f7ea675e0c5 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -262,7 +262,9 @@ static int | |||
262 | nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | 262 | nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) |
263 | { | 263 | { |
264 | struct kvec *iov = req->rq_rcv_buf.head; | 264 | struct kvec *iov = req->rq_rcv_buf.head; |
265 | int status, count, recvd, hdrlen; | 265 | size_t hdrlen; |
266 | u32 count, recvd; | ||
267 | int status; | ||
266 | 268 | ||
267 | if ((status = ntohl(*p++))) | 269 | if ((status = ntohl(*p++))) |
268 | return -nfs_stat_to_errno(status); | 270 | return -nfs_stat_to_errno(status); |
@@ -273,7 +275,7 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
273 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 275 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
274 | if (iov->iov_len < hdrlen) { | 276 | if (iov->iov_len < hdrlen) { |
275 | dprintk("NFS: READ reply header overflowed:" | 277 | dprintk("NFS: READ reply header overflowed:" |
276 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 278 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
277 | return -errno_NFSERR_IO; | 279 | return -errno_NFSERR_IO; |
278 | } else if (iov->iov_len != hdrlen) { | 280 | } else if (iov->iov_len != hdrlen) { |
279 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); | 281 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); |
@@ -283,11 +285,11 @@ nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
283 | recvd = req->rq_rcv_buf.len - hdrlen; | 285 | recvd = req->rq_rcv_buf.len - hdrlen; |
284 | if (count > recvd) { | 286 | if (count > recvd) { |
285 | dprintk("NFS: server cheating in read reply: " | 287 | dprintk("NFS: server cheating in read reply: " |
286 | "count %d > recvd %d\n", count, recvd); | 288 | "count %u > recvd %u\n", count, recvd); |
287 | count = recvd; | 289 | count = recvd; |
288 | } | 290 | } |
289 | 291 | ||
290 | dprintk("RPC: readres OK count %d\n", count); | 292 | dprintk("RPC: readres OK count %u\n", count); |
291 | if (count < res->count) | 293 | if (count < res->count) |
292 | res->count = count; | 294 | res->count = count; |
293 | 295 | ||
@@ -423,9 +425,10 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
423 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 425 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
424 | struct kvec *iov = rcvbuf->head; | 426 | struct kvec *iov = rcvbuf->head; |
425 | struct page **page; | 427 | struct page **page; |
426 | int hdrlen, recvd; | 428 | size_t hdrlen; |
429 | unsigned int pglen, recvd; | ||
430 | u32 len; | ||
427 | int status, nr; | 431 | int status, nr; |
428 | unsigned int len, pglen; | ||
429 | __be32 *end, *entry, *kaddr; | 432 | __be32 *end, *entry, *kaddr; |
430 | 433 | ||
431 | if ((status = ntohl(*p++))) | 434 | if ((status = ntohl(*p++))) |
@@ -434,7 +437,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
434 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 437 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
435 | if (iov->iov_len < hdrlen) { | 438 | if (iov->iov_len < hdrlen) { |
436 | dprintk("NFS: READDIR reply header overflowed:" | 439 | dprintk("NFS: READDIR reply header overflowed:" |
437 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 440 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
438 | return -errno_NFSERR_IO; | 441 | return -errno_NFSERR_IO; |
439 | } else if (iov->iov_len != hdrlen) { | 442 | } else if (iov->iov_len != hdrlen) { |
440 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); | 443 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); |
@@ -576,7 +579,8 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
576 | { | 579 | { |
577 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 580 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
578 | struct kvec *iov = rcvbuf->head; | 581 | struct kvec *iov = rcvbuf->head; |
579 | int hdrlen, len, recvd; | 582 | size_t hdrlen; |
583 | u32 len, recvd; | ||
580 | char *kaddr; | 584 | char *kaddr; |
581 | int status; | 585 | int status; |
582 | 586 | ||
@@ -584,14 +588,14 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) | |||
584 | return -nfs_stat_to_errno(status); | 588 | return -nfs_stat_to_errno(status); |
585 | /* Convert length of symlink */ | 589 | /* Convert length of symlink */ |
586 | len = ntohl(*p++); | 590 | len = ntohl(*p++); |
587 | if (len >= rcvbuf->page_len || len <= 0) { | 591 | if (len >= rcvbuf->page_len) { |
588 | dprintk("nfs: server returned giant symlink!\n"); | 592 | dprintk("nfs: server returned giant symlink!\n"); |
589 | return -ENAMETOOLONG; | 593 | return -ENAMETOOLONG; |
590 | } | 594 | } |
591 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 595 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
592 | if (iov->iov_len < hdrlen) { | 596 | if (iov->iov_len < hdrlen) { |
593 | dprintk("NFS: READLINK reply header overflowed:" | 597 | dprintk("NFS: READLINK reply header overflowed:" |
594 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 598 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
595 | return -errno_NFSERR_IO; | 599 | return -errno_NFSERR_IO; |
596 | } else if (iov->iov_len != hdrlen) { | 600 | } else if (iov->iov_len != hdrlen) { |
597 | dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); | 601 | dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 4cdc2361a669..b353c1a05bfd 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -732,16 +732,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
732 | return 0; | 732 | return 0; |
733 | } | 733 | } |
734 | 734 | ||
735 | static void nfs3_proc_read_setup(struct nfs_read_data *data) | 735 | static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
736 | { | 736 | { |
737 | struct rpc_message msg = { | 737 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; |
738 | .rpc_proc = &nfs3_procedures[NFS3PROC_READ], | ||
739 | .rpc_argp = &data->args, | ||
740 | .rpc_resp = &data->res, | ||
741 | .rpc_cred = data->cred, | ||
742 | }; | ||
743 | |||
744 | rpc_call_setup(&data->task, &msg, 0); | ||
745 | } | 738 | } |
746 | 739 | ||
747 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | 740 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -753,24 +746,9 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
753 | return 0; | 746 | return 0; |
754 | } | 747 | } |
755 | 748 | ||
756 | static void nfs3_proc_write_setup(struct nfs_write_data *data, int how) | 749 | static void nfs3_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
757 | { | 750 | { |
758 | struct rpc_message msg = { | 751 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE]; |
759 | .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], | ||
760 | .rpc_argp = &data->args, | ||
761 | .rpc_resp = &data->res, | ||
762 | .rpc_cred = data->cred, | ||
763 | }; | ||
764 | |||
765 | data->args.stable = NFS_UNSTABLE; | ||
766 | if (how & FLUSH_STABLE) { | ||
767 | data->args.stable = NFS_FILE_SYNC; | ||
768 | if (NFS_I(data->inode)->ncommit) | ||
769 | data->args.stable = NFS_DATA_SYNC; | ||
770 | } | ||
771 | |||
772 | /* Finalize the task. */ | ||
773 | rpc_call_setup(&data->task, &msg, 0); | ||
774 | } | 752 | } |
775 | 753 | ||
776 | static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 754 | static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -781,22 +759,17 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
781 | return 0; | 759 | return 0; |
782 | } | 760 | } |
783 | 761 | ||
784 | static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how) | 762 | static void nfs3_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
785 | { | 763 | { |
786 | struct rpc_message msg = { | 764 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT]; |
787 | .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], | ||
788 | .rpc_argp = &data->args, | ||
789 | .rpc_resp = &data->res, | ||
790 | .rpc_cred = data->cred, | ||
791 | }; | ||
792 | |||
793 | rpc_call_setup(&data->task, &msg, 0); | ||
794 | } | 765 | } |
795 | 766 | ||
796 | static int | 767 | static int |
797 | nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) | 768 | nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) |
798 | { | 769 | { |
799 | return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); | 770 | struct inode *inode = filp->f_path.dentry->d_inode; |
771 | |||
772 | return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); | ||
800 | } | 773 | } |
801 | 774 | ||
802 | const struct nfs_rpc_ops nfs_v3_clientops = { | 775 | const struct nfs_rpc_ops nfs_v3_clientops = { |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 616d3267b7e7..3917e2fa4e40 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -506,9 +506,9 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
506 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 506 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
507 | struct kvec *iov = rcvbuf->head; | 507 | struct kvec *iov = rcvbuf->head; |
508 | struct page **page; | 508 | struct page **page; |
509 | int hdrlen, recvd; | 509 | size_t hdrlen; |
510 | u32 len, recvd, pglen; | ||
510 | int status, nr; | 511 | int status, nr; |
511 | unsigned int len, pglen; | ||
512 | __be32 *entry, *end, *kaddr; | 512 | __be32 *entry, *end, *kaddr; |
513 | 513 | ||
514 | status = ntohl(*p++); | 514 | status = ntohl(*p++); |
@@ -527,7 +527,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
527 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 527 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
528 | if (iov->iov_len < hdrlen) { | 528 | if (iov->iov_len < hdrlen) { |
529 | dprintk("NFS: READDIR reply header overflowed:" | 529 | dprintk("NFS: READDIR reply header overflowed:" |
530 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 530 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
531 | return -errno_NFSERR_IO; | 531 | return -errno_NFSERR_IO; |
532 | } else if (iov->iov_len != hdrlen) { | 532 | } else if (iov->iov_len != hdrlen) { |
533 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); | 533 | dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); |
@@ -549,7 +549,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
549 | len = ntohl(*p++); /* string length */ | 549 | len = ntohl(*p++); /* string length */ |
550 | p += XDR_QUADLEN(len) + 2; /* name + cookie */ | 550 | p += XDR_QUADLEN(len) + 2; /* name + cookie */ |
551 | if (len > NFS3_MAXNAMLEN) { | 551 | if (len > NFS3_MAXNAMLEN) { |
552 | dprintk("NFS: giant filename in readdir (len %x)!\n", | 552 | dprintk("NFS: giant filename in readdir (len 0x%x)!\n", |
553 | len); | 553 | len); |
554 | goto err_unmap; | 554 | goto err_unmap; |
555 | } | 555 | } |
@@ -570,7 +570,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
570 | len = ntohl(*p++); | 570 | len = ntohl(*p++); |
571 | if (len > NFS3_FHSIZE) { | 571 | if (len > NFS3_FHSIZE) { |
572 | dprintk("NFS: giant filehandle in " | 572 | dprintk("NFS: giant filehandle in " |
573 | "readdir (len %x)!\n", len); | 573 | "readdir (len 0x%x)!\n", len); |
574 | goto err_unmap; | 574 | goto err_unmap; |
575 | } | 575 | } |
576 | p += XDR_QUADLEN(len); | 576 | p += XDR_QUADLEN(len); |
@@ -815,7 +815,8 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
815 | { | 815 | { |
816 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 816 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
817 | struct kvec *iov = rcvbuf->head; | 817 | struct kvec *iov = rcvbuf->head; |
818 | int hdrlen, len, recvd; | 818 | size_t hdrlen; |
819 | u32 len, recvd; | ||
819 | char *kaddr; | 820 | char *kaddr; |
820 | int status; | 821 | int status; |
821 | 822 | ||
@@ -827,7 +828,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
827 | 828 | ||
828 | /* Convert length of symlink */ | 829 | /* Convert length of symlink */ |
829 | len = ntohl(*p++); | 830 | len = ntohl(*p++); |
830 | if (len >= rcvbuf->page_len || len <= 0) { | 831 | if (len >= rcvbuf->page_len) { |
831 | dprintk("nfs: server returned giant symlink!\n"); | 832 | dprintk("nfs: server returned giant symlink!\n"); |
832 | return -ENAMETOOLONG; | 833 | return -ENAMETOOLONG; |
833 | } | 834 | } |
@@ -835,7 +836,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
835 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 836 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
836 | if (iov->iov_len < hdrlen) { | 837 | if (iov->iov_len < hdrlen) { |
837 | dprintk("NFS: READLINK reply header overflowed:" | 838 | dprintk("NFS: READLINK reply header overflowed:" |
838 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 839 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
839 | return -errno_NFSERR_IO; | 840 | return -errno_NFSERR_IO; |
840 | } else if (iov->iov_len != hdrlen) { | 841 | } else if (iov->iov_len != hdrlen) { |
841 | dprintk("NFS: READLINK header is short. " | 842 | dprintk("NFS: READLINK header is short. " |
@@ -863,7 +864,9 @@ static int | |||
863 | nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | 864 | nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) |
864 | { | 865 | { |
865 | struct kvec *iov = req->rq_rcv_buf.head; | 866 | struct kvec *iov = req->rq_rcv_buf.head; |
866 | int status, count, ocount, recvd, hdrlen; | 867 | size_t hdrlen; |
868 | u32 count, ocount, recvd; | ||
869 | int status; | ||
867 | 870 | ||
868 | status = ntohl(*p++); | 871 | status = ntohl(*p++); |
869 | p = xdr_decode_post_op_attr(p, res->fattr); | 872 | p = xdr_decode_post_op_attr(p, res->fattr); |
@@ -871,7 +874,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
871 | if (status != 0) | 874 | if (status != 0) |
872 | return -nfs_stat_to_errno(status); | 875 | return -nfs_stat_to_errno(status); |
873 | 876 | ||
874 | /* Decode reply could and EOF flag. NFSv3 is somewhat redundant | 877 | /* Decode reply count and EOF flag. NFSv3 is somewhat redundant |
875 | * in that it puts the count both in the res struct and in the | 878 | * in that it puts the count both in the res struct and in the |
876 | * opaque data count. */ | 879 | * opaque data count. */ |
877 | count = ntohl(*p++); | 880 | count = ntohl(*p++); |
@@ -886,7 +889,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
886 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; | 889 | hdrlen = (u8 *) p - (u8 *) iov->iov_base; |
887 | if (iov->iov_len < hdrlen) { | 890 | if (iov->iov_len < hdrlen) { |
888 | dprintk("NFS: READ reply header overflowed:" | 891 | dprintk("NFS: READ reply header overflowed:" |
889 | "length %d > %Zu\n", hdrlen, iov->iov_len); | 892 | "length %Zu > %Zu\n", hdrlen, iov->iov_len); |
890 | return -errno_NFSERR_IO; | 893 | return -errno_NFSERR_IO; |
891 | } else if (iov->iov_len != hdrlen) { | 894 | } else if (iov->iov_len != hdrlen) { |
892 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); | 895 | dprintk("NFS: READ header is short. iovec will be shifted.\n"); |
@@ -896,7 +899,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
896 | recvd = req->rq_rcv_buf.len - hdrlen; | 899 | recvd = req->rq_rcv_buf.len - hdrlen; |
897 | if (count > recvd) { | 900 | if (count > recvd) { |
898 | dprintk("NFS: server cheating in read reply: " | 901 | dprintk("NFS: server cheating in read reply: " |
899 | "count %d > recvd %d\n", count, recvd); | 902 | "count %u > recvd %u\n", count, recvd); |
900 | count = recvd; | 903 | count = recvd; |
901 | res->eof = 0; | 904 | res->eof = 0; |
902 | } | 905 | } |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index dd5fef20c702..5f9ba41ed5bf 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -114,10 +114,7 @@ static inline int valid_ipaddr4(const char *buf) | |||
114 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error | 114 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error |
115 | * @mnt_parent - mountpoint of parent directory | 115 | * @mnt_parent - mountpoint of parent directory |
116 | * @dentry - parent directory | 116 | * @dentry - parent directory |
117 | * @fspath - fs path returned in fs_locations | 117 | * @locations - array of NFSv4 server location information |
118 | * @mntpath - mount path to new server | ||
119 | * @hostname - hostname of new server | ||
120 | * @addr - host addr of new server | ||
121 | * | 118 | * |
122 | */ | 119 | */ |
123 | static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | 120 | static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, |
@@ -131,7 +128,8 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
131 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, | 128 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, |
132 | }; | 129 | }; |
133 | char *page = NULL, *page2 = NULL; | 130 | char *page = NULL, *page2 = NULL; |
134 | int loc, s, error; | 131 | unsigned int s; |
132 | int loc, error; | ||
135 | 133 | ||
136 | if (locations == NULL || locations->nlocations <= 0) | 134 | if (locations == NULL || locations->nlocations <= 0) |
137 | goto out; | 135 | goto out; |
@@ -174,7 +172,10 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
174 | 172 | ||
175 | s = 0; | 173 | s = 0; |
176 | while (s < location->nservers) { | 174 | while (s < location->nservers) { |
177 | struct sockaddr_in addr = {}; | 175 | struct sockaddr_in addr = { |
176 | .sin_family = AF_INET, | ||
177 | .sin_port = htons(NFS_PORT), | ||
178 | }; | ||
178 | 179 | ||
179 | if (location->servers[s].len <= 0 || | 180 | if (location->servers[s].len <= 0 || |
180 | valid_ipaddr4(location->servers[s].data) < 0) { | 181 | valid_ipaddr4(location->servers[s].data) < 0) { |
@@ -183,10 +184,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
183 | } | 184 | } |
184 | 185 | ||
185 | mountdata.hostname = location->servers[s].data; | 186 | mountdata.hostname = location->servers[s].data; |
186 | addr.sin_addr.s_addr = in_aton(mountdata.hostname); | 187 | addr.sin_addr.s_addr = in_aton(mountdata.hostname), |
187 | addr.sin_family = AF_INET; | 188 | mountdata.addr = (struct sockaddr *)&addr; |
188 | addr.sin_port = htons(NFS_PORT); | 189 | mountdata.addrlen = sizeof(addr); |
189 | mountdata.addr = &addr; | ||
190 | 190 | ||
191 | snprintf(page, PAGE_SIZE, "%s:%s", | 191 | snprintf(page, PAGE_SIZE, "%s:%s", |
192 | mountdata.hostname, | 192 | mountdata.hostname, |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9e2e1c7291db..5c189bd57eb2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -210,7 +210,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
210 | spin_lock(&dir->i_lock); | 210 | spin_lock(&dir->i_lock); |
211 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; | 211 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; |
212 | if (!cinfo->atomic || cinfo->before != nfsi->change_attr) | 212 | if (!cinfo->atomic || cinfo->before != nfsi->change_attr) |
213 | nfsi->cache_change_attribute = jiffies; | 213 | nfs_force_lookup_revalidate(dir); |
214 | nfsi->change_attr = cinfo->after; | 214 | nfsi->change_attr = cinfo->after; |
215 | spin_unlock(&dir->i_lock); | 215 | spin_unlock(&dir->i_lock); |
216 | } | 216 | } |
@@ -718,19 +718,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
718 | return err; | 718 | return err; |
719 | } | 719 | } |
720 | 720 | ||
721 | static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | ||
722 | { | ||
723 | struct nfs4_opendata *data = calldata; | ||
724 | struct rpc_message msg = { | ||
725 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], | ||
726 | .rpc_argp = &data->c_arg, | ||
727 | .rpc_resp = &data->c_res, | ||
728 | .rpc_cred = data->owner->so_cred, | ||
729 | }; | ||
730 | data->timestamp = jiffies; | ||
731 | rpc_call_setup(task, &msg, 0); | ||
732 | } | ||
733 | |||
734 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 721 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
735 | { | 722 | { |
736 | struct nfs4_opendata *data = calldata; | 723 | struct nfs4_opendata *data = calldata; |
@@ -767,7 +754,6 @@ out_free: | |||
767 | } | 754 | } |
768 | 755 | ||
769 | static const struct rpc_call_ops nfs4_open_confirm_ops = { | 756 | static const struct rpc_call_ops nfs4_open_confirm_ops = { |
770 | .rpc_call_prepare = nfs4_open_confirm_prepare, | ||
771 | .rpc_call_done = nfs4_open_confirm_done, | 757 | .rpc_call_done = nfs4_open_confirm_done, |
772 | .rpc_release = nfs4_open_confirm_release, | 758 | .rpc_release = nfs4_open_confirm_release, |
773 | }; | 759 | }; |
@@ -779,12 +765,26 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
779 | { | 765 | { |
780 | struct nfs_server *server = NFS_SERVER(data->dir->d_inode); | 766 | struct nfs_server *server = NFS_SERVER(data->dir->d_inode); |
781 | struct rpc_task *task; | 767 | struct rpc_task *task; |
768 | struct rpc_message msg = { | ||
769 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], | ||
770 | .rpc_argp = &data->c_arg, | ||
771 | .rpc_resp = &data->c_res, | ||
772 | .rpc_cred = data->owner->so_cred, | ||
773 | }; | ||
774 | struct rpc_task_setup task_setup_data = { | ||
775 | .rpc_client = server->client, | ||
776 | .rpc_message = &msg, | ||
777 | .callback_ops = &nfs4_open_confirm_ops, | ||
778 | .callback_data = data, | ||
779 | .flags = RPC_TASK_ASYNC, | ||
780 | }; | ||
782 | int status; | 781 | int status; |
783 | 782 | ||
784 | kref_get(&data->kref); | 783 | kref_get(&data->kref); |
785 | data->rpc_done = 0; | 784 | data->rpc_done = 0; |
786 | data->rpc_status = 0; | 785 | data->rpc_status = 0; |
787 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); | 786 | data->timestamp = jiffies; |
787 | task = rpc_run_task(&task_setup_data); | ||
788 | if (IS_ERR(task)) | 788 | if (IS_ERR(task)) |
789 | return PTR_ERR(task); | 789 | return PTR_ERR(task); |
790 | status = nfs4_wait_for_completion_rpc_task(task); | 790 | status = nfs4_wait_for_completion_rpc_task(task); |
@@ -801,13 +801,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
801 | { | 801 | { |
802 | struct nfs4_opendata *data = calldata; | 802 | struct nfs4_opendata *data = calldata; |
803 | struct nfs4_state_owner *sp = data->owner; | 803 | struct nfs4_state_owner *sp = data->owner; |
804 | struct rpc_message msg = { | 804 | |
805 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], | ||
806 | .rpc_argp = &data->o_arg, | ||
807 | .rpc_resp = &data->o_res, | ||
808 | .rpc_cred = sp->so_cred, | ||
809 | }; | ||
810 | |||
811 | if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) | 805 | if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) |
812 | return; | 806 | return; |
813 | /* | 807 | /* |
@@ -832,11 +826,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
832 | data->o_arg.id = sp->so_owner_id.id; | 826 | data->o_arg.id = sp->so_owner_id.id; |
833 | data->o_arg.clientid = sp->so_client->cl_clientid; | 827 | data->o_arg.clientid = sp->so_client->cl_clientid; |
834 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 828 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
835 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 829 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
836 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 830 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
837 | } | 831 | } |
838 | data->timestamp = jiffies; | 832 | data->timestamp = jiffies; |
839 | rpc_call_setup(task, &msg, 0); | 833 | rpc_call_start(task); |
840 | return; | 834 | return; |
841 | out_no_action: | 835 | out_no_action: |
842 | task->tk_action = NULL; | 836 | task->tk_action = NULL; |
@@ -908,13 +902,26 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
908 | struct nfs_openargs *o_arg = &data->o_arg; | 902 | struct nfs_openargs *o_arg = &data->o_arg; |
909 | struct nfs_openres *o_res = &data->o_res; | 903 | struct nfs_openres *o_res = &data->o_res; |
910 | struct rpc_task *task; | 904 | struct rpc_task *task; |
905 | struct rpc_message msg = { | ||
906 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], | ||
907 | .rpc_argp = o_arg, | ||
908 | .rpc_resp = o_res, | ||
909 | .rpc_cred = data->owner->so_cred, | ||
910 | }; | ||
911 | struct rpc_task_setup task_setup_data = { | ||
912 | .rpc_client = server->client, | ||
913 | .rpc_message = &msg, | ||
914 | .callback_ops = &nfs4_open_ops, | ||
915 | .callback_data = data, | ||
916 | .flags = RPC_TASK_ASYNC, | ||
917 | }; | ||
911 | int status; | 918 | int status; |
912 | 919 | ||
913 | kref_get(&data->kref); | 920 | kref_get(&data->kref); |
914 | data->rpc_done = 0; | 921 | data->rpc_done = 0; |
915 | data->rpc_status = 0; | 922 | data->rpc_status = 0; |
916 | data->cancelled = 0; | 923 | data->cancelled = 0; |
917 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); | 924 | task = rpc_run_task(&task_setup_data); |
918 | if (IS_ERR(task)) | 925 | if (IS_ERR(task)) |
919 | return PTR_ERR(task); | 926 | return PTR_ERR(task); |
920 | status = nfs4_wait_for_completion_rpc_task(task); | 927 | status = nfs4_wait_for_completion_rpc_task(task); |
@@ -1244,12 +1251,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1244 | { | 1251 | { |
1245 | struct nfs4_closedata *calldata = data; | 1252 | struct nfs4_closedata *calldata = data; |
1246 | struct nfs4_state *state = calldata->state; | 1253 | struct nfs4_state *state = calldata->state; |
1247 | struct rpc_message msg = { | ||
1248 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | ||
1249 | .rpc_argp = &calldata->arg, | ||
1250 | .rpc_resp = &calldata->res, | ||
1251 | .rpc_cred = state->owner->so_cred, | ||
1252 | }; | ||
1253 | int clear_rd, clear_wr, clear_rdwr; | 1254 | int clear_rd, clear_wr, clear_rdwr; |
1254 | 1255 | ||
1255 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 1256 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
@@ -1276,14 +1277,14 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1276 | } | 1277 | } |
1277 | nfs_fattr_init(calldata->res.fattr); | 1278 | nfs_fattr_init(calldata->res.fattr); |
1278 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { | 1279 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { |
1279 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 1280 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
1280 | calldata->arg.open_flags = FMODE_READ; | 1281 | calldata->arg.open_flags = FMODE_READ; |
1281 | } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { | 1282 | } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { |
1282 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 1283 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
1283 | calldata->arg.open_flags = FMODE_WRITE; | 1284 | calldata->arg.open_flags = FMODE_WRITE; |
1284 | } | 1285 | } |
1285 | calldata->timestamp = jiffies; | 1286 | calldata->timestamp = jiffies; |
1286 | rpc_call_setup(task, &msg, 0); | 1287 | rpc_call_start(task); |
1287 | } | 1288 | } |
1288 | 1289 | ||
1289 | static const struct rpc_call_ops nfs4_close_ops = { | 1290 | static const struct rpc_call_ops nfs4_close_ops = { |
@@ -1309,6 +1310,16 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1309 | struct nfs4_closedata *calldata; | 1310 | struct nfs4_closedata *calldata; |
1310 | struct nfs4_state_owner *sp = state->owner; | 1311 | struct nfs4_state_owner *sp = state->owner; |
1311 | struct rpc_task *task; | 1312 | struct rpc_task *task; |
1313 | struct rpc_message msg = { | ||
1314 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | ||
1315 | .rpc_cred = state->owner->so_cred, | ||
1316 | }; | ||
1317 | struct rpc_task_setup task_setup_data = { | ||
1318 | .rpc_client = server->client, | ||
1319 | .rpc_message = &msg, | ||
1320 | .callback_ops = &nfs4_close_ops, | ||
1321 | .flags = RPC_TASK_ASYNC, | ||
1322 | }; | ||
1312 | int status = -ENOMEM; | 1323 | int status = -ENOMEM; |
1313 | 1324 | ||
1314 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); | 1325 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
@@ -1328,7 +1339,10 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1328 | calldata->path.mnt = mntget(path->mnt); | 1339 | calldata->path.mnt = mntget(path->mnt); |
1329 | calldata->path.dentry = dget(path->dentry); | 1340 | calldata->path.dentry = dget(path->dentry); |
1330 | 1341 | ||
1331 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); | 1342 | msg.rpc_argp = &calldata->arg, |
1343 | msg.rpc_resp = &calldata->res, | ||
1344 | task_setup_data.callback_data = calldata; | ||
1345 | task = rpc_run_task(&task_setup_data); | ||
1332 | if (IS_ERR(task)) | 1346 | if (IS_ERR(task)) |
1333 | return PTR_ERR(task); | 1347 | return PTR_ERR(task); |
1334 | status = 0; | 1348 | status = 0; |
@@ -2414,18 +2428,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
2414 | return 0; | 2428 | return 0; |
2415 | } | 2429 | } |
2416 | 2430 | ||
2417 | static void nfs4_proc_read_setup(struct nfs_read_data *data) | 2431 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
2418 | { | 2432 | { |
2419 | struct rpc_message msg = { | ||
2420 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], | ||
2421 | .rpc_argp = &data->args, | ||
2422 | .rpc_resp = &data->res, | ||
2423 | .rpc_cred = data->cred, | ||
2424 | }; | ||
2425 | |||
2426 | data->timestamp = jiffies; | 2433 | data->timestamp = jiffies; |
2427 | 2434 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | |
2428 | rpc_call_setup(&data->task, &msg, 0); | ||
2429 | } | 2435 | } |
2430 | 2436 | ||
2431 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 2437 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -2443,33 +2449,15 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2443 | return 0; | 2449 | return 0; |
2444 | } | 2450 | } |
2445 | 2451 | ||
2446 | static void nfs4_proc_write_setup(struct nfs_write_data *data, int how) | 2452 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
2447 | { | 2453 | { |
2448 | struct rpc_message msg = { | 2454 | struct nfs_server *server = NFS_SERVER(data->inode); |
2449 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], | 2455 | |
2450 | .rpc_argp = &data->args, | ||
2451 | .rpc_resp = &data->res, | ||
2452 | .rpc_cred = data->cred, | ||
2453 | }; | ||
2454 | struct inode *inode = data->inode; | ||
2455 | struct nfs_server *server = NFS_SERVER(inode); | ||
2456 | int stable; | ||
2457 | |||
2458 | if (how & FLUSH_STABLE) { | ||
2459 | if (!NFS_I(inode)->ncommit) | ||
2460 | stable = NFS_FILE_SYNC; | ||
2461 | else | ||
2462 | stable = NFS_DATA_SYNC; | ||
2463 | } else | ||
2464 | stable = NFS_UNSTABLE; | ||
2465 | data->args.stable = stable; | ||
2466 | data->args.bitmask = server->attr_bitmask; | 2456 | data->args.bitmask = server->attr_bitmask; |
2467 | data->res.server = server; | 2457 | data->res.server = server; |
2468 | |||
2469 | data->timestamp = jiffies; | 2458 | data->timestamp = jiffies; |
2470 | 2459 | ||
2471 | /* Finalize the task. */ | 2460 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
2472 | rpc_call_setup(&data->task, &msg, 0); | ||
2473 | } | 2461 | } |
2474 | 2462 | ||
2475 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 2463 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -2484,20 +2472,13 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2484 | return 0; | 2472 | return 0; |
2485 | } | 2473 | } |
2486 | 2474 | ||
2487 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | 2475 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
2488 | { | 2476 | { |
2489 | struct rpc_message msg = { | ||
2490 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], | ||
2491 | .rpc_argp = &data->args, | ||
2492 | .rpc_resp = &data->res, | ||
2493 | .rpc_cred = data->cred, | ||
2494 | }; | ||
2495 | struct nfs_server *server = NFS_SERVER(data->inode); | 2477 | struct nfs_server *server = NFS_SERVER(data->inode); |
2496 | 2478 | ||
2497 | data->args.bitmask = server->attr_bitmask; | 2479 | data->args.bitmask = server->attr_bitmask; |
2498 | data->res.server = server; | 2480 | data->res.server = server; |
2499 | 2481 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | |
2500 | rpc_call_setup(&data->task, &msg, 0); | ||
2501 | } | 2482 | } |
2502 | 2483 | ||
2503 | /* | 2484 | /* |
@@ -2910,14 +2891,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po | |||
2910 | 2891 | ||
2911 | for(;;) { | 2892 | for(;;) { |
2912 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 2893 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
2913 | sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", | 2894 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", |
2914 | clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr), | 2895 | clp->cl_ipaddr, |
2896 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2897 | RPC_DISPLAY_ADDR), | ||
2898 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2899 | RPC_DISPLAY_PROTO), | ||
2915 | cred->cr_ops->cr_name, | 2900 | cred->cr_ops->cr_name, |
2916 | clp->cl_id_uniquifier); | 2901 | clp->cl_id_uniquifier); |
2917 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 2902 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
2918 | sizeof(setclientid.sc_netid), "tcp"); | 2903 | sizeof(setclientid.sc_netid), |
2904 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2905 | RPC_DISPLAY_NETID)); | ||
2919 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | 2906 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, |
2920 | sizeof(setclientid.sc_uaddr), "%s.%d.%d", | 2907 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
2921 | clp->cl_ipaddr, port >> 8, port & 255); | 2908 | clp->cl_ipaddr, port >> 8, port & 255); |
2922 | 2909 | ||
2923 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 2910 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); |
@@ -2981,25 +2968,11 @@ struct nfs4_delegreturndata { | |||
2981 | struct nfs4_delegreturnres res; | 2968 | struct nfs4_delegreturnres res; |
2982 | struct nfs_fh fh; | 2969 | struct nfs_fh fh; |
2983 | nfs4_stateid stateid; | 2970 | nfs4_stateid stateid; |
2984 | struct rpc_cred *cred; | ||
2985 | unsigned long timestamp; | 2971 | unsigned long timestamp; |
2986 | struct nfs_fattr fattr; | 2972 | struct nfs_fattr fattr; |
2987 | int rpc_status; | 2973 | int rpc_status; |
2988 | }; | 2974 | }; |
2989 | 2975 | ||
2990 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata) | ||
2991 | { | ||
2992 | struct nfs4_delegreturndata *data = calldata; | ||
2993 | struct rpc_message msg = { | ||
2994 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], | ||
2995 | .rpc_argp = &data->args, | ||
2996 | .rpc_resp = &data->res, | ||
2997 | .rpc_cred = data->cred, | ||
2998 | }; | ||
2999 | nfs_fattr_init(data->res.fattr); | ||
3000 | rpc_call_setup(task, &msg, 0); | ||
3001 | } | ||
3002 | |||
3003 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | 2976 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) |
3004 | { | 2977 | { |
3005 | struct nfs4_delegreturndata *data = calldata; | 2978 | struct nfs4_delegreturndata *data = calldata; |
@@ -3010,24 +2983,30 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
3010 | 2983 | ||
3011 | static void nfs4_delegreturn_release(void *calldata) | 2984 | static void nfs4_delegreturn_release(void *calldata) |
3012 | { | 2985 | { |
3013 | struct nfs4_delegreturndata *data = calldata; | ||
3014 | |||
3015 | put_rpccred(data->cred); | ||
3016 | kfree(calldata); | 2986 | kfree(calldata); |
3017 | } | 2987 | } |
3018 | 2988 | ||
3019 | static const struct rpc_call_ops nfs4_delegreturn_ops = { | 2989 | static const struct rpc_call_ops nfs4_delegreturn_ops = { |
3020 | .rpc_call_prepare = nfs4_delegreturn_prepare, | ||
3021 | .rpc_call_done = nfs4_delegreturn_done, | 2990 | .rpc_call_done = nfs4_delegreturn_done, |
3022 | .rpc_release = nfs4_delegreturn_release, | 2991 | .rpc_release = nfs4_delegreturn_release, |
3023 | }; | 2992 | }; |
3024 | 2993 | ||
3025 | static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 2994 | static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) |
3026 | { | 2995 | { |
3027 | struct nfs4_delegreturndata *data; | 2996 | struct nfs4_delegreturndata *data; |
3028 | struct nfs_server *server = NFS_SERVER(inode); | 2997 | struct nfs_server *server = NFS_SERVER(inode); |
3029 | struct rpc_task *task; | 2998 | struct rpc_task *task; |
3030 | int status; | 2999 | struct rpc_message msg = { |
3000 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], | ||
3001 | .rpc_cred = cred, | ||
3002 | }; | ||
3003 | struct rpc_task_setup task_setup_data = { | ||
3004 | .rpc_client = server->client, | ||
3005 | .rpc_message = &msg, | ||
3006 | .callback_ops = &nfs4_delegreturn_ops, | ||
3007 | .flags = RPC_TASK_ASYNC, | ||
3008 | }; | ||
3009 | int status = 0; | ||
3031 | 3010 | ||
3032 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 3011 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
3033 | if (data == NULL) | 3012 | if (data == NULL) |
@@ -3039,30 +3018,37 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3039 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); | 3018 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); |
3040 | data->res.fattr = &data->fattr; | 3019 | data->res.fattr = &data->fattr; |
3041 | data->res.server = server; | 3020 | data->res.server = server; |
3042 | data->cred = get_rpccred(cred); | 3021 | nfs_fattr_init(data->res.fattr); |
3043 | data->timestamp = jiffies; | 3022 | data->timestamp = jiffies; |
3044 | data->rpc_status = 0; | 3023 | data->rpc_status = 0; |
3045 | 3024 | ||
3046 | task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); | 3025 | task_setup_data.callback_data = data; |
3026 | msg.rpc_argp = &data->args, | ||
3027 | msg.rpc_resp = &data->res, | ||
3028 | task = rpc_run_task(&task_setup_data); | ||
3047 | if (IS_ERR(task)) | 3029 | if (IS_ERR(task)) |
3048 | return PTR_ERR(task); | 3030 | return PTR_ERR(task); |
3031 | if (!issync) | ||
3032 | goto out; | ||
3049 | status = nfs4_wait_for_completion_rpc_task(task); | 3033 | status = nfs4_wait_for_completion_rpc_task(task); |
3050 | if (status == 0) { | 3034 | if (status != 0) |
3051 | status = data->rpc_status; | 3035 | goto out; |
3052 | if (status == 0) | 3036 | status = data->rpc_status; |
3053 | nfs_refresh_inode(inode, &data->fattr); | 3037 | if (status != 0) |
3054 | } | 3038 | goto out; |
3039 | nfs_refresh_inode(inode, &data->fattr); | ||
3040 | out: | ||
3055 | rpc_put_task(task); | 3041 | rpc_put_task(task); |
3056 | return status; | 3042 | return status; |
3057 | } | 3043 | } |
3058 | 3044 | ||
3059 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 3045 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) |
3060 | { | 3046 | { |
3061 | struct nfs_server *server = NFS_SERVER(inode); | 3047 | struct nfs_server *server = NFS_SERVER(inode); |
3062 | struct nfs4_exception exception = { }; | 3048 | struct nfs4_exception exception = { }; |
3063 | int err; | 3049 | int err; |
3064 | do { | 3050 | do { |
3065 | err = _nfs4_proc_delegreturn(inode, cred, stateid); | 3051 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); |
3066 | switch (err) { | 3052 | switch (err) { |
3067 | case -NFS4ERR_STALE_STATEID: | 3053 | case -NFS4ERR_STALE_STATEID: |
3068 | case -NFS4ERR_EXPIRED: | 3054 | case -NFS4ERR_EXPIRED: |
@@ -3230,12 +3216,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3230 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) | 3216 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) |
3231 | { | 3217 | { |
3232 | struct nfs4_unlockdata *calldata = data; | 3218 | struct nfs4_unlockdata *calldata = data; |
3233 | struct rpc_message msg = { | ||
3234 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | ||
3235 | .rpc_argp = &calldata->arg, | ||
3236 | .rpc_resp = &calldata->res, | ||
3237 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, | ||
3238 | }; | ||
3239 | 3219 | ||
3240 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 3220 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
3241 | return; | 3221 | return; |
@@ -3245,7 +3225,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
3245 | return; | 3225 | return; |
3246 | } | 3226 | } |
3247 | calldata->timestamp = jiffies; | 3227 | calldata->timestamp = jiffies; |
3248 | rpc_call_setup(task, &msg, 0); | 3228 | rpc_call_start(task); |
3249 | } | 3229 | } |
3250 | 3230 | ||
3251 | static const struct rpc_call_ops nfs4_locku_ops = { | 3231 | static const struct rpc_call_ops nfs4_locku_ops = { |
@@ -3260,6 +3240,16 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
3260 | struct nfs_seqid *seqid) | 3240 | struct nfs_seqid *seqid) |
3261 | { | 3241 | { |
3262 | struct nfs4_unlockdata *data; | 3242 | struct nfs4_unlockdata *data; |
3243 | struct rpc_message msg = { | ||
3244 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | ||
3245 | .rpc_cred = ctx->cred, | ||
3246 | }; | ||
3247 | struct rpc_task_setup task_setup_data = { | ||
3248 | .rpc_client = NFS_CLIENT(lsp->ls_state->inode), | ||
3249 | .rpc_message = &msg, | ||
3250 | .callback_ops = &nfs4_locku_ops, | ||
3251 | .flags = RPC_TASK_ASYNC, | ||
3252 | }; | ||
3263 | 3253 | ||
3264 | /* Ensure this is an unlock - when canceling a lock, the | 3254 | /* Ensure this is an unlock - when canceling a lock, the |
3265 | * canceled lock is passed in, and it won't be an unlock. | 3255 | * canceled lock is passed in, and it won't be an unlock. |
@@ -3272,7 +3262,10 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
3272 | return ERR_PTR(-ENOMEM); | 3262 | return ERR_PTR(-ENOMEM); |
3273 | } | 3263 | } |
3274 | 3264 | ||
3275 | return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); | 3265 | msg.rpc_argp = &data->arg, |
3266 | msg.rpc_resp = &data->res, | ||
3267 | task_setup_data.callback_data = data; | ||
3268 | return rpc_run_task(&task_setup_data); | ||
3276 | } | 3269 | } |
3277 | 3270 | ||
3278 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 3271 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) |
@@ -3331,15 +3324,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3331 | 3324 | ||
3332 | p->arg.fh = NFS_FH(inode); | 3325 | p->arg.fh = NFS_FH(inode); |
3333 | p->arg.fl = &p->fl; | 3326 | p->arg.fl = &p->fl; |
3334 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { | 3327 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); |
3335 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); | 3328 | if (p->arg.open_seqid == NULL) |
3336 | if (p->arg.open_seqid == NULL) | 3329 | goto out_free; |
3337 | goto out_free; | ||
3338 | |||
3339 | } | ||
3340 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 3330 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
3341 | if (p->arg.lock_seqid == NULL) | 3331 | if (p->arg.lock_seqid == NULL) |
3342 | goto out_free; | 3332 | goto out_free_seqid; |
3343 | p->arg.lock_stateid = &lsp->ls_stateid; | 3333 | p->arg.lock_stateid = &lsp->ls_stateid; |
3344 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 3334 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
3345 | p->arg.lock_owner.id = lsp->ls_id.id; | 3335 | p->arg.lock_owner.id = lsp->ls_id.id; |
@@ -3348,9 +3338,9 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3348 | p->ctx = get_nfs_open_context(ctx); | 3338 | p->ctx = get_nfs_open_context(ctx); |
3349 | memcpy(&p->fl, fl, sizeof(p->fl)); | 3339 | memcpy(&p->fl, fl, sizeof(p->fl)); |
3350 | return p; | 3340 | return p; |
3341 | out_free_seqid: | ||
3342 | nfs_free_seqid(p->arg.open_seqid); | ||
3351 | out_free: | 3343 | out_free: |
3352 | if (p->arg.open_seqid != NULL) | ||
3353 | nfs_free_seqid(p->arg.open_seqid); | ||
3354 | kfree(p); | 3344 | kfree(p); |
3355 | return NULL; | 3345 | return NULL; |
3356 | } | 3346 | } |
@@ -3359,31 +3349,20 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
3359 | { | 3349 | { |
3360 | struct nfs4_lockdata *data = calldata; | 3350 | struct nfs4_lockdata *data = calldata; |
3361 | struct nfs4_state *state = data->lsp->ls_state; | 3351 | struct nfs4_state *state = data->lsp->ls_state; |
3362 | struct nfs4_state_owner *sp = state->owner; | ||
3363 | struct rpc_message msg = { | ||
3364 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], | ||
3365 | .rpc_argp = &data->arg, | ||
3366 | .rpc_resp = &data->res, | ||
3367 | .rpc_cred = sp->so_cred, | ||
3368 | }; | ||
3369 | 3352 | ||
3370 | dprintk("%s: begin!\n", __FUNCTION__); | 3353 | dprintk("%s: begin!\n", __FUNCTION__); |
3354 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) | ||
3355 | return; | ||
3371 | /* Do we need to do an open_to_lock_owner? */ | 3356 | /* Do we need to do an open_to_lock_owner? */ |
3372 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 3357 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
3373 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) | 3358 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) |
3374 | return; | 3359 | return; |
3375 | data->arg.open_stateid = &state->stateid; | 3360 | data->arg.open_stateid = &state->stateid; |
3376 | data->arg.new_lock_owner = 1; | 3361 | data->arg.new_lock_owner = 1; |
3377 | /* Retest in case we raced... */ | 3362 | } else |
3378 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) | 3363 | data->arg.new_lock_owner = 0; |
3379 | goto do_rpc; | ||
3380 | } | ||
3381 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) | ||
3382 | return; | ||
3383 | data->arg.new_lock_owner = 0; | ||
3384 | do_rpc: | ||
3385 | data->timestamp = jiffies; | 3364 | data->timestamp = jiffies; |
3386 | rpc_call_setup(task, &msg, 0); | 3365 | rpc_call_start(task); |
3387 | dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); | 3366 | dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); |
3388 | } | 3367 | } |
3389 | 3368 | ||
@@ -3419,6 +3398,7 @@ static void nfs4_lock_release(void *calldata) | |||
3419 | struct nfs4_lockdata *data = calldata; | 3398 | struct nfs4_lockdata *data = calldata; |
3420 | 3399 | ||
3421 | dprintk("%s: begin!\n", __FUNCTION__); | 3400 | dprintk("%s: begin!\n", __FUNCTION__); |
3401 | nfs_free_seqid(data->arg.open_seqid); | ||
3422 | if (data->cancelled != 0) { | 3402 | if (data->cancelled != 0) { |
3423 | struct rpc_task *task; | 3403 | struct rpc_task *task; |
3424 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, | 3404 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, |
@@ -3428,8 +3408,6 @@ static void nfs4_lock_release(void *calldata) | |||
3428 | dprintk("%s: cancelling lock!\n", __FUNCTION__); | 3408 | dprintk("%s: cancelling lock!\n", __FUNCTION__); |
3429 | } else | 3409 | } else |
3430 | nfs_free_seqid(data->arg.lock_seqid); | 3410 | nfs_free_seqid(data->arg.lock_seqid); |
3431 | if (data->arg.open_seqid != NULL) | ||
3432 | nfs_free_seqid(data->arg.open_seqid); | ||
3433 | nfs4_put_lock_state(data->lsp); | 3411 | nfs4_put_lock_state(data->lsp); |
3434 | put_nfs_open_context(data->ctx); | 3412 | put_nfs_open_context(data->ctx); |
3435 | kfree(data); | 3413 | kfree(data); |
@@ -3446,6 +3424,16 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3446 | { | 3424 | { |
3447 | struct nfs4_lockdata *data; | 3425 | struct nfs4_lockdata *data; |
3448 | struct rpc_task *task; | 3426 | struct rpc_task *task; |
3427 | struct rpc_message msg = { | ||
3428 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], | ||
3429 | .rpc_cred = state->owner->so_cred, | ||
3430 | }; | ||
3431 | struct rpc_task_setup task_setup_data = { | ||
3432 | .rpc_client = NFS_CLIENT(state->inode), | ||
3433 | .rpc_message = &msg, | ||
3434 | .callback_ops = &nfs4_lock_ops, | ||
3435 | .flags = RPC_TASK_ASYNC, | ||
3436 | }; | ||
3449 | int ret; | 3437 | int ret; |
3450 | 3438 | ||
3451 | dprintk("%s: begin!\n", __FUNCTION__); | 3439 | dprintk("%s: begin!\n", __FUNCTION__); |
@@ -3457,8 +3445,10 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3457 | data->arg.block = 1; | 3445 | data->arg.block = 1; |
3458 | if (reclaim != 0) | 3446 | if (reclaim != 0) |
3459 | data->arg.reclaim = 1; | 3447 | data->arg.reclaim = 1; |
3460 | task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC, | 3448 | msg.rpc_argp = &data->arg, |
3461 | &nfs4_lock_ops, data); | 3449 | msg.rpc_resp = &data->res, |
3450 | task_setup_data.callback_data = data; | ||
3451 | task = rpc_run_task(&task_setup_data); | ||
3462 | if (IS_ERR(task)) | 3452 | if (IS_ERR(task)) |
3463 | return PTR_ERR(task); | 3453 | return PTR_ERR(task); |
3464 | ret = nfs4_wait_for_completion_rpc_task(task); | 3454 | ret = nfs4_wait_for_completion_rpc_task(task); |
@@ -3631,10 +3621,6 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, | |||
3631 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) | 3621 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) |
3632 | return -EOPNOTSUPP; | 3622 | return -EOPNOTSUPP; |
3633 | 3623 | ||
3634 | if (!S_ISREG(inode->i_mode) && | ||
3635 | (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) | ||
3636 | return -EPERM; | ||
3637 | |||
3638 | return nfs4_proc_set_acl(inode, buf, buflen); | 3624 | return nfs4_proc_set_acl(inode, buf, buflen); |
3639 | } | 3625 | } |
3640 | 3626 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 5a39c6f78acf..f9c7432471dc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -644,27 +644,26 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
644 | 644 | ||
645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | 645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
646 | { | 646 | { |
647 | struct rpc_sequence *sequence = counter->sequence; | ||
648 | struct nfs_seqid *new; | 647 | struct nfs_seqid *new; |
649 | 648 | ||
650 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 649 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
651 | if (new != NULL) { | 650 | if (new != NULL) { |
652 | new->sequence = counter; | 651 | new->sequence = counter; |
653 | spin_lock(&sequence->lock); | 652 | INIT_LIST_HEAD(&new->list); |
654 | list_add_tail(&new->list, &sequence->list); | ||
655 | spin_unlock(&sequence->lock); | ||
656 | } | 653 | } |
657 | return new; | 654 | return new; |
658 | } | 655 | } |
659 | 656 | ||
660 | void nfs_free_seqid(struct nfs_seqid *seqid) | 657 | void nfs_free_seqid(struct nfs_seqid *seqid) |
661 | { | 658 | { |
662 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 659 | if (!list_empty(&seqid->list)) { |
660 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
663 | 661 | ||
664 | spin_lock(&sequence->lock); | 662 | spin_lock(&sequence->lock); |
665 | list_del(&seqid->list); | 663 | list_del(&seqid->list); |
666 | spin_unlock(&sequence->lock); | 664 | spin_unlock(&sequence->lock); |
667 | rpc_wake_up(&sequence->wait); | 665 | rpc_wake_up(&sequence->wait); |
666 | } | ||
668 | kfree(seqid); | 667 | kfree(seqid); |
669 | } | 668 | } |
670 | 669 | ||
@@ -675,6 +674,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
675 | */ | 674 | */ |
676 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | 675 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
677 | { | 676 | { |
677 | BUG_ON(list_first_entry(&seqid->sequence->sequence->list, struct nfs_seqid, list) != seqid); | ||
678 | switch (status) { | 678 | switch (status) { |
679 | case 0: | 679 | case 0: |
680 | break; | 680 | break; |
@@ -726,15 +726,15 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | |||
726 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 726 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
727 | int status = 0; | 727 | int status = 0; |
728 | 728 | ||
729 | if (sequence->list.next == &seqid->list) | ||
730 | goto out; | ||
731 | spin_lock(&sequence->lock); | 729 | spin_lock(&sequence->lock); |
732 | if (sequence->list.next != &seqid->list) { | 730 | if (list_empty(&seqid->list)) |
733 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | 731 | list_add_tail(&seqid->list, &sequence->list); |
734 | status = -EAGAIN; | 732 | if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid) |
735 | } | 733 | goto unlock; |
734 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | ||
735 | status = -EAGAIN; | ||
736 | unlock: | ||
736 | spin_unlock(&sequence->lock); | 737 | spin_unlock(&sequence->lock); |
737 | out: | ||
738 | return status; | 738 | return status; |
739 | } | 739 | } |
740 | 740 | ||
@@ -758,8 +758,9 @@ static void nfs4_recover_state(struct nfs_client *clp) | |||
758 | 758 | ||
759 | __module_get(THIS_MODULE); | 759 | __module_get(THIS_MODULE); |
760 | atomic_inc(&clp->cl_count); | 760 | atomic_inc(&clp->cl_count); |
761 | task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", | 761 | task = kthread_run(reclaimer, clp, "%s-reclaim", |
762 | NIPQUAD(clp->cl_addr.sin_addr)); | 762 | rpc_peeraddr2str(clp->cl_rpcclient, |
763 | RPC_DISPLAY_ADDR)); | ||
763 | if (!IS_ERR(task)) | 764 | if (!IS_ERR(task)) |
764 | return; | 765 | return; |
765 | nfs4_clear_recover_bit(clp); | 766 | nfs4_clear_recover_bit(clp); |
@@ -970,8 +971,8 @@ out: | |||
970 | module_put_and_exit(0); | 971 | module_put_and_exit(0); |
971 | return 0; | 972 | return 0; |
972 | out_error: | 973 | out_error: |
973 | printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", | 974 | printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s" |
974 | NIPQUAD(clp->cl_addr.sin_addr), -status); | 975 | " with error %d\n", clp->cl_hostname, -status); |
975 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 976 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
976 | goto out; | 977 | goto out; |
977 | } | 978 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 51dd3804866f..db1ed9c46ede 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -116,10 +116,12 @@ static int nfs4_stat_to_errno(int); | |||
116 | #define decode_renew_maxsz (op_decode_hdr_maxsz) | 116 | #define decode_renew_maxsz (op_decode_hdr_maxsz) |
117 | #define encode_setclientid_maxsz \ | 117 | #define encode_setclientid_maxsz \ |
118 | (op_encode_hdr_maxsz + \ | 118 | (op_encode_hdr_maxsz + \ |
119 | 4 /*server->ip_addr*/ + \ | 119 | XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \ |
120 | 1 /*Netid*/ + \ | 120 | XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \ |
121 | 6 /*uaddr*/ + \ | 121 | 1 /* sc_prog */ + \ |
122 | 6 + (NFS4_VERIFIER_SIZE >> 2)) | 122 | XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \ |
123 | XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \ | ||
124 | 1) /* sc_cb_ident */ | ||
123 | #define decode_setclientid_maxsz \ | 125 | #define decode_setclientid_maxsz \ |
124 | (op_decode_hdr_maxsz + \ | 126 | (op_decode_hdr_maxsz + \ |
125 | 2 + \ | 127 | 2 + \ |
@@ -2515,14 +2517,12 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin | |||
2515 | 2517 | ||
2516 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) | 2518 | static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path) |
2517 | { | 2519 | { |
2518 | int n; | 2520 | u32 n; |
2519 | __be32 *p; | 2521 | __be32 *p; |
2520 | int status = 0; | 2522 | int status = 0; |
2521 | 2523 | ||
2522 | READ_BUF(4); | 2524 | READ_BUF(4); |
2523 | READ32(n); | 2525 | READ32(n); |
2524 | if (n < 0) | ||
2525 | goto out_eio; | ||
2526 | if (n == 0) | 2526 | if (n == 0) |
2527 | goto root_path; | 2527 | goto root_path; |
2528 | dprintk("path "); | 2528 | dprintk("path "); |
@@ -2579,13 +2579,11 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
2579 | goto out_eio; | 2579 | goto out_eio; |
2580 | res->nlocations = 0; | 2580 | res->nlocations = 0; |
2581 | while (res->nlocations < n) { | 2581 | while (res->nlocations < n) { |
2582 | int m; | 2582 | u32 m; |
2583 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; | 2583 | struct nfs4_fs_location *loc = &res->locations[res->nlocations]; |
2584 | 2584 | ||
2585 | READ_BUF(4); | 2585 | READ_BUF(4); |
2586 | READ32(m); | 2586 | READ32(m); |
2587 | if (m <= 0) | ||
2588 | goto out_eio; | ||
2589 | 2587 | ||
2590 | loc->nservers = 0; | 2588 | loc->nservers = 0; |
2591 | dprintk("%s: servers ", __FUNCTION__); | 2589 | dprintk("%s: servers ", __FUNCTION__); |
@@ -2598,8 +2596,12 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
2598 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) | 2596 | if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS) |
2599 | loc->nservers++; | 2597 | loc->nservers++; |
2600 | else { | 2598 | else { |
2601 | int i; | 2599 | unsigned int i; |
2602 | dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations); | 2600 | dprintk("%s: using first %u of %u servers " |
2601 | "returned for location %u\n", | ||
2602 | __FUNCTION__, | ||
2603 | NFS4_FS_LOCATION_MAXSERVERS, | ||
2604 | m, res->nlocations); | ||
2603 | for (i = loc->nservers; i < m; i++) { | 2605 | for (i = loc->nservers; i < m; i++) { |
2604 | unsigned int len; | 2606 | unsigned int len; |
2605 | char *data; | 2607 | char *data; |
@@ -3476,10 +3478,11 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3476 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 3478 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
3477 | struct page *page = *rcvbuf->pages; | 3479 | struct page *page = *rcvbuf->pages; |
3478 | struct kvec *iov = rcvbuf->head; | 3480 | struct kvec *iov = rcvbuf->head; |
3479 | unsigned int nr, pglen = rcvbuf->page_len; | 3481 | size_t hdrlen; |
3482 | u32 recvd, pglen = rcvbuf->page_len; | ||
3480 | __be32 *end, *entry, *p, *kaddr; | 3483 | __be32 *end, *entry, *p, *kaddr; |
3481 | uint32_t len, attrlen, xlen; | 3484 | unsigned int nr; |
3482 | int hdrlen, recvd, status; | 3485 | int status; |
3483 | 3486 | ||
3484 | status = decode_op_hdr(xdr, OP_READDIR); | 3487 | status = decode_op_hdr(xdr, OP_READDIR); |
3485 | if (status) | 3488 | if (status) |
@@ -3503,6 +3506,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3503 | end = p + ((pglen + readdir->pgbase) >> 2); | 3506 | end = p + ((pglen + readdir->pgbase) >> 2); |
3504 | entry = p; | 3507 | entry = p; |
3505 | for (nr = 0; *p++; nr++) { | 3508 | for (nr = 0; *p++; nr++) { |
3509 | u32 len, attrlen, xlen; | ||
3506 | if (end - p < 3) | 3510 | if (end - p < 3) |
3507 | goto short_pkt; | 3511 | goto short_pkt; |
3508 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); | 3512 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); |
@@ -3551,7 +3555,8 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | |||
3551 | { | 3555 | { |
3552 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 3556 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
3553 | struct kvec *iov = rcvbuf->head; | 3557 | struct kvec *iov = rcvbuf->head; |
3554 | int hdrlen, len, recvd; | 3558 | size_t hdrlen; |
3559 | u32 len, recvd; | ||
3555 | __be32 *p; | 3560 | __be32 *p; |
3556 | char *kaddr; | 3561 | char *kaddr; |
3557 | int status; | 3562 | int status; |
@@ -3646,7 +3651,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
3646 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) | 3651 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) |
3647 | return -EIO; | 3652 | return -EIO; |
3648 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | 3653 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
3649 | int hdrlen, recvd; | 3654 | size_t hdrlen; |
3655 | u32 recvd; | ||
3650 | 3656 | ||
3651 | /* We ignore &savep and don't do consistency checks on | 3657 | /* We ignore &savep and don't do consistency checks on |
3652 | * the attr length. Let userspace figure it out.... */ | 3658 | * the attr length. Let userspace figure it out.... */ |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 345bb9b4765b..3b3dbb94393d 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -111,13 +111,14 @@ void nfs_unlock_request(struct nfs_page *req) | |||
111 | * nfs_set_page_tag_locked - Tag a request as locked | 111 | * nfs_set_page_tag_locked - Tag a request as locked |
112 | * @req: | 112 | * @req: |
113 | */ | 113 | */ |
114 | static int nfs_set_page_tag_locked(struct nfs_page *req) | 114 | int nfs_set_page_tag_locked(struct nfs_page *req) |
115 | { | 115 | { |
116 | struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode); | 116 | struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode); |
117 | 117 | ||
118 | if (!nfs_lock_request(req)) | 118 | if (!nfs_lock_request_dontget(req)) |
119 | return 0; | 119 | return 0; |
120 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 120 | if (req->wb_page != NULL) |
121 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | ||
121 | return 1; | 122 | return 1; |
122 | } | 123 | } |
123 | 124 | ||
@@ -132,9 +133,10 @@ void nfs_clear_page_tag_locked(struct nfs_page *req) | |||
132 | if (req->wb_page != NULL) { | 133 | if (req->wb_page != NULL) { |
133 | spin_lock(&inode->i_lock); | 134 | spin_lock(&inode->i_lock); |
134 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 135 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
136 | nfs_unlock_request(req); | ||
135 | spin_unlock(&inode->i_lock); | 137 | spin_unlock(&inode->i_lock); |
136 | } | 138 | } else |
137 | nfs_unlock_request(req); | 139 | nfs_unlock_request(req); |
138 | } | 140 | } |
139 | 141 | ||
140 | /** | 142 | /** |
@@ -421,6 +423,7 @@ int nfs_scan_list(struct nfs_inode *nfsi, | |||
421 | goto out; | 423 | goto out; |
422 | idx_start = req->wb_index + 1; | 424 | idx_start = req->wb_index + 1; |
423 | if (nfs_set_page_tag_locked(req)) { | 425 | if (nfs_set_page_tag_locked(req)) { |
426 | kref_get(&req->wb_kref); | ||
424 | nfs_list_remove_request(req); | 427 | nfs_list_remove_request(req); |
425 | radix_tree_tag_clear(&nfsi->nfs_page_tree, | 428 | radix_tree_tag_clear(&nfsi->nfs_page_tree, |
426 | req->wb_index, tag); | 429 | req->wb_index, tag); |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 4f80d88e9fee..5ccf7faee19c 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -565,16 +565,9 @@ static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
565 | return 0; | 565 | return 0; |
566 | } | 566 | } |
567 | 567 | ||
568 | static void nfs_proc_read_setup(struct nfs_read_data *data) | 568 | static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
569 | { | 569 | { |
570 | struct rpc_message msg = { | 570 | msg->rpc_proc = &nfs_procedures[NFSPROC_READ]; |
571 | .rpc_proc = &nfs_procedures[NFSPROC_READ], | ||
572 | .rpc_argp = &data->args, | ||
573 | .rpc_resp = &data->res, | ||
574 | .rpc_cred = data->cred, | ||
575 | }; | ||
576 | |||
577 | rpc_call_setup(&data->task, &msg, 0); | ||
578 | } | 571 | } |
579 | 572 | ||
580 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 573 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -584,24 +577,15 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
584 | return 0; | 577 | return 0; |
585 | } | 578 | } |
586 | 579 | ||
587 | static void nfs_proc_write_setup(struct nfs_write_data *data, int how) | 580 | static void nfs_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
588 | { | 581 | { |
589 | struct rpc_message msg = { | ||
590 | .rpc_proc = &nfs_procedures[NFSPROC_WRITE], | ||
591 | .rpc_argp = &data->args, | ||
592 | .rpc_resp = &data->res, | ||
593 | .rpc_cred = data->cred, | ||
594 | }; | ||
595 | |||
596 | /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ | 582 | /* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */ |
597 | data->args.stable = NFS_FILE_SYNC; | 583 | data->args.stable = NFS_FILE_SYNC; |
598 | 584 | msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE]; | |
599 | /* Finalize the task. */ | ||
600 | rpc_call_setup(&data->task, &msg, 0); | ||
601 | } | 585 | } |
602 | 586 | ||
603 | static void | 587 | static void |
604 | nfs_proc_commit_setup(struct nfs_write_data *data, int how) | 588 | nfs_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
605 | { | 589 | { |
606 | BUG(); | 590 | BUG(); |
607 | } | 591 | } |
@@ -609,7 +593,9 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how) | |||
609 | static int | 593 | static int |
610 | nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) | 594 | nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) |
611 | { | 595 | { |
612 | return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); | 596 | struct inode *inode = filp->f_path.dentry->d_inode; |
597 | |||
598 | return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); | ||
613 | } | 599 | } |
614 | 600 | ||
615 | 601 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 4587a86adaac..8fd6dfbe1bc3 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -160,12 +160,26 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
160 | const struct rpc_call_ops *call_ops, | 160 | const struct rpc_call_ops *call_ops, |
161 | unsigned int count, unsigned int offset) | 161 | unsigned int count, unsigned int offset) |
162 | { | 162 | { |
163 | struct inode *inode; | 163 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
164 | int flags; | 164 | int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0; |
165 | struct rpc_task *task; | ||
166 | struct rpc_message msg = { | ||
167 | .rpc_argp = &data->args, | ||
168 | .rpc_resp = &data->res, | ||
169 | .rpc_cred = req->wb_context->cred, | ||
170 | }; | ||
171 | struct rpc_task_setup task_setup_data = { | ||
172 | .task = &data->task, | ||
173 | .rpc_client = NFS_CLIENT(inode), | ||
174 | .rpc_message = &msg, | ||
175 | .callback_ops = call_ops, | ||
176 | .callback_data = data, | ||
177 | .flags = RPC_TASK_ASYNC | swap_flags, | ||
178 | }; | ||
165 | 179 | ||
166 | data->req = req; | 180 | data->req = req; |
167 | data->inode = inode = req->wb_context->path.dentry->d_inode; | 181 | data->inode = inode; |
168 | data->cred = req->wb_context->cred; | 182 | data->cred = msg.rpc_cred; |
169 | 183 | ||
170 | data->args.fh = NFS_FH(inode); | 184 | data->args.fh = NFS_FH(inode); |
171 | data->args.offset = req_offset(req) + offset; | 185 | data->args.offset = req_offset(req) + offset; |
@@ -180,11 +194,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
180 | nfs_fattr_init(&data->fattr); | 194 | nfs_fattr_init(&data->fattr); |
181 | 195 | ||
182 | /* Set up the initial task struct. */ | 196 | /* Set up the initial task struct. */ |
183 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | 197 | NFS_PROTO(inode)->read_setup(data, &msg); |
184 | rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data); | ||
185 | NFS_PROTO(inode)->read_setup(data); | ||
186 | |||
187 | data->task.tk_cookie = (unsigned long)inode; | ||
188 | 198 | ||
189 | dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 199 | dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
190 | data->task.tk_pid, | 200 | data->task.tk_pid, |
@@ -192,6 +202,10 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
192 | (long long)NFS_FILEID(inode), | 202 | (long long)NFS_FILEID(inode), |
193 | count, | 203 | count, |
194 | (unsigned long long)data->args.offset); | 204 | (unsigned long long)data->args.offset); |
205 | |||
206 | task = rpc_run_task(&task_setup_data); | ||
207 | if (!IS_ERR(task)) | ||
208 | rpc_put_task(task); | ||
195 | } | 209 | } |
196 | 210 | ||
197 | static void | 211 | static void |
@@ -208,19 +222,6 @@ nfs_async_read_error(struct list_head *head) | |||
208 | } | 222 | } |
209 | 223 | ||
210 | /* | 224 | /* |
211 | * Start an async read operation | ||
212 | */ | ||
213 | static void nfs_execute_read(struct nfs_read_data *data) | ||
214 | { | ||
215 | struct rpc_clnt *clnt = NFS_CLIENT(data->inode); | ||
216 | sigset_t oldset; | ||
217 | |||
218 | rpc_clnt_sigmask(clnt, &oldset); | ||
219 | rpc_execute(&data->task); | ||
220 | rpc_clnt_sigunmask(clnt, &oldset); | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Generate multiple requests to fill a single page. | 225 | * Generate multiple requests to fill a single page. |
225 | * | 226 | * |
226 | * We optimize to reduce the number of read operations on the wire. If we | 227 | * We optimize to reduce the number of read operations on the wire. If we |
@@ -274,7 +275,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne | |||
274 | rsize, offset); | 275 | rsize, offset); |
275 | offset += rsize; | 276 | offset += rsize; |
276 | nbytes -= rsize; | 277 | nbytes -= rsize; |
277 | nfs_execute_read(data); | ||
278 | } while (nbytes != 0); | 278 | } while (nbytes != 0); |
279 | 279 | ||
280 | return 0; | 280 | return 0; |
@@ -312,8 +312,6 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned | |||
312 | req = nfs_list_entry(data->pages.next); | 312 | req = nfs_list_entry(data->pages.next); |
313 | 313 | ||
314 | nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); | 314 | nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); |
315 | |||
316 | nfs_execute_read(data); | ||
317 | return 0; | 315 | return 0; |
318 | out_bad: | 316 | out_bad: |
319 | nfs_async_read_error(head); | 317 | nfs_async_read_error(head); |
@@ -338,7 +336,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | |||
338 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); | 336 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); |
339 | 337 | ||
340 | if (task->tk_status == -ESTALE) { | 338 | if (task->tk_status == -ESTALE) { |
341 | set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); | 339 | set_bit(NFS_INO_STALE, &NFS_I(data->inode)->flags); |
342 | nfs_mark_for_revalidate(data->inode); | 340 | nfs_mark_for_revalidate(data->inode); |
343 | } | 341 | } |
344 | return 0; | 342 | return 0; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 0b0c72a072ff..22c49c02897d 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <linux/nfs_idmap.h> | 45 | #include <linux/nfs_idmap.h> |
46 | #include <linux/vfs.h> | 46 | #include <linux/vfs.h> |
47 | #include <linux/inet.h> | 47 | #include <linux/inet.h> |
48 | #include <linux/in6.h> | ||
49 | #include <net/ipv6.h> | ||
48 | #include <linux/nfs_xdr.h> | 50 | #include <linux/nfs_xdr.h> |
49 | #include <linux/magic.h> | 51 | #include <linux/magic.h> |
50 | #include <linux/parser.h> | 52 | #include <linux/parser.h> |
@@ -83,11 +85,11 @@ enum { | |||
83 | Opt_actimeo, | 85 | Opt_actimeo, |
84 | Opt_namelen, | 86 | Opt_namelen, |
85 | Opt_mountport, | 87 | Opt_mountport, |
86 | Opt_mountprog, Opt_mountvers, | 88 | Opt_mountvers, |
87 | Opt_nfsprog, Opt_nfsvers, | 89 | Opt_nfsvers, |
88 | 90 | ||
89 | /* Mount options that take string arguments */ | 91 | /* Mount options that take string arguments */ |
90 | Opt_sec, Opt_proto, Opt_mountproto, | 92 | Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, |
91 | Opt_addr, Opt_mountaddr, Opt_clientaddr, | 93 | Opt_addr, Opt_mountaddr, Opt_clientaddr, |
92 | 94 | ||
93 | /* Mount options that are ignored */ | 95 | /* Mount options that are ignored */ |
@@ -137,9 +139,7 @@ static match_table_t nfs_mount_option_tokens = { | |||
137 | { Opt_userspace, "retry=%u" }, | 139 | { Opt_userspace, "retry=%u" }, |
138 | { Opt_namelen, "namlen=%u" }, | 140 | { Opt_namelen, "namlen=%u" }, |
139 | { Opt_mountport, "mountport=%u" }, | 141 | { Opt_mountport, "mountport=%u" }, |
140 | { Opt_mountprog, "mountprog=%u" }, | ||
141 | { Opt_mountvers, "mountvers=%u" }, | 142 | { Opt_mountvers, "mountvers=%u" }, |
142 | { Opt_nfsprog, "nfsprog=%u" }, | ||
143 | { Opt_nfsvers, "nfsvers=%u" }, | 143 | { Opt_nfsvers, "nfsvers=%u" }, |
144 | { Opt_nfsvers, "vers=%u" }, | 144 | { Opt_nfsvers, "vers=%u" }, |
145 | 145 | ||
@@ -148,7 +148,7 @@ static match_table_t nfs_mount_option_tokens = { | |||
148 | { Opt_mountproto, "mountproto=%s" }, | 148 | { Opt_mountproto, "mountproto=%s" }, |
149 | { Opt_addr, "addr=%s" }, | 149 | { Opt_addr, "addr=%s" }, |
150 | { Opt_clientaddr, "clientaddr=%s" }, | 150 | { Opt_clientaddr, "clientaddr=%s" }, |
151 | { Opt_userspace, "mounthost=%s" }, | 151 | { Opt_mounthost, "mounthost=%s" }, |
152 | { Opt_mountaddr, "mountaddr=%s" }, | 152 | { Opt_mountaddr, "mountaddr=%s" }, |
153 | 153 | ||
154 | { Opt_err, NULL } | 154 | { Opt_err, NULL } |
@@ -202,6 +202,7 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru | |||
202 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, | 202 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, |
203 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 203 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
204 | static void nfs_kill_super(struct super_block *); | 204 | static void nfs_kill_super(struct super_block *); |
205 | static void nfs_put_super(struct super_block *); | ||
205 | 206 | ||
206 | static struct file_system_type nfs_fs_type = { | 207 | static struct file_system_type nfs_fs_type = { |
207 | .owner = THIS_MODULE, | 208 | .owner = THIS_MODULE, |
@@ -223,6 +224,7 @@ static const struct super_operations nfs_sops = { | |||
223 | .alloc_inode = nfs_alloc_inode, | 224 | .alloc_inode = nfs_alloc_inode, |
224 | .destroy_inode = nfs_destroy_inode, | 225 | .destroy_inode = nfs_destroy_inode, |
225 | .write_inode = nfs_write_inode, | 226 | .write_inode = nfs_write_inode, |
227 | .put_super = nfs_put_super, | ||
226 | .statfs = nfs_statfs, | 228 | .statfs = nfs_statfs, |
227 | .clear_inode = nfs_clear_inode, | 229 | .clear_inode = nfs_clear_inode, |
228 | .umount_begin = nfs_umount_begin, | 230 | .umount_begin = nfs_umount_begin, |
@@ -325,6 +327,28 @@ void __exit unregister_nfs_fs(void) | |||
325 | unregister_filesystem(&nfs_fs_type); | 327 | unregister_filesystem(&nfs_fs_type); |
326 | } | 328 | } |
327 | 329 | ||
330 | void nfs_sb_active(struct nfs_server *server) | ||
331 | { | ||
332 | atomic_inc(&server->active); | ||
333 | } | ||
334 | |||
335 | void nfs_sb_deactive(struct nfs_server *server) | ||
336 | { | ||
337 | if (atomic_dec_and_test(&server->active)) | ||
338 | wake_up(&server->active_wq); | ||
339 | } | ||
340 | |||
341 | static void nfs_put_super(struct super_block *sb) | ||
342 | { | ||
343 | struct nfs_server *server = NFS_SB(sb); | ||
344 | /* | ||
345 | * Make sure there are no outstanding ops to this server. | ||
346 | * If so, wait for them to finish before allowing the | ||
347 | * unmount to continue. | ||
348 | */ | ||
349 | wait_event(server->active_wq, atomic_read(&server->active) == 0); | ||
350 | } | ||
351 | |||
328 | /* | 352 | /* |
329 | * Deliver file system statistics to userspace | 353 | * Deliver file system statistics to userspace |
330 | */ | 354 | */ |
@@ -455,8 +479,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
455 | } | 479 | } |
456 | seq_printf(m, ",proto=%s", | 480 | seq_printf(m, ",proto=%s", |
457 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); | 481 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); |
458 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | 482 | seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ); |
459 | seq_printf(m, ",retrans=%u", clp->retrans_count); | 483 | seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries); |
460 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); | 484 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
461 | } | 485 | } |
462 | 486 | ||
@@ -469,8 +493,9 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
469 | 493 | ||
470 | nfs_show_mount_options(m, nfss, 0); | 494 | nfs_show_mount_options(m, nfss, 0); |
471 | 495 | ||
472 | seq_printf(m, ",addr="NIPQUAD_FMT, | 496 | seq_printf(m, ",addr=%s", |
473 | NIPQUAD(nfss->nfs_client->cl_addr.sin_addr)); | 497 | rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient, |
498 | RPC_DISPLAY_ADDR)); | ||
474 | 499 | ||
475 | return 0; | 500 | return 0; |
476 | } | 501 | } |
@@ -507,7 +532,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) | |||
507 | seq_printf(m, ",namelen=%d", nfss->namelen); | 532 | seq_printf(m, ",namelen=%d", nfss->namelen); |
508 | 533 | ||
509 | #ifdef CONFIG_NFS_V4 | 534 | #ifdef CONFIG_NFS_V4 |
510 | if (nfss->nfs_client->cl_nfsversion == 4) { | 535 | if (nfss->nfs_client->rpc_ops->version == 4) { |
511 | seq_printf(m, "\n\tnfsv4:\t"); | 536 | seq_printf(m, "\n\tnfsv4:\t"); |
512 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 537 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
513 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); | 538 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
@@ -575,16 +600,40 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
575 | } | 600 | } |
576 | 601 | ||
577 | /* | 602 | /* |
578 | * Sanity-check a server address provided by the mount command | 603 | * Set the port number in an address. Be agnostic about the address family. |
604 | */ | ||
605 | static void nfs_set_port(struct sockaddr *sap, unsigned short port) | ||
606 | { | ||
607 | switch (sap->sa_family) { | ||
608 | case AF_INET: { | ||
609 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
610 | ap->sin_port = htons(port); | ||
611 | break; | ||
612 | } | ||
613 | case AF_INET6: { | ||
614 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
615 | ap->sin6_port = htons(port); | ||
616 | break; | ||
617 | } | ||
618 | } | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * Sanity-check a server address provided by the mount command. | ||
623 | * | ||
624 | * Address family must be initialized, and address must not be | ||
625 | * the ANY address for that family. | ||
579 | */ | 626 | */ |
580 | static int nfs_verify_server_address(struct sockaddr *addr) | 627 | static int nfs_verify_server_address(struct sockaddr *addr) |
581 | { | 628 | { |
582 | switch (addr->sa_family) { | 629 | switch (addr->sa_family) { |
583 | case AF_INET: { | 630 | case AF_INET: { |
584 | struct sockaddr_in *sa = (struct sockaddr_in *) addr; | 631 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; |
585 | if (sa->sin_addr.s_addr != INADDR_ANY) | 632 | return sa->sin_addr.s_addr != INADDR_ANY; |
586 | return 1; | 633 | } |
587 | break; | 634 | case AF_INET6: { |
635 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; | ||
636 | return !ipv6_addr_any(sa); | ||
588 | } | 637 | } |
589 | } | 638 | } |
590 | 639 | ||
@@ -592,6 +641,40 @@ static int nfs_verify_server_address(struct sockaddr *addr) | |||
592 | } | 641 | } |
593 | 642 | ||
594 | /* | 643 | /* |
644 | * Parse string addresses passed in via a mount option, | ||
645 | * and construct a sockaddr based on the result. | ||
646 | * | ||
647 | * If address parsing fails, set the sockaddr's address | ||
648 | * family to AF_UNSPEC to force nfs_verify_server_address() | ||
649 | * to punt the mount. | ||
650 | */ | ||
651 | static void nfs_parse_server_address(char *value, | ||
652 | struct sockaddr *sap, | ||
653 | size_t *len) | ||
654 | { | ||
655 | if (strchr(value, ':')) { | ||
656 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
657 | u8 *addr = (u8 *)&ap->sin6_addr.in6_u; | ||
658 | |||
659 | ap->sin6_family = AF_INET6; | ||
660 | *len = sizeof(*ap); | ||
661 | if (in6_pton(value, -1, addr, '\0', NULL)) | ||
662 | return; | ||
663 | } else { | ||
664 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
665 | u8 *addr = (u8 *)&ap->sin_addr.s_addr; | ||
666 | |||
667 | ap->sin_family = AF_INET; | ||
668 | *len = sizeof(*ap); | ||
669 | if (in4_pton(value, -1, addr, '\0', NULL)) | ||
670 | return; | ||
671 | } | ||
672 | |||
673 | sap->sa_family = AF_UNSPEC; | ||
674 | *len = 0; | ||
675 | } | ||
676 | |||
677 | /* | ||
595 | * Error-check and convert a string of mount options from user space into | 678 | * Error-check and convert a string of mount options from user space into |
596 | * a data structure | 679 | * a data structure |
597 | */ | 680 | */ |
@@ -599,6 +682,7 @@ static int nfs_parse_mount_options(char *raw, | |||
599 | struct nfs_parsed_mount_data *mnt) | 682 | struct nfs_parsed_mount_data *mnt) |
600 | { | 683 | { |
601 | char *p, *string; | 684 | char *p, *string; |
685 | unsigned short port = 0; | ||
602 | 686 | ||
603 | if (!raw) { | 687 | if (!raw) { |
604 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 688 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -701,7 +785,7 @@ static int nfs_parse_mount_options(char *raw, | |||
701 | return 0; | 785 | return 0; |
702 | if (option < 0 || option > 65535) | 786 | if (option < 0 || option > 65535) |
703 | return 0; | 787 | return 0; |
704 | mnt->nfs_server.address.sin_port = htons(option); | 788 | port = option; |
705 | break; | 789 | break; |
706 | case Opt_rsize: | 790 | case Opt_rsize: |
707 | if (match_int(args, &mnt->rsize)) | 791 | if (match_int(args, &mnt->rsize)) |
@@ -763,13 +847,6 @@ static int nfs_parse_mount_options(char *raw, | |||
763 | return 0; | 847 | return 0; |
764 | mnt->mount_server.port = option; | 848 | mnt->mount_server.port = option; |
765 | break; | 849 | break; |
766 | case Opt_mountprog: | ||
767 | if (match_int(args, &option)) | ||
768 | return 0; | ||
769 | if (option < 0) | ||
770 | return 0; | ||
771 | mnt->mount_server.program = option; | ||
772 | break; | ||
773 | case Opt_mountvers: | 850 | case Opt_mountvers: |
774 | if (match_int(args, &option)) | 851 | if (match_int(args, &option)) |
775 | return 0; | 852 | return 0; |
@@ -777,13 +854,6 @@ static int nfs_parse_mount_options(char *raw, | |||
777 | return 0; | 854 | return 0; |
778 | mnt->mount_server.version = option; | 855 | mnt->mount_server.version = option; |
779 | break; | 856 | break; |
780 | case Opt_nfsprog: | ||
781 | if (match_int(args, &option)) | ||
782 | return 0; | ||
783 | if (option < 0) | ||
784 | return 0; | ||
785 | mnt->nfs_server.program = option; | ||
786 | break; | ||
787 | case Opt_nfsvers: | 857 | case Opt_nfsvers: |
788 | if (match_int(args, &option)) | 858 | if (match_int(args, &option)) |
789 | return 0; | 859 | return 0; |
@@ -927,24 +997,32 @@ static int nfs_parse_mount_options(char *raw, | |||
927 | string = match_strdup(args); | 997 | string = match_strdup(args); |
928 | if (string == NULL) | 998 | if (string == NULL) |
929 | goto out_nomem; | 999 | goto out_nomem; |
930 | mnt->nfs_server.address.sin_family = AF_INET; | 1000 | nfs_parse_server_address(string, (struct sockaddr *) |
931 | mnt->nfs_server.address.sin_addr.s_addr = | 1001 | &mnt->nfs_server.address, |
932 | in_aton(string); | 1002 | &mnt->nfs_server.addrlen); |
933 | kfree(string); | 1003 | kfree(string); |
934 | break; | 1004 | break; |
935 | case Opt_clientaddr: | 1005 | case Opt_clientaddr: |
936 | string = match_strdup(args); | 1006 | string = match_strdup(args); |
937 | if (string == NULL) | 1007 | if (string == NULL) |
938 | goto out_nomem; | 1008 | goto out_nomem; |
1009 | kfree(mnt->client_address); | ||
939 | mnt->client_address = string; | 1010 | mnt->client_address = string; |
940 | break; | 1011 | break; |
1012 | case Opt_mounthost: | ||
1013 | string = match_strdup(args); | ||
1014 | if (string == NULL) | ||
1015 | goto out_nomem; | ||
1016 | kfree(mnt->mount_server.hostname); | ||
1017 | mnt->mount_server.hostname = string; | ||
1018 | break; | ||
941 | case Opt_mountaddr: | 1019 | case Opt_mountaddr: |
942 | string = match_strdup(args); | 1020 | string = match_strdup(args); |
943 | if (string == NULL) | 1021 | if (string == NULL) |
944 | goto out_nomem; | 1022 | goto out_nomem; |
945 | mnt->mount_server.address.sin_family = AF_INET; | 1023 | nfs_parse_server_address(string, (struct sockaddr *) |
946 | mnt->mount_server.address.sin_addr.s_addr = | 1024 | &mnt->mount_server.address, |
947 | in_aton(string); | 1025 | &mnt->mount_server.addrlen); |
948 | kfree(string); | 1026 | kfree(string); |
949 | break; | 1027 | break; |
950 | 1028 | ||
@@ -957,6 +1035,8 @@ static int nfs_parse_mount_options(char *raw, | |||
957 | } | 1035 | } |
958 | } | 1036 | } |
959 | 1037 | ||
1038 | nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port); | ||
1039 | |||
960 | return 1; | 1040 | return 1; |
961 | 1041 | ||
962 | out_nomem: | 1042 | out_nomem: |
@@ -987,7 +1067,8 @@ out_unknown: | |||
987 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, | 1067 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, |
988 | struct nfs_fh *root_fh) | 1068 | struct nfs_fh *root_fh) |
989 | { | 1069 | { |
990 | struct sockaddr_in sin; | 1070 | struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address; |
1071 | char *hostname; | ||
991 | int status; | 1072 | int status; |
992 | 1073 | ||
993 | if (args->mount_server.version == 0) { | 1074 | if (args->mount_server.version == 0) { |
@@ -997,25 +1078,32 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
997 | args->mount_server.version = NFS_MNT_VERSION; | 1078 | args->mount_server.version = NFS_MNT_VERSION; |
998 | } | 1079 | } |
999 | 1080 | ||
1081 | if (args->mount_server.hostname) | ||
1082 | hostname = args->mount_server.hostname; | ||
1083 | else | ||
1084 | hostname = args->nfs_server.hostname; | ||
1085 | |||
1000 | /* | 1086 | /* |
1001 | * Construct the mount server's address. | 1087 | * Construct the mount server's address. |
1002 | */ | 1088 | */ |
1003 | if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY) | 1089 | if (args->mount_server.address.ss_family == AF_UNSPEC) { |
1004 | sin = args->mount_server.address; | 1090 | memcpy(sap, &args->nfs_server.address, |
1005 | else | 1091 | args->nfs_server.addrlen); |
1006 | sin = args->nfs_server.address; | 1092 | args->mount_server.addrlen = args->nfs_server.addrlen; |
1093 | } | ||
1094 | |||
1007 | /* | 1095 | /* |
1008 | * autobind will be used if mount_server.port == 0 | 1096 | * autobind will be used if mount_server.port == 0 |
1009 | */ | 1097 | */ |
1010 | sin.sin_port = htons(args->mount_server.port); | 1098 | nfs_set_port(sap, args->mount_server.port); |
1011 | 1099 | ||
1012 | /* | 1100 | /* |
1013 | * Now ask the mount server to map our export path | 1101 | * Now ask the mount server to map our export path |
1014 | * to a file handle. | 1102 | * to a file handle. |
1015 | */ | 1103 | */ |
1016 | status = nfs_mount((struct sockaddr *) &sin, | 1104 | status = nfs_mount(sap, |
1017 | sizeof(sin), | 1105 | args->mount_server.addrlen, |
1018 | args->nfs_server.hostname, | 1106 | hostname, |
1019 | args->nfs_server.export_path, | 1107 | args->nfs_server.export_path, |
1020 | args->mount_server.version, | 1108 | args->mount_server.version, |
1021 | args->mount_server.protocol, | 1109 | args->mount_server.protocol, |
@@ -1023,8 +1111,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1023 | if (status == 0) | 1111 | if (status == 0) |
1024 | return 0; | 1112 | return 0; |
1025 | 1113 | ||
1026 | dfprintk(MOUNT, "NFS: unable to mount server " NIPQUAD_FMT | 1114 | dfprintk(MOUNT, "NFS: unable to mount server %s, error %d", |
1027 | ", error %d\n", NIPQUAD(sin.sin_addr.s_addr), status); | 1115 | hostname, status); |
1028 | return status; | 1116 | return status; |
1029 | } | 1117 | } |
1030 | 1118 | ||
@@ -1043,9 +1131,6 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1043 | * | 1131 | * |
1044 | * + breaking back: trying proto=udp after proto=tcp, v2 after v3, | 1132 | * + breaking back: trying proto=udp after proto=tcp, v2 after v3, |
1045 | * mountproto=tcp after mountproto=udp, and so on | 1133 | * mountproto=tcp after mountproto=udp, and so on |
1046 | * | ||
1047 | * XXX: as far as I can tell, changing the NFS program number is not | ||
1048 | * supported in the NFS client. | ||
1049 | */ | 1134 | */ |
1050 | static int nfs_validate_mount_data(void *options, | 1135 | static int nfs_validate_mount_data(void *options, |
1051 | struct nfs_parsed_mount_data *args, | 1136 | struct nfs_parsed_mount_data *args, |
@@ -1069,9 +1154,7 @@ static int nfs_validate_mount_data(void *options, | |||
1069 | args->acdirmin = 30; | 1154 | args->acdirmin = 30; |
1070 | args->acdirmax = 60; | 1155 | args->acdirmax = 60; |
1071 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; | 1156 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; |
1072 | args->mount_server.program = NFS_MNT_PROGRAM; | ||
1073 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 1157 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
1074 | args->nfs_server.program = NFS_PROGRAM; | ||
1075 | 1158 | ||
1076 | switch (data->version) { | 1159 | switch (data->version) { |
1077 | case 1: | 1160 | case 1: |
@@ -1102,9 +1185,6 @@ static int nfs_validate_mount_data(void *options, | |||
1102 | memset(mntfh->data + mntfh->size, 0, | 1185 | memset(mntfh->data + mntfh->size, 0, |
1103 | sizeof(mntfh->data) - mntfh->size); | 1186 | sizeof(mntfh->data) - mntfh->size); |
1104 | 1187 | ||
1105 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
1106 | goto out_no_address; | ||
1107 | |||
1108 | /* | 1188 | /* |
1109 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | 1189 | * Translate to nfs_parsed_mount_data, which nfs_fill_super |
1110 | * can deal with. | 1190 | * can deal with. |
@@ -1119,7 +1199,14 @@ static int nfs_validate_mount_data(void *options, | |||
1119 | args->acregmax = data->acregmax; | 1199 | args->acregmax = data->acregmax; |
1120 | args->acdirmin = data->acdirmin; | 1200 | args->acdirmin = data->acdirmin; |
1121 | args->acdirmax = data->acdirmax; | 1201 | args->acdirmax = data->acdirmax; |
1122 | args->nfs_server.address = data->addr; | 1202 | |
1203 | memcpy(&args->nfs_server.address, &data->addr, | ||
1204 | sizeof(data->addr)); | ||
1205 | args->nfs_server.addrlen = sizeof(data->addr); | ||
1206 | if (!nfs_verify_server_address((struct sockaddr *) | ||
1207 | &args->nfs_server.address)) | ||
1208 | goto out_no_address; | ||
1209 | |||
1123 | if (!(data->flags & NFS_MOUNT_TCP)) | 1210 | if (!(data->flags & NFS_MOUNT_TCP)) |
1124 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1211 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
1125 | /* N.B. caller will free nfs_server.hostname in all cases */ | 1212 | /* N.B. caller will free nfs_server.hostname in all cases */ |
@@ -1322,15 +1409,50 @@ static int nfs_set_super(struct super_block *s, void *data) | |||
1322 | return ret; | 1409 | return ret; |
1323 | } | 1410 | } |
1324 | 1411 | ||
1412 | static int nfs_compare_super_address(struct nfs_server *server1, | ||
1413 | struct nfs_server *server2) | ||
1414 | { | ||
1415 | struct sockaddr *sap1, *sap2; | ||
1416 | |||
1417 | sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr; | ||
1418 | sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr; | ||
1419 | |||
1420 | if (sap1->sa_family != sap2->sa_family) | ||
1421 | return 0; | ||
1422 | |||
1423 | switch (sap1->sa_family) { | ||
1424 | case AF_INET: { | ||
1425 | struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1; | ||
1426 | struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2; | ||
1427 | if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) | ||
1428 | return 0; | ||
1429 | if (sin1->sin_port != sin2->sin_port) | ||
1430 | return 0; | ||
1431 | break; | ||
1432 | } | ||
1433 | case AF_INET6: { | ||
1434 | struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1; | ||
1435 | struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2; | ||
1436 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) | ||
1437 | return 0; | ||
1438 | if (sin1->sin6_port != sin2->sin6_port) | ||
1439 | return 0; | ||
1440 | break; | ||
1441 | } | ||
1442 | default: | ||
1443 | return 0; | ||
1444 | } | ||
1445 | |||
1446 | return 1; | ||
1447 | } | ||
1448 | |||
1325 | static int nfs_compare_super(struct super_block *sb, void *data) | 1449 | static int nfs_compare_super(struct super_block *sb, void *data) |
1326 | { | 1450 | { |
1327 | struct nfs_sb_mountdata *sb_mntdata = data; | 1451 | struct nfs_sb_mountdata *sb_mntdata = data; |
1328 | struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb); | 1452 | struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb); |
1329 | int mntflags = sb_mntdata->mntflags; | 1453 | int mntflags = sb_mntdata->mntflags; |
1330 | 1454 | ||
1331 | if (memcmp(&old->nfs_client->cl_addr, | 1455 | if (!nfs_compare_super_address(old, server)) |
1332 | &server->nfs_client->cl_addr, | ||
1333 | sizeof(old->nfs_client->cl_addr)) != 0) | ||
1334 | return 0; | 1456 | return 0; |
1335 | /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */ | 1457 | /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */ |
1336 | if (old->flags & NFS_MOUNT_UNSHARED) | 1458 | if (old->flags & NFS_MOUNT_UNSHARED) |
@@ -1400,6 +1522,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1400 | 1522 | ||
1401 | out: | 1523 | out: |
1402 | kfree(data.nfs_server.hostname); | 1524 | kfree(data.nfs_server.hostname); |
1525 | kfree(data.mount_server.hostname); | ||
1403 | return error; | 1526 | return error; |
1404 | 1527 | ||
1405 | out_err_nosb: | 1528 | out_err_nosb: |
@@ -1528,12 +1651,35 @@ static void nfs4_fill_super(struct super_block *sb) | |||
1528 | } | 1651 | } |
1529 | 1652 | ||
1530 | /* | 1653 | /* |
1654 | * If the user didn't specify a port, set the port number to | ||
1655 | * the NFS version 4 default port. | ||
1656 | */ | ||
1657 | static void nfs4_default_port(struct sockaddr *sap) | ||
1658 | { | ||
1659 | switch (sap->sa_family) { | ||
1660 | case AF_INET: { | ||
1661 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
1662 | if (ap->sin_port == 0) | ||
1663 | ap->sin_port = htons(NFS_PORT); | ||
1664 | break; | ||
1665 | } | ||
1666 | case AF_INET6: { | ||
1667 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
1668 | if (ap->sin6_port == 0) | ||
1669 | ap->sin6_port = htons(NFS_PORT); | ||
1670 | break; | ||
1671 | } | ||
1672 | } | ||
1673 | } | ||
1674 | |||
1675 | /* | ||
1531 | * Validate NFSv4 mount options | 1676 | * Validate NFSv4 mount options |
1532 | */ | 1677 | */ |
1533 | static int nfs4_validate_mount_data(void *options, | 1678 | static int nfs4_validate_mount_data(void *options, |
1534 | struct nfs_parsed_mount_data *args, | 1679 | struct nfs_parsed_mount_data *args, |
1535 | const char *dev_name) | 1680 | const char *dev_name) |
1536 | { | 1681 | { |
1682 | struct sockaddr_in *ap; | ||
1537 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; | 1683 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1538 | char *c; | 1684 | char *c; |
1539 | 1685 | ||
@@ -1554,18 +1700,21 @@ static int nfs4_validate_mount_data(void *options, | |||
1554 | 1700 | ||
1555 | switch (data->version) { | 1701 | switch (data->version) { |
1556 | case 1: | 1702 | case 1: |
1557 | if (data->host_addrlen != sizeof(args->nfs_server.address)) | 1703 | ap = (struct sockaddr_in *)&args->nfs_server.address; |
1704 | if (data->host_addrlen > sizeof(args->nfs_server.address)) | ||
1558 | goto out_no_address; | 1705 | goto out_no_address; |
1559 | if (copy_from_user(&args->nfs_server.address, | 1706 | if (data->host_addrlen == 0) |
1560 | data->host_addr, | 1707 | goto out_no_address; |
1561 | sizeof(args->nfs_server.address))) | 1708 | args->nfs_server.addrlen = data->host_addrlen; |
1709 | if (copy_from_user(ap, data->host_addr, data->host_addrlen)) | ||
1562 | return -EFAULT; | 1710 | return -EFAULT; |
1563 | if (args->nfs_server.address.sin_port == 0) | ||
1564 | args->nfs_server.address.sin_port = htons(NFS_PORT); | ||
1565 | if (!nfs_verify_server_address((struct sockaddr *) | 1711 | if (!nfs_verify_server_address((struct sockaddr *) |
1566 | &args->nfs_server.address)) | 1712 | &args->nfs_server.address)) |
1567 | goto out_no_address; | 1713 | goto out_no_address; |
1568 | 1714 | ||
1715 | nfs4_default_port((struct sockaddr *) | ||
1716 | &args->nfs_server.address); | ||
1717 | |||
1569 | switch (data->auth_flavourlen) { | 1718 | switch (data->auth_flavourlen) { |
1570 | case 0: | 1719 | case 0: |
1571 | args->auth_flavors[0] = RPC_AUTH_UNIX; | 1720 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
@@ -1623,6 +1772,9 @@ static int nfs4_validate_mount_data(void *options, | |||
1623 | &args->nfs_server.address)) | 1772 | &args->nfs_server.address)) |
1624 | return -EINVAL; | 1773 | return -EINVAL; |
1625 | 1774 | ||
1775 | nfs4_default_port((struct sockaddr *) | ||
1776 | &args->nfs_server.address); | ||
1777 | |||
1626 | switch (args->auth_flavor_len) { | 1778 | switch (args->auth_flavor_len) { |
1627 | case 0: | 1779 | case 0: |
1628 | args->auth_flavors[0] = RPC_AUTH_UNIX; | 1780 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
@@ -1643,21 +1795,16 @@ static int nfs4_validate_mount_data(void *options, | |||
1643 | len = c - dev_name; | 1795 | len = c - dev_name; |
1644 | if (len > NFS4_MAXNAMLEN) | 1796 | if (len > NFS4_MAXNAMLEN) |
1645 | return -ENAMETOOLONG; | 1797 | return -ENAMETOOLONG; |
1646 | args->nfs_server.hostname = kzalloc(len, GFP_KERNEL); | 1798 | /* N.B. caller will free nfs_server.hostname in all cases */ |
1647 | if (args->nfs_server.hostname == NULL) | 1799 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); |
1648 | return -ENOMEM; | ||
1649 | strncpy(args->nfs_server.hostname, dev_name, len - 1); | ||
1650 | 1800 | ||
1651 | c++; /* step over the ':' */ | 1801 | c++; /* step over the ':' */ |
1652 | len = strlen(c); | 1802 | len = strlen(c); |
1653 | if (len > NFS4_MAXPATHLEN) | 1803 | if (len > NFS4_MAXPATHLEN) |
1654 | return -ENAMETOOLONG; | 1804 | return -ENAMETOOLONG; |
1655 | args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL); | 1805 | args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL); |
1656 | if (args->nfs_server.export_path == NULL) | ||
1657 | return -ENOMEM; | ||
1658 | strncpy(args->nfs_server.export_path, c, len); | ||
1659 | 1806 | ||
1660 | dprintk("MNTPATH: %s\n", args->nfs_server.export_path); | 1807 | dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path); |
1661 | 1808 | ||
1662 | if (args->client_address == NULL) | 1809 | if (args->client_address == NULL) |
1663 | goto out_no_client_address; | 1810 | goto out_no_client_address; |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 233ad38161f9..757415363422 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
16 | 16 | ||
17 | #include "internal.h" | ||
18 | |||
17 | struct nfs_unlinkdata { | 19 | struct nfs_unlinkdata { |
18 | struct hlist_node list; | 20 | struct hlist_node list; |
19 | struct nfs_removeargs args; | 21 | struct nfs_removeargs args; |
@@ -69,24 +71,6 @@ static void nfs_dec_sillycount(struct inode *dir) | |||
69 | } | 71 | } |
70 | 72 | ||
71 | /** | 73 | /** |
72 | * nfs_async_unlink_init - Initialize the RPC info | ||
73 | * task: rpc_task of the sillydelete | ||
74 | */ | ||
75 | static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) | ||
76 | { | ||
77 | struct nfs_unlinkdata *data = calldata; | ||
78 | struct inode *dir = data->dir; | ||
79 | struct rpc_message msg = { | ||
80 | .rpc_argp = &data->args, | ||
81 | .rpc_resp = &data->res, | ||
82 | .rpc_cred = data->cred, | ||
83 | }; | ||
84 | |||
85 | NFS_PROTO(dir)->unlink_setup(&msg, dir); | ||
86 | rpc_call_setup(task, &msg, 0); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * nfs_async_unlink_done - Sillydelete post-processing | 74 | * nfs_async_unlink_done - Sillydelete post-processing |
91 | * @task: rpc_task of the sillydelete | 75 | * @task: rpc_task of the sillydelete |
92 | * | 76 | * |
@@ -113,32 +97,45 @@ static void nfs_async_unlink_release(void *calldata) | |||
113 | struct nfs_unlinkdata *data = calldata; | 97 | struct nfs_unlinkdata *data = calldata; |
114 | 98 | ||
115 | nfs_dec_sillycount(data->dir); | 99 | nfs_dec_sillycount(data->dir); |
100 | nfs_sb_deactive(NFS_SERVER(data->dir)); | ||
116 | nfs_free_unlinkdata(data); | 101 | nfs_free_unlinkdata(data); |
117 | } | 102 | } |
118 | 103 | ||
119 | static const struct rpc_call_ops nfs_unlink_ops = { | 104 | static const struct rpc_call_ops nfs_unlink_ops = { |
120 | .rpc_call_prepare = nfs_async_unlink_init, | ||
121 | .rpc_call_done = nfs_async_unlink_done, | 105 | .rpc_call_done = nfs_async_unlink_done, |
122 | .rpc_release = nfs_async_unlink_release, | 106 | .rpc_release = nfs_async_unlink_release, |
123 | }; | 107 | }; |
124 | 108 | ||
125 | static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) | 109 | static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data) |
126 | { | 110 | { |
111 | struct rpc_message msg = { | ||
112 | .rpc_argp = &data->args, | ||
113 | .rpc_resp = &data->res, | ||
114 | .rpc_cred = data->cred, | ||
115 | }; | ||
116 | struct rpc_task_setup task_setup_data = { | ||
117 | .rpc_message = &msg, | ||
118 | .callback_ops = &nfs_unlink_ops, | ||
119 | .callback_data = data, | ||
120 | .flags = RPC_TASK_ASYNC, | ||
121 | }; | ||
127 | struct rpc_task *task; | 122 | struct rpc_task *task; |
128 | struct dentry *alias; | 123 | struct dentry *alias; |
129 | 124 | ||
130 | alias = d_lookup(parent, &data->args.name); | 125 | alias = d_lookup(parent, &data->args.name); |
131 | if (alias != NULL) { | 126 | if (alias != NULL) { |
132 | int ret = 0; | 127 | int ret = 0; |
128 | |||
133 | /* | 129 | /* |
134 | * Hey, we raced with lookup... See if we need to transfer | 130 | * Hey, we raced with lookup... See if we need to transfer |
135 | * the sillyrename information to the aliased dentry. | 131 | * the sillyrename information to the aliased dentry. |
136 | */ | 132 | */ |
137 | nfs_free_dname(data); | 133 | nfs_free_dname(data); |
138 | spin_lock(&alias->d_lock); | 134 | spin_lock(&alias->d_lock); |
139 | if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { | 135 | if (alias->d_inode != NULL && |
136 | !(alias->d_flags & DCACHE_NFSFS_RENAMED)) { | ||
140 | alias->d_fsdata = data; | 137 | alias->d_fsdata = data; |
141 | alias->d_flags ^= DCACHE_NFSFS_RENAMED; | 138 | alias->d_flags |= DCACHE_NFSFS_RENAMED; |
142 | ret = 1; | 139 | ret = 1; |
143 | } | 140 | } |
144 | spin_unlock(&alias->d_lock); | 141 | spin_unlock(&alias->d_lock); |
@@ -151,10 +148,14 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
151 | nfs_dec_sillycount(dir); | 148 | nfs_dec_sillycount(dir); |
152 | return 0; | 149 | return 0; |
153 | } | 150 | } |
151 | nfs_sb_active(NFS_SERVER(dir)); | ||
154 | data->args.fh = NFS_FH(dir); | 152 | data->args.fh = NFS_FH(dir); |
155 | nfs_fattr_init(&data->res.dir_attr); | 153 | nfs_fattr_init(&data->res.dir_attr); |
156 | 154 | ||
157 | task = rpc_run_task(NFS_CLIENT(dir), RPC_TASK_ASYNC, &nfs_unlink_ops, data); | 155 | NFS_PROTO(dir)->unlink_setup(&msg, dir); |
156 | |||
157 | task_setup_data.rpc_client = NFS_CLIENT(dir); | ||
158 | task = rpc_run_task(&task_setup_data); | ||
158 | if (!IS_ERR(task)) | 159 | if (!IS_ERR(task)) |
159 | rpc_put_task(task); | 160 | rpc_put_task(task); |
160 | return 1; | 161 | return 1; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 51cc1bd6a116..5ac5b27b639a 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -196,7 +196,7 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
196 | } | 196 | } |
197 | /* Update file length */ | 197 | /* Update file length */ |
198 | nfs_grow_file(page, offset, count); | 198 | nfs_grow_file(page, offset, count); |
199 | nfs_unlock_request(req); | 199 | nfs_clear_page_tag_locked(req); |
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
@@ -252,7 +252,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
252 | struct page *page) | 252 | struct page *page) |
253 | { | 253 | { |
254 | struct inode *inode = page->mapping->host; | 254 | struct inode *inode = page->mapping->host; |
255 | struct nfs_inode *nfsi = NFS_I(inode); | ||
256 | struct nfs_page *req; | 255 | struct nfs_page *req; |
257 | int ret; | 256 | int ret; |
258 | 257 | ||
@@ -263,10 +262,10 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
263 | spin_unlock(&inode->i_lock); | 262 | spin_unlock(&inode->i_lock); |
264 | return 0; | 263 | return 0; |
265 | } | 264 | } |
266 | if (nfs_lock_request_dontget(req)) | 265 | if (nfs_set_page_tag_locked(req)) |
267 | break; | 266 | break; |
268 | /* Note: If we hold the page lock, as is the case in nfs_writepage, | 267 | /* Note: If we hold the page lock, as is the case in nfs_writepage, |
269 | * then the call to nfs_lock_request_dontget() will always | 268 | * then the call to nfs_set_page_tag_locked() will always |
270 | * succeed provided that someone hasn't already marked the | 269 | * succeed provided that someone hasn't already marked the |
271 | * request as dirty (in which case we don't care). | 270 | * request as dirty (in which case we don't care). |
272 | */ | 271 | */ |
@@ -280,7 +279,7 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
280 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 279 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
281 | /* This request is marked for commit */ | 280 | /* This request is marked for commit */ |
282 | spin_unlock(&inode->i_lock); | 281 | spin_unlock(&inode->i_lock); |
283 | nfs_unlock_request(req); | 282 | nfs_clear_page_tag_locked(req); |
284 | nfs_pageio_complete(pgio); | 283 | nfs_pageio_complete(pgio); |
285 | return 0; | 284 | return 0; |
286 | } | 285 | } |
@@ -288,8 +287,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
288 | spin_unlock(&inode->i_lock); | 287 | spin_unlock(&inode->i_lock); |
289 | BUG(); | 288 | BUG(); |
290 | } | 289 | } |
291 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, | ||
292 | NFS_PAGE_TAG_LOCKED); | ||
293 | spin_unlock(&inode->i_lock); | 290 | spin_unlock(&inode->i_lock); |
294 | nfs_pageio_add_request(pgio, req); | 291 | nfs_pageio_add_request(pgio, req); |
295 | return 0; | 292 | return 0; |
@@ -381,6 +378,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
381 | set_page_private(req->wb_page, (unsigned long)req); | 378 | set_page_private(req->wb_page, (unsigned long)req); |
382 | nfsi->npages++; | 379 | nfsi->npages++; |
383 | kref_get(&req->wb_kref); | 380 | kref_get(&req->wb_kref); |
381 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | ||
384 | return 0; | 382 | return 0; |
385 | } | 383 | } |
386 | 384 | ||
@@ -596,7 +594,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
596 | spin_lock(&inode->i_lock); | 594 | spin_lock(&inode->i_lock); |
597 | req = nfs_page_find_request_locked(page); | 595 | req = nfs_page_find_request_locked(page); |
598 | if (req) { | 596 | if (req) { |
599 | if (!nfs_lock_request_dontget(req)) { | 597 | if (!nfs_set_page_tag_locked(req)) { |
600 | int error; | 598 | int error; |
601 | 599 | ||
602 | spin_unlock(&inode->i_lock); | 600 | spin_unlock(&inode->i_lock); |
@@ -646,7 +644,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
646 | || req->wb_page != page | 644 | || req->wb_page != page |
647 | || !nfs_dirty_request(req) | 645 | || !nfs_dirty_request(req) |
648 | || offset > rqend || end < req->wb_offset) { | 646 | || offset > rqend || end < req->wb_offset) { |
649 | nfs_unlock_request(req); | 647 | nfs_clear_page_tag_locked(req); |
650 | return ERR_PTR(-EBUSY); | 648 | return ERR_PTR(-EBUSY); |
651 | } | 649 | } |
652 | 650 | ||
@@ -755,7 +753,7 @@ static void nfs_writepage_release(struct nfs_page *req) | |||
755 | nfs_clear_page_tag_locked(req); | 753 | nfs_clear_page_tag_locked(req); |
756 | } | 754 | } |
757 | 755 | ||
758 | static inline int flush_task_priority(int how) | 756 | static int flush_task_priority(int how) |
759 | { | 757 | { |
760 | switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) { | 758 | switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) { |
761 | case FLUSH_HIGHPRI: | 759 | case FLUSH_HIGHPRI: |
@@ -775,15 +773,31 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
775 | unsigned int count, unsigned int offset, | 773 | unsigned int count, unsigned int offset, |
776 | int how) | 774 | int how) |
777 | { | 775 | { |
778 | struct inode *inode; | 776 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
779 | int flags; | 777 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
778 | int priority = flush_task_priority(how); | ||
779 | struct rpc_task *task; | ||
780 | struct rpc_message msg = { | ||
781 | .rpc_argp = &data->args, | ||
782 | .rpc_resp = &data->res, | ||
783 | .rpc_cred = req->wb_context->cred, | ||
784 | }; | ||
785 | struct rpc_task_setup task_setup_data = { | ||
786 | .rpc_client = NFS_CLIENT(inode), | ||
787 | .task = &data->task, | ||
788 | .rpc_message = &msg, | ||
789 | .callback_ops = call_ops, | ||
790 | .callback_data = data, | ||
791 | .flags = flags, | ||
792 | .priority = priority, | ||
793 | }; | ||
780 | 794 | ||
781 | /* Set up the RPC argument and reply structs | 795 | /* Set up the RPC argument and reply structs |
782 | * NB: take care not to mess about with data->commit et al. */ | 796 | * NB: take care not to mess about with data->commit et al. */ |
783 | 797 | ||
784 | data->req = req; | 798 | data->req = req; |
785 | data->inode = inode = req->wb_context->path.dentry->d_inode; | 799 | data->inode = inode = req->wb_context->path.dentry->d_inode; |
786 | data->cred = req->wb_context->cred; | 800 | data->cred = msg.rpc_cred; |
787 | 801 | ||
788 | data->args.fh = NFS_FH(inode); | 802 | data->args.fh = NFS_FH(inode); |
789 | data->args.offset = req_offset(req) + offset; | 803 | data->args.offset = req_offset(req) + offset; |
@@ -791,6 +805,12 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
791 | data->args.pages = data->pagevec; | 805 | data->args.pages = data->pagevec; |
792 | data->args.count = count; | 806 | data->args.count = count; |
793 | data->args.context = req->wb_context; | 807 | data->args.context = req->wb_context; |
808 | data->args.stable = NFS_UNSTABLE; | ||
809 | if (how & FLUSH_STABLE) { | ||
810 | data->args.stable = NFS_DATA_SYNC; | ||
811 | if (!NFS_I(inode)->ncommit) | ||
812 | data->args.stable = NFS_FILE_SYNC; | ||
813 | } | ||
794 | 814 | ||
795 | data->res.fattr = &data->fattr; | 815 | data->res.fattr = &data->fattr; |
796 | data->res.count = count; | 816 | data->res.count = count; |
@@ -798,12 +818,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
798 | nfs_fattr_init(&data->fattr); | 818 | nfs_fattr_init(&data->fattr); |
799 | 819 | ||
800 | /* Set up the initial task struct. */ | 820 | /* Set up the initial task struct. */ |
801 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 821 | NFS_PROTO(inode)->write_setup(data, &msg); |
802 | rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data); | ||
803 | NFS_PROTO(inode)->write_setup(data, how); | ||
804 | |||
805 | data->task.tk_priority = flush_task_priority(how); | ||
806 | data->task.tk_cookie = (unsigned long)inode; | ||
807 | 822 | ||
808 | dprintk("NFS: %5u initiated write call " | 823 | dprintk("NFS: %5u initiated write call " |
809 | "(req %s/%Ld, %u bytes @ offset %Lu)\n", | 824 | "(req %s/%Ld, %u bytes @ offset %Lu)\n", |
@@ -812,16 +827,10 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
812 | (long long)NFS_FILEID(inode), | 827 | (long long)NFS_FILEID(inode), |
813 | count, | 828 | count, |
814 | (unsigned long long)data->args.offset); | 829 | (unsigned long long)data->args.offset); |
815 | } | ||
816 | |||
817 | static void nfs_execute_write(struct nfs_write_data *data) | ||
818 | { | ||
819 | struct rpc_clnt *clnt = NFS_CLIENT(data->inode); | ||
820 | sigset_t oldset; | ||
821 | 830 | ||
822 | rpc_clnt_sigmask(clnt, &oldset); | 831 | task = rpc_run_task(&task_setup_data); |
823 | rpc_execute(&data->task); | 832 | if (!IS_ERR(task)) |
824 | rpc_clnt_sigunmask(clnt, &oldset); | 833 | rpc_put_task(task); |
825 | } | 834 | } |
826 | 835 | ||
827 | /* | 836 | /* |
@@ -868,7 +877,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned | |||
868 | wsize, offset, how); | 877 | wsize, offset, how); |
869 | offset += wsize; | 878 | offset += wsize; |
870 | nbytes -= wsize; | 879 | nbytes -= wsize; |
871 | nfs_execute_write(data); | ||
872 | } while (nbytes != 0); | 880 | } while (nbytes != 0); |
873 | 881 | ||
874 | return 0; | 882 | return 0; |
@@ -916,7 +924,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
916 | /* Set up the argument struct */ | 924 | /* Set up the argument struct */ |
917 | nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how); | 925 | nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how); |
918 | 926 | ||
919 | nfs_execute_write(data); | ||
920 | return 0; | 927 | return 0; |
921 | out_bad: | 928 | out_bad: |
922 | while (!list_empty(head)) { | 929 | while (!list_empty(head)) { |
@@ -932,7 +939,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
932 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 939 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
933 | struct inode *inode, int ioflags) | 940 | struct inode *inode, int ioflags) |
934 | { | 941 | { |
935 | int wsize = NFS_SERVER(inode)->wsize; | 942 | size_t wsize = NFS_SERVER(inode)->wsize; |
936 | 943 | ||
937 | if (wsize < PAGE_CACHE_SIZE) | 944 | if (wsize < PAGE_CACHE_SIZE) |
938 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); | 945 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); |
@@ -1146,19 +1153,33 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1146 | struct nfs_write_data *data, | 1153 | struct nfs_write_data *data, |
1147 | int how) | 1154 | int how) |
1148 | { | 1155 | { |
1149 | struct nfs_page *first; | 1156 | struct nfs_page *first = nfs_list_entry(head->next); |
1150 | struct inode *inode; | 1157 | struct inode *inode = first->wb_context->path.dentry->d_inode; |
1151 | int flags; | 1158 | int flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
1159 | int priority = flush_task_priority(how); | ||
1160 | struct rpc_task *task; | ||
1161 | struct rpc_message msg = { | ||
1162 | .rpc_argp = &data->args, | ||
1163 | .rpc_resp = &data->res, | ||
1164 | .rpc_cred = first->wb_context->cred, | ||
1165 | }; | ||
1166 | struct rpc_task_setup task_setup_data = { | ||
1167 | .task = &data->task, | ||
1168 | .rpc_client = NFS_CLIENT(inode), | ||
1169 | .rpc_message = &msg, | ||
1170 | .callback_ops = &nfs_commit_ops, | ||
1171 | .callback_data = data, | ||
1172 | .flags = flags, | ||
1173 | .priority = priority, | ||
1174 | }; | ||
1152 | 1175 | ||
1153 | /* Set up the RPC argument and reply structs | 1176 | /* Set up the RPC argument and reply structs |
1154 | * NB: take care not to mess about with data->commit et al. */ | 1177 | * NB: take care not to mess about with data->commit et al. */ |
1155 | 1178 | ||
1156 | list_splice_init(head, &data->pages); | 1179 | list_splice_init(head, &data->pages); |
1157 | first = nfs_list_entry(data->pages.next); | ||
1158 | inode = first->wb_context->path.dentry->d_inode; | ||
1159 | 1180 | ||
1160 | data->inode = inode; | 1181 | data->inode = inode; |
1161 | data->cred = first->wb_context->cred; | 1182 | data->cred = msg.rpc_cred; |
1162 | 1183 | ||
1163 | data->args.fh = NFS_FH(data->inode); | 1184 | data->args.fh = NFS_FH(data->inode); |
1164 | /* Note: we always request a commit of the entire inode */ | 1185 | /* Note: we always request a commit of the entire inode */ |
@@ -1170,14 +1191,13 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1170 | nfs_fattr_init(&data->fattr); | 1191 | nfs_fattr_init(&data->fattr); |
1171 | 1192 | ||
1172 | /* Set up the initial task struct. */ | 1193 | /* Set up the initial task struct. */ |
1173 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 1194 | NFS_PROTO(inode)->commit_setup(data, &msg); |
1174 | rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data); | ||
1175 | NFS_PROTO(inode)->commit_setup(data, how); | ||
1176 | 1195 | ||
1177 | data->task.tk_priority = flush_task_priority(how); | ||
1178 | data->task.tk_cookie = (unsigned long)inode; | ||
1179 | |||
1180 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 1196 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
1197 | |||
1198 | task = rpc_run_task(&task_setup_data); | ||
1199 | if (!IS_ERR(task)) | ||
1200 | rpc_put_task(task); | ||
1181 | } | 1201 | } |
1182 | 1202 | ||
1183 | /* | 1203 | /* |
@@ -1197,7 +1217,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1197 | /* Set up the argument struct */ | 1217 | /* Set up the argument struct */ |
1198 | nfs_commit_rpcsetup(head, data, how); | 1218 | nfs_commit_rpcsetup(head, data, how); |
1199 | 1219 | ||
1200 | nfs_execute_write(data); | ||
1201 | return 0; | 1220 | return 0; |
1202 | out_bad: | 1221 | out_bad: |
1203 | while (!list_empty(head)) { | 1222 | while (!list_empty(head)) { |
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 6f1637c61e10..3d25bcd139d1 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h | |||
@@ -33,9 +33,26 @@ struct nlmsvc_binding { | |||
33 | extern struct nlmsvc_binding * nlmsvc_ops; | 33 | extern struct nlmsvc_binding * nlmsvc_ops; |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Similar to nfs_client_initdata, but without the NFS-specific | ||
37 | * rpc_ops field. | ||
38 | */ | ||
39 | struct nlmclnt_initdata { | ||
40 | const char *hostname; | ||
41 | const struct sockaddr *address; | ||
42 | size_t addrlen; | ||
43 | unsigned short protocol; | ||
44 | u32 nfs_version; | ||
45 | }; | ||
46 | |||
47 | /* | ||
36 | * Functions exported by the lockd module | 48 | * Functions exported by the lockd module |
37 | */ | 49 | */ |
38 | extern int nlmclnt_proc(struct inode *, int, struct file_lock *); | 50 | |
51 | extern struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init); | ||
52 | extern void nlmclnt_done(struct nlm_host *host); | ||
53 | |||
54 | extern int nlmclnt_proc(struct nlm_host *host, int cmd, | ||
55 | struct file_lock *fl); | ||
39 | extern int lockd_up(int proto); | 56 | extern int lockd_up(int proto); |
40 | extern void lockd_down(void); | 57 | extern void lockd_down(void); |
41 | 58 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 2d15d4aac094..099ddb4481c0 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -196,28 +196,67 @@ struct nfs_inode { | |||
196 | #define NFS_INO_STALE (2) /* possible stale inode */ | 196 | #define NFS_INO_STALE (2) /* possible stale inode */ |
197 | #define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ | 197 | #define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ |
198 | 198 | ||
199 | static inline struct nfs_inode *NFS_I(struct inode *inode) | 199 | static inline struct nfs_inode *NFS_I(const struct inode *inode) |
200 | { | 200 | { |
201 | return container_of(inode, struct nfs_inode, vfs_inode); | 201 | return container_of(inode, struct nfs_inode, vfs_inode); |
202 | } | 202 | } |
203 | #define NFS_SB(s) ((struct nfs_server *)(s->s_fs_info)) | ||
204 | 203 | ||
205 | #define NFS_FH(inode) (&NFS_I(inode)->fh) | 204 | static inline struct nfs_server *NFS_SB(const struct super_block *s) |
206 | #define NFS_SERVER(inode) (NFS_SB(inode->i_sb)) | 205 | { |
207 | #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) | 206 | return (struct nfs_server *)(s->s_fs_info); |
208 | #define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) | 207 | } |
209 | #define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) | 208 | |
210 | #define NFS_MINATTRTIMEO(inode) \ | 209 | static inline struct nfs_fh *NFS_FH(const struct inode *inode) |
211 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmin \ | 210 | { |
212 | : NFS_SERVER(inode)->acregmin) | 211 | return &NFS_I(inode)->fh; |
213 | #define NFS_MAXATTRTIMEO(inode) \ | 212 | } |
214 | (S_ISDIR(inode->i_mode)? NFS_SERVER(inode)->acdirmax \ | 213 | |
215 | : NFS_SERVER(inode)->acregmax) | 214 | static inline struct nfs_server *NFS_SERVER(const struct inode *inode) |
215 | { | ||
216 | return NFS_SB(inode->i_sb); | ||
217 | } | ||
218 | |||
219 | static inline struct rpc_clnt *NFS_CLIENT(const struct inode *inode) | ||
220 | { | ||
221 | return NFS_SERVER(inode)->client; | ||
222 | } | ||
223 | |||
224 | static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) | ||
225 | { | ||
226 | return NFS_SERVER(inode)->nfs_client->rpc_ops; | ||
227 | } | ||
228 | |||
229 | static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) | ||
230 | { | ||
231 | return NFS_I(inode)->cookieverf; | ||
232 | } | ||
233 | |||
234 | static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) | ||
235 | { | ||
236 | struct nfs_server *nfss = NFS_SERVER(inode); | ||
237 | return S_ISDIR(inode->i_mode) ? nfss->acdirmin : nfss->acregmin; | ||
238 | } | ||
216 | 239 | ||
217 | #define NFS_FLAGS(inode) (NFS_I(inode)->flags) | 240 | static inline unsigned NFS_MAXATTRTIMEO(const struct inode *inode) |
218 | #define NFS_STALE(inode) (test_bit(NFS_INO_STALE, &NFS_FLAGS(inode))) | 241 | { |
242 | struct nfs_server *nfss = NFS_SERVER(inode); | ||
243 | return S_ISDIR(inode->i_mode) ? nfss->acdirmax : nfss->acregmax; | ||
244 | } | ||
219 | 245 | ||
220 | #define NFS_FILEID(inode) (NFS_I(inode)->fileid) | 246 | static inline int NFS_STALE(const struct inode *inode) |
247 | { | ||
248 | return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags); | ||
249 | } | ||
250 | |||
251 | static inline __u64 NFS_FILEID(const struct inode *inode) | ||
252 | { | ||
253 | return NFS_I(inode)->fileid; | ||
254 | } | ||
255 | |||
256 | static inline void set_nfs_fileid(struct inode *inode, __u64 fileid) | ||
257 | { | ||
258 | NFS_I(inode)->fileid = fileid; | ||
259 | } | ||
221 | 260 | ||
222 | static inline void nfs_mark_for_revalidate(struct inode *inode) | 261 | static inline void nfs_mark_for_revalidate(struct inode *inode) |
223 | { | 262 | { |
@@ -237,7 +276,7 @@ static inline int nfs_server_capable(struct inode *inode, int cap) | |||
237 | 276 | ||
238 | static inline int NFS_USE_READDIRPLUS(struct inode *inode) | 277 | static inline int NFS_USE_READDIRPLUS(struct inode *inode) |
239 | { | 278 | { |
240 | return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 279 | return test_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
241 | } | 280 | } |
242 | 281 | ||
243 | static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | 282 | static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) |
@@ -366,6 +405,7 @@ extern const struct inode_operations nfs3_dir_inode_operations; | |||
366 | extern const struct file_operations nfs_dir_operations; | 405 | extern const struct file_operations nfs_dir_operations; |
367 | extern struct dentry_operations nfs_dentry_operations; | 406 | extern struct dentry_operations nfs_dentry_operations; |
368 | 407 | ||
408 | extern void nfs_force_lookup_revalidate(struct inode *dir); | ||
369 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); | 409 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); |
370 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); | 410 | extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags); |
371 | extern void nfs_access_zap_cache(struct inode *inode); | 411 | extern void nfs_access_zap_cache(struct inode *inode); |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 0cac49bc0955..3423c6761bf7 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -3,8 +3,12 @@ | |||
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/backing-dev.h> | 5 | #include <linux/backing-dev.h> |
6 | #include <linux/wait.h> | ||
7 | |||
8 | #include <asm/atomic.h> | ||
6 | 9 | ||
7 | struct nfs_iostats; | 10 | struct nfs_iostats; |
11 | struct nlm_host; | ||
8 | 12 | ||
9 | /* | 13 | /* |
10 | * The nfs_client identifies our client state to the server. | 14 | * The nfs_client identifies our client state to the server. |
@@ -14,20 +18,19 @@ struct nfs_client { | |||
14 | int cl_cons_state; /* current construction state (-ve: init error) */ | 18 | int cl_cons_state; /* current construction state (-ve: init error) */ |
15 | #define NFS_CS_READY 0 /* ready to be used */ | 19 | #define NFS_CS_READY 0 /* ready to be used */ |
16 | #define NFS_CS_INITING 1 /* busy initialising */ | 20 | #define NFS_CS_INITING 1 /* busy initialising */ |
17 | int cl_nfsversion; /* NFS protocol version */ | ||
18 | unsigned long cl_res_state; /* NFS resources state */ | 21 | unsigned long cl_res_state; /* NFS resources state */ |
19 | #define NFS_CS_CALLBACK 1 /* - callback started */ | 22 | #define NFS_CS_CALLBACK 1 /* - callback started */ |
20 | #define NFS_CS_IDMAP 2 /* - idmap started */ | 23 | #define NFS_CS_IDMAP 2 /* - idmap started */ |
21 | #define NFS_CS_RENEWD 3 /* - renewd started */ | 24 | #define NFS_CS_RENEWD 3 /* - renewd started */ |
22 | struct sockaddr_in cl_addr; /* server identifier */ | 25 | struct sockaddr_storage cl_addr; /* server identifier */ |
26 | size_t cl_addrlen; | ||
23 | char * cl_hostname; /* hostname of server */ | 27 | char * cl_hostname; /* hostname of server */ |
24 | struct list_head cl_share_link; /* link in global client list */ | 28 | struct list_head cl_share_link; /* link in global client list */ |
25 | struct list_head cl_superblocks; /* List of nfs_server structs */ | 29 | struct list_head cl_superblocks; /* List of nfs_server structs */ |
26 | 30 | ||
27 | struct rpc_clnt * cl_rpcclient; | 31 | struct rpc_clnt * cl_rpcclient; |
28 | const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ | 32 | const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ |
29 | unsigned long retrans_timeo; /* retransmit timeout */ | 33 | int cl_proto; /* Network transport protocol */ |
30 | unsigned int retrans_count; /* number of retransmit tries */ | ||
31 | 34 | ||
32 | #ifdef CONFIG_NFS_V4 | 35 | #ifdef CONFIG_NFS_V4 |
33 | u64 cl_clientid; /* constant */ | 36 | u64 cl_clientid; /* constant */ |
@@ -62,7 +65,7 @@ struct nfs_client { | |||
62 | /* Our own IP address, as a null-terminated string. | 65 | /* Our own IP address, as a null-terminated string. |
63 | * This is used to generate the clientid, and the callback address. | 66 | * This is used to generate the clientid, and the callback address. |
64 | */ | 67 | */ |
65 | char cl_ipaddr[16]; | 68 | char cl_ipaddr[48]; |
66 | unsigned char cl_id_uniquifier; | 69 | unsigned char cl_id_uniquifier; |
67 | #endif | 70 | #endif |
68 | }; | 71 | }; |
@@ -78,6 +81,7 @@ struct nfs_server { | |||
78 | struct list_head master_link; /* link in master servers list */ | 81 | struct list_head master_link; /* link in master servers list */ |
79 | struct rpc_clnt * client; /* RPC client handle */ | 82 | struct rpc_clnt * client; /* RPC client handle */ |
80 | struct rpc_clnt * client_acl; /* ACL RPC client handle */ | 83 | struct rpc_clnt * client_acl; /* ACL RPC client handle */ |
84 | struct nlm_host *nlm_host; /* NLM client handle */ | ||
81 | struct nfs_iostats * io_stats; /* I/O statistics */ | 85 | struct nfs_iostats * io_stats; /* I/O statistics */ |
82 | struct backing_dev_info backing_dev_info; | 86 | struct backing_dev_info backing_dev_info; |
83 | atomic_long_t writeback; /* number of writeback pages */ | 87 | atomic_long_t writeback; /* number of writeback pages */ |
@@ -110,6 +114,9 @@ struct nfs_server { | |||
110 | filesystem */ | 114 | filesystem */ |
111 | #endif | 115 | #endif |
112 | void (*destroy)(struct nfs_server *); | 116 | void (*destroy)(struct nfs_server *); |
117 | |||
118 | atomic_t active; /* Keep trace of any activity to this server */ | ||
119 | wait_queue_head_t active_wq; /* Wait for any activity to stop */ | ||
113 | }; | 120 | }; |
114 | 121 | ||
115 | /* Server capabilities */ | 122 | /* Server capabilities */ |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 30dbcc185e69..a1676e19e491 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -83,6 +83,7 @@ extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); | |||
83 | extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t); | 83 | extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t); |
84 | extern int nfs_wait_on_request(struct nfs_page *); | 84 | extern int nfs_wait_on_request(struct nfs_page *); |
85 | extern void nfs_unlock_request(struct nfs_page *req); | 85 | extern void nfs_unlock_request(struct nfs_page *req); |
86 | extern int nfs_set_page_tag_locked(struct nfs_page *req); | ||
86 | extern void nfs_clear_page_tag_locked(struct nfs_page *req); | 87 | extern void nfs_clear_page_tag_locked(struct nfs_page *req); |
87 | 88 | ||
88 | 89 | ||
@@ -95,18 +96,6 @@ nfs_lock_request_dontget(struct nfs_page *req) | |||
95 | return !test_and_set_bit(PG_BUSY, &req->wb_flags); | 96 | return !test_and_set_bit(PG_BUSY, &req->wb_flags); |
96 | } | 97 | } |
97 | 98 | ||
98 | /* | ||
99 | * Lock the page of an asynchronous request and take a reference | ||
100 | */ | ||
101 | static inline int | ||
102 | nfs_lock_request(struct nfs_page *req) | ||
103 | { | ||
104 | if (test_and_set_bit(PG_BUSY, &req->wb_flags)) | ||
105 | return 0; | ||
106 | kref_get(&req->wb_kref); | ||
107 | return 1; | ||
108 | } | ||
109 | |||
110 | /** | 99 | /** |
111 | * nfs_list_add_request - Insert a request into a list | 100 | * nfs_list_add_request - Insert a request into a list |
112 | * @req: request | 101 | * @req: request |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index daab252f2e5c..f301d0b8babc 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -666,16 +666,17 @@ struct nfs4_rename_res { | |||
666 | struct nfs_fattr * new_fattr; | 666 | struct nfs_fattr * new_fattr; |
667 | }; | 667 | }; |
668 | 668 | ||
669 | #define NFS4_SETCLIENTID_NAMELEN (56) | ||
669 | struct nfs4_setclientid { | 670 | struct nfs4_setclientid { |
670 | const nfs4_verifier * sc_verifier; /* request */ | 671 | const nfs4_verifier * sc_verifier; |
671 | unsigned int sc_name_len; | 672 | unsigned int sc_name_len; |
672 | char sc_name[48]; /* request */ | 673 | char sc_name[NFS4_SETCLIENTID_NAMELEN]; |
673 | u32 sc_prog; /* request */ | 674 | u32 sc_prog; |
674 | unsigned int sc_netid_len; | 675 | unsigned int sc_netid_len; |
675 | char sc_netid[4]; /* request */ | 676 | char sc_netid[RPCBIND_MAXNETIDLEN]; |
676 | unsigned int sc_uaddr_len; | 677 | unsigned int sc_uaddr_len; |
677 | char sc_uaddr[24]; /* request */ | 678 | char sc_uaddr[RPCBIND_MAXUADDRLEN]; |
678 | u32 sc_cb_ident; /* request */ | 679 | u32 sc_cb_ident; |
679 | }; | 680 | }; |
680 | 681 | ||
681 | struct nfs4_statfs_arg { | 682 | struct nfs4_statfs_arg { |
@@ -773,7 +774,7 @@ struct nfs_access_entry; | |||
773 | * RPC procedure vector for NFSv2/NFSv3 demuxing | 774 | * RPC procedure vector for NFSv2/NFSv3 demuxing |
774 | */ | 775 | */ |
775 | struct nfs_rpc_ops { | 776 | struct nfs_rpc_ops { |
776 | int version; /* Protocol version */ | 777 | u32 version; /* Protocol version */ |
777 | struct dentry_operations *dentry_ops; | 778 | struct dentry_operations *dentry_ops; |
778 | const struct inode_operations *dir_inode_ops; | 779 | const struct inode_operations *dir_inode_ops; |
779 | const struct inode_operations *file_inode_ops; | 780 | const struct inode_operations *file_inode_ops; |
@@ -816,11 +817,11 @@ struct nfs_rpc_ops { | |||
816 | struct nfs_pathconf *); | 817 | struct nfs_pathconf *); |
817 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); | 818 | int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); |
818 | __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus); | 819 | __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus); |
819 | void (*read_setup) (struct nfs_read_data *); | 820 | void (*read_setup) (struct nfs_read_data *, struct rpc_message *); |
820 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); | 821 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); |
821 | void (*write_setup) (struct nfs_write_data *, int how); | 822 | void (*write_setup) (struct nfs_write_data *, struct rpc_message *); |
822 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); | 823 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); |
823 | void (*commit_setup) (struct nfs_write_data *, int how); | 824 | void (*commit_setup) (struct nfs_write_data *, struct rpc_message *); |
824 | int (*commit_done) (struct rpc_task *, struct nfs_write_data *); | 825 | int (*commit_done) (struct rpc_task *, struct nfs_write_data *); |
825 | int (*file_open) (struct inode *, struct file *); | 826 | int (*file_open) (struct inode *, struct file *); |
826 | int (*file_release) (struct inode *, struct file *); | 827 | int (*file_release) (struct inode *, struct file *); |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index d9d5c5ad826c..3e9addc741c1 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -46,6 +46,7 @@ struct rpc_clnt { | |||
46 | cl_autobind : 1;/* use getport() */ | 46 | cl_autobind : 1;/* use getport() */ |
47 | 47 | ||
48 | struct rpc_rtt * cl_rtt; /* RTO estimator data */ | 48 | struct rpc_rtt * cl_rtt; /* RTO estimator data */ |
49 | const struct rpc_timeout *cl_timeout; /* Timeout strategy */ | ||
49 | 50 | ||
50 | int cl_nodelen; /* nodename length */ | 51 | int cl_nodelen; /* nodename length */ |
51 | char cl_nodename[UNX_MAXNODENAME]; | 52 | char cl_nodename[UNX_MAXNODENAME]; |
@@ -54,6 +55,7 @@ struct rpc_clnt { | |||
54 | struct dentry * cl_dentry; /* inode */ | 55 | struct dentry * cl_dentry; /* inode */ |
55 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ | 56 | struct rpc_clnt * cl_parent; /* Points to parent of clones */ |
56 | struct rpc_rtt cl_rtt_default; | 57 | struct rpc_rtt cl_rtt_default; |
58 | struct rpc_timeout cl_timeout_default; | ||
57 | struct rpc_program * cl_program; | 59 | struct rpc_program * cl_program; |
58 | char cl_inline_name[32]; | 60 | char cl_inline_name[32]; |
59 | }; | 61 | }; |
@@ -99,7 +101,7 @@ struct rpc_create_args { | |||
99 | struct sockaddr *address; | 101 | struct sockaddr *address; |
100 | size_t addrsize; | 102 | size_t addrsize; |
101 | struct sockaddr *saddress; | 103 | struct sockaddr *saddress; |
102 | struct rpc_timeout *timeout; | 104 | const struct rpc_timeout *timeout; |
103 | char *servername; | 105 | char *servername; |
104 | struct rpc_program *program; | 106 | struct rpc_program *program; |
105 | u32 version; | 107 | u32 version; |
@@ -123,11 +125,10 @@ void rpc_shutdown_client(struct rpc_clnt *); | |||
123 | void rpc_release_client(struct rpc_clnt *); | 125 | void rpc_release_client(struct rpc_clnt *); |
124 | 126 | ||
125 | int rpcb_register(u32, u32, int, unsigned short, int *); | 127 | int rpcb_register(u32, u32, int, unsigned short, int *); |
126 | int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int); | 128 | int rpcb_getport_sync(struct sockaddr_in *, u32, u32, int); |
127 | void rpcb_getport_async(struct rpc_task *); | 129 | void rpcb_getport_async(struct rpc_task *); |
128 | 130 | ||
129 | void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); | 131 | void rpc_call_start(struct rpc_task *); |
130 | |||
131 | int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, | 132 | int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, |
132 | int flags, const struct rpc_call_ops *tk_ops, | 133 | int flags, const struct rpc_call_ops *tk_ops, |
133 | void *calldata); | 134 | void *calldata); |
@@ -142,7 +143,7 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); | |||
142 | size_t rpc_max_payload(struct rpc_clnt *); | 143 | size_t rpc_max_payload(struct rpc_clnt *); |
143 | void rpc_force_rebind(struct rpc_clnt *); | 144 | void rpc_force_rebind(struct rpc_clnt *); |
144 | size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); | 145 | size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); |
145 | char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); | 146 | const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); |
146 | 147 | ||
147 | #endif /* __KERNEL__ */ | 148 | #endif /* __KERNEL__ */ |
148 | #endif /* _LINUX_SUNRPC_CLNT_H */ | 149 | #endif /* _LINUX_SUNRPC_CLNT_H */ |
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h index c4beb5775111..70df4f1d8847 100644 --- a/include/linux/sunrpc/msg_prot.h +++ b/include/linux/sunrpc/msg_prot.h | |||
@@ -152,5 +152,44 @@ typedef __be32 rpc_fraghdr; | |||
152 | */ | 152 | */ |
153 | #define RPCBIND_MAXNETIDLEN (4u) | 153 | #define RPCBIND_MAXNETIDLEN (4u) |
154 | 154 | ||
155 | /* | ||
156 | * Universal addresses are introduced in RFC 1833 and further spelled | ||
157 | * out in RFC 3530. RPCBIND_MAXUADDRLEN defines a maximum byte length | ||
158 | * of a universal address for use in allocating buffers and character | ||
159 | * arrays. | ||
160 | * | ||
161 | * Quoting RFC 3530, section 2.2: | ||
162 | * | ||
163 | * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the | ||
164 | * US-ASCII string: | ||
165 | * | ||
166 | * h1.h2.h3.h4.p1.p2 | ||
167 | * | ||
168 | * The prefix, "h1.h2.h3.h4", is the standard textual form for | ||
169 | * representing an IPv4 address, which is always four octets long. | ||
170 | * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively, | ||
171 | * the first through fourth octets each converted to ASCII-decimal. | ||
172 | * Assuming big-endian ordering, p1 and p2 are, respectively, the first | ||
173 | * and second octets each converted to ASCII-decimal. For example, if a | ||
174 | * host, in big-endian order, has an address of 0x0A010307 and there is | ||
175 | * a service listening on, in big endian order, port 0x020F (decimal | ||
176 | * 527), then the complete universal address is "10.1.3.7.2.15". | ||
177 | * | ||
178 | * ... | ||
179 | * | ||
180 | * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the | ||
181 | * US-ASCII string: | ||
182 | * | ||
183 | * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2 | ||
184 | * | ||
185 | * The suffix "p1.p2" is the service port, and is computed the same way | ||
186 | * as with universal addresses for TCP and UDP over IPv4. The prefix, | ||
187 | * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for | ||
188 | * representing an IPv6 address as defined in Section 2.2 of [RFC2373]. | ||
189 | * Additionally, the two alternative forms specified in Section 2.2 of | ||
190 | * [RFC2373] are also acceptable. | ||
191 | */ | ||
192 | #define RPCBIND_MAXUADDRLEN (56u) | ||
193 | |||
155 | #endif /* __KERNEL__ */ | 194 | #endif /* __KERNEL__ */ |
156 | #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ | 195 | #endif /* _LINUX_SUNRPC_MSGPROT_H_ */ |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 8ea077db0099..ce3d1b132729 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -56,8 +56,6 @@ struct rpc_task { | |||
56 | __u8 tk_garb_retry; | 56 | __u8 tk_garb_retry; |
57 | __u8 tk_cred_retry; | 57 | __u8 tk_cred_retry; |
58 | 58 | ||
59 | unsigned long tk_cookie; /* Cookie for batching tasks */ | ||
60 | |||
61 | /* | 59 | /* |
62 | * timeout_fn to be executed by timer bottom half | 60 | * timeout_fn to be executed by timer bottom half |
63 | * callback to be executed after waking up | 61 | * callback to be executed after waking up |
@@ -78,7 +76,6 @@ struct rpc_task { | |||
78 | struct timer_list tk_timer; /* kernel timer */ | 76 | struct timer_list tk_timer; /* kernel timer */ |
79 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ | 77 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ |
80 | unsigned short tk_flags; /* misc flags */ | 78 | unsigned short tk_flags; /* misc flags */ |
81 | unsigned char tk_priority : 2;/* Task priority */ | ||
82 | unsigned long tk_runstate; /* Task run status */ | 79 | unsigned long tk_runstate; /* Task run status */ |
83 | struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could | 80 | struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could |
84 | * be any workqueue | 81 | * be any workqueue |
@@ -94,6 +91,9 @@ struct rpc_task { | |||
94 | unsigned long tk_start; /* RPC task init timestamp */ | 91 | unsigned long tk_start; /* RPC task init timestamp */ |
95 | long tk_rtt; /* round-trip time (jiffies) */ | 92 | long tk_rtt; /* round-trip time (jiffies) */ |
96 | 93 | ||
94 | pid_t tk_owner; /* Process id for batching tasks */ | ||
95 | unsigned char tk_priority : 2;/* Task priority */ | ||
96 | |||
97 | #ifdef RPC_DEBUG | 97 | #ifdef RPC_DEBUG |
98 | unsigned short tk_pid; /* debugging aid */ | 98 | unsigned short tk_pid; /* debugging aid */ |
99 | #endif | 99 | #endif |
@@ -117,6 +117,15 @@ struct rpc_call_ops { | |||
117 | void (*rpc_release)(void *); | 117 | void (*rpc_release)(void *); |
118 | }; | 118 | }; |
119 | 119 | ||
120 | struct rpc_task_setup { | ||
121 | struct rpc_task *task; | ||
122 | struct rpc_clnt *rpc_client; | ||
123 | const struct rpc_message *rpc_message; | ||
124 | const struct rpc_call_ops *callback_ops; | ||
125 | void *callback_data; | ||
126 | unsigned short flags; | ||
127 | signed char priority; | ||
128 | }; | ||
120 | 129 | ||
121 | /* | 130 | /* |
122 | * RPC task flags | 131 | * RPC task flags |
@@ -180,10 +189,10 @@ struct rpc_call_ops { | |||
180 | * Note: if you change these, you must also change | 189 | * Note: if you change these, you must also change |
181 | * the task initialization definitions below. | 190 | * the task initialization definitions below. |
182 | */ | 191 | */ |
183 | #define RPC_PRIORITY_LOW 0 | 192 | #define RPC_PRIORITY_LOW (-1) |
184 | #define RPC_PRIORITY_NORMAL 1 | 193 | #define RPC_PRIORITY_NORMAL (0) |
185 | #define RPC_PRIORITY_HIGH 2 | 194 | #define RPC_PRIORITY_HIGH (1) |
186 | #define RPC_NR_PRIORITY (RPC_PRIORITY_HIGH+1) | 195 | #define RPC_NR_PRIORITY (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW) |
187 | 196 | ||
188 | /* | 197 | /* |
189 | * RPC synchronization objects | 198 | * RPC synchronization objects |
@@ -191,7 +200,7 @@ struct rpc_call_ops { | |||
191 | struct rpc_wait_queue { | 200 | struct rpc_wait_queue { |
192 | spinlock_t lock; | 201 | spinlock_t lock; |
193 | struct list_head tasks[RPC_NR_PRIORITY]; /* task queue for each priority level */ | 202 | struct list_head tasks[RPC_NR_PRIORITY]; /* task queue for each priority level */ |
194 | unsigned long cookie; /* cookie of last task serviced */ | 203 | pid_t owner; /* process id of last task serviced */ |
195 | unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ | 204 | unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */ |
196 | unsigned char priority; /* current priority */ | 205 | unsigned char priority; /* current priority */ |
197 | unsigned char count; /* # task groups remaining serviced so far */ | 206 | unsigned char count; /* # task groups remaining serviced so far */ |
@@ -208,41 +217,13 @@ struct rpc_wait_queue { | |||
208 | * performance of NFS operations such as read/write. | 217 | * performance of NFS operations such as read/write. |
209 | */ | 218 | */ |
210 | #define RPC_BATCH_COUNT 16 | 219 | #define RPC_BATCH_COUNT 16 |
211 | |||
212 | #ifndef RPC_DEBUG | ||
213 | # define RPC_WAITQ_INIT(var,qname) { \ | ||
214 | .lock = __SPIN_LOCK_UNLOCKED(var.lock), \ | ||
215 | .tasks = { \ | ||
216 | [0] = LIST_HEAD_INIT(var.tasks[0]), \ | ||
217 | [1] = LIST_HEAD_INIT(var.tasks[1]), \ | ||
218 | [2] = LIST_HEAD_INIT(var.tasks[2]), \ | ||
219 | }, \ | ||
220 | } | ||
221 | #else | ||
222 | # define RPC_WAITQ_INIT(var,qname) { \ | ||
223 | .lock = __SPIN_LOCK_UNLOCKED(var.lock), \ | ||
224 | .tasks = { \ | ||
225 | [0] = LIST_HEAD_INIT(var.tasks[0]), \ | ||
226 | [1] = LIST_HEAD_INIT(var.tasks[1]), \ | ||
227 | [2] = LIST_HEAD_INIT(var.tasks[2]), \ | ||
228 | }, \ | ||
229 | .name = qname, \ | ||
230 | } | ||
231 | #endif | ||
232 | # define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname) | ||
233 | |||
234 | #define RPC_IS_PRIORITY(q) ((q)->maxpriority > 0) | 220 | #define RPC_IS_PRIORITY(q) ((q)->maxpriority > 0) |
235 | 221 | ||
236 | /* | 222 | /* |
237 | * Function prototypes | 223 | * Function prototypes |
238 | */ | 224 | */ |
239 | struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, | 225 | struct rpc_task *rpc_new_task(const struct rpc_task_setup *); |
240 | const struct rpc_call_ops *ops, void *data); | 226 | struct rpc_task *rpc_run_task(const struct rpc_task_setup *); |
241 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
242 | const struct rpc_call_ops *ops, void *data); | ||
243 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, | ||
244 | int flags, const struct rpc_call_ops *ops, | ||
245 | void *data); | ||
246 | void rpc_put_task(struct rpc_task *); | 227 | void rpc_put_task(struct rpc_task *); |
247 | void rpc_exit_task(struct rpc_task *); | 228 | void rpc_exit_task(struct rpc_task *); |
248 | void rpc_release_calldata(const struct rpc_call_ops *, void *); | 229 | void rpc_release_calldata(const struct rpc_call_ops *, void *); |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 30b17b3bc1a9..b3ff9a815e6f 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -120,7 +120,7 @@ struct rpc_xprt { | |||
120 | struct kref kref; /* Reference count */ | 120 | struct kref kref; /* Reference count */ |
121 | struct rpc_xprt_ops * ops; /* transport methods */ | 121 | struct rpc_xprt_ops * ops; /* transport methods */ |
122 | 122 | ||
123 | struct rpc_timeout timeout; /* timeout parms */ | 123 | const struct rpc_timeout *timeout; /* timeout parms */ |
124 | struct sockaddr_storage addr; /* server address */ | 124 | struct sockaddr_storage addr; /* server address */ |
125 | size_t addrlen; /* size of server address */ | 125 | size_t addrlen; /* size of server address */ |
126 | int prot; /* IP protocol */ | 126 | int prot; /* IP protocol */ |
@@ -183,7 +183,7 @@ struct rpc_xprt { | |||
183 | bklog_u; /* backlog queue utilization */ | 183 | bklog_u; /* backlog queue utilization */ |
184 | } stat; | 184 | } stat; |
185 | 185 | ||
186 | char * address_strings[RPC_DISPLAY_MAX]; | 186 | const char *address_strings[RPC_DISPLAY_MAX]; |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct xprt_create { | 189 | struct xprt_create { |
@@ -191,7 +191,6 @@ struct xprt_create { | |||
191 | struct sockaddr * srcaddr; /* optional local address */ | 191 | struct sockaddr * srcaddr; /* optional local address */ |
192 | struct sockaddr * dstaddr; /* remote peer address */ | 192 | struct sockaddr * dstaddr; /* remote peer address */ |
193 | size_t addrlen; | 193 | size_t addrlen; |
194 | struct rpc_timeout * timeout; /* optional timeout parameters */ | ||
195 | }; | 194 | }; |
196 | 195 | ||
197 | struct xprt_class { | 196 | struct xprt_class { |
@@ -203,11 +202,6 @@ struct xprt_class { | |||
203 | }; | 202 | }; |
204 | 203 | ||
205 | /* | 204 | /* |
206 | * Transport operations used by ULPs | ||
207 | */ | ||
208 | void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr); | ||
209 | |||
210 | /* | ||
211 | * Generic internal transport functions | 205 | * Generic internal transport functions |
212 | */ | 206 | */ |
213 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args); | 207 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args); |
@@ -245,7 +239,8 @@ void xprt_adjust_cwnd(struct rpc_task *task, int result); | |||
245 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid); | 239 | struct rpc_rqst * xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid); |
246 | void xprt_complete_rqst(struct rpc_task *task, int copied); | 240 | void xprt_complete_rqst(struct rpc_task *task, int copied); |
247 | void xprt_release_rqst_cong(struct rpc_task *task); | 241 | void xprt_release_rqst_cong(struct rpc_task *task); |
248 | void xprt_disconnect(struct rpc_xprt *xprt); | 242 | void xprt_disconnect_done(struct rpc_xprt *xprt); |
243 | void xprt_force_disconnect(struct rpc_xprt *xprt); | ||
249 | 244 | ||
250 | /* | 245 | /* |
251 | * Reserved bit positions in xprt->state | 246 | * Reserved bit positions in xprt->state |
@@ -256,6 +251,7 @@ void xprt_disconnect(struct rpc_xprt *xprt); | |||
256 | #define XPRT_CLOSE_WAIT (3) | 251 | #define XPRT_CLOSE_WAIT (3) |
257 | #define XPRT_BOUND (4) | 252 | #define XPRT_BOUND (4) |
258 | #define XPRT_BINDING (5) | 253 | #define XPRT_BINDING (5) |
254 | #define XPRT_CLOSING (6) | ||
259 | 255 | ||
260 | static inline void xprt_set_connected(struct rpc_xprt *xprt) | 256 | static inline void xprt_set_connected(struct rpc_xprt *xprt) |
261 | { | 257 | { |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 1ea27559b1de..bcd9abdb031c 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -51,6 +51,7 @@ rpcauth_register(const struct rpc_authops *ops) | |||
51 | spin_unlock(&rpc_authflavor_lock); | 51 | spin_unlock(&rpc_authflavor_lock); |
52 | return ret; | 52 | return ret; |
53 | } | 53 | } |
54 | EXPORT_SYMBOL_GPL(rpcauth_register); | ||
54 | 55 | ||
55 | int | 56 | int |
56 | rpcauth_unregister(const struct rpc_authops *ops) | 57 | rpcauth_unregister(const struct rpc_authops *ops) |
@@ -68,6 +69,7 @@ rpcauth_unregister(const struct rpc_authops *ops) | |||
68 | spin_unlock(&rpc_authflavor_lock); | 69 | spin_unlock(&rpc_authflavor_lock); |
69 | return ret; | 70 | return ret; |
70 | } | 71 | } |
72 | EXPORT_SYMBOL_GPL(rpcauth_unregister); | ||
71 | 73 | ||
72 | struct rpc_auth * | 74 | struct rpc_auth * |
73 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 75 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) |
@@ -102,6 +104,7 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | |||
102 | out: | 104 | out: |
103 | return auth; | 105 | return auth; |
104 | } | 106 | } |
107 | EXPORT_SYMBOL_GPL(rpcauth_create); | ||
105 | 108 | ||
106 | void | 109 | void |
107 | rpcauth_release(struct rpc_auth *auth) | 110 | rpcauth_release(struct rpc_auth *auth) |
@@ -151,6 +154,7 @@ rpcauth_init_credcache(struct rpc_auth *auth) | |||
151 | auth->au_credcache = new; | 154 | auth->au_credcache = new; |
152 | return 0; | 155 | return 0; |
153 | } | 156 | } |
157 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | ||
154 | 158 | ||
155 | /* | 159 | /* |
156 | * Destroy a list of credentials | 160 | * Destroy a list of credentials |
@@ -213,6 +217,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) | |||
213 | kfree(cache); | 217 | kfree(cache); |
214 | } | 218 | } |
215 | } | 219 | } |
220 | EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache); | ||
216 | 221 | ||
217 | /* | 222 | /* |
218 | * Remove stale credentials. Avoid sleeping inside the loop. | 223 | * Remove stale credentials. Avoid sleeping inside the loop. |
@@ -332,6 +337,7 @@ found: | |||
332 | out: | 337 | out: |
333 | return cred; | 338 | return cred; |
334 | } | 339 | } |
340 | EXPORT_SYMBOL_GPL(rpcauth_lookup_credcache); | ||
335 | 341 | ||
336 | struct rpc_cred * | 342 | struct rpc_cred * |
337 | rpcauth_lookupcred(struct rpc_auth *auth, int flags) | 343 | rpcauth_lookupcred(struct rpc_auth *auth, int flags) |
@@ -350,6 +356,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
350 | put_group_info(acred.group_info); | 356 | put_group_info(acred.group_info); |
351 | return ret; | 357 | return ret; |
352 | } | 358 | } |
359 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); | ||
353 | 360 | ||
354 | void | 361 | void |
355 | rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | 362 | rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, |
@@ -366,7 +373,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | |||
366 | #endif | 373 | #endif |
367 | cred->cr_uid = acred->uid; | 374 | cred->cr_uid = acred->uid; |
368 | } | 375 | } |
369 | EXPORT_SYMBOL(rpcauth_init_cred); | 376 | EXPORT_SYMBOL_GPL(rpcauth_init_cred); |
370 | 377 | ||
371 | struct rpc_cred * | 378 | struct rpc_cred * |
372 | rpcauth_bindcred(struct rpc_task *task) | 379 | rpcauth_bindcred(struct rpc_task *task) |
@@ -378,6 +385,7 @@ rpcauth_bindcred(struct rpc_task *task) | |||
378 | .group_info = current->group_info, | 385 | .group_info = current->group_info, |
379 | }; | 386 | }; |
380 | struct rpc_cred *ret; | 387 | struct rpc_cred *ret; |
388 | sigset_t oldset; | ||
381 | int flags = 0; | 389 | int flags = 0; |
382 | 390 | ||
383 | dprintk("RPC: %5u looking up %s cred\n", | 391 | dprintk("RPC: %5u looking up %s cred\n", |
@@ -385,7 +393,9 @@ rpcauth_bindcred(struct rpc_task *task) | |||
385 | get_group_info(acred.group_info); | 393 | get_group_info(acred.group_info); |
386 | if (task->tk_flags & RPC_TASK_ROOTCREDS) | 394 | if (task->tk_flags & RPC_TASK_ROOTCREDS) |
387 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; | 395 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; |
396 | rpc_clnt_sigmask(task->tk_client, &oldset); | ||
388 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | 397 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
398 | rpc_clnt_sigunmask(task->tk_client, &oldset); | ||
389 | if (!IS_ERR(ret)) | 399 | if (!IS_ERR(ret)) |
390 | task->tk_msg.rpc_cred = ret; | 400 | task->tk_msg.rpc_cred = ret; |
391 | else | 401 | else |
@@ -435,6 +445,7 @@ need_lock: | |||
435 | out_destroy: | 445 | out_destroy: |
436 | cred->cr_ops->crdestroy(cred); | 446 | cred->cr_ops->crdestroy(cred); |
437 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(put_rpccred); | ||
438 | 449 | ||
439 | void | 450 | void |
440 | rpcauth_unbindcred(struct rpc_task *task) | 451 | rpcauth_unbindcred(struct rpc_task *task) |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1f2d85e869c0..6dac38792288 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -472,16 +472,15 @@ gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | |||
472 | char __user *dst, size_t buflen) | 472 | char __user *dst, size_t buflen) |
473 | { | 473 | { |
474 | char *data = (char *)msg->data + msg->copied; | 474 | char *data = (char *)msg->data + msg->copied; |
475 | ssize_t mlen = msg->len; | 475 | size_t mlen = min(msg->len, buflen); |
476 | ssize_t left; | 476 | unsigned long left; |
477 | 477 | ||
478 | if (mlen > buflen) | ||
479 | mlen = buflen; | ||
480 | left = copy_to_user(dst, data, mlen); | 478 | left = copy_to_user(dst, data, mlen); |
481 | if (left < 0) { | 479 | if (left == mlen) { |
482 | msg->errno = left; | 480 | msg->errno = -EFAULT; |
483 | return left; | 481 | return -EFAULT; |
484 | } | 482 | } |
483 | |||
485 | mlen -= left; | 484 | mlen -= left; |
486 | msg->copied += mlen; | 485 | msg->copied += mlen; |
487 | msg->errno = 0; | 486 | msg->errno = 0; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 76be83ee4b04..924916ceaa43 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
31 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
32 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
33 | #include <linux/in6.h> | ||
33 | 34 | ||
34 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
35 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
@@ -121,8 +122,9 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | |||
121 | } | 122 | } |
122 | } | 123 | } |
123 | 124 | ||
124 | static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, rpc_authflavor_t flavor) | 125 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
125 | { | 126 | { |
127 | struct rpc_program *program = args->program; | ||
126 | struct rpc_version *version; | 128 | struct rpc_version *version; |
127 | struct rpc_clnt *clnt = NULL; | 129 | struct rpc_clnt *clnt = NULL; |
128 | struct rpc_auth *auth; | 130 | struct rpc_auth *auth; |
@@ -131,13 +133,13 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
131 | 133 | ||
132 | /* sanity check the name before trying to print it */ | 134 | /* sanity check the name before trying to print it */ |
133 | err = -EINVAL; | 135 | err = -EINVAL; |
134 | len = strlen(servname); | 136 | len = strlen(args->servername); |
135 | if (len > RPC_MAXNETNAMELEN) | 137 | if (len > RPC_MAXNETNAMELEN) |
136 | goto out_no_rpciod; | 138 | goto out_no_rpciod; |
137 | len++; | 139 | len++; |
138 | 140 | ||
139 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 141 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
140 | program->name, servname, xprt); | 142 | program->name, args->servername, xprt); |
141 | 143 | ||
142 | err = rpciod_up(); | 144 | err = rpciod_up(); |
143 | if (err) | 145 | if (err) |
@@ -145,7 +147,11 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
145 | err = -EINVAL; | 147 | err = -EINVAL; |
146 | if (!xprt) | 148 | if (!xprt) |
147 | goto out_no_xprt; | 149 | goto out_no_xprt; |
148 | if (vers >= program->nrvers || !(version = program->version[vers])) | 150 | |
151 | if (args->version >= program->nrvers) | ||
152 | goto out_err; | ||
153 | version = program->version[args->version]; | ||
154 | if (version == NULL) | ||
149 | goto out_err; | 155 | goto out_err; |
150 | 156 | ||
151 | err = -ENOMEM; | 157 | err = -ENOMEM; |
@@ -157,12 +163,12 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
157 | clnt->cl_server = clnt->cl_inline_name; | 163 | clnt->cl_server = clnt->cl_inline_name; |
158 | if (len > sizeof(clnt->cl_inline_name)) { | 164 | if (len > sizeof(clnt->cl_inline_name)) { |
159 | char *buf = kmalloc(len, GFP_KERNEL); | 165 | char *buf = kmalloc(len, GFP_KERNEL); |
160 | if (buf != 0) | 166 | if (buf != NULL) |
161 | clnt->cl_server = buf; | 167 | clnt->cl_server = buf; |
162 | else | 168 | else |
163 | len = sizeof(clnt->cl_inline_name); | 169 | len = sizeof(clnt->cl_inline_name); |
164 | } | 170 | } |
165 | strlcpy(clnt->cl_server, servname, len); | 171 | strlcpy(clnt->cl_server, args->servername, len); |
166 | 172 | ||
167 | clnt->cl_xprt = xprt; | 173 | clnt->cl_xprt = xprt; |
168 | clnt->cl_procinfo = version->procs; | 174 | clnt->cl_procinfo = version->procs; |
@@ -182,8 +188,15 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
182 | if (!xprt_bound(clnt->cl_xprt)) | 188 | if (!xprt_bound(clnt->cl_xprt)) |
183 | clnt->cl_autobind = 1; | 189 | clnt->cl_autobind = 1; |
184 | 190 | ||
191 | clnt->cl_timeout = xprt->timeout; | ||
192 | if (args->timeout != NULL) { | ||
193 | memcpy(&clnt->cl_timeout_default, args->timeout, | ||
194 | sizeof(clnt->cl_timeout_default)); | ||
195 | clnt->cl_timeout = &clnt->cl_timeout_default; | ||
196 | } | ||
197 | |||
185 | clnt->cl_rtt = &clnt->cl_rtt_default; | 198 | clnt->cl_rtt = &clnt->cl_rtt_default; |
186 | rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); | 199 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); |
187 | 200 | ||
188 | kref_init(&clnt->cl_kref); | 201 | kref_init(&clnt->cl_kref); |
189 | 202 | ||
@@ -191,10 +204,10 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
191 | if (err < 0) | 204 | if (err < 0) |
192 | goto out_no_path; | 205 | goto out_no_path; |
193 | 206 | ||
194 | auth = rpcauth_create(flavor, clnt); | 207 | auth = rpcauth_create(args->authflavor, clnt); |
195 | if (IS_ERR(auth)) { | 208 | if (IS_ERR(auth)) { |
196 | printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", | 209 | printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", |
197 | flavor); | 210 | args->authflavor); |
198 | err = PTR_ERR(auth); | 211 | err = PTR_ERR(auth); |
199 | goto out_no_auth; | 212 | goto out_no_auth; |
200 | } | 213 | } |
@@ -245,9 +258,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
245 | .srcaddr = args->saddress, | 258 | .srcaddr = args->saddress, |
246 | .dstaddr = args->address, | 259 | .dstaddr = args->address, |
247 | .addrlen = args->addrsize, | 260 | .addrlen = args->addrsize, |
248 | .timeout = args->timeout | ||
249 | }; | 261 | }; |
250 | char servername[20]; | 262 | char servername[48]; |
251 | 263 | ||
252 | xprt = xprt_create_transport(&xprtargs); | 264 | xprt = xprt_create_transport(&xprtargs); |
253 | if (IS_ERR(xprt)) | 265 | if (IS_ERR(xprt)) |
@@ -258,13 +270,34 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
258 | * up a string representation of the passed-in address. | 270 | * up a string representation of the passed-in address. |
259 | */ | 271 | */ |
260 | if (args->servername == NULL) { | 272 | if (args->servername == NULL) { |
261 | struct sockaddr_in *addr = | 273 | servername[0] = '\0'; |
262 | (struct sockaddr_in *) args->address; | 274 | switch (args->address->sa_family) { |
263 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | 275 | case AF_INET: { |
264 | NIPQUAD(addr->sin_addr.s_addr)); | 276 | struct sockaddr_in *sin = |
277 | (struct sockaddr_in *)args->address; | ||
278 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | ||
279 | NIPQUAD(sin->sin_addr.s_addr)); | ||
280 | break; | ||
281 | } | ||
282 | case AF_INET6: { | ||
283 | struct sockaddr_in6 *sin = | ||
284 | (struct sockaddr_in6 *)args->address; | ||
285 | snprintf(servername, sizeof(servername), NIP6_FMT, | ||
286 | NIP6(sin->sin6_addr)); | ||
287 | break; | ||
288 | } | ||
289 | default: | ||
290 | /* caller wants default server name, but | ||
291 | * address family isn't recognized. */ | ||
292 | return ERR_PTR(-EINVAL); | ||
293 | } | ||
265 | args->servername = servername; | 294 | args->servername = servername; |
266 | } | 295 | } |
267 | 296 | ||
297 | xprt = xprt_create_transport(&xprtargs); | ||
298 | if (IS_ERR(xprt)) | ||
299 | return (struct rpc_clnt *)xprt; | ||
300 | |||
268 | /* | 301 | /* |
269 | * By default, kernel RPC client connects from a reserved port. | 302 | * By default, kernel RPC client connects from a reserved port. |
270 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, | 303 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, |
@@ -275,8 +308,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
275 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 308 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
276 | xprt->resvport = 0; | 309 | xprt->resvport = 0; |
277 | 310 | ||
278 | clnt = rpc_new_client(xprt, args->servername, args->program, | 311 | clnt = rpc_new_client(args, xprt); |
279 | args->version, args->authflavor); | ||
280 | if (IS_ERR(clnt)) | 312 | if (IS_ERR(clnt)) |
281 | return clnt; | 313 | return clnt; |
282 | 314 | ||
@@ -322,7 +354,7 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
322 | new->cl_autobind = 0; | 354 | new->cl_autobind = 0; |
323 | INIT_LIST_HEAD(&new->cl_tasks); | 355 | INIT_LIST_HEAD(&new->cl_tasks); |
324 | spin_lock_init(&new->cl_lock); | 356 | spin_lock_init(&new->cl_lock); |
325 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 357 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); |
326 | new->cl_metrics = rpc_alloc_iostats(clnt); | 358 | new->cl_metrics = rpc_alloc_iostats(clnt); |
327 | if (new->cl_metrics == NULL) | 359 | if (new->cl_metrics == NULL) |
328 | goto out_no_stats; | 360 | goto out_no_stats; |
@@ -345,6 +377,7 @@ out_no_clnt: | |||
345 | dprintk("RPC: %s: returned error %d\n", __FUNCTION__, err); | 377 | dprintk("RPC: %s: returned error %d\n", __FUNCTION__, err); |
346 | return ERR_PTR(err); | 378 | return ERR_PTR(err); |
347 | } | 379 | } |
380 | EXPORT_SYMBOL_GPL(rpc_clone_client); | ||
348 | 381 | ||
349 | /* | 382 | /* |
350 | * Properly shut down an RPC client, terminating all outstanding | 383 | * Properly shut down an RPC client, terminating all outstanding |
@@ -363,6 +396,7 @@ void rpc_shutdown_client(struct rpc_clnt *clnt) | |||
363 | 396 | ||
364 | rpc_release_client(clnt); | 397 | rpc_release_client(clnt); |
365 | } | 398 | } |
399 | EXPORT_SYMBOL_GPL(rpc_shutdown_client); | ||
366 | 400 | ||
367 | /* | 401 | /* |
368 | * Free an RPC client | 402 | * Free an RPC client |
@@ -467,6 +501,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | |||
467 | out: | 501 | out: |
468 | return clnt; | 502 | return clnt; |
469 | } | 503 | } |
504 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); | ||
470 | 505 | ||
471 | /* | 506 | /* |
472 | * Default callback for async RPC calls | 507 | * Default callback for async RPC calls |
@@ -498,12 +533,12 @@ static void rpc_save_sigmask(sigset_t *oldset, int intr) | |||
498 | sigprocmask(SIG_BLOCK, &sigmask, oldset); | 533 | sigprocmask(SIG_BLOCK, &sigmask, oldset); |
499 | } | 534 | } |
500 | 535 | ||
501 | static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset) | 536 | static void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset) |
502 | { | 537 | { |
503 | rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task)); | 538 | rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task)); |
504 | } | 539 | } |
505 | 540 | ||
506 | static inline void rpc_restore_sigmask(sigset_t *oldset) | 541 | static void rpc_restore_sigmask(sigset_t *oldset) |
507 | { | 542 | { |
508 | sigprocmask(SIG_SETMASK, oldset, NULL); | 543 | sigprocmask(SIG_SETMASK, oldset, NULL); |
509 | } | 544 | } |
@@ -512,45 +547,49 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset) | |||
512 | { | 547 | { |
513 | rpc_save_sigmask(oldset, clnt->cl_intr); | 548 | rpc_save_sigmask(oldset, clnt->cl_intr); |
514 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(rpc_clnt_sigmask); | ||
515 | 551 | ||
516 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) | 552 | void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) |
517 | { | 553 | { |
518 | rpc_restore_sigmask(oldset); | 554 | rpc_restore_sigmask(oldset); |
519 | } | 555 | } |
556 | EXPORT_SYMBOL_GPL(rpc_clnt_sigunmask); | ||
520 | 557 | ||
521 | static | 558 | /** |
522 | struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, | 559 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it |
523 | struct rpc_message *msg, | 560 | * @task_setup_data: pointer to task initialisation data |
524 | int flags, | 561 | */ |
525 | const struct rpc_call_ops *ops, | 562 | struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) |
526 | void *data) | ||
527 | { | 563 | { |
528 | struct rpc_task *task, *ret; | 564 | struct rpc_task *task, *ret; |
529 | sigset_t oldset; | 565 | sigset_t oldset; |
530 | 566 | ||
531 | task = rpc_new_task(clnt, flags, ops, data); | 567 | task = rpc_new_task(task_setup_data); |
532 | if (task == NULL) { | 568 | if (task == NULL) { |
533 | rpc_release_calldata(ops, data); | 569 | rpc_release_calldata(task_setup_data->callback_ops, |
534 | return ERR_PTR(-ENOMEM); | 570 | task_setup_data->callback_data); |
571 | ret = ERR_PTR(-ENOMEM); | ||
572 | goto out; | ||
535 | } | 573 | } |
536 | 574 | ||
537 | /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ | 575 | if (task->tk_status != 0) { |
538 | rpc_task_sigmask(task, &oldset); | 576 | ret = ERR_PTR(task->tk_status); |
539 | if (msg != NULL) { | 577 | rpc_put_task(task); |
540 | rpc_call_setup(task, msg, 0); | 578 | goto out; |
541 | if (task->tk_status != 0) { | ||
542 | ret = ERR_PTR(task->tk_status); | ||
543 | rpc_put_task(task); | ||
544 | goto out; | ||
545 | } | ||
546 | } | 579 | } |
547 | atomic_inc(&task->tk_count); | 580 | atomic_inc(&task->tk_count); |
548 | rpc_execute(task); | 581 | /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ |
582 | if (!RPC_IS_ASYNC(task)) { | ||
583 | rpc_task_sigmask(task, &oldset); | ||
584 | rpc_execute(task); | ||
585 | rpc_restore_sigmask(&oldset); | ||
586 | } else | ||
587 | rpc_execute(task); | ||
549 | ret = task; | 588 | ret = task; |
550 | out: | 589 | out: |
551 | rpc_restore_sigmask(&oldset); | ||
552 | return ret; | 590 | return ret; |
553 | } | 591 | } |
592 | EXPORT_SYMBOL_GPL(rpc_run_task); | ||
554 | 593 | ||
555 | /** | 594 | /** |
556 | * rpc_call_sync - Perform a synchronous RPC call | 595 | * rpc_call_sync - Perform a synchronous RPC call |
@@ -561,17 +600,24 @@ out: | |||
561 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | 600 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) |
562 | { | 601 | { |
563 | struct rpc_task *task; | 602 | struct rpc_task *task; |
603 | struct rpc_task_setup task_setup_data = { | ||
604 | .rpc_client = clnt, | ||
605 | .rpc_message = msg, | ||
606 | .callback_ops = &rpc_default_ops, | ||
607 | .flags = flags, | ||
608 | }; | ||
564 | int status; | 609 | int status; |
565 | 610 | ||
566 | BUG_ON(flags & RPC_TASK_ASYNC); | 611 | BUG_ON(flags & RPC_TASK_ASYNC); |
567 | 612 | ||
568 | task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL); | 613 | task = rpc_run_task(&task_setup_data); |
569 | if (IS_ERR(task)) | 614 | if (IS_ERR(task)) |
570 | return PTR_ERR(task); | 615 | return PTR_ERR(task); |
571 | status = task->tk_status; | 616 | status = task->tk_status; |
572 | rpc_put_task(task); | 617 | rpc_put_task(task); |
573 | return status; | 618 | return status; |
574 | } | 619 | } |
620 | EXPORT_SYMBOL_GPL(rpc_call_sync); | ||
575 | 621 | ||
576 | /** | 622 | /** |
577 | * rpc_call_async - Perform an asynchronous RPC call | 623 | * rpc_call_async - Perform an asynchronous RPC call |
@@ -586,45 +632,28 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
586 | const struct rpc_call_ops *tk_ops, void *data) | 632 | const struct rpc_call_ops *tk_ops, void *data) |
587 | { | 633 | { |
588 | struct rpc_task *task; | 634 | struct rpc_task *task; |
635 | struct rpc_task_setup task_setup_data = { | ||
636 | .rpc_client = clnt, | ||
637 | .rpc_message = msg, | ||
638 | .callback_ops = tk_ops, | ||
639 | .callback_data = data, | ||
640 | .flags = flags|RPC_TASK_ASYNC, | ||
641 | }; | ||
589 | 642 | ||
590 | task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data); | 643 | task = rpc_run_task(&task_setup_data); |
591 | if (IS_ERR(task)) | 644 | if (IS_ERR(task)) |
592 | return PTR_ERR(task); | 645 | return PTR_ERR(task); |
593 | rpc_put_task(task); | 646 | rpc_put_task(task); |
594 | return 0; | 647 | return 0; |
595 | } | 648 | } |
596 | 649 | EXPORT_SYMBOL_GPL(rpc_call_async); | |
597 | /** | ||
598 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it | ||
599 | * @clnt: pointer to RPC client | ||
600 | * @flags: RPC flags | ||
601 | * @ops: RPC call ops | ||
602 | * @data: user call data | ||
603 | */ | ||
604 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
605 | const struct rpc_call_ops *tk_ops, | ||
606 | void *data) | ||
607 | { | ||
608 | return rpc_do_run_task(clnt, NULL, flags, tk_ops, data); | ||
609 | } | ||
610 | EXPORT_SYMBOL(rpc_run_task); | ||
611 | 650 | ||
612 | void | 651 | void |
613 | rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | 652 | rpc_call_start(struct rpc_task *task) |
614 | { | 653 | { |
615 | task->tk_msg = *msg; | 654 | task->tk_action = call_start; |
616 | task->tk_flags |= flags; | ||
617 | /* Bind the user cred */ | ||
618 | if (task->tk_msg.rpc_cred != NULL) | ||
619 | rpcauth_holdcred(task); | ||
620 | else | ||
621 | rpcauth_bindcred(task); | ||
622 | |||
623 | if (task->tk_status == 0) | ||
624 | task->tk_action = call_start; | ||
625 | else | ||
626 | task->tk_action = rpc_exit_task; | ||
627 | } | 655 | } |
656 | EXPORT_SYMBOL_GPL(rpc_call_start); | ||
628 | 657 | ||
629 | /** | 658 | /** |
630 | * rpc_peeraddr - extract remote peer address from clnt's xprt | 659 | * rpc_peeraddr - extract remote peer address from clnt's xprt |
@@ -653,7 +682,8 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); | |||
653 | * @format: address format | 682 | * @format: address format |
654 | * | 683 | * |
655 | */ | 684 | */ |
656 | char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) | 685 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, |
686 | enum rpc_display_format_t format) | ||
657 | { | 687 | { |
658 | struct rpc_xprt *xprt = clnt->cl_xprt; | 688 | struct rpc_xprt *xprt = clnt->cl_xprt; |
659 | 689 | ||
@@ -671,6 +701,7 @@ rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize | |||
671 | if (xprt->ops->set_buffer_size) | 701 | if (xprt->ops->set_buffer_size) |
672 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); | 702 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); |
673 | } | 703 | } |
704 | EXPORT_SYMBOL_GPL(rpc_setbufsize); | ||
674 | 705 | ||
675 | /* | 706 | /* |
676 | * Return size of largest payload RPC client can support, in bytes | 707 | * Return size of largest payload RPC client can support, in bytes |
@@ -710,6 +741,7 @@ rpc_restart_call(struct rpc_task *task) | |||
710 | 741 | ||
711 | task->tk_action = call_start; | 742 | task->tk_action = call_start; |
712 | } | 743 | } |
744 | EXPORT_SYMBOL_GPL(rpc_restart_call); | ||
713 | 745 | ||
714 | /* | 746 | /* |
715 | * 0. Initial state | 747 | * 0. Initial state |
@@ -1137,7 +1169,7 @@ call_status(struct rpc_task *task) | |||
1137 | case -ETIMEDOUT: | 1169 | case -ETIMEDOUT: |
1138 | task->tk_action = call_timeout; | 1170 | task->tk_action = call_timeout; |
1139 | if (task->tk_client->cl_discrtry) | 1171 | if (task->tk_client->cl_discrtry) |
1140 | xprt_disconnect(task->tk_xprt); | 1172 | xprt_force_disconnect(task->tk_xprt); |
1141 | break; | 1173 | break; |
1142 | case -ECONNREFUSED: | 1174 | case -ECONNREFUSED: |
1143 | case -ENOTCONN: | 1175 | case -ENOTCONN: |
@@ -1260,7 +1292,7 @@ out_retry: | |||
1260 | req->rq_received = req->rq_private_buf.len = 0; | 1292 | req->rq_received = req->rq_private_buf.len = 0; |
1261 | task->tk_status = 0; | 1293 | task->tk_status = 0; |
1262 | if (task->tk_client->cl_discrtry) | 1294 | if (task->tk_client->cl_discrtry) |
1263 | xprt_disconnect(task->tk_xprt); | 1295 | xprt_force_disconnect(task->tk_xprt); |
1264 | } | 1296 | } |
1265 | 1297 | ||
1266 | /* | 1298 | /* |
@@ -1517,9 +1549,15 @@ struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int | |||
1517 | .rpc_proc = &rpcproc_null, | 1549 | .rpc_proc = &rpcproc_null, |
1518 | .rpc_cred = cred, | 1550 | .rpc_cred = cred, |
1519 | }; | 1551 | }; |
1520 | return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL); | 1552 | struct rpc_task_setup task_setup_data = { |
1553 | .rpc_client = clnt, | ||
1554 | .rpc_message = &msg, | ||
1555 | .callback_ops = &rpc_default_ops, | ||
1556 | .flags = flags, | ||
1557 | }; | ||
1558 | return rpc_run_task(&task_setup_data); | ||
1521 | } | 1559 | } |
1522 | EXPORT_SYMBOL(rpc_call_null); | 1560 | EXPORT_SYMBOL_GPL(rpc_call_null); |
1523 | 1561 | ||
1524 | #ifdef RPC_DEBUG | 1562 | #ifdef RPC_DEBUG |
1525 | void rpc_show_tasks(void) | 1563 | void rpc_show_tasks(void) |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index c59f3ca2b41b..7e197168a245 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -76,6 +76,16 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
76 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | 76 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); |
77 | } | 77 | } |
78 | 78 | ||
79 | /** | ||
80 | * rpc_queue_upcall | ||
81 | * @inode: inode of upcall pipe on which to queue given message | ||
82 | * @msg: message to queue | ||
83 | * | ||
84 | * Call with an @inode created by rpc_mkpipe() to queue an upcall. | ||
85 | * A userspace process may then later read the upcall by performing a | ||
86 | * read on an open file for this inode. It is up to the caller to | ||
87 | * initialize the fields of @msg (other than @msg->list) appropriately. | ||
88 | */ | ||
79 | int | 89 | int |
80 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | 90 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) |
81 | { | 91 | { |
@@ -103,6 +113,7 @@ out: | |||
103 | wake_up(&rpci->waitq); | 113 | wake_up(&rpci->waitq); |
104 | return res; | 114 | return res; |
105 | } | 115 | } |
116 | EXPORT_SYMBOL(rpc_queue_upcall); | ||
106 | 117 | ||
107 | static inline void | 118 | static inline void |
108 | rpc_inode_setowner(struct inode *inode, void *private) | 119 | rpc_inode_setowner(struct inode *inode, void *private) |
@@ -512,8 +523,8 @@ rpc_get_inode(struct super_block *sb, int mode) | |||
512 | /* | 523 | /* |
513 | * FIXME: This probably has races. | 524 | * FIXME: This probably has races. |
514 | */ | 525 | */ |
515 | static void | 526 | static void rpc_depopulate(struct dentry *parent, |
516 | rpc_depopulate(struct dentry *parent, int start, int eof) | 527 | unsigned long start, unsigned long eof) |
517 | { | 528 | { |
518 | struct inode *dir = parent->d_inode; | 529 | struct inode *dir = parent->d_inode; |
519 | struct list_head *pos, *next; | 530 | struct list_head *pos, *next; |
@@ -663,7 +674,16 @@ rpc_lookup_negative(char *path, struct nameidata *nd) | |||
663 | return dentry; | 674 | return dentry; |
664 | } | 675 | } |
665 | 676 | ||
666 | 677 | /** | |
678 | * rpc_mkdir - Create a new directory in rpc_pipefs | ||
679 | * @path: path from the rpc_pipefs root to the new directory | ||
680 | * @rpc_clnt: rpc client to associate with this directory | ||
681 | * | ||
682 | * This creates a directory at the given @path associated with | ||
683 | * @rpc_clnt, which will contain a file named "info" with some basic | ||
684 | * information about the client, together with any "pipes" that may | ||
685 | * later be created using rpc_mkpipe(). | ||
686 | */ | ||
667 | struct dentry * | 687 | struct dentry * |
668 | rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | 688 | rpc_mkdir(char *path, struct rpc_clnt *rpc_client) |
669 | { | 689 | { |
@@ -699,6 +719,10 @@ err_dput: | |||
699 | goto out; | 719 | goto out; |
700 | } | 720 | } |
701 | 721 | ||
722 | /** | ||
723 | * rpc_rmdir - Remove a directory created with rpc_mkdir() | ||
724 | * @dentry: directory to remove | ||
725 | */ | ||
702 | int | 726 | int |
703 | rpc_rmdir(struct dentry *dentry) | 727 | rpc_rmdir(struct dentry *dentry) |
704 | { | 728 | { |
@@ -717,6 +741,25 @@ rpc_rmdir(struct dentry *dentry) | |||
717 | return error; | 741 | return error; |
718 | } | 742 | } |
719 | 743 | ||
744 | /** | ||
745 | * rpc_mkpipe - make an rpc_pipefs file for kernel<->userspace communication | ||
746 | * @parent: dentry of directory to create new "pipe" in | ||
747 | * @name: name of pipe | ||
748 | * @private: private data to associate with the pipe, for the caller's use | ||
749 | * @ops: operations defining the behavior of the pipe: upcall, downcall, | ||
750 | * release_pipe, and destroy_msg. | ||
751 | * | ||
752 | * Data is made available for userspace to read by calls to | ||
753 | * rpc_queue_upcall(). The actual reads will result in calls to | ||
754 | * @ops->upcall, which will be called with the file pointer, | ||
755 | * message, and userspace buffer to copy to. | ||
756 | * | ||
757 | * Writes can come at any time, and do not necessarily have to be | ||
758 | * responses to upcalls. They will result in calls to @msg->downcall. | ||
759 | * | ||
760 | * The @private argument passed here will be available to all these methods | ||
761 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. | ||
762 | */ | ||
720 | struct dentry * | 763 | struct dentry * |
721 | rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pipe_ops *ops, int flags) | 764 | rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pipe_ops *ops, int flags) |
722 | { | 765 | { |
@@ -763,7 +806,16 @@ err_dput: | |||
763 | -ENOMEM); | 806 | -ENOMEM); |
764 | goto out; | 807 | goto out; |
765 | } | 808 | } |
809 | EXPORT_SYMBOL(rpc_mkpipe); | ||
766 | 810 | ||
811 | /** | ||
812 | * rpc_unlink - remove a pipe | ||
813 | * @dentry: dentry for the pipe, as returned from rpc_mkpipe | ||
814 | * | ||
815 | * After this call, lookups will no longer find the pipe, and any | ||
816 | * attempts to read or write using preexisting opens of the pipe will | ||
817 | * return -EPIPE. | ||
818 | */ | ||
767 | int | 819 | int |
768 | rpc_unlink(struct dentry *dentry) | 820 | rpc_unlink(struct dentry *dentry) |
769 | { | 821 | { |
@@ -785,6 +837,7 @@ rpc_unlink(struct dentry *dentry) | |||
785 | dput(parent); | 837 | dput(parent); |
786 | return error; | 838 | return error; |
787 | } | 839 | } |
840 | EXPORT_SYMBOL(rpc_unlink); | ||
788 | 841 | ||
789 | /* | 842 | /* |
790 | * populate the filesystem | 843 | * populate the filesystem |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index a05493aedb68..fa5b8f202d5b 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -55,45 +55,6 @@ enum { | |||
55 | #define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT | 55 | #define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * r_addr | ||
59 | * | ||
60 | * Quoting RFC 3530, section 2.2: | ||
61 | * | ||
62 | * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the | ||
63 | * US-ASCII string: | ||
64 | * | ||
65 | * h1.h2.h3.h4.p1.p2 | ||
66 | * | ||
67 | * The prefix, "h1.h2.h3.h4", is the standard textual form for | ||
68 | * representing an IPv4 address, which is always four octets long. | ||
69 | * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively, | ||
70 | * the first through fourth octets each converted to ASCII-decimal. | ||
71 | * Assuming big-endian ordering, p1 and p2 are, respectively, the first | ||
72 | * and second octets each converted to ASCII-decimal. For example, if a | ||
73 | * host, in big-endian order, has an address of 0x0A010307 and there is | ||
74 | * a service listening on, in big endian order, port 0x020F (decimal | ||
75 | * 527), then the complete universal address is "10.1.3.7.2.15". | ||
76 | * | ||
77 | * ... | ||
78 | * | ||
79 | * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the | ||
80 | * US-ASCII string: | ||
81 | * | ||
82 | * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2 | ||
83 | * | ||
84 | * The suffix "p1.p2" is the service port, and is computed the same way | ||
85 | * as with universal addresses for TCP and UDP over IPv4. The prefix, | ||
86 | * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for | ||
87 | * representing an IPv6 address as defined in Section 2.2 of [RFC2373]. | ||
88 | * Additionally, the two alternative forms specified in Section 2.2 of | ||
89 | * [RFC2373] are also acceptable. | ||
90 | * | ||
91 | * XXX: Currently this implementation does not explicitly convert the | ||
92 | * stored address to US-ASCII on non-ASCII systems. | ||
93 | */ | ||
94 | #define RPCB_MAXADDRLEN (128u) | ||
95 | |||
96 | /* | ||
97 | * r_owner | 58 | * r_owner |
98 | * | 59 | * |
99 | * The "owner" is allowed to unset a service in the rpcbind database. | 60 | * The "owner" is allowed to unset a service in the rpcbind database. |
@@ -112,9 +73,9 @@ struct rpcbind_args { | |||
112 | u32 r_vers; | 73 | u32 r_vers; |
113 | u32 r_prot; | 74 | u32 r_prot; |
114 | unsigned short r_port; | 75 | unsigned short r_port; |
115 | char * r_netid; | 76 | const char * r_netid; |
116 | char r_addr[RPCB_MAXADDRLEN]; | 77 | const char * r_addr; |
117 | char * r_owner; | 78 | const char * r_owner; |
118 | }; | 79 | }; |
119 | 80 | ||
120 | static struct rpc_procinfo rpcb_procedures2[]; | 81 | static struct rpc_procinfo rpcb_procedures2[]; |
@@ -128,19 +89,6 @@ struct rpcb_info { | |||
128 | static struct rpcb_info rpcb_next_version[]; | 89 | static struct rpcb_info rpcb_next_version[]; |
129 | static struct rpcb_info rpcb_next_version6[]; | 90 | static struct rpcb_info rpcb_next_version6[]; |
130 | 91 | ||
131 | static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) | ||
132 | { | ||
133 | struct rpcbind_args *map = calldata; | ||
134 | struct rpc_xprt *xprt = map->r_xprt; | ||
135 | struct rpc_message msg = { | ||
136 | .rpc_proc = rpcb_next_version[xprt->bind_index].rpc_proc, | ||
137 | .rpc_argp = map, | ||
138 | .rpc_resp = &map->r_port, | ||
139 | }; | ||
140 | |||
141 | rpc_call_setup(task, &msg, 0); | ||
142 | } | ||
143 | |||
144 | static void rpcb_map_release(void *data) | 92 | static void rpcb_map_release(void *data) |
145 | { | 93 | { |
146 | struct rpcbind_args *map = data; | 94 | struct rpcbind_args *map = data; |
@@ -150,7 +98,6 @@ static void rpcb_map_release(void *data) | |||
150 | } | 98 | } |
151 | 99 | ||
152 | static const struct rpc_call_ops rpcb_getport_ops = { | 100 | static const struct rpc_call_ops rpcb_getport_ops = { |
153 | .rpc_call_prepare = rpcb_getport_prepare, | ||
154 | .rpc_call_done = rpcb_getport_done, | 101 | .rpc_call_done = rpcb_getport_done, |
155 | .rpc_release = rpcb_map_release, | 102 | .rpc_release = rpcb_map_release, |
156 | }; | 103 | }; |
@@ -162,12 +109,13 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status) | |||
162 | } | 109 | } |
163 | 110 | ||
164 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | 111 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, |
165 | int proto, int version, int privileged) | 112 | size_t salen, int proto, u32 version, |
113 | int privileged) | ||
166 | { | 114 | { |
167 | struct rpc_create_args args = { | 115 | struct rpc_create_args args = { |
168 | .protocol = proto, | 116 | .protocol = proto, |
169 | .address = srvaddr, | 117 | .address = srvaddr, |
170 | .addrsize = sizeof(struct sockaddr_in), | 118 | .addrsize = salen, |
171 | .servername = hostname, | 119 | .servername = hostname, |
172 | .program = &rpcb_program, | 120 | .program = &rpcb_program, |
173 | .version = version, | 121 | .version = version, |
@@ -230,7 +178,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
230 | prog, vers, prot, port); | 178 | prog, vers, prot, port); |
231 | 179 | ||
232 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, | 180 | rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin, |
233 | XPRT_TRANSPORT_UDP, 2, 1); | 181 | sizeof(sin), XPRT_TRANSPORT_UDP, 2, 1); |
234 | if (IS_ERR(rpcb_clnt)) | 182 | if (IS_ERR(rpcb_clnt)) |
235 | return PTR_ERR(rpcb_clnt); | 183 | return PTR_ERR(rpcb_clnt); |
236 | 184 | ||
@@ -252,13 +200,15 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
252 | * @vers: RPC version number to bind | 200 | * @vers: RPC version number to bind |
253 | * @prot: transport protocol to use to make this request | 201 | * @prot: transport protocol to use to make this request |
254 | * | 202 | * |
203 | * Return value is the requested advertised port number, | ||
204 | * or a negative errno value. | ||
205 | * | ||
255 | * Called from outside the RPC client in a synchronous task context. | 206 | * Called from outside the RPC client in a synchronous task context. |
256 | * Uses default timeout parameters specified by underlying transport. | 207 | * Uses default timeout parameters specified by underlying transport. |
257 | * | 208 | * |
258 | * XXX: Needs to support IPv6, and rpcbind versions 3 and 4 | 209 | * XXX: Needs to support IPv6 |
259 | */ | 210 | */ |
260 | int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, | 211 | int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot) |
261 | __u32 vers, int prot) | ||
262 | { | 212 | { |
263 | struct rpcbind_args map = { | 213 | struct rpcbind_args map = { |
264 | .r_prog = prog, | 214 | .r_prog = prog, |
@@ -272,14 +222,13 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, | |||
272 | .rpc_resp = &map.r_port, | 222 | .rpc_resp = &map.r_port, |
273 | }; | 223 | }; |
274 | struct rpc_clnt *rpcb_clnt; | 224 | struct rpc_clnt *rpcb_clnt; |
275 | char hostname[40]; | ||
276 | int status; | 225 | int status; |
277 | 226 | ||
278 | dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n", | 227 | dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n", |
279 | __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); | 228 | __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); |
280 | 229 | ||
281 | sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); | 230 | rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin, |
282 | rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0); | 231 | sizeof(*sin), prot, 2, 0); |
283 | if (IS_ERR(rpcb_clnt)) | 232 | if (IS_ERR(rpcb_clnt)) |
284 | return PTR_ERR(rpcb_clnt); | 233 | return PTR_ERR(rpcb_clnt); |
285 | 234 | ||
@@ -295,6 +244,24 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog, | |||
295 | } | 244 | } |
296 | EXPORT_SYMBOL_GPL(rpcb_getport_sync); | 245 | EXPORT_SYMBOL_GPL(rpcb_getport_sync); |
297 | 246 | ||
247 | static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version) | ||
248 | { | ||
249 | struct rpc_message msg = { | ||
250 | .rpc_proc = rpcb_next_version[version].rpc_proc, | ||
251 | .rpc_argp = map, | ||
252 | .rpc_resp = &map->r_port, | ||
253 | }; | ||
254 | struct rpc_task_setup task_setup_data = { | ||
255 | .rpc_client = rpcb_clnt, | ||
256 | .rpc_message = &msg, | ||
257 | .callback_ops = &rpcb_getport_ops, | ||
258 | .callback_data = map, | ||
259 | .flags = RPC_TASK_ASYNC, | ||
260 | }; | ||
261 | |||
262 | return rpc_run_task(&task_setup_data); | ||
263 | } | ||
264 | |||
298 | /** | 265 | /** |
299 | * rpcb_getport_async - obtain the port for a given RPC service on a given host | 266 | * rpcb_getport_async - obtain the port for a given RPC service on a given host |
300 | * @task: task that is waiting for portmapper request | 267 | * @task: task that is waiting for portmapper request |
@@ -305,12 +272,14 @@ EXPORT_SYMBOL_GPL(rpcb_getport_sync); | |||
305 | void rpcb_getport_async(struct rpc_task *task) | 272 | void rpcb_getport_async(struct rpc_task *task) |
306 | { | 273 | { |
307 | struct rpc_clnt *clnt = task->tk_client; | 274 | struct rpc_clnt *clnt = task->tk_client; |
308 | int bind_version; | 275 | u32 bind_version; |
309 | struct rpc_xprt *xprt = task->tk_xprt; | 276 | struct rpc_xprt *xprt = task->tk_xprt; |
310 | struct rpc_clnt *rpcb_clnt; | 277 | struct rpc_clnt *rpcb_clnt; |
311 | static struct rpcbind_args *map; | 278 | static struct rpcbind_args *map; |
312 | struct rpc_task *child; | 279 | struct rpc_task *child; |
313 | struct sockaddr addr; | 280 | struct sockaddr_storage addr; |
281 | struct sockaddr *sap = (struct sockaddr *)&addr; | ||
282 | size_t salen; | ||
314 | int status; | 283 | int status; |
315 | struct rpcb_info *info; | 284 | struct rpcb_info *info; |
316 | 285 | ||
@@ -340,10 +309,10 @@ void rpcb_getport_async(struct rpc_task *task) | |||
340 | goto bailout_nofree; | 309 | goto bailout_nofree; |
341 | } | 310 | } |
342 | 311 | ||
343 | rpc_peeraddr(clnt, (void *)&addr, sizeof(addr)); | 312 | salen = rpc_peeraddr(clnt, sap, sizeof(addr)); |
344 | 313 | ||
345 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ | 314 | /* Don't ever use rpcbind v2 for AF_INET6 requests */ |
346 | switch (addr.sa_family) { | 315 | switch (sap->sa_family) { |
347 | case AF_INET: | 316 | case AF_INET: |
348 | info = rpcb_next_version; | 317 | info = rpcb_next_version; |
349 | break; | 318 | break; |
@@ -368,7 +337,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
368 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 337 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
369 | task->tk_pid, __FUNCTION__, bind_version); | 338 | task->tk_pid, __FUNCTION__, bind_version); |
370 | 339 | ||
371 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, | 340 | rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, |
372 | bind_version, 0); | 341 | bind_version, 0); |
373 | if (IS_ERR(rpcb_clnt)) { | 342 | if (IS_ERR(rpcb_clnt)) { |
374 | status = PTR_ERR(rpcb_clnt); | 343 | status = PTR_ERR(rpcb_clnt); |
@@ -390,12 +359,10 @@ void rpcb_getport_async(struct rpc_task *task) | |||
390 | map->r_port = 0; | 359 | map->r_port = 0; |
391 | map->r_xprt = xprt_get(xprt); | 360 | map->r_xprt = xprt_get(xprt); |
392 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 361 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
393 | memcpy(map->r_addr, | 362 | map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); |
394 | rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), | ||
395 | sizeof(map->r_addr)); | ||
396 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ | 363 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ |
397 | 364 | ||
398 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); | 365 | child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index); |
399 | rpc_release_client(rpcb_clnt); | 366 | rpc_release_client(rpcb_clnt); |
400 | if (IS_ERR(child)) { | 367 | if (IS_ERR(child)) { |
401 | status = -EIO; | 368 | status = -EIO; |
@@ -518,7 +485,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
518 | * Simple sanity check. The smallest possible universal | 485 | * Simple sanity check. The smallest possible universal |
519 | * address is an IPv4 address string containing 11 bytes. | 486 | * address is an IPv4 address string containing 11 bytes. |
520 | */ | 487 | */ |
521 | if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN) | 488 | if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN) |
522 | goto out_err; | 489 | goto out_err; |
523 | 490 | ||
524 | /* | 491 | /* |
@@ -569,7 +536,7 @@ out_err: | |||
569 | #define RPCB_boolean_sz (1u) | 536 | #define RPCB_boolean_sz (1u) |
570 | 537 | ||
571 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) | 538 | #define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN)) |
572 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN)) | 539 | #define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN)) |
573 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) | 540 | #define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN)) |
574 | 541 | ||
575 | #define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \ | 542 | #define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \ |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index eed5dd9819cd..40ce6f6672d6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -45,7 +45,7 @@ static void rpc_release_task(struct rpc_task *task); | |||
45 | /* | 45 | /* |
46 | * RPC tasks sit here while waiting for conditions to improve. | 46 | * RPC tasks sit here while waiting for conditions to improve. |
47 | */ | 47 | */ |
48 | static RPC_WAITQ(delay_queue, "delayq"); | 48 | static struct rpc_wait_queue delay_queue; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * rpciod-related stuff | 51 | * rpciod-related stuff |
@@ -135,7 +135,7 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct r | |||
135 | if (unlikely(task->tk_priority > queue->maxpriority)) | 135 | if (unlikely(task->tk_priority > queue->maxpriority)) |
136 | q = &queue->tasks[queue->maxpriority]; | 136 | q = &queue->tasks[queue->maxpriority]; |
137 | list_for_each_entry(t, q, u.tk_wait.list) { | 137 | list_for_each_entry(t, q, u.tk_wait.list) { |
138 | if (t->tk_cookie == task->tk_cookie) { | 138 | if (t->tk_owner == task->tk_owner) { |
139 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); | 139 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); |
140 | return; | 140 | return; |
141 | } | 141 | } |
@@ -208,26 +208,26 @@ static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int | |||
208 | queue->count = 1 << (priority * 2); | 208 | queue->count = 1 << (priority * 2); |
209 | } | 209 | } |
210 | 210 | ||
211 | static inline void rpc_set_waitqueue_cookie(struct rpc_wait_queue *queue, unsigned long cookie) | 211 | static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) |
212 | { | 212 | { |
213 | queue->cookie = cookie; | 213 | queue->owner = pid; |
214 | queue->nr = RPC_BATCH_COUNT; | 214 | queue->nr = RPC_BATCH_COUNT; |
215 | } | 215 | } |
216 | 216 | ||
217 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | 217 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) |
218 | { | 218 | { |
219 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | 219 | rpc_set_waitqueue_priority(queue, queue->maxpriority); |
220 | rpc_set_waitqueue_cookie(queue, 0); | 220 | rpc_set_waitqueue_owner(queue, 0); |
221 | } | 221 | } |
222 | 222 | ||
223 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, int maxprio) | 223 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) |
224 | { | 224 | { |
225 | int i; | 225 | int i; |
226 | 226 | ||
227 | spin_lock_init(&queue->lock); | 227 | spin_lock_init(&queue->lock); |
228 | for (i = 0; i < ARRAY_SIZE(queue->tasks); i++) | 228 | for (i = 0; i < ARRAY_SIZE(queue->tasks); i++) |
229 | INIT_LIST_HEAD(&queue->tasks[i]); | 229 | INIT_LIST_HEAD(&queue->tasks[i]); |
230 | queue->maxpriority = maxprio; | 230 | queue->maxpriority = nr_queues - 1; |
231 | rpc_reset_waitqueue_priority(queue); | 231 | rpc_reset_waitqueue_priority(queue); |
232 | #ifdef RPC_DEBUG | 232 | #ifdef RPC_DEBUG |
233 | queue->name = qname; | 233 | queue->name = qname; |
@@ -236,14 +236,14 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c | |||
236 | 236 | ||
237 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 237 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
238 | { | 238 | { |
239 | __rpc_init_priority_wait_queue(queue, qname, RPC_PRIORITY_HIGH); | 239 | __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY); |
240 | } | 240 | } |
241 | 241 | ||
242 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 242 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
243 | { | 243 | { |
244 | __rpc_init_priority_wait_queue(queue, qname, 0); | 244 | __rpc_init_priority_wait_queue(queue, qname, 1); |
245 | } | 245 | } |
246 | EXPORT_SYMBOL(rpc_init_wait_queue); | 246 | EXPORT_SYMBOL_GPL(rpc_init_wait_queue); |
247 | 247 | ||
248 | static int rpc_wait_bit_interruptible(void *word) | 248 | static int rpc_wait_bit_interruptible(void *word) |
249 | { | 249 | { |
@@ -303,7 +303,7 @@ int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) | |||
303 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, | 303 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, |
304 | action, TASK_INTERRUPTIBLE); | 304 | action, TASK_INTERRUPTIBLE); |
305 | } | 305 | } |
306 | EXPORT_SYMBOL(__rpc_wait_for_completion_task); | 306 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * Make an RPC task runnable. | 309 | * Make an RPC task runnable. |
@@ -373,6 +373,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
373 | __rpc_sleep_on(q, task, action, timer); | 373 | __rpc_sleep_on(q, task, action, timer); |
374 | spin_unlock_bh(&q->lock); | 374 | spin_unlock_bh(&q->lock); |
375 | } | 375 | } |
376 | EXPORT_SYMBOL_GPL(rpc_sleep_on); | ||
376 | 377 | ||
377 | /** | 378 | /** |
378 | * __rpc_do_wake_up_task - wake up a single rpc_task | 379 | * __rpc_do_wake_up_task - wake up a single rpc_task |
@@ -444,6 +445,7 @@ void rpc_wake_up_task(struct rpc_task *task) | |||
444 | } | 445 | } |
445 | rcu_read_unlock_bh(); | 446 | rcu_read_unlock_bh(); |
446 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(rpc_wake_up_task); | ||
447 | 449 | ||
448 | /* | 450 | /* |
449 | * Wake up the next task on a priority queue. | 451 | * Wake up the next task on a priority queue. |
@@ -454,12 +456,12 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
454 | struct rpc_task *task; | 456 | struct rpc_task *task; |
455 | 457 | ||
456 | /* | 458 | /* |
457 | * Service a batch of tasks from a single cookie. | 459 | * Service a batch of tasks from a single owner. |
458 | */ | 460 | */ |
459 | q = &queue->tasks[queue->priority]; | 461 | q = &queue->tasks[queue->priority]; |
460 | if (!list_empty(q)) { | 462 | if (!list_empty(q)) { |
461 | task = list_entry(q->next, struct rpc_task, u.tk_wait.list); | 463 | task = list_entry(q->next, struct rpc_task, u.tk_wait.list); |
462 | if (queue->cookie == task->tk_cookie) { | 464 | if (queue->owner == task->tk_owner) { |
463 | if (--queue->nr) | 465 | if (--queue->nr) |
464 | goto out; | 466 | goto out; |
465 | list_move_tail(&task->u.tk_wait.list, q); | 467 | list_move_tail(&task->u.tk_wait.list, q); |
@@ -468,7 +470,7 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
468 | * Check if we need to switch queues. | 470 | * Check if we need to switch queues. |
469 | */ | 471 | */ |
470 | if (--queue->count) | 472 | if (--queue->count) |
471 | goto new_cookie; | 473 | goto new_owner; |
472 | } | 474 | } |
473 | 475 | ||
474 | /* | 476 | /* |
@@ -490,8 +492,8 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
490 | 492 | ||
491 | new_queue: | 493 | new_queue: |
492 | rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0])); | 494 | rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0])); |
493 | new_cookie: | 495 | new_owner: |
494 | rpc_set_waitqueue_cookie(queue, task->tk_cookie); | 496 | rpc_set_waitqueue_owner(queue, task->tk_owner); |
495 | out: | 497 | out: |
496 | __rpc_wake_up_task(task); | 498 | __rpc_wake_up_task(task); |
497 | return task; | 499 | return task; |
@@ -519,6 +521,7 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) | |||
519 | 521 | ||
520 | return task; | 522 | return task; |
521 | } | 523 | } |
524 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); | ||
522 | 525 | ||
523 | /** | 526 | /** |
524 | * rpc_wake_up - wake up all rpc_tasks | 527 | * rpc_wake_up - wake up all rpc_tasks |
@@ -544,6 +547,7 @@ void rpc_wake_up(struct rpc_wait_queue *queue) | |||
544 | spin_unlock(&queue->lock); | 547 | spin_unlock(&queue->lock); |
545 | rcu_read_unlock_bh(); | 548 | rcu_read_unlock_bh(); |
546 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(rpc_wake_up); | ||
547 | 551 | ||
548 | /** | 552 | /** |
549 | * rpc_wake_up_status - wake up all rpc_tasks and set their status value. | 553 | * rpc_wake_up_status - wake up all rpc_tasks and set their status value. |
@@ -572,6 +576,7 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | |||
572 | spin_unlock(&queue->lock); | 576 | spin_unlock(&queue->lock); |
573 | rcu_read_unlock_bh(); | 577 | rcu_read_unlock_bh(); |
574 | } | 578 | } |
579 | EXPORT_SYMBOL_GPL(rpc_wake_up_status); | ||
575 | 580 | ||
576 | static void __rpc_atrun(struct rpc_task *task) | 581 | static void __rpc_atrun(struct rpc_task *task) |
577 | { | 582 | { |
@@ -586,6 +591,7 @@ void rpc_delay(struct rpc_task *task, unsigned long delay) | |||
586 | task->tk_timeout = delay; | 591 | task->tk_timeout = delay; |
587 | rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); | 592 | rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); |
588 | } | 593 | } |
594 | EXPORT_SYMBOL_GPL(rpc_delay); | ||
589 | 595 | ||
590 | /* | 596 | /* |
591 | * Helper to call task->tk_ops->rpc_call_prepare | 597 | * Helper to call task->tk_ops->rpc_call_prepare |
@@ -614,7 +620,7 @@ void rpc_exit_task(struct rpc_task *task) | |||
614 | } | 620 | } |
615 | } | 621 | } |
616 | } | 622 | } |
617 | EXPORT_SYMBOL(rpc_exit_task); | 623 | EXPORT_SYMBOL_GPL(rpc_exit_task); |
618 | 624 | ||
619 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | 625 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) |
620 | { | 626 | { |
@@ -808,39 +814,49 @@ EXPORT_SYMBOL_GPL(rpc_free); | |||
808 | /* | 814 | /* |
809 | * Creation and deletion of RPC task structures | 815 | * Creation and deletion of RPC task structures |
810 | */ | 816 | */ |
811 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) | 817 | static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) |
812 | { | 818 | { |
813 | memset(task, 0, sizeof(*task)); | 819 | memset(task, 0, sizeof(*task)); |
814 | setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, | 820 | setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, |
815 | (unsigned long)task); | 821 | (unsigned long)task); |
816 | atomic_set(&task->tk_count, 1); | 822 | atomic_set(&task->tk_count, 1); |
817 | task->tk_client = clnt; | 823 | task->tk_flags = task_setup_data->flags; |
818 | task->tk_flags = flags; | 824 | task->tk_ops = task_setup_data->callback_ops; |
819 | task->tk_ops = tk_ops; | 825 | task->tk_calldata = task_setup_data->callback_data; |
820 | if (tk_ops->rpc_call_prepare != NULL) | ||
821 | task->tk_action = rpc_prepare_task; | ||
822 | task->tk_calldata = calldata; | ||
823 | INIT_LIST_HEAD(&task->tk_task); | 826 | INIT_LIST_HEAD(&task->tk_task); |
824 | 827 | ||
825 | /* Initialize retry counters */ | 828 | /* Initialize retry counters */ |
826 | task->tk_garb_retry = 2; | 829 | task->tk_garb_retry = 2; |
827 | task->tk_cred_retry = 2; | 830 | task->tk_cred_retry = 2; |
828 | 831 | ||
829 | task->tk_priority = RPC_PRIORITY_NORMAL; | 832 | task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; |
830 | task->tk_cookie = (unsigned long)current; | 833 | task->tk_owner = current->tgid; |
831 | 834 | ||
832 | /* Initialize workqueue for async tasks */ | 835 | /* Initialize workqueue for async tasks */ |
833 | task->tk_workqueue = rpciod_workqueue; | 836 | task->tk_workqueue = rpciod_workqueue; |
834 | 837 | ||
835 | if (clnt) { | 838 | task->tk_client = task_setup_data->rpc_client; |
836 | kref_get(&clnt->cl_kref); | 839 | if (task->tk_client != NULL) { |
837 | if (clnt->cl_softrtry) | 840 | kref_get(&task->tk_client->cl_kref); |
841 | if (task->tk_client->cl_softrtry) | ||
838 | task->tk_flags |= RPC_TASK_SOFT; | 842 | task->tk_flags |= RPC_TASK_SOFT; |
839 | if (!clnt->cl_intr) | 843 | if (!task->tk_client->cl_intr) |
840 | task->tk_flags |= RPC_TASK_NOINTR; | 844 | task->tk_flags |= RPC_TASK_NOINTR; |
841 | } | 845 | } |
842 | 846 | ||
843 | BUG_ON(task->tk_ops == NULL); | 847 | if (task->tk_ops->rpc_call_prepare != NULL) |
848 | task->tk_action = rpc_prepare_task; | ||
849 | |||
850 | if (task_setup_data->rpc_message != NULL) { | ||
851 | memcpy(&task->tk_msg, task_setup_data->rpc_message, sizeof(task->tk_msg)); | ||
852 | /* Bind the user cred */ | ||
853 | if (task->tk_msg.rpc_cred != NULL) | ||
854 | rpcauth_holdcred(task); | ||
855 | else | ||
856 | rpcauth_bindcred(task); | ||
857 | if (task->tk_action == NULL) | ||
858 | rpc_call_start(task); | ||
859 | } | ||
844 | 860 | ||
845 | /* starting timestamp */ | 861 | /* starting timestamp */ |
846 | task->tk_start = jiffies; | 862 | task->tk_start = jiffies; |
@@ -865,18 +881,22 @@ static void rpc_free_task(struct rcu_head *rcu) | |||
865 | /* | 881 | /* |
866 | * Create a new task for the specified client. | 882 | * Create a new task for the specified client. |
867 | */ | 883 | */ |
868 | struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) | 884 | struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) |
869 | { | 885 | { |
870 | struct rpc_task *task; | 886 | struct rpc_task *task = setup_data->task; |
871 | 887 | unsigned short flags = 0; | |
872 | task = rpc_alloc_task(); | 888 | |
873 | if (!task) | 889 | if (task == NULL) { |
874 | goto out; | 890 | task = rpc_alloc_task(); |
891 | if (task == NULL) | ||
892 | goto out; | ||
893 | flags = RPC_TASK_DYNAMIC; | ||
894 | } | ||
875 | 895 | ||
876 | rpc_init_task(task, clnt, flags, tk_ops, calldata); | 896 | rpc_init_task(task, setup_data); |
877 | 897 | ||
898 | task->tk_flags |= flags; | ||
878 | dprintk("RPC: allocated task %p\n", task); | 899 | dprintk("RPC: allocated task %p\n", task); |
879 | task->tk_flags |= RPC_TASK_DYNAMIC; | ||
880 | out: | 900 | out: |
881 | return task; | 901 | return task; |
882 | } | 902 | } |
@@ -902,7 +922,7 @@ void rpc_put_task(struct rpc_task *task) | |||
902 | call_rcu_bh(&task->u.tk_rcu, rpc_free_task); | 922 | call_rcu_bh(&task->u.tk_rcu, rpc_free_task); |
903 | rpc_release_calldata(tk_ops, calldata); | 923 | rpc_release_calldata(tk_ops, calldata); |
904 | } | 924 | } |
905 | EXPORT_SYMBOL(rpc_put_task); | 925 | EXPORT_SYMBOL_GPL(rpc_put_task); |
906 | 926 | ||
907 | static void rpc_release_task(struct rpc_task *task) | 927 | static void rpc_release_task(struct rpc_task *task) |
908 | { | 928 | { |
@@ -959,6 +979,7 @@ void rpc_killall_tasks(struct rpc_clnt *clnt) | |||
959 | } | 979 | } |
960 | spin_unlock(&clnt->cl_lock); | 980 | spin_unlock(&clnt->cl_lock); |
961 | } | 981 | } |
982 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
962 | 983 | ||
963 | int rpciod_up(void) | 984 | int rpciod_up(void) |
964 | { | 985 | { |
@@ -1038,6 +1059,11 @@ rpc_init_mempool(void) | |||
1038 | goto err_nomem; | 1059 | goto err_nomem; |
1039 | if (!rpciod_start()) | 1060 | if (!rpciod_start()) |
1040 | goto err_nomem; | 1061 | goto err_nomem; |
1062 | /* | ||
1063 | * The following is not strictly a mempool initialisation, | ||
1064 | * but there is no harm in doing it here | ||
1065 | */ | ||
1066 | rpc_init_wait_queue(&delay_queue, "delayq"); | ||
1041 | return 0; | 1067 | return 0; |
1042 | err_nomem: | 1068 | err_nomem: |
1043 | rpc_destroy_mempool(); | 1069 | rpc_destroy_mempool(); |
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 97ac45f034d6..a661a3acb37e 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c | |||
@@ -72,7 +72,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct | |||
72 | struct page **ppage = xdr->pages; | 72 | struct page **ppage = xdr->pages; |
73 | unsigned int len, pglen = xdr->page_len; | 73 | unsigned int len, pglen = xdr->page_len; |
74 | ssize_t copied = 0; | 74 | ssize_t copied = 0; |
75 | int ret; | 75 | size_t ret; |
76 | 76 | ||
77 | len = xdr->head[0].iov_len; | 77 | len = xdr->head[0].iov_len; |
78 | if (base < len) { | 78 | if (base < len) { |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 4d4f3738b688..74df2d358e61 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -118,7 +118,7 @@ struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) | |||
118 | new = kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL); | 118 | new = kcalloc(clnt->cl_maxproc, sizeof(struct rpc_iostats), GFP_KERNEL); |
119 | return new; | 119 | return new; |
120 | } | 120 | } |
121 | EXPORT_SYMBOL(rpc_alloc_iostats); | 121 | EXPORT_SYMBOL_GPL(rpc_alloc_iostats); |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * rpc_free_iostats - release an rpc_iostats structure | 124 | * rpc_free_iostats - release an rpc_iostats structure |
@@ -129,7 +129,7 @@ void rpc_free_iostats(struct rpc_iostats *stats) | |||
129 | { | 129 | { |
130 | kfree(stats); | 130 | kfree(stats); |
131 | } | 131 | } |
132 | EXPORT_SYMBOL(rpc_free_iostats); | 132 | EXPORT_SYMBOL_GPL(rpc_free_iostats); |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * rpc_count_iostats - tally up per-task stats | 135 | * rpc_count_iostats - tally up per-task stats |
@@ -215,7 +215,7 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
215 | metrics->om_execute * MILLISECS_PER_JIFFY); | 215 | metrics->om_execute * MILLISECS_PER_JIFFY); |
216 | } | 216 | } |
217 | } | 217 | } |
218 | EXPORT_SYMBOL(rpc_print_iostats); | 218 | EXPORT_SYMBOL_GPL(rpc_print_iostats); |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Register/unregister RPC proc files | 221 | * Register/unregister RPC proc files |
@@ -241,12 +241,14 @@ rpc_proc_register(struct rpc_stat *statp) | |||
241 | { | 241 | { |
242 | return do_register(statp->program->name, statp, &rpc_proc_fops); | 242 | return do_register(statp->program->name, statp, &rpc_proc_fops); |
243 | } | 243 | } |
244 | EXPORT_SYMBOL_GPL(rpc_proc_register); | ||
244 | 245 | ||
245 | void | 246 | void |
246 | rpc_proc_unregister(const char *name) | 247 | rpc_proc_unregister(const char *name) |
247 | { | 248 | { |
248 | remove_proc_entry(name, proc_net_rpc); | 249 | remove_proc_entry(name, proc_net_rpc); |
249 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); | ||
250 | 252 | ||
251 | struct proc_dir_entry * | 253 | struct proc_dir_entry * |
252 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) | 254 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 33d89e842c85..1a7e309d008b 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -22,45 +22,6 @@ | |||
22 | #include <linux/sunrpc/rpc_pipe_fs.h> | 22 | #include <linux/sunrpc/rpc_pipe_fs.h> |
23 | #include <linux/sunrpc/xprtsock.h> | 23 | #include <linux/sunrpc/xprtsock.h> |
24 | 24 | ||
25 | /* RPC scheduler */ | ||
26 | EXPORT_SYMBOL(rpc_execute); | ||
27 | EXPORT_SYMBOL(rpc_init_task); | ||
28 | EXPORT_SYMBOL(rpc_sleep_on); | ||
29 | EXPORT_SYMBOL(rpc_wake_up_next); | ||
30 | EXPORT_SYMBOL(rpc_wake_up_task); | ||
31 | EXPORT_SYMBOL(rpc_wake_up_status); | ||
32 | |||
33 | /* RPC client functions */ | ||
34 | EXPORT_SYMBOL(rpc_clone_client); | ||
35 | EXPORT_SYMBOL(rpc_bind_new_program); | ||
36 | EXPORT_SYMBOL(rpc_shutdown_client); | ||
37 | EXPORT_SYMBOL(rpc_killall_tasks); | ||
38 | EXPORT_SYMBOL(rpc_call_sync); | ||
39 | EXPORT_SYMBOL(rpc_call_async); | ||
40 | EXPORT_SYMBOL(rpc_call_setup); | ||
41 | EXPORT_SYMBOL(rpc_clnt_sigmask); | ||
42 | EXPORT_SYMBOL(rpc_clnt_sigunmask); | ||
43 | EXPORT_SYMBOL(rpc_delay); | ||
44 | EXPORT_SYMBOL(rpc_restart_call); | ||
45 | EXPORT_SYMBOL(rpc_setbufsize); | ||
46 | EXPORT_SYMBOL(rpc_unlink); | ||
47 | EXPORT_SYMBOL(rpc_wake_up); | ||
48 | EXPORT_SYMBOL(rpc_queue_upcall); | ||
49 | EXPORT_SYMBOL(rpc_mkpipe); | ||
50 | |||
51 | /* Client transport */ | ||
52 | EXPORT_SYMBOL(xprt_set_timeout); | ||
53 | |||
54 | /* Client credential cache */ | ||
55 | EXPORT_SYMBOL(rpcauth_register); | ||
56 | EXPORT_SYMBOL(rpcauth_unregister); | ||
57 | EXPORT_SYMBOL(rpcauth_create); | ||
58 | EXPORT_SYMBOL(rpcauth_lookupcred); | ||
59 | EXPORT_SYMBOL(rpcauth_lookup_credcache); | ||
60 | EXPORT_SYMBOL(rpcauth_destroy_credcache); | ||
61 | EXPORT_SYMBOL(rpcauth_init_credcache); | ||
62 | EXPORT_SYMBOL(put_rpccred); | ||
63 | |||
64 | /* RPC server stuff */ | 25 | /* RPC server stuff */ |
65 | EXPORT_SYMBOL(svc_create); | 26 | EXPORT_SYMBOL(svc_create); |
66 | EXPORT_SYMBOL(svc_create_thread); | 27 | EXPORT_SYMBOL(svc_create_thread); |
@@ -81,8 +42,6 @@ EXPORT_SYMBOL(svc_set_client); | |||
81 | 42 | ||
82 | /* RPC statistics */ | 43 | /* RPC statistics */ |
83 | #ifdef CONFIG_PROC_FS | 44 | #ifdef CONFIG_PROC_FS |
84 | EXPORT_SYMBOL(rpc_proc_register); | ||
85 | EXPORT_SYMBOL(rpc_proc_unregister); | ||
86 | EXPORT_SYMBOL(svc_proc_register); | 45 | EXPORT_SYMBOL(svc_proc_register); |
87 | EXPORT_SYMBOL(svc_proc_unregister); | 46 | EXPORT_SYMBOL(svc_proc_unregister); |
88 | EXPORT_SYMBOL(svc_seq_show); | 47 | EXPORT_SYMBOL(svc_seq_show); |
@@ -105,31 +64,6 @@ EXPORT_SYMBOL(qword_get); | |||
105 | EXPORT_SYMBOL(svcauth_unix_purge); | 64 | EXPORT_SYMBOL(svcauth_unix_purge); |
106 | EXPORT_SYMBOL(unix_domain_find); | 65 | EXPORT_SYMBOL(unix_domain_find); |
107 | 66 | ||
108 | /* Generic XDR */ | ||
109 | EXPORT_SYMBOL(xdr_encode_string); | ||
110 | EXPORT_SYMBOL(xdr_decode_string_inplace); | ||
111 | EXPORT_SYMBOL(xdr_decode_netobj); | ||
112 | EXPORT_SYMBOL(xdr_encode_netobj); | ||
113 | EXPORT_SYMBOL(xdr_encode_pages); | ||
114 | EXPORT_SYMBOL(xdr_inline_pages); | ||
115 | EXPORT_SYMBOL(xdr_shift_buf); | ||
116 | EXPORT_SYMBOL(xdr_encode_word); | ||
117 | EXPORT_SYMBOL(xdr_decode_word); | ||
118 | EXPORT_SYMBOL(xdr_encode_array2); | ||
119 | EXPORT_SYMBOL(xdr_decode_array2); | ||
120 | EXPORT_SYMBOL(xdr_buf_from_iov); | ||
121 | EXPORT_SYMBOL(xdr_buf_subsegment); | ||
122 | EXPORT_SYMBOL(xdr_buf_read_netobj); | ||
123 | EXPORT_SYMBOL(read_bytes_from_xdr_buf); | ||
124 | |||
125 | /* Debugging symbols */ | ||
126 | #ifdef RPC_DEBUG | ||
127 | EXPORT_SYMBOL(rpc_debug); | ||
128 | EXPORT_SYMBOL(nfs_debug); | ||
129 | EXPORT_SYMBOL(nfsd_debug); | ||
130 | EXPORT_SYMBOL(nlm_debug); | ||
131 | #endif | ||
132 | |||
133 | extern struct cache_detail ip_map_cache, unix_gid_cache; | 67 | extern struct cache_detail ip_map_cache, unix_gid_cache; |
134 | 68 | ||
135 | static int __init | 69 | static int __init |
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 2be714e9b382..bada7de0c2fc 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -23,9 +23,16 @@ | |||
23 | * Declare the debug flags here | 23 | * Declare the debug flags here |
24 | */ | 24 | */ |
25 | unsigned int rpc_debug; | 25 | unsigned int rpc_debug; |
26 | EXPORT_SYMBOL_GPL(rpc_debug); | ||
27 | |||
26 | unsigned int nfs_debug; | 28 | unsigned int nfs_debug; |
29 | EXPORT_SYMBOL_GPL(nfs_debug); | ||
30 | |||
27 | unsigned int nfsd_debug; | 31 | unsigned int nfsd_debug; |
32 | EXPORT_SYMBOL_GPL(nfsd_debug); | ||
33 | |||
28 | unsigned int nlm_debug; | 34 | unsigned int nlm_debug; |
35 | EXPORT_SYMBOL_GPL(nlm_debug); | ||
29 | 36 | ||
30 | #ifdef RPC_DEBUG | 37 | #ifdef RPC_DEBUG |
31 | 38 | ||
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index fdc5e6d7562b..54264062ea69 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -28,6 +28,7 @@ xdr_encode_netobj(__be32 *p, const struct xdr_netobj *obj) | |||
28 | memcpy(p, obj->data, obj->len); | 28 | memcpy(p, obj->data, obj->len); |
29 | return p + XDR_QUADLEN(obj->len); | 29 | return p + XDR_QUADLEN(obj->len); |
30 | } | 30 | } |
31 | EXPORT_SYMBOL(xdr_encode_netobj); | ||
31 | 32 | ||
32 | __be32 * | 33 | __be32 * |
33 | xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj) | 34 | xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj) |
@@ -40,6 +41,7 @@ xdr_decode_netobj(__be32 *p, struct xdr_netobj *obj) | |||
40 | obj->data = (u8 *) p; | 41 | obj->data = (u8 *) p; |
41 | return p + XDR_QUADLEN(len); | 42 | return p + XDR_QUADLEN(len); |
42 | } | 43 | } |
44 | EXPORT_SYMBOL(xdr_decode_netobj); | ||
43 | 45 | ||
44 | /** | 46 | /** |
45 | * xdr_encode_opaque_fixed - Encode fixed length opaque data | 47 | * xdr_encode_opaque_fixed - Encode fixed length opaque data |
@@ -91,6 +93,7 @@ xdr_encode_string(__be32 *p, const char *string) | |||
91 | { | 93 | { |
92 | return xdr_encode_array(p, string, strlen(string)); | 94 | return xdr_encode_array(p, string, strlen(string)); |
93 | } | 95 | } |
96 | EXPORT_SYMBOL(xdr_encode_string); | ||
94 | 97 | ||
95 | __be32 * | 98 | __be32 * |
96 | xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen) | 99 | xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen) |
@@ -103,6 +106,7 @@ xdr_decode_string_inplace(__be32 *p, char **sp, int *lenp, int maxlen) | |||
103 | *sp = (char *) p; | 106 | *sp = (char *) p; |
104 | return p + XDR_QUADLEN(len); | 107 | return p + XDR_QUADLEN(len); |
105 | } | 108 | } |
109 | EXPORT_SYMBOL(xdr_decode_string_inplace); | ||
106 | 110 | ||
107 | void | 111 | void |
108 | xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base, | 112 | xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base, |
@@ -130,6 +134,7 @@ xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base, | |||
130 | xdr->buflen += len; | 134 | xdr->buflen += len; |
131 | xdr->len += len; | 135 | xdr->len += len; |
132 | } | 136 | } |
137 | EXPORT_SYMBOL(xdr_encode_pages); | ||
133 | 138 | ||
134 | void | 139 | void |
135 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | 140 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, |
@@ -151,7 +156,7 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | |||
151 | 156 | ||
152 | xdr->buflen += len; | 157 | xdr->buflen += len; |
153 | } | 158 | } |
154 | 159 | EXPORT_SYMBOL(xdr_inline_pages); | |
155 | 160 | ||
156 | /* | 161 | /* |
157 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf | 162 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf |
@@ -418,6 +423,7 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len) | |||
418 | { | 423 | { |
419 | xdr_shrink_bufhead(buf, len); | 424 | xdr_shrink_bufhead(buf, len); |
420 | } | 425 | } |
426 | EXPORT_SYMBOL(xdr_shift_buf); | ||
421 | 427 | ||
422 | /** | 428 | /** |
423 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. | 429 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. |
@@ -639,6 +645,7 @@ xdr_buf_from_iov(struct kvec *iov, struct xdr_buf *buf) | |||
639 | buf->page_len = 0; | 645 | buf->page_len = 0; |
640 | buf->buflen = buf->len = iov->iov_len; | 646 | buf->buflen = buf->len = iov->iov_len; |
641 | } | 647 | } |
648 | EXPORT_SYMBOL(xdr_buf_from_iov); | ||
642 | 649 | ||
643 | /* Sets subbuf to the portion of buf of length len beginning base bytes | 650 | /* Sets subbuf to the portion of buf of length len beginning base bytes |
644 | * from the start of buf. Returns -1 if base of length are out of bounds. */ | 651 | * from the start of buf. Returns -1 if base of length are out of bounds. */ |
@@ -687,6 +694,7 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | |||
687 | return -1; | 694 | return -1; |
688 | return 0; | 695 | return 0; |
689 | } | 696 | } |
697 | EXPORT_SYMBOL(xdr_buf_subsegment); | ||
690 | 698 | ||
691 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) | 699 | static void __read_bytes_from_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) |
692 | { | 700 | { |
@@ -717,6 +725,7 @@ int read_bytes_from_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, u | |||
717 | __read_bytes_from_xdr_buf(&subbuf, obj, len); | 725 | __read_bytes_from_xdr_buf(&subbuf, obj, len); |
718 | return 0; | 726 | return 0; |
719 | } | 727 | } |
728 | EXPORT_SYMBOL(read_bytes_from_xdr_buf); | ||
720 | 729 | ||
721 | static void __write_bytes_to_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) | 730 | static void __write_bytes_to_xdr_buf(struct xdr_buf *subbuf, void *obj, unsigned int len) |
722 | { | 731 | { |
@@ -760,6 +769,7 @@ xdr_decode_word(struct xdr_buf *buf, unsigned int base, u32 *obj) | |||
760 | *obj = ntohl(raw); | 769 | *obj = ntohl(raw); |
761 | return 0; | 770 | return 0; |
762 | } | 771 | } |
772 | EXPORT_SYMBOL(xdr_decode_word); | ||
763 | 773 | ||
764 | int | 774 | int |
765 | xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj) | 775 | xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj) |
@@ -768,6 +778,7 @@ xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj) | |||
768 | 778 | ||
769 | return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj)); | 779 | return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj)); |
770 | } | 780 | } |
781 | EXPORT_SYMBOL(xdr_encode_word); | ||
771 | 782 | ||
772 | /* If the netobj starting offset bytes from the start of xdr_buf is contained | 783 | /* If the netobj starting offset bytes from the start of xdr_buf is contained |
773 | * entirely in the head or the tail, set object to point to it; otherwise | 784 | * entirely in the head or the tail, set object to point to it; otherwise |
@@ -805,6 +816,7 @@ int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned in | |||
805 | __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len); | 816 | __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len); |
806 | return 0; | 817 | return 0; |
807 | } | 818 | } |
819 | EXPORT_SYMBOL(xdr_buf_read_netobj); | ||
808 | 820 | ||
809 | /* Returns 0 on success, or else a negative error code. */ | 821 | /* Returns 0 on success, or else a negative error code. */ |
810 | static int | 822 | static int |
@@ -1010,6 +1022,7 @@ xdr_decode_array2(struct xdr_buf *buf, unsigned int base, | |||
1010 | 1022 | ||
1011 | return xdr_xcode_array2(buf, base, desc, 0); | 1023 | return xdr_xcode_array2(buf, base, desc, 0); |
1012 | } | 1024 | } |
1025 | EXPORT_SYMBOL(xdr_decode_array2); | ||
1013 | 1026 | ||
1014 | int | 1027 | int |
1015 | xdr_encode_array2(struct xdr_buf *buf, unsigned int base, | 1028 | xdr_encode_array2(struct xdr_buf *buf, unsigned int base, |
@@ -1021,6 +1034,7 @@ xdr_encode_array2(struct xdr_buf *buf, unsigned int base, | |||
1021 | 1034 | ||
1022 | return xdr_xcode_array2(buf, base, desc, 1); | 1035 | return xdr_xcode_array2(buf, base, desc, 1); |
1023 | } | 1036 | } |
1037 | EXPORT_SYMBOL(xdr_encode_array2); | ||
1024 | 1038 | ||
1025 | int | 1039 | int |
1026 | xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, | 1040 | xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index fb92f51405c5..cfcade906a56 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -501,9 +501,10 @@ EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); | |||
501 | void xprt_set_retrans_timeout_rtt(struct rpc_task *task) | 501 | void xprt_set_retrans_timeout_rtt(struct rpc_task *task) |
502 | { | 502 | { |
503 | int timer = task->tk_msg.rpc_proc->p_timer; | 503 | int timer = task->tk_msg.rpc_proc->p_timer; |
504 | struct rpc_rtt *rtt = task->tk_client->cl_rtt; | 504 | struct rpc_clnt *clnt = task->tk_client; |
505 | struct rpc_rtt *rtt = clnt->cl_rtt; | ||
505 | struct rpc_rqst *req = task->tk_rqstp; | 506 | struct rpc_rqst *req = task->tk_rqstp; |
506 | unsigned long max_timeout = req->rq_xprt->timeout.to_maxval; | 507 | unsigned long max_timeout = clnt->cl_timeout->to_maxval; |
507 | 508 | ||
508 | task->tk_timeout = rpc_calc_rto(rtt, timer); | 509 | task->tk_timeout = rpc_calc_rto(rtt, timer); |
509 | task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries; | 510 | task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries; |
@@ -514,7 +515,7 @@ EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt); | |||
514 | 515 | ||
515 | static void xprt_reset_majortimeo(struct rpc_rqst *req) | 516 | static void xprt_reset_majortimeo(struct rpc_rqst *req) |
516 | { | 517 | { |
517 | struct rpc_timeout *to = &req->rq_xprt->timeout; | 518 | const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; |
518 | 519 | ||
519 | req->rq_majortimeo = req->rq_timeout; | 520 | req->rq_majortimeo = req->rq_timeout; |
520 | if (to->to_exponential) | 521 | if (to->to_exponential) |
@@ -534,7 +535,7 @@ static void xprt_reset_majortimeo(struct rpc_rqst *req) | |||
534 | int xprt_adjust_timeout(struct rpc_rqst *req) | 535 | int xprt_adjust_timeout(struct rpc_rqst *req) |
535 | { | 536 | { |
536 | struct rpc_xprt *xprt = req->rq_xprt; | 537 | struct rpc_xprt *xprt = req->rq_xprt; |
537 | struct rpc_timeout *to = &xprt->timeout; | 538 | const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout; |
538 | int status = 0; | 539 | int status = 0; |
539 | 540 | ||
540 | if (time_before(jiffies, req->rq_majortimeo)) { | 541 | if (time_before(jiffies, req->rq_majortimeo)) { |
@@ -568,17 +569,17 @@ static void xprt_autoclose(struct work_struct *work) | |||
568 | struct rpc_xprt *xprt = | 569 | struct rpc_xprt *xprt = |
569 | container_of(work, struct rpc_xprt, task_cleanup); | 570 | container_of(work, struct rpc_xprt, task_cleanup); |
570 | 571 | ||
571 | xprt_disconnect(xprt); | ||
572 | xprt->ops->close(xprt); | 572 | xprt->ops->close(xprt); |
573 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
573 | xprt_release_write(xprt, NULL); | 574 | xprt_release_write(xprt, NULL); |
574 | } | 575 | } |
575 | 576 | ||
576 | /** | 577 | /** |
577 | * xprt_disconnect - mark a transport as disconnected | 578 | * xprt_disconnect_done - mark a transport as disconnected |
578 | * @xprt: transport to flag for disconnect | 579 | * @xprt: transport to flag for disconnect |
579 | * | 580 | * |
580 | */ | 581 | */ |
581 | void xprt_disconnect(struct rpc_xprt *xprt) | 582 | void xprt_disconnect_done(struct rpc_xprt *xprt) |
582 | { | 583 | { |
583 | dprintk("RPC: disconnected transport %p\n", xprt); | 584 | dprintk("RPC: disconnected transport %p\n", xprt); |
584 | spin_lock_bh(&xprt->transport_lock); | 585 | spin_lock_bh(&xprt->transport_lock); |
@@ -586,7 +587,26 @@ void xprt_disconnect(struct rpc_xprt *xprt) | |||
586 | xprt_wake_pending_tasks(xprt, -ENOTCONN); | 587 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
587 | spin_unlock_bh(&xprt->transport_lock); | 588 | spin_unlock_bh(&xprt->transport_lock); |
588 | } | 589 | } |
589 | EXPORT_SYMBOL_GPL(xprt_disconnect); | 590 | EXPORT_SYMBOL_GPL(xprt_disconnect_done); |
591 | |||
592 | /** | ||
593 | * xprt_force_disconnect - force a transport to disconnect | ||
594 | * @xprt: transport to disconnect | ||
595 | * | ||
596 | */ | ||
597 | void xprt_force_disconnect(struct rpc_xprt *xprt) | ||
598 | { | ||
599 | /* Don't race with the test_bit() in xprt_clear_locked() */ | ||
600 | spin_lock_bh(&xprt->transport_lock); | ||
601 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
602 | /* Try to schedule an autoclose RPC call */ | ||
603 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | ||
604 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | ||
605 | else if (xprt->snd_task != NULL) | ||
606 | rpc_wake_up_task(xprt->snd_task); | ||
607 | spin_unlock_bh(&xprt->transport_lock); | ||
608 | } | ||
609 | EXPORT_SYMBOL_GPL(xprt_force_disconnect); | ||
590 | 610 | ||
591 | static void | 611 | static void |
592 | xprt_init_autodisconnect(unsigned long data) | 612 | xprt_init_autodisconnect(unsigned long data) |
@@ -909,7 +929,7 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
909 | { | 929 | { |
910 | struct rpc_rqst *req = task->tk_rqstp; | 930 | struct rpc_rqst *req = task->tk_rqstp; |
911 | 931 | ||
912 | req->rq_timeout = xprt->timeout.to_initval; | 932 | req->rq_timeout = task->tk_client->cl_timeout->to_initval; |
913 | req->rq_task = task; | 933 | req->rq_task = task; |
914 | req->rq_xprt = xprt; | 934 | req->rq_xprt = xprt; |
915 | req->rq_buffer = NULL; | 935 | req->rq_buffer = NULL; |
@@ -959,22 +979,6 @@ void xprt_release(struct rpc_task *task) | |||
959 | } | 979 | } |
960 | 980 | ||
961 | /** | 981 | /** |
962 | * xprt_set_timeout - set constant RPC timeout | ||
963 | * @to: RPC timeout parameters to set up | ||
964 | * @retr: number of retries | ||
965 | * @incr: amount of increase after each retry | ||
966 | * | ||
967 | */ | ||
968 | void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr) | ||
969 | { | ||
970 | to->to_initval = | ||
971 | to->to_increment = incr; | ||
972 | to->to_maxval = to->to_initval + (incr * retr); | ||
973 | to->to_retries = retr; | ||
974 | to->to_exponential = 0; | ||
975 | } | ||
976 | |||
977 | /** | ||
978 | * xprt_create_transport - create an RPC transport | 982 | * xprt_create_transport - create an RPC transport |
979 | * @args: rpc transport creation arguments | 983 | * @args: rpc transport creation arguments |
980 | * | 984 | * |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 1aa1580cda6d..e55427f73dfe 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -83,7 +83,7 @@ static const char transfertypes[][12] = { | |||
83 | */ | 83 | */ |
84 | 84 | ||
85 | static int | 85 | static int |
86 | rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, int pos, | 86 | rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos, |
87 | enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg, int nsegs) | 87 | enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg, int nsegs) |
88 | { | 88 | { |
89 | int len, n = 0, p; | 89 | int len, n = 0, p; |
@@ -169,7 +169,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | |||
169 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | 169 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); |
170 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_task->tk_xprt); | 170 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_task->tk_xprt); |
171 | int nsegs, nchunks = 0; | 171 | int nsegs, nchunks = 0; |
172 | int pos; | 172 | unsigned int pos; |
173 | struct rpcrdma_mr_seg *seg = req->rl_segments; | 173 | struct rpcrdma_mr_seg *seg = req->rl_segments; |
174 | struct rpcrdma_read_chunk *cur_rchunk = NULL; | 174 | struct rpcrdma_read_chunk *cur_rchunk = NULL; |
175 | struct rpcrdma_write_array *warray = NULL; | 175 | struct rpcrdma_write_array *warray = NULL; |
@@ -213,7 +213,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | |||
213 | (__be32 *)&cur_rchunk->rc_target.rs_offset, | 213 | (__be32 *)&cur_rchunk->rc_target.rs_offset, |
214 | seg->mr_base); | 214 | seg->mr_base); |
215 | dprintk("RPC: %s: read chunk " | 215 | dprintk("RPC: %s: read chunk " |
216 | "elem %d@0x%llx:0x%x pos %d (%s)\n", __func__, | 216 | "elem %d@0x%llx:0x%x pos %u (%s)\n", __func__, |
217 | seg->mr_len, (unsigned long long)seg->mr_base, | 217 | seg->mr_len, (unsigned long long)seg->mr_base, |
218 | seg->mr_rkey, pos, n < nsegs ? "more" : "last"); | 218 | seg->mr_rkey, pos, n < nsegs ? "more" : "last"); |
219 | cur_rchunk++; | 219 | cur_rchunk++; |
@@ -552,7 +552,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
552 | * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) | 552 | * RDMA'd by server. See map at rpcrdma_create_chunks()! :-) |
553 | */ | 553 | */ |
554 | static int | 554 | static int |
555 | rpcrdma_count_chunks(struct rpcrdma_rep *rep, int max, int wrchunk, __be32 **iptrp) | 555 | rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __be32 **iptrp) |
556 | { | 556 | { |
557 | unsigned int i, total_len; | 557 | unsigned int i, total_len; |
558 | struct rpcrdma_write_chunk *cur_wchunk; | 558 | struct rpcrdma_write_chunk *cur_wchunk; |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 6f2112dd9f78..02c522c17de5 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -212,12 +212,16 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt) | |||
212 | static void | 212 | static void |
213 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) | 213 | xprt_rdma_free_addresses(struct rpc_xprt *xprt) |
214 | { | 214 | { |
215 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | 215 | unsigned int i; |
216 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | 216 | |
217 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | 217 | for (i = 0; i < RPC_DISPLAY_MAX; i++) |
218 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_ADDR]); | 218 | switch (i) { |
219 | kfree(xprt->address_strings[RPC_DISPLAY_HEX_PORT]); | 219 | case RPC_DISPLAY_PROTO: |
220 | kfree(xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR]); | 220 | case RPC_DISPLAY_NETID: |
221 | continue; | ||
222 | default: | ||
223 | kfree(xprt->address_strings[i]); | ||
224 | } | ||
221 | } | 225 | } |
222 | 226 | ||
223 | static void | 227 | static void |
@@ -289,6 +293,11 @@ xprt_rdma_destroy(struct rpc_xprt *xprt) | |||
289 | module_put(THIS_MODULE); | 293 | module_put(THIS_MODULE); |
290 | } | 294 | } |
291 | 295 | ||
296 | static const struct rpc_timeout xprt_rdma_default_timeout = { | ||
297 | .to_initval = 60 * HZ, | ||
298 | .to_maxval = 60 * HZ, | ||
299 | }; | ||
300 | |||
292 | /** | 301 | /** |
293 | * xprt_setup_rdma - Set up transport to use RDMA | 302 | * xprt_setup_rdma - Set up transport to use RDMA |
294 | * | 303 | * |
@@ -327,7 +336,7 @@ xprt_setup_rdma(struct xprt_create *args) | |||
327 | } | 336 | } |
328 | 337 | ||
329 | /* 60 second timeout, no retries */ | 338 | /* 60 second timeout, no retries */ |
330 | xprt_set_timeout(&xprt->timeout, 0, 60UL * HZ); | 339 | xprt->timeout = &xprt_rdma_default_timeout; |
331 | xprt->bind_timeout = (60U * HZ); | 340 | xprt->bind_timeout = (60U * HZ); |
332 | xprt->connect_timeout = (60U * HZ); | 341 | xprt->connect_timeout = (60U * HZ); |
333 | xprt->reestablish_timeout = (5U * HZ); | 342 | xprt->reestablish_timeout = (5U * HZ); |
@@ -449,7 +458,7 @@ xprt_rdma_close(struct rpc_xprt *xprt) | |||
449 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | 458 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); |
450 | 459 | ||
451 | dprintk("RPC: %s: closing\n", __func__); | 460 | dprintk("RPC: %s: closing\n", __func__); |
452 | xprt_disconnect(xprt); | 461 | xprt_disconnect_done(xprt); |
453 | (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); | 462 | (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); |
454 | } | 463 | } |
455 | 464 | ||
@@ -682,7 +691,7 @@ xprt_rdma_send_request(struct rpc_task *task) | |||
682 | } | 691 | } |
683 | 692 | ||
684 | if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { | 693 | if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) { |
685 | xprt_disconnect(xprt); | 694 | xprt_disconnect_done(xprt); |
686 | return -ENOTCONN; /* implies disconnect */ | 695 | return -ENOTCONN; /* implies disconnect */ |
687 | } | 696 | } |
688 | 697 | ||
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 44b0fb942e8d..ffbf22a1d2ca 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -522,7 +522,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | |||
522 | struct rpcrdma_create_data_internal *cdata) | 522 | struct rpcrdma_create_data_internal *cdata) |
523 | { | 523 | { |
524 | struct ib_device_attr devattr; | 524 | struct ib_device_attr devattr; |
525 | int rc; | 525 | int rc, err; |
526 | 526 | ||
527 | rc = ib_query_device(ia->ri_id->device, &devattr); | 527 | rc = ib_query_device(ia->ri_id->device, &devattr); |
528 | if (rc) { | 528 | if (rc) { |
@@ -648,8 +648,10 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | |||
648 | return 0; | 648 | return 0; |
649 | 649 | ||
650 | out2: | 650 | out2: |
651 | if (ib_destroy_cq(ep->rep_cq)) | 651 | err = ib_destroy_cq(ep->rep_cq); |
652 | ; | 652 | if (err) |
653 | dprintk("RPC: %s: ib_destroy_cq returned %i\n", | ||
654 | __func__, err); | ||
653 | out1: | 655 | out1: |
654 | return rc; | 656 | return rc; |
655 | } | 657 | } |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 6fa52f44de0f..30e7ac243a90 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -280,7 +280,9 @@ static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt) | |||
280 | return (struct sockaddr_in6 *) &xprt->addr; | 280 | return (struct sockaddr_in6 *) &xprt->addr; |
281 | } | 281 | } |
282 | 282 | ||
283 | static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | 283 | static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt, |
284 | const char *protocol, | ||
285 | const char *netid) | ||
284 | { | 286 | { |
285 | struct sockaddr_in *addr = xs_addr_in(xprt); | 287 | struct sockaddr_in *addr = xs_addr_in(xprt); |
286 | char *buf; | 288 | char *buf; |
@@ -299,21 +301,14 @@ static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | |||
299 | } | 301 | } |
300 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | 302 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; |
301 | 303 | ||
302 | buf = kzalloc(8, GFP_KERNEL); | 304 | xprt->address_strings[RPC_DISPLAY_PROTO] = protocol; |
303 | if (buf) { | ||
304 | if (xprt->prot == IPPROTO_UDP) | ||
305 | snprintf(buf, 8, "udp"); | ||
306 | else | ||
307 | snprintf(buf, 8, "tcp"); | ||
308 | } | ||
309 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
310 | 305 | ||
311 | buf = kzalloc(48, GFP_KERNEL); | 306 | buf = kzalloc(48, GFP_KERNEL); |
312 | if (buf) { | 307 | if (buf) { |
313 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", | 308 | snprintf(buf, 48, "addr="NIPQUAD_FMT" port=%u proto=%s", |
314 | NIPQUAD(addr->sin_addr.s_addr), | 309 | NIPQUAD(addr->sin_addr.s_addr), |
315 | ntohs(addr->sin_port), | 310 | ntohs(addr->sin_port), |
316 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | 311 | protocol); |
317 | } | 312 | } |
318 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | 313 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; |
319 | 314 | ||
@@ -340,12 +335,12 @@ static void xs_format_ipv4_peer_addresses(struct rpc_xprt *xprt) | |||
340 | } | 335 | } |
341 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | 336 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; |
342 | 337 | ||
343 | xprt->address_strings[RPC_DISPLAY_NETID] = | 338 | xprt->address_strings[RPC_DISPLAY_NETID] = netid; |
344 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
345 | RPCBIND_NETID_UDP : RPCBIND_NETID_TCP, GFP_KERNEL); | ||
346 | } | 339 | } |
347 | 340 | ||
348 | static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | 341 | static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt, |
342 | const char *protocol, | ||
343 | const char *netid) | ||
349 | { | 344 | { |
350 | struct sockaddr_in6 *addr = xs_addr_in6(xprt); | 345 | struct sockaddr_in6 *addr = xs_addr_in6(xprt); |
351 | char *buf; | 346 | char *buf; |
@@ -364,21 +359,14 @@ static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | |||
364 | } | 359 | } |
365 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | 360 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; |
366 | 361 | ||
367 | buf = kzalloc(8, GFP_KERNEL); | 362 | xprt->address_strings[RPC_DISPLAY_PROTO] = protocol; |
368 | if (buf) { | ||
369 | if (xprt->prot == IPPROTO_UDP) | ||
370 | snprintf(buf, 8, "udp"); | ||
371 | else | ||
372 | snprintf(buf, 8, "tcp"); | ||
373 | } | ||
374 | xprt->address_strings[RPC_DISPLAY_PROTO] = buf; | ||
375 | 363 | ||
376 | buf = kzalloc(64, GFP_KERNEL); | 364 | buf = kzalloc(64, GFP_KERNEL); |
377 | if (buf) { | 365 | if (buf) { |
378 | snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", | 366 | snprintf(buf, 64, "addr="NIP6_FMT" port=%u proto=%s", |
379 | NIP6(addr->sin6_addr), | 367 | NIP6(addr->sin6_addr), |
380 | ntohs(addr->sin6_port), | 368 | ntohs(addr->sin6_port), |
381 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | 369 | protocol); |
382 | } | 370 | } |
383 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | 371 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; |
384 | 372 | ||
@@ -405,17 +393,21 @@ static void xs_format_ipv6_peer_addresses(struct rpc_xprt *xprt) | |||
405 | } | 393 | } |
406 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; | 394 | xprt->address_strings[RPC_DISPLAY_UNIVERSAL_ADDR] = buf; |
407 | 395 | ||
408 | xprt->address_strings[RPC_DISPLAY_NETID] = | 396 | xprt->address_strings[RPC_DISPLAY_NETID] = netid; |
409 | kstrdup(xprt->prot == IPPROTO_UDP ? | ||
410 | RPCBIND_NETID_UDP6 : RPCBIND_NETID_TCP6, GFP_KERNEL); | ||
411 | } | 397 | } |
412 | 398 | ||
413 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) | 399 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) |
414 | { | 400 | { |
415 | int i; | 401 | unsigned int i; |
416 | 402 | ||
417 | for (i = 0; i < RPC_DISPLAY_MAX; i++) | 403 | for (i = 0; i < RPC_DISPLAY_MAX; i++) |
418 | kfree(xprt->address_strings[i]); | 404 | switch (i) { |
405 | case RPC_DISPLAY_PROTO: | ||
406 | case RPC_DISPLAY_NETID: | ||
407 | continue; | ||
408 | default: | ||
409 | kfree(xprt->address_strings[i]); | ||
410 | } | ||
419 | } | 411 | } |
420 | 412 | ||
421 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) | 413 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) |
@@ -614,6 +606,22 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
614 | return status; | 606 | return status; |
615 | } | 607 | } |
616 | 608 | ||
609 | /** | ||
610 | * xs_tcp_shutdown - gracefully shut down a TCP socket | ||
611 | * @xprt: transport | ||
612 | * | ||
613 | * Initiates a graceful shutdown of the TCP socket by calling the | ||
614 | * equivalent of shutdown(SHUT_WR); | ||
615 | */ | ||
616 | static void xs_tcp_shutdown(struct rpc_xprt *xprt) | ||
617 | { | ||
618 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | ||
619 | struct socket *sock = transport->sock; | ||
620 | |||
621 | if (sock != NULL) | ||
622 | kernel_sock_shutdown(sock, SHUT_WR); | ||
623 | } | ||
624 | |||
617 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | 625 | static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) |
618 | { | 626 | { |
619 | u32 reclen = buf->len - sizeof(rpc_fraghdr); | 627 | u32 reclen = buf->len - sizeof(rpc_fraghdr); |
@@ -691,7 +699,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
691 | default: | 699 | default: |
692 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | 700 | dprintk("RPC: sendmsg returned unrecognized error %d\n", |
693 | -status); | 701 | -status); |
694 | xprt_disconnect(xprt); | 702 | xs_tcp_shutdown(xprt); |
695 | break; | 703 | break; |
696 | } | 704 | } |
697 | 705 | ||
@@ -759,7 +767,9 @@ static void xs_close(struct rpc_xprt *xprt) | |||
759 | clear_close_wait: | 767 | clear_close_wait: |
760 | smp_mb__before_clear_bit(); | 768 | smp_mb__before_clear_bit(); |
761 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 769 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
770 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
762 | smp_mb__after_clear_bit(); | 771 | smp_mb__after_clear_bit(); |
772 | xprt_disconnect_done(xprt); | ||
763 | } | 773 | } |
764 | 774 | ||
765 | /** | 775 | /** |
@@ -775,7 +785,6 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
775 | 785 | ||
776 | cancel_rearming_delayed_work(&transport->connect_worker); | 786 | cancel_rearming_delayed_work(&transport->connect_worker); |
777 | 787 | ||
778 | xprt_disconnect(xprt); | ||
779 | xs_close(xprt); | 788 | xs_close(xprt); |
780 | xs_free_peer_addresses(xprt); | 789 | xs_free_peer_addresses(xprt); |
781 | kfree(xprt->slot); | 790 | kfree(xprt->slot); |
@@ -886,7 +895,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
886 | /* Sanity check of the record length */ | 895 | /* Sanity check of the record length */ |
887 | if (unlikely(transport->tcp_reclen < 4)) { | 896 | if (unlikely(transport->tcp_reclen < 4)) { |
888 | dprintk("RPC: invalid TCP record fragment length\n"); | 897 | dprintk("RPC: invalid TCP record fragment length\n"); |
889 | xprt_disconnect(xprt); | 898 | xprt_force_disconnect(xprt); |
890 | return; | 899 | return; |
891 | } | 900 | } |
892 | dprintk("RPC: reading TCP record fragment of length %d\n", | 901 | dprintk("RPC: reading TCP record fragment of length %d\n", |
@@ -1113,21 +1122,44 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1113 | transport->tcp_flags = | 1122 | transport->tcp_flags = |
1114 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; | 1123 | TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; |
1115 | 1124 | ||
1116 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
1117 | xprt_wake_pending_tasks(xprt, 0); | 1125 | xprt_wake_pending_tasks(xprt, 0); |
1118 | } | 1126 | } |
1119 | spin_unlock_bh(&xprt->transport_lock); | 1127 | spin_unlock_bh(&xprt->transport_lock); |
1120 | break; | 1128 | break; |
1121 | case TCP_SYN_SENT: | 1129 | case TCP_FIN_WAIT1: |
1122 | case TCP_SYN_RECV: | 1130 | /* The client initiated a shutdown of the socket */ |
1131 | xprt->reestablish_timeout = 0; | ||
1132 | set_bit(XPRT_CLOSING, &xprt->state); | ||
1133 | smp_mb__before_clear_bit(); | ||
1134 | clear_bit(XPRT_CONNECTED, &xprt->state); | ||
1135 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
1136 | smp_mb__after_clear_bit(); | ||
1123 | break; | 1137 | break; |
1124 | case TCP_CLOSE_WAIT: | 1138 | case TCP_CLOSE_WAIT: |
1125 | /* Try to schedule an autoclose RPC calls */ | 1139 | /* The server initiated a shutdown of the socket */ |
1126 | set_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1140 | set_bit(XPRT_CLOSING, &xprt->state); |
1127 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) | 1141 | xprt_force_disconnect(xprt); |
1128 | queue_work(rpciod_workqueue, &xprt->task_cleanup); | 1142 | case TCP_SYN_SENT: |
1129 | default: | 1143 | case TCP_CLOSING: |
1130 | xprt_disconnect(xprt); | 1144 | /* |
1145 | * If the server closed down the connection, make sure that | ||
1146 | * we back off before reconnecting | ||
1147 | */ | ||
1148 | if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) | ||
1149 | xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; | ||
1150 | break; | ||
1151 | case TCP_LAST_ACK: | ||
1152 | smp_mb__before_clear_bit(); | ||
1153 | clear_bit(XPRT_CONNECTED, &xprt->state); | ||
1154 | smp_mb__after_clear_bit(); | ||
1155 | break; | ||
1156 | case TCP_CLOSE: | ||
1157 | smp_mb__before_clear_bit(); | ||
1158 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | ||
1159 | clear_bit(XPRT_CLOSING, &xprt->state); | ||
1160 | smp_mb__after_clear_bit(); | ||
1161 | /* Mark transport as closed and wake up all pending tasks */ | ||
1162 | xprt_disconnect_done(xprt); | ||
1131 | } | 1163 | } |
1132 | out: | 1164 | out: |
1133 | read_unlock(&sk->sk_callback_lock); | 1165 | read_unlock(&sk->sk_callback_lock); |
@@ -1279,34 +1311,53 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | |||
1279 | } | 1311 | } |
1280 | } | 1312 | } |
1281 | 1313 | ||
1314 | static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket *sock) | ||
1315 | { | ||
1316 | unsigned short port = transport->port; | ||
1317 | |||
1318 | if (port == 0 && transport->xprt.resvport) | ||
1319 | port = xs_get_random_port(); | ||
1320 | return port; | ||
1321 | } | ||
1322 | |||
1323 | static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket *sock, unsigned short port) | ||
1324 | { | ||
1325 | if (transport->port != 0) | ||
1326 | transport->port = 0; | ||
1327 | if (!transport->xprt.resvport) | ||
1328 | return 0; | ||
1329 | if (port <= xprt_min_resvport || port > xprt_max_resvport) | ||
1330 | return xprt_max_resvport; | ||
1331 | return --port; | ||
1332 | } | ||
1333 | |||
1282 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | 1334 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) |
1283 | { | 1335 | { |
1284 | struct sockaddr_in myaddr = { | 1336 | struct sockaddr_in myaddr = { |
1285 | .sin_family = AF_INET, | 1337 | .sin_family = AF_INET, |
1286 | }; | 1338 | }; |
1287 | struct sockaddr_in *sa; | 1339 | struct sockaddr_in *sa; |
1288 | int err; | 1340 | int err, nloop = 0; |
1289 | unsigned short port = transport->port; | 1341 | unsigned short port = xs_get_srcport(transport, sock); |
1342 | unsigned short last; | ||
1290 | 1343 | ||
1291 | if (!transport->xprt.resvport) | ||
1292 | port = 0; | ||
1293 | sa = (struct sockaddr_in *)&transport->addr; | 1344 | sa = (struct sockaddr_in *)&transport->addr; |
1294 | myaddr.sin_addr = sa->sin_addr; | 1345 | myaddr.sin_addr = sa->sin_addr; |
1295 | do { | 1346 | do { |
1296 | myaddr.sin_port = htons(port); | 1347 | myaddr.sin_port = htons(port); |
1297 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1348 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, |
1298 | sizeof(myaddr)); | 1349 | sizeof(myaddr)); |
1299 | if (!transport->xprt.resvport) | 1350 | if (port == 0) |
1300 | break; | 1351 | break; |
1301 | if (err == 0) { | 1352 | if (err == 0) { |
1302 | transport->port = port; | 1353 | transport->port = port; |
1303 | break; | 1354 | break; |
1304 | } | 1355 | } |
1305 | if (port <= xprt_min_resvport) | 1356 | last = port; |
1306 | port = xprt_max_resvport; | 1357 | port = xs_next_srcport(transport, sock, port); |
1307 | else | 1358 | if (port > last) |
1308 | port--; | 1359 | nloop++; |
1309 | } while (err == -EADDRINUSE && port != transport->port); | 1360 | } while (err == -EADDRINUSE && nloop != 2); |
1310 | dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n", | 1361 | dprintk("RPC: %s "NIPQUAD_FMT":%u: %s (%d)\n", |
1311 | __FUNCTION__, NIPQUAD(myaddr.sin_addr), | 1362 | __FUNCTION__, NIPQUAD(myaddr.sin_addr), |
1312 | port, err ? "failed" : "ok", err); | 1363 | port, err ? "failed" : "ok", err); |
@@ -1319,28 +1370,27 @@ static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | |||
1319 | .sin6_family = AF_INET6, | 1370 | .sin6_family = AF_INET6, |
1320 | }; | 1371 | }; |
1321 | struct sockaddr_in6 *sa; | 1372 | struct sockaddr_in6 *sa; |
1322 | int err; | 1373 | int err, nloop = 0; |
1323 | unsigned short port = transport->port; | 1374 | unsigned short port = xs_get_srcport(transport, sock); |
1375 | unsigned short last; | ||
1324 | 1376 | ||
1325 | if (!transport->xprt.resvport) | ||
1326 | port = 0; | ||
1327 | sa = (struct sockaddr_in6 *)&transport->addr; | 1377 | sa = (struct sockaddr_in6 *)&transport->addr; |
1328 | myaddr.sin6_addr = sa->sin6_addr; | 1378 | myaddr.sin6_addr = sa->sin6_addr; |
1329 | do { | 1379 | do { |
1330 | myaddr.sin6_port = htons(port); | 1380 | myaddr.sin6_port = htons(port); |
1331 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1381 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, |
1332 | sizeof(myaddr)); | 1382 | sizeof(myaddr)); |
1333 | if (!transport->xprt.resvport) | 1383 | if (port == 0) |
1334 | break; | 1384 | break; |
1335 | if (err == 0) { | 1385 | if (err == 0) { |
1336 | transport->port = port; | 1386 | transport->port = port; |
1337 | break; | 1387 | break; |
1338 | } | 1388 | } |
1339 | if (port <= xprt_min_resvport) | 1389 | last = port; |
1340 | port = xprt_max_resvport; | 1390 | port = xs_next_srcport(transport, sock, port); |
1341 | else | 1391 | if (port > last) |
1342 | port--; | 1392 | nloop++; |
1343 | } while (err == -EADDRINUSE && port != transport->port); | 1393 | } while (err == -EADDRINUSE && nloop != 2); |
1344 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", | 1394 | dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n", |
1345 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); | 1395 | NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err); |
1346 | return err; | 1396 | return err; |
@@ -1602,8 +1652,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work) | |||
1602 | break; | 1652 | break; |
1603 | default: | 1653 | default: |
1604 | /* get rid of existing socket, and retry */ | 1654 | /* get rid of existing socket, and retry */ |
1605 | xs_close(xprt); | 1655 | xs_tcp_shutdown(xprt); |
1606 | break; | ||
1607 | } | 1656 | } |
1608 | } | 1657 | } |
1609 | out: | 1658 | out: |
@@ -1662,8 +1711,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work) | |||
1662 | break; | 1711 | break; |
1663 | default: | 1712 | default: |
1664 | /* get rid of existing socket, and retry */ | 1713 | /* get rid of existing socket, and retry */ |
1665 | xs_close(xprt); | 1714 | xs_tcp_shutdown(xprt); |
1666 | break; | ||
1667 | } | 1715 | } |
1668 | } | 1716 | } |
1669 | out: | 1717 | out: |
@@ -1710,6 +1758,19 @@ static void xs_connect(struct rpc_task *task) | |||
1710 | } | 1758 | } |
1711 | } | 1759 | } |
1712 | 1760 | ||
1761 | static void xs_tcp_connect(struct rpc_task *task) | ||
1762 | { | ||
1763 | struct rpc_xprt *xprt = task->tk_xprt; | ||
1764 | |||
1765 | /* Initiate graceful shutdown of the socket if not already done */ | ||
1766 | if (test_bit(XPRT_CONNECTED, &xprt->state)) | ||
1767 | xs_tcp_shutdown(xprt); | ||
1768 | /* Exit if we need to wait for socket shutdown to complete */ | ||
1769 | if (test_bit(XPRT_CLOSING, &xprt->state)) | ||
1770 | return; | ||
1771 | xs_connect(task); | ||
1772 | } | ||
1773 | |||
1713 | /** | 1774 | /** |
1714 | * xs_udp_print_stats - display UDP socket-specifc stats | 1775 | * xs_udp_print_stats - display UDP socket-specifc stats |
1715 | * @xprt: rpc_xprt struct containing statistics | 1776 | * @xprt: rpc_xprt struct containing statistics |
@@ -1780,12 +1841,12 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1780 | .release_xprt = xs_tcp_release_xprt, | 1841 | .release_xprt = xs_tcp_release_xprt, |
1781 | .rpcbind = rpcb_getport_async, | 1842 | .rpcbind = rpcb_getport_async, |
1782 | .set_port = xs_set_port, | 1843 | .set_port = xs_set_port, |
1783 | .connect = xs_connect, | 1844 | .connect = xs_tcp_connect, |
1784 | .buf_alloc = rpc_malloc, | 1845 | .buf_alloc = rpc_malloc, |
1785 | .buf_free = rpc_free, | 1846 | .buf_free = rpc_free, |
1786 | .send_request = xs_tcp_send_request, | 1847 | .send_request = xs_tcp_send_request, |
1787 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | 1848 | .set_retrans_timeout = xprt_set_retrans_timeout_def, |
1788 | .close = xs_close, | 1849 | .close = xs_tcp_shutdown, |
1789 | .destroy = xs_destroy, | 1850 | .destroy = xs_destroy, |
1790 | .print_stats = xs_tcp_print_stats, | 1851 | .print_stats = xs_tcp_print_stats, |
1791 | }; | 1852 | }; |
@@ -1822,11 +1883,17 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | |||
1822 | xprt->addrlen = args->addrlen; | 1883 | xprt->addrlen = args->addrlen; |
1823 | if (args->srcaddr) | 1884 | if (args->srcaddr) |
1824 | memcpy(&new->addr, args->srcaddr, args->addrlen); | 1885 | memcpy(&new->addr, args->srcaddr, args->addrlen); |
1825 | new->port = xs_get_random_port(); | ||
1826 | 1886 | ||
1827 | return xprt; | 1887 | return xprt; |
1828 | } | 1888 | } |
1829 | 1889 | ||
1890 | static const struct rpc_timeout xs_udp_default_timeout = { | ||
1891 | .to_initval = 5 * HZ, | ||
1892 | .to_maxval = 30 * HZ, | ||
1893 | .to_increment = 5 * HZ, | ||
1894 | .to_retries = 5, | ||
1895 | }; | ||
1896 | |||
1830 | /** | 1897 | /** |
1831 | * xs_setup_udp - Set up transport to use a UDP socket | 1898 | * xs_setup_udp - Set up transport to use a UDP socket |
1832 | * @args: rpc transport creation arguments | 1899 | * @args: rpc transport creation arguments |
@@ -1855,10 +1922,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
1855 | 1922 | ||
1856 | xprt->ops = &xs_udp_ops; | 1923 | xprt->ops = &xs_udp_ops; |
1857 | 1924 | ||
1858 | if (args->timeout) | 1925 | xprt->timeout = &xs_udp_default_timeout; |
1859 | xprt->timeout = *args->timeout; | ||
1860 | else | ||
1861 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | ||
1862 | 1926 | ||
1863 | switch (addr->sa_family) { | 1927 | switch (addr->sa_family) { |
1864 | case AF_INET: | 1928 | case AF_INET: |
@@ -1867,7 +1931,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
1867 | 1931 | ||
1868 | INIT_DELAYED_WORK(&transport->connect_worker, | 1932 | INIT_DELAYED_WORK(&transport->connect_worker, |
1869 | xs_udp_connect_worker4); | 1933 | xs_udp_connect_worker4); |
1870 | xs_format_ipv4_peer_addresses(xprt); | 1934 | xs_format_ipv4_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP); |
1871 | break; | 1935 | break; |
1872 | case AF_INET6: | 1936 | case AF_INET6: |
1873 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | 1937 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) |
@@ -1875,7 +1939,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
1875 | 1939 | ||
1876 | INIT_DELAYED_WORK(&transport->connect_worker, | 1940 | INIT_DELAYED_WORK(&transport->connect_worker, |
1877 | xs_udp_connect_worker6); | 1941 | xs_udp_connect_worker6); |
1878 | xs_format_ipv6_peer_addresses(xprt); | 1942 | xs_format_ipv6_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6); |
1879 | break; | 1943 | break; |
1880 | default: | 1944 | default: |
1881 | kfree(xprt); | 1945 | kfree(xprt); |
@@ -1893,6 +1957,12 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
1893 | return ERR_PTR(-EINVAL); | 1957 | return ERR_PTR(-EINVAL); |
1894 | } | 1958 | } |
1895 | 1959 | ||
1960 | static const struct rpc_timeout xs_tcp_default_timeout = { | ||
1961 | .to_initval = 60 * HZ, | ||
1962 | .to_maxval = 60 * HZ, | ||
1963 | .to_retries = 2, | ||
1964 | }; | ||
1965 | |||
1896 | /** | 1966 | /** |
1897 | * xs_setup_tcp - Set up transport to use a TCP socket | 1967 | * xs_setup_tcp - Set up transport to use a TCP socket |
1898 | * @args: rpc transport creation arguments | 1968 | * @args: rpc transport creation arguments |
@@ -1919,11 +1989,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
1919 | xprt->idle_timeout = XS_IDLE_DISC_TO; | 1989 | xprt->idle_timeout = XS_IDLE_DISC_TO; |
1920 | 1990 | ||
1921 | xprt->ops = &xs_tcp_ops; | 1991 | xprt->ops = &xs_tcp_ops; |
1922 | 1992 | xprt->timeout = &xs_tcp_default_timeout; | |
1923 | if (args->timeout) | ||
1924 | xprt->timeout = *args->timeout; | ||
1925 | else | ||
1926 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | ||
1927 | 1993 | ||
1928 | switch (addr->sa_family) { | 1994 | switch (addr->sa_family) { |
1929 | case AF_INET: | 1995 | case AF_INET: |
@@ -1931,14 +1997,14 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
1931 | xprt_set_bound(xprt); | 1997 | xprt_set_bound(xprt); |
1932 | 1998 | ||
1933 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); | 1999 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker4); |
1934 | xs_format_ipv4_peer_addresses(xprt); | 2000 | xs_format_ipv4_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP); |
1935 | break; | 2001 | break; |
1936 | case AF_INET6: | 2002 | case AF_INET6: |
1937 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) | 2003 | if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0)) |
1938 | xprt_set_bound(xprt); | 2004 | xprt_set_bound(xprt); |
1939 | 2005 | ||
1940 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); | 2006 | INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_connect_worker6); |
1941 | xs_format_ipv6_peer_addresses(xprt); | 2007 | xs_format_ipv6_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6); |
1942 | break; | 2008 | break; |
1943 | default: | 2009 | default: |
1944 | kfree(xprt); | 2010 | kfree(xprt); |