aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-04-11 01:54:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:48 -0400
commitd713311464bcca73c990d1a1b5c9467eae87f5b4 (patch)
treed049e9655bebed5212cd3534961d354e51c2769f /fs
parent0720b315976447cba3f0c3e211223b8cb82b0f93 (diff)
[PATCH] fuse: use a per-mount spinlock
Remove the global spinlock in favor of a per-mount one. This patch is basically find & replace. The difficult part has already been done by the previous patch. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c122
-rw-r--r--fs/fuse/fuse_i.h24
-rw-r--r--fs/fuse/inode.c12
3 files changed, 74 insertions, 84 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c510533c6849..63d2cf43b5e3 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1,6 +1,6 @@
1/* 1/*
2 FUSE: Filesystem in Userspace 2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu> 3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
4 4
5 This program can be distributed under the terms of the GNU GPL. 5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING. 6 See the file COPYING.
@@ -94,11 +94,11 @@ static struct fuse_req *do_get_request(struct fuse_conn *fc)
94{ 94{
95 struct fuse_req *req; 95 struct fuse_req *req;
96 96
97 spin_lock(&fuse_lock); 97 spin_lock(&fc->lock);
98 BUG_ON(list_empty(&fc->unused_list)); 98 BUG_ON(list_empty(&fc->unused_list));
99 req = list_entry(fc->unused_list.next, struct fuse_req, list); 99 req = list_entry(fc->unused_list.next, struct fuse_req, list);
100 list_del_init(&req->list); 100 list_del_init(&req->list);
101 spin_unlock(&fuse_lock); 101 spin_unlock(&fc->lock);
102 fuse_request_init(req); 102 fuse_request_init(req);
103 req->preallocated = 1; 103 req->preallocated = 1;
104 req->in.h.uid = current->fsuid; 104 req->in.h.uid = current->fsuid;
@@ -124,7 +124,7 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc)
124 return do_get_request(fc); 124 return do_get_request(fc);
125} 125}
126 126
127/* Must be called with fuse_lock held */ 127/* Must be called with fc->lock held */
128static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) 128static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
129{ 129{
130 if (req->preallocated) { 130 if (req->preallocated) {
@@ -143,9 +143,9 @@ static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
143void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 143void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
144{ 144{
145 if (atomic_dec_and_test(&req->count)) { 145 if (atomic_dec_and_test(&req->count)) {
146 spin_lock(&fuse_lock); 146 spin_lock(&fc->lock);
147 fuse_putback_request(fc, req); 147 fuse_putback_request(fc, req);
148 spin_unlock(&fuse_lock); 148 spin_unlock(&fc->lock);
149 } 149 }
150} 150}
151 151
@@ -155,15 +155,15 @@ static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
155 fuse_putback_request(fc, req); 155 fuse_putback_request(fc, req);
156} 156}
157 157
158void fuse_release_background(struct fuse_req *req) 158void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
159{ 159{
160 iput(req->inode); 160 iput(req->inode);
161 iput(req->inode2); 161 iput(req->inode2);
162 if (req->file) 162 if (req->file)
163 fput(req->file); 163 fput(req->file);
164 spin_lock(&fuse_lock); 164 spin_lock(&fc->lock);
165 list_del(&req->bg_entry); 165 list_del(&req->bg_entry);
166 spin_unlock(&fuse_lock); 166 spin_unlock(&fc->lock);
167} 167}
168 168
169/* 169/*
@@ -182,7 +182,7 @@ void fuse_release_background(struct fuse_req *req)
182 * interrupted and put in the background, it will return with an error 182 * interrupted and put in the background, it will return with an error
183 * and hence never be reset and reused. 183 * and hence never be reset and reused.
184 * 184 *
185 * Called with fuse_lock, unlocks it 185 * Called with fc->lock, unlocks it
186 */ 186 */
187static void request_end(struct fuse_conn *fc, struct fuse_req *req) 187static void request_end(struct fuse_conn *fc, struct fuse_req *req)
188{ 188{
@@ -191,14 +191,14 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
191 if (!req->background) { 191 if (!req->background) {
192 wake_up(&req->waitq); 192 wake_up(&req->waitq);
193 fuse_put_request_locked(fc, req); 193 fuse_put_request_locked(fc, req);
194 spin_unlock(&fuse_lock); 194 spin_unlock(&fc->lock);
195 } else { 195 } else {
196 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 196 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
197 req->end = NULL; 197 req->end = NULL;
198 spin_unlock(&fuse_lock); 198 spin_unlock(&fc->lock);
199 down_read(&fc->sbput_sem); 199 down_read(&fc->sbput_sem);
200 if (fc->mounted) 200 if (fc->mounted)
201 fuse_release_background(req); 201 fuse_release_background(fc, req);
202 up_read(&fc->sbput_sem); 202 up_read(&fc->sbput_sem);
203 if (end) 203 if (end)
204 end(fc, req); 204 end(fc, req);
@@ -248,16 +248,16 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
248 get_file(req->file); 248 get_file(req->file);
249} 249}
250 250
251/* Called with fuse_lock held. Releases, and then reacquires it. */ 251/* Called with fc->lock held. Releases, and then reacquires it. */
252static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 252static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
253{ 253{
254 sigset_t oldset; 254 sigset_t oldset;
255 255
256 spin_unlock(&fuse_lock); 256 spin_unlock(&fc->lock);
257 block_sigs(&oldset); 257 block_sigs(&oldset);
258 wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); 258 wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
259 restore_sigs(&oldset); 259 restore_sigs(&oldset);
260 spin_lock(&fuse_lock); 260 spin_lock(&fc->lock);
261 if (req->state == FUSE_REQ_FINISHED && !req->interrupted) 261 if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
262 return; 262 return;
263 263
@@ -271,9 +271,9 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
271 locked state, there mustn't be any filesystem 271 locked state, there mustn't be any filesystem
272 operation (e.g. page fault), since that could lead 272 operation (e.g. page fault), since that could lead
273 to deadlock */ 273 to deadlock */
274 spin_unlock(&fuse_lock); 274 spin_unlock(&fc->lock);
275 wait_event(req->waitq, !req->locked); 275 wait_event(req->waitq, !req->locked);
276 spin_lock(&fuse_lock); 276 spin_lock(&fc->lock);
277 } 277 }
278 if (req->state == FUSE_REQ_PENDING) { 278 if (req->state == FUSE_REQ_PENDING) {
279 list_del(&req->list); 279 list_del(&req->list);
@@ -324,7 +324,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
324void request_send(struct fuse_conn *fc, struct fuse_req *req) 324void request_send(struct fuse_conn *fc, struct fuse_req *req)
325{ 325{
326 req->isreply = 1; 326 req->isreply = 1;
327 spin_lock(&fuse_lock); 327 spin_lock(&fc->lock);
328 if (!fc->connected) 328 if (!fc->connected)
329 req->out.h.error = -ENOTCONN; 329 req->out.h.error = -ENOTCONN;
330 else if (fc->conn_error) 330 else if (fc->conn_error)
@@ -337,15 +337,15 @@ void request_send(struct fuse_conn *fc, struct fuse_req *req)
337 337
338 request_wait_answer(fc, req); 338 request_wait_answer(fc, req);
339 } 339 }
340 spin_unlock(&fuse_lock); 340 spin_unlock(&fc->lock);
341} 341}
342 342
343static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 343static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
344{ 344{
345 spin_lock(&fuse_lock); 345 spin_lock(&fc->lock);
346 if (fc->connected) { 346 if (fc->connected) {
347 queue_request(fc, req); 347 queue_request(fc, req);
348 spin_unlock(&fuse_lock); 348 spin_unlock(&fc->lock);
349 } else { 349 } else {
350 req->out.h.error = -ENOTCONN; 350 req->out.h.error = -ENOTCONN;
351 request_end(fc, req); 351 request_end(fc, req);
@@ -361,9 +361,9 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
361void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 361void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
362{ 362{
363 req->isreply = 1; 363 req->isreply = 1;
364 spin_lock(&fuse_lock); 364 spin_lock(&fc->lock);
365 background_request(fc, req); 365 background_request(fc, req);
366 spin_unlock(&fuse_lock); 366 spin_unlock(&fc->lock);
367 request_send_nowait(fc, req); 367 request_send_nowait(fc, req);
368} 368}
369 369
@@ -372,16 +372,16 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
372 * anything that could cause a page-fault. If the request was already 372 * anything that could cause a page-fault. If the request was already
373 * interrupted bail out. 373 * interrupted bail out.
374 */ 374 */
375static int lock_request(struct fuse_req *req) 375static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
376{ 376{
377 int err = 0; 377 int err = 0;
378 if (req) { 378 if (req) {
379 spin_lock(&fuse_lock); 379 spin_lock(&fc->lock);
380 if (req->interrupted) 380 if (req->interrupted)
381 err = -ENOENT; 381 err = -ENOENT;
382 else 382 else
383 req->locked = 1; 383 req->locked = 1;
384 spin_unlock(&fuse_lock); 384 spin_unlock(&fc->lock);
385 } 385 }
386 return err; 386 return err;
387} 387}
@@ -391,18 +391,19 @@ static int lock_request(struct fuse_req *req)
391 * requester thread is currently waiting for it to be unlocked, so 391 * requester thread is currently waiting for it to be unlocked, so
392 * wake it up. 392 * wake it up.
393 */ 393 */
394static void unlock_request(struct fuse_req *req) 394static void unlock_request(struct fuse_conn *fc, struct fuse_req *req)
395{ 395{
396 if (req) { 396 if (req) {
397 spin_lock(&fuse_lock); 397 spin_lock(&fc->lock);
398 req->locked = 0; 398 req->locked = 0;
399 if (req->interrupted) 399 if (req->interrupted)
400 wake_up(&req->waitq); 400 wake_up(&req->waitq);
401 spin_unlock(&fuse_lock); 401 spin_unlock(&fc->lock);
402 } 402 }
403} 403}
404 404
405struct fuse_copy_state { 405struct fuse_copy_state {
406 struct fuse_conn *fc;
406 int write; 407 int write;
407 struct fuse_req *req; 408 struct fuse_req *req;
408 const struct iovec *iov; 409 const struct iovec *iov;
@@ -415,11 +416,12 @@ struct fuse_copy_state {
415 unsigned len; 416 unsigned len;
416}; 417};
417 418
418static void fuse_copy_init(struct fuse_copy_state *cs, int write, 419static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
419 struct fuse_req *req, const struct iovec *iov, 420 int write, struct fuse_req *req,
420 unsigned long nr_segs) 421 const struct iovec *iov, unsigned long nr_segs)
421{ 422{
422 memset(cs, 0, sizeof(*cs)); 423 memset(cs, 0, sizeof(*cs));
424 cs->fc = fc;
423 cs->write = write; 425 cs->write = write;
424 cs->req = req; 426 cs->req = req;
425 cs->iov = iov; 427 cs->iov = iov;
@@ -449,7 +451,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
449 unsigned long offset; 451 unsigned long offset;
450 int err; 452 int err;
451 453
452 unlock_request(cs->req); 454 unlock_request(cs->fc, cs->req);
453 fuse_copy_finish(cs); 455 fuse_copy_finish(cs);
454 if (!cs->seglen) { 456 if (!cs->seglen) {
455 BUG_ON(!cs->nr_segs); 457 BUG_ON(!cs->nr_segs);
@@ -472,7 +474,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
472 cs->seglen -= cs->len; 474 cs->seglen -= cs->len;
473 cs->addr += cs->len; 475 cs->addr += cs->len;
474 476
475 return lock_request(cs->req); 477 return lock_request(cs->fc, cs->req);
476} 478}
477 479
478/* Do as much copy to/from userspace buffer as we can */ 480/* Do as much copy to/from userspace buffer as we can */
@@ -584,9 +586,9 @@ static void request_wait(struct fuse_conn *fc)
584 if (signal_pending(current)) 586 if (signal_pending(current))
585 break; 587 break;
586 588
587 spin_unlock(&fuse_lock); 589 spin_unlock(&fc->lock);
588 schedule(); 590 schedule();
589 spin_lock(&fuse_lock); 591 spin_lock(&fc->lock);
590 } 592 }
591 set_current_state(TASK_RUNNING); 593 set_current_state(TASK_RUNNING);
592 remove_wait_queue(&fc->waitq, &wait); 594 remove_wait_queue(&fc->waitq, &wait);
@@ -614,7 +616,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
614 return -EPERM; 616 return -EPERM;
615 617
616 restart: 618 restart:
617 spin_lock(&fuse_lock); 619 spin_lock(&fc->lock);
618 err = -EAGAIN; 620 err = -EAGAIN;
619 if ((file->f_flags & O_NONBLOCK) && fc->connected && 621 if ((file->f_flags & O_NONBLOCK) && fc->connected &&
620 list_empty(&fc->pending)) 622 list_empty(&fc->pending))
@@ -643,14 +645,14 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
643 request_end(fc, req); 645 request_end(fc, req);
644 goto restart; 646 goto restart;
645 } 647 }
646 spin_unlock(&fuse_lock); 648 spin_unlock(&fc->lock);
647 fuse_copy_init(&cs, 1, req, iov, nr_segs); 649 fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);
648 err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 650 err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
649 if (!err) 651 if (!err)
650 err = fuse_copy_args(&cs, in->numargs, in->argpages, 652 err = fuse_copy_args(&cs, in->numargs, in->argpages,
651 (struct fuse_arg *) in->args, 0); 653 (struct fuse_arg *) in->args, 0);
652 fuse_copy_finish(&cs); 654 fuse_copy_finish(&cs);
653 spin_lock(&fuse_lock); 655 spin_lock(&fc->lock);
654 req->locked = 0; 656 req->locked = 0;
655 if (!err && req->interrupted) 657 if (!err && req->interrupted)
656 err = -ENOENT; 658 err = -ENOENT;
@@ -665,12 +667,12 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
665 else { 667 else {
666 req->state = FUSE_REQ_SENT; 668 req->state = FUSE_REQ_SENT;
667 list_move_tail(&req->list, &fc->processing); 669 list_move_tail(&req->list, &fc->processing);
668 spin_unlock(&fuse_lock); 670 spin_unlock(&fc->lock);
669 } 671 }
670 return reqsize; 672 return reqsize;
671 673
672 err_unlock: 674 err_unlock:
673 spin_unlock(&fuse_lock); 675 spin_unlock(&fc->lock);
674 return err; 676 return err;
675} 677}
676 678
@@ -739,7 +741,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
739 if (!fc) 741 if (!fc)
740 return -ENODEV; 742 return -ENODEV;
741 743
742 fuse_copy_init(&cs, 0, NULL, iov, nr_segs); 744 fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs);
743 if (nbytes < sizeof(struct fuse_out_header)) 745 if (nbytes < sizeof(struct fuse_out_header))
744 return -EINVAL; 746 return -EINVAL;
745 747
@@ -751,7 +753,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
751 oh.len != nbytes) 753 oh.len != nbytes)
752 goto err_finish; 754 goto err_finish;
753 755
754 spin_lock(&fuse_lock); 756 spin_lock(&fc->lock);
755 err = -ENOENT; 757 err = -ENOENT;
756 if (!fc->connected) 758 if (!fc->connected)
757 goto err_unlock; 759 goto err_unlock;
@@ -762,9 +764,9 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
762 goto err_unlock; 764 goto err_unlock;
763 765
764 if (req->interrupted) { 766 if (req->interrupted) {
765 spin_unlock(&fuse_lock); 767 spin_unlock(&fc->lock);
766 fuse_copy_finish(&cs); 768 fuse_copy_finish(&cs);
767 spin_lock(&fuse_lock); 769 spin_lock(&fc->lock);
768 request_end(fc, req); 770 request_end(fc, req);
769 return -ENOENT; 771 return -ENOENT;
770 } 772 }
@@ -772,12 +774,12 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
772 req->out.h = oh; 774 req->out.h = oh;
773 req->locked = 1; 775 req->locked = 1;
774 cs.req = req; 776 cs.req = req;
775 spin_unlock(&fuse_lock); 777 spin_unlock(&fc->lock);
776 778
777 err = copy_out_args(&cs, &req->out, nbytes); 779 err = copy_out_args(&cs, &req->out, nbytes);
778 fuse_copy_finish(&cs); 780 fuse_copy_finish(&cs);
779 781
780 spin_lock(&fuse_lock); 782 spin_lock(&fc->lock);
781 req->locked = 0; 783 req->locked = 0;
782 if (!err) { 784 if (!err) {
783 if (req->interrupted) 785 if (req->interrupted)
@@ -789,7 +791,7 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
789 return err ? err : nbytes; 791 return err ? err : nbytes;
790 792
791 err_unlock: 793 err_unlock:
792 spin_unlock(&fuse_lock); 794 spin_unlock(&fc->lock);
793 err_finish: 795 err_finish:
794 fuse_copy_finish(&cs); 796 fuse_copy_finish(&cs);
795 return err; 797 return err;
@@ -813,12 +815,12 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
813 815
814 poll_wait(file, &fc->waitq, wait); 816 poll_wait(file, &fc->waitq, wait);
815 817
816 spin_lock(&fuse_lock); 818 spin_lock(&fc->lock);
817 if (!fc->connected) 819 if (!fc->connected)
818 mask = POLLERR; 820 mask = POLLERR;
819 else if (!list_empty(&fc->pending)) 821 else if (!list_empty(&fc->pending))
820 mask |= POLLIN | POLLRDNORM; 822 mask |= POLLIN | POLLRDNORM;
821 spin_unlock(&fuse_lock); 823 spin_unlock(&fc->lock);
822 824
823 return mask; 825 return mask;
824} 826}
@@ -826,7 +828,7 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
826/* 828/*
827 * Abort all requests on the given list (pending or processing) 829 * Abort all requests on the given list (pending or processing)
828 * 830 *
829 * This function releases and reacquires fuse_lock 831 * This function releases and reacquires fc->lock
830 */ 832 */
831static void end_requests(struct fuse_conn *fc, struct list_head *head) 833static void end_requests(struct fuse_conn *fc, struct list_head *head)
832{ 834{
@@ -835,7 +837,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
835 req = list_entry(head->next, struct fuse_req, list); 837 req = list_entry(head->next, struct fuse_req, list);
836 req->out.h.error = -ECONNABORTED; 838 req->out.h.error = -ECONNABORTED;
837 request_end(fc, req); 839 request_end(fc, req);
838 spin_lock(&fuse_lock); 840 spin_lock(&fc->lock);
839 } 841 }
840} 842}
841 843
@@ -866,10 +868,10 @@ static void end_io_requests(struct fuse_conn *fc)
866 req->end = NULL; 868 req->end = NULL;
867 /* The end function will consume this reference */ 869 /* The end function will consume this reference */
868 __fuse_get_request(req); 870 __fuse_get_request(req);
869 spin_unlock(&fuse_lock); 871 spin_unlock(&fc->lock);
870 wait_event(req->waitq, !req->locked); 872 wait_event(req->waitq, !req->locked);
871 end(fc, req); 873 end(fc, req);
872 spin_lock(&fuse_lock); 874 spin_lock(&fc->lock);
873 } 875 }
874 } 876 }
875} 877}
@@ -896,7 +898,7 @@ static void end_io_requests(struct fuse_conn *fc)
896 */ 898 */
897void fuse_abort_conn(struct fuse_conn *fc) 899void fuse_abort_conn(struct fuse_conn *fc)
898{ 900{
899 spin_lock(&fuse_lock); 901 spin_lock(&fc->lock);
900 if (fc->connected) { 902 if (fc->connected) {
901 fc->connected = 0; 903 fc->connected = 0;
902 end_io_requests(fc); 904 end_io_requests(fc);
@@ -905,18 +907,18 @@ void fuse_abort_conn(struct fuse_conn *fc)
905 wake_up_all(&fc->waitq); 907 wake_up_all(&fc->waitq);
906 kill_fasync(&fc->fasync, SIGIO, POLL_IN); 908 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
907 } 909 }
908 spin_unlock(&fuse_lock); 910 spin_unlock(&fc->lock);
909} 911}
910 912
911static int fuse_dev_release(struct inode *inode, struct file *file) 913static int fuse_dev_release(struct inode *inode, struct file *file)
912{ 914{
913 struct fuse_conn *fc = fuse_get_conn(file); 915 struct fuse_conn *fc = fuse_get_conn(file);
914 if (fc) { 916 if (fc) {
915 spin_lock(&fuse_lock); 917 spin_lock(&fc->lock);
916 fc->connected = 0; 918 fc->connected = 0;
917 end_requests(fc, &fc->pending); 919 end_requests(fc, &fc->pending);
918 end_requests(fc, &fc->processing); 920 end_requests(fc, &fc->processing);
919 spin_unlock(&fuse_lock); 921 spin_unlock(&fc->lock);
920 fasync_helper(-1, file, 0, &fc->fasync); 922 fasync_helper(-1, file, 0, &fc->fasync);
921 kobject_put(&fc->kobj); 923 kobject_put(&fc->kobj);
922 } 924 }
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e5cb46b78437..6ed812fd6200 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1,6 +1,6 @@
1/* 1/*
2 FUSE: Filesystem in Userspace 2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu> 3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
4 4
5 This program can be distributed under the terms of the GNU GPL. 5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING. 6 See the file COPYING.
@@ -144,7 +144,7 @@ struct fuse_req {
144 /* 144 /*
145 * The following bitfields are either set once before the 145 * The following bitfields are either set once before the
146 * request is queued or setting/clearing them is protected by 146 * request is queued or setting/clearing them is protected by
147 * fuse_lock 147 * fuse_conn->lock
148 */ 148 */
149 149
150 /** True if the request has reply */ 150 /** True if the request has reply */
@@ -213,6 +213,9 @@ struct fuse_req {
213 * unmounted. 213 * unmounted.
214 */ 214 */
215struct fuse_conn { 215struct fuse_conn {
216 /** Lock protecting accessess to members of this structure */
217 spinlock_t lock;
218
216 /** The user id for this mount */ 219 /** The user id for this mount */
217 uid_t user_id; 220 uid_t user_id;
218 221
@@ -352,21 +355,6 @@ static inline u64 get_node_id(struct inode *inode)
352extern const struct file_operations fuse_dev_operations; 355extern const struct file_operations fuse_dev_operations;
353 356
354/** 357/**
355 * This is the single global spinlock which protects FUSE's structures
356 *
357 * The following data is protected by this lock:
358 *
359 * - the private_data field of the device file
360 * - the s_fs_info field of the super block
361 * - unused_list, pending, processing lists in fuse_conn
362 * - background list in fuse_conn
363 * - the unique request ID counter reqctr in fuse_conn
364 * - the sb (super_block) field in fuse_conn
365 * - the file (device file) field in fuse_conn
366 */
367extern spinlock_t fuse_lock;
368
369/**
370 * Get a filled in inode 358 * Get a filled in inode
371 */ 359 */
372struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, 360struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
@@ -490,7 +478,7 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
490/** 478/**
491 * Release inodes and file associated with background request 479 * Release inodes and file associated with background request
492 */ 480 */
493void fuse_release_background(struct fuse_req *req); 481void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req);
494 482
495/* Abort all requests */ 483/* Abort all requests */
496void fuse_abort_conn(struct fuse_conn *fc); 484void fuse_abort_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 620579a69107..cc58debeabd4 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1,6 +1,6 @@
1/* 1/*
2 FUSE: Filesystem in Userspace 2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu> 3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
4 4
5 This program can be distributed under the terms of the GNU GPL. 5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING. 6 See the file COPYING.
@@ -22,7 +22,6 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
22MODULE_DESCRIPTION("Filesystem in Userspace"); 22MODULE_DESCRIPTION("Filesystem in Userspace");
23MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
24 24
25spinlock_t fuse_lock;
26static kmem_cache_t *fuse_inode_cachep; 25static kmem_cache_t *fuse_inode_cachep;
27static struct subsystem connections_subsys; 26static struct subsystem connections_subsys;
28 27
@@ -207,13 +206,14 @@ static void fuse_put_super(struct super_block *sb)
207 206
208 down_write(&fc->sbput_sem); 207 down_write(&fc->sbput_sem);
209 while (!list_empty(&fc->background)) 208 while (!list_empty(&fc->background))
210 fuse_release_background(list_entry(fc->background.next, 209 fuse_release_background(fc,
210 list_entry(fc->background.next,
211 struct fuse_req, bg_entry)); 211 struct fuse_req, bg_entry));
212 212
213 spin_lock(&fuse_lock); 213 spin_lock(&fc->lock);
214 fc->mounted = 0; 214 fc->mounted = 0;
215 fc->connected = 0; 215 fc->connected = 0;
216 spin_unlock(&fuse_lock); 216 spin_unlock(&fc->lock);
217 up_write(&fc->sbput_sem); 217 up_write(&fc->sbput_sem);
218 /* Flush all readers on this fs */ 218 /* Flush all readers on this fs */
219 kill_fasync(&fc->fasync, SIGIO, POLL_IN); 219 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
@@ -388,6 +388,7 @@ static struct fuse_conn *new_conn(void)
388 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 388 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
389 if (fc) { 389 if (fc) {
390 int i; 390 int i;
391 spin_lock_init(&fc->lock);
391 init_waitqueue_head(&fc->waitq); 392 init_waitqueue_head(&fc->waitq);
392 INIT_LIST_HEAD(&fc->pending); 393 INIT_LIST_HEAD(&fc->pending);
393 INIT_LIST_HEAD(&fc->processing); 394 INIT_LIST_HEAD(&fc->processing);
@@ -734,7 +735,6 @@ static int __init fuse_init(void)
734 printk("fuse init (API version %i.%i)\n", 735 printk("fuse init (API version %i.%i)\n",
735 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); 736 FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
736 737
737 spin_lock_init(&fuse_lock);
738 res = fuse_fs_init(); 738 res = fuse_fs_init();
739 if (res) 739 if (res)
740 goto err; 740 goto err;