Commit 763008c4 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:
  NFS: Fix an Oops in the NFSv4 atomic open code
  NFS: Fix the selection of security flavours in Kconfig
  NFS: fix the return value of nfs_file_fsync()
  rpcrdma: Fix SQ size calculation when memreg is FRMR
  xprtrdma: Do not truncate iova_start values in frmr registrations.
  nfs: Remove redundant NULL check upon kfree()
  nfs: Add "lookupcache" to displayed mount options
  NFS: allow close-to-open cache semantics to apply to root of NFS filesystem
  SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494)
parents d1126ad9 0a377cff
...@@ -63,7 +63,6 @@ config NFS_V3_ACL ...@@ -63,7 +63,6 @@ config NFS_V3_ACL
config NFS_V4 config NFS_V4
bool "NFS client support for NFS version 4" bool "NFS client support for NFS version 4"
depends on NFS_FS depends on NFS_FS
select RPCSEC_GSS_KRB5
help help
This option enables support for version 4 of the NFS protocol This option enables support for version 4 of the NFS protocol
(RFC 3530) in the kernel's NFS client. (RFC 3530) in the kernel's NFS client.
......
...@@ -140,6 +140,13 @@ nfs_opendir(struct inode *inode, struct file *filp) ...@@ -140,6 +140,13 @@ nfs_opendir(struct inode *inode, struct file *filp)
/* Call generic open code in order to cache credentials */ /* Call generic open code in order to cache credentials */
res = nfs_open(inode, filp); res = nfs_open(inode, filp);
if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) {
/* This is a mountpoint, so d_revalidate will never
* have been called, so we need to refresh the
* inode (for close-open consistency) ourselves.
*/
__nfs_revalidate_inode(NFS_SERVER(inode), inode);
}
return res; return res;
} }
...@@ -1103,7 +1110,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -1103,7 +1110,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
goto no_open_dput; goto no_open_dput;
/* We can't create new files, or truncate existing ones here */ /* We can't create new files, or truncate existing ones here */
openflags &= ~(O_CREAT|O_TRUNC); openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
/* /*
* Note: we're not holding inode->i_mutex and so may be racing with * Note: we're not holding inode->i_mutex and so may be racing with
......
...@@ -323,7 +323,7 @@ nfs_file_fsync(struct file *file, int datasync) ...@@ -323,7 +323,7 @@ nfs_file_fsync(struct file *file, int datasync)
have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
if (have_error) if (have_error)
ret = xchg(&ctx->error, 0); ret = xchg(&ctx->error, 0);
if (!ret) if (!ret && status < 0)
ret = status; ret = status;
return ret; return ret;
} }
......
...@@ -2036,7 +2036,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ...@@ -2036,7 +2036,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
struct rpc_cred *cred; struct rpc_cred *cred;
struct nfs4_state *state; struct nfs4_state *state;
struct dentry *res; struct dentry *res;
fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); int open_flags = nd->intent.open.flags;
fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
if (nd->flags & LOOKUP_CREATE) { if (nd->flags & LOOKUP_CREATE) {
attr.ia_mode = nd->intent.open.create_mode; attr.ia_mode = nd->intent.open.create_mode;
...@@ -2044,8 +2045,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ...@@ -2044,8 +2045,9 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
if (!IS_POSIXACL(dir)) if (!IS_POSIXACL(dir))
attr.ia_mode &= ~current_umask(); attr.ia_mode &= ~current_umask();
} else { } else {
open_flags &= ~O_EXCL;
attr.ia_valid = 0; attr.ia_valid = 0;
BUG_ON(nd->intent.open.flags & O_CREAT); BUG_ON(open_flags & O_CREAT);
} }
cred = rpc_lookup_cred(); cred = rpc_lookup_cred();
...@@ -2054,7 +2056,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) ...@@ -2054,7 +2056,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
parent = dentry->d_parent; parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */ /* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent); nfs_block_sillyrename(parent);
state = nfs4_do_open(dir, &path, fmode, nd->intent.open.flags, &attr, cred); state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
put_rpccred(cred); put_rpccred(cred);
if (IS_ERR(state)) { if (IS_ERR(state)) {
if (PTR_ERR(state) == -ENOENT) { if (PTR_ERR(state) == -ENOENT) {
...@@ -2273,7 +2275,6 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct ...@@ -2273,7 +2275,6 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct
out: out:
if (page) if (page)
__free_page(page); __free_page(page);
if (locations)
kfree(locations); kfree(locations);
return status; return status;
} }
......
...@@ -655,6 +655,13 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, ...@@ -655,6 +655,13 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
if (nfss->options & NFS_OPTION_FSCACHE) if (nfss->options & NFS_OPTION_FSCACHE)
seq_printf(m, ",fsc"); seq_printf(m, ",fsc");
if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
seq_printf(m, ",lookupcache=none");
else
seq_printf(m, ",lookupcache=pos");
}
} }
/* /*
......
...@@ -69,7 +69,6 @@ config NFSD_V4 ...@@ -69,7 +69,6 @@ config NFSD_V4
depends on NFSD && PROC_FS && EXPERIMENTAL depends on NFSD && PROC_FS && EXPERIMENTAL
select NFSD_V3 select NFSD_V3
select FS_POSIX_ACL select FS_POSIX_ACL
select RPCSEC_GSS_KRB5
help help
This option enables support in your system's NFS server for This option enables support in your system's NFS server for
version 4 of the NFS protocol (RFC 3530). version 4 of the NFS protocol (RFC 3530).
......
...@@ -18,10 +18,11 @@ config SUNRPC_XPRT_RDMA ...@@ -18,10 +18,11 @@ config SUNRPC_XPRT_RDMA
If unsure, say N. If unsure, say N.
config RPCSEC_GSS_KRB5 config RPCSEC_GSS_KRB5
tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" tristate
depends on SUNRPC && EXPERIMENTAL depends on SUNRPC && CRYPTO
prompt "Secure RPC: Kerberos V mechanism" if !(NFS_V4 || NFSD_V4)
default y
select SUNRPC_GSS select SUNRPC_GSS
select CRYPTO
select CRYPTO_MD5 select CRYPTO_MD5
select CRYPTO_DES select CRYPTO_DES
select CRYPTO_CBC select CRYPTO_CBC
...@@ -34,7 +35,7 @@ config RPCSEC_GSS_KRB5 ...@@ -34,7 +35,7 @@ config RPCSEC_GSS_KRB5
available from http://linux-nfs.org/. In addition, user-space available from http://linux-nfs.org/. In addition, user-space
Kerberos support should be installed. Kerberos support should be installed.
If unsure, say N. If unsure, say Y.
config RPCSEC_GSS_SPKM3 config RPCSEC_GSS_SPKM3
tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)" tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
......
...@@ -249,6 +249,8 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, ...@@ -249,6 +249,8 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
req->rl_nchunks = nchunks; req->rl_nchunks = nchunks;
BUG_ON(nchunks == 0); BUG_ON(nchunks == 0);
BUG_ON((r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR)
&& (nchunks > 3));
/* /*
* finish off header. If write, marshal discrim and nchunks. * finish off header. If write, marshal discrim and nchunks.
......
...@@ -650,10 +650,22 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, ...@@ -650,10 +650,22 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
ep->rep_attr.cap.max_send_wr = cdata->max_requests; ep->rep_attr.cap.max_send_wr = cdata->max_requests;
switch (ia->ri_memreg_strategy) { switch (ia->ri_memreg_strategy) {
case RPCRDMA_FRMR: case RPCRDMA_FRMR:
/* Add room for frmr register and invalidate WRs */ /* Add room for frmr register and invalidate WRs.
ep->rep_attr.cap.max_send_wr *= 3; * 1. FRMR reg WR for head
if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) * 2. FRMR invalidate WR for head
* 3. FRMR reg WR for pagelist
* 4. FRMR invalidate WR for pagelist
* 5. FRMR reg WR for tail
* 6. FRMR invalidate WR for tail
* 7. The RDMA_SEND WR
*/
ep->rep_attr.cap.max_send_wr *= 7;
if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) {
cdata->max_requests = devattr.max_qp_wr / 7;
if (!cdata->max_requests)
return -EINVAL; return -EINVAL;
ep->rep_attr.cap.max_send_wr = cdata->max_requests * 7;
}
break; break;
case RPCRDMA_MEMWINDOWS_ASYNC: case RPCRDMA_MEMWINDOWS_ASYNC:
case RPCRDMA_MEMWINDOWS: case RPCRDMA_MEMWINDOWS:
...@@ -1490,7 +1502,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, ...@@ -1490,7 +1502,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
memset(&frmr_wr, 0, sizeof frmr_wr); memset(&frmr_wr, 0, sizeof frmr_wr);
frmr_wr.opcode = IB_WR_FAST_REG_MR; frmr_wr.opcode = IB_WR_FAST_REG_MR;
frmr_wr.send_flags = 0; /* unsignaled */ frmr_wr.send_flags = 0; /* unsignaled */
frmr_wr.wr.fast_reg.iova_start = (unsigned long)seg1->mr_dma; frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma;
frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl;
frmr_wr.wr.fast_reg.page_list_len = i; frmr_wr.wr.fast_reg.page_list_len = i;
frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
......
...@@ -1305,10 +1305,11 @@ static void xs_tcp_state_change(struct sock *sk) ...@@ -1305,10 +1305,11 @@ static void xs_tcp_state_change(struct sock *sk)
if (!(xprt = xprt_from_sock(sk))) if (!(xprt = xprt_from_sock(sk)))
goto out; goto out;
dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); dprintk("RPC: xs_tcp_state_change client %p...\n", xprt);
dprintk("RPC: state %x conn %d dead %d zapped %d\n", dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n",
sk->sk_state, xprt_connected(xprt), sk->sk_state, xprt_connected(xprt),
sock_flag(sk, SOCK_DEAD), sock_flag(sk, SOCK_DEAD),
sock_flag(sk, SOCK_ZAPPED)); sock_flag(sk, SOCK_ZAPPED),
sk->sk_shutdown);
switch (sk->sk_state) { switch (sk->sk_state) {
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
...@@ -1779,10 +1780,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra ...@@ -1779,10 +1780,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra
{ {
unsigned int state = transport->inet->sk_state; unsigned int state = transport->inet->sk_state;
if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) {
/* we don't need to abort the connection if the socket
* hasn't undergone a shutdown
*/
if (transport->inet->sk_shutdown == 0)
return; return;
if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n",
__func__, transport->inet->sk_shutdown);
}
if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) {
/* we don't need to abort the connection if the socket
* hasn't undergone a shutdown
*/
if (transport->inet->sk_shutdown == 0)
return; return;
dprintk("RPC: %s: ESTABLISHED/SYN_SENT "
"sk_shutdown set to %d\n",
__func__, transport->inet->sk_shutdown);
}
xs_abort_connection(xprt, transport); xs_abort_connection(xprt, transport);
} }
......
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