aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-16 18:25:31 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-16 18:25:31 -0500
commit0b233b7c79d2ba92c7fb5d60d4116693f1b3b0fe (patch)
tree440a6093bacfadf46782592fff22c4a2b2b51443 /fs/nfsd
parent6f51ee709e4c6b56f2c2a071da2d056a109b9d26 (diff)
parentbf7491f1be5e125eece2ec67e0f79d513caa6c7e (diff)
Merge branch 'for-3.19' of git://linux-nfs.org/~bfields/linux
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 ...
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c57
-rw-r--r--fs/nfsd/nfs4state.c68
-rw-r--r--fs/nfsd/nfs4xdr.c34
-rw-r--r--fs/nfsd/nfscache.c4
-rw-r--r--fs/nfsd/nfsctl.c6
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfssvc.c2
-rw-r--r--fs/nfsd/state.h19
-rw-r--r--fs/nfsd/vfs.c37
-rw-r--r--fs/nfsd/vfs.h2
-rw-r--r--fs/nfsd/xdr4.h9
11 files changed, 180 insertions, 60 deletions
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
1016static __be32 1017static __be32
1018nfsd4_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
1040static __be32
1041nfsd4_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
1047static __be32
1048nfsd4_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
1055static __be32
1017nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1056nfsd4_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);
1448out: 1487out:
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
278static void nfsd4_free_file(struct nfs4_file *f) 278static 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
283static inline void 285static 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
1714static long long 1717static int
1715compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2) 1718compare_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
1725static int same_name(const char *n1, const char *n2) 1727static 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)
1907static struct nfs4_client * 1909static struct nfs4_client *
1908find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) 1910find_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 */
3060static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh) 3062static 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
3079void 3080void
@@ -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 */
3296static struct nfs4_file * 3297static struct nfs4_file *
3297find_file_locked(struct knfsd_fh *fh) 3298find_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 *
3314find_file(struct knfsd_fh *fh) 3312find_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 *
3325find_or_add_file(struct nfs4_file *new, struct knfsd_fh *fh) 3324find_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
1516static __be32 1516static __be32
1517nfsd4_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
1533static __be32
1517nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) 1534nfsd4_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 */
471struct nfs4_file { 475struct 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
881nfsd_vfs_read(struct svc_rqst *rqstp, struct file *file, 902nfsd_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
976out_nfserr: 1001out_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
431struct nfsd4_fallocate {
432 /* request */
433 stateid_t falloc_stateid;
434 loff_t falloc_offset;
435 u64 falloc_length;
436};
437
431struct nfsd4_seek { 438struct 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;