diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback.c | 7 | ||||
-rw-r--r-- | fs/nfs/callback.h | 4 | ||||
-rw-r--r-- | fs/nfs/callback_proc.c | 51 | ||||
-rw-r--r-- | fs/nfs/callback_xdr.c | 6 | ||||
-rw-r--r-- | fs/nfs/client.c | 358 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 110 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 3 | ||||
-rw-r--r-- | fs/nfs/dir.c | 63 | ||||
-rw-r--r-- | fs/nfs/direct.c | 113 | ||||
-rw-r--r-- | fs/nfs/file.c | 40 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 11 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 99 | ||||
-rw-r--r-- | fs/nfs/inode.c | 34 | ||||
-rw-r--r-- | fs/nfs/internal.h | 16 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 24 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 27 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 20 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 286 | ||||
-rw-r--r-- | fs/nfs/nfs4renewd.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 46 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 40 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 14 | ||||
-rw-r--r-- | fs/nfs/proc.c | 30 | ||||
-rw-r--r-- | fs/nfs/read.c | 45 | ||||
-rw-r--r-- | fs/nfs/super.c | 309 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 45 | ||||
-rw-r--r-- | fs/nfs/write.c | 102 |
30 files changed, 1189 insertions, 764 deletions
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 310fa2f4cbb8..c5c0175898f6 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", |
@@ -410,11 +492,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto, | |||
410 | */ | 492 | */ |
411 | static void nfs_destroy_server(struct nfs_server *server) | 493 | static void nfs_destroy_server(struct nfs_server *server) |
412 | { | 494 | { |
413 | if (!IS_ERR(server->client_acl)) | ||
414 | rpc_shutdown_client(server->client_acl); | ||
415 | |||
416 | if (!(server->flags & NFS_MOUNT_NONLM)) | 495 | if (!(server->flags & NFS_MOUNT_NONLM)) |
417 | lockd_down(); /* release rpc.lockd */ | 496 | nlmclnt_done(server->nlm_host); |
418 | } | 497 | } |
419 | 498 | ||
420 | /* | 499 | /* |
@@ -422,20 +501,29 @@ static void nfs_destroy_server(struct nfs_server *server) | |||
422 | */ | 501 | */ |
423 | static int nfs_start_lockd(struct nfs_server *server) | 502 | static int nfs_start_lockd(struct nfs_server *server) |
424 | { | 503 | { |
425 | 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 | }; | ||
426 | 514 | ||
427 | if (server->nfs_client->cl_nfsversion > 3) | 515 | if (nlm_init.nfs_version > 3) |
428 | goto out; | 516 | return 0; |
429 | if (server->flags & NFS_MOUNT_NONLM) | 517 | if (server->flags & NFS_MOUNT_NONLM) |
430 | goto out; | 518 | return 0; |
431 | error = lockd_up((server->flags & NFS_MOUNT_TCP) ? | 519 | |
432 | IPPROTO_TCP : IPPROTO_UDP); | 520 | host = nlmclnt_init(&nlm_init); |
433 | if (error < 0) | 521 | if (IS_ERR(host)) |
434 | server->flags |= NFS_MOUNT_NONLM; | 522 | return PTR_ERR(host); |
435 | else | 523 | |
436 | server->destroy = nfs_destroy_server; | 524 | server->nlm_host = host; |
437 | out: | 525 | server->destroy = nfs_destroy_server; |
438 | return error; | 526 | return 0; |
439 | } | 527 | } |
440 | 528 | ||
441 | /* | 529 | /* |
@@ -444,7 +532,7 @@ out: | |||
444 | #ifdef CONFIG_NFS_V3_ACL | 532 | #ifdef CONFIG_NFS_V3_ACL |
445 | static void nfs_init_server_aclclient(struct nfs_server *server) | 533 | static void nfs_init_server_aclclient(struct nfs_server *server) |
446 | { | 534 | { |
447 | if (server->nfs_client->cl_nfsversion != 3) | 535 | if (server->nfs_client->rpc_ops->version != 3) |
448 | goto out_noacl; | 536 | goto out_noacl; |
449 | if (server->flags & NFS_MOUNT_NOACL) | 537 | if (server->flags & NFS_MOUNT_NOACL) |
450 | goto out_noacl; | 538 | goto out_noacl; |
@@ -471,7 +559,9 @@ static inline void nfs_init_server_aclclient(struct nfs_server *server) | |||
471 | /* | 559 | /* |
472 | * Create a general RPC client | 560 | * Create a general RPC client |
473 | */ | 561 | */ |
474 | 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) | ||
475 | { | 565 | { |
476 | struct nfs_client *clp = server->nfs_client; | 566 | struct nfs_client *clp = server->nfs_client; |
477 | 567 | ||
@@ -481,6 +571,11 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t | |||
481 | return PTR_ERR(server->client); | 571 | return PTR_ERR(server->client); |
482 | } | 572 | } |
483 | 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 | |||
484 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { | 579 | if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { |
485 | struct rpc_auth *auth; | 580 | struct rpc_auth *auth; |
486 | 581 | ||
@@ -501,6 +596,7 @@ static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t | |||
501 | * Initialise an NFS2 or NFS3 client | 596 | * Initialise an NFS2 or NFS3 client |
502 | */ | 597 | */ |
503 | static int nfs_init_client(struct nfs_client *clp, | 598 | static int nfs_init_client(struct nfs_client *clp, |
599 | const struct rpc_timeout *timeparms, | ||
504 | const struct nfs_parsed_mount_data *data) | 600 | const struct nfs_parsed_mount_data *data) |
505 | { | 601 | { |
506 | int error; | 602 | int error; |
@@ -511,18 +607,11 @@ static int nfs_init_client(struct nfs_client *clp, | |||
511 | return 0; | 607 | return 0; |
512 | } | 608 | } |
513 | 609 | ||
514 | /* Check NFS protocol revision and initialize RPC op vector */ | ||
515 | clp->rpc_ops = &nfs_v2_clientops; | ||
516 | #ifdef CONFIG_NFS_V3 | ||
517 | if (clp->cl_nfsversion == 3) | ||
518 | clp->rpc_ops = &nfs_v3_clientops; | ||
519 | #endif | ||
520 | /* | 610 | /* |
521 | * Create a client RPC handle for doing FSSTAT with UNIX auth only | 611 | * Create a client RPC handle for doing FSSTAT with UNIX auth only |
522 | * - RFC 2623, sec 2.3.2 | 612 | * - RFC 2623, sec 2.3.2 |
523 | */ | 613 | */ |
524 | error = nfs_create_rpc_client(clp, data->nfs_server.protocol, | 614 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0); |
525 | data->timeo, data->retrans, RPC_AUTH_UNIX, 0); | ||
526 | if (error < 0) | 615 | if (error < 0) |
527 | goto error; | 616 | goto error; |
528 | nfs_mark_client_ready(clp, NFS_CS_READY); | 617 | nfs_mark_client_ready(clp, NFS_CS_READY); |
@@ -540,25 +629,34 @@ error: | |||
540 | static int nfs_init_server(struct nfs_server *server, | 629 | static int nfs_init_server(struct nfs_server *server, |
541 | const struct nfs_parsed_mount_data *data) | 630 | const struct nfs_parsed_mount_data *data) |
542 | { | 631 | { |
632 | struct nfs_client_initdata cl_init = { | ||
633 | .hostname = data->nfs_server.hostname, | ||
634 | .addr = (const struct sockaddr *)&data->nfs_server.address, | ||
635 | .addrlen = data->nfs_server.addrlen, | ||
636 | .rpc_ops = &nfs_v2_clientops, | ||
637 | .proto = data->nfs_server.protocol, | ||
638 | }; | ||
639 | struct rpc_timeout timeparms; | ||
543 | struct nfs_client *clp; | 640 | struct nfs_client *clp; |
544 | int error, nfsvers = 2; | 641 | int error; |
545 | 642 | ||
546 | dprintk("--> nfs_init_server()\n"); | 643 | dprintk("--> nfs_init_server()\n"); |
547 | 644 | ||
548 | #ifdef CONFIG_NFS_V3 | 645 | #ifdef CONFIG_NFS_V3 |
549 | if (data->flags & NFS_MOUNT_VER3) | 646 | if (data->flags & NFS_MOUNT_VER3) |
550 | nfsvers = 3; | 647 | cl_init.rpc_ops = &nfs_v3_clientops; |
551 | #endif | 648 | #endif |
552 | 649 | ||
553 | /* Allocate or find a client reference we can use */ | 650 | /* Allocate or find a client reference we can use */ |
554 | clp = nfs_get_client(data->nfs_server.hostname, | 651 | clp = nfs_get_client(&cl_init); |
555 | &data->nfs_server.address, nfsvers); | ||
556 | if (IS_ERR(clp)) { | 652 | if (IS_ERR(clp)) { |
557 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); | 653 | dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); |
558 | return PTR_ERR(clp); | 654 | return PTR_ERR(clp); |
559 | } | 655 | } |
560 | 656 | ||
561 | error = nfs_init_client(clp, data); | 657 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, |
658 | data->timeo, data->retrans); | ||
659 | error = nfs_init_client(clp, &timeparms, data); | ||
562 | if (error < 0) | 660 | if (error < 0) |
563 | goto error; | 661 | goto error; |
564 | 662 | ||
@@ -582,7 +680,7 @@ static int nfs_init_server(struct nfs_server *server, | |||
582 | if (error < 0) | 680 | if (error < 0) |
583 | goto error; | 681 | goto error; |
584 | 682 | ||
585 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); | 683 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
586 | if (error < 0) | 684 | if (error < 0) |
587 | goto error; | 685 | goto error; |
588 | 686 | ||
@@ -728,6 +826,9 @@ static struct nfs_server *nfs_alloc_server(void) | |||
728 | INIT_LIST_HEAD(&server->client_link); | 826 | INIT_LIST_HEAD(&server->client_link); |
729 | INIT_LIST_HEAD(&server->master_link); | 827 | INIT_LIST_HEAD(&server->master_link); |
730 | 828 | ||
829 | init_waitqueue_head(&server->active_wq); | ||
830 | atomic_set(&server->active, 0); | ||
831 | |||
731 | server->io_stats = nfs_alloc_iostats(); | 832 | server->io_stats = nfs_alloc_iostats(); |
732 | if (!server->io_stats) { | 833 | if (!server->io_stats) { |
733 | kfree(server); | 834 | kfree(server); |
@@ -751,6 +852,9 @@ void nfs_free_server(struct nfs_server *server) | |||
751 | 852 | ||
752 | if (server->destroy != NULL) | 853 | if (server->destroy != NULL) |
753 | server->destroy(server); | 854 | server->destroy(server); |
855 | |||
856 | if (!IS_ERR(server->client_acl)) | ||
857 | rpc_shutdown_client(server->client_acl); | ||
754 | if (!IS_ERR(server->client)) | 858 | if (!IS_ERR(server->client)) |
755 | rpc_shutdown_client(server->client); | 859 | rpc_shutdown_client(server->client); |
756 | 860 | ||
@@ -836,7 +940,7 @@ error: | |||
836 | * Initialise an NFS4 client record | 940 | * Initialise an NFS4 client record |
837 | */ | 941 | */ |
838 | static int nfs4_init_client(struct nfs_client *clp, | 942 | static int nfs4_init_client(struct nfs_client *clp, |
839 | int proto, int timeo, int retrans, | 943 | const struct rpc_timeout *timeparms, |
840 | const char *ip_addr, | 944 | const char *ip_addr, |
841 | rpc_authflavor_t authflavour) | 945 | rpc_authflavor_t authflavour) |
842 | { | 946 | { |
@@ -851,7 +955,7 @@ static int nfs4_init_client(struct nfs_client *clp, | |||
851 | /* Check NFS protocol revision and initialize RPC op vector */ | 955 | /* Check NFS protocol revision and initialize RPC op vector */ |
852 | clp->rpc_ops = &nfs_v4_clientops; | 956 | clp->rpc_ops = &nfs_v4_clientops; |
853 | 957 | ||
854 | error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour, | 958 | error = nfs_create_rpc_client(clp, timeparms, authflavour, |
855 | RPC_CLNT_CREATE_DISCRTRY); | 959 | RPC_CLNT_CREATE_DISCRTRY); |
856 | if (error < 0) | 960 | if (error < 0) |
857 | goto error; | 961 | goto error; |
@@ -878,23 +982,32 @@ error: | |||
878 | * Set up an NFS4 client | 982 | * Set up an NFS4 client |
879 | */ | 983 | */ |
880 | static int nfs4_set_client(struct nfs_server *server, | 984 | static int nfs4_set_client(struct nfs_server *server, |
881 | const char *hostname, const struct sockaddr_in *addr, | 985 | const char *hostname, |
986 | const struct sockaddr *addr, | ||
987 | const size_t addrlen, | ||
882 | const char *ip_addr, | 988 | const char *ip_addr, |
883 | rpc_authflavor_t authflavour, | 989 | rpc_authflavor_t authflavour, |
884 | int proto, int timeo, int retrans) | 990 | int proto, const struct rpc_timeout *timeparms) |
885 | { | 991 | { |
992 | struct nfs_client_initdata cl_init = { | ||
993 | .hostname = hostname, | ||
994 | .addr = addr, | ||
995 | .addrlen = addrlen, | ||
996 | .rpc_ops = &nfs_v4_clientops, | ||
997 | .proto = proto, | ||
998 | }; | ||
886 | struct nfs_client *clp; | 999 | struct nfs_client *clp; |
887 | int error; | 1000 | int error; |
888 | 1001 | ||
889 | dprintk("--> nfs4_set_client()\n"); | 1002 | dprintk("--> nfs4_set_client()\n"); |
890 | 1003 | ||
891 | /* Allocate or find a client reference we can use */ | 1004 | /* Allocate or find a client reference we can use */ |
892 | clp = nfs_get_client(hostname, addr, 4); | 1005 | clp = nfs_get_client(&cl_init); |
893 | if (IS_ERR(clp)) { | 1006 | if (IS_ERR(clp)) { |
894 | error = PTR_ERR(clp); | 1007 | error = PTR_ERR(clp); |
895 | goto error; | 1008 | goto error; |
896 | } | 1009 | } |
897 | error = nfs4_init_client(clp, proto, timeo, retrans, ip_addr, authflavour); | 1010 | error = nfs4_init_client(clp, timeparms, ip_addr, authflavour); |
898 | if (error < 0) | 1011 | if (error < 0) |
899 | goto error_put; | 1012 | goto error_put; |
900 | 1013 | ||
@@ -915,10 +1028,26 @@ error: | |||
915 | static int nfs4_init_server(struct nfs_server *server, | 1028 | static int nfs4_init_server(struct nfs_server *server, |
916 | const struct nfs_parsed_mount_data *data) | 1029 | const struct nfs_parsed_mount_data *data) |
917 | { | 1030 | { |
1031 | struct rpc_timeout timeparms; | ||
918 | int error; | 1032 | int error; |
919 | 1033 | ||
920 | dprintk("--> nfs4_init_server()\n"); | 1034 | dprintk("--> nfs4_init_server()\n"); |
921 | 1035 | ||
1036 | nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, | ||
1037 | data->timeo, data->retrans); | ||
1038 | |||
1039 | /* Get a client record */ | ||
1040 | error = nfs4_set_client(server, | ||
1041 | data->nfs_server.hostname, | ||
1042 | (const struct sockaddr *)&data->nfs_server.address, | ||
1043 | data->nfs_server.addrlen, | ||
1044 | data->client_address, | ||
1045 | data->auth_flavors[0], | ||
1046 | data->nfs_server.protocol, | ||
1047 | &timeparms); | ||
1048 | if (error < 0) | ||
1049 | goto error; | ||
1050 | |||
922 | /* Initialise the client representation from the mount data */ | 1051 | /* Initialise the client representation from the mount data */ |
923 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1052 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; |
924 | server->caps |= NFS_CAP_ATOMIC_OPEN; | 1053 | server->caps |= NFS_CAP_ATOMIC_OPEN; |
@@ -933,8 +1062,9 @@ static int nfs4_init_server(struct nfs_server *server, | |||
933 | server->acdirmin = data->acdirmin * HZ; | 1062 | server->acdirmin = data->acdirmin * HZ; |
934 | server->acdirmax = data->acdirmax * HZ; | 1063 | server->acdirmax = data->acdirmax * HZ; |
935 | 1064 | ||
936 | error = nfs_init_server_rpcclient(server, data->auth_flavors[0]); | 1065 | error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]); |
937 | 1066 | ||
1067 | error: | ||
938 | /* Done */ | 1068 | /* Done */ |
939 | dprintk("<-- nfs4_init_server() = %d\n", error); | 1069 | dprintk("<-- nfs4_init_server() = %d\n", error); |
940 | return error; | 1070 | return error; |
@@ -957,17 +1087,6 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
957 | if (!server) | 1087 | if (!server) |
958 | return ERR_PTR(-ENOMEM); | 1088 | return ERR_PTR(-ENOMEM); |
959 | 1089 | ||
960 | /* Get a client record */ | ||
961 | error = nfs4_set_client(server, | ||
962 | data->nfs_server.hostname, | ||
963 | &data->nfs_server.address, | ||
964 | data->client_address, | ||
965 | data->auth_flavors[0], | ||
966 | data->nfs_server.protocol, | ||
967 | data->timeo, data->retrans); | ||
968 | if (error < 0) | ||
969 | goto error; | ||
970 | |||
971 | /* set up the general RPC client */ | 1090 | /* set up the general RPC client */ |
972 | error = nfs4_init_server(server, data); | 1091 | error = nfs4_init_server(server, data); |
973 | if (error < 0) | 1092 | if (error < 0) |
@@ -1035,12 +1154,13 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1035 | 1154 | ||
1036 | /* Get a client representation. | 1155 | /* Get a client representation. |
1037 | * Note: NFSv4 always uses TCP, */ | 1156 | * Note: NFSv4 always uses TCP, */ |
1038 | error = nfs4_set_client(server, data->hostname, data->addr, | 1157 | error = nfs4_set_client(server, data->hostname, |
1039 | parent_client->cl_ipaddr, | 1158 | data->addr, |
1040 | data->authflavor, | 1159 | data->addrlen, |
1041 | parent_server->client->cl_xprt->prot, | 1160 | parent_client->cl_ipaddr, |
1042 | parent_client->retrans_timeo, | 1161 | data->authflavor, |
1043 | parent_client->retrans_count); | 1162 | parent_server->client->cl_xprt->prot, |
1163 | parent_server->client->cl_timeout); | ||
1044 | if (error < 0) | 1164 | if (error < 0) |
1045 | goto error; | 1165 | goto error; |
1046 | 1166 | ||
@@ -1048,7 +1168,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1048 | nfs_server_copy_userdata(server, parent_server); | 1168 | nfs_server_copy_userdata(server, parent_server); |
1049 | server->caps |= NFS_CAP_ATOMIC_OPEN; | 1169 | server->caps |= NFS_CAP_ATOMIC_OPEN; |
1050 | 1170 | ||
1051 | error = nfs_init_server_rpcclient(server, data->authflavor); | 1171 | error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); |
1052 | if (error < 0) | 1172 | if (error < 0) |
1053 | goto error; | 1173 | goto error; |
1054 | 1174 | ||
@@ -1117,7 +1237,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
1117 | 1237 | ||
1118 | server->fsid = fattr->fsid; | 1238 | server->fsid = fattr->fsid; |
1119 | 1239 | ||
1120 | error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); | 1240 | error = nfs_init_server_rpcclient(server, |
1241 | source->client->cl_timeout, | ||
1242 | source->client->cl_auth->au_flavor); | ||
1121 | if (error < 0) | 1243 | if (error < 0) |
1122 | goto out_free_server; | 1244 | goto out_free_server; |
1123 | if (!IS_ERR(source->client_acl)) | 1245 | if (!IS_ERR(source->client_acl)) |
@@ -1259,10 +1381,10 @@ static int nfs_server_list_show(struct seq_file *m, void *v) | |||
1259 | /* display one transport per line on subsequent lines */ | 1381 | /* display one transport per line on subsequent lines */ |
1260 | clp = list_entry(v, struct nfs_client, cl_share_link); | 1382 | clp = list_entry(v, struct nfs_client, cl_share_link); |
1261 | 1383 | ||
1262 | seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", | 1384 | seq_printf(m, "v%u %s %s %3d %s\n", |
1263 | clp->cl_nfsversion, | 1385 | clp->rpc_ops->version, |
1264 | NIPQUAD(clp->cl_addr.sin_addr), | 1386 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1265 | ntohs(clp->cl_addr.sin_port), | 1387 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1266 | atomic_read(&clp->cl_count), | 1388 | atomic_read(&clp->cl_count), |
1267 | clp->cl_hostname); | 1389 | clp->cl_hostname); |
1268 | 1390 | ||
@@ -1338,10 +1460,10 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) | |||
1338 | (unsigned long long) server->fsid.major, | 1460 | (unsigned long long) server->fsid.major, |
1339 | (unsigned long long) server->fsid.minor); | 1461 | (unsigned long long) server->fsid.minor); |
1340 | 1462 | ||
1341 | seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", | 1463 | seq_printf(m, "v%u %s %s %-7s %-17s\n", |
1342 | clp->cl_nfsversion, | 1464 | clp->rpc_ops->version, |
1343 | NIPQUAD(clp->cl_addr.sin_addr), | 1465 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR), |
1344 | ntohs(clp->cl_addr.sin_port), | 1466 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT), |
1345 | dev, | 1467 | dev, |
1346 | fsid); | 1468 | fsid); |
1347 | 1469 | ||
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 7b994b2fa593..16844f98f50e 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -272,6 +272,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | 272 | unsigned long user_addr = (unsigned long)iov->iov_base; |
273 | size_t count = iov->iov_len; | 273 | size_t count = iov->iov_len; |
274 | size_t rsize = NFS_SERVER(inode)->rsize; | 274 | size_t rsize = NFS_SERVER(inode)->rsize; |
275 | struct rpc_task *task; | ||
276 | struct rpc_message msg = { | ||
277 | .rpc_cred = ctx->cred, | ||
278 | }; | ||
279 | struct rpc_task_setup task_setup_data = { | ||
280 | .rpc_client = NFS_CLIENT(inode), | ||
281 | .rpc_message = &msg, | ||
282 | .callback_ops = &nfs_read_direct_ops, | ||
283 | .flags = RPC_TASK_ASYNC, | ||
284 | }; | ||
275 | unsigned int pgbase; | 285 | unsigned int pgbase; |
276 | int result; | 286 | int result; |
277 | ssize_t started = 0; | 287 | ssize_t started = 0; |
@@ -311,7 +321,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
311 | 321 | ||
312 | data->req = (struct nfs_page *) dreq; | 322 | data->req = (struct nfs_page *) dreq; |
313 | data->inode = inode; | 323 | data->inode = inode; |
314 | data->cred = ctx->cred; | 324 | data->cred = msg.rpc_cred; |
315 | data->args.fh = NFS_FH(inode); | 325 | data->args.fh = NFS_FH(inode); |
316 | data->args.context = ctx; | 326 | data->args.context = ctx; |
317 | data->args.offset = pos; | 327 | data->args.offset = pos; |
@@ -321,14 +331,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
321 | data->res.fattr = &data->fattr; | 331 | data->res.fattr = &data->fattr; |
322 | data->res.eof = 0; | 332 | data->res.eof = 0; |
323 | data->res.count = bytes; | 333 | data->res.count = bytes; |
334 | msg.rpc_argp = &data->args; | ||
335 | msg.rpc_resp = &data->res; | ||
324 | 336 | ||
325 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 337 | task_setup_data.task = &data->task; |
326 | &nfs_read_direct_ops, data); | 338 | task_setup_data.callback_data = data; |
327 | NFS_PROTO(inode)->read_setup(data); | 339 | NFS_PROTO(inode)->read_setup(data, &msg); |
328 | 340 | ||
329 | data->task.tk_cookie = (unsigned long) inode; | 341 | task = rpc_run_task(&task_setup_data); |
330 | 342 | if (!IS_ERR(task)) | |
331 | rpc_execute(&data->task); | 343 | rpc_put_task(task); |
332 | 344 | ||
333 | dprintk("NFS: %5u initiated direct read call " | 345 | dprintk("NFS: %5u initiated direct read call " |
334 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 346 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -427,6 +439,15 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
427 | struct inode *inode = dreq->inode; | 439 | struct inode *inode = dreq->inode; |
428 | struct list_head *p; | 440 | struct list_head *p; |
429 | struct nfs_write_data *data; | 441 | struct nfs_write_data *data; |
442 | struct rpc_task *task; | ||
443 | struct rpc_message msg = { | ||
444 | .rpc_cred = dreq->ctx->cred, | ||
445 | }; | ||
446 | struct rpc_task_setup task_setup_data = { | ||
447 | .rpc_client = NFS_CLIENT(inode), | ||
448 | .callback_ops = &nfs_write_direct_ops, | ||
449 | .flags = RPC_TASK_ASYNC, | ||
450 | }; | ||
430 | 451 | ||
431 | dreq->count = 0; | 452 | dreq->count = 0; |
432 | get_dreq(dreq); | 453 | get_dreq(dreq); |
@@ -436,6 +457,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
436 | 457 | ||
437 | get_dreq(dreq); | 458 | get_dreq(dreq); |
438 | 459 | ||
460 | /* Use stable writes */ | ||
461 | data->args.stable = NFS_FILE_SYNC; | ||
462 | |||
439 | /* | 463 | /* |
440 | * Reset data->res. | 464 | * Reset data->res. |
441 | */ | 465 | */ |
@@ -447,17 +471,18 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
447 | * Reuse data->task; data->args should not have changed | 471 | * Reuse data->task; data->args should not have changed |
448 | * since the original request was sent. | 472 | * since the original request was sent. |
449 | */ | 473 | */ |
450 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 474 | task_setup_data.task = &data->task; |
451 | &nfs_write_direct_ops, data); | 475 | task_setup_data.callback_data = data; |
452 | NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); | 476 | msg.rpc_argp = &data->args; |
453 | 477 | msg.rpc_resp = &data->res; | |
454 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 478 | NFS_PROTO(inode)->write_setup(data, &msg); |
455 | data->task.tk_cookie = (unsigned long) inode; | ||
456 | 479 | ||
457 | /* | 480 | /* |
458 | * We're called via an RPC callback, so BKL is already held. | 481 | * We're called via an RPC callback, so BKL is already held. |
459 | */ | 482 | */ |
460 | rpc_execute(&data->task); | 483 | task = rpc_run_task(&task_setup_data); |
484 | if (!IS_ERR(task)) | ||
485 | rpc_put_task(task); | ||
461 | 486 | ||
462 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 487 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
463 | data->task.tk_pid, | 488 | data->task.tk_pid, |
@@ -500,9 +525,23 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { | |||
500 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 525 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
501 | { | 526 | { |
502 | struct nfs_write_data *data = dreq->commit_data; | 527 | struct nfs_write_data *data = dreq->commit_data; |
528 | struct rpc_task *task; | ||
529 | struct rpc_message msg = { | ||
530 | .rpc_argp = &data->args, | ||
531 | .rpc_resp = &data->res, | ||
532 | .rpc_cred = dreq->ctx->cred, | ||
533 | }; | ||
534 | struct rpc_task_setup task_setup_data = { | ||
535 | .task = &data->task, | ||
536 | .rpc_client = NFS_CLIENT(dreq->inode), | ||
537 | .rpc_message = &msg, | ||
538 | .callback_ops = &nfs_commit_direct_ops, | ||
539 | .callback_data = data, | ||
540 | .flags = RPC_TASK_ASYNC, | ||
541 | }; | ||
503 | 542 | ||
504 | data->inode = dreq->inode; | 543 | data->inode = dreq->inode; |
505 | data->cred = dreq->ctx->cred; | 544 | data->cred = msg.rpc_cred; |
506 | 545 | ||
507 | data->args.fh = NFS_FH(data->inode); | 546 | data->args.fh = NFS_FH(data->inode); |
508 | data->args.offset = 0; | 547 | data->args.offset = 0; |
@@ -511,18 +550,16 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
511 | data->res.fattr = &data->fattr; | 550 | data->res.fattr = &data->fattr; |
512 | data->res.verf = &data->verf; | 551 | data->res.verf = &data->verf; |
513 | 552 | ||
514 | rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC, | 553 | NFS_PROTO(data->inode)->commit_setup(data, &msg); |
515 | &nfs_commit_direct_ops, data); | ||
516 | NFS_PROTO(data->inode)->commit_setup(data, 0); | ||
517 | 554 | ||
518 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | ||
519 | data->task.tk_cookie = (unsigned long)data->inode; | ||
520 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ | 555 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ |
521 | dreq->commit_data = NULL; | 556 | dreq->commit_data = NULL; |
522 | 557 | ||
523 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 558 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
524 | 559 | ||
525 | rpc_execute(&data->task); | 560 | task = rpc_run_task(&task_setup_data); |
561 | if (!IS_ERR(task)) | ||
562 | rpc_put_task(task); | ||
526 | } | 563 | } |
527 | 564 | ||
528 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 565 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
@@ -637,6 +674,16 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
637 | struct inode *inode = ctx->path.dentry->d_inode; | 674 | struct inode *inode = ctx->path.dentry->d_inode; |
638 | unsigned long user_addr = (unsigned long)iov->iov_base; | 675 | unsigned long user_addr = (unsigned long)iov->iov_base; |
639 | size_t count = iov->iov_len; | 676 | size_t count = iov->iov_len; |
677 | struct rpc_task *task; | ||
678 | struct rpc_message msg = { | ||
679 | .rpc_cred = ctx->cred, | ||
680 | }; | ||
681 | struct rpc_task_setup task_setup_data = { | ||
682 | .rpc_client = NFS_CLIENT(inode), | ||
683 | .rpc_message = &msg, | ||
684 | .callback_ops = &nfs_write_direct_ops, | ||
685 | .flags = RPC_TASK_ASYNC, | ||
686 | }; | ||
640 | size_t wsize = NFS_SERVER(inode)->wsize; | 687 | size_t wsize = NFS_SERVER(inode)->wsize; |
641 | unsigned int pgbase; | 688 | unsigned int pgbase; |
642 | int result; | 689 | int result; |
@@ -679,25 +726,27 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
679 | 726 | ||
680 | data->req = (struct nfs_page *) dreq; | 727 | data->req = (struct nfs_page *) dreq; |
681 | data->inode = inode; | 728 | data->inode = inode; |
682 | data->cred = ctx->cred; | 729 | data->cred = msg.rpc_cred; |
683 | data->args.fh = NFS_FH(inode); | 730 | data->args.fh = NFS_FH(inode); |
684 | data->args.context = ctx; | 731 | data->args.context = ctx; |
685 | data->args.offset = pos; | 732 | data->args.offset = pos; |
686 | data->args.pgbase = pgbase; | 733 | data->args.pgbase = pgbase; |
687 | data->args.pages = data->pagevec; | 734 | data->args.pages = data->pagevec; |
688 | data->args.count = bytes; | 735 | data->args.count = bytes; |
736 | data->args.stable = sync; | ||
689 | data->res.fattr = &data->fattr; | 737 | data->res.fattr = &data->fattr; |
690 | data->res.count = bytes; | 738 | data->res.count = bytes; |
691 | data->res.verf = &data->verf; | 739 | data->res.verf = &data->verf; |
692 | 740 | ||
693 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 741 | task_setup_data.task = &data->task; |
694 | &nfs_write_direct_ops, data); | 742 | task_setup_data.callback_data = data; |
695 | NFS_PROTO(inode)->write_setup(data, sync); | 743 | msg.rpc_argp = &data->args; |
744 | msg.rpc_resp = &data->res; | ||
745 | NFS_PROTO(inode)->write_setup(data, &msg); | ||
696 | 746 | ||
697 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 747 | task = rpc_run_task(&task_setup_data); |
698 | data->task.tk_cookie = (unsigned long) inode; | 748 | if (!IS_ERR(task)) |
699 | 749 | rpc_put_task(task); | |
700 | rpc_execute(&data->task); | ||
701 | 750 | ||
702 | dprintk("NFS: %5u initiated direct write call " | 751 | dprintk("NFS: %5u initiated direct write call " |
703 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 752 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -766,7 +815,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
766 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 815 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
767 | struct nfs_direct_req *dreq; | 816 | struct nfs_direct_req *dreq; |
768 | size_t wsize = NFS_SERVER(inode)->wsize; | 817 | size_t wsize = NFS_SERVER(inode)->wsize; |
769 | int sync = 0; | 818 | int sync = NFS_UNSTABLE; |
770 | 819 | ||
771 | dreq = nfs_direct_req_alloc(); | 820 | dreq = nfs_direct_req_alloc(); |
772 | if (!dreq) | 821 | if (!dreq) |
@@ -774,7 +823,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
774 | nfs_alloc_commit_data(dreq); | 823 | nfs_alloc_commit_data(dreq); |
775 | 824 | ||
776 | if (dreq->commit_data == NULL || count < wsize) | 825 | if (dreq->commit_data == NULL || count < wsize) |
777 | sync = FLUSH_STABLE; | 826 | sync = NFS_FILE_SYNC; |
778 | 827 | ||
779 | dreq->inode = inode; | 828 | dreq->inode = inode; |
780 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 829 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
@@ -886,8 +935,6 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
886 | retval = generic_write_checks(file, &pos, &count, 0); | 935 | retval = generic_write_checks(file, &pos, &count, 0); |
887 | if (retval) | 936 | if (retval) |
888 | goto out; | 937 | goto out; |
889 | if (!count) | ||
890 | goto out; /* return 0 */ | ||
891 | 938 | ||
892 | retval = -EINVAL; | 939 | retval = -EINVAL; |
893 | if ((ssize_t) count < 0) | 940 | if ((ssize_t) count < 0) |
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/getroot.c b/fs/nfs/getroot.c index 0ee43843f4ec..e6242cdbaf91 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -57,6 +57,17 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i | |||
57 | } | 57 | } |
58 | /* Circumvent igrab(): we know the inode is not being freed */ | 58 | /* Circumvent igrab(): we know the inode is not being freed */ |
59 | atomic_inc(&inode->i_count); | 59 | atomic_inc(&inode->i_count); |
60 | /* | ||
61 | * Ensure that this dentry is invisible to d_find_alias(). | ||
62 | * Otherwise, it may be spliced into the tree by | ||
63 | * d_materialise_unique if a parent directory from the same | ||
64 | * filesystem gets mounted at a later time. | ||
65 | * This again causes shrink_dcache_for_umount_subtree() to | ||
66 | * Oops, since the test for IS_ROOT() will fail. | ||
67 | */ | ||
68 | spin_lock(&dcache_lock); | ||
69 | list_del_init(&sb->s_root->d_alias); | ||
70 | spin_unlock(&dcache_lock); | ||
60 | } | 71 | } |
61 | return 0; | 72 | return 0; |
62 | } | 73 | } |
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 f68c22215b14..966a8850aa30 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) |
@@ -457,9 +457,18 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
457 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; | 457 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
458 | int err; | 458 | int err; |
459 | 459 | ||
460 | /* Flush out writes to the server in order to update c/mtime */ | 460 | /* |
461 | if (S_ISREG(inode->i_mode)) | 461 | * Flush out writes to the server in order to update c/mtime. |
462 | * | ||
463 | * Hold the i_mutex to suspend application writes temporarily; | ||
464 | * this prevents long-running writing applications from blocking | ||
465 | * nfs_wb_nocommit. | ||
466 | */ | ||
467 | if (S_ISREG(inode->i_mode)) { | ||
468 | mutex_lock(&inode->i_mutex); | ||
462 | nfs_wb_nocommit(inode); | 469 | nfs_wb_nocommit(inode); |
470 | mutex_unlock(&inode->i_mutex); | ||
471 | } | ||
463 | 472 | ||
464 | /* | 473 | /* |
465 | * We may force a getattr if the user cares about atime. | 474 | * We may force a getattr if the user cares about atime. |
@@ -655,7 +664,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
655 | if (status == -ESTALE) { | 664 | if (status == -ESTALE) { |
656 | nfs_zap_caches(inode); | 665 | nfs_zap_caches(inode); |
657 | if (!S_ISDIR(inode->i_mode)) | 666 | if (!S_ISDIR(inode->i_mode)) |
658 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | 667 | set_bit(NFS_INO_STALE, &NFS_I(inode)->flags); |
659 | } | 668 | } |
660 | goto out; | 669 | goto out; |
661 | } | 670 | } |
@@ -810,8 +819,9 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
810 | if (S_ISDIR(inode->i_mode)) | 819 | if (S_ISDIR(inode->i_mode)) |
811 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 820 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
812 | } | 821 | } |
813 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) | 822 | if (inode->i_size == nfs_size_to_loff_t(fattr->pre_size) && |
814 | inode->i_size = fattr->size; | 823 | nfsi->npages == 0) |
824 | inode->i_size = nfs_size_to_loff_t(fattr->size); | ||
815 | } | 825 | } |
816 | } | 826 | } |
817 | 827 | ||
@@ -1015,7 +1025,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1015 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1025 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1016 | inode->i_sb->s_id, inode->i_ino); | 1026 | inode->i_sb->s_id, inode->i_ino); |
1017 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1027 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1018 | nfsi->cache_change_attribute = now; | 1028 | if (S_ISDIR(inode->i_mode)) |
1029 | nfs_force_lookup_revalidate(inode); | ||
1019 | } | 1030 | } |
1020 | /* If ctime has changed we should definitely clear access+acl caches */ | 1031 | /* If ctime has changed we should definitely clear access+acl caches */ |
1021 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1032 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) |
@@ -1024,7 +1035,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1024 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1035 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1025 | inode->i_sb->s_id, inode->i_ino); | 1036 | inode->i_sb->s_id, inode->i_ino); |
1026 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1037 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1027 | nfsi->cache_change_attribute = now; | 1038 | if (S_ISDIR(inode->i_mode)) |
1039 | nfs_force_lookup_revalidate(inode); | ||
1028 | } | 1040 | } |
1029 | 1041 | ||
1030 | /* Check if our cached file size is stale */ | 1042 | /* Check if our cached file size is stale */ |
@@ -1129,7 +1141,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1129 | void nfs4_clear_inode(struct inode *inode) | 1141 | void nfs4_clear_inode(struct inode *inode) |
1130 | { | 1142 | { |
1131 | /* If we are holding a delegation, return it! */ | 1143 | /* If we are holding a delegation, return it! */ |
1132 | nfs_inode_return_delegation(inode); | 1144 | nfs_inode_return_delegation_noreclaim(inode); |
1133 | /* First call standard NFS clear_inode() code */ | 1145 | /* First call standard NFS clear_inode() code */ |
1134 | nfs_clear_inode(inode); | 1146 | nfs_clear_inode(inode); |
1135 | } | 1147 | } |
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 5ae96340f2c2..549dbce714a4 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -729,16 +729,9 @@ static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
729 | return 0; | 729 | return 0; |
730 | } | 730 | } |
731 | 731 | ||
732 | static void nfs3_proc_read_setup(struct nfs_read_data *data) | 732 | static void nfs3_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
733 | { | 733 | { |
734 | struct rpc_message msg = { | 734 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_READ]; |
735 | .rpc_proc = &nfs3_procedures[NFS3PROC_READ], | ||
736 | .rpc_argp = &data->args, | ||
737 | .rpc_resp = &data->res, | ||
738 | .rpc_cred = data->cred, | ||
739 | }; | ||
740 | |||
741 | rpc_call_setup(&data->task, &msg, 0); | ||
742 | } | 735 | } |
743 | 736 | ||
744 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | 737 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -750,24 +743,9 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
750 | return 0; | 743 | return 0; |
751 | } | 744 | } |
752 | 745 | ||
753 | static void nfs3_proc_write_setup(struct nfs_write_data *data, int how) | 746 | static void nfs3_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
754 | { | 747 | { |
755 | struct rpc_message msg = { | 748 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE]; |
756 | .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE], | ||
757 | .rpc_argp = &data->args, | ||
758 | .rpc_resp = &data->res, | ||
759 | .rpc_cred = data->cred, | ||
760 | }; | ||
761 | |||
762 | data->args.stable = NFS_UNSTABLE; | ||
763 | if (how & FLUSH_STABLE) { | ||
764 | data->args.stable = NFS_FILE_SYNC; | ||
765 | if (NFS_I(data->inode)->ncommit) | ||
766 | data->args.stable = NFS_DATA_SYNC; | ||
767 | } | ||
768 | |||
769 | /* Finalize the task. */ | ||
770 | rpc_call_setup(&data->task, &msg, 0); | ||
771 | } | 749 | } |
772 | 750 | ||
773 | static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 751 | static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -778,22 +756,17 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
778 | return 0; | 756 | return 0; |
779 | } | 757 | } |
780 | 758 | ||
781 | static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how) | 759 | static void nfs3_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
782 | { | 760 | { |
783 | struct rpc_message msg = { | 761 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT]; |
784 | .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT], | ||
785 | .rpc_argp = &data->args, | ||
786 | .rpc_resp = &data->res, | ||
787 | .rpc_cred = data->cred, | ||
788 | }; | ||
789 | |||
790 | rpc_call_setup(&data->task, &msg, 0); | ||
791 | } | 762 | } |
792 | 763 | ||
793 | static int | 764 | static int |
794 | nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) | 765 | nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) |
795 | { | 766 | { |
796 | return nlmclnt_proc(filp->f_path.dentry->d_inode, cmd, fl); | 767 | struct inode *inode = filp->f_path.dentry->d_inode; |
768 | |||
769 | return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); | ||
797 | } | 770 | } |
798 | 771 | ||
799 | const struct nfs_rpc_ops nfs_v3_clientops = { | 772 | 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/nfs4_fs.h b/fs/nfs/nfs4_fs.h index b35069a2aa9e..bd1b9d663fb9 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -115,6 +115,7 @@ struct nfs4_lock_state { | |||
115 | #define NFS_LOCK_INITIALIZED 1 | 115 | #define NFS_LOCK_INITIALIZED 1 |
116 | int ls_flags; | 116 | int ls_flags; |
117 | struct nfs_seqid_counter ls_seqid; | 117 | struct nfs_seqid_counter ls_seqid; |
118 | struct rpc_sequence ls_sequence; | ||
118 | struct nfs_unique_id ls_id; | 119 | struct nfs_unique_id ls_id; |
119 | nfs4_stateid ls_stateid; | 120 | nfs4_stateid ls_stateid; |
120 | atomic_t ls_count; | 121 | atomic_t ls_count; |
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 c4faa43b36de..027e1095256e 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 | } |
@@ -715,19 +715,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
715 | return err; | 715 | return err; |
716 | } | 716 | } |
717 | 717 | ||
718 | static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | ||
719 | { | ||
720 | struct nfs4_opendata *data = calldata; | ||
721 | struct rpc_message msg = { | ||
722 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], | ||
723 | .rpc_argp = &data->c_arg, | ||
724 | .rpc_resp = &data->c_res, | ||
725 | .rpc_cred = data->owner->so_cred, | ||
726 | }; | ||
727 | data->timestamp = jiffies; | ||
728 | rpc_call_setup(task, &msg, 0); | ||
729 | } | ||
730 | |||
731 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 718 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
732 | { | 719 | { |
733 | struct nfs4_opendata *data = calldata; | 720 | struct nfs4_opendata *data = calldata; |
@@ -738,10 +725,10 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | |||
738 | if (data->rpc_status == 0) { | 725 | if (data->rpc_status == 0) { |
739 | memcpy(data->o_res.stateid.data, data->c_res.stateid.data, | 726 | memcpy(data->o_res.stateid.data, data->c_res.stateid.data, |
740 | sizeof(data->o_res.stateid.data)); | 727 | sizeof(data->o_res.stateid.data)); |
728 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | ||
741 | renew_lease(data->o_res.server, data->timestamp); | 729 | renew_lease(data->o_res.server, data->timestamp); |
742 | data->rpc_done = 1; | 730 | data->rpc_done = 1; |
743 | } | 731 | } |
744 | nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status); | ||
745 | nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid); | 732 | nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid); |
746 | } | 733 | } |
747 | 734 | ||
@@ -756,7 +743,6 @@ static void nfs4_open_confirm_release(void *calldata) | |||
756 | /* In case of error, no cleanup! */ | 743 | /* In case of error, no cleanup! */ |
757 | if (!data->rpc_done) | 744 | if (!data->rpc_done) |
758 | goto out_free; | 745 | goto out_free; |
759 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | ||
760 | state = nfs4_opendata_to_nfs4_state(data); | 746 | state = nfs4_opendata_to_nfs4_state(data); |
761 | if (!IS_ERR(state)) | 747 | if (!IS_ERR(state)) |
762 | nfs4_close_state(&data->path, state, data->o_arg.open_flags); | 748 | nfs4_close_state(&data->path, state, data->o_arg.open_flags); |
@@ -765,7 +751,6 @@ out_free: | |||
765 | } | 751 | } |
766 | 752 | ||
767 | static const struct rpc_call_ops nfs4_open_confirm_ops = { | 753 | static const struct rpc_call_ops nfs4_open_confirm_ops = { |
768 | .rpc_call_prepare = nfs4_open_confirm_prepare, | ||
769 | .rpc_call_done = nfs4_open_confirm_done, | 754 | .rpc_call_done = nfs4_open_confirm_done, |
770 | .rpc_release = nfs4_open_confirm_release, | 755 | .rpc_release = nfs4_open_confirm_release, |
771 | }; | 756 | }; |
@@ -777,12 +762,26 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
777 | { | 762 | { |
778 | struct nfs_server *server = NFS_SERVER(data->dir->d_inode); | 763 | struct nfs_server *server = NFS_SERVER(data->dir->d_inode); |
779 | struct rpc_task *task; | 764 | struct rpc_task *task; |
765 | struct rpc_message msg = { | ||
766 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], | ||
767 | .rpc_argp = &data->c_arg, | ||
768 | .rpc_resp = &data->c_res, | ||
769 | .rpc_cred = data->owner->so_cred, | ||
770 | }; | ||
771 | struct rpc_task_setup task_setup_data = { | ||
772 | .rpc_client = server->client, | ||
773 | .rpc_message = &msg, | ||
774 | .callback_ops = &nfs4_open_confirm_ops, | ||
775 | .callback_data = data, | ||
776 | .flags = RPC_TASK_ASYNC, | ||
777 | }; | ||
780 | int status; | 778 | int status; |
781 | 779 | ||
782 | kref_get(&data->kref); | 780 | kref_get(&data->kref); |
783 | data->rpc_done = 0; | 781 | data->rpc_done = 0; |
784 | data->rpc_status = 0; | 782 | data->rpc_status = 0; |
785 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); | 783 | data->timestamp = jiffies; |
784 | task = rpc_run_task(&task_setup_data); | ||
786 | if (IS_ERR(task)) | 785 | if (IS_ERR(task)) |
787 | return PTR_ERR(task); | 786 | return PTR_ERR(task); |
788 | status = nfs4_wait_for_completion_rpc_task(task); | 787 | status = nfs4_wait_for_completion_rpc_task(task); |
@@ -799,13 +798,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
799 | { | 798 | { |
800 | struct nfs4_opendata *data = calldata; | 799 | struct nfs4_opendata *data = calldata; |
801 | struct nfs4_state_owner *sp = data->owner; | 800 | struct nfs4_state_owner *sp = data->owner; |
802 | struct rpc_message msg = { | 801 | |
803 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], | ||
804 | .rpc_argp = &data->o_arg, | ||
805 | .rpc_resp = &data->o_res, | ||
806 | .rpc_cred = sp->so_cred, | ||
807 | }; | ||
808 | |||
809 | if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) | 802 | if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) |
810 | return; | 803 | return; |
811 | /* | 804 | /* |
@@ -830,11 +823,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
830 | data->o_arg.id = sp->so_owner_id.id; | 823 | data->o_arg.id = sp->so_owner_id.id; |
831 | data->o_arg.clientid = sp->so_client->cl_clientid; | 824 | data->o_arg.clientid = sp->so_client->cl_clientid; |
832 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 825 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
833 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 826 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
834 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 827 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
835 | } | 828 | } |
836 | data->timestamp = jiffies; | 829 | data->timestamp = jiffies; |
837 | rpc_call_setup(task, &msg, 0); | 830 | rpc_call_start(task); |
838 | return; | 831 | return; |
839 | out_no_action: | 832 | out_no_action: |
840 | task->tk_action = NULL; | 833 | task->tk_action = NULL; |
@@ -883,7 +876,6 @@ static void nfs4_open_release(void *calldata) | |||
883 | /* In case we need an open_confirm, no cleanup! */ | 876 | /* In case we need an open_confirm, no cleanup! */ |
884 | if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) | 877 | if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) |
885 | goto out_free; | 878 | goto out_free; |
886 | nfs_confirm_seqid(&data->owner->so_seqid, 0); | ||
887 | state = nfs4_opendata_to_nfs4_state(data); | 879 | state = nfs4_opendata_to_nfs4_state(data); |
888 | if (!IS_ERR(state)) | 880 | if (!IS_ERR(state)) |
889 | nfs4_close_state(&data->path, state, data->o_arg.open_flags); | 881 | nfs4_close_state(&data->path, state, data->o_arg.open_flags); |
@@ -907,13 +899,26 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
907 | struct nfs_openargs *o_arg = &data->o_arg; | 899 | struct nfs_openargs *o_arg = &data->o_arg; |
908 | struct nfs_openres *o_res = &data->o_res; | 900 | struct nfs_openres *o_res = &data->o_res; |
909 | struct rpc_task *task; | 901 | struct rpc_task *task; |
902 | struct rpc_message msg = { | ||
903 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], | ||
904 | .rpc_argp = o_arg, | ||
905 | .rpc_resp = o_res, | ||
906 | .rpc_cred = data->owner->so_cred, | ||
907 | }; | ||
908 | struct rpc_task_setup task_setup_data = { | ||
909 | .rpc_client = server->client, | ||
910 | .rpc_message = &msg, | ||
911 | .callback_ops = &nfs4_open_ops, | ||
912 | .callback_data = data, | ||
913 | .flags = RPC_TASK_ASYNC, | ||
914 | }; | ||
910 | int status; | 915 | int status; |
911 | 916 | ||
912 | kref_get(&data->kref); | 917 | kref_get(&data->kref); |
913 | data->rpc_done = 0; | 918 | data->rpc_done = 0; |
914 | data->rpc_status = 0; | 919 | data->rpc_status = 0; |
915 | data->cancelled = 0; | 920 | data->cancelled = 0; |
916 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); | 921 | task = rpc_run_task(&task_setup_data); |
917 | if (IS_ERR(task)) | 922 | if (IS_ERR(task)) |
918 | return PTR_ERR(task); | 923 | return PTR_ERR(task); |
919 | status = nfs4_wait_for_completion_rpc_task(task); | 924 | status = nfs4_wait_for_completion_rpc_task(task); |
@@ -1243,12 +1248,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1243 | { | 1248 | { |
1244 | struct nfs4_closedata *calldata = data; | 1249 | struct nfs4_closedata *calldata = data; |
1245 | struct nfs4_state *state = calldata->state; | 1250 | struct nfs4_state *state = calldata->state; |
1246 | struct rpc_message msg = { | ||
1247 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | ||
1248 | .rpc_argp = &calldata->arg, | ||
1249 | .rpc_resp = &calldata->res, | ||
1250 | .rpc_cred = state->owner->so_cred, | ||
1251 | }; | ||
1252 | int clear_rd, clear_wr, clear_rdwr; | 1251 | int clear_rd, clear_wr, clear_rdwr; |
1253 | 1252 | ||
1254 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 1253 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
@@ -1275,14 +1274,14 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1275 | } | 1274 | } |
1276 | nfs_fattr_init(calldata->res.fattr); | 1275 | nfs_fattr_init(calldata->res.fattr); |
1277 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { | 1276 | if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) { |
1278 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 1277 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
1279 | calldata->arg.open_flags = FMODE_READ; | 1278 | calldata->arg.open_flags = FMODE_READ; |
1280 | } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { | 1279 | } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) { |
1281 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 1280 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
1282 | calldata->arg.open_flags = FMODE_WRITE; | 1281 | calldata->arg.open_flags = FMODE_WRITE; |
1283 | } | 1282 | } |
1284 | calldata->timestamp = jiffies; | 1283 | calldata->timestamp = jiffies; |
1285 | rpc_call_setup(task, &msg, 0); | 1284 | rpc_call_start(task); |
1286 | } | 1285 | } |
1287 | 1286 | ||
1288 | static const struct rpc_call_ops nfs4_close_ops = { | 1287 | static const struct rpc_call_ops nfs4_close_ops = { |
@@ -1308,6 +1307,16 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1308 | struct nfs4_closedata *calldata; | 1307 | struct nfs4_closedata *calldata; |
1309 | struct nfs4_state_owner *sp = state->owner; | 1308 | struct nfs4_state_owner *sp = state->owner; |
1310 | struct rpc_task *task; | 1309 | struct rpc_task *task; |
1310 | struct rpc_message msg = { | ||
1311 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | ||
1312 | .rpc_cred = state->owner->so_cred, | ||
1313 | }; | ||
1314 | struct rpc_task_setup task_setup_data = { | ||
1315 | .rpc_client = server->client, | ||
1316 | .rpc_message = &msg, | ||
1317 | .callback_ops = &nfs4_close_ops, | ||
1318 | .flags = RPC_TASK_ASYNC, | ||
1319 | }; | ||
1311 | int status = -ENOMEM; | 1320 | int status = -ENOMEM; |
1312 | 1321 | ||
1313 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); | 1322 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
@@ -1327,7 +1336,10 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) | |||
1327 | calldata->path.mnt = mntget(path->mnt); | 1336 | calldata->path.mnt = mntget(path->mnt); |
1328 | calldata->path.dentry = dget(path->dentry); | 1337 | calldata->path.dentry = dget(path->dentry); |
1329 | 1338 | ||
1330 | task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata); | 1339 | msg.rpc_argp = &calldata->arg, |
1340 | msg.rpc_resp = &calldata->res, | ||
1341 | task_setup_data.callback_data = calldata; | ||
1342 | task = rpc_run_task(&task_setup_data); | ||
1331 | if (IS_ERR(task)) | 1343 | if (IS_ERR(task)) |
1332 | return PTR_ERR(task); | 1344 | return PTR_ERR(task); |
1333 | status = 0; | 1345 | status = 0; |
@@ -2413,18 +2425,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
2413 | return 0; | 2425 | return 0; |
2414 | } | 2426 | } |
2415 | 2427 | ||
2416 | static void nfs4_proc_read_setup(struct nfs_read_data *data) | 2428 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
2417 | { | 2429 | { |
2418 | struct rpc_message msg = { | ||
2419 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], | ||
2420 | .rpc_argp = &data->args, | ||
2421 | .rpc_resp = &data->res, | ||
2422 | .rpc_cred = data->cred, | ||
2423 | }; | ||
2424 | |||
2425 | data->timestamp = jiffies; | 2430 | data->timestamp = jiffies; |
2426 | 2431 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | |
2427 | rpc_call_setup(&data->task, &msg, 0); | ||
2428 | } | 2432 | } |
2429 | 2433 | ||
2430 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 2434 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -2442,33 +2446,15 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2442 | return 0; | 2446 | return 0; |
2443 | } | 2447 | } |
2444 | 2448 | ||
2445 | static void nfs4_proc_write_setup(struct nfs_write_data *data, int how) | 2449 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
2446 | { | 2450 | { |
2447 | struct rpc_message msg = { | 2451 | struct nfs_server *server = NFS_SERVER(data->inode); |
2448 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE], | 2452 | |
2449 | .rpc_argp = &data->args, | ||
2450 | .rpc_resp = &data->res, | ||
2451 | .rpc_cred = data->cred, | ||
2452 | }; | ||
2453 | struct inode *inode = data->inode; | ||
2454 | struct nfs_server *server = NFS_SERVER(inode); | ||
2455 | int stable; | ||
2456 | |||
2457 | if (how & FLUSH_STABLE) { | ||
2458 | if (!NFS_I(inode)->ncommit) | ||
2459 | stable = NFS_FILE_SYNC; | ||
2460 | else | ||
2461 | stable = NFS_DATA_SYNC; | ||
2462 | } else | ||
2463 | stable = NFS_UNSTABLE; | ||
2464 | data->args.stable = stable; | ||
2465 | data->args.bitmask = server->attr_bitmask; | 2453 | data->args.bitmask = server->attr_bitmask; |
2466 | data->res.server = server; | 2454 | data->res.server = server; |
2467 | |||
2468 | data->timestamp = jiffies; | 2455 | data->timestamp = jiffies; |
2469 | 2456 | ||
2470 | /* Finalize the task. */ | 2457 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
2471 | rpc_call_setup(&data->task, &msg, 0); | ||
2472 | } | 2458 | } |
2473 | 2459 | ||
2474 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 2460 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -2483,20 +2469,13 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
2483 | return 0; | 2469 | return 0; |
2484 | } | 2470 | } |
2485 | 2471 | ||
2486 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | 2472 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
2487 | { | 2473 | { |
2488 | struct rpc_message msg = { | ||
2489 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT], | ||
2490 | .rpc_argp = &data->args, | ||
2491 | .rpc_resp = &data->res, | ||
2492 | .rpc_cred = data->cred, | ||
2493 | }; | ||
2494 | struct nfs_server *server = NFS_SERVER(data->inode); | 2474 | struct nfs_server *server = NFS_SERVER(data->inode); |
2495 | 2475 | ||
2496 | data->args.bitmask = server->attr_bitmask; | 2476 | data->args.bitmask = server->attr_bitmask; |
2497 | data->res.server = server; | 2477 | data->res.server = server; |
2498 | 2478 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | |
2499 | rpc_call_setup(&data->task, &msg, 0); | ||
2500 | } | 2479 | } |
2501 | 2480 | ||
2502 | /* | 2481 | /* |
@@ -2899,14 +2878,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po | |||
2899 | 2878 | ||
2900 | for(;;) { | 2879 | for(;;) { |
2901 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 2880 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
2902 | sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", | 2881 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", |
2903 | clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr), | 2882 | clp->cl_ipaddr, |
2883 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2884 | RPC_DISPLAY_ADDR), | ||
2885 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2886 | RPC_DISPLAY_PROTO), | ||
2904 | cred->cr_ops->cr_name, | 2887 | cred->cr_ops->cr_name, |
2905 | clp->cl_id_uniquifier); | 2888 | clp->cl_id_uniquifier); |
2906 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 2889 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
2907 | sizeof(setclientid.sc_netid), "tcp"); | 2890 | sizeof(setclientid.sc_netid), |
2891 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
2892 | RPC_DISPLAY_NETID)); | ||
2908 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | 2893 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, |
2909 | sizeof(setclientid.sc_uaddr), "%s.%d.%d", | 2894 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
2910 | clp->cl_ipaddr, port >> 8, port & 255); | 2895 | clp->cl_ipaddr, port >> 8, port & 255); |
2911 | 2896 | ||
2912 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 2897 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); |
@@ -2970,25 +2955,11 @@ struct nfs4_delegreturndata { | |||
2970 | struct nfs4_delegreturnres res; | 2955 | struct nfs4_delegreturnres res; |
2971 | struct nfs_fh fh; | 2956 | struct nfs_fh fh; |
2972 | nfs4_stateid stateid; | 2957 | nfs4_stateid stateid; |
2973 | struct rpc_cred *cred; | ||
2974 | unsigned long timestamp; | 2958 | unsigned long timestamp; |
2975 | struct nfs_fattr fattr; | 2959 | struct nfs_fattr fattr; |
2976 | int rpc_status; | 2960 | int rpc_status; |
2977 | }; | 2961 | }; |
2978 | 2962 | ||
2979 | static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata) | ||
2980 | { | ||
2981 | struct nfs4_delegreturndata *data = calldata; | ||
2982 | struct rpc_message msg = { | ||
2983 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], | ||
2984 | .rpc_argp = &data->args, | ||
2985 | .rpc_resp = &data->res, | ||
2986 | .rpc_cred = data->cred, | ||
2987 | }; | ||
2988 | nfs_fattr_init(data->res.fattr); | ||
2989 | rpc_call_setup(task, &msg, 0); | ||
2990 | } | ||
2991 | |||
2992 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | 2963 | static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) |
2993 | { | 2964 | { |
2994 | struct nfs4_delegreturndata *data = calldata; | 2965 | struct nfs4_delegreturndata *data = calldata; |
@@ -2999,24 +2970,30 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
2999 | 2970 | ||
3000 | static void nfs4_delegreturn_release(void *calldata) | 2971 | static void nfs4_delegreturn_release(void *calldata) |
3001 | { | 2972 | { |
3002 | struct nfs4_delegreturndata *data = calldata; | ||
3003 | |||
3004 | put_rpccred(data->cred); | ||
3005 | kfree(calldata); | 2973 | kfree(calldata); |
3006 | } | 2974 | } |
3007 | 2975 | ||
3008 | static const struct rpc_call_ops nfs4_delegreturn_ops = { | 2976 | static const struct rpc_call_ops nfs4_delegreturn_ops = { |
3009 | .rpc_call_prepare = nfs4_delegreturn_prepare, | ||
3010 | .rpc_call_done = nfs4_delegreturn_done, | 2977 | .rpc_call_done = nfs4_delegreturn_done, |
3011 | .rpc_release = nfs4_delegreturn_release, | 2978 | .rpc_release = nfs4_delegreturn_release, |
3012 | }; | 2979 | }; |
3013 | 2980 | ||
3014 | static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 2981 | static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) |
3015 | { | 2982 | { |
3016 | struct nfs4_delegreturndata *data; | 2983 | struct nfs4_delegreturndata *data; |
3017 | struct nfs_server *server = NFS_SERVER(inode); | 2984 | struct nfs_server *server = NFS_SERVER(inode); |
3018 | struct rpc_task *task; | 2985 | struct rpc_task *task; |
3019 | int status; | 2986 | struct rpc_message msg = { |
2987 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], | ||
2988 | .rpc_cred = cred, | ||
2989 | }; | ||
2990 | struct rpc_task_setup task_setup_data = { | ||
2991 | .rpc_client = server->client, | ||
2992 | .rpc_message = &msg, | ||
2993 | .callback_ops = &nfs4_delegreturn_ops, | ||
2994 | .flags = RPC_TASK_ASYNC, | ||
2995 | }; | ||
2996 | int status = 0; | ||
3020 | 2997 | ||
3021 | data = kmalloc(sizeof(*data), GFP_KERNEL); | 2998 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
3022 | if (data == NULL) | 2999 | if (data == NULL) |
@@ -3028,30 +3005,37 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
3028 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); | 3005 | memcpy(&data->stateid, stateid, sizeof(data->stateid)); |
3029 | data->res.fattr = &data->fattr; | 3006 | data->res.fattr = &data->fattr; |
3030 | data->res.server = server; | 3007 | data->res.server = server; |
3031 | data->cred = get_rpccred(cred); | 3008 | nfs_fattr_init(data->res.fattr); |
3032 | data->timestamp = jiffies; | 3009 | data->timestamp = jiffies; |
3033 | data->rpc_status = 0; | 3010 | data->rpc_status = 0; |
3034 | 3011 | ||
3035 | task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); | 3012 | task_setup_data.callback_data = data; |
3013 | msg.rpc_argp = &data->args, | ||
3014 | msg.rpc_resp = &data->res, | ||
3015 | task = rpc_run_task(&task_setup_data); | ||
3036 | if (IS_ERR(task)) | 3016 | if (IS_ERR(task)) |
3037 | return PTR_ERR(task); | 3017 | return PTR_ERR(task); |
3018 | if (!issync) | ||
3019 | goto out; | ||
3038 | status = nfs4_wait_for_completion_rpc_task(task); | 3020 | status = nfs4_wait_for_completion_rpc_task(task); |
3039 | if (status == 0) { | 3021 | if (status != 0) |
3040 | status = data->rpc_status; | 3022 | goto out; |
3041 | if (status == 0) | 3023 | status = data->rpc_status; |
3042 | nfs_refresh_inode(inode, &data->fattr); | 3024 | if (status != 0) |
3043 | } | 3025 | goto out; |
3026 | nfs_refresh_inode(inode, &data->fattr); | ||
3027 | out: | ||
3044 | rpc_put_task(task); | 3028 | rpc_put_task(task); |
3045 | return status; | 3029 | return status; |
3046 | } | 3030 | } |
3047 | 3031 | ||
3048 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) | 3032 | int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) |
3049 | { | 3033 | { |
3050 | struct nfs_server *server = NFS_SERVER(inode); | 3034 | struct nfs_server *server = NFS_SERVER(inode); |
3051 | struct nfs4_exception exception = { }; | 3035 | struct nfs4_exception exception = { }; |
3052 | int err; | 3036 | int err; |
3053 | do { | 3037 | do { |
3054 | err = _nfs4_proc_delegreturn(inode, cred, stateid); | 3038 | err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); |
3055 | switch (err) { | 3039 | switch (err) { |
3056 | case -NFS4ERR_STALE_STATEID: | 3040 | case -NFS4ERR_STALE_STATEID: |
3057 | case -NFS4ERR_EXPIRED: | 3041 | case -NFS4ERR_EXPIRED: |
@@ -3219,12 +3203,6 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3219 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) | 3203 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) |
3220 | { | 3204 | { |
3221 | struct nfs4_unlockdata *calldata = data; | 3205 | struct nfs4_unlockdata *calldata = data; |
3222 | struct rpc_message msg = { | ||
3223 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | ||
3224 | .rpc_argp = &calldata->arg, | ||
3225 | .rpc_resp = &calldata->res, | ||
3226 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, | ||
3227 | }; | ||
3228 | 3206 | ||
3229 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 3207 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
3230 | return; | 3208 | return; |
@@ -3234,7 +3212,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
3234 | return; | 3212 | return; |
3235 | } | 3213 | } |
3236 | calldata->timestamp = jiffies; | 3214 | calldata->timestamp = jiffies; |
3237 | rpc_call_setup(task, &msg, 0); | 3215 | rpc_call_start(task); |
3238 | } | 3216 | } |
3239 | 3217 | ||
3240 | static const struct rpc_call_ops nfs4_locku_ops = { | 3218 | static const struct rpc_call_ops nfs4_locku_ops = { |
@@ -3249,6 +3227,16 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
3249 | struct nfs_seqid *seqid) | 3227 | struct nfs_seqid *seqid) |
3250 | { | 3228 | { |
3251 | struct nfs4_unlockdata *data; | 3229 | struct nfs4_unlockdata *data; |
3230 | struct rpc_message msg = { | ||
3231 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | ||
3232 | .rpc_cred = ctx->cred, | ||
3233 | }; | ||
3234 | struct rpc_task_setup task_setup_data = { | ||
3235 | .rpc_client = NFS_CLIENT(lsp->ls_state->inode), | ||
3236 | .rpc_message = &msg, | ||
3237 | .callback_ops = &nfs4_locku_ops, | ||
3238 | .flags = RPC_TASK_ASYNC, | ||
3239 | }; | ||
3252 | 3240 | ||
3253 | /* Ensure this is an unlock - when canceling a lock, the | 3241 | /* Ensure this is an unlock - when canceling a lock, the |
3254 | * canceled lock is passed in, and it won't be an unlock. | 3242 | * canceled lock is passed in, and it won't be an unlock. |
@@ -3261,7 +3249,10 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, | |||
3261 | return ERR_PTR(-ENOMEM); | 3249 | return ERR_PTR(-ENOMEM); |
3262 | } | 3250 | } |
3263 | 3251 | ||
3264 | return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); | 3252 | msg.rpc_argp = &data->arg, |
3253 | msg.rpc_resp = &data->res, | ||
3254 | task_setup_data.callback_data = data; | ||
3255 | return rpc_run_task(&task_setup_data); | ||
3265 | } | 3256 | } |
3266 | 3257 | ||
3267 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 3258 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) |
@@ -3320,9 +3311,12 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3320 | 3311 | ||
3321 | p->arg.fh = NFS_FH(inode); | 3312 | p->arg.fh = NFS_FH(inode); |
3322 | p->arg.fl = &p->fl; | 3313 | p->arg.fl = &p->fl; |
3314 | p->arg.open_seqid = nfs_alloc_seqid(&lsp->ls_state->owner->so_seqid); | ||
3315 | if (p->arg.open_seqid == NULL) | ||
3316 | goto out_free; | ||
3323 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); | 3317 | p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
3324 | if (p->arg.lock_seqid == NULL) | 3318 | if (p->arg.lock_seqid == NULL) |
3325 | goto out_free; | 3319 | goto out_free_seqid; |
3326 | p->arg.lock_stateid = &lsp->ls_stateid; | 3320 | p->arg.lock_stateid = &lsp->ls_stateid; |
3327 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; | 3321 | p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; |
3328 | p->arg.lock_owner.id = lsp->ls_id.id; | 3322 | p->arg.lock_owner.id = lsp->ls_id.id; |
@@ -3331,6 +3325,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, | |||
3331 | p->ctx = get_nfs_open_context(ctx); | 3325 | p->ctx = get_nfs_open_context(ctx); |
3332 | memcpy(&p->fl, fl, sizeof(p->fl)); | 3326 | memcpy(&p->fl, fl, sizeof(p->fl)); |
3333 | return p; | 3327 | return p; |
3328 | out_free_seqid: | ||
3329 | nfs_free_seqid(p->arg.open_seqid); | ||
3334 | out_free: | 3330 | out_free: |
3335 | kfree(p); | 3331 | kfree(p); |
3336 | return NULL; | 3332 | return NULL; |
@@ -3340,31 +3336,20 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
3340 | { | 3336 | { |
3341 | struct nfs4_lockdata *data = calldata; | 3337 | struct nfs4_lockdata *data = calldata; |
3342 | struct nfs4_state *state = data->lsp->ls_state; | 3338 | struct nfs4_state *state = data->lsp->ls_state; |
3343 | struct nfs4_state_owner *sp = state->owner; | ||
3344 | struct rpc_message msg = { | ||
3345 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], | ||
3346 | .rpc_argp = &data->arg, | ||
3347 | .rpc_resp = &data->res, | ||
3348 | .rpc_cred = sp->so_cred, | ||
3349 | }; | ||
3350 | 3339 | ||
3340 | dprintk("%s: begin!\n", __FUNCTION__); | ||
3351 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) | 3341 | if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) |
3352 | return; | 3342 | return; |
3353 | dprintk("%s: begin!\n", __FUNCTION__); | ||
3354 | /* Do we need to do an open_to_lock_owner? */ | 3343 | /* Do we need to do an open_to_lock_owner? */ |
3355 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 3344 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
3356 | data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid); | 3345 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) |
3357 | if (data->arg.open_seqid == NULL) { | 3346 | return; |
3358 | data->rpc_status = -ENOMEM; | ||
3359 | task->tk_action = NULL; | ||
3360 | goto out; | ||
3361 | } | ||
3362 | data->arg.open_stateid = &state->stateid; | 3347 | data->arg.open_stateid = &state->stateid; |
3363 | data->arg.new_lock_owner = 1; | 3348 | data->arg.new_lock_owner = 1; |
3364 | } | 3349 | } else |
3350 | data->arg.new_lock_owner = 0; | ||
3365 | data->timestamp = jiffies; | 3351 | data->timestamp = jiffies; |
3366 | rpc_call_setup(task, &msg, 0); | 3352 | rpc_call_start(task); |
3367 | out: | ||
3368 | dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); | 3353 | dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); |
3369 | } | 3354 | } |
3370 | 3355 | ||
@@ -3400,8 +3385,7 @@ static void nfs4_lock_release(void *calldata) | |||
3400 | struct nfs4_lockdata *data = calldata; | 3385 | struct nfs4_lockdata *data = calldata; |
3401 | 3386 | ||
3402 | dprintk("%s: begin!\n", __FUNCTION__); | 3387 | dprintk("%s: begin!\n", __FUNCTION__); |
3403 | if (data->arg.open_seqid != NULL) | 3388 | nfs_free_seqid(data->arg.open_seqid); |
3404 | nfs_free_seqid(data->arg.open_seqid); | ||
3405 | if (data->cancelled != 0) { | 3389 | if (data->cancelled != 0) { |
3406 | struct rpc_task *task; | 3390 | struct rpc_task *task; |
3407 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, | 3391 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, |
@@ -3427,6 +3411,16 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3427 | { | 3411 | { |
3428 | struct nfs4_lockdata *data; | 3412 | struct nfs4_lockdata *data; |
3429 | struct rpc_task *task; | 3413 | struct rpc_task *task; |
3414 | struct rpc_message msg = { | ||
3415 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], | ||
3416 | .rpc_cred = state->owner->so_cred, | ||
3417 | }; | ||
3418 | struct rpc_task_setup task_setup_data = { | ||
3419 | .rpc_client = NFS_CLIENT(state->inode), | ||
3420 | .rpc_message = &msg, | ||
3421 | .callback_ops = &nfs4_lock_ops, | ||
3422 | .flags = RPC_TASK_ASYNC, | ||
3423 | }; | ||
3430 | int ret; | 3424 | int ret; |
3431 | 3425 | ||
3432 | dprintk("%s: begin!\n", __FUNCTION__); | 3426 | dprintk("%s: begin!\n", __FUNCTION__); |
@@ -3438,8 +3432,10 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f | |||
3438 | data->arg.block = 1; | 3432 | data->arg.block = 1; |
3439 | if (reclaim != 0) | 3433 | if (reclaim != 0) |
3440 | data->arg.reclaim = 1; | 3434 | data->arg.reclaim = 1; |
3441 | task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC, | 3435 | msg.rpc_argp = &data->arg, |
3442 | &nfs4_lock_ops, data); | 3436 | msg.rpc_resp = &data->res, |
3437 | task_setup_data.callback_data = data; | ||
3438 | task = rpc_run_task(&task_setup_data); | ||
3443 | if (IS_ERR(task)) | 3439 | if (IS_ERR(task)) |
3444 | return PTR_ERR(task); | 3440 | return PTR_ERR(task); |
3445 | ret = nfs4_wait_for_completion_rpc_task(task); | 3441 | ret = nfs4_wait_for_completion_rpc_task(task); |
@@ -3612,10 +3608,6 @@ int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, | |||
3612 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) | 3608 | if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0) |
3613 | return -EOPNOTSUPP; | 3609 | return -EOPNOTSUPP; |
3614 | 3610 | ||
3615 | if (!S_ISREG(inode->i_mode) && | ||
3616 | (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) | ||
3617 | return -EPERM; | ||
3618 | |||
3619 | return nfs4_proc_set_acl(inode, buf, buflen); | 3611 | return nfs4_proc_set_acl(inode, buf, buflen); |
3620 | } | 3612 | } |
3621 | 3613 | ||
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index 3ea352d82eba..5e2e4af1a0e6 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c | |||
@@ -133,9 +133,7 @@ nfs4_renewd_prepare_shutdown(struct nfs_server *server) | |||
133 | void | 133 | void |
134 | nfs4_kill_renewd(struct nfs_client *clp) | 134 | nfs4_kill_renewd(struct nfs_client *clp) |
135 | { | 135 | { |
136 | down_read(&clp->cl_sem); | ||
137 | cancel_delayed_work_sync(&clp->cl_renewd); | 136 | cancel_delayed_work_sync(&clp->cl_renewd); |
138 | up_read(&clp->cl_sem); | ||
139 | } | 137 | } |
140 | 138 | ||
141 | /* | 139 | /* |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 23a9a36556bf..f9c7432471dc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -509,7 +509,10 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
509 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); | 509 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
510 | if (lsp == NULL) | 510 | if (lsp == NULL) |
511 | return NULL; | 511 | return NULL; |
512 | lsp->ls_seqid.sequence = &state->owner->so_sequence; | 512 | rpc_init_wait_queue(&lsp->ls_sequence.wait, "lock_seqid_waitqueue"); |
513 | spin_lock_init(&lsp->ls_sequence.lock); | ||
514 | INIT_LIST_HEAD(&lsp->ls_sequence.list); | ||
515 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | ||
513 | atomic_set(&lsp->ls_count, 1); | 516 | atomic_set(&lsp->ls_count, 1); |
514 | lsp->ls_owner = fl_owner; | 517 | lsp->ls_owner = fl_owner; |
515 | spin_lock(&clp->cl_lock); | 518 | spin_lock(&clp->cl_lock); |
@@ -641,27 +644,26 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
641 | 644 | ||
642 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | 645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
643 | { | 646 | { |
644 | struct rpc_sequence *sequence = counter->sequence; | ||
645 | struct nfs_seqid *new; | 647 | struct nfs_seqid *new; |
646 | 648 | ||
647 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 649 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
648 | if (new != NULL) { | 650 | if (new != NULL) { |
649 | new->sequence = counter; | 651 | new->sequence = counter; |
650 | spin_lock(&sequence->lock); | 652 | INIT_LIST_HEAD(&new->list); |
651 | list_add_tail(&new->list, &sequence->list); | ||
652 | spin_unlock(&sequence->lock); | ||
653 | } | 653 | } |
654 | return new; | 654 | return new; |
655 | } | 655 | } |
656 | 656 | ||
657 | void nfs_free_seqid(struct nfs_seqid *seqid) | 657 | void nfs_free_seqid(struct nfs_seqid *seqid) |
658 | { | 658 | { |
659 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 659 | if (!list_empty(&seqid->list)) { |
660 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
660 | 661 | ||
661 | spin_lock(&sequence->lock); | 662 | spin_lock(&sequence->lock); |
662 | list_del(&seqid->list); | 663 | list_del(&seqid->list); |
663 | spin_unlock(&sequence->lock); | 664 | spin_unlock(&sequence->lock); |
664 | rpc_wake_up(&sequence->wait); | 665 | rpc_wake_up(&sequence->wait); |
666 | } | ||
665 | kfree(seqid); | 667 | kfree(seqid); |
666 | } | 668 | } |
667 | 669 | ||
@@ -672,6 +674,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
672 | */ | 674 | */ |
673 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | 675 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
674 | { | 676 | { |
677 | BUG_ON(list_first_entry(&seqid->sequence->sequence->list, struct nfs_seqid, list) != seqid); | ||
675 | switch (status) { | 678 | switch (status) { |
676 | case 0: | 679 | case 0: |
677 | break; | 680 | break; |
@@ -723,15 +726,15 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | |||
723 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 726 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
724 | int status = 0; | 727 | int status = 0; |
725 | 728 | ||
726 | if (sequence->list.next == &seqid->list) | ||
727 | goto out; | ||
728 | spin_lock(&sequence->lock); | 729 | spin_lock(&sequence->lock); |
729 | if (sequence->list.next != &seqid->list) { | 730 | if (list_empty(&seqid->list)) |
730 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | 731 | list_add_tail(&seqid->list, &sequence->list); |
731 | status = -EAGAIN; | 732 | if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid) |
732 | } | 733 | goto unlock; |
734 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | ||
735 | status = -EAGAIN; | ||
736 | unlock: | ||
733 | spin_unlock(&sequence->lock); | 737 | spin_unlock(&sequence->lock); |
734 | out: | ||
735 | return status; | 738 | return status; |
736 | } | 739 | } |
737 | 740 | ||
@@ -755,8 +758,9 @@ static void nfs4_recover_state(struct nfs_client *clp) | |||
755 | 758 | ||
756 | __module_get(THIS_MODULE); | 759 | __module_get(THIS_MODULE); |
757 | atomic_inc(&clp->cl_count); | 760 | atomic_inc(&clp->cl_count); |
758 | task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", | 761 | task = kthread_run(reclaimer, clp, "%s-reclaim", |
759 | NIPQUAD(clp->cl_addr.sin_addr)); | 762 | rpc_peeraddr2str(clp->cl_rpcclient, |
763 | RPC_DISPLAY_ADDR)); | ||
760 | if (!IS_ERR(task)) | 764 | if (!IS_ERR(task)) |
761 | return; | 765 | return; |
762 | nfs4_clear_recover_bit(clp); | 766 | nfs4_clear_recover_bit(clp); |
@@ -967,8 +971,8 @@ out: | |||
967 | module_put_and_exit(0); | 971 | module_put_and_exit(0); |
968 | return 0; | 972 | return 0; |
969 | out_error: | 973 | out_error: |
970 | 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" |
971 | NIPQUAD(clp->cl_addr.sin_addr), -status); | 975 | " with error %d\n", clp->cl_hostname, -status); |
972 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 976 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
973 | goto out; | 977 | goto out; |
974 | } | 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 2dff469f04fe..7f079209d70a 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -58,7 +58,6 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
58 | struct page *page, | 58 | struct page *page, |
59 | unsigned int offset, unsigned int count) | 59 | unsigned int offset, unsigned int count) |
60 | { | 60 | { |
61 | struct nfs_server *server = NFS_SERVER(inode); | ||
62 | struct nfs_page *req; | 61 | struct nfs_page *req; |
63 | 62 | ||
64 | for (;;) { | 63 | for (;;) { |
@@ -111,13 +110,14 @@ void nfs_unlock_request(struct nfs_page *req) | |||
111 | * nfs_set_page_tag_locked - Tag a request as locked | 110 | * nfs_set_page_tag_locked - Tag a request as locked |
112 | * @req: | 111 | * @req: |
113 | */ | 112 | */ |
114 | static int nfs_set_page_tag_locked(struct nfs_page *req) | 113 | int nfs_set_page_tag_locked(struct nfs_page *req) |
115 | { | 114 | { |
116 | struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode); | 115 | struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode); |
117 | 116 | ||
118 | if (!nfs_lock_request(req)) | 117 | if (!nfs_lock_request_dontget(req)) |
119 | return 0; | 118 | return 0; |
120 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 119 | if (req->wb_page != NULL) |
120 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | ||
121 | return 1; | 121 | return 1; |
122 | } | 122 | } |
123 | 123 | ||
@@ -132,9 +132,10 @@ void nfs_clear_page_tag_locked(struct nfs_page *req) | |||
132 | if (req->wb_page != NULL) { | 132 | if (req->wb_page != NULL) { |
133 | spin_lock(&inode->i_lock); | 133 | spin_lock(&inode->i_lock); |
134 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); | 134 | radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
135 | nfs_unlock_request(req); | ||
135 | spin_unlock(&inode->i_lock); | 136 | spin_unlock(&inode->i_lock); |
136 | } | 137 | } else |
137 | nfs_unlock_request(req); | 138 | nfs_unlock_request(req); |
138 | } | 139 | } |
139 | 140 | ||
140 | /** | 141 | /** |
@@ -413,6 +414,7 @@ int nfs_scan_list(struct nfs_inode *nfsi, | |||
413 | goto out; | 414 | goto out; |
414 | idx_start = req->wb_index + 1; | 415 | idx_start = req->wb_index + 1; |
415 | if (nfs_set_page_tag_locked(req)) { | 416 | if (nfs_set_page_tag_locked(req)) { |
417 | kref_get(&req->wb_kref); | ||
416 | nfs_list_remove_request(req); | 418 | nfs_list_remove_request(req); |
417 | radix_tree_tag_clear(&nfsi->nfs_page_tree, | 419 | radix_tree_tag_clear(&nfsi->nfs_page_tree, |
418 | req->wb_index, tag); | 420 | 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 3dcaa6a73261..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,14 +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 | rpc_execute(&data->task); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Generate multiple requests to fill a single page. | 225 | * Generate multiple requests to fill a single page. |
220 | * | 226 | * |
221 | * 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 |
@@ -269,7 +275,6 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne | |||
269 | rsize, offset); | 275 | rsize, offset); |
270 | offset += rsize; | 276 | offset += rsize; |
271 | nbytes -= rsize; | 277 | nbytes -= rsize; |
272 | nfs_execute_read(data); | ||
273 | } while (nbytes != 0); | 278 | } while (nbytes != 0); |
274 | 279 | ||
275 | return 0; | 280 | return 0; |
@@ -307,8 +312,6 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned | |||
307 | req = nfs_list_entry(data->pages.next); | 312 | req = nfs_list_entry(data->pages.next); |
308 | 313 | ||
309 | nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); | 314 | nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); |
310 | |||
311 | nfs_execute_read(data); | ||
312 | return 0; | 315 | return 0; |
313 | out_bad: | 316 | out_bad: |
314 | nfs_async_read_error(head); | 317 | nfs_async_read_error(head); |
@@ -333,7 +336,7 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | |||
333 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); | 336 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count); |
334 | 337 | ||
335 | if (task->tk_status == -ESTALE) { | 338 | if (task->tk_status == -ESTALE) { |
336 | set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); | 339 | set_bit(NFS_INO_STALE, &NFS_I(data->inode)->flags); |
337 | nfs_mark_for_revalidate(data->inode); | 340 | nfs_mark_for_revalidate(data->inode); |
338 | } | 341 | } |
339 | return 0; | 342 | return 0; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 5b6339f70a4c..7f4505f6ac6f 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 | */ |
@@ -454,8 +478,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
454 | } | 478 | } |
455 | seq_printf(m, ",proto=%s", | 479 | seq_printf(m, ",proto=%s", |
456 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); | 480 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); |
457 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | 481 | seq_printf(m, ",timeo=%lu", 10U * nfss->client->cl_timeout->to_initval / HZ); |
458 | seq_printf(m, ",retrans=%u", clp->retrans_count); | 482 | seq_printf(m, ",retrans=%u", nfss->client->cl_timeout->to_retries); |
459 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); | 483 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
460 | } | 484 | } |
461 | 485 | ||
@@ -468,8 +492,9 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
468 | 492 | ||
469 | nfs_show_mount_options(m, nfss, 0); | 493 | nfs_show_mount_options(m, nfss, 0); |
470 | 494 | ||
471 | seq_printf(m, ",addr="NIPQUAD_FMT, | 495 | seq_printf(m, ",addr=%s", |
472 | NIPQUAD(nfss->nfs_client->cl_addr.sin_addr)); | 496 | rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient, |
497 | RPC_DISPLAY_ADDR)); | ||
473 | 498 | ||
474 | return 0; | 499 | return 0; |
475 | } | 500 | } |
@@ -506,7 +531,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) | |||
506 | seq_printf(m, ",namelen=%d", nfss->namelen); | 531 | seq_printf(m, ",namelen=%d", nfss->namelen); |
507 | 532 | ||
508 | #ifdef CONFIG_NFS_V4 | 533 | #ifdef CONFIG_NFS_V4 |
509 | if (nfss->nfs_client->cl_nfsversion == 4) { | 534 | if (nfss->nfs_client->rpc_ops->version == 4) { |
510 | seq_printf(m, "\n\tnfsv4:\t"); | 535 | seq_printf(m, "\n\tnfsv4:\t"); |
511 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 536 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
512 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); | 537 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
@@ -574,16 +599,40 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | |||
574 | } | 599 | } |
575 | 600 | ||
576 | /* | 601 | /* |
577 | * Sanity-check a server address provided by the mount command | 602 | * Set the port number in an address. Be agnostic about the address family. |
603 | */ | ||
604 | static void nfs_set_port(struct sockaddr *sap, unsigned short port) | ||
605 | { | ||
606 | switch (sap->sa_family) { | ||
607 | case AF_INET: { | ||
608 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
609 | ap->sin_port = htons(port); | ||
610 | break; | ||
611 | } | ||
612 | case AF_INET6: { | ||
613 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
614 | ap->sin6_port = htons(port); | ||
615 | break; | ||
616 | } | ||
617 | } | ||
618 | } | ||
619 | |||
620 | /* | ||
621 | * Sanity-check a server address provided by the mount command. | ||
622 | * | ||
623 | * Address family must be initialized, and address must not be | ||
624 | * the ANY address for that family. | ||
578 | */ | 625 | */ |
579 | static int nfs_verify_server_address(struct sockaddr *addr) | 626 | static int nfs_verify_server_address(struct sockaddr *addr) |
580 | { | 627 | { |
581 | switch (addr->sa_family) { | 628 | switch (addr->sa_family) { |
582 | case AF_INET: { | 629 | case AF_INET: { |
583 | struct sockaddr_in *sa = (struct sockaddr_in *) addr; | 630 | struct sockaddr_in *sa = (struct sockaddr_in *)addr; |
584 | if (sa->sin_addr.s_addr != INADDR_ANY) | 631 | return sa->sin_addr.s_addr != INADDR_ANY; |
585 | return 1; | 632 | } |
586 | break; | 633 | case AF_INET6: { |
634 | struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; | ||
635 | return !ipv6_addr_any(sa); | ||
587 | } | 636 | } |
588 | } | 637 | } |
589 | 638 | ||
@@ -591,6 +640,40 @@ static int nfs_verify_server_address(struct sockaddr *addr) | |||
591 | } | 640 | } |
592 | 641 | ||
593 | /* | 642 | /* |
643 | * Parse string addresses passed in via a mount option, | ||
644 | * and construct a sockaddr based on the result. | ||
645 | * | ||
646 | * If address parsing fails, set the sockaddr's address | ||
647 | * family to AF_UNSPEC to force nfs_verify_server_address() | ||
648 | * to punt the mount. | ||
649 | */ | ||
650 | static void nfs_parse_server_address(char *value, | ||
651 | struct sockaddr *sap, | ||
652 | size_t *len) | ||
653 | { | ||
654 | if (strchr(value, ':')) { | ||
655 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
656 | u8 *addr = (u8 *)&ap->sin6_addr.in6_u; | ||
657 | |||
658 | ap->sin6_family = AF_INET6; | ||
659 | *len = sizeof(*ap); | ||
660 | if (in6_pton(value, -1, addr, '\0', NULL)) | ||
661 | return; | ||
662 | } else { | ||
663 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
664 | u8 *addr = (u8 *)&ap->sin_addr.s_addr; | ||
665 | |||
666 | ap->sin_family = AF_INET; | ||
667 | *len = sizeof(*ap); | ||
668 | if (in4_pton(value, -1, addr, '\0', NULL)) | ||
669 | return; | ||
670 | } | ||
671 | |||
672 | sap->sa_family = AF_UNSPEC; | ||
673 | *len = 0; | ||
674 | } | ||
675 | |||
676 | /* | ||
594 | * Error-check and convert a string of mount options from user space into | 677 | * Error-check and convert a string of mount options from user space into |
595 | * a data structure | 678 | * a data structure |
596 | */ | 679 | */ |
@@ -598,6 +681,7 @@ static int nfs_parse_mount_options(char *raw, | |||
598 | struct nfs_parsed_mount_data *mnt) | 681 | struct nfs_parsed_mount_data *mnt) |
599 | { | 682 | { |
600 | char *p, *string; | 683 | char *p, *string; |
684 | unsigned short port = 0; | ||
601 | 685 | ||
602 | if (!raw) { | 686 | if (!raw) { |
603 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 687 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -697,7 +781,7 @@ static int nfs_parse_mount_options(char *raw, | |||
697 | return 0; | 781 | return 0; |
698 | if (option < 0 || option > 65535) | 782 | if (option < 0 || option > 65535) |
699 | return 0; | 783 | return 0; |
700 | mnt->nfs_server.address.sin_port = htons(option); | 784 | port = option; |
701 | break; | 785 | break; |
702 | case Opt_rsize: | 786 | case Opt_rsize: |
703 | if (match_int(args, &mnt->rsize)) | 787 | if (match_int(args, &mnt->rsize)) |
@@ -759,13 +843,6 @@ static int nfs_parse_mount_options(char *raw, | |||
759 | return 0; | 843 | return 0; |
760 | mnt->mount_server.port = option; | 844 | mnt->mount_server.port = option; |
761 | break; | 845 | break; |
762 | case Opt_mountprog: | ||
763 | if (match_int(args, &option)) | ||
764 | return 0; | ||
765 | if (option < 0) | ||
766 | return 0; | ||
767 | mnt->mount_server.program = option; | ||
768 | break; | ||
769 | case Opt_mountvers: | 846 | case Opt_mountvers: |
770 | if (match_int(args, &option)) | 847 | if (match_int(args, &option)) |
771 | return 0; | 848 | return 0; |
@@ -773,13 +850,6 @@ static int nfs_parse_mount_options(char *raw, | |||
773 | return 0; | 850 | return 0; |
774 | mnt->mount_server.version = option; | 851 | mnt->mount_server.version = option; |
775 | break; | 852 | break; |
776 | case Opt_nfsprog: | ||
777 | if (match_int(args, &option)) | ||
778 | return 0; | ||
779 | if (option < 0) | ||
780 | return 0; | ||
781 | mnt->nfs_server.program = option; | ||
782 | break; | ||
783 | case Opt_nfsvers: | 853 | case Opt_nfsvers: |
784 | if (match_int(args, &option)) | 854 | if (match_int(args, &option)) |
785 | return 0; | 855 | return 0; |
@@ -923,24 +993,32 @@ static int nfs_parse_mount_options(char *raw, | |||
923 | string = match_strdup(args); | 993 | string = match_strdup(args); |
924 | if (string == NULL) | 994 | if (string == NULL) |
925 | goto out_nomem; | 995 | goto out_nomem; |
926 | mnt->nfs_server.address.sin_family = AF_INET; | 996 | nfs_parse_server_address(string, (struct sockaddr *) |
927 | mnt->nfs_server.address.sin_addr.s_addr = | 997 | &mnt->nfs_server.address, |
928 | in_aton(string); | 998 | &mnt->nfs_server.addrlen); |
929 | kfree(string); | 999 | kfree(string); |
930 | break; | 1000 | break; |
931 | case Opt_clientaddr: | 1001 | case Opt_clientaddr: |
932 | string = match_strdup(args); | 1002 | string = match_strdup(args); |
933 | if (string == NULL) | 1003 | if (string == NULL) |
934 | goto out_nomem; | 1004 | goto out_nomem; |
1005 | kfree(mnt->client_address); | ||
935 | mnt->client_address = string; | 1006 | mnt->client_address = string; |
936 | break; | 1007 | break; |
1008 | case Opt_mounthost: | ||
1009 | string = match_strdup(args); | ||
1010 | if (string == NULL) | ||
1011 | goto out_nomem; | ||
1012 | kfree(mnt->mount_server.hostname); | ||
1013 | mnt->mount_server.hostname = string; | ||
1014 | break; | ||
937 | case Opt_mountaddr: | 1015 | case Opt_mountaddr: |
938 | string = match_strdup(args); | 1016 | string = match_strdup(args); |
939 | if (string == NULL) | 1017 | if (string == NULL) |
940 | goto out_nomem; | 1018 | goto out_nomem; |
941 | mnt->mount_server.address.sin_family = AF_INET; | 1019 | nfs_parse_server_address(string, (struct sockaddr *) |
942 | mnt->mount_server.address.sin_addr.s_addr = | 1020 | &mnt->mount_server.address, |
943 | in_aton(string); | 1021 | &mnt->mount_server.addrlen); |
944 | kfree(string); | 1022 | kfree(string); |
945 | break; | 1023 | break; |
946 | 1024 | ||
@@ -953,6 +1031,8 @@ static int nfs_parse_mount_options(char *raw, | |||
953 | } | 1031 | } |
954 | } | 1032 | } |
955 | 1033 | ||
1034 | nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port); | ||
1035 | |||
956 | return 1; | 1036 | return 1; |
957 | 1037 | ||
958 | out_nomem: | 1038 | out_nomem: |
@@ -983,7 +1063,8 @@ out_unknown: | |||
983 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, | 1063 | static int nfs_try_mount(struct nfs_parsed_mount_data *args, |
984 | struct nfs_fh *root_fh) | 1064 | struct nfs_fh *root_fh) |
985 | { | 1065 | { |
986 | struct sockaddr_in sin; | 1066 | struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address; |
1067 | char *hostname; | ||
987 | int status; | 1068 | int status; |
988 | 1069 | ||
989 | if (args->mount_server.version == 0) { | 1070 | if (args->mount_server.version == 0) { |
@@ -993,25 +1074,32 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
993 | args->mount_server.version = NFS_MNT_VERSION; | 1074 | args->mount_server.version = NFS_MNT_VERSION; |
994 | } | 1075 | } |
995 | 1076 | ||
1077 | if (args->mount_server.hostname) | ||
1078 | hostname = args->mount_server.hostname; | ||
1079 | else | ||
1080 | hostname = args->nfs_server.hostname; | ||
1081 | |||
996 | /* | 1082 | /* |
997 | * Construct the mount server's address. | 1083 | * Construct the mount server's address. |
998 | */ | 1084 | */ |
999 | if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY) | 1085 | if (args->mount_server.address.ss_family == AF_UNSPEC) { |
1000 | sin = args->mount_server.address; | 1086 | memcpy(sap, &args->nfs_server.address, |
1001 | else | 1087 | args->nfs_server.addrlen); |
1002 | sin = args->nfs_server.address; | 1088 | args->mount_server.addrlen = args->nfs_server.addrlen; |
1089 | } | ||
1090 | |||
1003 | /* | 1091 | /* |
1004 | * autobind will be used if mount_server.port == 0 | 1092 | * autobind will be used if mount_server.port == 0 |
1005 | */ | 1093 | */ |
1006 | sin.sin_port = htons(args->mount_server.port); | 1094 | nfs_set_port(sap, args->mount_server.port); |
1007 | 1095 | ||
1008 | /* | 1096 | /* |
1009 | * Now ask the mount server to map our export path | 1097 | * Now ask the mount server to map our export path |
1010 | * to a file handle. | 1098 | * to a file handle. |
1011 | */ | 1099 | */ |
1012 | status = nfs_mount((struct sockaddr *) &sin, | 1100 | status = nfs_mount(sap, |
1013 | sizeof(sin), | 1101 | args->mount_server.addrlen, |
1014 | args->nfs_server.hostname, | 1102 | hostname, |
1015 | args->nfs_server.export_path, | 1103 | args->nfs_server.export_path, |
1016 | args->mount_server.version, | 1104 | args->mount_server.version, |
1017 | args->mount_server.protocol, | 1105 | args->mount_server.protocol, |
@@ -1019,8 +1107,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1019 | if (status == 0) | 1107 | if (status == 0) |
1020 | return 0; | 1108 | return 0; |
1021 | 1109 | ||
1022 | dfprintk(MOUNT, "NFS: unable to mount server " NIPQUAD_FMT | 1110 | dfprintk(MOUNT, "NFS: unable to mount server %s, error %d", |
1023 | ", error %d\n", NIPQUAD(sin.sin_addr.s_addr), status); | 1111 | hostname, status); |
1024 | return status; | 1112 | return status; |
1025 | } | 1113 | } |
1026 | 1114 | ||
@@ -1039,9 +1127,6 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1039 | * | 1127 | * |
1040 | * + breaking back: trying proto=udp after proto=tcp, v2 after v3, | 1128 | * + breaking back: trying proto=udp after proto=tcp, v2 after v3, |
1041 | * mountproto=tcp after mountproto=udp, and so on | 1129 | * mountproto=tcp after mountproto=udp, and so on |
1042 | * | ||
1043 | * XXX: as far as I can tell, changing the NFS program number is not | ||
1044 | * supported in the NFS client. | ||
1045 | */ | 1130 | */ |
1046 | static int nfs_validate_mount_data(void *options, | 1131 | static int nfs_validate_mount_data(void *options, |
1047 | struct nfs_parsed_mount_data *args, | 1132 | struct nfs_parsed_mount_data *args, |
@@ -1065,9 +1150,7 @@ static int nfs_validate_mount_data(void *options, | |||
1065 | args->acdirmin = 30; | 1150 | args->acdirmin = 30; |
1066 | args->acdirmax = 60; | 1151 | args->acdirmax = 60; |
1067 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; | 1152 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; |
1068 | args->mount_server.program = NFS_MNT_PROGRAM; | ||
1069 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 1153 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
1070 | args->nfs_server.program = NFS_PROGRAM; | ||
1071 | 1154 | ||
1072 | switch (data->version) { | 1155 | switch (data->version) { |
1073 | case 1: | 1156 | case 1: |
@@ -1098,9 +1181,6 @@ static int nfs_validate_mount_data(void *options, | |||
1098 | memset(mntfh->data + mntfh->size, 0, | 1181 | memset(mntfh->data + mntfh->size, 0, |
1099 | sizeof(mntfh->data) - mntfh->size); | 1182 | sizeof(mntfh->data) - mntfh->size); |
1100 | 1183 | ||
1101 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
1102 | goto out_no_address; | ||
1103 | |||
1104 | /* | 1184 | /* |
1105 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | 1185 | * Translate to nfs_parsed_mount_data, which nfs_fill_super |
1106 | * can deal with. | 1186 | * can deal with. |
@@ -1115,7 +1195,14 @@ static int nfs_validate_mount_data(void *options, | |||
1115 | args->acregmax = data->acregmax; | 1195 | args->acregmax = data->acregmax; |
1116 | args->acdirmin = data->acdirmin; | 1196 | args->acdirmin = data->acdirmin; |
1117 | args->acdirmax = data->acdirmax; | 1197 | args->acdirmax = data->acdirmax; |
1118 | args->nfs_server.address = data->addr; | 1198 | |
1199 | memcpy(&args->nfs_server.address, &data->addr, | ||
1200 | sizeof(data->addr)); | ||
1201 | args->nfs_server.addrlen = sizeof(data->addr); | ||
1202 | if (!nfs_verify_server_address((struct sockaddr *) | ||
1203 | &args->nfs_server.address)) | ||
1204 | goto out_no_address; | ||
1205 | |||
1119 | if (!(data->flags & NFS_MOUNT_TCP)) | 1206 | if (!(data->flags & NFS_MOUNT_TCP)) |
1120 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1207 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
1121 | /* N.B. caller will free nfs_server.hostname in all cases */ | 1208 | /* N.B. caller will free nfs_server.hostname in all cases */ |
@@ -1318,15 +1405,50 @@ static int nfs_set_super(struct super_block *s, void *data) | |||
1318 | return ret; | 1405 | return ret; |
1319 | } | 1406 | } |
1320 | 1407 | ||
1408 | static int nfs_compare_super_address(struct nfs_server *server1, | ||
1409 | struct nfs_server *server2) | ||
1410 | { | ||
1411 | struct sockaddr *sap1, *sap2; | ||
1412 | |||
1413 | sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr; | ||
1414 | sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr; | ||
1415 | |||
1416 | if (sap1->sa_family != sap2->sa_family) | ||
1417 | return 0; | ||
1418 | |||
1419 | switch (sap1->sa_family) { | ||
1420 | case AF_INET: { | ||
1421 | struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1; | ||
1422 | struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2; | ||
1423 | if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) | ||
1424 | return 0; | ||
1425 | if (sin1->sin_port != sin2->sin_port) | ||
1426 | return 0; | ||
1427 | break; | ||
1428 | } | ||
1429 | case AF_INET6: { | ||
1430 | struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1; | ||
1431 | struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2; | ||
1432 | if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) | ||
1433 | return 0; | ||
1434 | if (sin1->sin6_port != sin2->sin6_port) | ||
1435 | return 0; | ||
1436 | break; | ||
1437 | } | ||
1438 | default: | ||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | return 1; | ||
1443 | } | ||
1444 | |||
1321 | static int nfs_compare_super(struct super_block *sb, void *data) | 1445 | static int nfs_compare_super(struct super_block *sb, void *data) |
1322 | { | 1446 | { |
1323 | struct nfs_sb_mountdata *sb_mntdata = data; | 1447 | struct nfs_sb_mountdata *sb_mntdata = data; |
1324 | struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb); | 1448 | struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb); |
1325 | int mntflags = sb_mntdata->mntflags; | 1449 | int mntflags = sb_mntdata->mntflags; |
1326 | 1450 | ||
1327 | if (memcmp(&old->nfs_client->cl_addr, | 1451 | if (!nfs_compare_super_address(old, server)) |
1328 | &server->nfs_client->cl_addr, | ||
1329 | sizeof(old->nfs_client->cl_addr)) != 0) | ||
1330 | return 0; | 1452 | return 0; |
1331 | /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */ | 1453 | /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */ |
1332 | if (old->flags & NFS_MOUNT_UNSHARED) | 1454 | if (old->flags & NFS_MOUNT_UNSHARED) |
@@ -1396,6 +1518,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1396 | 1518 | ||
1397 | out: | 1519 | out: |
1398 | kfree(data.nfs_server.hostname); | 1520 | kfree(data.nfs_server.hostname); |
1521 | kfree(data.mount_server.hostname); | ||
1399 | return error; | 1522 | return error; |
1400 | 1523 | ||
1401 | out_err_nosb: | 1524 | out_err_nosb: |
@@ -1471,7 +1594,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1471 | error = PTR_ERR(mntroot); | 1594 | error = PTR_ERR(mntroot); |
1472 | goto error_splat_super; | 1595 | goto error_splat_super; |
1473 | } | 1596 | } |
1474 | if (mntroot->d_inode->i_op != &nfs_dir_inode_operations) { | 1597 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { |
1475 | dput(mntroot); | 1598 | dput(mntroot); |
1476 | error = -ESTALE; | 1599 | error = -ESTALE; |
1477 | goto error_splat_super; | 1600 | goto error_splat_super; |
@@ -1524,12 +1647,35 @@ static void nfs4_fill_super(struct super_block *sb) | |||
1524 | } | 1647 | } |
1525 | 1648 | ||
1526 | /* | 1649 | /* |
1650 | * If the user didn't specify a port, set the port number to | ||
1651 | * the NFS version 4 default port. | ||
1652 | */ | ||
1653 | static void nfs4_default_port(struct sockaddr *sap) | ||
1654 | { | ||
1655 | switch (sap->sa_family) { | ||
1656 | case AF_INET: { | ||
1657 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
1658 | if (ap->sin_port == 0) | ||
1659 | ap->sin_port = htons(NFS_PORT); | ||
1660 | break; | ||
1661 | } | ||
1662 | case AF_INET6: { | ||
1663 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
1664 | if (ap->sin6_port == 0) | ||
1665 | ap->sin6_port = htons(NFS_PORT); | ||
1666 | break; | ||
1667 | } | ||
1668 | } | ||
1669 | } | ||
1670 | |||
1671 | /* | ||
1527 | * Validate NFSv4 mount options | 1672 | * Validate NFSv4 mount options |
1528 | */ | 1673 | */ |
1529 | static int nfs4_validate_mount_data(void *options, | 1674 | static int nfs4_validate_mount_data(void *options, |
1530 | struct nfs_parsed_mount_data *args, | 1675 | struct nfs_parsed_mount_data *args, |
1531 | const char *dev_name) | 1676 | const char *dev_name) |
1532 | { | 1677 | { |
1678 | struct sockaddr_in *ap; | ||
1533 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; | 1679 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1534 | char *c; | 1680 | char *c; |
1535 | 1681 | ||
@@ -1550,18 +1696,21 @@ static int nfs4_validate_mount_data(void *options, | |||
1550 | 1696 | ||
1551 | switch (data->version) { | 1697 | switch (data->version) { |
1552 | case 1: | 1698 | case 1: |
1553 | if (data->host_addrlen != sizeof(args->nfs_server.address)) | 1699 | ap = (struct sockaddr_in *)&args->nfs_server.address; |
1700 | if (data->host_addrlen > sizeof(args->nfs_server.address)) | ||
1701 | goto out_no_address; | ||
1702 | if (data->host_addrlen == 0) | ||
1554 | goto out_no_address; | 1703 | goto out_no_address; |
1555 | if (copy_from_user(&args->nfs_server.address, | 1704 | args->nfs_server.addrlen = data->host_addrlen; |
1556 | data->host_addr, | 1705 | if (copy_from_user(ap, data->host_addr, data->host_addrlen)) |
1557 | sizeof(args->nfs_server.address))) | ||
1558 | return -EFAULT; | 1706 | return -EFAULT; |
1559 | if (args->nfs_server.address.sin_port == 0) | ||
1560 | args->nfs_server.address.sin_port = htons(NFS_PORT); | ||
1561 | if (!nfs_verify_server_address((struct sockaddr *) | 1707 | if (!nfs_verify_server_address((struct sockaddr *) |
1562 | &args->nfs_server.address)) | 1708 | &args->nfs_server.address)) |
1563 | goto out_no_address; | 1709 | goto out_no_address; |
1564 | 1710 | ||
1711 | nfs4_default_port((struct sockaddr *) | ||
1712 | &args->nfs_server.address); | ||
1713 | |||
1565 | switch (data->auth_flavourlen) { | 1714 | switch (data->auth_flavourlen) { |
1566 | case 0: | 1715 | case 0: |
1567 | args->auth_flavors[0] = RPC_AUTH_UNIX; | 1716 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
@@ -1619,6 +1768,9 @@ static int nfs4_validate_mount_data(void *options, | |||
1619 | &args->nfs_server.address)) | 1768 | &args->nfs_server.address)) |
1620 | return -EINVAL; | 1769 | return -EINVAL; |
1621 | 1770 | ||
1771 | nfs4_default_port((struct sockaddr *) | ||
1772 | &args->nfs_server.address); | ||
1773 | |||
1622 | switch (args->auth_flavor_len) { | 1774 | switch (args->auth_flavor_len) { |
1623 | case 0: | 1775 | case 0: |
1624 | args->auth_flavors[0] = RPC_AUTH_UNIX; | 1776 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
@@ -1639,21 +1791,16 @@ static int nfs4_validate_mount_data(void *options, | |||
1639 | len = c - dev_name; | 1791 | len = c - dev_name; |
1640 | if (len > NFS4_MAXNAMLEN) | 1792 | if (len > NFS4_MAXNAMLEN) |
1641 | return -ENAMETOOLONG; | 1793 | return -ENAMETOOLONG; |
1642 | args->nfs_server.hostname = kzalloc(len, GFP_KERNEL); | 1794 | /* N.B. caller will free nfs_server.hostname in all cases */ |
1643 | if (args->nfs_server.hostname == NULL) | 1795 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); |
1644 | return -ENOMEM; | ||
1645 | strncpy(args->nfs_server.hostname, dev_name, len - 1); | ||
1646 | 1796 | ||
1647 | c++; /* step over the ':' */ | 1797 | c++; /* step over the ':' */ |
1648 | len = strlen(c); | 1798 | len = strlen(c); |
1649 | if (len > NFS4_MAXPATHLEN) | 1799 | if (len > NFS4_MAXPATHLEN) |
1650 | return -ENAMETOOLONG; | 1800 | return -ENAMETOOLONG; |
1651 | args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL); | 1801 | args->nfs_server.export_path = kstrndup(c, len, GFP_KERNEL); |
1652 | if (args->nfs_server.export_path == NULL) | ||
1653 | return -ENOMEM; | ||
1654 | strncpy(args->nfs_server.export_path, c, len); | ||
1655 | 1802 | ||
1656 | dprintk("MNTPATH: %s\n", args->nfs_server.export_path); | 1803 | dprintk("NFS: MNTPATH: '%s'\n", args->nfs_server.export_path); |
1657 | 1804 | ||
1658 | if (args->client_address == NULL) | 1805 | if (args->client_address == NULL) |
1659 | goto out_no_client_address; | 1806 | goto out_no_client_address; |
@@ -1822,6 +1969,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1822 | error = PTR_ERR(mntroot); | 1969 | error = PTR_ERR(mntroot); |
1823 | goto error_splat_super; | 1970 | goto error_splat_super; |
1824 | } | 1971 | } |
1972 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { | ||
1973 | dput(mntroot); | ||
1974 | error = -ESTALE; | ||
1975 | goto error_splat_super; | ||
1976 | } | ||
1825 | 1977 | ||
1826 | s->s_flags |= MS_ACTIVE; | 1978 | s->s_flags |= MS_ACTIVE; |
1827 | mnt->mnt_sb = s; | 1979 | mnt->mnt_sb = s; |
@@ -1896,6 +2048,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, | |||
1896 | error = PTR_ERR(mntroot); | 2048 | error = PTR_ERR(mntroot); |
1897 | goto error_splat_super; | 2049 | goto error_splat_super; |
1898 | } | 2050 | } |
2051 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) { | ||
2052 | dput(mntroot); | ||
2053 | error = -ESTALE; | ||
2054 | goto error_splat_super; | ||
2055 | } | ||
1899 | 2056 | ||
1900 | s->s_flags |= MS_ACTIVE; | 2057 | s->s_flags |= MS_ACTIVE; |
1901 | mnt->mnt_sb = s; | 2058 | mnt->mnt_sb = s; |
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 60e3e870ada4..522efff3e2c5 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,11 +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 | 830 | ||
817 | static void nfs_execute_write(struct nfs_write_data *data) | 831 | task = rpc_run_task(&task_setup_data); |
818 | { | 832 | if (!IS_ERR(task)) |
819 | rpc_execute(&data->task); | 833 | rpc_put_task(task); |
820 | } | 834 | } |
821 | 835 | ||
822 | /* | 836 | /* |
@@ -863,7 +877,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned | |||
863 | wsize, offset, how); | 877 | wsize, offset, how); |
864 | offset += wsize; | 878 | offset += wsize; |
865 | nbytes -= wsize; | 879 | nbytes -= wsize; |
866 | nfs_execute_write(data); | ||
867 | } while (nbytes != 0); | 880 | } while (nbytes != 0); |
868 | 881 | ||
869 | return 0; | 882 | return 0; |
@@ -911,7 +924,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
911 | /* Set up the argument struct */ | 924 | /* Set up the argument struct */ |
912 | 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); |
913 | 926 | ||
914 | nfs_execute_write(data); | ||
915 | return 0; | 927 | return 0; |
916 | out_bad: | 928 | out_bad: |
917 | while (!list_empty(head)) { | 929 | while (!list_empty(head)) { |
@@ -927,7 +939,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
927 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 939 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
928 | struct inode *inode, int ioflags) | 940 | struct inode *inode, int ioflags) |
929 | { | 941 | { |
930 | int wsize = NFS_SERVER(inode)->wsize; | 942 | size_t wsize = NFS_SERVER(inode)->wsize; |
931 | 943 | ||
932 | if (wsize < PAGE_CACHE_SIZE) | 944 | if (wsize < PAGE_CACHE_SIZE) |
933 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); | 945 | nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags); |
@@ -1141,19 +1153,33 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1141 | struct nfs_write_data *data, | 1153 | struct nfs_write_data *data, |
1142 | int how) | 1154 | int how) |
1143 | { | 1155 | { |
1144 | struct nfs_page *first; | 1156 | struct nfs_page *first = nfs_list_entry(head->next); |
1145 | struct inode *inode; | 1157 | struct inode *inode = first->wb_context->path.dentry->d_inode; |
1146 | 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 | }; | ||
1147 | 1175 | ||
1148 | /* Set up the RPC argument and reply structs | 1176 | /* Set up the RPC argument and reply structs |
1149 | * 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. */ |
1150 | 1178 | ||
1151 | list_splice_init(head, &data->pages); | 1179 | list_splice_init(head, &data->pages); |
1152 | first = nfs_list_entry(data->pages.next); | ||
1153 | inode = first->wb_context->path.dentry->d_inode; | ||
1154 | 1180 | ||
1155 | data->inode = inode; | 1181 | data->inode = inode; |
1156 | data->cred = first->wb_context->cred; | 1182 | data->cred = msg.rpc_cred; |
1157 | 1183 | ||
1158 | data->args.fh = NFS_FH(data->inode); | 1184 | data->args.fh = NFS_FH(data->inode); |
1159 | /* Note: we always request a commit of the entire inode */ | 1185 | /* Note: we always request a commit of the entire inode */ |
@@ -1165,14 +1191,13 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1165 | nfs_fattr_init(&data->fattr); | 1191 | nfs_fattr_init(&data->fattr); |
1166 | 1192 | ||
1167 | /* Set up the initial task struct. */ | 1193 | /* Set up the initial task struct. */ |
1168 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 1194 | NFS_PROTO(inode)->commit_setup(data, &msg); |
1169 | rpc_init_task(&data->task, NFS_CLIENT(inode), flags, &nfs_commit_ops, data); | ||
1170 | NFS_PROTO(inode)->commit_setup(data, how); | ||
1171 | 1195 | ||
1172 | data->task.tk_priority = flush_task_priority(how); | ||
1173 | data->task.tk_cookie = (unsigned long)inode; | ||
1174 | |||
1175 | 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); | ||
1176 | } | 1201 | } |
1177 | 1202 | ||
1178 | /* | 1203 | /* |
@@ -1192,7 +1217,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1192 | /* Set up the argument struct */ | 1217 | /* Set up the argument struct */ |
1193 | nfs_commit_rpcsetup(head, data, how); | 1218 | nfs_commit_rpcsetup(head, data, how); |
1194 | 1219 | ||
1195 | nfs_execute_write(data); | ||
1196 | return 0; | 1220 | return 0; |
1197 | out_bad: | 1221 | out_bad: |
1198 | while (!list_empty(head)) { | 1222 | while (!list_empty(head)) { |