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
This commit is contained in:
commit
e7865c234f
122
fs/nfs/client.c
122
fs/nfs/client.c
|
@ -1286,6 +1286,55 @@ static void nfs4_session_set_rwsize(struct nfs_server *server)
|
|||
#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
|
||||
*/
|
||||
|
@ -1346,7 +1395,6 @@ error:
|
|||
struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
|
||||
struct nfs_fh *mntfh)
|
||||
{
|
||||
struct nfs_fattr *fattr;
|
||||
struct nfs_server *server;
|
||||
int error;
|
||||
|
||||
|
@ -1356,55 +1404,19 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
|
|||
if (!server)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
error = -ENOMEM;
|
||||
fattr = nfs_alloc_fattr();
|
||||
if (fattr == NULL)
|
||||
goto error;
|
||||
|
||||
/* set up the general RPC client */
|
||||
error = nfs4_init_server(server, data);
|
||||
if (error < 0)
|
||||
goto error;
|
||||
|
||||
BUG_ON(!server->nfs_client);
|
||||
BUG_ON(!server->nfs_client->rpc_ops);
|
||||
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
|
||||
|
||||
error = nfs4_init_session(server);
|
||||
error = nfs4_server_common_setup(server, mntfh);
|
||||
if (error < 0)
|
||||
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);
|
||||
nfs_free_fattr(fattr);
|
||||
return server;
|
||||
|
||||
error:
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_server(server);
|
||||
dprintk("<-- nfs4_create_server() = error %d\n", 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_server *server, *parent_server;
|
||||
struct nfs_fattr *fattr;
|
||||
int error;
|
||||
|
||||
dprintk("--> nfs4_create_referral_server()\n");
|
||||
|
@ -1427,11 +1438,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
|
|||
if (!server)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
error = -ENOMEM;
|
||||
fattr = nfs_alloc_fattr();
|
||||
if (fattr == NULL)
|
||||
goto error;
|
||||
|
||||
parent_server = NFS_SB(data->sb);
|
||||
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)
|
||||
goto error;
|
||||
|
||||
BUG_ON(!server->nfs_client);
|
||||
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);
|
||||
error = nfs4_server_common_setup(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)
|
||||
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);
|
||||
return server;
|
||||
|
||||
error:
|
||||
nfs_free_fattr(fattr);
|
||||
nfs_free_server(server);
|
||||
dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
|
||||
return ERR_PTR(error);
|
||||
|
|
|
@ -146,7 +146,7 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE)
|
||||
if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_TYPE)
|
||||
|| !S_ISDIR(fsinfo.fattr->mode)) {
|
||||
printk(KERN_ERR "nfs4_get_rootfh:"
|
||||
" getroot encountered non-directory\n");
|
||||
|
|
|
@ -862,8 +862,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
|
|||
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
|
||||
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
|
||||
*p++ = cpu_to_be32(0);
|
||||
*p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
|
||||
*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
|
||||
*p++ = cpu_to_be32(iap->ia_atime.tv_sec);
|
||||
*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
|
||||
}
|
||||
else if (iap->ia_valid & ATTR_ATIME) {
|
||||
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
#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
|
||||
*/
|
||||
|
@ -631,11 +647,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
|
|||
|
||||
if (version != 4)
|
||||
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)
|
||||
seq_printf(m, ",fsc");
|
||||
}
|
||||
|
|
|
@ -210,7 +210,8 @@ struct sock_xprt {
|
|||
* State of TCP reply receive
|
||||
*/
|
||||
__be32 tcp_fraghdr,
|
||||
tcp_xid;
|
||||
tcp_xid,
|
||||
tcp_calldir;
|
||||
|
||||
u32 tcp_offset,
|
||||
tcp_reclen;
|
||||
|
@ -927,7 +928,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
|
|||
{
|
||||
size_t len, used;
|
||||
u32 offset;
|
||||
__be32 calldir;
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
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);
|
||||
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;
|
||||
if (used != len)
|
||||
return;
|
||||
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
|
||||
* 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;
|
||||
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;
|
||||
dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
|
||||
(transport->tcp_flags & TCP_RPC_REPLY) ?
|
||||
"reply for" : "request with", calldir);
|
||||
break;
|
||||
default:
|
||||
dprintk("RPC: invalid request message type\n");
|
||||
xprt_force_disconnect(&transport->xprt);
|
||||
}
|
||||
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
|
||||
*/
|
||||
__be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
|
||||
htonl(RPC_REPLY) : 0;
|
||||
|
||||
memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
|
||||
&calldir, sizeof(calldir));
|
||||
transport->tcp_copied += sizeof(calldir);
|
||||
&transport->tcp_calldir,
|
||||
sizeof(transport->tcp_calldir));
|
||||
transport->tcp_copied += sizeof(transport->tcp_calldir);
|
||||
transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue