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

Commit e7865c23 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
  NFSv4: Fix an embarassing typo in encode_attrs()
  NFSv4: Ensure that /proc/self/mountinfo displays the minor version number
  NFSv4.1: Ensure that we initialise the session when following a referral
  SUNRPC: Fix a re-entrancy bug in xs_tcp_read_calldir()
  nfs4 use mandatory attribute file type in nfs4_get_root
parents bf293769 d3f6baaa
Loading
Loading
Loading
Loading
+51 −71
Original line number Original line Diff line number Diff line
@@ -1286,6 +1286,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server)
#endif /* CONFIG_NFS_V4_1 */
#endif /* CONFIG_NFS_V4_1 */
}
}


static int nfs4_server_common_setup(struct nfs_server *server,
		struct nfs_fh *mntfh)
{
	struct nfs_fattr *fattr;
	int error;

	BUG_ON(!server->nfs_client);
	BUG_ON(!server->nfs_client->rpc_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);

	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
		return -ENOMEM;

	/* We must ensure the session is initialised first */
	error = nfs4_init_session(server);
	if (error < 0)
		goto out;

	/* Probe the root fh to retrieve its FSID and filehandle */
	error = nfs4_get_rootfh(server, mntfh);
	if (error < 0)
		goto out;

	dprintk("Server FSID: %llx:%llx\n",
			(unsigned long long) server->fsid.major,
			(unsigned long long) server->fsid.minor);
	dprintk("Mount FH: %d\n", mntfh->size);

	nfs4_session_set_rwsize(server);

	error = nfs_probe_fsinfo(server, mntfh, fattr);
	if (error < 0)
		goto out;

	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
		server->namelen = NFS4_MAXNAMLEN;

	spin_lock(&nfs_client_lock);
	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
	list_add_tail(&server->master_link, &nfs_volume_list);
	spin_unlock(&nfs_client_lock);

	server->mount_time = jiffies;
out:
	nfs_free_fattr(fattr);
	return error;
}

/*
/*
 * Create a version 4 volume record
 * Create a version 4 volume record
 */
 */
@@ -1346,7 +1395,6 @@ error:
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
				      struct nfs_fh *mntfh)
				      struct nfs_fh *mntfh)
{
{
	struct nfs_fattr *fattr;
	struct nfs_server *server;
	struct nfs_server *server;
	int error;
	int error;


@@ -1356,55 +1404,19 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
	if (!server)
	if (!server)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	error = -ENOMEM;
	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
		goto error;

	/* set up the general RPC client */
	/* set up the general RPC client */
	error = nfs4_init_server(server, data);
	error = nfs4_init_server(server, data);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	BUG_ON(!server->nfs_client);
	error = nfs4_server_common_setup(server, mntfh);
	BUG_ON(!server->nfs_client->rpc_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);

	error = nfs4_init_session(server);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	/* Probe the root fh to retrieve its FSID */
	error = nfs4_get_rootfh(server, mntfh);
	if (error < 0)
		goto error;

	dprintk("Server FSID: %llx:%llx\n",
		(unsigned long long) server->fsid.major,
		(unsigned long long) server->fsid.minor);
	dprintk("Mount FH: %d\n", mntfh->size);

	nfs4_session_set_rwsize(server);

	error = nfs_probe_fsinfo(server, mntfh, fattr);
	if (error < 0)
		goto error;

	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
		server->namelen = NFS4_MAXNAMLEN;

	spin_lock(&nfs_client_lock);
	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
	list_add_tail(&server->master_link, &nfs_volume_list);
	spin_unlock(&nfs_client_lock);

	server->mount_time = jiffies;
	dprintk("<-- nfs4_create_server() = %p\n", server);
	dprintk("<-- nfs4_create_server() = %p\n", server);
	nfs_free_fattr(fattr);
	return server;
	return server;


error:
error:
	nfs_free_fattr(fattr);
	nfs_free_server(server);
	nfs_free_server(server);
	dprintk("<-- nfs4_create_server() = error %d\n", error);
	dprintk("<-- nfs4_create_server() = error %d\n", error);
	return ERR_PTR(error);
	return ERR_PTR(error);
@@ -1418,7 +1430,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
{
{
	struct nfs_client *parent_client;
	struct nfs_client *parent_client;
	struct nfs_server *server, *parent_server;
	struct nfs_server *server, *parent_server;
	struct nfs_fattr *fattr;
	int error;
	int error;


	dprintk("--> nfs4_create_referral_server()\n");
	dprintk("--> nfs4_create_referral_server()\n");
@@ -1427,11 +1438,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
	if (!server)
	if (!server)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	error = -ENOMEM;
	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
		goto error;

	parent_server = NFS_SB(data->sb);
	parent_server = NFS_SB(data->sb);
	parent_client = parent_server->nfs_client;
	parent_client = parent_server->nfs_client;


@@ -1456,40 +1462,14 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	BUG_ON(!server->nfs_client);
	error = nfs4_server_common_setup(server, mntfh);
	BUG_ON(!server->nfs_client->rpc_ops);
	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);

	/* Probe the root fh to retrieve its FSID and filehandle */
	error = nfs4_get_rootfh(server, mntfh);
	if (error < 0)
		goto error;

	/* probe the filesystem info for this server filesystem */
	error = nfs_probe_fsinfo(server, mntfh, fattr);
	if (error < 0)
	if (error < 0)
		goto error;
		goto error;


	if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
		server->namelen = NFS4_MAXNAMLEN;

	dprintk("Referral FSID: %llx:%llx\n",
		(unsigned long long) server->fsid.major,
		(unsigned long long) server->fsid.minor);

	spin_lock(&nfs_client_lock);
	list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks);
	list_add_tail(&server->master_link, &nfs_volume_list);
	spin_unlock(&nfs_client_lock);

	server->mount_time = jiffies;

	nfs_free_fattr(fattr);
	dprintk("<-- nfs_create_referral_server() = %p\n", server);
	dprintk("<-- nfs_create_referral_server() = %p\n", server);
	return server;
	return server;


error:
error:
	nfs_free_fattr(fattr);
	nfs_free_server(server);
	nfs_free_server(server);
	dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
	dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
	return ERR_PTR(error);
	return ERR_PTR(error);
+1 −1
Original line number Original line Diff line number Diff line
@@ -146,7 +146,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
		goto out;
		goto out;
	}
	}


	if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE)
	if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
			|| !S_ISDIR(fsinfo.fattr->mode)) {
			|| !S_ISDIR(fsinfo.fattr->mode)) {
		printk(KERN_ERR "nfs4_get_rootfh:"
		printk(KERN_ERR "nfs4_get_rootfh:"
		       " getroot encountered non-directory\n");
		       " getroot encountered non-directory\n");
+2 −2
Original line number Original line Diff line number Diff line
@@ -862,8 +862,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
		*p++ = cpu_to_be32(0);
		*p++ = cpu_to_be32(0);
		*p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
		*p++ = cpu_to_be32(iap->ia_atime.tv_sec);
		*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
		*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
	}
	}
	else if (iap->ia_valid & ATTR_ATIME) {
	else if (iap->ia_valid & ATTR_ATIME) {
		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
+18 −4
Original line number Original line Diff line number Diff line
@@ -570,6 +570,22 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
	nfs_show_mountd_netid(m, nfss, showdefaults);
	nfs_show_mountd_netid(m, nfss, showdefaults);
}
}


#ifdef CONFIG_NFS_V4
static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
				    int showdefaults)
{
	struct nfs_client *clp = nfss->nfs_client;

	seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
	seq_printf(m, ",minorversion=%u", clp->cl_minorversion);
}
#else
static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
				    int showdefaults)
{
}
#endif

/*
/*
 * Describe the mount options in force on this server representation
 * Describe the mount options in force on this server representation
 */
 */
@@ -631,11 +647,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,


	if (version != 4)
	if (version != 4)
		nfs_show_mountd_options(m, nfss, showdefaults);
		nfs_show_mountd_options(m, nfss, showdefaults);
	else
		nfs_show_nfsv4_options(m, nfss, showdefaults);


#ifdef CONFIG_NFS_V4
	if (clp->rpc_ops->version == 4)
		seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
#endif
	if (nfss->options & NFS_OPTION_FSCACHE)
	if (nfss->options & NFS_OPTION_FSCACHE)
		seq_printf(m, ",fsc");
		seq_printf(m, ",fsc");
}
}
+22 −16
Original line number Original line Diff line number Diff line
@@ -210,7 +210,8 @@ struct sock_xprt {
	 * State of TCP reply receive
	 * State of TCP reply receive
	 */
	 */
	__be32			tcp_fraghdr,
	__be32			tcp_fraghdr,
				tcp_xid;
				tcp_xid,
				tcp_calldir;


	u32			tcp_offset,
	u32			tcp_offset,
				tcp_reclen;
				tcp_reclen;
@@ -927,7 +928,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
{
{
	size_t len, used;
	size_t len, used;
	u32 offset;
	u32 offset;
	__be32	calldir;
	char *p;


	/*
	/*
	 * We want transport->tcp_offset to be 8 at the end of this routine
	 * We want transport->tcp_offset to be 8 at the end of this routine
@@ -936,26 +937,33 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
	 * transport->tcp_offset is 4 (after having already read the xid).
	 * transport->tcp_offset is 4 (after having already read the xid).
	 */
	 */
	offset = transport->tcp_offset - sizeof(transport->tcp_xid);
	offset = transport->tcp_offset - sizeof(transport->tcp_xid);
	len = sizeof(calldir) - offset;
	len = sizeof(transport->tcp_calldir) - offset;
	dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)\n", len);
	dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)\n", len);
	used = xdr_skb_read_bits(desc, &calldir, len);
	p = ((char *) &transport->tcp_calldir) + offset;
	used = xdr_skb_read_bits(desc, p, len);
	transport->tcp_offset += used;
	transport->tcp_offset += used;
	if (used != len)
	if (used != len)
		return;
		return;
	transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
	transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
	transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
	transport->tcp_flags |= TCP_RCV_COPY_DATA;
	/*
	/*
	 * We don't yet have the XDR buffer, so we will write the calldir
	 * We don't yet have the XDR buffer, so we will write the calldir
	 * out after we get the buffer from the 'struct rpc_rqst'
	 * out after we get the buffer from the 'struct rpc_rqst'
	 */
	 */
	if (ntohl(calldir) == RPC_REPLY)
	switch (ntohl(transport->tcp_calldir)) {
	case RPC_REPLY:
		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
		transport->tcp_flags |= TCP_RCV_COPY_DATA;
		transport->tcp_flags |= TCP_RPC_REPLY;
		transport->tcp_flags |= TCP_RPC_REPLY;
	else
		break;
	case RPC_CALL:
		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
		transport->tcp_flags |= TCP_RCV_COPY_DATA;
		transport->tcp_flags &= ~TCP_RPC_REPLY;
		transport->tcp_flags &= ~TCP_RPC_REPLY;
	dprintk("RPC:       reading %s CALL/REPLY flag %08x\n",
		break;
			(transport->tcp_flags & TCP_RPC_REPLY) ?
	default:
				"reply for" : "request with", calldir);
		dprintk("RPC:       invalid request message type\n");
		xprt_force_disconnect(&transport->xprt);
	}
	xs_tcp_check_fraghdr(transport);
	xs_tcp_check_fraghdr(transport);
}
}


@@ -975,12 +983,10 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
		/*
		/*
		 * Save the RPC direction in the XDR buffer
		 * Save the RPC direction in the XDR buffer
		 */
		 */
		__be32	calldir = transport->tcp_flags & TCP_RPC_REPLY ?
					htonl(RPC_REPLY) : 0;

		memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
		memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
			&calldir, sizeof(calldir));
			&transport->tcp_calldir,
		transport->tcp_copied += sizeof(calldir);
			sizeof(transport->tcp_calldir));
		transport->tcp_copied += sizeof(transport->tcp_calldir);
		transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
		transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
	}
	}