Commit 1e848913 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-4.0' of git://linux-nfs.org/~bfields/linux

Pull nfsd fixes from Bruce Fields:
 "Two main issues:

   - We found that turning on pNFS by default (when it's configured at
     build time) was too aggressive, so we want to switch the default
     before the 4.0 release.

   - Recent client changes to increase open parallelism uncovered a
     serious bug lurking in the server's open code.

  Also fix a krb5/selinux regression.

  The rest is mainly smaller pNFS fixes"

* 'for-4.0' of git://linux-nfs.org/~bfields/linux:
  sunrpc: make debugfs file creation failure non-fatal
  nfsd: require an explicit option to enable pNFS
  NFSD: Fix bad update of layout in nfsd4_return_file_layout
  NFSD: Take care the return value from nfsd4_encode_stateid
  NFSD: Printk blocklayout length and offset as format 0x%llx
  nfsd: return correct lockowner when there is a race on hash insert
  nfsd: return correct openowner when there is a race to put one in the hash
  NFSD: Put exports after nfsd4_layout_verify fail
  NFSD: Error out when register_shrinker() fail
  NFSD: Take care the return value from nfsd4_decode_stateid
  NFSD: Check layout type when returning client layouts
  NFSD: restore trace event lost in mismerge
parents 6c310bc1 f9c72d10
......@@ -137,7 +137,7 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
seg->offset = iomap.offset;
seg->length = iomap.length;
dprintk("GET: %lld:%lld %d\n", bex->foff, bex->len, bex->es);
dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es);
return 0;
out_error:
......
......@@ -122,19 +122,19 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
p = xdr_decode_hyper(p, &bex.foff);
if (bex.foff & (block_size - 1)) {
dprintk("%s: unaligned offset %lld\n",
dprintk("%s: unaligned offset 0x%llx\n",
__func__, bex.foff);
goto fail;
}
p = xdr_decode_hyper(p, &bex.len);
if (bex.len & (block_size - 1)) {
dprintk("%s: unaligned length %lld\n",
dprintk("%s: unaligned length 0x%llx\n",
__func__, bex.foff);
goto fail;
}
p = xdr_decode_hyper(p, &bex.soff);
if (bex.soff & (block_size - 1)) {
dprintk("%s: unaligned disk offset %lld\n",
dprintk("%s: unaligned disk offset 0x%llx\n",
__func__, bex.soff);
goto fail;
}
......
......@@ -118,7 +118,7 @@ void nfsd4_setup_layout_type(struct svc_export *exp)
{
struct super_block *sb = exp->ex_path.mnt->mnt_sb;
if (exp->ex_flags & NFSEXP_NOPNFS)
if (!(exp->ex_flags & NFSEXP_PNFS))
return;
if (sb->s_export_op->get_uuid &&
......@@ -440,15 +440,14 @@ nfsd4_return_file_layout(struct nfs4_layout *lp, struct nfsd4_layout_seg *seg,
list_move_tail(&lp->lo_perstate, reaplist);
return;
}
end = seg->offset;
lo->offset = layout_end(seg);
} else {
/* retain the whole layout segment on a split. */
if (layout_end(seg) < end) {
dprintk("%s: split not supported\n", __func__);
return;
}
lo->offset = layout_end(seg);
end = seg->offset;
}
layout_update_len(lo, end);
......@@ -513,6 +512,9 @@ nfsd4_return_client_layouts(struct svc_rqst *rqstp,
spin_lock(&clp->cl_lock);
list_for_each_entry_safe(ls, n, &clp->cl_lo_states, ls_perclnt) {
if (ls->ls_layout_type != lrp->lr_layout_type)
continue;
if (lrp->lr_return_type == RETURN_FSID &&
!fh_fsid_match(&ls->ls_stid.sc_file->fi_fhandle,
&cstate->current_fh.fh_handle))
......@@ -587,6 +589,8 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls)
rpc_ntop((struct sockaddr *)&clp->cl_addr, addr_str, sizeof(addr_str));
trace_layout_recall_fail(&ls->ls_stid.sc_stateid);
printk(KERN_WARNING
"nfsd: client %s failed to respond to layout recall. "
" Fencing..\n", addr_str);
......
......@@ -1237,8 +1237,8 @@ nfsd4_getdeviceinfo(struct svc_rqst *rqstp,
nfserr = ops->proc_getdeviceinfo(exp->ex_path.mnt->mnt_sb, gdp);
gdp->gd_notify_types &= ops->notify_types;
exp_put(exp);
out:
exp_put(exp);
return nfserr;
}
......
......@@ -3221,7 +3221,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
} else
nfs4_free_openowner(&oo->oo_owner);
spin_unlock(&clp->cl_lock);
return oo;
return ret;
}
static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
......@@ -5062,7 +5062,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp,
} else
nfs4_free_lockowner(&lo->lo_owner);
spin_unlock(&clp->cl_lock);
return lo;
return ret;
}
static void
......
......@@ -1562,7 +1562,11 @@ nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
p = xdr_decode_hyper(p, &lgp->lg_seg.offset);
p = xdr_decode_hyper(p, &lgp->lg_seg.length);
p = xdr_decode_hyper(p, &lgp->lg_minlength);
nfsd4_decode_stateid(argp, &lgp->lg_sid);
status = nfsd4_decode_stateid(argp, &lgp->lg_sid);
if (status)
return status;
READ_BUF(4);
lgp->lg_maxcount = be32_to_cpup(p++);
......@@ -1580,7 +1584,11 @@ nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
p = xdr_decode_hyper(p, &lcp->lc_seg.offset);
p = xdr_decode_hyper(p, &lcp->lc_seg.length);
lcp->lc_reclaim = be32_to_cpup(p++);
nfsd4_decode_stateid(argp, &lcp->lc_sid);
status = nfsd4_decode_stateid(argp, &lcp->lc_sid);
if (status)
return status;
READ_BUF(4);
lcp->lc_newoffset = be32_to_cpup(p++);
if (lcp->lc_newoffset) {
......@@ -1628,7 +1636,11 @@ nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
READ_BUF(16);
p = xdr_decode_hyper(p, &lrp->lr_seg.offset);
p = xdr_decode_hyper(p, &lrp->lr_seg.length);
nfsd4_decode_stateid(argp, &lrp->lr_sid);
status = nfsd4_decode_stateid(argp, &lrp->lr_sid);
if (status)
return status;
READ_BUF(4);
lrp->lrf_body_len = be32_to_cpup(p++);
if (lrp->lrf_body_len > 0) {
......@@ -4123,7 +4135,7 @@ nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
return nfserr_resource;
*p++ = cpu_to_be32(lrp->lrs_present);
if (lrp->lrs_present)
nfsd4_encode_stateid(xdr, &lrp->lr_sid);
return nfsd4_encode_stateid(xdr, &lrp->lr_sid);
return nfs_ok;
}
#endif /* CONFIG_NFSD_PNFS */
......
......@@ -165,13 +165,17 @@ int nfsd_reply_cache_init(void)
{
unsigned int hashsize;
unsigned int i;
int status = 0;
max_drc_entries = nfsd_cache_size_limit();
atomic_set(&num_drc_entries, 0);
hashsize = nfsd_hashsize(max_drc_entries);
maskbits = ilog2(hashsize);
register_shrinker(&nfsd_reply_cache_shrinker);
status = register_shrinker(&nfsd_reply_cache_shrinker);
if (status)
return status;
drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep),
0, 0, NULL);
if (!drc_slab)
......
......@@ -60,17 +60,17 @@ struct rpc_xprt;
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
void rpc_register_sysctl(void);
void rpc_unregister_sysctl(void);
int sunrpc_debugfs_init(void);
void sunrpc_debugfs_init(void);
void sunrpc_debugfs_exit(void);
int rpc_clnt_debugfs_register(struct rpc_clnt *);
void rpc_clnt_debugfs_register(struct rpc_clnt *);
void rpc_clnt_debugfs_unregister(struct rpc_clnt *);
int rpc_xprt_debugfs_register(struct rpc_xprt *);
void rpc_xprt_debugfs_register(struct rpc_xprt *);
void rpc_xprt_debugfs_unregister(struct rpc_xprt *);
#else
static inline int
static inline void
sunrpc_debugfs_init(void)
{
return 0;
return;
}
static inline void
......@@ -79,10 +79,10 @@ sunrpc_debugfs_exit(void)
return;
}
static inline int
static inline void
rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
{
return 0;
return;
}
static inline void
......@@ -91,10 +91,10 @@ rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt)
return;
}
static inline int
static inline void
rpc_xprt_debugfs_register(struct rpc_xprt *xprt)
{
return 0;
return;
}
static inline void
......
......@@ -47,7 +47,7 @@
* exported filesystem.
*/
#define NFSEXP_V4ROOT 0x10000
#define NFSEXP_NOPNFS 0x20000
#define NFSEXP_PNFS 0x20000
/* All flags that we claim to support. (Note we don't support NOACL.) */
#define NFSEXP_ALLFLAGS 0x3FE7F
......
......@@ -303,9 +303,7 @@ static int rpc_client_register(struct rpc_clnt *clnt,
struct super_block *pipefs_sb;
int err;
err = rpc_clnt_debugfs_register(clnt);
if (err)
return err;
rpc_clnt_debugfs_register(clnt);
pipefs_sb = rpc_get_sb_net(net);
if (pipefs_sb) {
......
......@@ -129,48 +129,52 @@ static const struct file_operations tasks_fops = {
.release = tasks_release,
};
int
void
rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
{
int len, err;
int len;
char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */
struct rpc_xprt *xprt;
/* Already registered? */
if (clnt->cl_debugfs)
return 0;
if (clnt->cl_debugfs || !rpc_clnt_dir)
return;
len = snprintf(name, sizeof(name), "%x", clnt->cl_clid);
if (len >= sizeof(name))
return -EINVAL;
return;
/* make the per-client dir */
clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir);
if (!clnt->cl_debugfs)
return -ENOMEM;
return;
/* make tasks file */
err = -ENOMEM;
if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs,
clnt, &tasks_fops))
goto out_err;
err = -EINVAL;
rcu_read_lock();
xprt = rcu_dereference(clnt->cl_xprt);
/* no "debugfs" dentry? Don't bother with the symlink. */
if (!xprt->debugfs) {
rcu_read_unlock();
return;
}
len = snprintf(name, sizeof(name), "../../rpc_xprt/%s",
rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name);
xprt->debugfs->d_name.name);
rcu_read_unlock();
if (len >= sizeof(name))
goto out_err;
err = -ENOMEM;
if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name))
goto out_err;
return 0;
return;
out_err:
debugfs_remove_recursive(clnt->cl_debugfs);
clnt->cl_debugfs = NULL;
return err;
}
void
......@@ -226,33 +230,33 @@ static const struct file_operations xprt_info_fops = {
.release = xprt_info_release,
};
int
void
rpc_xprt_debugfs_register(struct rpc_xprt *xprt)
{
int len, id;
static atomic_t cur_id;
char name[9]; /* 8 hex digits + NULL term */
if (!rpc_xprt_dir)
return;
id = (unsigned int)atomic_inc_return(&cur_id);
len = snprintf(name, sizeof(name), "%x", id);
if (len >= sizeof(name))
return -EINVAL;
return;
/* make the per-client dir */
xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir);
if (!xprt->debugfs)
return -ENOMEM;
return;
/* make tasks file */
if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs,
xprt, &xprt_info_fops)) {
debugfs_remove_recursive(xprt->debugfs);
xprt->debugfs = NULL;
return -ENOMEM;
}
return 0;
}
void
......@@ -266,14 +270,17 @@ void __exit
sunrpc_debugfs_exit(void)
{
debugfs_remove_recursive(topdir);
topdir = NULL;
rpc_clnt_dir = NULL;
rpc_xprt_dir = NULL;
}
int __init
void __init
sunrpc_debugfs_init(void)
{
topdir = debugfs_create_dir("sunrpc", NULL);
if (!topdir)
goto out;
return;
rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir);
if (!rpc_clnt_dir)
......@@ -283,10 +290,9 @@ sunrpc_debugfs_init(void)
if (!rpc_xprt_dir)
goto out_remove;
return 0;
return;
out_remove:
debugfs_remove_recursive(topdir);
topdir = NULL;
out:
return -ENOMEM;
rpc_clnt_dir = NULL;
}
......@@ -98,10 +98,7 @@ init_sunrpc(void)
if (err)
goto out4;
err = sunrpc_debugfs_init();
if (err)
goto out5;
sunrpc_debugfs_init();
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
rpc_register_sysctl();
#endif
......@@ -109,8 +106,6 @@ init_sunrpc(void)
init_socket_xprt(); /* clnt sock transport */
return 0;
out5:
unregister_rpc_pipefs();
out4:
unregister_pernet_subsys(&sunrpc_net_ops);
out3:
......
......@@ -1331,7 +1331,6 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
*/
struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
{
int err;
struct rpc_xprt *xprt;
struct xprt_class *t;
......@@ -1372,11 +1371,7 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
return ERR_PTR(-ENOMEM);
}
err = rpc_xprt_debugfs_register(xprt);
if (err) {
xprt_destroy(xprt);
return ERR_PTR(err);
}
rpc_xprt_debugfs_register(xprt);
dprintk("RPC: created transport %p with %u slots\n", xprt,
xprt->max_reqs);
......
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