Commit e7865c23 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* '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
...@@ -1286,6 +1286,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server) ...@@ -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 @@ static int nfs4_init_server(struct nfs_server *server, ...@@ -1346,7 +1395,6 @@ static int nfs4_init_server(struct nfs_server *server,
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, ...@@ -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)
goto error;
/* Probe the root fh to retrieve its FSID */
error = nfs4_get_rootfh(server, mntfh);
if (error < 0) if (error < 0)
goto error; 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, ...@@ -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, ...@@ -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, ...@@ -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);
......
...@@ -146,7 +146,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) ...@@ -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");
......
...@@ -862,8 +862,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const ...@@ -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;
......
...@@ -570,6 +570,22 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, ...@@ -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, ...@@ -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");
} }
......
...@@ -210,7 +210,8 @@ struct sock_xprt { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment