aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-08-04 12:56:40 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-08-04 12:56:40 -0400
commit3b445eeac4f292aeb14df50b272729d0924da937 (patch)
tree8f301134c8755f77bd09481d5165cd4a91b66ee5
parent12952784e5271374b7cb926501f51b9649bf5a2b (diff)
parent5c3e985a2c1908aa97221d3806f85ce7e2fbfa88 (diff)
Merge branch 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6
* 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6: SUNRPC: Fix obvious refcounting bugs in rpc_pipefs. RPC: Ensure that we disconnect TCP socket when client requests error out NLM/lockd: remove b_done NFS: make 2 functions static NFS: Release dcache_lock in an error path of nfs_path
-rw-r--r--fs/lockd/svclock.c12
-rw-r--r--fs/nfs/namespace.c4
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/write.c2
-rw-r--r--include/linux/lockd/lockd.h1
-rw-r--r--include/linux/nfs_fs.h6
-rw-r--r--include/linux/sunrpc/xprt.h2
-rw-r--r--net/sunrpc/clnt.c52
-rw-r--r--net/sunrpc/rpc_pipe.c6
-rw-r--r--net/sunrpc/xprt.c21
-rw-r--r--net/sunrpc/xprtsock.c29
11 files changed, 75 insertions, 62 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index baf5ae513481..c9d419703cf3 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -638,9 +638,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
638 if (task->tk_status < 0) { 638 if (task->tk_status < 0) {
639 /* RPC error: Re-insert for retransmission */ 639 /* RPC error: Re-insert for retransmission */
640 timeout = 10 * HZ; 640 timeout = 10 * HZ;
641 } else if (block->b_done) {
642 /* Block already removed, kill it for real */
643 timeout = 0;
644 } else { 641 } else {
645 /* Call was successful, now wait for client callback */ 642 /* Call was successful, now wait for client callback */
646 timeout = 60 * HZ; 643 timeout = 60 * HZ;
@@ -709,13 +706,10 @@ nlmsvc_retry_blocked(void)
709 break; 706 break;
710 if (time_after(block->b_when,jiffies)) 707 if (time_after(block->b_when,jiffies))
711 break; 708 break;
712 dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", 709 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
713 block, block->b_when, block->b_done); 710 block, block->b_when);
714 kref_get(&block->b_count); 711 kref_get(&block->b_count);
715 if (block->b_done) 712 nlmsvc_grant_blocked(block);
716 nlmsvc_unlink_block(block);
717 else
718 nlmsvc_grant_blocked(block);
719 nlmsvc_release_block(block); 713 nlmsvc_release_block(block);
720 } 714 }
721 715
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 19b98ca468eb..86b3169c8cac 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -51,7 +51,7 @@ char *nfs_path(const char *base, const struct dentry *dentry,
51 namelen = dentry->d_name.len; 51 namelen = dentry->d_name.len;
52 buflen -= namelen + 1; 52 buflen -= namelen + 1;
53 if (buflen < 0) 53 if (buflen < 0)
54 goto Elong; 54 goto Elong_unlock;
55 end -= namelen; 55 end -= namelen;
56 memcpy(end, dentry->d_name.name, namelen); 56 memcpy(end, dentry->d_name.name, namelen);
57 *--end = '/'; 57 *--end = '/';
@@ -68,6 +68,8 @@ char *nfs_path(const char *base, const struct dentry *dentry,
68 end -= namelen; 68 end -= namelen;
69 memcpy(end, base, namelen); 69 memcpy(end, base, namelen);
70 return end; 70 return end;
71Elong_unlock:
72 spin_unlock(&dcache_lock);
71Elong: 73Elong:
72 return ERR_PTR(-ENAMETOOLONG); 74 return ERR_PTR(-ENAMETOOLONG);
73} 75}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 52bf634260a1..65c0c5b32351 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -63,7 +63,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
63 return p; 63 return p;
64} 64}
65 65
66void nfs_readdata_free(struct nfs_read_data *p) 66static void nfs_readdata_free(struct nfs_read_data *p)
67{ 67{
68 if (p && (p->pagevec != &p->page_array[0])) 68 if (p && (p->pagevec != &p->page_array[0]))
69 kfree(p->pagevec); 69 kfree(p->pagevec);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 86bac6a5008e..50774991f8d5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -137,7 +137,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
137 return p; 137 return p;
138} 138}
139 139
140void nfs_writedata_free(struct nfs_write_data *p) 140static void nfs_writedata_free(struct nfs_write_data *p)
141{ 141{
142 if (p && (p->pagevec != &p->page_array[0])) 142 if (p && (p->pagevec != &p->page_array[0]))
143 kfree(p->pagevec); 143 kfree(p->pagevec);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index aa4fe905bb4d..0d92c468d55a 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -123,7 +123,6 @@ struct nlm_block {
123 unsigned int b_id; /* block id */ 123 unsigned int b_id; /* block id */
124 unsigned char b_queued; /* re-queued */ 124 unsigned char b_queued; /* re-queued */
125 unsigned char b_granted; /* VFS granted lock */ 125 unsigned char b_granted; /* VFS granted lock */
126 unsigned char b_done; /* callback complete */
127 struct nlm_file * b_file; /* file in question */ 126 struct nlm_file * b_file; /* file in question */
128}; 127};
129 128
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 55ea853d57bc..247434553ae8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -476,10 +476,9 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
476} 476}
477 477
478/* 478/*
479 * Allocate and free nfs_write_data structures 479 * Allocate nfs_write_data structures
480 */ 480 */
481extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); 481extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
482extern void nfs_writedata_free(struct nfs_write_data *p);
483 482
484/* 483/*
485 * linux/fs/nfs/read.c 484 * linux/fs/nfs/read.c
@@ -491,10 +490,9 @@ extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
491extern void nfs_readdata_release(void *data); 490extern void nfs_readdata_release(void *data);
492 491
493/* 492/*
494 * Allocate and free nfs_read_data structures 493 * Allocate nfs_read_data structures
495 */ 494 */
496extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); 495extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
497extern void nfs_readdata_free(struct nfs_read_data *p);
498 496
499/* 497/*
500 * linux/fs/nfs3proc.c 498 * linux/fs/nfs3proc.c
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e8bbe8118de8..840e47a4ccc5 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -229,7 +229,7 @@ int xprt_reserve_xprt(struct rpc_task *task);
229int xprt_reserve_xprt_cong(struct rpc_task *task); 229int xprt_reserve_xprt_cong(struct rpc_task *task);
230int xprt_prepare_transmit(struct rpc_task *task); 230int xprt_prepare_transmit(struct rpc_task *task);
231void xprt_transmit(struct rpc_task *task); 231void xprt_transmit(struct rpc_task *task);
232void xprt_abort_transmit(struct rpc_task *task); 232void xprt_end_transmit(struct rpc_task *task);
233int xprt_adjust_timeout(struct rpc_rqst *req); 233int xprt_adjust_timeout(struct rpc_rqst *req);
234void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); 234void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
235void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); 235void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4ba271f892c8..d6409e757219 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task)
921 task->tk_status = xprt_prepare_transmit(task); 921 task->tk_status = xprt_prepare_transmit(task);
922 if (task->tk_status != 0) 922 if (task->tk_status != 0)
923 return; 923 return;
924 task->tk_action = call_transmit_status;
924 /* Encode here so that rpcsec_gss can use correct sequence number. */ 925 /* Encode here so that rpcsec_gss can use correct sequence number. */
925 if (rpc_task_need_encode(task)) { 926 if (rpc_task_need_encode(task)) {
926 task->tk_rqstp->rq_bytes_sent = 0; 927 BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
927 call_encode(task); 928 call_encode(task);
928 /* Did the encode result in an error condition? */ 929 /* Did the encode result in an error condition? */
929 if (task->tk_status != 0) 930 if (task->tk_status != 0)
930 goto out_nosend; 931 return;
931 } 932 }
932 task->tk_action = call_transmit_status;
933 xprt_transmit(task); 933 xprt_transmit(task);
934 if (task->tk_status < 0) 934 if (task->tk_status < 0)
935 return; 935 return;
936 if (!task->tk_msg.rpc_proc->p_decode) { 936 /*
937 task->tk_action = rpc_exit_task; 937 * On success, ensure that we call xprt_end_transmit() before sleeping
938 rpc_wake_up_task(task); 938 * in order to allow access to the socket to other RPC requests.
939 } 939 */
940 return; 940 call_transmit_status(task);
941out_nosend: 941 if (task->tk_msg.rpc_proc->p_decode != NULL)
942 /* release socket write lock before attempting to handle error */ 942 return;
943 xprt_abort_transmit(task); 943 task->tk_action = rpc_exit_task;
944 rpc_wake_up_task(task);
945}
946
947/*
948 * 5a. Handle cleanup after a transmission
949 */
950static void
951call_transmit_status(struct rpc_task *task)
952{
953 task->tk_action = call_status;
954 /*
955 * Special case: if we've been waiting on the socket's write_space()
956 * callback, then don't call xprt_end_transmit().
957 */
958 if (task->tk_status == -EAGAIN)
959 return;
960 xprt_end_transmit(task);
944 rpc_task_force_reencode(task); 961 rpc_task_force_reencode(task);
945} 962}
946 963
@@ -992,18 +1009,7 @@ call_status(struct rpc_task *task)
992} 1009}
993 1010
994/* 1011/*
995 * 6a. Handle transmission errors. 1012 * 6a. Handle RPC timeout
996 */
997static void
998call_transmit_status(struct rpc_task *task)
999{
1000 if (task->tk_status != -EAGAIN)
1001 rpc_task_force_reencode(task);
1002 call_status(task);
1003}
1004
1005/*
1006 * 6b. Handle RPC timeout
1007 * We do not release the request slot, so we keep using the 1013 * We do not release the request slot, so we keep using the
1008 * same XID for all retransmits. 1014 * same XID for all retransmits.
1009 */ 1015 */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dc6cb93c8830..a3bd2db2e024 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -667,10 +667,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
667 RPCAUTH_info, RPCAUTH_EOF); 667 RPCAUTH_info, RPCAUTH_EOF);
668 if (error) 668 if (error)
669 goto err_depopulate; 669 goto err_depopulate;
670 dget(dentry);
670out: 671out:
671 mutex_unlock(&dir->i_mutex); 672 mutex_unlock(&dir->i_mutex);
672 rpc_release_path(&nd); 673 rpc_release_path(&nd);
673 return dget(dentry); 674 return dentry;
674err_depopulate: 675err_depopulate:
675 rpc_depopulate(dentry); 676 rpc_depopulate(dentry);
676 __rpc_rmdir(dir, dentry); 677 __rpc_rmdir(dir, dentry);
@@ -731,10 +732,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
731 rpci->flags = flags; 732 rpci->flags = flags;
732 rpci->ops = ops; 733 rpci->ops = ops;
733 inode_dir_notify(dir, DN_CREATE); 734 inode_dir_notify(dir, DN_CREATE);
735 dget(dentry);
734out: 736out:
735 mutex_unlock(&dir->i_mutex); 737 mutex_unlock(&dir->i_mutex);
736 rpc_release_path(&nd); 738 rpc_release_path(&nd);
737 return dget(dentry); 739 return dentry;
738err_dput: 740err_dput:
739 dput(dentry); 741 dput(dentry);
740 dentry = ERR_PTR(-ENOMEM); 742 dentry = ERR_PTR(-ENOMEM);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 313b68d892c6..e8c2bc4977f3 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -707,12 +707,9 @@ out_unlock:
707 return err; 707 return err;
708} 708}
709 709
710void 710void xprt_end_transmit(struct rpc_task *task)
711xprt_abort_transmit(struct rpc_task *task)
712{ 711{
713 struct rpc_xprt *xprt = task->tk_xprt; 712 xprt_release_write(task->tk_xprt, task);
714
715 xprt_release_write(xprt, task);
716} 713}
717 714
718/** 715/**
@@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task)
761 task->tk_status = -ENOTCONN; 758 task->tk_status = -ENOTCONN;
762 else if (!req->rq_received) 759 else if (!req->rq_received)
763 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); 760 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
764
765 xprt->ops->release_xprt(xprt, task);
766 spin_unlock_bh(&xprt->transport_lock); 761 spin_unlock_bh(&xprt->transport_lock);
767 return; 762 return;
768 } 763 }
@@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task)
772 * schedq, and being picked up by a parallel run of rpciod(). 767 * schedq, and being picked up by a parallel run of rpciod().
773 */ 768 */
774 task->tk_status = status; 769 task->tk_status = status;
775 770 if (status == -ECONNREFUSED)
776 switch (status) {
777 case -ECONNREFUSED:
778 rpc_sleep_on(&xprt->sending, task, NULL, NULL); 771 rpc_sleep_on(&xprt->sending, task, NULL, NULL);
779 case -EAGAIN:
780 case -ENOTCONN:
781 return;
782 default:
783 break;
784 }
785 xprt_release_write(xprt, task);
786 return;
787} 772}
788 773
789static inline void do_xprt_reserve(struct rpc_task *task) 774static inline void do_xprt_reserve(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ee678ed13b6f..441bd53f5eca 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
414} 414}
415 415
416/** 416/**
417 * xs_tcp_release_xprt - clean up after a tcp transmission
418 * @xprt: transport
419 * @task: rpc task
420 *
421 * This cleans up if an error causes us to abort the transmission of a request.
422 * In this case, the socket may need to be reset in order to avoid confusing
423 * the server.
424 */
425static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
426{
427 struct rpc_rqst *req;
428
429 if (task != xprt->snd_task)
430 return;
431 if (task == NULL)
432 goto out_release;
433 req = task->tk_rqstp;
434 if (req->rq_bytes_sent == 0)
435 goto out_release;
436 if (req->rq_bytes_sent == req->rq_snd_buf.len)
437 goto out_release;
438 set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
439out_release:
440 xprt_release_xprt(xprt, task);
441}
442
443/**
417 * xs_close - close a socket 444 * xs_close - close a socket
418 * @xprt: transport 445 * @xprt: transport
419 * 446 *
@@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
1250 1277
1251static struct rpc_xprt_ops xs_tcp_ops = { 1278static struct rpc_xprt_ops xs_tcp_ops = {
1252 .reserve_xprt = xprt_reserve_xprt, 1279 .reserve_xprt = xprt_reserve_xprt,
1253 .release_xprt = xprt_release_xprt, 1280 .release_xprt = xs_tcp_release_xprt,
1254 .set_port = xs_set_port, 1281 .set_port = xs_set_port,
1255 .connect = xs_connect, 1282 .connect = xs_connect,
1256 .buf_alloc = rpc_malloc, 1283 .buf_alloc = rpc_malloc,