diff options
| -rw-r--r-- | drivers/staging/android/ashmem.c | 2 | ||||
| -rw-r--r-- | fs/ioctl.c | 2 | ||||
| -rw-r--r-- | fs/lockd/mon.c | 2 | ||||
| -rw-r--r-- | fs/lockd/svc.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 57 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 68 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 34 | ||||
| -rw-r--r-- | fs/nfsd/nfscache.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 6 | ||||
| -rw-r--r-- | fs/nfsd/nfsfh.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 19 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 37 | ||||
| -rw-r--r-- | fs/nfsd/vfs.h | 2 | ||||
| -rw-r--r-- | fs/nfsd/xdr4.h | 9 | ||||
| -rw-r--r-- | fs/open.c | 5 | ||||
| -rw-r--r-- | include/linux/fs.h | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc.h | 34 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 7 | ||||
| -rw-r--r-- | include/trace/events/sunrpc.h | 120 | ||||
| -rw-r--r-- | mm/madvise.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/cache.c | 26 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 42 | ||||
| -rw-r--r-- | net/sunrpc/svc_xprt.c | 292 | ||||
| -rw-r--r-- | net/sunrpc/svcsock.c | 5 | ||||
| -rw-r--r-- | net/sunrpc/xdr.c | 9 |
27 files changed, 525 insertions, 269 deletions
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 46f8ef42559e..8c7852742f4b 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c | |||
| @@ -446,7 +446,7 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | |||
| 446 | loff_t start = range->pgstart * PAGE_SIZE; | 446 | loff_t start = range->pgstart * PAGE_SIZE; |
| 447 | loff_t end = (range->pgend + 1) * PAGE_SIZE; | 447 | loff_t end = (range->pgend + 1) * PAGE_SIZE; |
| 448 | 448 | ||
| 449 | do_fallocate(range->asma->file, | 449 | vfs_fallocate(range->asma->file, |
| 450 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, | 450 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, |
| 451 | start, end - start); | 451 | start, end - start); |
| 452 | range->purged = ASHMEM_WAS_PURGED; | 452 | range->purged = ASHMEM_WAS_PURGED; |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 77c9a7812542..214c3c11fbc2 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
| @@ -443,7 +443,7 @@ int ioctl_preallocate(struct file *filp, void __user *argp) | |||
| 443 | return -EINVAL; | 443 | return -EINVAL; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len); | 446 | return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len); |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | static int file_ioctl(struct file *filp, unsigned int cmd, | 449 | static int file_ioctl(struct file *filp, unsigned int cmd, |
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 9106f42c472c..1cc6ec51e6b1 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
| @@ -214,7 +214,7 @@ int nsm_monitor(const struct nlm_host *host) | |||
| 214 | if (unlikely(res.status != 0)) | 214 | if (unlikely(res.status != 0)) |
| 215 | status = -EIO; | 215 | status = -EIO; |
| 216 | if (unlikely(status < 0)) { | 216 | if (unlikely(status < 0)) { |
| 217 | printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name); | 217 | pr_notice_ratelimited("lockd: cannot monitor %s\n", nsm->sm_name); |
| 218 | return status; | 218 | return status; |
| 219 | } | 219 | } |
| 220 | 220 | ||
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index d1bb7ecfd201..e94c887da2d7 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
| @@ -350,7 +350,7 @@ static struct svc_serv *lockd_create_svc(void) | |||
| 350 | printk(KERN_WARNING | 350 | printk(KERN_WARNING |
| 351 | "lockd_up: no pid, %d users??\n", nlmsvc_users); | 351 | "lockd_up: no pid, %d users??\n", nlmsvc_users); |
| 352 | 352 | ||
| 353 | serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); | 353 | serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, svc_rpcb_cleanup); |
| 354 | if (!serv) { | 354 | if (!serv) { |
| 355 | printk(KERN_WARNING "lockd_up: create service failed\n"); | 355 | printk(KERN_WARNING "lockd_up: create service failed\n"); |
| 356 | return ERR_PTR(-ENOMEM); | 356 | return ERR_PTR(-ENOMEM); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0beb023f25ac..ac71d13c69ef 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 34 | */ | 34 | */ |
| 35 | #include <linux/file.h> | 35 | #include <linux/file.h> |
| 36 | #include <linux/falloc.h> | ||
| 36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 37 | 38 | ||
| 38 | #include "idmap.h" | 39 | #include "idmap.h" |
| @@ -772,7 +773,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 772 | * the client wants us to do more in this compound: | 773 | * the client wants us to do more in this compound: |
| 773 | */ | 774 | */ |
| 774 | if (!nfsd4_last_compound_op(rqstp)) | 775 | if (!nfsd4_last_compound_op(rqstp)) |
| 775 | rqstp->rq_splice_ok = false; | 776 | clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); |
| 776 | 777 | ||
| 777 | /* check stateid */ | 778 | /* check stateid */ |
| 778 | if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), | 779 | if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), |
| @@ -1014,6 +1015,44 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 1014 | } | 1015 | } |
| 1015 | 1016 | ||
| 1016 | static __be32 | 1017 | static __be32 |
| 1018 | nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
| 1019 | struct nfsd4_fallocate *fallocate, int flags) | ||
| 1020 | { | ||
| 1021 | __be32 status = nfserr_notsupp; | ||
| 1022 | struct file *file; | ||
| 1023 | |||
| 1024 | status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, | ||
| 1025 | &fallocate->falloc_stateid, | ||
| 1026 | WR_STATE, &file); | ||
| 1027 | if (status != nfs_ok) { | ||
| 1028 | dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n"); | ||
| 1029 | return status; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file, | ||
| 1033 | fallocate->falloc_offset, | ||
| 1034 | fallocate->falloc_length, | ||
| 1035 | flags); | ||
| 1036 | fput(file); | ||
| 1037 | return status; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | static __be32 | ||
| 1041 | nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
| 1042 | struct nfsd4_fallocate *fallocate) | ||
| 1043 | { | ||
| 1044 | return nfsd4_fallocate(rqstp, cstate, fallocate, 0); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static __be32 | ||
| 1048 | nfsd4_deallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
| 1049 | struct nfsd4_fallocate *fallocate) | ||
| 1050 | { | ||
| 1051 | return nfsd4_fallocate(rqstp, cstate, fallocate, | ||
| 1052 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static __be32 | ||
| 1017 | nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1056 | nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
| 1018 | struct nfsd4_seek *seek) | 1057 | struct nfsd4_seek *seek) |
| 1019 | { | 1058 | { |
| @@ -1331,7 +1370,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
| 1331 | * Don't use the deferral mechanism for NFSv4; compounds make it | 1370 | * Don't use the deferral mechanism for NFSv4; compounds make it |
| 1332 | * too hard to avoid non-idempotency problems. | 1371 | * too hard to avoid non-idempotency problems. |
| 1333 | */ | 1372 | */ |
| 1334 | rqstp->rq_usedeferral = false; | 1373 | clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); |
| 1335 | 1374 | ||
| 1336 | /* | 1375 | /* |
| 1337 | * According to RFC3010, this takes precedence over all other errors. | 1376 | * According to RFC3010, this takes precedence over all other errors. |
| @@ -1447,7 +1486,7 @@ encode_op: | |||
| 1447 | BUG_ON(cstate->replay_owner); | 1486 | BUG_ON(cstate->replay_owner); |
| 1448 | out: | 1487 | out: |
| 1449 | /* Reset deferral mechanism for RPC deferrals */ | 1488 | /* Reset deferral mechanism for RPC deferrals */ |
| 1450 | rqstp->rq_usedeferral = true; | 1489 | set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); |
| 1451 | dprintk("nfsv4 compound returned %d\n", ntohl(status)); | 1490 | dprintk("nfsv4 compound returned %d\n", ntohl(status)); |
| 1452 | return status; | 1491 | return status; |
| 1453 | } | 1492 | } |
| @@ -1929,6 +1968,18 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
| 1929 | }, | 1968 | }, |
| 1930 | 1969 | ||
| 1931 | /* NFSv4.2 operations */ | 1970 | /* NFSv4.2 operations */ |
| 1971 | [OP_ALLOCATE] = { | ||
| 1972 | .op_func = (nfsd4op_func)nfsd4_allocate, | ||
| 1973 | .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, | ||
| 1974 | .op_name = "OP_ALLOCATE", | ||
| 1975 | .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, | ||
| 1976 | }, | ||
| 1977 | [OP_DEALLOCATE] = { | ||
| 1978 | .op_func = (nfsd4op_func)nfsd4_deallocate, | ||
| 1979 | .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, | ||
| 1980 | .op_name = "OP_DEALLOCATE", | ||
| 1981 | .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, | ||
| 1982 | }, | ||
| 1932 | [OP_SEEK] = { | 1983 | [OP_SEEK] = { |
| 1933 | .op_func = (nfsd4op_func)nfsd4_seek, | 1984 | .op_func = (nfsd4op_func)nfsd4_seek, |
| 1934 | .op_name = "OP_SEEK", | 1985 | .op_name = "OP_SEEK", |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 4e1d7268b004..3550a9c87616 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -275,9 +275,11 @@ opaque_hashval(const void *ptr, int nbytes) | |||
| 275 | return x; | 275 | return x; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | static void nfsd4_free_file(struct nfs4_file *f) | 278 | static void nfsd4_free_file_rcu(struct rcu_head *rcu) |
| 279 | { | 279 | { |
| 280 | kmem_cache_free(file_slab, f); | 280 | struct nfs4_file *fp = container_of(rcu, struct nfs4_file, fi_rcu); |
| 281 | |||
| 282 | kmem_cache_free(file_slab, fp); | ||
| 281 | } | 283 | } |
| 282 | 284 | ||
| 283 | static inline void | 285 | static inline void |
| @@ -286,9 +288,10 @@ put_nfs4_file(struct nfs4_file *fi) | |||
| 286 | might_lock(&state_lock); | 288 | might_lock(&state_lock); |
| 287 | 289 | ||
| 288 | if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { | 290 | if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { |
| 289 | hlist_del(&fi->fi_hash); | 291 | hlist_del_rcu(&fi->fi_hash); |
| 290 | spin_unlock(&state_lock); | 292 | spin_unlock(&state_lock); |
| 291 | nfsd4_free_file(fi); | 293 | WARN_ON_ONCE(!list_empty(&fi->fi_delegations)); |
| 294 | call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu); | ||
| 292 | } | 295 | } |
| 293 | } | 296 | } |
| 294 | 297 | ||
| @@ -1440,7 +1443,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru | |||
| 1440 | list_add(&new->se_perclnt, &clp->cl_sessions); | 1443 | list_add(&new->se_perclnt, &clp->cl_sessions); |
| 1441 | spin_unlock(&clp->cl_lock); | 1444 | spin_unlock(&clp->cl_lock); |
| 1442 | 1445 | ||
| 1443 | if (cses->flags & SESSION4_BACK_CHAN) { | 1446 | { |
| 1444 | struct sockaddr *sa = svc_addr(rqstp); | 1447 | struct sockaddr *sa = svc_addr(rqstp); |
| 1445 | /* | 1448 | /* |
| 1446 | * This is a little silly; with sessions there's no real | 1449 | * This is a little silly; with sessions there's no real |
| @@ -1711,15 +1714,14 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source) | |||
| 1711 | return 0; | 1714 | return 0; |
| 1712 | } | 1715 | } |
| 1713 | 1716 | ||
| 1714 | static long long | 1717 | static int |
| 1715 | compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2) | 1718 | compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2) |
| 1716 | { | 1719 | { |
| 1717 | long long res; | 1720 | if (o1->len < o2->len) |
| 1718 | 1721 | return -1; | |
| 1719 | res = o1->len - o2->len; | 1722 | if (o1->len > o2->len) |
| 1720 | if (res) | 1723 | return 1; |
| 1721 | return res; | 1724 | return memcmp(o1->data, o2->data, o1->len); |
| 1722 | return (long long)memcmp(o1->data, o2->data, o1->len); | ||
| 1723 | } | 1725 | } |
| 1724 | 1726 | ||
| 1725 | static int same_name(const char *n1, const char *n2) | 1727 | static int same_name(const char *n1, const char *n2) |
| @@ -1907,7 +1909,7 @@ add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root) | |||
| 1907 | static struct nfs4_client * | 1909 | static struct nfs4_client * |
| 1908 | find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) | 1910 | find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) |
| 1909 | { | 1911 | { |
| 1910 | long long cmp; | 1912 | int cmp; |
| 1911 | struct rb_node *node = root->rb_node; | 1913 | struct rb_node *node = root->rb_node; |
| 1912 | struct nfs4_client *clp; | 1914 | struct nfs4_client *clp; |
| 1913 | 1915 | ||
| @@ -3057,10 +3059,9 @@ static struct nfs4_file *nfsd4_alloc_file(void) | |||
| 3057 | } | 3059 | } |
| 3058 | 3060 | ||
| 3059 | /* OPEN Share state helper functions */ | 3061 | /* OPEN Share state helper functions */ |
| 3060 | static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) | 3062 | static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval, |
| 3063 | struct nfs4_file *fp) | ||
| 3061 | { | 3064 | { |
| 3062 | unsigned int hashval = file_hashval(fh); | ||
| 3063 | |||
| 3064 | lockdep_assert_held(&state_lock); | 3065 | lockdep_assert_held(&state_lock); |
| 3065 | 3066 | ||
| 3066 | atomic_set(&fp->fi_ref, 1); | 3067 | atomic_set(&fp->fi_ref, 1); |
| @@ -3073,7 +3074,7 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) | |||
| 3073 | fp->fi_share_deny = 0; | 3074 | fp->fi_share_deny = 0; |
| 3074 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); | 3075 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); |
| 3075 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); | 3076 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); |
| 3076 | hlist_add_head(&fp->fi_hash, &file_hashtbl[hashval]); | 3077 | hlist_add_head_rcu(&fp->fi_hash, &file_hashtbl[hashval]); |
| 3077 | } | 3078 | } |
| 3078 | 3079 | ||
| 3079 | void | 3080 | void |
| @@ -3294,17 +3295,14 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) | |||
| 3294 | 3295 | ||
| 3295 | /* search file_hashtbl[] for file */ | 3296 | /* search file_hashtbl[] for file */ |
| 3296 | static struct nfs4_file * | 3297 | static struct nfs4_file * |
| 3297 | find_file_locked(struct knfsd_fh *fh) | 3298 | find_file_locked(struct knfsd_fh *fh, unsigned int hashval) |
| 3298 | { | 3299 | { |
| 3299 | unsigned int hashval = file_hashval(fh); | ||
| 3300 | struct nfs4_file *fp; | 3300 | struct nfs4_file *fp; |
| 3301 | 3301 | ||
| 3302 | lockdep_assert_held(&state_lock); | 3302 | hlist_for_each_entry_rcu(fp, &file_hashtbl[hashval], fi_hash) { |
| 3303 | |||
| 3304 | hlist_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { | ||
| 3305 | if (nfsd_fh_match(&fp->fi_fhandle, fh)) { | 3303 | if (nfsd_fh_match(&fp->fi_fhandle, fh)) { |
| 3306 | get_nfs4_file(fp); | 3304 | if (atomic_inc_not_zero(&fp->fi_ref)) |
| 3307 | return fp; | 3305 | return fp; |
| 3308 | } | 3306 | } |
| 3309 | } | 3307 | } |
| 3310 | return NULL; | 3308 | return NULL; |
| @@ -3314,10 +3312,11 @@ static struct nfs4_file * | |||
| 3314 | find_file(struct knfsd_fh *fh) | 3312 | find_file(struct knfsd_fh *fh) |
| 3315 | { | 3313 | { |
| 3316 | struct nfs4_file *fp; | 3314 | struct nfs4_file *fp; |
| 3315 | unsigned int hashval = file_hashval(fh); | ||
| 3317 | 3316 | ||
| 3318 | spin_lock(&state_lock); | 3317 | rcu_read_lock(); |
| 3319 | fp = find_file_locked(fh); | 3318 | fp = find_file_locked(fh, hashval); |
| 3320 | spin_unlock(&state_lock); | 3319 | rcu_read_unlock(); |
| 3321 | return fp; | 3320 | return fp; |
| 3322 | } | 3321 | } |
| 3323 | 3322 | ||
| @@ -3325,11 +3324,18 @@ static struct nfs4_file * | |||
| 3325 | find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh) | 3324 | find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh) |
| 3326 | { | 3325 | { |
| 3327 | struct nfs4_file *fp; | 3326 | struct nfs4_file *fp; |
| 3327 | unsigned int hashval = file_hashval(fh); | ||
| 3328 | |||
| 3329 | rcu_read_lock(); | ||
| 3330 | fp = find_file_locked(fh, hashval); | ||
| 3331 | rcu_read_unlock(); | ||
| 3332 | if (fp) | ||
| 3333 | return fp; | ||
| 3328 | 3334 | ||
| 3329 | spin_lock(&state_lock); | 3335 | spin_lock(&state_lock); |
| 3330 | fp = find_file_locked(fh); | 3336 | fp = find_file_locked(fh, hashval); |
| 3331 | if (fp == NULL) { | 3337 | if (likely(fp == NULL)) { |
| 3332 | nfsd4_init_file(new, fh); | 3338 | nfsd4_init_file(fh, hashval, new); |
| 3333 | fp = new; | 3339 | fp = new; |
| 3334 | } | 3340 | } |
| 3335 | spin_unlock(&state_lock); | 3341 | spin_unlock(&state_lock); |
| @@ -4127,7 +4133,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate, | |||
| 4127 | nfs4_put_stateowner(so); | 4133 | nfs4_put_stateowner(so); |
| 4128 | } | 4134 | } |
| 4129 | if (open->op_file) | 4135 | if (open->op_file) |
| 4130 | nfsd4_free_file(open->op_file); | 4136 | kmem_cache_free(file_slab, open->op_file); |
| 4131 | if (open->op_stp) | 4137 | if (open->op_stp) |
| 4132 | nfs4_put_stid(&open->op_stp->st_stid); | 4138 | nfs4_put_stid(&open->op_stp->st_stid); |
| 4133 | } | 4139 | } |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b1eed4dd2eab..15f7b73e0c0f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -1514,6 +1514,23 @@ static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, str | |||
| 1514 | } | 1514 | } |
| 1515 | 1515 | ||
| 1516 | static __be32 | 1516 | static __be32 |
| 1517 | nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp, | ||
| 1518 | struct nfsd4_fallocate *fallocate) | ||
| 1519 | { | ||
| 1520 | DECODE_HEAD; | ||
| 1521 | |||
| 1522 | status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid); | ||
| 1523 | if (status) | ||
| 1524 | return status; | ||
| 1525 | |||
| 1526 | READ_BUF(16); | ||
| 1527 | p = xdr_decode_hyper(p, &fallocate->falloc_offset); | ||
| 1528 | xdr_decode_hyper(p, &fallocate->falloc_length); | ||
| 1529 | |||
| 1530 | DECODE_TAIL; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | static __be32 | ||
| 1517 | nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) | 1534 | nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) |
| 1518 | { | 1535 | { |
| 1519 | DECODE_HEAD; | 1536 | DECODE_HEAD; |
| @@ -1604,10 +1621,10 @@ static nfsd4_dec nfsd4_dec_ops[] = { | |||
| 1604 | [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, | 1621 | [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, |
| 1605 | 1622 | ||
| 1606 | /* new operations for NFSv4.2 */ | 1623 | /* new operations for NFSv4.2 */ |
| 1607 | [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp, | 1624 | [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate, |
| 1608 | [OP_COPY] = (nfsd4_dec)nfsd4_decode_notsupp, | 1625 | [OP_COPY] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1609 | [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp, | 1626 | [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1610 | [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_notsupp, | 1627 | [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate, |
| 1611 | [OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp, | 1628 | [OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1612 | [OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp, | 1629 | [OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1613 | [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp, | 1630 | [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp, |
| @@ -1714,7 +1731,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
| 1714 | argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; | 1731 | argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; |
| 1715 | 1732 | ||
| 1716 | if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack) | 1733 | if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack) |
| 1717 | argp->rqstp->rq_splice_ok = false; | 1734 | clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags); |
| 1718 | 1735 | ||
| 1719 | DECODE_TAIL; | 1736 | DECODE_TAIL; |
| 1720 | } | 1737 | } |
| @@ -1795,9 +1812,12 @@ static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep, | |||
| 1795 | } | 1812 | } |
| 1796 | else | 1813 | else |
| 1797 | end++; | 1814 | end++; |
| 1815 | if (found_esc) | ||
| 1816 | end = next; | ||
| 1817 | |||
| 1798 | str = end; | 1818 | str = end; |
| 1799 | } | 1819 | } |
| 1800 | pathlen = htonl(xdr->buf->len - pathlen_offset); | 1820 | pathlen = htonl(count); |
| 1801 | write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4); | 1821 | write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4); |
| 1802 | return 0; | 1822 | return 0; |
| 1803 | } | 1823 | } |
| @@ -3236,10 +3256,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
| 3236 | 3256 | ||
| 3237 | p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ | 3257 | p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ |
| 3238 | if (!p) { | 3258 | if (!p) { |
| 3239 | WARN_ON_ONCE(resp->rqstp->rq_splice_ok); | 3259 | WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)); |
| 3240 | return nfserr_resource; | 3260 | return nfserr_resource; |
| 3241 | } | 3261 | } |
| 3242 | if (resp->xdr.buf->page_len && resp->rqstp->rq_splice_ok) { | 3262 | if (resp->xdr.buf->page_len && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) { |
| 3243 | WARN_ON_ONCE(1); | 3263 | WARN_ON_ONCE(1); |
| 3244 | return nfserr_resource; | 3264 | return nfserr_resource; |
| 3245 | } | 3265 | } |
| @@ -3256,7 +3276,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
| 3256 | goto err_truncate; | 3276 | goto err_truncate; |
| 3257 | } | 3277 | } |
| 3258 | 3278 | ||
| 3259 | if (file->f_op->splice_read && resp->rqstp->rq_splice_ok) | 3279 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) |
| 3260 | err = nfsd4_encode_splice_read(resp, read, file, maxcount); | 3280 | err = nfsd4_encode_splice_read(resp, read, file, maxcount); |
| 3261 | else | 3281 | else |
| 3262 | err = nfsd4_encode_readv(resp, read, file, maxcount); | 3282 | err = nfsd4_encode_readv(resp, read, file, maxcount); |
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index 122f69185ef5..83a9694ec485 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c | |||
| @@ -490,7 +490,7 @@ found_entry: | |||
| 490 | /* From the hall of fame of impractical attacks: | 490 | /* From the hall of fame of impractical attacks: |
| 491 | * Is this a user who tries to snoop on the cache? */ | 491 | * Is this a user who tries to snoop on the cache? */ |
| 492 | rtn = RC_DOIT; | 492 | rtn = RC_DOIT; |
| 493 | if (!rqstp->rq_secure && rp->c_secure) | 493 | if (!test_bit(RQ_SECURE, &rqstp->rq_flags) && rp->c_secure) |
| 494 | goto out; | 494 | goto out; |
| 495 | 495 | ||
| 496 | /* Compose RPC reply header */ | 496 | /* Compose RPC reply header */ |
| @@ -579,7 +579,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp) | |||
| 579 | spin_lock(&b->cache_lock); | 579 | spin_lock(&b->cache_lock); |
| 580 | drc_mem_usage += bufsize; | 580 | drc_mem_usage += bufsize; |
| 581 | lru_put_end(b, rp); | 581 | lru_put_end(b, rp); |
| 582 | rp->c_secure = rqstp->rq_secure; | 582 | rp->c_secure = test_bit(RQ_SECURE, &rqstp->rq_flags); |
| 583 | rp->c_type = cachetype; | 583 | rp->c_type = cachetype; |
| 584 | rp->c_state = RC_DONE; | 584 | rp->c_state = RC_DONE; |
| 585 | spin_unlock(&b->cache_lock); | 585 | spin_unlock(&b->cache_lock); |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 9506ea565610..19ace74d35f6 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -608,7 +608,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
| 608 | num); | 608 | num); |
| 609 | sep = " "; | 609 | sep = " "; |
| 610 | 610 | ||
| 611 | if (len > remaining) | 611 | if (len >= remaining) |
| 612 | break; | 612 | break; |
| 613 | remaining -= len; | 613 | remaining -= len; |
| 614 | buf += len; | 614 | buf += len; |
| @@ -623,7 +623,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
| 623 | '+' : '-', | 623 | '+' : '-', |
| 624 | minor); | 624 | minor); |
| 625 | 625 | ||
| 626 | if (len > remaining) | 626 | if (len >= remaining) |
| 627 | break; | 627 | break; |
| 628 | remaining -= len; | 628 | remaining -= len; |
| 629 | buf += len; | 629 | buf += len; |
| @@ -631,7 +631,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) | |||
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | len = snprintf(buf, remaining, "\n"); | 633 | len = snprintf(buf, remaining, "\n"); |
| 634 | if (len > remaining) | 634 | if (len >= remaining) |
| 635 | return -EINVAL; | 635 | return -EINVAL; |
| 636 | return tlen + len; | 636 | return tlen + len; |
| 637 | } | 637 | } |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 88026fc6a981..965b478d50fc 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
| @@ -86,7 +86,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, | |||
| 86 | int flags = nfsexp_flags(rqstp, exp); | 86 | int flags = nfsexp_flags(rqstp, exp); |
| 87 | 87 | ||
| 88 | /* Check if the request originated from a secure port. */ | 88 | /* Check if the request originated from a secure port. */ |
| 89 | if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) { | 89 | if (!test_bit(RQ_SECURE, &rqstp->rq_flags) && !(flags & NFSEXP_INSECURE_PORT)) { |
| 90 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | 90 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
| 91 | dprintk("nfsd: request from insecure port %s!\n", | 91 | dprintk("nfsd: request from insecure port %s!\n", |
| 92 | svc_print_addr(rqstp, buf, sizeof(buf))); | 92 | svc_print_addr(rqstp, buf, sizeof(buf))); |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 752d56bbe0ba..314f5c8f8f1a 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -692,7 +692,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |||
| 692 | /* Now call the procedure handler, and encode NFS status. */ | 692 | /* Now call the procedure handler, and encode NFS status. */ |
| 693 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); | 693 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
| 694 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); | 694 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); |
| 695 | if (nfserr == nfserr_dropit || rqstp->rq_dropme) { | 695 | if (nfserr == nfserr_dropit || test_bit(RQ_DROPME, &rqstp->rq_flags)) { |
| 696 | dprintk("nfsd: Dropping request; may be revisited later\n"); | 696 | dprintk("nfsd: Dropping request; may be revisited later\n"); |
| 697 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | 697 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); |
| 698 | return 0; | 698 | return 0; |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2712042a66b1..9d3be371240a 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
| @@ -463,17 +463,24 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so) | |||
| 463 | /* | 463 | /* |
| 464 | * nfs4_file: a file opened by some number of (open) nfs4_stateowners. | 464 | * nfs4_file: a file opened by some number of (open) nfs4_stateowners. |
| 465 | * | 465 | * |
| 466 | * These objects are global. nfsd only keeps one instance of a nfs4_file per | 466 | * These objects are global. nfsd keeps one instance of a nfs4_file per |
| 467 | * inode (though it may keep multiple file descriptors open per inode). These | 467 | * filehandle (though it may keep multiple file descriptors for each). Each |
| 468 | * are tracked in the file_hashtbl which is protected by the state_lock | 468 | * inode can have multiple filehandles associated with it, so there is |
| 469 | * spinlock. | 469 | * (potentially) a many to one relationship between this struct and struct |
| 470 | * inode. | ||
| 471 | * | ||
| 472 | * These are hashed by filehandle in the file_hashtbl, which is protected by | ||
| 473 | * the global state_lock spinlock. | ||
| 470 | */ | 474 | */ |
| 471 | struct nfs4_file { | 475 | struct nfs4_file { |
| 472 | atomic_t fi_ref; | 476 | atomic_t fi_ref; |
| 473 | spinlock_t fi_lock; | 477 | spinlock_t fi_lock; |
| 474 | struct hlist_node fi_hash; /* hash by "struct inode *" */ | 478 | struct hlist_node fi_hash; /* hash on fi_fhandle */ |
| 475 | struct list_head fi_stateids; | 479 | struct list_head fi_stateids; |
| 476 | struct list_head fi_delegations; | 480 | union { |
| 481 | struct list_head fi_delegations; | ||
| 482 | struct rcu_head fi_rcu; | ||
| 483 | }; | ||
| 477 | /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ | 484 | /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ |
| 478 | struct file * fi_fds[3]; | 485 | struct file * fi_fds[3]; |
| 479 | /* | 486 | /* |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 0a82e3c033ee..5685c679dd93 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
| 17 | #include <linux/file.h> | 17 | #include <linux/file.h> |
| 18 | #include <linux/splice.h> | 18 | #include <linux/splice.h> |
| 19 | #include <linux/falloc.h> | ||
| 19 | #include <linux/fcntl.h> | 20 | #include <linux/fcntl.h> |
| 20 | #include <linux/namei.h> | 21 | #include <linux/namei.h> |
| 21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| @@ -533,6 +534,26 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 533 | } | 534 | } |
| 534 | #endif | 535 | #endif |
| 535 | 536 | ||
| 537 | __be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
| 538 | struct file *file, loff_t offset, loff_t len, | ||
| 539 | int flags) | ||
| 540 | { | ||
| 541 | __be32 err; | ||
| 542 | int error; | ||
| 543 | |||
| 544 | if (!S_ISREG(file_inode(file)->i_mode)) | ||
| 545 | return nfserr_inval; | ||
| 546 | |||
| 547 | err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, NFSD_MAY_WRITE); | ||
| 548 | if (err) | ||
| 549 | return err; | ||
| 550 | |||
| 551 | error = vfs_fallocate(file, flags, offset, len); | ||
| 552 | if (!error) | ||
| 553 | error = commit_metadata(fhp); | ||
| 554 | |||
| 555 | return nfserrno(error); | ||
| 556 | } | ||
| 536 | #endif /* defined(CONFIG_NFSD_V4) */ | 557 | #endif /* defined(CONFIG_NFSD_V4) */ |
| 537 | 558 | ||
| 538 | #ifdef CONFIG_NFSD_V3 | 559 | #ifdef CONFIG_NFSD_V3 |
| @@ -881,7 +902,7 @@ static __be32 | |||
| 881 | nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file, | 902 | nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file, |
| 882 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 903 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
| 883 | { | 904 | { |
| 884 | if (file->f_op->splice_read && rqstp->rq_splice_ok) | 905 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) |
| 885 | return nfsd_splice_read(rqstp, file, offset, count); | 906 | return nfsd_splice_read(rqstp, file, offset, count); |
| 886 | else | 907 | else |
| 887 | return nfsd_readv(file, offset, vec, vlen, count); | 908 | return nfsd_readv(file, offset, vec, vlen, count); |
| @@ -937,9 +958,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 937 | int stable = *stablep; | 958 | int stable = *stablep; |
| 938 | int use_wgather; | 959 | int use_wgather; |
| 939 | loff_t pos = offset; | 960 | loff_t pos = offset; |
| 961 | loff_t end = LLONG_MAX; | ||
| 940 | unsigned int pflags = current->flags; | 962 | unsigned int pflags = current->flags; |
| 941 | 963 | ||
| 942 | if (rqstp->rq_local) | 964 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) |
| 943 | /* | 965 | /* |
| 944 | * We want less throttling in balance_dirty_pages() | 966 | * We want less throttling in balance_dirty_pages() |
| 945 | * and shrink_inactive_list() so that nfs to | 967 | * and shrink_inactive_list() so that nfs to |
| @@ -967,10 +989,13 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 967 | fsnotify_modify(file); | 989 | fsnotify_modify(file); |
| 968 | 990 | ||
| 969 | if (stable) { | 991 | if (stable) { |
| 970 | if (use_wgather) | 992 | if (use_wgather) { |
| 971 | host_err = wait_for_concurrent_writes(file); | 993 | host_err = wait_for_concurrent_writes(file); |
| 972 | else | 994 | } else { |
| 973 | host_err = vfs_fsync_range(file, offset, offset+*cnt, 0); | 995 | if (*cnt) |
| 996 | end = offset + *cnt - 1; | ||
| 997 | host_err = vfs_fsync_range(file, offset, end, 0); | ||
| 998 | } | ||
| 974 | } | 999 | } |
| 975 | 1000 | ||
| 976 | out_nfserr: | 1001 | out_nfserr: |
| @@ -979,7 +1004,7 @@ out_nfserr: | |||
| 979 | err = 0; | 1004 | err = 0; |
| 980 | else | 1005 | else |
| 981 | err = nfserrno(host_err); | 1006 | err = nfserrno(host_err); |
| 982 | if (rqstp->rq_local) | 1007 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) |
| 983 | tsk_restore_flags(current, pflags, PF_LESS_THROTTLE); | 1008 | tsk_restore_flags(current, pflags, PF_LESS_THROTTLE); |
| 984 | return err; | 1009 | return err; |
| 985 | } | 1010 | } |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index b1796d6ee538..2050cb016998 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
| @@ -54,6 +54,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *); | |||
| 54 | #ifdef CONFIG_NFSD_V4 | 54 | #ifdef CONFIG_NFSD_V4 |
| 55 | __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, | 55 | __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, |
| 56 | struct xdr_netobj *); | 56 | struct xdr_netobj *); |
| 57 | __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *, | ||
| 58 | struct file *, loff_t, loff_t, int); | ||
| 57 | #endif /* CONFIG_NFSD_V4 */ | 59 | #endif /* CONFIG_NFSD_V4 */ |
| 58 | __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, | 60 | __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, |
| 59 | char *name, int len, struct iattr *attrs, | 61 | char *name, int len, struct iattr *attrs, |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 5720e9457f33..90a5925bd6ab 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
| @@ -428,6 +428,13 @@ struct nfsd4_reclaim_complete { | |||
| 428 | u32 rca_one_fs; | 428 | u32 rca_one_fs; |
| 429 | }; | 429 | }; |
| 430 | 430 | ||
| 431 | struct nfsd4_fallocate { | ||
| 432 | /* request */ | ||
| 433 | stateid_t falloc_stateid; | ||
| 434 | loff_t falloc_offset; | ||
| 435 | u64 falloc_length; | ||
| 436 | }; | ||
| 437 | |||
| 431 | struct nfsd4_seek { | 438 | struct nfsd4_seek { |
| 432 | /* request */ | 439 | /* request */ |
| 433 | stateid_t seek_stateid; | 440 | stateid_t seek_stateid; |
| @@ -486,6 +493,8 @@ struct nfsd4_op { | |||
| 486 | struct nfsd4_free_stateid free_stateid; | 493 | struct nfsd4_free_stateid free_stateid; |
| 487 | 494 | ||
| 488 | /* NFSv4.2 */ | 495 | /* NFSv4.2 */ |
| 496 | struct nfsd4_fallocate allocate; | ||
| 497 | struct nfsd4_fallocate deallocate; | ||
| 489 | struct nfsd4_seek seek; | 498 | struct nfsd4_seek seek; |
| 490 | } u; | 499 | } u; |
| 491 | struct nfs4_replay * replay; | 500 | struct nfs4_replay * replay; |
| @@ -222,7 +222,7 @@ SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length) | |||
| 222 | #endif /* BITS_PER_LONG == 32 */ | 222 | #endif /* BITS_PER_LONG == 32 */ |
| 223 | 223 | ||
| 224 | 224 | ||
| 225 | int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | 225 | int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
| 226 | { | 226 | { |
| 227 | struct inode *inode = file_inode(file); | 227 | struct inode *inode = file_inode(file); |
| 228 | long ret; | 228 | long ret; |
| @@ -309,6 +309,7 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 309 | sb_end_write(inode->i_sb); | 309 | sb_end_write(inode->i_sb); |
| 310 | return ret; | 310 | return ret; |
| 311 | } | 311 | } |
| 312 | EXPORT_SYMBOL_GPL(vfs_fallocate); | ||
| 312 | 313 | ||
| 313 | SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) | 314 | SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) |
| 314 | { | 315 | { |
| @@ -316,7 +317,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) | |||
| 316 | int error = -EBADF; | 317 | int error = -EBADF; |
| 317 | 318 | ||
| 318 | if (f.file) { | 319 | if (f.file) { |
| 319 | error = do_fallocate(f.file, mode, offset, len); | 320 | error = vfs_fallocate(f.file, mode, offset, len); |
| 320 | fdput(f); | 321 | fdput(f); |
| 321 | } | 322 | } |
| 322 | return error; | 323 | return error; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 88157253b9e6..eeaccd37184f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -2086,7 +2086,7 @@ struct filename { | |||
| 2086 | extern long vfs_truncate(struct path *, loff_t); | 2086 | extern long vfs_truncate(struct path *, loff_t); |
| 2087 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, | 2087 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, |
| 2088 | struct file *filp); | 2088 | struct file *filp); |
| 2089 | extern int do_fallocate(struct file *file, int mode, loff_t offset, | 2089 | extern int vfs_fallocate(struct file *file, int mode, loff_t offset, |
| 2090 | loff_t len); | 2090 | loff_t len); |
| 2091 | extern long do_sys_open(int dfd, const char __user *filename, int flags, | 2091 | extern long do_sys_open(int dfd, const char __user *filename, int flags, |
| 2092 | umode_t mode); | 2092 | umode_t mode); |
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 21678464883a..6f22cfeef5e3 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h | |||
| @@ -26,10 +26,10 @@ typedef int (*svc_thread_fn)(void *); | |||
| 26 | 26 | ||
| 27 | /* statistics for svc_pool structures */ | 27 | /* statistics for svc_pool structures */ |
| 28 | struct svc_pool_stats { | 28 | struct svc_pool_stats { |
| 29 | unsigned long packets; | 29 | atomic_long_t packets; |
| 30 | unsigned long sockets_queued; | 30 | unsigned long sockets_queued; |
| 31 | unsigned long threads_woken; | 31 | atomic_long_t threads_woken; |
| 32 | unsigned long threads_timedout; | 32 | atomic_long_t threads_timedout; |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| @@ -45,12 +45,13 @@ struct svc_pool_stats { | |||
| 45 | struct svc_pool { | 45 | struct svc_pool { |
| 46 | unsigned int sp_id; /* pool id; also node id on NUMA */ | 46 | unsigned int sp_id; /* pool id; also node id on NUMA */ |
| 47 | spinlock_t sp_lock; /* protects all fields */ | 47 | spinlock_t sp_lock; /* protects all fields */ |
| 48 | struct list_head sp_threads; /* idle server threads */ | ||
| 49 | struct list_head sp_sockets; /* pending sockets */ | 48 | struct list_head sp_sockets; /* pending sockets */ |
| 50 | unsigned int sp_nrthreads; /* # of threads in pool */ | 49 | unsigned int sp_nrthreads; /* # of threads in pool */ |
| 51 | struct list_head sp_all_threads; /* all server threads */ | 50 | struct list_head sp_all_threads; /* all server threads */ |
| 52 | struct svc_pool_stats sp_stats; /* statistics on pool operation */ | 51 | struct svc_pool_stats sp_stats; /* statistics on pool operation */ |
| 53 | int sp_task_pending;/* has pending task */ | 52 | #define SP_TASK_PENDING (0) /* still work to do even if no |
| 53 | * xprt is queued. */ | ||
| 54 | unsigned long sp_flags; | ||
| 54 | } ____cacheline_aligned_in_smp; | 55 | } ____cacheline_aligned_in_smp; |
| 55 | 56 | ||
| 56 | /* | 57 | /* |
| @@ -219,8 +220,8 @@ static inline void svc_putu32(struct kvec *iov, __be32 val) | |||
| 219 | * processed. | 220 | * processed. |
| 220 | */ | 221 | */ |
| 221 | struct svc_rqst { | 222 | struct svc_rqst { |
| 222 | struct list_head rq_list; /* idle list */ | ||
| 223 | struct list_head rq_all; /* all threads list */ | 223 | struct list_head rq_all; /* all threads list */ |
| 224 | struct rcu_head rq_rcu_head; /* for RCU deferred kfree */ | ||
| 224 | struct svc_xprt * rq_xprt; /* transport ptr */ | 225 | struct svc_xprt * rq_xprt; /* transport ptr */ |
| 225 | 226 | ||
| 226 | struct sockaddr_storage rq_addr; /* peer address */ | 227 | struct sockaddr_storage rq_addr; /* peer address */ |
| @@ -236,7 +237,6 @@ struct svc_rqst { | |||
| 236 | struct svc_cred rq_cred; /* auth info */ | 237 | struct svc_cred rq_cred; /* auth info */ |
| 237 | void * rq_xprt_ctxt; /* transport specific context ptr */ | 238 | void * rq_xprt_ctxt; /* transport specific context ptr */ |
| 238 | struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */ | 239 | struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */ |
| 239 | bool rq_usedeferral; /* use deferral */ | ||
| 240 | 240 | ||
| 241 | size_t rq_xprt_hlen; /* xprt header len */ | 241 | size_t rq_xprt_hlen; /* xprt header len */ |
| 242 | struct xdr_buf rq_arg; | 242 | struct xdr_buf rq_arg; |
| @@ -253,9 +253,17 @@ struct svc_rqst { | |||
| 253 | u32 rq_vers; /* program version */ | 253 | u32 rq_vers; /* program version */ |
| 254 | u32 rq_proc; /* procedure number */ | 254 | u32 rq_proc; /* procedure number */ |
| 255 | u32 rq_prot; /* IP protocol */ | 255 | u32 rq_prot; /* IP protocol */ |
| 256 | unsigned short | 256 | int rq_cachetype; /* catering to nfsd */ |
| 257 | rq_secure : 1; /* secure port */ | 257 | #define RQ_SECURE (0) /* secure port */ |
| 258 | unsigned short rq_local : 1; /* local request */ | 258 | #define RQ_LOCAL (1) /* local request */ |
| 259 | #define RQ_USEDEFERRAL (2) /* use deferral */ | ||
| 260 | #define RQ_DROPME (3) /* drop current reply */ | ||
| 261 | #define RQ_SPLICE_OK (4) /* turned off in gss privacy | ||
| 262 | * to prevent encrypting page | ||
| 263 | * cache pages */ | ||
| 264 | #define RQ_VICTIM (5) /* about to be shut down */ | ||
| 265 | #define RQ_BUSY (6) /* request is busy */ | ||
| 266 | unsigned long rq_flags; /* flags field */ | ||
| 259 | 267 | ||
| 260 | void * rq_argp; /* decoded arguments */ | 268 | void * rq_argp; /* decoded arguments */ |
| 261 | void * rq_resp; /* xdr'd results */ | 269 | void * rq_resp; /* xdr'd results */ |
| @@ -271,16 +279,12 @@ struct svc_rqst { | |||
| 271 | struct cache_req rq_chandle; /* handle passed to caches for | 279 | struct cache_req rq_chandle; /* handle passed to caches for |
| 272 | * request delaying | 280 | * request delaying |
| 273 | */ | 281 | */ |
| 274 | bool rq_dropme; | ||
| 275 | /* Catering to nfsd */ | 282 | /* Catering to nfsd */ |
| 276 | struct auth_domain * rq_client; /* RPC peer info */ | 283 | struct auth_domain * rq_client; /* RPC peer info */ |
| 277 | struct auth_domain * rq_gssclient; /* "gss/"-style peer info */ | 284 | struct auth_domain * rq_gssclient; /* "gss/"-style peer info */ |
| 278 | int rq_cachetype; | ||
| 279 | struct svc_cacherep * rq_cacherep; /* cache info */ | 285 | struct svc_cacherep * rq_cacherep; /* cache info */ |
| 280 | bool rq_splice_ok; /* turned off in gss privacy | ||
| 281 | * to prevent encrypting page | ||
| 282 | * cache pages */ | ||
| 283 | struct task_struct *rq_task; /* service thread */ | 286 | struct task_struct *rq_task; /* service thread */ |
| 287 | spinlock_t rq_lock; /* per-request lock */ | ||
| 284 | }; | 288 | }; |
| 285 | 289 | ||
| 286 | #define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net) | 290 | #define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net) |
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h index ce6e4182a5b2..79f6f8f3dc0a 100644 --- a/include/linux/sunrpc/svc_xprt.h +++ b/include/linux/sunrpc/svc_xprt.h | |||
| @@ -63,10 +63,9 @@ struct svc_xprt { | |||
| 63 | #define XPT_CHNGBUF 7 /* need to change snd/rcv buf sizes */ | 63 | #define XPT_CHNGBUF 7 /* need to change snd/rcv buf sizes */ |
| 64 | #define XPT_DEFERRED 8 /* deferred request pending */ | 64 | #define XPT_DEFERRED 8 /* deferred request pending */ |
| 65 | #define XPT_OLD 9 /* used for xprt aging mark+sweep */ | 65 | #define XPT_OLD 9 /* used for xprt aging mark+sweep */ |
| 66 | #define XPT_DETACHED 10 /* detached from tempsocks list */ | 66 | #define XPT_LISTENER 10 /* listening endpoint */ |
| 67 | #define XPT_LISTENER 11 /* listening endpoint */ | 67 | #define XPT_CACHE_AUTH 11 /* cache auth info */ |
| 68 | #define XPT_CACHE_AUTH 12 /* cache auth info */ | 68 | #define XPT_LOCAL 12 /* connection from loopback interface */ |
| 69 | #define XPT_LOCAL 13 /* connection from loopback interface */ | ||
| 70 | 69 | ||
| 71 | struct svc_serv *xpt_server; /* service for transport */ | 70 | struct svc_serv *xpt_server; /* service for transport */ |
| 72 | atomic_t xpt_reserved; /* space on outq that is rsvd */ | 71 | atomic_t xpt_reserved; /* space on outq that is rsvd */ |
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 171ca4ff6d99..b9c1dc6c825a 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/sunrpc/clnt.h> | 8 | #include <linux/sunrpc/clnt.h> |
| 9 | #include <linux/sunrpc/svc.h> | 9 | #include <linux/sunrpc/svc.h> |
| 10 | #include <linux/sunrpc/xprtsock.h> | 10 | #include <linux/sunrpc/xprtsock.h> |
| 11 | #include <linux/sunrpc/svc_xprt.h> | ||
| 11 | #include <net/tcp_states.h> | 12 | #include <net/tcp_states.h> |
| 12 | #include <linux/net.h> | 13 | #include <linux/net.h> |
| 13 | #include <linux/tracepoint.h> | 14 | #include <linux/tracepoint.h> |
| @@ -412,6 +413,16 @@ TRACE_EVENT(xs_tcp_data_recv, | |||
| 412 | __entry->copied, __entry->reclen, __entry->offset) | 413 | __entry->copied, __entry->reclen, __entry->offset) |
| 413 | ); | 414 | ); |
| 414 | 415 | ||
| 416 | #define show_rqstp_flags(flags) \ | ||
| 417 | __print_flags(flags, "|", \ | ||
| 418 | { (1UL << RQ_SECURE), "RQ_SECURE"}, \ | ||
| 419 | { (1UL << RQ_LOCAL), "RQ_LOCAL"}, \ | ||
| 420 | { (1UL << RQ_USEDEFERRAL), "RQ_USEDEFERRAL"}, \ | ||
| 421 | { (1UL << RQ_DROPME), "RQ_DROPME"}, \ | ||
| 422 | { (1UL << RQ_SPLICE_OK), "RQ_SPLICE_OK"}, \ | ||
| 423 | { (1UL << RQ_VICTIM), "RQ_VICTIM"}, \ | ||
| 424 | { (1UL << RQ_BUSY), "RQ_BUSY"}) | ||
| 425 | |||
| 415 | TRACE_EVENT(svc_recv, | 426 | TRACE_EVENT(svc_recv, |
| 416 | TP_PROTO(struct svc_rqst *rqst, int status), | 427 | TP_PROTO(struct svc_rqst *rqst, int status), |
| 417 | 428 | ||
| @@ -421,16 +432,19 @@ TRACE_EVENT(svc_recv, | |||
| 421 | __field(struct sockaddr *, addr) | 432 | __field(struct sockaddr *, addr) |
| 422 | __field(__be32, xid) | 433 | __field(__be32, xid) |
| 423 | __field(int, status) | 434 | __field(int, status) |
| 435 | __field(unsigned long, flags) | ||
| 424 | ), | 436 | ), |
| 425 | 437 | ||
| 426 | TP_fast_assign( | 438 | TP_fast_assign( |
| 427 | __entry->addr = (struct sockaddr *)&rqst->rq_addr; | 439 | __entry->addr = (struct sockaddr *)&rqst->rq_addr; |
| 428 | __entry->xid = status > 0 ? rqst->rq_xid : 0; | 440 | __entry->xid = status > 0 ? rqst->rq_xid : 0; |
| 429 | __entry->status = status; | 441 | __entry->status = status; |
| 442 | __entry->flags = rqst->rq_flags; | ||
| 430 | ), | 443 | ), |
| 431 | 444 | ||
| 432 | TP_printk("addr=%pIScp xid=0x%x status=%d", __entry->addr, | 445 | TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", __entry->addr, |
| 433 | be32_to_cpu(__entry->xid), __entry->status) | 446 | be32_to_cpu(__entry->xid), __entry->status, |
| 447 | show_rqstp_flags(__entry->flags)) | ||
| 434 | ); | 448 | ); |
| 435 | 449 | ||
| 436 | DECLARE_EVENT_CLASS(svc_rqst_status, | 450 | DECLARE_EVENT_CLASS(svc_rqst_status, |
| @@ -444,18 +458,19 @@ DECLARE_EVENT_CLASS(svc_rqst_status, | |||
| 444 | __field(__be32, xid) | 458 | __field(__be32, xid) |
| 445 | __field(int, dropme) | 459 | __field(int, dropme) |
| 446 | __field(int, status) | 460 | __field(int, status) |
| 461 | __field(unsigned long, flags) | ||
| 447 | ), | 462 | ), |
| 448 | 463 | ||
| 449 | TP_fast_assign( | 464 | TP_fast_assign( |
| 450 | __entry->addr = (struct sockaddr *)&rqst->rq_addr; | 465 | __entry->addr = (struct sockaddr *)&rqst->rq_addr; |
| 451 | __entry->xid = rqst->rq_xid; | 466 | __entry->xid = rqst->rq_xid; |
| 452 | __entry->dropme = (int)rqst->rq_dropme; | ||
| 453 | __entry->status = status; | 467 | __entry->status = status; |
| 468 | __entry->flags = rqst->rq_flags; | ||
| 454 | ), | 469 | ), |
| 455 | 470 | ||
| 456 | TP_printk("addr=%pIScp rq_xid=0x%x dropme=%d status=%d", | 471 | TP_printk("addr=%pIScp rq_xid=0x%x status=%d flags=%s", |
| 457 | __entry->addr, be32_to_cpu(__entry->xid), __entry->dropme, | 472 | __entry->addr, be32_to_cpu(__entry->xid), |
| 458 | __entry->status) | 473 | __entry->status, show_rqstp_flags(__entry->flags)) |
| 459 | ); | 474 | ); |
| 460 | 475 | ||
| 461 | DEFINE_EVENT(svc_rqst_status, svc_process, | 476 | DEFINE_EVENT(svc_rqst_status, svc_process, |
| @@ -466,6 +481,99 @@ DEFINE_EVENT(svc_rqst_status, svc_send, | |||
| 466 | TP_PROTO(struct svc_rqst *rqst, int status), | 481 | TP_PROTO(struct svc_rqst *rqst, int status), |
| 467 | TP_ARGS(rqst, status)); | 482 | TP_ARGS(rqst, status)); |
| 468 | 483 | ||
| 484 | #define show_svc_xprt_flags(flags) \ | ||
| 485 | __print_flags(flags, "|", \ | ||
| 486 | { (1UL << XPT_BUSY), "XPT_BUSY"}, \ | ||
| 487 | { (1UL << XPT_CONN), "XPT_CONN"}, \ | ||
| 488 | { (1UL << XPT_CLOSE), "XPT_CLOSE"}, \ | ||
| 489 | { (1UL << XPT_DATA), "XPT_DATA"}, \ | ||
| 490 | { (1UL << XPT_TEMP), "XPT_TEMP"}, \ | ||
| 491 | { (1UL << XPT_DEAD), "XPT_DEAD"}, \ | ||
| 492 | { (1UL << XPT_CHNGBUF), "XPT_CHNGBUF"}, \ | ||
| 493 | { (1UL << XPT_DEFERRED), "XPT_DEFERRED"}, \ | ||
| 494 | { (1UL << XPT_OLD), "XPT_OLD"}, \ | ||
| 495 | { (1UL << XPT_LISTENER), "XPT_LISTENER"}, \ | ||
| 496 | { (1UL << XPT_CACHE_AUTH), "XPT_CACHE_AUTH"}, \ | ||
| 497 | { (1UL << XPT_LOCAL), "XPT_LOCAL"}) | ||
| 498 | |||
| 499 | TRACE_EVENT(svc_xprt_do_enqueue, | ||
| 500 | TP_PROTO(struct svc_xprt *xprt, struct svc_rqst *rqst), | ||
| 501 | |||
| 502 | TP_ARGS(xprt, rqst), | ||
| 503 | |||
| 504 | TP_STRUCT__entry( | ||
| 505 | __field(struct svc_xprt *, xprt) | ||
| 506 | __field(struct svc_rqst *, rqst) | ||
| 507 | ), | ||
| 508 | |||
| 509 | TP_fast_assign( | ||
| 510 | __entry->xprt = xprt; | ||
| 511 | __entry->rqst = rqst; | ||
| 512 | ), | ||
| 513 | |||
| 514 | TP_printk("xprt=0x%p addr=%pIScp pid=%d flags=%s", __entry->xprt, | ||
| 515 | (struct sockaddr *)&__entry->xprt->xpt_remote, | ||
| 516 | __entry->rqst ? __entry->rqst->rq_task->pid : 0, | ||
| 517 | show_svc_xprt_flags(__entry->xprt->xpt_flags)) | ||
| 518 | ); | ||
| 519 | |||
| 520 | TRACE_EVENT(svc_xprt_dequeue, | ||
| 521 | TP_PROTO(struct svc_xprt *xprt), | ||
| 522 | |||
| 523 | TP_ARGS(xprt), | ||
| 524 | |||
| 525 | TP_STRUCT__entry( | ||
| 526 | __field(struct svc_xprt *, xprt) | ||
| 527 | __field_struct(struct sockaddr_storage, ss) | ||
| 528 | __field(unsigned long, flags) | ||
| 529 | ), | ||
| 530 | |||
| 531 | TP_fast_assign( | ||
| 532 | __entry->xprt = xprt, | ||
| 533 | xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss)); | ||
| 534 | __entry->flags = xprt ? xprt->xpt_flags : 0; | ||
| 535 | ), | ||
| 536 | |||
| 537 | TP_printk("xprt=0x%p addr=%pIScp flags=%s", __entry->xprt, | ||
| 538 | (struct sockaddr *)&__entry->ss, | ||
| 539 | show_svc_xprt_flags(__entry->flags)) | ||
| 540 | ); | ||
| 541 | |||
| 542 | TRACE_EVENT(svc_wake_up, | ||
| 543 | TP_PROTO(int pid), | ||
| 544 | |||
| 545 | TP_ARGS(pid), | ||
| 546 | |||
| 547 | TP_STRUCT__entry( | ||
| 548 | __field(int, pid) | ||
| 549 | ), | ||
| 550 | |||
| 551 | TP_fast_assign( | ||
| 552 | __entry->pid = pid; | ||
| 553 | ), | ||
| 554 | |||
| 555 | TP_printk("pid=%d", __entry->pid) | ||
| 556 | ); | ||
| 557 | |||
| 558 | TRACE_EVENT(svc_handle_xprt, | ||
| 559 | TP_PROTO(struct svc_xprt *xprt, int len), | ||
| 560 | |||
| 561 | TP_ARGS(xprt, len), | ||
| 562 | |||
| 563 | TP_STRUCT__entry( | ||
| 564 | __field(struct svc_xprt *, xprt) | ||
| 565 | __field(int, len) | ||
| 566 | ), | ||
| 567 | |||
| 568 | TP_fast_assign( | ||
| 569 | __entry->xprt = xprt; | ||
| 570 | __entry->len = len; | ||
| 571 | ), | ||
| 572 | |||
| 573 | TP_printk("xprt=0x%p addr=%pIScp len=%d flags=%s", __entry->xprt, | ||
| 574 | (struct sockaddr *)&__entry->xprt->xpt_remote, __entry->len, | ||
| 575 | show_svc_xprt_flags(__entry->xprt->xpt_flags)) | ||
| 576 | ); | ||
| 469 | #endif /* _TRACE_SUNRPC_H */ | 577 | #endif /* _TRACE_SUNRPC_H */ |
| 470 | 578 | ||
| 471 | #include <trace/define_trace.h> | 579 | #include <trace/define_trace.h> |
diff --git a/mm/madvise.c b/mm/madvise.c index 0938b30da4ab..a271adc93289 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
| @@ -326,7 +326,7 @@ static long madvise_remove(struct vm_area_struct *vma, | |||
| 326 | */ | 326 | */ |
| 327 | get_file(f); | 327 | get_file(f); |
| 328 | up_read(¤t->mm->mmap_sem); | 328 | up_read(¤t->mm->mmap_sem); |
| 329 | error = do_fallocate(f, | 329 | error = vfs_fallocate(f, |
| 330 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, | 330 | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, |
| 331 | offset, end - start); | 331 | offset, end - start); |
| 332 | fput(f); | 332 | fput(f); |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index de856ddf5fed..224a82f24d3c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
| @@ -886,7 +886,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs | |||
| 886 | u32 priv_len, maj_stat; | 886 | u32 priv_len, maj_stat; |
| 887 | int pad, saved_len, remaining_len, offset; | 887 | int pad, saved_len, remaining_len, offset; |
| 888 | 888 | ||
| 889 | rqstp->rq_splice_ok = false; | 889 | clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); |
| 890 | 890 | ||
| 891 | priv_len = svc_getnl(&buf->head[0]); | 891 | priv_len = svc_getnl(&buf->head[0]); |
| 892 | if (rqstp->rq_deferred) { | 892 | if (rqstp->rq_deferred) { |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 066362141133..33fb105d4352 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
| 23 | #include <linux/string_helpers.h> | ||
| 23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 24 | #include <linux/poll.h> | 25 | #include <linux/poll.h> |
| 25 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
| @@ -1067,30 +1068,15 @@ void qword_add(char **bpp, int *lp, char *str) | |||
| 1067 | { | 1068 | { |
| 1068 | char *bp = *bpp; | 1069 | char *bp = *bpp; |
| 1069 | int len = *lp; | 1070 | int len = *lp; |
| 1070 | char c; | 1071 | int ret; |
| 1071 | 1072 | ||
| 1072 | if (len < 0) return; | 1073 | if (len < 0) return; |
| 1073 | 1074 | ||
| 1074 | while ((c=*str++) && len) | 1075 | ret = string_escape_str(str, &bp, len, ESCAPE_OCTAL, "\\ \n\t"); |
| 1075 | switch(c) { | 1076 | if (ret < 0 || ret == len) |
| 1076 | case ' ': | 1077 | len = -1; |
| 1077 | case '\t': | ||
| 1078 | case '\n': | ||
| 1079 | case '\\': | ||
| 1080 | if (len >= 4) { | ||
| 1081 | *bp++ = '\\'; | ||
| 1082 | *bp++ = '0' + ((c & 0300)>>6); | ||
| 1083 | *bp++ = '0' + ((c & 0070)>>3); | ||
| 1084 | *bp++ = '0' + ((c & 0007)>>0); | ||
| 1085 | } | ||
| 1086 | len -= 4; | ||
| 1087 | break; | ||
| 1088 | default: | ||
| 1089 | *bp++ = c; | ||
| 1090 | len--; | ||
| 1091 | } | ||
| 1092 | if (c || len <1) len = -1; | ||
| 1093 | else { | 1078 | else { |
| 1079 | len -= ret; | ||
| 1094 | *bp++ = ' '; | 1080 | *bp++ = ' '; |
| 1095 | len--; | 1081 | len--; |
| 1096 | } | 1082 | } |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 2783fd80c229..91eaef1844c8 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -191,7 +191,7 @@ svc_pool_map_init_percpu(struct svc_pool_map *m) | |||
| 191 | return err; | 191 | return err; |
| 192 | 192 | ||
| 193 | for_each_online_cpu(cpu) { | 193 | for_each_online_cpu(cpu) { |
| 194 | BUG_ON(pidx > maxpools); | 194 | BUG_ON(pidx >= maxpools); |
| 195 | m->to_pool[cpu] = pidx; | 195 | m->to_pool[cpu] = pidx; |
| 196 | m->pool_to[pidx] = cpu; | 196 | m->pool_to[pidx] = cpu; |
| 197 | pidx++; | 197 | pidx++; |
| @@ -476,15 +476,11 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
| 476 | i, serv->sv_name); | 476 | i, serv->sv_name); |
| 477 | 477 | ||
| 478 | pool->sp_id = i; | 478 | pool->sp_id = i; |
| 479 | INIT_LIST_HEAD(&pool->sp_threads); | ||
| 480 | INIT_LIST_HEAD(&pool->sp_sockets); | 479 | INIT_LIST_HEAD(&pool->sp_sockets); |
| 481 | INIT_LIST_HEAD(&pool->sp_all_threads); | 480 | INIT_LIST_HEAD(&pool->sp_all_threads); |
| 482 | spin_lock_init(&pool->sp_lock); | 481 | spin_lock_init(&pool->sp_lock); |
| 483 | } | 482 | } |
| 484 | 483 | ||
| 485 | if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) | ||
| 486 | serv->sv_shutdown = svc_rpcb_cleanup; | ||
| 487 | |||
| 488 | return serv; | 484 | return serv; |
| 489 | } | 485 | } |
| 490 | 486 | ||
| @@ -505,13 +501,15 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
| 505 | unsigned int npools = svc_pool_map_get(); | 501 | unsigned int npools = svc_pool_map_get(); |
| 506 | 502 | ||
| 507 | serv = __svc_create(prog, bufsize, npools, shutdown); | 503 | serv = __svc_create(prog, bufsize, npools, shutdown); |
| 504 | if (!serv) | ||
| 505 | goto out_err; | ||
| 508 | 506 | ||
| 509 | if (serv != NULL) { | 507 | serv->sv_function = func; |
| 510 | serv->sv_function = func; | 508 | serv->sv_module = mod; |
| 511 | serv->sv_module = mod; | ||
| 512 | } | ||
| 513 | |||
| 514 | return serv; | 509 | return serv; |
| 510 | out_err: | ||
| 511 | svc_pool_map_put(); | ||
| 512 | return NULL; | ||
| 515 | } | 513 | } |
| 516 | EXPORT_SYMBOL_GPL(svc_create_pooled); | 514 | EXPORT_SYMBOL_GPL(svc_create_pooled); |
| 517 | 515 | ||
| @@ -615,12 +613,14 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) | |||
| 615 | goto out_enomem; | 613 | goto out_enomem; |
| 616 | 614 | ||
| 617 | serv->sv_nrthreads++; | 615 | serv->sv_nrthreads++; |
| 616 | __set_bit(RQ_BUSY, &rqstp->rq_flags); | ||
| 617 | spin_lock_init(&rqstp->rq_lock); | ||
| 618 | rqstp->rq_server = serv; | ||
| 619 | rqstp->rq_pool = pool; | ||
| 618 | spin_lock_bh(&pool->sp_lock); | 620 | spin_lock_bh(&pool->sp_lock); |
| 619 | pool->sp_nrthreads++; | 621 | pool->sp_nrthreads++; |
| 620 | list_add(&rqstp->rq_all, &pool->sp_all_threads); | 622 | list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads); |
| 621 | spin_unlock_bh(&pool->sp_lock); | 623 | spin_unlock_bh(&pool->sp_lock); |
| 622 | rqstp->rq_server = serv; | ||
| 623 | rqstp->rq_pool = pool; | ||
| 624 | 624 | ||
| 625 | rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); | 625 | rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); |
| 626 | if (!rqstp->rq_argp) | 626 | if (!rqstp->rq_argp) |
| @@ -685,7 +685,8 @@ found_pool: | |||
| 685 | * so we don't try to kill it again. | 685 | * so we don't try to kill it again. |
| 686 | */ | 686 | */ |
| 687 | rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all); | 687 | rqstp = list_entry(pool->sp_all_threads.next, struct svc_rqst, rq_all); |
| 688 | list_del_init(&rqstp->rq_all); | 688 | set_bit(RQ_VICTIM, &rqstp->rq_flags); |
| 689 | list_del_rcu(&rqstp->rq_all); | ||
| 689 | task = rqstp->rq_task; | 690 | task = rqstp->rq_task; |
| 690 | } | 691 | } |
| 691 | spin_unlock_bh(&pool->sp_lock); | 692 | spin_unlock_bh(&pool->sp_lock); |
| @@ -783,10 +784,11 @@ svc_exit_thread(struct svc_rqst *rqstp) | |||
| 783 | 784 | ||
| 784 | spin_lock_bh(&pool->sp_lock); | 785 | spin_lock_bh(&pool->sp_lock); |
| 785 | pool->sp_nrthreads--; | 786 | pool->sp_nrthreads--; |
| 786 | list_del(&rqstp->rq_all); | 787 | if (!test_and_set_bit(RQ_VICTIM, &rqstp->rq_flags)) |
| 788 | list_del_rcu(&rqstp->rq_all); | ||
| 787 | spin_unlock_bh(&pool->sp_lock); | 789 | spin_unlock_bh(&pool->sp_lock); |
| 788 | 790 | ||
| 789 | kfree(rqstp); | 791 | kfree_rcu(rqstp, rq_rcu_head); |
| 790 | 792 | ||
| 791 | /* Release the server */ | 793 | /* Release the server */ |
| 792 | if (serv) | 794 | if (serv) |
| @@ -1086,10 +1088,10 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) | |||
| 1086 | goto err_short_len; | 1088 | goto err_short_len; |
| 1087 | 1089 | ||
| 1088 | /* Will be turned off only in gss privacy case: */ | 1090 | /* Will be turned off only in gss privacy case: */ |
| 1089 | rqstp->rq_splice_ok = true; | 1091 | set_bit(RQ_SPLICE_OK, &rqstp->rq_flags); |
| 1090 | /* Will be turned off only when NFSv4 Sessions are used */ | 1092 | /* Will be turned off only when NFSv4 Sessions are used */ |
| 1091 | rqstp->rq_usedeferral = true; | 1093 | set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); |
| 1092 | rqstp->rq_dropme = false; | 1094 | clear_bit(RQ_DROPME, &rqstp->rq_flags); |
| 1093 | 1095 | ||
| 1094 | /* Setup reply header */ | 1096 | /* Setup reply header */ |
| 1095 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); | 1097 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); |
| @@ -1189,7 +1191,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) | |||
| 1189 | *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); | 1191 | *statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
| 1190 | 1192 | ||
| 1191 | /* Encode reply */ | 1193 | /* Encode reply */ |
| 1192 | if (rqstp->rq_dropme) { | 1194 | if (test_bit(RQ_DROPME, &rqstp->rq_flags)) { |
| 1193 | if (procp->pc_release) | 1195 | if (procp->pc_release) |
| 1194 | procp->pc_release(rqstp, NULL, rqstp->rq_resp); | 1196 | procp->pc_release(rqstp, NULL, rqstp->rq_resp); |
| 1195 | goto dropit; | 1197 | goto dropit; |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index bbb3b044b877..c69358b3cf7f 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
| @@ -220,9 +220,11 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
| 220 | */ | 220 | */ |
| 221 | static void svc_xprt_received(struct svc_xprt *xprt) | 221 | static void svc_xprt_received(struct svc_xprt *xprt) |
| 222 | { | 222 | { |
| 223 | WARN_ON_ONCE(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | 223 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) { |
| 224 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) | 224 | WARN_ONCE(1, "xprt=0x%p already busy!", xprt); |
| 225 | return; | 225 | return; |
| 226 | } | ||
| 227 | |||
| 226 | /* As soon as we clear busy, the xprt could be closed and | 228 | /* As soon as we clear busy, the xprt could be closed and |
| 227 | * 'put', so we need a reference to call svc_xprt_do_enqueue with: | 229 | * 'put', so we need a reference to call svc_xprt_do_enqueue with: |
| 228 | */ | 230 | */ |
| @@ -310,25 +312,6 @@ char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len) | |||
| 310 | } | 312 | } |
| 311 | EXPORT_SYMBOL_GPL(svc_print_addr); | 313 | EXPORT_SYMBOL_GPL(svc_print_addr); |
| 312 | 314 | ||
| 313 | /* | ||
| 314 | * Queue up an idle server thread. Must have pool->sp_lock held. | ||
| 315 | * Note: this is really a stack rather than a queue, so that we only | ||
| 316 | * use as many different threads as we need, and the rest don't pollute | ||
| 317 | * the cache. | ||
| 318 | */ | ||
| 319 | static void svc_thread_enqueue(struct svc_pool *pool, struct svc_rqst *rqstp) | ||
| 320 | { | ||
| 321 | list_add(&rqstp->rq_list, &pool->sp_threads); | ||
| 322 | } | ||
| 323 | |||
| 324 | /* | ||
| 325 | * Dequeue an nfsd thread. Must have pool->sp_lock held. | ||
| 326 | */ | ||
| 327 | static void svc_thread_dequeue(struct svc_pool *pool, struct svc_rqst *rqstp) | ||
| 328 | { | ||
| 329 | list_del(&rqstp->rq_list); | ||
| 330 | } | ||
| 331 | |||
| 332 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | 315 | static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) |
| 333 | { | 316 | { |
| 334 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) | 317 | if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE))) |
| @@ -341,11 +324,12 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | |||
| 341 | static void svc_xprt_do_enqueue(struct svc_xprt *xprt) | 324 | static void svc_xprt_do_enqueue(struct svc_xprt *xprt) |
| 342 | { | 325 | { |
| 343 | struct svc_pool *pool; | 326 | struct svc_pool *pool; |
| 344 | struct svc_rqst *rqstp; | 327 | struct svc_rqst *rqstp = NULL; |
| 345 | int cpu; | 328 | int cpu; |
| 329 | bool queued = false; | ||
| 346 | 330 | ||
| 347 | if (!svc_xprt_has_something_to_do(xprt)) | 331 | if (!svc_xprt_has_something_to_do(xprt)) |
| 348 | return; | 332 | goto out; |
| 349 | 333 | ||
| 350 | /* Mark transport as busy. It will remain in this state until | 334 | /* Mark transport as busy. It will remain in this state until |
| 351 | * the provider calls svc_xprt_received. We update XPT_BUSY | 335 | * the provider calls svc_xprt_received. We update XPT_BUSY |
| @@ -355,43 +339,69 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt) | |||
| 355 | if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) { | 339 | if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags)) { |
| 356 | /* Don't enqueue transport while already enqueued */ | 340 | /* Don't enqueue transport while already enqueued */ |
| 357 | dprintk("svc: transport %p busy, not enqueued\n", xprt); | 341 | dprintk("svc: transport %p busy, not enqueued\n", xprt); |
| 358 | return; | 342 | goto out; |
| 359 | } | 343 | } |
| 360 | 344 | ||
| 361 | cpu = get_cpu(); | 345 | cpu = get_cpu(); |
| 362 | pool = svc_pool_for_cpu(xprt->xpt_server, cpu); | 346 | pool = svc_pool_for_cpu(xprt->xpt_server, cpu); |
| 363 | spin_lock_bh(&pool->sp_lock); | ||
| 364 | 347 | ||
| 365 | pool->sp_stats.packets++; | 348 | atomic_long_inc(&pool->sp_stats.packets); |
| 366 | 349 | ||
| 367 | if (!list_empty(&pool->sp_threads)) { | 350 | redo_search: |
| 368 | rqstp = list_entry(pool->sp_threads.next, | 351 | /* find a thread for this xprt */ |
| 369 | struct svc_rqst, | 352 | rcu_read_lock(); |
| 370 | rq_list); | 353 | list_for_each_entry_rcu(rqstp, &pool->sp_all_threads, rq_all) { |
| 371 | dprintk("svc: transport %p served by daemon %p\n", | 354 | /* Do a lockless check first */ |
| 372 | xprt, rqstp); | 355 | if (test_bit(RQ_BUSY, &rqstp->rq_flags)) |
| 373 | svc_thread_dequeue(pool, rqstp); | 356 | continue; |
| 374 | if (rqstp->rq_xprt) | 357 | |
| 375 | printk(KERN_ERR | 358 | /* |
| 376 | "svc_xprt_enqueue: server %p, rq_xprt=%p!\n", | 359 | * Once the xprt has been queued, it can only be dequeued by |
| 377 | rqstp, rqstp->rq_xprt); | 360 | * the task that intends to service it. All we can do at that |
| 378 | /* Note the order of the following 3 lines: | 361 | * point is to try to wake this thread back up so that it can |
| 379 | * We want to assign xprt to rqstp->rq_xprt only _after_ | 362 | * do so. |
| 380 | * we've woken up the process, so that we don't race with | ||
| 381 | * the lockless check in svc_get_next_xprt(). | ||
| 382 | */ | 363 | */ |
| 383 | svc_xprt_get(xprt); | 364 | if (!queued) { |
| 365 | spin_lock_bh(&rqstp->rq_lock); | ||
| 366 | if (test_and_set_bit(RQ_BUSY, &rqstp->rq_flags)) { | ||
| 367 | /* already busy, move on... */ | ||
| 368 | spin_unlock_bh(&rqstp->rq_lock); | ||
| 369 | continue; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* this one will do */ | ||
| 373 | rqstp->rq_xprt = xprt; | ||
| 374 | svc_xprt_get(xprt); | ||
| 375 | spin_unlock_bh(&rqstp->rq_lock); | ||
| 376 | } | ||
| 377 | rcu_read_unlock(); | ||
| 378 | |||
| 379 | atomic_long_inc(&pool->sp_stats.threads_woken); | ||
| 384 | wake_up_process(rqstp->rq_task); | 380 | wake_up_process(rqstp->rq_task); |
| 385 | rqstp->rq_xprt = xprt; | 381 | put_cpu(); |
| 386 | pool->sp_stats.threads_woken++; | 382 | goto out; |
| 387 | } else { | 383 | } |
| 384 | rcu_read_unlock(); | ||
| 385 | |||
| 386 | /* | ||
| 387 | * We didn't find an idle thread to use, so we need to queue the xprt. | ||
| 388 | * Do so and then search again. If we find one, we can't hook this one | ||
| 389 | * up to it directly but we can wake the thread up in the hopes that it | ||
| 390 | * will pick it up once it searches for a xprt to service. | ||
| 391 | */ | ||
| 392 | if (!queued) { | ||
| 393 | queued = true; | ||
| 388 | dprintk("svc: transport %p put into queue\n", xprt); | 394 | dprintk("svc: transport %p put into queue\n", xprt); |
| 395 | spin_lock_bh(&pool->sp_lock); | ||
| 389 | list_add_tail(&xprt->xpt_ready, &pool->sp_sockets); | 396 | list_add_tail(&xprt->xpt_ready, &pool->sp_sockets); |
| 390 | pool->sp_stats.sockets_queued++; | 397 | pool->sp_stats.sockets_queued++; |
| 398 | spin_unlock_bh(&pool->sp_lock); | ||
| 399 | goto redo_search; | ||
| 391 | } | 400 | } |
| 392 | 401 | rqstp = NULL; | |
| 393 | spin_unlock_bh(&pool->sp_lock); | ||
| 394 | put_cpu(); | 402 | put_cpu(); |
| 403 | out: | ||
| 404 | trace_svc_xprt_do_enqueue(xprt, rqstp); | ||
| 395 | } | 405 | } |
| 396 | 406 | ||
| 397 | /* | 407 | /* |
| @@ -408,22 +418,28 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
| 408 | EXPORT_SYMBOL_GPL(svc_xprt_enqueue); | 418 | EXPORT_SYMBOL_GPL(svc_xprt_enqueue); |
| 409 | 419 | ||
| 410 | /* | 420 | /* |
| 411 | * Dequeue the first transport. Must be called with the pool->sp_lock held. | 421 | * Dequeue the first transport, if there is one. |
| 412 | */ | 422 | */ |
| 413 | static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) | 423 | static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) |
| 414 | { | 424 | { |
| 415 | struct svc_xprt *xprt; | 425 | struct svc_xprt *xprt = NULL; |
| 416 | 426 | ||
| 417 | if (list_empty(&pool->sp_sockets)) | 427 | if (list_empty(&pool->sp_sockets)) |
| 418 | return NULL; | 428 | goto out; |
| 419 | |||
| 420 | xprt = list_entry(pool->sp_sockets.next, | ||
| 421 | struct svc_xprt, xpt_ready); | ||
| 422 | list_del_init(&xprt->xpt_ready); | ||
| 423 | 429 | ||
| 424 | dprintk("svc: transport %p dequeued, inuse=%d\n", | 430 | spin_lock_bh(&pool->sp_lock); |
| 425 | xprt, atomic_read(&xprt->xpt_ref.refcount)); | 431 | if (likely(!list_empty(&pool->sp_sockets))) { |
| 432 | xprt = list_first_entry(&pool->sp_sockets, | ||
| 433 | struct svc_xprt, xpt_ready); | ||
| 434 | list_del_init(&xprt->xpt_ready); | ||
| 435 | svc_xprt_get(xprt); | ||
| 426 | 436 | ||
| 437 | dprintk("svc: transport %p dequeued, inuse=%d\n", | ||
| 438 | xprt, atomic_read(&xprt->xpt_ref.refcount)); | ||
| 439 | } | ||
| 440 | spin_unlock_bh(&pool->sp_lock); | ||
| 441 | out: | ||
| 442 | trace_svc_xprt_dequeue(xprt); | ||
| 427 | return xprt; | 443 | return xprt; |
| 428 | } | 444 | } |
| 429 | 445 | ||
| @@ -484,34 +500,36 @@ static void svc_xprt_release(struct svc_rqst *rqstp) | |||
| 484 | } | 500 | } |
| 485 | 501 | ||
| 486 | /* | 502 | /* |
| 487 | * External function to wake up a server waiting for data | 503 | * Some svc_serv's will have occasional work to do, even when a xprt is not |
| 488 | * This really only makes sense for services like lockd | 504 | * waiting to be serviced. This function is there to "kick" a task in one of |
| 489 | * which have exactly one thread anyway. | 505 | * those services so that it can wake up and do that work. Note that we only |
| 506 | * bother with pool 0 as we don't need to wake up more than one thread for | ||
| 507 | * this purpose. | ||
| 490 | */ | 508 | */ |
| 491 | void svc_wake_up(struct svc_serv *serv) | 509 | void svc_wake_up(struct svc_serv *serv) |
| 492 | { | 510 | { |
| 493 | struct svc_rqst *rqstp; | 511 | struct svc_rqst *rqstp; |
| 494 | unsigned int i; | ||
| 495 | struct svc_pool *pool; | 512 | struct svc_pool *pool; |
| 496 | 513 | ||
| 497 | for (i = 0; i < serv->sv_nrpools; i++) { | 514 | pool = &serv->sv_pools[0]; |
| 498 | pool = &serv->sv_pools[i]; | ||
| 499 | 515 | ||
| 500 | spin_lock_bh(&pool->sp_lock); | 516 | rcu_read_lock(); |
| 501 | if (!list_empty(&pool->sp_threads)) { | 517 | list_for_each_entry_rcu(rqstp, &pool->sp_all_threads, rq_all) { |
| 502 | rqstp = list_entry(pool->sp_threads.next, | 518 | /* skip any that aren't queued */ |
| 503 | struct svc_rqst, | 519 | if (test_bit(RQ_BUSY, &rqstp->rq_flags)) |
| 504 | rq_list); | 520 | continue; |
| 505 | dprintk("svc: daemon %p woken up.\n", rqstp); | 521 | rcu_read_unlock(); |
| 506 | /* | 522 | dprintk("svc: daemon %p woken up.\n", rqstp); |
| 507 | svc_thread_dequeue(pool, rqstp); | 523 | wake_up_process(rqstp->rq_task); |
| 508 | rqstp->rq_xprt = NULL; | 524 | trace_svc_wake_up(rqstp->rq_task->pid); |
| 509 | */ | 525 | return; |
| 510 | wake_up_process(rqstp->rq_task); | ||
| 511 | } else | ||
| 512 | pool->sp_task_pending = 1; | ||
| 513 | spin_unlock_bh(&pool->sp_lock); | ||
| 514 | } | 526 | } |
| 527 | rcu_read_unlock(); | ||
| 528 | |||
| 529 | /* No free entries available */ | ||
| 530 | set_bit(SP_TASK_PENDING, &pool->sp_flags); | ||
| 531 | smp_wmb(); | ||
| 532 | trace_svc_wake_up(0); | ||
| 515 | } | 533 | } |
| 516 | EXPORT_SYMBOL_GPL(svc_wake_up); | 534 | EXPORT_SYMBOL_GPL(svc_wake_up); |
| 517 | 535 | ||
| @@ -622,75 +640,86 @@ static int svc_alloc_arg(struct svc_rqst *rqstp) | |||
| 622 | return 0; | 640 | return 0; |
| 623 | } | 641 | } |
| 624 | 642 | ||
| 643 | static bool | ||
| 644 | rqst_should_sleep(struct svc_rqst *rqstp) | ||
| 645 | { | ||
| 646 | struct svc_pool *pool = rqstp->rq_pool; | ||
| 647 | |||
| 648 | /* did someone call svc_wake_up? */ | ||
| 649 | if (test_and_clear_bit(SP_TASK_PENDING, &pool->sp_flags)) | ||
| 650 | return false; | ||
| 651 | |||
| 652 | /* was a socket queued? */ | ||
| 653 | if (!list_empty(&pool->sp_sockets)) | ||
| 654 | return false; | ||
| 655 | |||
| 656 | /* are we shutting down? */ | ||
| 657 | if (signalled() || kthread_should_stop()) | ||
| 658 | return false; | ||
| 659 | |||
| 660 | /* are we freezing? */ | ||
| 661 | if (freezing(current)) | ||
| 662 | return false; | ||
| 663 | |||
| 664 | return true; | ||
| 665 | } | ||
| 666 | |||
| 625 | static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | 667 | static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) |
| 626 | { | 668 | { |
| 627 | struct svc_xprt *xprt; | 669 | struct svc_xprt *xprt; |
| 628 | struct svc_pool *pool = rqstp->rq_pool; | 670 | struct svc_pool *pool = rqstp->rq_pool; |
| 629 | long time_left = 0; | 671 | long time_left = 0; |
| 630 | 672 | ||
| 673 | /* rq_xprt should be clear on entry */ | ||
| 674 | WARN_ON_ONCE(rqstp->rq_xprt); | ||
| 675 | |||
| 631 | /* Normally we will wait up to 5 seconds for any required | 676 | /* Normally we will wait up to 5 seconds for any required |
| 632 | * cache information to be provided. | 677 | * cache information to be provided. |
| 633 | */ | 678 | */ |
| 634 | rqstp->rq_chandle.thread_wait = 5*HZ; | 679 | rqstp->rq_chandle.thread_wait = 5*HZ; |
| 635 | 680 | ||
| 636 | spin_lock_bh(&pool->sp_lock); | ||
| 637 | xprt = svc_xprt_dequeue(pool); | 681 | xprt = svc_xprt_dequeue(pool); |
| 638 | if (xprt) { | 682 | if (xprt) { |
| 639 | rqstp->rq_xprt = xprt; | 683 | rqstp->rq_xprt = xprt; |
| 640 | svc_xprt_get(xprt); | ||
| 641 | 684 | ||
| 642 | /* As there is a shortage of threads and this request | 685 | /* As there is a shortage of threads and this request |
| 643 | * had to be queued, don't allow the thread to wait so | 686 | * had to be queued, don't allow the thread to wait so |
| 644 | * long for cache updates. | 687 | * long for cache updates. |
| 645 | */ | 688 | */ |
| 646 | rqstp->rq_chandle.thread_wait = 1*HZ; | 689 | rqstp->rq_chandle.thread_wait = 1*HZ; |
| 647 | pool->sp_task_pending = 0; | 690 | clear_bit(SP_TASK_PENDING, &pool->sp_flags); |
| 648 | } else { | 691 | return xprt; |
| 649 | if (pool->sp_task_pending) { | 692 | } |
| 650 | pool->sp_task_pending = 0; | ||
| 651 | xprt = ERR_PTR(-EAGAIN); | ||
| 652 | goto out; | ||
| 653 | } | ||
| 654 | /* | ||
| 655 | * We have to be able to interrupt this wait | ||
| 656 | * to bring down the daemons ... | ||
| 657 | */ | ||
| 658 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 659 | 693 | ||
| 660 | /* No data pending. Go to sleep */ | 694 | /* |
| 661 | svc_thread_enqueue(pool, rqstp); | 695 | * We have to be able to interrupt this wait |
| 662 | spin_unlock_bh(&pool->sp_lock); | 696 | * to bring down the daemons ... |
| 697 | */ | ||
| 698 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 699 | clear_bit(RQ_BUSY, &rqstp->rq_flags); | ||
| 700 | smp_mb(); | ||
| 663 | 701 | ||
| 664 | if (!(signalled() || kthread_should_stop())) { | 702 | if (likely(rqst_should_sleep(rqstp))) |
| 665 | time_left = schedule_timeout(timeout); | 703 | time_left = schedule_timeout(timeout); |
| 666 | __set_current_state(TASK_RUNNING); | 704 | else |
| 705 | __set_current_state(TASK_RUNNING); | ||
| 667 | 706 | ||
| 668 | try_to_freeze(); | 707 | try_to_freeze(); |
| 669 | 708 | ||
| 670 | xprt = rqstp->rq_xprt; | 709 | spin_lock_bh(&rqstp->rq_lock); |
| 671 | if (xprt != NULL) | 710 | set_bit(RQ_BUSY, &rqstp->rq_flags); |
| 672 | return xprt; | 711 | spin_unlock_bh(&rqstp->rq_lock); |
| 673 | } else | ||
| 674 | __set_current_state(TASK_RUNNING); | ||
| 675 | 712 | ||
| 676 | spin_lock_bh(&pool->sp_lock); | 713 | xprt = rqstp->rq_xprt; |
| 677 | if (!time_left) | 714 | if (xprt != NULL) |
| 678 | pool->sp_stats.threads_timedout++; | 715 | return xprt; |
| 679 | 716 | ||
| 680 | xprt = rqstp->rq_xprt; | 717 | if (!time_left) |
| 681 | if (!xprt) { | 718 | atomic_long_inc(&pool->sp_stats.threads_timedout); |
| 682 | svc_thread_dequeue(pool, rqstp); | 719 | |
| 683 | spin_unlock_bh(&pool->sp_lock); | 720 | if (signalled() || kthread_should_stop()) |
| 684 | dprintk("svc: server %p, no data yet\n", rqstp); | 721 | return ERR_PTR(-EINTR); |
| 685 | if (signalled() || kthread_should_stop()) | 722 | return ERR_PTR(-EAGAIN); |
| 686 | return ERR_PTR(-EINTR); | ||
| 687 | else | ||
| 688 | return ERR_PTR(-EAGAIN); | ||
| 689 | } | ||
| 690 | } | ||
| 691 | out: | ||
| 692 | spin_unlock_bh(&pool->sp_lock); | ||
| 693 | return xprt; | ||
| 694 | } | 723 | } |
| 695 | 724 | ||
| 696 | static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) | 725 | static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) |
| @@ -719,7 +748,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
| 719 | dprintk("svc_recv: found XPT_CLOSE\n"); | 748 | dprintk("svc_recv: found XPT_CLOSE\n"); |
| 720 | svc_delete_xprt(xprt); | 749 | svc_delete_xprt(xprt); |
| 721 | /* Leave XPT_BUSY set on the dead xprt: */ | 750 | /* Leave XPT_BUSY set on the dead xprt: */ |
| 722 | return 0; | 751 | goto out; |
| 723 | } | 752 | } |
| 724 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | 753 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { |
| 725 | struct svc_xprt *newxpt; | 754 | struct svc_xprt *newxpt; |
| @@ -750,6 +779,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
| 750 | } | 779 | } |
| 751 | /* clear XPT_BUSY: */ | 780 | /* clear XPT_BUSY: */ |
| 752 | svc_xprt_received(xprt); | 781 | svc_xprt_received(xprt); |
| 782 | out: | ||
| 783 | trace_svc_handle_xprt(xprt, len); | ||
| 753 | return len; | 784 | return len; |
| 754 | } | 785 | } |
| 755 | 786 | ||
| @@ -797,7 +828,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
| 797 | 828 | ||
| 798 | clear_bit(XPT_OLD, &xprt->xpt_flags); | 829 | clear_bit(XPT_OLD, &xprt->xpt_flags); |
| 799 | 830 | ||
| 800 | rqstp->rq_secure = xprt->xpt_ops->xpo_secure_port(rqstp); | 831 | if (xprt->xpt_ops->xpo_secure_port(rqstp)) |
| 832 | set_bit(RQ_SECURE, &rqstp->rq_flags); | ||
| 833 | else | ||
| 834 | clear_bit(RQ_SECURE, &rqstp->rq_flags); | ||
| 801 | rqstp->rq_chandle.defer = svc_defer; | 835 | rqstp->rq_chandle.defer = svc_defer; |
| 802 | rqstp->rq_xid = svc_getu32(&rqstp->rq_arg.head[0]); | 836 | rqstp->rq_xid = svc_getu32(&rqstp->rq_arg.head[0]); |
| 803 | 837 | ||
| @@ -895,7 +929,6 @@ static void svc_age_temp_xprts(unsigned long closure) | |||
| 895 | continue; | 929 | continue; |
| 896 | list_del_init(le); | 930 | list_del_init(le); |
| 897 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 931 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
| 898 | set_bit(XPT_DETACHED, &xprt->xpt_flags); | ||
| 899 | dprintk("queuing xprt %p for closing\n", xprt); | 932 | dprintk("queuing xprt %p for closing\n", xprt); |
| 900 | 933 | ||
| 901 | /* a thread will dequeue and close it soon */ | 934 | /* a thread will dequeue and close it soon */ |
| @@ -935,8 +968,7 @@ static void svc_delete_xprt(struct svc_xprt *xprt) | |||
| 935 | xprt->xpt_ops->xpo_detach(xprt); | 968 | xprt->xpt_ops->xpo_detach(xprt); |
| 936 | 969 | ||
| 937 | spin_lock_bh(&serv->sv_lock); | 970 | spin_lock_bh(&serv->sv_lock); |
| 938 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | 971 | list_del_init(&xprt->xpt_list); |
| 939 | list_del_init(&xprt->xpt_list); | ||
| 940 | WARN_ON_ONCE(!list_empty(&xprt->xpt_ready)); | 972 | WARN_ON_ONCE(!list_empty(&xprt->xpt_ready)); |
| 941 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 973 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
| 942 | serv->sv_tmpcnt--; | 974 | serv->sv_tmpcnt--; |
| @@ -1080,7 +1112,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req) | |||
| 1080 | struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle); | 1112 | struct svc_rqst *rqstp = container_of(req, struct svc_rqst, rq_chandle); |
| 1081 | struct svc_deferred_req *dr; | 1113 | struct svc_deferred_req *dr; |
| 1082 | 1114 | ||
| 1083 | if (rqstp->rq_arg.page_len || !rqstp->rq_usedeferral) | 1115 | if (rqstp->rq_arg.page_len || !test_bit(RQ_USEDEFERRAL, &rqstp->rq_flags)) |
| 1084 | return NULL; /* if more than a page, give up FIXME */ | 1116 | return NULL; /* if more than a page, give up FIXME */ |
| 1085 | if (rqstp->rq_deferred) { | 1117 | if (rqstp->rq_deferred) { |
| 1086 | dr = rqstp->rq_deferred; | 1118 | dr = rqstp->rq_deferred; |
| @@ -1109,7 +1141,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req) | |||
| 1109 | } | 1141 | } |
| 1110 | svc_xprt_get(rqstp->rq_xprt); | 1142 | svc_xprt_get(rqstp->rq_xprt); |
| 1111 | dr->xprt = rqstp->rq_xprt; | 1143 | dr->xprt = rqstp->rq_xprt; |
| 1112 | rqstp->rq_dropme = true; | 1144 | set_bit(RQ_DROPME, &rqstp->rq_flags); |
| 1113 | 1145 | ||
| 1114 | dr->handle.revisit = svc_revisit; | 1146 | dr->handle.revisit = svc_revisit; |
| 1115 | return &dr->handle; | 1147 | return &dr->handle; |
| @@ -1311,10 +1343,10 @@ static int svc_pool_stats_show(struct seq_file *m, void *p) | |||
| 1311 | 1343 | ||
| 1312 | seq_printf(m, "%u %lu %lu %lu %lu\n", | 1344 | seq_printf(m, "%u %lu %lu %lu %lu\n", |
| 1313 | pool->sp_id, | 1345 | pool->sp_id, |
| 1314 | pool->sp_stats.packets, | 1346 | (unsigned long)atomic_long_read(&pool->sp_stats.packets), |
| 1315 | pool->sp_stats.sockets_queued, | 1347 | pool->sp_stats.sockets_queued, |
| 1316 | pool->sp_stats.threads_woken, | 1348 | (unsigned long)atomic_long_read(&pool->sp_stats.threads_woken), |
| 1317 | pool->sp_stats.threads_timedout); | 1349 | (unsigned long)atomic_long_read(&pool->sp_stats.threads_timedout)); |
| 1318 | 1350 | ||
| 1319 | return 0; | 1351 | return 0; |
| 1320 | } | 1352 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f9c052d508f0..cc331b6cf573 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -1145,7 +1145,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
| 1145 | 1145 | ||
| 1146 | rqstp->rq_xprt_ctxt = NULL; | 1146 | rqstp->rq_xprt_ctxt = NULL; |
| 1147 | rqstp->rq_prot = IPPROTO_TCP; | 1147 | rqstp->rq_prot = IPPROTO_TCP; |
| 1148 | rqstp->rq_local = !!test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags); | 1148 | if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags)) |
| 1149 | set_bit(RQ_LOCAL, &rqstp->rq_flags); | ||
| 1150 | else | ||
| 1151 | clear_bit(RQ_LOCAL, &rqstp->rq_flags); | ||
| 1149 | 1152 | ||
| 1150 | p = (__be32 *)rqstp->rq_arg.head[0].iov_base; | 1153 | p = (__be32 *)rqstp->rq_arg.head[0].iov_base; |
| 1151 | calldir = p[1]; | 1154 | calldir = p[1]; |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 290af97bf6f9..1cb61242e55e 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
| @@ -617,9 +617,10 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
| 617 | fraglen = min_t(int, buf->len - len, tail->iov_len); | 617 | fraglen = min_t(int, buf->len - len, tail->iov_len); |
| 618 | tail->iov_len -= fraglen; | 618 | tail->iov_len -= fraglen; |
| 619 | buf->len -= fraglen; | 619 | buf->len -= fraglen; |
| 620 | if (tail->iov_len && buf->len == len) { | 620 | if (tail->iov_len) { |
| 621 | xdr->p = tail->iov_base + tail->iov_len; | 621 | xdr->p = tail->iov_base + tail->iov_len; |
| 622 | /* xdr->end, xdr->iov should be set already */ | 622 | WARN_ON_ONCE(!xdr->end); |
| 623 | WARN_ON_ONCE(!xdr->iov); | ||
| 623 | return; | 624 | return; |
| 624 | } | 625 | } |
| 625 | WARN_ON_ONCE(fraglen); | 626 | WARN_ON_ONCE(fraglen); |
| @@ -631,11 +632,11 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
| 631 | old = new + fraglen; | 632 | old = new + fraglen; |
| 632 | xdr->page_ptr -= (old >> PAGE_SHIFT) - (new >> PAGE_SHIFT); | 633 | xdr->page_ptr -= (old >> PAGE_SHIFT) - (new >> PAGE_SHIFT); |
| 633 | 634 | ||
| 634 | if (buf->page_len && buf->len == len) { | 635 | if (buf->page_len) { |
| 635 | xdr->p = page_address(*xdr->page_ptr); | 636 | xdr->p = page_address(*xdr->page_ptr); |
| 636 | xdr->end = (void *)xdr->p + PAGE_SIZE; | 637 | xdr->end = (void *)xdr->p + PAGE_SIZE; |
| 637 | xdr->p = (void *)xdr->p + (new % PAGE_SIZE); | 638 | xdr->p = (void *)xdr->p + (new % PAGE_SIZE); |
| 638 | /* xdr->iov should already be NULL */ | 639 | WARN_ON_ONCE(xdr->iov); |
| 639 | return; | 640 | return; |
| 640 | } | 641 | } |
| 641 | if (fraglen) { | 642 | if (fraglen) { |
