aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-31 18:41:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-31 18:41:02 -0500
commit0fd08c5545a806c960a6597fae4a2e656eb7ead9 (patch)
tree027dfcc65f600afe6a4b19ab72c472fe3f0f24fa /fs
parent7921127e297ea203b794c4a1c3ef3eb0ee52acbf (diff)
parentd1205f87bbb8040c1408bbd9e0a720310b2b0b9b (diff)
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: NFS: NFSv4 readdir loses entries NFS: Micro-optimize nfs4_decode_dirent() NFS: Fix an NFS client lockdep issue NFS construct consistent co_ownerid for v4.1 NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount NFS improve pnfs_put_deviceid_cache debug print NFS fix cb_sequence error processing NFS do not find client in NFSv4 pg_authenticate NLM: Fix "kernel BUG at fs/lockd/host.c:417!" or ".../host.c:283!" NFS: Prevent memory allocation failure in nfsacl_encode() NFS: nfsacl_{encode,decode} should return signed integer NFS: Fix "kernel BUG at fs/nfs/nfs3xdr.c:1338!" NFS: Fix "kernel BUG at fs/aio.c:554!" NFS4: Avoid potential NULL pointer dereference in decode_and_add_ds(). NFS: fix handling of malloc failure during nfs_flush_multi()
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/host.c9
-rw-r--r--fs/nfs/callback.c109
-rw-r--r--fs/nfs/callback.h4
-rw-r--r--fs/nfs/callback_proc.c12
-rw-r--r--fs/nfs/callback_xdr.c5
-rw-r--r--fs/nfs/client.c15
-rw-r--r--fs/nfs/delegation.c6
-rw-r--r--fs/nfs/direct.c34
-rw-r--r--fs/nfs/inode.c26
-rw-r--r--fs/nfs/internal.h3
-rw-r--r--fs/nfs/nfs3acl.c4
-rw-r--r--fs/nfs/nfs3xdr.c5
-rw-r--r--fs/nfs/nfs4filelayoutdev.c9
-rw-r--r--fs/nfs/nfs4proc.c30
-rw-r--r--fs/nfs/nfs4state.c6
-rw-r--r--fs/nfs/nfs4xdr.c9
-rw-r--r--fs/nfs/pnfs.c2
-rw-r--r--fs/nfs/write.c2
-rw-r--r--fs/nfs_common/nfsacl.c54
-rw-r--r--fs/posix_acl.c17
20 files changed, 170 insertions, 191 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 5f1bcb2f06f3..b7c99bfb3da6 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -520,7 +520,7 @@ static struct nlm_host *next_host_state(struct hlist_head *cache,
520 struct nsm_handle *nsm, 520 struct nsm_handle *nsm,
521 const struct nlm_reboot *info) 521 const struct nlm_reboot *info)
522{ 522{
523 struct nlm_host *host = NULL; 523 struct nlm_host *host;
524 struct hlist_head *chain; 524 struct hlist_head *chain;
525 struct hlist_node *pos; 525 struct hlist_node *pos;
526 526
@@ -532,12 +532,13 @@ static struct nlm_host *next_host_state(struct hlist_head *cache,
532 host->h_state++; 532 host->h_state++;
533 533
534 nlm_get_host(host); 534 nlm_get_host(host);
535 goto out; 535 mutex_unlock(&nlm_host_mutex);
536 return host;
536 } 537 }
537 } 538 }
538out: 539
539 mutex_unlock(&nlm_host_mutex); 540 mutex_unlock(&nlm_host_mutex);
540 return host; 541 return NULL;
541} 542}
542 543
543/** 544/**
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 199016528fcb..e3d294269058 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -135,33 +135,6 @@ out_err:
135 135
136#if defined(CONFIG_NFS_V4_1) 136#if defined(CONFIG_NFS_V4_1)
137/* 137/*
138 * * CB_SEQUENCE operations will fail until the callback sessionid is set.
139 * */
140int nfs4_set_callback_sessionid(struct nfs_client *clp)
141{
142 struct svc_serv *serv = clp->cl_rpcclient->cl_xprt->bc_serv;
143 struct nfs4_sessionid *bc_sid;
144
145 if (!serv->sv_bc_xprt)
146 return -EINVAL;
147
148 /* on success freed in xprt_free */
149 bc_sid = kmalloc(sizeof(struct nfs4_sessionid), GFP_KERNEL);
150 if (!bc_sid)
151 return -ENOMEM;
152 memcpy(bc_sid->data, &clp->cl_session->sess_id.data,
153 NFS4_MAX_SESSIONID_LEN);
154 spin_lock_bh(&serv->sv_cb_lock);
155 serv->sv_bc_xprt->xpt_bc_sid = bc_sid;
156 spin_unlock_bh(&serv->sv_cb_lock);
157 dprintk("%s set xpt_bc_sid=%u:%u:%u:%u for sv_bc_xprt %p\n", __func__,
158 ((u32 *)bc_sid->data)[0], ((u32 *)bc_sid->data)[1],
159 ((u32 *)bc_sid->data)[2], ((u32 *)bc_sid->data)[3],
160 serv->sv_bc_xprt);
161 return 0;
162}
163
164/*
165 * The callback service for NFSv4.1 callbacks 138 * The callback service for NFSv4.1 callbacks
166 */ 139 */
167static int 140static int
@@ -266,10 +239,6 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
266 struct nfs_callback_data *cb_info) 239 struct nfs_callback_data *cb_info)
267{ 240{
268} 241}
269int nfs4_set_callback_sessionid(struct nfs_client *clp)
270{
271 return 0;
272}
273#endif /* CONFIG_NFS_V4_1 */ 242#endif /* CONFIG_NFS_V4_1 */
274 243
275/* 244/*
@@ -359,78 +328,58 @@ void nfs_callback_down(int minorversion)
359 mutex_unlock(&nfs_callback_mutex); 328 mutex_unlock(&nfs_callback_mutex);
360} 329}
361 330
362static int check_gss_callback_principal(struct nfs_client *clp, 331/* Boolean check of RPC_AUTH_GSS principal */
363 struct svc_rqst *rqstp) 332int
333check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
364{ 334{
365 struct rpc_clnt *r = clp->cl_rpcclient; 335 struct rpc_clnt *r = clp->cl_rpcclient;
366 char *p = svc_gss_principal(rqstp); 336 char *p = svc_gss_principal(rqstp);
367 337
338 if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
339 return 1;
340
368 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ 341 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
369 if (clp->cl_minorversion != 0) 342 if (clp->cl_minorversion != 0)
370 return SVC_DROP; 343 return 0;
371 /* 344 /*
372 * It might just be a normal user principal, in which case 345 * It might just be a normal user principal, in which case
373 * userspace won't bother to tell us the name at all. 346 * userspace won't bother to tell us the name at all.
374 */ 347 */
375 if (p == NULL) 348 if (p == NULL)
376 return SVC_DENIED; 349 return 0;
377 350
378 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 351 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
379 352
380 if (memcmp(p, "nfs@", 4) != 0) 353 if (memcmp(p, "nfs@", 4) != 0)
381 return SVC_DENIED; 354 return 0;
382 p += 4; 355 p += 4;
383 if (strcmp(p, r->cl_server) != 0) 356 if (strcmp(p, r->cl_server) != 0)
384 return SVC_DENIED; 357 return 0;
385 return SVC_OK; 358 return 1;
386} 359}
387 360
388/* pg_authenticate method helper */ 361/*
389static struct nfs_client *nfs_cb_find_client(struct svc_rqst *rqstp) 362 * pg_authenticate method for nfsv4 callback threads.
390{ 363 *
391 struct nfs4_sessionid *sessionid = bc_xprt_sid(rqstp); 364 * The authflavor has been negotiated, so an incorrect flavor is a server
392 int is_cb_compound = rqstp->rq_proc == CB_COMPOUND ? 1 : 0; 365 * bug. Drop packets with incorrect authflavor.
393 366 *
394 dprintk("--> %s rq_proc %d\n", __func__, rqstp->rq_proc); 367 * All other checking done after NFS decoding where the nfs_client can be
395 if (svc_is_backchannel(rqstp)) 368 * found in nfs4_callback_compound
396 /* Sessionid (usually) set after CB_NULL ping */ 369 */
397 return nfs4_find_client_sessionid(svc_addr(rqstp), sessionid,
398 is_cb_compound);
399 else
400 /* No callback identifier in pg_authenticate */
401 return nfs4_find_client_no_ident(svc_addr(rqstp));
402}
403
404/* pg_authenticate method for nfsv4 callback threads. */
405static int nfs_callback_authenticate(struct svc_rqst *rqstp) 370static int nfs_callback_authenticate(struct svc_rqst *rqstp)
406{ 371{
407 struct nfs_client *clp;
408 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
409 int ret = SVC_OK;
410
411 /* Don't talk to strangers */
412 clp = nfs_cb_find_client(rqstp);
413 if (clp == NULL)
414 return SVC_DROP;
415
416 dprintk("%s: %s NFSv4 callback!\n", __func__,
417 svc_print_addr(rqstp, buf, sizeof(buf)));
418
419 switch (rqstp->rq_authop->flavour) { 372 switch (rqstp->rq_authop->flavour) {
420 case RPC_AUTH_NULL: 373 case RPC_AUTH_NULL:
421 if (rqstp->rq_proc != CB_NULL) 374 if (rqstp->rq_proc != CB_NULL)
422 ret = SVC_DENIED; 375 return SVC_DROP;
423 break; 376 break;
424 case RPC_AUTH_UNIX: 377 case RPC_AUTH_GSS:
425 break; 378 /* No RPC_AUTH_GSS support yet in NFSv4.1 */
426 case RPC_AUTH_GSS: 379 if (svc_is_backchannel(rqstp))
427 ret = check_gss_callback_principal(clp, rqstp); 380 return SVC_DROP;
428 break;
429 default:
430 ret = SVC_DENIED;
431 } 381 }
432 nfs_put_client(clp); 382 return SVC_OK;
433 return ret;
434} 383}
435 384
436/* 385/*
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index d3b44f9bd747..46d93ce7311b 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -7,6 +7,7 @@
7 */ 7 */
8#ifndef __LINUX_FS_NFS_CALLBACK_H 8#ifndef __LINUX_FS_NFS_CALLBACK_H
9#define __LINUX_FS_NFS_CALLBACK_H 9#define __LINUX_FS_NFS_CALLBACK_H
10#include <linux/sunrpc/svc.h>
10 11
11#define NFS4_CALLBACK 0x40000000 12#define NFS4_CALLBACK 0x40000000
12#define NFS4_CALLBACK_XDRSIZE 2048 13#define NFS4_CALLBACK_XDRSIZE 2048
@@ -37,7 +38,6 @@ enum nfs4_callback_opnum {
37struct cb_process_state { 38struct cb_process_state {
38 __be32 drc_status; 39 __be32 drc_status;
39 struct nfs_client *clp; 40 struct nfs_client *clp;
40 struct nfs4_sessionid *svc_sid; /* v4.1 callback service sessionid */
41}; 41};
42 42
43struct cb_compound_hdr_arg { 43struct cb_compound_hdr_arg {
@@ -168,7 +168,7 @@ extern unsigned nfs4_callback_layoutrecall(
168extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses); 168extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
169extern void nfs4_cb_take_slot(struct nfs_client *clp); 169extern void nfs4_cb_take_slot(struct nfs_client *clp);
170#endif /* CONFIG_NFS_V4_1 */ 170#endif /* CONFIG_NFS_V4_1 */
171 171extern int check_gss_callback_principal(struct nfs_client *, struct svc_rqst *);
172extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, 172extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args,
173 struct cb_getattrres *res, 173 struct cb_getattrres *res,
174 struct cb_process_state *cps); 174 struct cb_process_state *cps);
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 4bb91cb2620d..89587573fe50 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -373,17 +373,11 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
373{ 373{
374 struct nfs_client *clp; 374 struct nfs_client *clp;
375 int i; 375 int i;
376 __be32 status; 376 __be32 status = htonl(NFS4ERR_BADSESSION);
377 377
378 cps->clp = NULL; 378 cps->clp = NULL;
379 379
380 status = htonl(NFS4ERR_BADSESSION); 380 clp = nfs4_find_client_sessionid(args->csa_addr, &args->csa_sessionid);
381 /* Incoming session must match the callback session */
382 if (memcmp(&args->csa_sessionid, cps->svc_sid, NFS4_MAX_SESSIONID_LEN))
383 goto out;
384
385 clp = nfs4_find_client_sessionid(args->csa_addr,
386 &args->csa_sessionid, 1);
387 if (clp == NULL) 381 if (clp == NULL)
388 goto out; 382 goto out;
389 383
@@ -414,9 +408,9 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
414 res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; 408 res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
415 res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1; 409 res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS - 1;
416 nfs4_cb_take_slot(clp); 410 nfs4_cb_take_slot(clp);
417 cps->clp = clp; /* put in nfs4_callback_compound */
418 411
419out: 412out:
413 cps->clp = clp; /* put in nfs4_callback_compound */
420 for (i = 0; i < args->csa_nrclists; i++) 414 for (i = 0; i < args->csa_nrclists; i++)
421 kfree(args->csa_rclists[i].rcl_refcalls); 415 kfree(args->csa_rclists[i].rcl_refcalls);
422 kfree(args->csa_rclists); 416 kfree(args->csa_rclists);
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 23112c263f81..14e0f9371d14 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -794,10 +794,9 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
794 794
795 if (hdr_arg.minorversion == 0) { 795 if (hdr_arg.minorversion == 0) {
796 cps.clp = nfs4_find_client_ident(hdr_arg.cb_ident); 796 cps.clp = nfs4_find_client_ident(hdr_arg.cb_ident);
797 if (!cps.clp) 797 if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
798 return rpc_drop_reply; 798 return rpc_drop_reply;
799 } else 799 }
800 cps.svc_sid = bc_xprt_sid(rqstp);
801 800
802 hdr_res.taglen = hdr_arg.taglen; 801 hdr_res.taglen = hdr_arg.taglen;
803 hdr_res.tag = hdr_arg.tag; 802 hdr_res.tag = hdr_arg.tag;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 192f2f860265..bd3ca32879e7 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1206,16 +1206,11 @@ nfs4_find_client_ident(int cb_ident)
1206 * For CB_COMPOUND calls, find a client by IP address, protocol version, 1206 * For CB_COMPOUND calls, find a client by IP address, protocol version,
1207 * minorversion, and sessionID 1207 * minorversion, and sessionID
1208 * 1208 *
1209 * CREATE_SESSION triggers a CB_NULL ping from servers. The callback service
1210 * sessionid can only be set after the CREATE_SESSION return, so a CB_NULL
1211 * can arrive before the callback sessionid is set. For CB_NULL calls,
1212 * find a client by IP address protocol version, and minorversion.
1213 *
1214 * Returns NULL if no such client 1209 * Returns NULL if no such client
1215 */ 1210 */
1216struct nfs_client * 1211struct nfs_client *
1217nfs4_find_client_sessionid(const struct sockaddr *addr, 1212nfs4_find_client_sessionid(const struct sockaddr *addr,
1218 struct nfs4_sessionid *sid, int is_cb_compound) 1213 struct nfs4_sessionid *sid)
1219{ 1214{
1220 struct nfs_client *clp; 1215 struct nfs_client *clp;
1221 1216
@@ -1227,9 +1222,9 @@ nfs4_find_client_sessionid(const struct sockaddr *addr,
1227 if (!nfs4_has_session(clp)) 1222 if (!nfs4_has_session(clp))
1228 continue; 1223 continue;
1229 1224
1230 /* Match sessionid unless cb_null call*/ 1225 /* Match sessionid*/
1231 if (is_cb_compound && (memcmp(clp->cl_session->sess_id.data, 1226 if (memcmp(clp->cl_session->sess_id.data,
1232 sid->data, NFS4_MAX_SESSIONID_LEN) != 0)) 1227 sid->data, NFS4_MAX_SESSIONID_LEN) != 0)
1233 continue; 1228 continue;
1234 1229
1235 atomic_inc(&clp->cl_count); 1230 atomic_inc(&clp->cl_count);
@@ -1244,7 +1239,7 @@ nfs4_find_client_sessionid(const struct sockaddr *addr,
1244 1239
1245struct nfs_client * 1240struct nfs_client *
1246nfs4_find_client_sessionid(const struct sockaddr *addr, 1241nfs4_find_client_sessionid(const struct sockaddr *addr,
1247 struct nfs4_sessionid *sid, int is_cb_compound) 1242 struct nfs4_sessionid *sid)
1248{ 1243{
1249 return NULL; 1244 return NULL;
1250} 1245}
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 364e4328f392..bbbc6bf5cb2e 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -23,8 +23,6 @@
23 23
24static void nfs_do_free_delegation(struct nfs_delegation *delegation) 24static void nfs_do_free_delegation(struct nfs_delegation *delegation)
25{ 25{
26 if (delegation->cred)
27 put_rpccred(delegation->cred);
28 kfree(delegation); 26 kfree(delegation);
29} 27}
30 28
@@ -37,6 +35,10 @@ static void nfs_free_delegation_callback(struct rcu_head *head)
37 35
38static void nfs_free_delegation(struct nfs_delegation *delegation) 36static void nfs_free_delegation(struct nfs_delegation *delegation)
39{ 37{
38 if (delegation->cred) {
39 put_rpccred(delegation->cred);
40 delegation->cred = NULL;
41 }
40 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 42 call_rcu(&delegation->rcu, nfs_free_delegation_callback);
41} 43}
42 44
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index e6ace0d93c71..9943a75bb6d1 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -407,15 +407,18 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
407 pos += vec->iov_len; 407 pos += vec->iov_len;
408 } 408 }
409 409
410 /*
411 * If no bytes were started, return the error, and let the
412 * generic layer handle the completion.
413 */
414 if (requested_bytes == 0) {
415 nfs_direct_req_release(dreq);
416 return result < 0 ? result : -EIO;
417 }
418
410 if (put_dreq(dreq)) 419 if (put_dreq(dreq))
411 nfs_direct_complete(dreq); 420 nfs_direct_complete(dreq);
412 421 return 0;
413 if (requested_bytes != 0)
414 return 0;
415
416 if (result < 0)
417 return result;
418 return -EIO;
419} 422}
420 423
421static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, 424static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
@@ -841,15 +844,18 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
841 pos += vec->iov_len; 844 pos += vec->iov_len;
842 } 845 }
843 846
847 /*
848 * If no bytes were started, return the error, and let the
849 * generic layer handle the completion.
850 */
851 if (requested_bytes == 0) {
852 nfs_direct_req_release(dreq);
853 return result < 0 ? result : -EIO;
854 }
855
844 if (put_dreq(dreq)) 856 if (put_dreq(dreq))
845 nfs_direct_write_complete(dreq, dreq->inode); 857 nfs_direct_write_complete(dreq, dreq->inode);
846 858 return 0;
847 if (requested_bytes != 0)
848 return 0;
849
850 if (result < 0)
851 return result;
852 return -EIO;
853} 859}
854 860
855static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, 861static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d8512423ba72..1cc600e77bb4 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -881,9 +881,10 @@ out:
881 return ret; 881 return ret;
882} 882}
883 883
884static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) 884static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
885{ 885{
886 struct nfs_inode *nfsi = NFS_I(inode); 886 struct nfs_inode *nfsi = NFS_I(inode);
887 unsigned long ret = 0;
887 888
888 if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) 889 if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
889 && (fattr->valid & NFS_ATTR_FATTR_CHANGE) 890 && (fattr->valid & NFS_ATTR_FATTR_CHANGE)
@@ -891,25 +892,32 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
891 nfsi->change_attr = fattr->change_attr; 892 nfsi->change_attr = fattr->change_attr;
892 if (S_ISDIR(inode->i_mode)) 893 if (S_ISDIR(inode->i_mode))
893 nfsi->cache_validity |= NFS_INO_INVALID_DATA; 894 nfsi->cache_validity |= NFS_INO_INVALID_DATA;
895 ret |= NFS_INO_INVALID_ATTR;
894 } 896 }
895 /* If we have atomic WCC data, we may update some attributes */ 897 /* If we have atomic WCC data, we may update some attributes */
896 if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) 898 if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
897 && (fattr->valid & NFS_ATTR_FATTR_CTIME) 899 && (fattr->valid & NFS_ATTR_FATTR_CTIME)
898 && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) 900 && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
899 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); 901 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
902 ret |= NFS_INO_INVALID_ATTR;
903 }
900 904
901 if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) 905 if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
902 && (fattr->valid & NFS_ATTR_FATTR_MTIME) 906 && (fattr->valid & NFS_ATTR_FATTR_MTIME)
903 && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { 907 && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
904 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); 908 memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
905 if (S_ISDIR(inode->i_mode)) 909 if (S_ISDIR(inode->i_mode))
906 nfsi->cache_validity |= NFS_INO_INVALID_DATA; 910 nfsi->cache_validity |= NFS_INO_INVALID_DATA;
911 ret |= NFS_INO_INVALID_ATTR;
907 } 912 }
908 if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) 913 if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE)
909 && (fattr->valid & NFS_ATTR_FATTR_SIZE) 914 && (fattr->valid & NFS_ATTR_FATTR_SIZE)
910 && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) 915 && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size)
911 && nfsi->npages == 0) 916 && nfsi->npages == 0) {
912 i_size_write(inode, nfs_size_to_loff_t(fattr->size)); 917 i_size_write(inode, nfs_size_to_loff_t(fattr->size));
918 ret |= NFS_INO_INVALID_ATTR;
919 }
920 return ret;
913} 921}
914 922
915/** 923/**
@@ -1223,7 +1231,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1223 | NFS_INO_REVAL_PAGECACHE); 1231 | NFS_INO_REVAL_PAGECACHE);
1224 1232
1225 /* Do atomic weak cache consistency updates */ 1233 /* Do atomic weak cache consistency updates */
1226 nfs_wcc_update_inode(inode, fattr); 1234 invalid |= nfs_wcc_update_inode(inode, fattr);
1227 1235
1228 /* More cache consistency checks */ 1236 /* More cache consistency checks */
1229 if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { 1237 if (fattr->valid & NFS_ATTR_FATTR_CHANGE) {
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4644f04b4b46..cf9fdbdabc67 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -133,8 +133,7 @@ extern void nfs_put_client(struct nfs_client *);
133extern struct nfs_client *nfs4_find_client_no_ident(const struct sockaddr *); 133extern struct nfs_client *nfs4_find_client_no_ident(const struct sockaddr *);
134extern struct nfs_client *nfs4_find_client_ident(int); 134extern struct nfs_client *nfs4_find_client_ident(int);
135extern struct nfs_client * 135extern struct nfs_client *
136nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *, 136nfs4_find_client_sessionid(const struct sockaddr *, struct nfs4_sessionid *);
137 int);
138extern struct nfs_server *nfs_create_server( 137extern struct nfs_server *nfs_create_server(
139 const struct nfs_parsed_mount_data *, 138 const struct nfs_parsed_mount_data *,
140 struct nfs_fh *); 139 struct nfs_fh *);
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 9f88c5f4c7e2..274342771655 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -311,8 +311,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
311 if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 311 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
312 goto out; 312 goto out;
313 313
314 /* We are doing this here, because XDR marshalling can only 314 /* We are doing this here because XDR marshalling does not
315 return -ENOMEM. */ 315 * return any results, it BUGs. */
316 status = -ENOSPC; 316 status = -ENOSPC;
317 if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES) 317 if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
318 goto out; 318 goto out;
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 01c5e8b1941d..183c6b123d0f 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1328,10 +1328,13 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
1328 1328
1329 encode_nfs_fh3(xdr, NFS_FH(args->inode)); 1329 encode_nfs_fh3(xdr, NFS_FH(args->inode));
1330 encode_uint32(xdr, args->mask); 1330 encode_uint32(xdr, args->mask);
1331
1332 base = req->rq_slen;
1331 if (args->npages != 0) 1333 if (args->npages != 0)
1332 xdr_write_pages(xdr, args->pages, 0, args->len); 1334 xdr_write_pages(xdr, args->pages, 0, args->len);
1335 else
1336 xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE);
1333 1337
1334 base = req->rq_slen;
1335 error = nfsacl_encode(xdr->buf, base, args->inode, 1338 error = nfsacl_encode(xdr->buf, base, args->inode,
1336 (args->mask & NFS_ACL) ? 1339 (args->mask & NFS_ACL) ?
1337 args->acl_access : NULL, 1, 0); 1340 args->acl_access : NULL, 1, 0);
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 51fe64ace55a..f5c9b125e8cc 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -214,7 +214,7 @@ decode_and_add_ds(__be32 **pp, struct inode *inode)
214 214
215 /* ipv6 length plus port is legal */ 215 /* ipv6 length plus port is legal */
216 if (rlen > INET6_ADDRSTRLEN + 8) { 216 if (rlen > INET6_ADDRSTRLEN + 8) {
217 dprintk("%s Invalid address, length %d\n", __func__, 217 dprintk("%s: Invalid address, length %d\n", __func__,
218 rlen); 218 rlen);
219 goto out_err; 219 goto out_err;
220 } 220 }
@@ -225,6 +225,11 @@ decode_and_add_ds(__be32 **pp, struct inode *inode)
225 /* replace the port dots with dashes for the in4_pton() delimiter*/ 225 /* replace the port dots with dashes for the in4_pton() delimiter*/
226 for (i = 0; i < 2; i++) { 226 for (i = 0; i < 2; i++) {
227 char *res = strrchr(buf, '.'); 227 char *res = strrchr(buf, '.');
228 if (!res) {
229 dprintk("%s: Failed finding expected dots in port\n",
230 __func__);
231 goto out_free;
232 }
228 *res = '-'; 233 *res = '-';
229 } 234 }
230 235
@@ -240,7 +245,7 @@ decode_and_add_ds(__be32 **pp, struct inode *inode)
240 port = htons((tmp[0] << 8) | (tmp[1])); 245 port = htons((tmp[0] << 8) | (tmp[1]));
241 246
242 ds = nfs4_pnfs_ds_add(inode, ip_addr, port); 247 ds = nfs4_pnfs_ds_add(inode, ip_addr, port);
243 dprintk("%s Decoded address and port %s\n", __func__, buf); 248 dprintk("%s: Decoded address and port %s\n", __func__, buf);
244out_free: 249out_free:
245 kfree(buf); 250 kfree(buf);
246out_err: 251out_err:
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9d992b0346e3..78936a8f40ab 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -50,6 +50,7 @@
50#include <linux/module.h> 50#include <linux/module.h>
51#include <linux/sunrpc/bc_xprt.h> 51#include <linux/sunrpc/bc_xprt.h>
52#include <linux/xattr.h> 52#include <linux/xattr.h>
53#include <linux/utsname.h>
53 54
54#include "nfs4_fs.h" 55#include "nfs4_fs.h"
55#include "delegation.h" 56#include "delegation.h"
@@ -4572,27 +4573,16 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4572 *p = htonl((u32)clp->cl_boot_time.tv_nsec); 4573 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
4573 args.verifier = &verifier; 4574 args.verifier = &verifier;
4574 4575
4575 while (1) { 4576 args.id_len = scnprintf(args.id, sizeof(args.id),
4576 args.id_len = scnprintf(args.id, sizeof(args.id), 4577 "%s/%s.%s/%u",
4577 "%s/%s %u", 4578 clp->cl_ipaddr,
4578 clp->cl_ipaddr, 4579 init_utsname()->nodename,
4579 rpc_peeraddr2str(clp->cl_rpcclient, 4580 init_utsname()->domainname,
4580 RPC_DISPLAY_ADDR), 4581 clp->cl_rpcclient->cl_auth->au_flavor);
4581 clp->cl_id_uniquifier);
4582
4583 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4584
4585 if (status != -NFS4ERR_CLID_INUSE)
4586 break;
4587
4588 if (signalled())
4589 break;
4590
4591 if (++clp->cl_id_uniquifier == 0)
4592 break;
4593 }
4594 4582
4595 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); 4583 status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
4584 if (!status)
4585 status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
4596 dprintk("<-- %s status= %d\n", __func__, status); 4586 dprintk("<-- %s status= %d\n", __func__, status);
4597 return status; 4587 return status;
4598} 4588}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2336d532cf66..e6742b57a04c 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -232,12 +232,6 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
232 status = nfs4_proc_create_session(clp); 232 status = nfs4_proc_create_session(clp);
233 if (status != 0) 233 if (status != 0)
234 goto out; 234 goto out;
235 status = nfs4_set_callback_sessionid(clp);
236 if (status != 0) {
237 printk(KERN_WARNING "Sessionid not set. No callback service\n");
238 nfs_callback_down(1);
239 status = 0;
240 }
241 nfs41_setup_state_renewal(clp); 235 nfs41_setup_state_renewal(clp);
242 nfs_mark_client_ready(clp, NFS_CS_READY); 236 nfs_mark_client_ready(clp, NFS_CS_READY);
243out: 237out:
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 2ab8e5cb8f59..4e2c168b6ee9 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6086,11 +6086,11 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6086 __be32 *p = xdr_inline_decode(xdr, 4); 6086 __be32 *p = xdr_inline_decode(xdr, 4);
6087 if (unlikely(!p)) 6087 if (unlikely(!p))
6088 goto out_overflow; 6088 goto out_overflow;
6089 if (!ntohl(*p++)) { 6089 if (*p == xdr_zero) {
6090 p = xdr_inline_decode(xdr, 4); 6090 p = xdr_inline_decode(xdr, 4);
6091 if (unlikely(!p)) 6091 if (unlikely(!p))
6092 goto out_overflow; 6092 goto out_overflow;
6093 if (!ntohl(*p++)) 6093 if (*p == xdr_zero)
6094 return -EAGAIN; 6094 return -EAGAIN;
6095 entry->eof = 1; 6095 entry->eof = 1;
6096 return -EBADCOOKIE; 6096 return -EBADCOOKIE;
@@ -6101,7 +6101,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6101 goto out_overflow; 6101 goto out_overflow;
6102 entry->prev_cookie = entry->cookie; 6102 entry->prev_cookie = entry->cookie;
6103 p = xdr_decode_hyper(p, &entry->cookie); 6103 p = xdr_decode_hyper(p, &entry->cookie);
6104 entry->len = ntohl(*p++); 6104 entry->len = be32_to_cpup(p);
6105 6105
6106 p = xdr_inline_decode(xdr, entry->len); 6106 p = xdr_inline_decode(xdr, entry->len);
6107 if (unlikely(!p)) 6107 if (unlikely(!p))
@@ -6132,9 +6132,6 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6132 if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) 6132 if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
6133 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 6133 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
6134 6134
6135 if (verify_attr_len(xdr, p, len) < 0)
6136 goto out_overflow;
6137
6138 return 0; 6135 return 0;
6139 6136
6140out_overflow: 6137out_overflow:
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index bc4089769735..1b1bc1a0fb0a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -951,7 +951,7 @@ pnfs_put_deviceid_cache(struct nfs_client *clp)
951{ 951{
952 struct pnfs_deviceid_cache *local = clp->cl_devid_cache; 952 struct pnfs_deviceid_cache *local = clp->cl_devid_cache;
953 953
954 dprintk("--> %s cl_devid_cache %p\n", __func__, clp->cl_devid_cache); 954 dprintk("--> %s ({%d})\n", __func__, atomic_read(&local->dc_ref));
955 if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) { 955 if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) {
956 int i; 956 int i;
957 /* Verify cache is empty */ 957 /* Verify cache is empty */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 10d648ea128b..c8278f4046cb 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -932,7 +932,7 @@ out_bad:
932 while (!list_empty(&list)) { 932 while (!list_empty(&list)) {
933 data = list_entry(list.next, struct nfs_write_data, pages); 933 data = list_entry(list.next, struct nfs_write_data, pages);
934 list_del(&data->pages); 934 list_del(&data->pages);
935 nfs_writedata_release(data); 935 nfs_writedata_free(data);
936 } 936 }
937 nfs_redirty_request(req); 937 nfs_redirty_request(req);
938 return -ENOMEM; 938 return -ENOMEM;
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
index fc1c52571c03..84c27d69d421 100644
--- a/fs/nfs_common/nfsacl.c
+++ b/fs/nfs_common/nfsacl.c
@@ -42,6 +42,11 @@ struct nfsacl_encode_desc {
42 gid_t gid; 42 gid_t gid;
43}; 43};
44 44
45struct nfsacl_simple_acl {
46 struct posix_acl acl;
47 struct posix_acl_entry ace[4];
48};
49
45static int 50static int
46xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) 51xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
47{ 52{
@@ -72,9 +77,20 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
72 return 0; 77 return 0;
73} 78}
74 79
75unsigned int 80/**
76nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, 81 * nfsacl_encode - Encode an NFSv3 ACL
77 struct posix_acl *acl, int encode_entries, int typeflag) 82 *
83 * @buf: destination xdr_buf to contain XDR encoded ACL
84 * @base: byte offset in xdr_buf where XDR'd ACL begins
85 * @inode: inode of file whose ACL this is
86 * @acl: posix_acl to encode
87 * @encode_entries: whether to encode ACEs as well
88 * @typeflag: ACL type: NFS_ACL_DEFAULT or zero
89 *
90 * Returns size of encoded ACL in bytes or a negative errno value.
91 */
92int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
93 struct posix_acl *acl, int encode_entries, int typeflag)
78{ 94{
79 int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0; 95 int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0;
80 struct nfsacl_encode_desc nfsacl_desc = { 96 struct nfsacl_encode_desc nfsacl_desc = {
@@ -88,17 +104,22 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
88 .uid = inode->i_uid, 104 .uid = inode->i_uid,
89 .gid = inode->i_gid, 105 .gid = inode->i_gid,
90 }; 106 };
107 struct nfsacl_simple_acl aclbuf;
91 int err; 108 int err;
92 struct posix_acl *acl2 = NULL;
93 109
94 if (entries > NFS_ACL_MAX_ENTRIES || 110 if (entries > NFS_ACL_MAX_ENTRIES ||
95 xdr_encode_word(buf, base, entries)) 111 xdr_encode_word(buf, base, entries))
96 return -EINVAL; 112 return -EINVAL;
97 if (encode_entries && acl && acl->a_count == 3) { 113 if (encode_entries && acl && acl->a_count == 3) {
98 /* Fake up an ACL_MASK entry. */ 114 struct posix_acl *acl2 = &aclbuf.acl;
99 acl2 = posix_acl_alloc(4, GFP_KERNEL); 115
100 if (!acl2) 116 /* Avoid the use of posix_acl_alloc(). nfsacl_encode() is
101 return -ENOMEM; 117 * invoked in contexts where a memory allocation failure is
118 * fatal. Fortunately this fake ACL is small enough to
119 * construct on the stack. */
120 memset(acl2, 0, sizeof(acl2));
121 posix_acl_init(acl2, 4);
122
102 /* Insert entries in canonical order: other orders seem 123 /* Insert entries in canonical order: other orders seem
103 to confuse Solaris VxFS. */ 124 to confuse Solaris VxFS. */
104 acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ 125 acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */
@@ -109,8 +130,6 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
109 nfsacl_desc.acl = acl2; 130 nfsacl_desc.acl = acl2;
110 } 131 }
111 err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); 132 err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc);
112 if (acl2)
113 posix_acl_release(acl2);
114 if (!err) 133 if (!err)
115 err = 8 + nfsacl_desc.desc.elem_size * 134 err = 8 + nfsacl_desc.desc.elem_size *
116 nfsacl_desc.desc.array_len; 135 nfsacl_desc.desc.array_len;
@@ -224,9 +243,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
224 return 0; 243 return 0;
225} 244}
226 245
227unsigned int 246/**
228nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt, 247 * nfsacl_decode - Decode an NFSv3 ACL
229 struct posix_acl **pacl) 248 *
249 * @buf: xdr_buf containing XDR'd ACL data to decode
250 * @base: byte offset in xdr_buf where XDR'd ACL begins
251 * @aclcnt: count of ACEs in decoded posix_acl
252 * @pacl: buffer in which to place decoded posix_acl
253 *
254 * Returns the length of the decoded ACL in bytes, or a negative errno value.
255 */
256int nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
257 struct posix_acl **pacl)
230{ 258{
231 struct nfsacl_decode_desc nfsacl_desc = { 259 struct nfsacl_decode_desc nfsacl_desc = {
232 .desc = { 260 .desc = {
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 39df95a0ec25..b1cf6bf4b41d 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -22,6 +22,7 @@
22 22
23#include <linux/errno.h> 23#include <linux/errno.h>
24 24
25EXPORT_SYMBOL(posix_acl_init);
25EXPORT_SYMBOL(posix_acl_alloc); 26EXPORT_SYMBOL(posix_acl_alloc);
26EXPORT_SYMBOL(posix_acl_clone); 27EXPORT_SYMBOL(posix_acl_clone);
27EXPORT_SYMBOL(posix_acl_valid); 28EXPORT_SYMBOL(posix_acl_valid);
@@ -32,6 +33,16 @@ EXPORT_SYMBOL(posix_acl_chmod_masq);
32EXPORT_SYMBOL(posix_acl_permission); 33EXPORT_SYMBOL(posix_acl_permission);
33 34
34/* 35/*
36 * Init a fresh posix_acl
37 */
38void
39posix_acl_init(struct posix_acl *acl, int count)
40{
41 atomic_set(&acl->a_refcount, 1);
42 acl->a_count = count;
43}
44
45/*
35 * Allocate a new ACL with the specified number of entries. 46 * Allocate a new ACL with the specified number of entries.
36 */ 47 */
37struct posix_acl * 48struct posix_acl *
@@ -40,10 +51,8 @@ posix_acl_alloc(int count, gfp_t flags)
40 const size_t size = sizeof(struct posix_acl) + 51 const size_t size = sizeof(struct posix_acl) +
41 count * sizeof(struct posix_acl_entry); 52 count * sizeof(struct posix_acl_entry);
42 struct posix_acl *acl = kmalloc(size, flags); 53 struct posix_acl *acl = kmalloc(size, flags);
43 if (acl) { 54 if (acl)
44 atomic_set(&acl->a_refcount, 1); 55 posix_acl_init(acl, count);
45 acl->a_count = count;
46 }
47 return acl; 56 return acl;
48} 57}
49 58