Commit 529acf58981440eefeaf1451387e2a0aa4825c12
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge tag 'nfs-for-3.4-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: - Fixes for the NFSv4 security negotiation - Use the correct hostname when mounting from a private namespace - NFS net namespace bugfixes for the pipefs filesystem - NFSv4 GETACL bugfixes - IPv6 bugfix for NFSv4 referrals * tag 'nfs-for-3.4-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4.1: Use the correct hostname in the client identifier string SUNRPC: RPC client must use the current utsname hostname string NFS: get module in idmap PipeFS notifier callback NFS: Remove unused function nfs_lookup_with_sec() NFS: Honor the authflavor set in the clone mount data NFS: Fix following referral mount points with different security NFS: Do secinfo as part of lookup NFS: Handle exceptions coming out of nfs4_proc_fs_locations() NFS: Fix SECINFO_NO_NAME SUNRPC: traverse clients tree on PipeFS event SUNRPC: set per-net PipeFS superblock before notification SUNRPC: skip clients with program without PipeFS entries SUNRPC: skip dead but not buried clients on PipeFS events Avoid beyond bounds copy while caching ACL Avoid reading past buffer when calling GETACL fix page number calculation bug for block layout decode buffer NFSv4.1 fix page number calculation bug for filelayout decode buffers pnfs-obj: Remove unused variable from objlayout_get_deviceinfo() nfs4: fix referrals on mounts that use IPv6 addrs
Showing 15 changed files Side-by-side Diff
- fs/nfs/blocklayout/blocklayout.c
- fs/nfs/client.c
- fs/nfs/idmap.c
- fs/nfs/internal.h
- fs/nfs/namespace.c
- fs/nfs/nfs4_fs.h
- fs/nfs/nfs4filelayoutdev.c
- fs/nfs/nfs4namespace.c
- fs/nfs/nfs4proc.c
- fs/nfs/nfs4xdr.c
- fs/nfs/objlayout/objlayout.c
- fs/nfs/pnfs.c
- fs/nfs/super.c
- net/sunrpc/clnt.c
- net/sunrpc/rpc_pipe.c
fs/nfs/blocklayout/blocklayout.c
... | ... | @@ -38,6 +38,8 @@ |
38 | 38 | #include <linux/buffer_head.h> /* various write calls */ |
39 | 39 | #include <linux/prefetch.h> |
40 | 40 | |
41 | +#include "../pnfs.h" | |
42 | +#include "../internal.h" | |
41 | 43 | #include "blocklayout.h" |
42 | 44 | |
43 | 45 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
... | ... | @@ -868,7 +870,7 @@ |
868 | 870 | * GETDEVICEINFO's maxcount |
869 | 871 | */ |
870 | 872 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
871 | - max_pages = max_resp_sz >> PAGE_SHIFT; | |
873 | + max_pages = nfs_page_array_len(0, max_resp_sz); | |
872 | 874 | dprintk("%s max_resp_sz %u max_pages %d\n", |
873 | 875 | __func__, max_resp_sz, max_pages); |
874 | 876 |
fs/nfs/client.c
... | ... | @@ -1729,7 +1729,8 @@ |
1729 | 1729 | */ |
1730 | 1730 | struct nfs_server *nfs_clone_server(struct nfs_server *source, |
1731 | 1731 | struct nfs_fh *fh, |
1732 | - struct nfs_fattr *fattr) | |
1732 | + struct nfs_fattr *fattr, | |
1733 | + rpc_authflavor_t flavor) | |
1733 | 1734 | { |
1734 | 1735 | struct nfs_server *server; |
1735 | 1736 | struct nfs_fattr *fattr_fsinfo; |
... | ... | @@ -1758,7 +1759,7 @@ |
1758 | 1759 | |
1759 | 1760 | error = nfs_init_server_rpcclient(server, |
1760 | 1761 | source->client->cl_timeout, |
1761 | - source->client->cl_auth->au_flavor); | |
1762 | + flavor); | |
1762 | 1763 | if (error < 0) |
1763 | 1764 | goto out_free_server; |
1764 | 1765 | if (!IS_ERR(source->client_acl)) |
fs/nfs/idmap.c
... | ... | @@ -554,12 +554,16 @@ |
554 | 554 | struct nfs_client *clp; |
555 | 555 | int error = 0; |
556 | 556 | |
557 | + if (!try_module_get(THIS_MODULE)) | |
558 | + return 0; | |
559 | + | |
557 | 560 | while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) { |
558 | 561 | error = __rpc_pipefs_event(clp, event, sb); |
559 | 562 | nfs_put_client(clp); |
560 | 563 | if (error) |
561 | 564 | break; |
562 | 565 | } |
566 | + module_put(THIS_MODULE); | |
563 | 567 | return error; |
564 | 568 | } |
565 | 569 |
fs/nfs/internal.h
... | ... | @@ -165,7 +165,8 @@ |
165 | 165 | extern void nfs_free_server(struct nfs_server *server); |
166 | 166 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, |
167 | 167 | struct nfs_fh *, |
168 | - struct nfs_fattr *); | |
168 | + struct nfs_fattr *, | |
169 | + rpc_authflavor_t); | |
169 | 170 | extern void nfs_mark_client_ready(struct nfs_client *clp, int state); |
170 | 171 | extern int nfs4_check_client_ready(struct nfs_client *clp); |
171 | 172 | extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, |
172 | 173 | |
... | ... | @@ -186,10 +187,10 @@ |
186 | 187 | |
187 | 188 | /* nfs4namespace.c */ |
188 | 189 | #ifdef CONFIG_NFS_V4 |
189 | -extern struct vfsmount *nfs_do_refmount(struct dentry *dentry); | |
190 | +extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry); | |
190 | 191 | #else |
191 | 192 | static inline |
192 | -struct vfsmount *nfs_do_refmount(struct dentry *dentry) | |
193 | +struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) | |
193 | 194 | { |
194 | 195 | return ERR_PTR(-ENOENT); |
195 | 196 | } |
... | ... | @@ -234,7 +235,6 @@ |
234 | 235 | /* nfs4proc.c */ |
235 | 236 | #ifdef CONFIG_NFS_V4 |
236 | 237 | extern struct rpc_procinfo nfs4_procedures[]; |
237 | -void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); | |
238 | 238 | #endif |
239 | 239 | |
240 | 240 | extern int nfs4_init_ds_session(struct nfs_client *clp); |
fs/nfs/namespace.c
... | ... | @@ -148,66 +148,31 @@ |
148 | 148 | return pseudoflavor; |
149 | 149 | } |
150 | 150 | |
151 | -static int nfs_negotiate_security(const struct dentry *parent, | |
152 | - const struct dentry *dentry, | |
153 | - rpc_authflavor_t *flavor) | |
151 | +static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, | |
152 | + struct qstr *name, | |
153 | + struct nfs_fh *fh, | |
154 | + struct nfs_fattr *fattr) | |
154 | 155 | { |
155 | - struct page *page; | |
156 | - struct nfs4_secinfo_flavors *flavors; | |
157 | - int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | |
158 | - int ret = -EPERM; | |
156 | + int err; | |
159 | 157 | |
160 | - secinfo = NFS_PROTO(parent->d_inode)->secinfo; | |
161 | - if (secinfo != NULL) { | |
162 | - page = alloc_page(GFP_KERNEL); | |
163 | - if (!page) { | |
164 | - ret = -ENOMEM; | |
165 | - goto out; | |
166 | - } | |
167 | - flavors = page_address(page); | |
168 | - ret = secinfo(parent->d_inode, &dentry->d_name, flavors); | |
169 | - *flavor = nfs_find_best_sec(flavors); | |
170 | - put_page(page); | |
171 | - } | |
158 | + if (NFS_PROTO(dir)->version == 4) | |
159 | + return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr); | |
172 | 160 | |
173 | -out: | |
174 | - return ret; | |
161 | + err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); | |
162 | + if (err) | |
163 | + return ERR_PTR(err); | |
164 | + return rpc_clone_client(NFS_SERVER(dir)->client); | |
175 | 165 | } |
176 | - | |
177 | -static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, | |
178 | - struct dentry *dentry, struct path *path, | |
179 | - struct nfs_fh *fh, struct nfs_fattr *fattr, | |
180 | - rpc_authflavor_t *flavor) | |
181 | -{ | |
182 | - struct rpc_clnt *clone; | |
183 | - struct rpc_auth *auth; | |
184 | - int err; | |
185 | - | |
186 | - err = nfs_negotiate_security(parent, path->dentry, flavor); | |
187 | - if (err < 0) | |
188 | - goto out; | |
189 | - clone = rpc_clone_client(server->client); | |
190 | - auth = rpcauth_create(*flavor, clone); | |
191 | - if (!auth) { | |
192 | - err = -EIO; | |
193 | - goto out_shutdown; | |
194 | - } | |
195 | - err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, | |
196 | - &path->dentry->d_name, | |
197 | - fh, fattr); | |
198 | -out_shutdown: | |
199 | - rpc_shutdown_client(clone); | |
200 | -out: | |
201 | - return err; | |
202 | -} | |
203 | 166 | #else /* CONFIG_NFS_V4 */ |
204 | -static inline int nfs_lookup_with_sec(struct nfs_server *server, | |
205 | - struct dentry *parent, struct dentry *dentry, | |
206 | - struct path *path, struct nfs_fh *fh, | |
207 | - struct nfs_fattr *fattr, | |
208 | - rpc_authflavor_t *flavor) | |
167 | +static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir, | |
168 | + struct qstr *name, | |
169 | + struct nfs_fh *fh, | |
170 | + struct nfs_fattr *fattr) | |
209 | 171 | { |
210 | - return -EPERM; | |
172 | + int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr); | |
173 | + if (err) | |
174 | + return ERR_PTR(err); | |
175 | + return rpc_clone_client(NFS_SERVER(dir)->client); | |
211 | 176 | } |
212 | 177 | #endif /* CONFIG_NFS_V4 */ |
213 | 178 | |
214 | 179 | |
... | ... | @@ -226,12 +191,10 @@ |
226 | 191 | struct vfsmount *nfs_d_automount(struct path *path) |
227 | 192 | { |
228 | 193 | struct vfsmount *mnt; |
229 | - struct nfs_server *server = NFS_SERVER(path->dentry->d_inode); | |
230 | 194 | struct dentry *parent; |
231 | 195 | struct nfs_fh *fh = NULL; |
232 | 196 | struct nfs_fattr *fattr = NULL; |
233 | - int err; | |
234 | - rpc_authflavor_t flavor = RPC_AUTH_UNIX; | |
197 | + struct rpc_clnt *client; | |
235 | 198 | |
236 | 199 | dprintk("--> nfs_d_automount()\n"); |
237 | 200 | |
238 | 201 | |
239 | 202 | |
240 | 203 | |
... | ... | @@ -249,21 +212,19 @@ |
249 | 212 | |
250 | 213 | /* Look it up again to get its attributes */ |
251 | 214 | parent = dget_parent(path->dentry); |
252 | - err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, | |
253 | - &path->dentry->d_name, | |
254 | - fh, fattr); | |
255 | - if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL) | |
256 | - err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor); | |
215 | + client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr); | |
257 | 216 | dput(parent); |
258 | - if (err != 0) { | |
259 | - mnt = ERR_PTR(err); | |
217 | + if (IS_ERR(client)) { | |
218 | + mnt = ERR_CAST(client); | |
260 | 219 | goto out; |
261 | 220 | } |
262 | 221 | |
263 | 222 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
264 | - mnt = nfs_do_refmount(path->dentry); | |
223 | + mnt = nfs_do_refmount(client, path->dentry); | |
265 | 224 | else |
266 | - mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); | |
225 | + mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor); | |
226 | + rpc_shutdown_client(client); | |
227 | + | |
267 | 228 | if (IS_ERR(mnt)) |
268 | 229 | goto out; |
269 | 230 |
fs/nfs/nfs4_fs.h
... | ... | @@ -205,6 +205,9 @@ |
205 | 205 | extern const struct dentry_operations nfs4_dentry_operations; |
206 | 206 | extern const struct inode_operations nfs4_dir_inode_operations; |
207 | 207 | |
208 | +/* nfs4namespace.c */ | |
209 | +struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | |
210 | + | |
208 | 211 | /* nfs4proc.c */ |
209 | 212 | extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *); |
210 | 213 | extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *); |
... | ... | @@ -213,8 +216,11 @@ |
213 | 216 | extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *); |
214 | 217 | extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc); |
215 | 218 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
216 | -extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |
217 | - struct nfs4_fs_locations *fs_locations, struct page *page); | |
219 | +extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *, | |
220 | + struct nfs4_fs_locations *, struct page *); | |
221 | +extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *, | |
222 | + struct nfs_fh *, struct nfs_fattr *); | |
223 | +extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | |
218 | 224 | extern int nfs4_release_lockowner(struct nfs4_lock_state *); |
219 | 225 | extern const struct xattr_handler *nfs4_xattr_handlers[]; |
220 | 226 |
fs/nfs/nfs4filelayoutdev.c
... | ... | @@ -699,7 +699,7 @@ |
699 | 699 | * GETDEVICEINFO's maxcount |
700 | 700 | */ |
701 | 701 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
702 | - max_pages = max_resp_sz >> PAGE_SHIFT; | |
702 | + max_pages = nfs_page_array_len(0, max_resp_sz); | |
703 | 703 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", |
704 | 704 | __func__, inode, max_resp_sz, max_pages); |
705 | 705 |
fs/nfs/nfs4namespace.c
... | ... | @@ -52,6 +52,30 @@ |
52 | 52 | } |
53 | 53 | |
54 | 54 | /* |
55 | + * return the path component of "<server>:<path>" | |
56 | + * nfspath - the "<server>:<path>" string | |
57 | + * end - one past the last char that could contain "<server>:" | |
58 | + * returns NULL on failure | |
59 | + */ | |
60 | +static char *nfs_path_component(const char *nfspath, const char *end) | |
61 | +{ | |
62 | + char *p; | |
63 | + | |
64 | + if (*nfspath == '[') { | |
65 | + /* parse [] escaped IPv6 addrs */ | |
66 | + p = strchr(nfspath, ']'); | |
67 | + if (p != NULL && ++p < end && *p == ':') | |
68 | + return p + 1; | |
69 | + } else { | |
70 | + /* otherwise split on first colon */ | |
71 | + p = strchr(nfspath, ':'); | |
72 | + if (p != NULL && p < end) | |
73 | + return p + 1; | |
74 | + } | |
75 | + return NULL; | |
76 | +} | |
77 | + | |
78 | +/* | |
55 | 79 | * Determine the mount path as a string |
56 | 80 | */ |
57 | 81 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) |
... | ... | @@ -59,9 +83,9 @@ |
59 | 83 | char *limit; |
60 | 84 | char *path = nfs_path(&limit, dentry, buffer, buflen); |
61 | 85 | if (!IS_ERR(path)) { |
62 | - char *colon = strchr(path, ':'); | |
63 | - if (colon && colon < limit) | |
64 | - path = colon + 1; | |
86 | + char *path_component = nfs_path_component(path, limit); | |
87 | + if (path_component) | |
88 | + return path_component; | |
65 | 89 | } |
66 | 90 | return path; |
67 | 91 | } |
... | ... | @@ -108,6 +132,58 @@ |
108 | 132 | return ret; |
109 | 133 | } |
110 | 134 | |
135 | +static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name) | |
136 | +{ | |
137 | + struct page *page; | |
138 | + struct nfs4_secinfo_flavors *flavors; | |
139 | + rpc_authflavor_t flavor; | |
140 | + int err; | |
141 | + | |
142 | + page = alloc_page(GFP_KERNEL); | |
143 | + if (!page) | |
144 | + return -ENOMEM; | |
145 | + flavors = page_address(page); | |
146 | + | |
147 | + err = nfs4_proc_secinfo(inode, name, flavors); | |
148 | + if (err < 0) { | |
149 | + flavor = err; | |
150 | + goto out; | |
151 | + } | |
152 | + | |
153 | + flavor = nfs_find_best_sec(flavors); | |
154 | + | |
155 | +out: | |
156 | + put_page(page); | |
157 | + return flavor; | |
158 | +} | |
159 | + | |
160 | +/* | |
161 | + * Please call rpc_shutdown_client() when you are done with this client. | |
162 | + */ | |
163 | +struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode, | |
164 | + struct qstr *name) | |
165 | +{ | |
166 | + struct rpc_clnt *clone; | |
167 | + struct rpc_auth *auth; | |
168 | + rpc_authflavor_t flavor; | |
169 | + | |
170 | + flavor = nfs4_negotiate_security(inode, name); | |
171 | + if (flavor < 0) | |
172 | + return ERR_PTR(flavor); | |
173 | + | |
174 | + clone = rpc_clone_client(clnt); | |
175 | + if (IS_ERR(clone)) | |
176 | + return clone; | |
177 | + | |
178 | + auth = rpcauth_create(flavor, clone); | |
179 | + if (!auth) { | |
180 | + rpc_shutdown_client(clone); | |
181 | + clone = ERR_PTR(-EIO); | |
182 | + } | |
183 | + | |
184 | + return clone; | |
185 | +} | |
186 | + | |
111 | 187 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, |
112 | 188 | char *page, char *page2, |
113 | 189 | const struct nfs4_fs_location *location) |
... | ... | @@ -224,7 +300,7 @@ |
224 | 300 | * @dentry - dentry of referral |
225 | 301 | * |
226 | 302 | */ |
227 | -struct vfsmount *nfs_do_refmount(struct dentry *dentry) | |
303 | +struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry) | |
228 | 304 | { |
229 | 305 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); |
230 | 306 | struct dentry *parent; |
... | ... | @@ -250,7 +326,7 @@ |
250 | 326 | dprintk("%s: getting locations for %s/%s\n", |
251 | 327 | __func__, parent->d_name.name, dentry->d_name.name); |
252 | 328 | |
253 | - err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page); | |
329 | + err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page); | |
254 | 330 | dput(parent); |
255 | 331 | if (err != 0 || |
256 | 332 | fs_locations->nlocations <= 0 || |
fs/nfs/nfs4proc.c
... | ... | @@ -2377,8 +2377,9 @@ |
2377 | 2377 | * Note that we'll actually follow the referral later when |
2378 | 2378 | * we detect fsid mismatch in inode revalidation |
2379 | 2379 | */ |
2380 | -static int nfs4_get_referral(struct inode *dir, const struct qstr *name, | |
2381 | - struct nfs_fattr *fattr, struct nfs_fh *fhandle) | |
2380 | +static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir, | |
2381 | + const struct qstr *name, struct nfs_fattr *fattr, | |
2382 | + struct nfs_fh *fhandle) | |
2382 | 2383 | { |
2383 | 2384 | int status = -ENOMEM; |
2384 | 2385 | struct page *page = NULL; |
... | ... | @@ -2391,7 +2392,7 @@ |
2391 | 2392 | if (locations == NULL) |
2392 | 2393 | goto out; |
2393 | 2394 | |
2394 | - status = nfs4_proc_fs_locations(dir, name, locations, page); | |
2395 | + status = nfs4_proc_fs_locations(client, dir, name, locations, page); | |
2395 | 2396 | if (status != 0) |
2396 | 2397 | goto out; |
2397 | 2398 | /* Make sure server returned a different fsid for the referral */ |
2398 | 2399 | |
2399 | 2400 | |
2400 | 2401 | |
2401 | 2402 | |
2402 | 2403 | |
2403 | 2404 | |
2404 | 2405 | |
2405 | 2406 | |
2406 | 2407 | |
2407 | 2408 | |
2408 | 2409 | |
... | ... | @@ -2528,39 +2529,84 @@ |
2528 | 2529 | return status; |
2529 | 2530 | } |
2530 | 2531 | |
2531 | -void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) | |
2532 | +static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr) | |
2532 | 2533 | { |
2533 | - memset(fh, 0, sizeof(struct nfs_fh)); | |
2534 | - fattr->fsid.major = 1; | |
2535 | 2534 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | |
2536 | - NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; | |
2535 | + NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT; | |
2537 | 2536 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; |
2538 | 2537 | fattr->nlink = 2; |
2539 | 2538 | } |
2540 | 2539 | |
2541 | -static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | |
2542 | - struct nfs_fh *fhandle, struct nfs_fattr *fattr) | |
2540 | +static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir, | |
2541 | + struct qstr *name, struct nfs_fh *fhandle, | |
2542 | + struct nfs_fattr *fattr) | |
2543 | 2543 | { |
2544 | 2544 | struct nfs4_exception exception = { }; |
2545 | + struct rpc_clnt *client = *clnt; | |
2545 | 2546 | int err; |
2546 | 2547 | do { |
2547 | - int status; | |
2548 | - | |
2549 | - status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr); | |
2550 | - switch (status) { | |
2548 | + err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr); | |
2549 | + switch (err) { | |
2551 | 2550 | case -NFS4ERR_BADNAME: |
2552 | - return -ENOENT; | |
2551 | + err = -ENOENT; | |
2552 | + goto out; | |
2553 | 2553 | case -NFS4ERR_MOVED: |
2554 | - return nfs4_get_referral(dir, name, fattr, fhandle); | |
2554 | + err = nfs4_get_referral(client, dir, name, fattr, fhandle); | |
2555 | + goto out; | |
2555 | 2556 | case -NFS4ERR_WRONGSEC: |
2556 | - nfs_fixup_secinfo_attributes(fattr, fhandle); | |
2557 | + err = -EPERM; | |
2558 | + if (client != *clnt) | |
2559 | + goto out; | |
2560 | + | |
2561 | + client = nfs4_create_sec_client(client, dir, name); | |
2562 | + if (IS_ERR(client)) | |
2563 | + return PTR_ERR(client); | |
2564 | + | |
2565 | + exception.retry = 1; | |
2566 | + break; | |
2567 | + default: | |
2568 | + err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception); | |
2557 | 2569 | } |
2558 | - err = nfs4_handle_exception(NFS_SERVER(dir), | |
2559 | - status, &exception); | |
2560 | 2570 | } while (exception.retry); |
2571 | + | |
2572 | +out: | |
2573 | + if (err == 0) | |
2574 | + *clnt = client; | |
2575 | + else if (client != *clnt) | |
2576 | + rpc_shutdown_client(client); | |
2577 | + | |
2561 | 2578 | return err; |
2562 | 2579 | } |
2563 | 2580 | |
2581 | +static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | |
2582 | + struct nfs_fh *fhandle, struct nfs_fattr *fattr) | |
2583 | +{ | |
2584 | + int status; | |
2585 | + struct rpc_clnt *client = NFS_CLIENT(dir); | |
2586 | + | |
2587 | + status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | |
2588 | + if (client != NFS_CLIENT(dir)) { | |
2589 | + rpc_shutdown_client(client); | |
2590 | + nfs_fixup_secinfo_attributes(fattr); | |
2591 | + } | |
2592 | + return status; | |
2593 | +} | |
2594 | + | |
2595 | +struct rpc_clnt * | |
2596 | +nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name, | |
2597 | + struct nfs_fh *fhandle, struct nfs_fattr *fattr) | |
2598 | +{ | |
2599 | + int status; | |
2600 | + struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir)); | |
2601 | + | |
2602 | + status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr); | |
2603 | + if (status < 0) { | |
2604 | + rpc_shutdown_client(client); | |
2605 | + return ERR_PTR(status); | |
2606 | + } | |
2607 | + return client; | |
2608 | +} | |
2609 | + | |
2564 | 2610 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
2565 | 2611 | { |
2566 | 2612 | struct nfs_server *server = NFS_SERVER(inode); |
2567 | 2613 | |
2568 | 2614 | |
... | ... | @@ -3628,16 +3674,16 @@ |
3628 | 3674 | return ret; |
3629 | 3675 | } |
3630 | 3676 | |
3631 | -static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len) | |
3677 | +static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) | |
3632 | 3678 | { |
3633 | 3679 | struct nfs4_cached_acl *acl; |
3634 | 3680 | |
3635 | - if (buf && acl_len <= PAGE_SIZE) { | |
3681 | + if (pages && acl_len <= PAGE_SIZE) { | |
3636 | 3682 | acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); |
3637 | 3683 | if (acl == NULL) |
3638 | 3684 | goto out; |
3639 | 3685 | acl->cached = 1; |
3640 | - memcpy(acl->data, buf, acl_len); | |
3686 | + _copy_from_pages(acl->data, pages, pgbase, acl_len); | |
3641 | 3687 | } else { |
3642 | 3688 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); |
3643 | 3689 | if (acl == NULL) |
... | ... | @@ -3670,7 +3716,6 @@ |
3670 | 3716 | struct nfs_getaclres res = { |
3671 | 3717 | .acl_len = buflen, |
3672 | 3718 | }; |
3673 | - void *resp_buf; | |
3674 | 3719 | struct rpc_message msg = { |
3675 | 3720 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL], |
3676 | 3721 | .rpc_argp = &args, |
3677 | 3722 | |
3678 | 3723 | |
3679 | 3724 | |
... | ... | @@ -3684,24 +3729,27 @@ |
3684 | 3729 | if (npages == 0) |
3685 | 3730 | npages = 1; |
3686 | 3731 | |
3732 | + /* Add an extra page to handle the bitmap returned */ | |
3733 | + npages++; | |
3734 | + | |
3687 | 3735 | for (i = 0; i < npages; i++) { |
3688 | 3736 | pages[i] = alloc_page(GFP_KERNEL); |
3689 | 3737 | if (!pages[i]) |
3690 | 3738 | goto out_free; |
3691 | 3739 | } |
3692 | - if (npages > 1) { | |
3693 | - /* for decoding across pages */ | |
3694 | - res.acl_scratch = alloc_page(GFP_KERNEL); | |
3695 | - if (!res.acl_scratch) | |
3696 | - goto out_free; | |
3697 | - } | |
3740 | + | |
3741 | + /* for decoding across pages */ | |
3742 | + res.acl_scratch = alloc_page(GFP_KERNEL); | |
3743 | + if (!res.acl_scratch) | |
3744 | + goto out_free; | |
3745 | + | |
3698 | 3746 | args.acl_len = npages * PAGE_SIZE; |
3699 | 3747 | args.acl_pgbase = 0; |
3748 | + | |
3700 | 3749 | /* Let decode_getfacl know not to fail if the ACL data is larger than |
3701 | 3750 | * the page we send as a guess */ |
3702 | 3751 | if (buf == NULL) |
3703 | 3752 | res.acl_flags |= NFS4_ACL_LEN_REQUEST; |
3704 | - resp_buf = page_address(pages[0]); | |
3705 | 3753 | |
3706 | 3754 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", |
3707 | 3755 | __func__, buf, buflen, npages, args.acl_len); |
3708 | 3756 | |
... | ... | @@ -3712,9 +3760,9 @@ |
3712 | 3760 | |
3713 | 3761 | acl_len = res.acl_len - res.acl_data_offset; |
3714 | 3762 | if (acl_len > args.acl_len) |
3715 | - nfs4_write_cached_acl(inode, NULL, acl_len); | |
3763 | + nfs4_write_cached_acl(inode, NULL, 0, acl_len); | |
3716 | 3764 | else |
3717 | - nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset, | |
3765 | + nfs4_write_cached_acl(inode, pages, res.acl_data_offset, | |
3718 | 3766 | acl_len); |
3719 | 3767 | if (buf) { |
3720 | 3768 | ret = -ERANGE; |
... | ... | @@ -4919,8 +4967,10 @@ |
4919 | 4967 | fattr->nlink = 2; |
4920 | 4968 | } |
4921 | 4969 | |
4922 | -int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |
4923 | - struct nfs4_fs_locations *fs_locations, struct page *page) | |
4970 | +static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |
4971 | + const struct qstr *name, | |
4972 | + struct nfs4_fs_locations *fs_locations, | |
4973 | + struct page *page) | |
4924 | 4974 | { |
4925 | 4975 | struct nfs_server *server = NFS_SERVER(dir); |
4926 | 4976 | u32 bitmask[2] = { |
4927 | 4977 | |
... | ... | @@ -4954,11 +5004,26 @@ |
4954 | 5004 | nfs_fattr_init(&fs_locations->fattr); |
4955 | 5005 | fs_locations->server = server; |
4956 | 5006 | fs_locations->nlocations = 0; |
4957 | - status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | |
5007 | + status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0); | |
4958 | 5008 | dprintk("%s: returned status = %d\n", __func__, status); |
4959 | 5009 | return status; |
4960 | 5010 | } |
4961 | 5011 | |
5012 | +int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, | |
5013 | + const struct qstr *name, | |
5014 | + struct nfs4_fs_locations *fs_locations, | |
5015 | + struct page *page) | |
5016 | +{ | |
5017 | + struct nfs4_exception exception = { }; | |
5018 | + int err; | |
5019 | + do { | |
5020 | + err = nfs4_handle_exception(NFS_SERVER(dir), | |
5021 | + _nfs4_proc_fs_locations(client, dir, name, fs_locations, page), | |
5022 | + &exception); | |
5023 | + } while (exception.retry); | |
5024 | + return err; | |
5025 | +} | |
5026 | + | |
4962 | 5027 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) |
4963 | 5028 | { |
4964 | 5029 | int status; |
... | ... | @@ -4981,8 +5046,8 @@ |
4981 | 5046 | return status; |
4982 | 5047 | } |
4983 | 5048 | |
4984 | -static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | |
4985 | - struct nfs4_secinfo_flavors *flavors) | |
5049 | +int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, | |
5050 | + struct nfs4_secinfo_flavors *flavors) | |
4986 | 5051 | { |
4987 | 5052 | struct nfs4_exception exception = { }; |
4988 | 5053 | int err; |
4989 | 5054 | |
... | ... | @@ -5057,10 +5122,9 @@ |
5057 | 5122 | nfs4_construct_boot_verifier(clp, &verifier); |
5058 | 5123 | |
5059 | 5124 | args.id_len = scnprintf(args.id, sizeof(args.id), |
5060 | - "%s/%s.%s/%u", | |
5125 | + "%s/%s/%u", | |
5061 | 5126 | clp->cl_ipaddr, |
5062 | - init_utsname()->nodename, | |
5063 | - init_utsname()->domainname, | |
5127 | + clp->cl_rpcclient->cl_nodename, | |
5064 | 5128 | clp->cl_rpcclient->cl_auth->au_flavor); |
5065 | 5129 | |
5066 | 5130 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); |
fs/nfs/nfs4xdr.c
... | ... | @@ -4258,8 +4258,6 @@ |
4258 | 4258 | status = decode_attr_error(xdr, bitmap, &err); |
4259 | 4259 | if (status < 0) |
4260 | 4260 | goto xdr_error; |
4261 | - if (err == -NFS4ERR_WRONGSEC) | |
4262 | - nfs_fixup_secinfo_attributes(fattr, fh); | |
4263 | 4261 | |
4264 | 4262 | status = decode_attr_filehandle(xdr, bitmap, fh); |
4265 | 4263 | if (status < 0) |
4266 | 4264 | |
4267 | 4265 | |
... | ... | @@ -4902,11 +4900,19 @@ |
4902 | 4900 | bitmap[3] = {0}; |
4903 | 4901 | struct kvec *iov = req->rq_rcv_buf.head; |
4904 | 4902 | int status; |
4903 | + size_t page_len = xdr->buf->page_len; | |
4905 | 4904 | |
4906 | 4905 | res->acl_len = 0; |
4907 | 4906 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
4908 | 4907 | goto out; |
4908 | + | |
4909 | 4909 | bm_p = xdr->p; |
4910 | + res->acl_data_offset = be32_to_cpup(bm_p) + 2; | |
4911 | + res->acl_data_offset <<= 2; | |
4912 | + /* Check if the acl data starts beyond the allocated buffer */ | |
4913 | + if (res->acl_data_offset > page_len) | |
4914 | + return -ERANGE; | |
4915 | + | |
4910 | 4916 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
4911 | 4917 | goto out; |
4912 | 4918 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) |
4913 | 4919 | |
4914 | 4920 | |
4915 | 4921 | |
... | ... | @@ -4916,28 +4922,24 @@ |
4916 | 4922 | return -EIO; |
4917 | 4923 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
4918 | 4924 | size_t hdrlen; |
4919 | - u32 recvd; | |
4920 | 4925 | |
4921 | 4926 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
4922 | 4927 | * are stored with the acl data to handle the problem of |
4923 | 4928 | * variable length bitmaps.*/ |
4924 | 4929 | xdr->p = bm_p; |
4925 | - res->acl_data_offset = be32_to_cpup(bm_p) + 2; | |
4926 | - res->acl_data_offset <<= 2; | |
4927 | 4930 | |
4928 | 4931 | /* We ignore &savep and don't do consistency checks on |
4929 | 4932 | * the attr length. Let userspace figure it out.... */ |
4930 | 4933 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; |
4931 | 4934 | attrlen += res->acl_data_offset; |
4932 | - recvd = req->rq_rcv_buf.len - hdrlen; | |
4933 | - if (attrlen > recvd) { | |
4935 | + if (attrlen > page_len) { | |
4934 | 4936 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
4935 | 4937 | /* getxattr interface called with a NULL buf */ |
4936 | 4938 | res->acl_len = attrlen; |
4937 | 4939 | goto out; |
4938 | 4940 | } |
4939 | - dprintk("NFS: acl reply: attrlen %u > recvd %u\n", | |
4940 | - attrlen, recvd); | |
4941 | + dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", | |
4942 | + attrlen, page_len); | |
4941 | 4943 | return -EINVAL; |
4942 | 4944 | } |
4943 | 4945 | xdr_read_pages(xdr, attrlen); |
4944 | 4946 | |
... | ... | @@ -5090,16 +5092,13 @@ |
5090 | 5092 | return -EINVAL; |
5091 | 5093 | } |
5092 | 5094 | |
5093 | -static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |
5095 | +static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |
5094 | 5096 | { |
5095 | 5097 | struct nfs4_secinfo_flavor *sec_flavor; |
5096 | 5098 | int status; |
5097 | 5099 | __be32 *p; |
5098 | 5100 | int i, num_flavors; |
5099 | 5101 | |
5100 | - status = decode_op_hdr(xdr, OP_SECINFO); | |
5101 | - if (status) | |
5102 | - goto out; | |
5103 | 5102 | p = xdr_inline_decode(xdr, 4); |
5104 | 5103 | if (unlikely(!p)) |
5105 | 5104 | goto out_overflow; |
... | ... | @@ -5125,6 +5124,7 @@ |
5125 | 5124 | res->flavors->num_flavors++; |
5126 | 5125 | } |
5127 | 5126 | |
5127 | + status = 0; | |
5128 | 5128 | out: |
5129 | 5129 | return status; |
5130 | 5130 | out_overflow: |
5131 | 5131 | |
... | ... | @@ -5132,7 +5132,23 @@ |
5132 | 5132 | return -EIO; |
5133 | 5133 | } |
5134 | 5134 | |
5135 | +static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |
5136 | +{ | |
5137 | + int status = decode_op_hdr(xdr, OP_SECINFO); | |
5138 | + if (status) | |
5139 | + return status; | |
5140 | + return decode_secinfo_common(xdr, res); | |
5141 | +} | |
5142 | + | |
5135 | 5143 | #if defined(CONFIG_NFS_V4_1) |
5144 | +static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |
5145 | +{ | |
5146 | + int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME); | |
5147 | + if (status) | |
5148 | + return status; | |
5149 | + return decode_secinfo_common(xdr, res); | |
5150 | +} | |
5151 | + | |
5136 | 5152 | static int decode_exchange_id(struct xdr_stream *xdr, |
5137 | 5153 | struct nfs41_exchange_id_res *res) |
5138 | 5154 | { |
... | ... | @@ -6817,7 +6833,7 @@ |
6817 | 6833 | status = decode_putrootfh(xdr); |
6818 | 6834 | if (status) |
6819 | 6835 | goto out; |
6820 | - status = decode_secinfo(xdr, res); | |
6836 | + status = decode_secinfo_no_name(xdr, res); | |
6821 | 6837 | out: |
6822 | 6838 | return status; |
6823 | 6839 | } |
fs/nfs/objlayout/objlayout.c
... | ... | @@ -604,7 +604,6 @@ |
604 | 604 | { |
605 | 605 | struct objlayout_deviceinfo *odi; |
606 | 606 | struct pnfs_device pd; |
607 | - struct super_block *sb; | |
608 | 607 | struct page *page, **pages; |
609 | 608 | u32 *p; |
610 | 609 | int err; |
... | ... | @@ -623,7 +622,6 @@ |
623 | 622 | pd.pglen = PAGE_SIZE; |
624 | 623 | pd.mincount = 0; |
625 | 624 | |
626 | - sb = pnfslay->plh_inode->i_sb; | |
627 | 625 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); |
628 | 626 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); |
629 | 627 | if (err) |
fs/nfs/pnfs.c
... | ... | @@ -587,7 +587,7 @@ |
587 | 587 | |
588 | 588 | /* allocate pages for xdr post processing */ |
589 | 589 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
590 | - max_pages = max_resp_sz >> PAGE_SHIFT; | |
590 | + max_pages = nfs_page_array_len(0, max_resp_sz); | |
591 | 591 | |
592 | 592 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); |
593 | 593 | if (!pages) |
fs/nfs/super.c
... | ... | @@ -2428,7 +2428,7 @@ |
2428 | 2428 | dprintk("--> nfs_xdev_mount()\n"); |
2429 | 2429 | |
2430 | 2430 | /* create a new volume representation */ |
2431 | - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | |
2431 | + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); | |
2432 | 2432 | if (IS_ERR(server)) { |
2433 | 2433 | error = PTR_ERR(server); |
2434 | 2434 | goto out_err_noserver; |
... | ... | @@ -2955,7 +2955,7 @@ |
2955 | 2955 | dprintk("--> nfs4_xdev_mount()\n"); |
2956 | 2956 | |
2957 | 2957 | /* create a new volume representation */ |
2958 | - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | |
2958 | + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); | |
2959 | 2959 | if (IS_ERR(server)) { |
2960 | 2960 | error = PTR_ERR(server); |
2961 | 2961 | goto out_err_noserver; |
net/sunrpc/clnt.c
... | ... | @@ -176,16 +176,22 @@ |
176 | 176 | return 0; |
177 | 177 | } |
178 | 178 | |
179 | -static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, | |
180 | - struct super_block *sb) | |
179 | +static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) | |
181 | 180 | { |
181 | + if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | |
182 | + ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | |
183 | + return 1; | |
184 | + return 0; | |
185 | +} | |
186 | + | |
187 | +static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, | |
188 | + struct super_block *sb) | |
189 | +{ | |
182 | 190 | struct dentry *dentry; |
183 | 191 | int err = 0; |
184 | 192 | |
185 | 193 | switch (event) { |
186 | 194 | case RPC_PIPEFS_MOUNT: |
187 | - if (clnt->cl_program->pipe_dir_name == NULL) | |
188 | - break; | |
189 | 195 | dentry = rpc_setup_pipedir_sb(sb, clnt, |
190 | 196 | clnt->cl_program->pipe_dir_name); |
191 | 197 | BUG_ON(dentry == NULL); |
... | ... | @@ -208,6 +214,20 @@ |
208 | 214 | return err; |
209 | 215 | } |
210 | 216 | |
217 | +static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, | |
218 | + struct super_block *sb) | |
219 | +{ | |
220 | + int error = 0; | |
221 | + | |
222 | + for (;; clnt = clnt->cl_parent) { | |
223 | + if (!rpc_clnt_skip_event(clnt, event)) | |
224 | + error = __rpc_clnt_handle_event(clnt, event, sb); | |
225 | + if (error || clnt == clnt->cl_parent) | |
226 | + break; | |
227 | + } | |
228 | + return error; | |
229 | +} | |
230 | + | |
211 | 231 | static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) |
212 | 232 | { |
213 | 233 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
214 | 234 | |
... | ... | @@ -215,10 +235,12 @@ |
215 | 235 | |
216 | 236 | spin_lock(&sn->rpc_client_lock); |
217 | 237 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
218 | - if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | |
219 | - ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | |
238 | + if (clnt->cl_program->pipe_dir_name == NULL) | |
239 | + break; | |
240 | + if (rpc_clnt_skip_event(clnt, event)) | |
220 | 241 | continue; |
221 | - atomic_inc(&clnt->cl_count); | |
242 | + if (atomic_inc_not_zero(&clnt->cl_count) == 0) | |
243 | + continue; | |
222 | 244 | spin_unlock(&sn->rpc_client_lock); |
223 | 245 | return clnt; |
224 | 246 | } |
... | ... | @@ -257,6 +279,14 @@ |
257 | 279 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); |
258 | 280 | } |
259 | 281 | |
282 | +static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |
283 | +{ | |
284 | + clnt->cl_nodelen = strlen(nodename); | |
285 | + if (clnt->cl_nodelen > UNX_MAXNODENAME) | |
286 | + clnt->cl_nodelen = UNX_MAXNODENAME; | |
287 | + memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | |
288 | +} | |
289 | + | |
260 | 290 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
261 | 291 | { |
262 | 292 | const struct rpc_program *program = args->program; |
... | ... | @@ -337,10 +367,7 @@ |
337 | 367 | } |
338 | 368 | |
339 | 369 | /* save the nodename */ |
340 | - clnt->cl_nodelen = strlen(init_utsname()->nodename); | |
341 | - if (clnt->cl_nodelen > UNX_MAXNODENAME) | |
342 | - clnt->cl_nodelen = UNX_MAXNODENAME; | |
343 | - memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen); | |
370 | + rpc_clnt_set_nodename(clnt, utsname()->nodename); | |
344 | 371 | rpc_register_client(clnt); |
345 | 372 | return clnt; |
346 | 373 | |
... | ... | @@ -499,6 +526,7 @@ |
499 | 526 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
500 | 527 | if (err != 0) |
501 | 528 | goto out_no_path; |
529 | + rpc_clnt_set_nodename(new, utsname()->nodename); | |
502 | 530 | if (new->cl_auth) |
503 | 531 | atomic_inc(&new->cl_auth->au_count); |
504 | 532 | atomic_inc(&clnt->cl_count); |
net/sunrpc/rpc_pipe.c
... | ... | @@ -1126,19 +1126,20 @@ |
1126 | 1126 | return -ENOMEM; |
1127 | 1127 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", net, |
1128 | 1128 | NET_NAME(net)); |
1129 | + sn->pipefs_sb = sb; | |
1129 | 1130 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1130 | 1131 | RPC_PIPEFS_MOUNT, |
1131 | 1132 | sb); |
1132 | 1133 | if (err) |
1133 | 1134 | goto err_depopulate; |
1134 | 1135 | sb->s_fs_info = get_net(net); |
1135 | - sn->pipefs_sb = sb; | |
1136 | 1136 | return 0; |
1137 | 1137 | |
1138 | 1138 | err_depopulate: |
1139 | 1139 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, |
1140 | 1140 | RPC_PIPEFS_UMOUNT, |
1141 | 1141 | sb); |
1142 | + sn->pipefs_sb = NULL; | |
1142 | 1143 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); |
1143 | 1144 | return err; |
1144 | 1145 | } |