Skip to content

Commit

Permalink
Merge branch 'for-3.19' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
Pull nfsd updates from Bruce Fields:
 "A comparatively quieter cycle for nfsd this time, but still with two
  larger changes:

   - RPC server scalability improvements from Jeff Layton (using RCU
     instead of a spinlock to find idle threads).

   - server-side NFSv4.2 ALLOCATE/DEALLOCATE support from Anna
     Schumaker, enabling fallocate on new clients"

* 'for-3.19' of git://linux-nfs.org/~bfields/linux: (32 commits)
  nfsd4: fix xdr4 count of server in fs_location4
  nfsd4: fix xdr4 inclusion of escaped char
  sunrpc/cache: convert to use string_escape_str()
  sunrpc: only call test_bit once in svc_xprt_received
  fs: nfsd: Fix signedness bug in compare_blob
  sunrpc: add some tracepoints around enqueue and dequeue of svc_xprt
  sunrpc: convert to lockless lookup of queued server threads
  sunrpc: fix potential races in pool_stats collection
  sunrpc: add a rcu_head to svc_rqst and use kfree_rcu to free it
  sunrpc: require svc_create callers to pass in meaningful shutdown routine
  sunrpc: have svc_wake_up only deal with pool 0
  sunrpc: convert sp_task_pending flag to use atomic bitops
  sunrpc: move rq_cachetype field to better optimize space
  sunrpc: move rq_splice_ok flag into rq_flags
  sunrpc: move rq_dropme flag into rq_flags
  sunrpc: move rq_usedeferral flag to rq_flags
  sunrpc: move rq_local field to rq_flags
  sunrpc: add a generic rq_flags field to svc_rqst and move rq_secure to it
  nfsd: minor off by one checks in __write_versions()
  sunrpc: release svc_pool_map reference when serv allocation fails
  ...
  • Loading branch information
torvalds committed Dec 16, 2014
2 parents 6f51ee7 + bf7491f commit 0b233b7
Show file tree
Hide file tree
Showing 27 changed files with 525 additions and 269 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/android/ashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;

do_fallocate(range->asma->file,
vfs_fallocate(range->asma->file,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
start, end - start);
range->purged = ASHMEM_WAS_PURGED;
Expand Down
2 changes: 1 addition & 1 deletion fs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ int ioctl_preallocate(struct file *filp, void __user *argp)
return -EINVAL;
}

return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
}

static int file_ioctl(struct file *filp, unsigned int cmd,
Expand Down
2 changes: 1 addition & 1 deletion fs/lockd/mon.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ int nsm_monitor(const struct nlm_host *host)
if (unlikely(res.status != 0))
status = -EIO;
if (unlikely(status < 0)) {
printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
pr_notice_ratelimited("lockd: cannot monitor %s\n", nsm->sm_name);
return status;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ static struct svc_serv *lockd_create_svc(void)
printk(KERN_WARNING
"lockd_up: no pid, %d users??\n", nlmsvc_users);

serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, svc_rpcb_cleanup);
if (!serv) {
printk(KERN_WARNING "lockd_up: create service failed\n");
return ERR_PTR(-ENOMEM);
Expand Down
57 changes: 54 additions & 3 deletions fs/nfsd/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/file.h>
#include <linux/falloc.h>
#include <linux/slab.h>

#include "idmap.h"
Expand Down Expand Up @@ -772,7 +773,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
* the client wants us to do more in this compound:
*/
if (!nfsd4_last_compound_op(rqstp))
rqstp->rq_splice_ok = false;
clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);

/* check stateid */
if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
Expand Down Expand Up @@ -1013,6 +1014,44 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return status;
}

static __be32
nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_fallocate *fallocate, int flags)
{
__be32 status = nfserr_notsupp;
struct file *file;

status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
&fallocate->falloc_stateid,
WR_STATE, &file);
if (status != nfs_ok) {
dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
return status;
}

status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
fallocate->falloc_offset,
fallocate->falloc_length,
flags);
fput(file);
return status;
}

static __be32
nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_fallocate *fallocate)
{
return nfsd4_fallocate(rqstp, cstate, fallocate, 0);
}

static __be32
nfsd4_deallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_fallocate *fallocate)
{
return nfsd4_fallocate(rqstp, cstate, fallocate,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE);
}

static __be32
nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_seek *seek)
Expand Down Expand Up @@ -1331,7 +1370,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* Don't use the deferral mechanism for NFSv4; compounds make it
* too hard to avoid non-idempotency problems.
*/
rqstp->rq_usedeferral = false;
clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);

/*
* According to RFC3010, this takes precedence over all other errors.
Expand Down Expand Up @@ -1447,7 +1486,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
BUG_ON(cstate->replay_owner);
out:
/* Reset deferral mechanism for RPC deferrals */
rqstp->rq_usedeferral = true;
set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
dprintk("nfsv4 compound returned %d\n", ntohl(status));
return status;
}
Expand Down Expand Up @@ -1929,6 +1968,18 @@ static struct nfsd4_operation nfsd4_ops[] = {
},

/* NFSv4.2 operations */
[OP_ALLOCATE] = {
.op_func = (nfsd4op_func)nfsd4_allocate,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_name = "OP_ALLOCATE",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
},
[OP_DEALLOCATE] = {
.op_func = (nfsd4op_func)nfsd4_deallocate,
.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
.op_name = "OP_DEALLOCATE",
.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
},
[OP_SEEK] = {
.op_func = (nfsd4op_func)nfsd4_seek,
.op_name = "OP_SEEK",
Expand Down
68 changes: 37 additions & 31 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,11 @@ opaque_hashval(const void *ptr, int nbytes)
return x;
}

static void nfsd4_free_file(struct nfs4_file *f)
static void nfsd4_free_file_rcu(struct rcu_head *rcu)
{
kmem_cache_free(file_slab, f);
struct nfs4_file *fp = container_of(rcu, struct nfs4_file, fi_rcu);

kmem_cache_free(file_slab, fp);
}

static inline void
Expand All @@ -286,9 +288,10 @@ put_nfs4_file(struct nfs4_file *fi)
might_lock(&state_lock);

if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) {
hlist_del(&fi->fi_hash);
hlist_del_rcu(&fi->fi_hash);
spin_unlock(&state_lock);
nfsd4_free_file(fi);
WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu);
}
}

Expand Down Expand Up @@ -1440,7 +1443,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
list_add(&new->se_perclnt, &clp->cl_sessions);
spin_unlock(&clp->cl_lock);

if (cses->flags & SESSION4_BACK_CHAN) {
{
struct sockaddr *sa = svc_addr(rqstp);
/*
* This is a little silly; with sessions there's no real
Expand Down Expand Up @@ -1711,15 +1714,14 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
return 0;
}

static long long
static int
compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
{
long long res;

res = o1->len - o2->len;
if (res)
return res;
return (long long)memcmp(o1->data, o2->data, o1->len);
if (o1->len < o2->len)
return -1;
if (o1->len > o2->len)
return 1;
return memcmp(o1->data, o2->data, o1->len);
}

static int same_name(const char *n1, const char *n2)
Expand Down Expand Up @@ -1907,7 +1909,7 @@ add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root)
static struct nfs4_client *
find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root)
{
long long cmp;
int cmp;
struct rb_node *node = root->rb_node;
struct nfs4_client *clp;

Expand Down Expand Up @@ -3057,10 +3059,9 @@ static struct nfs4_file *nfsd4_alloc_file(void)
}

/* OPEN Share state helper functions */
static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh)
static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,
struct nfs4_file *fp)
{
unsigned int hashval = file_hashval(fh);

lockdep_assert_held(&state_lock);

atomic_set(&fp->fi_ref, 1);
Expand All @@ -3073,7 +3074,7 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh)
fp->fi_share_deny = 0;
memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
memset(fp->fi_access, 0, sizeof(fp->fi_access));
hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]);
hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]);
}

void
Expand Down Expand Up @@ -3294,17 +3295,14 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)

/* search file_hashtbl[] for file */
static struct nfs4_file *
find_file_locked(struct knfsd_fh *fh)
find_file_locked(struct knfsd_fh *fh, unsigned int hashval)
{
unsigned int hashval = file_hashval(fh);
struct nfs4_file *fp;

lockdep_assert_held(&state_lock);

hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) {
if (nfsd_fh_match(&fp->fi_fhandle, fh)) {
get_nfs4_file(fp);
return fp;
if (atomic_inc_not_zero(&fp->fi_ref))
return fp;
}
}
return NULL;
Expand All @@ -3314,22 +3312,30 @@ static struct nfs4_file *
find_file(struct knfsd_fh *fh)
{
struct nfs4_file *fp;
unsigned int hashval = file_hashval(fh);

spin_lock(&state_lock);
fp = find_file_locked(fh);
spin_unlock(&state_lock);
rcu_read_lock();
fp = find_file_locked(fh, hashval);
rcu_read_unlock();
return fp;
}

static struct nfs4_file *
find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh)
{
struct nfs4_file *fp;
unsigned int hashval = file_hashval(fh);

rcu_read_lock();
fp = find_file_locked(fh, hashval);
rcu_read_unlock();
if (fp)
return fp;

spin_lock(&state_lock);
fp = find_file_locked(fh);
if (fp == NULL) {
nfsd4_init_file(new, fh);
fp = find_file_locked(fh, hashval);
if (likely(fp == NULL)) {
nfsd4_init_file(fh, hashval, new);
fp = new;
}
spin_unlock(&state_lock);
Expand Down Expand Up @@ -4127,7 +4133,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
nfs4_put_stateowner(so);
}
if (open->op_file)
nfsd4_free_file(open->op_file);
kmem_cache_free(file_slab, open->op_file);
if (open->op_stp)
nfs4_put_stid(&open->op_stp->st_stid);
}
Expand Down
34 changes: 27 additions & 7 deletions fs/nfsd/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str
DECODE_TAIL;
}

static __be32
nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
struct nfsd4_fallocate *fallocate)
{
DECODE_HEAD;

status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid);
if (status)
return status;

READ_BUF(16);
p = xdr_decode_hyper(p, &fallocate->falloc_offset);
xdr_decode_hyper(p, &fallocate->falloc_length);

DECODE_TAIL;
}

static __be32
nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
{
Expand Down Expand Up @@ -1604,10 +1621,10 @@ static nfsd4_dec nfsd4_dec_ops[] = {
[OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,

/* new operations for NFSv4.2 */
[OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
[OP_COPY] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
[OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp,
[OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
Expand Down Expand Up @@ -1714,7 +1731,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;

if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
argp->rqstp->rq_splice_ok = false;
clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);

DECODE_TAIL;
}
Expand Down Expand Up @@ -1795,9 +1812,12 @@ static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
}
else
end++;
if (found_esc)
end = next;

str = end;
}
pathlen = htonl(xdr->buf->len - pathlen_offset);
pathlen = htonl(count);
write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4);
return 0;
}
Expand Down Expand Up @@ -3236,10 +3256,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,

p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */
if (!p) {
WARN_ON_ONCE(resp->rqstp->rq_splice_ok);
WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags));
return nfserr_resource;
}
if (resp->xdr.buf->page_len && resp->rqstp->rq_splice_ok) {
if (resp->xdr.buf->page_len && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) {
WARN_ON_ONCE(1);
return nfserr_resource;
}
Expand All @@ -3256,7 +3276,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
goto err_truncate;
}

if (file->f_op->splice_read && resp->rqstp->rq_splice_ok)
if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
err = nfsd4_encode_splice_read(resp, read, file, maxcount);
else
err = nfsd4_encode_readv(resp, read, file, maxcount);
Expand Down
4 changes: 2 additions & 2 deletions fs/nfsd/nfscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
/* From the hall of fame of impractical attacks:
* Is this a user who tries to snoop on the cache? */
rtn = RC_DOIT;
if (!rqstp->rq_secure && rp->c_secure)
if (!test_bit(RQ_SECURE, &rqstp->rq_flags) && rp->c_secure)
goto out;

/* Compose RPC reply header */
Expand Down Expand Up @@ -579,7 +579,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
spin_lock(&b->cache_lock);
drc_mem_usage += bufsize;
lru_put_end(b, rp);
rp->c_secure = rqstp->rq_secure;
rp->c_secure = test_bit(RQ_SECURE, &rqstp->rq_flags);
rp->c_type = cachetype;
rp->c_state = RC_DONE;
spin_unlock(&b->cache_lock);
Expand Down
Loading

0 comments on commit 0b233b7

Please sign in to comment.