Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 529acf58 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents b821861b 3617e503
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
#include <linux/buffer_head.h>	/* various write calls */
#include <linux/prefetch.h>

#include "../pnfs.h"
#include "../internal.h"
#include "blocklayout.h"

#define NFSDBG_FACILITY	NFSDBG_PNFS_LD
@@ -868,7 +870,7 @@ nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
	 * GETDEVICEINFO's maxcount
	 */
	max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
	max_pages = max_resp_sz >> PAGE_SHIFT;
	max_pages = nfs_page_array_len(0, max_resp_sz);
	dprintk("%s max_resp_sz %u max_pages %d\n",
		__func__, max_resp_sz, max_pages);

+3 −2
Original line number Diff line number Diff line
@@ -1729,7 +1729,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
 */
struct nfs_server *nfs_clone_server(struct nfs_server *source,
				    struct nfs_fh *fh,
				    struct nfs_fattr *fattr)
				    struct nfs_fattr *fattr,
				    rpc_authflavor_t flavor)
{
	struct nfs_server *server;
	struct nfs_fattr *fattr_fsinfo;
@@ -1758,7 +1759,7 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,

	error = nfs_init_server_rpcclient(server,
			source->client->cl_timeout,
			source->client->cl_auth->au_flavor);
			flavor);
	if (error < 0)
		goto out_free_server;
	if (!IS_ERR(source->client_acl))
+4 −0
Original line number Diff line number Diff line
@@ -554,12 +554,16 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
	struct nfs_client *clp;
	int error = 0;

	if (!try_module_get(THIS_MODULE))
		return 0;

	while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
		error = __rpc_pipefs_event(clp, event, sb);
		nfs_put_client(clp);
		if (error)
			break;
	}
	module_put(THIS_MODULE);
	return error;
}

+4 −4
Original line number Diff line number Diff line
@@ -165,7 +165,8 @@ extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
extern void nfs_free_server(struct nfs_server *server);
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
					   struct nfs_fh *,
					   struct nfs_fattr *);
					   struct nfs_fattr *,
					   rpc_authflavor_t);
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
extern int nfs4_check_client_ready(struct nfs_client *clp);
extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
@@ -186,10 +187,10 @@ static inline void nfs_fs_proc_exit(void)

/* nfs4namespace.c */
#ifdef CONFIG_NFS_V4
extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry);
#else
static inline
struct vfsmount *nfs_do_refmount(struct dentry *dentry)
struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
{
	return ERR_PTR(-ENOENT);
}
@@ -234,7 +235,6 @@ extern const u32 nfs41_maxwrite_overhead;
/* nfs4proc.c */
#ifdef CONFIG_NFS_V4
extern struct rpc_procinfo nfs4_procedures[];
void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *);
#endif

extern int nfs4_init_ds_session(struct nfs_client *clp);
+27 −66
Original line number Diff line number Diff line
@@ -148,66 +148,31 @@ rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
	return pseudoflavor;
}

static int nfs_negotiate_security(const struct dentry *parent,
				  const struct dentry *dentry,
				  rpc_authflavor_t *flavor)
{
	struct page *page;
	struct nfs4_secinfo_flavors *flavors;
	int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
	int ret = -EPERM;

	secinfo = NFS_PROTO(parent->d_inode)->secinfo;
	if (secinfo != NULL) {
		page = alloc_page(GFP_KERNEL);
		if (!page) {
			ret = -ENOMEM;
			goto out;
		}
		flavors = page_address(page);
		ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
		*flavor = nfs_find_best_sec(flavors);
		put_page(page);
	}

out:
	return ret;
}

static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent,
			       struct dentry *dentry, struct path *path,
			       struct nfs_fh *fh, struct nfs_fattr *fattr,
			       rpc_authflavor_t *flavor)
static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
					      struct qstr *name,
					      struct nfs_fh *fh,
					      struct nfs_fattr *fattr)
{
	struct rpc_clnt *clone;
	struct rpc_auth *auth;
	int err;

	err = nfs_negotiate_security(parent, path->dentry, flavor);
	if (err < 0)
		goto out;
	clone  = rpc_clone_client(server->client);
	auth   = rpcauth_create(*flavor, clone);
	if (!auth) {
		err = -EIO;
		goto out_shutdown;
	}
	err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode,
						  &path->dentry->d_name,
						  fh, fattr);
out_shutdown:
	rpc_shutdown_client(clone);
out:
	return err;
	if (NFS_PROTO(dir)->version == 4)
		return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr);

	err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
	if (err)
		return ERR_PTR(err);
	return rpc_clone_client(NFS_SERVER(dir)->client);
}
#else /* CONFIG_NFS_V4 */
static inline int nfs_lookup_with_sec(struct nfs_server *server,
				      struct dentry *parent, struct dentry *dentry,
				      struct path *path, struct nfs_fh *fh,
				      struct nfs_fattr *fattr,
				      rpc_authflavor_t *flavor)
static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
						     struct qstr *name,
						     struct nfs_fh *fh,
						     struct nfs_fattr *fattr)
{
	return -EPERM;
	int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
	if (err)
		return ERR_PTR(err);
	return rpc_clone_client(NFS_SERVER(dir)->client);
}
#endif /* CONFIG_NFS_V4 */

@@ -226,12 +191,10 @@ static inline int nfs_lookup_with_sec(struct nfs_server *server,
struct vfsmount *nfs_d_automount(struct path *path)
{
	struct vfsmount *mnt;
	struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
	struct dentry *parent;
	struct nfs_fh *fh = NULL;
	struct nfs_fattr *fattr = NULL;
	int err;
	rpc_authflavor_t flavor = RPC_AUTH_UNIX;
	struct rpc_clnt *client;

	dprintk("--> nfs_d_automount()\n");

@@ -249,21 +212,19 @@ struct vfsmount *nfs_d_automount(struct path *path)

	/* Look it up again to get its attributes */
	parent = dget_parent(path->dentry);
	err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
						  &path->dentry->d_name,
						  fh, fattr);
	if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
		err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
	client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
	dput(parent);
	if (err != 0) {
		mnt = ERR_PTR(err);
	if (IS_ERR(client)) {
		mnt = ERR_CAST(client);
		goto out;
	}

	if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
		mnt = nfs_do_refmount(path->dentry);
		mnt = nfs_do_refmount(client, path->dentry);
	else
		mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
		mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor);
	rpc_shutdown_client(client);

	if (IS_ERR(mnt))
		goto out;

Loading