Commit 529acf58981440eefeaf1451387e2a0aa4825c12

Authored by Linus Torvalds

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
... ... @@ -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  
... ... @@ -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))
... ... @@ -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  
... ... @@ -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);
... ... @@ -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  
... ... @@ -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 ||
... ... @@ -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);
... ... @@ -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)
... ... @@ -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)
... ... @@ -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;
... ... @@ -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 }