diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 19:14:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 19:14:02 -0400 |
commit | 8e9d2089723d08d51e66c5eea49253d76e27941e (patch) | |
tree | cf15609d5eeb0c1f3a39231d8ce793d3c8ad0ed0 /fs | |
parent | ba1eb95cf3cc666769afe42eaa15a3a34ae82f94 (diff) | |
parent | 60aa49243d09afc873f082567d2e3c16634ced84 (diff) |
Merge branch 'bkl-removal' of git://git.lwn.net/linux-2.6
* 'bkl-removal' of git://git.lwn.net/linux-2.6:
Rationalize fasync return values
Move FASYNC bit handling to f_op->fasync()
Use f_lock to protect f_flags
Rename struct file->f_ep_lock
Diffstat (limited to 'fs')
-rw-r--r-- | fs/eventpoll.c | 12 | ||||
-rw-r--r-- | fs/fcntl.c | 33 | ||||
-rw-r--r-- | fs/file_table.c | 1 | ||||
-rw-r--r-- | fs/ioctl.c | 18 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 5 | ||||
-rw-r--r-- | fs/pipe.c | 16 |
6 files changed, 39 insertions, 46 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 011b9b8c90c6..c5c424f23fd5 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -417,10 +417,10 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) | |||
417 | ep_unregister_pollwait(ep, epi); | 417 | ep_unregister_pollwait(ep, epi); |
418 | 418 | ||
419 | /* Remove the current item from the list of epoll hooks */ | 419 | /* Remove the current item from the list of epoll hooks */ |
420 | spin_lock(&file->f_ep_lock); | 420 | spin_lock(&file->f_lock); |
421 | if (ep_is_linked(&epi->fllink)) | 421 | if (ep_is_linked(&epi->fllink)) |
422 | list_del_init(&epi->fllink); | 422 | list_del_init(&epi->fllink); |
423 | spin_unlock(&file->f_ep_lock); | 423 | spin_unlock(&file->f_lock); |
424 | 424 | ||
425 | rb_erase(&epi->rbn, &ep->rbr); | 425 | rb_erase(&epi->rbn, &ep->rbr); |
426 | 426 | ||
@@ -538,7 +538,7 @@ void eventpoll_release_file(struct file *file) | |||
538 | struct epitem *epi; | 538 | struct epitem *epi; |
539 | 539 | ||
540 | /* | 540 | /* |
541 | * We don't want to get "file->f_ep_lock" because it is not | 541 | * We don't want to get "file->f_lock" because it is not |
542 | * necessary. It is not necessary because we're in the "struct file" | 542 | * necessary. It is not necessary because we're in the "struct file" |
543 | * cleanup path, and this means that noone is using this file anymore. | 543 | * cleanup path, and this means that noone is using this file anymore. |
544 | * So, for example, epoll_ctl() cannot hit here sicne if we reach this | 544 | * So, for example, epoll_ctl() cannot hit here sicne if we reach this |
@@ -547,6 +547,8 @@ void eventpoll_release_file(struct file *file) | |||
547 | * will correctly serialize the operation. We do need to acquire | 547 | * will correctly serialize the operation. We do need to acquire |
548 | * "ep->mtx" after "epmutex" because ep_remove() requires it when called | 548 | * "ep->mtx" after "epmutex" because ep_remove() requires it when called |
549 | * from anywhere but ep_free(). | 549 | * from anywhere but ep_free(). |
550 | * | ||
551 | * Besides, ep_remove() acquires the lock, so we can't hold it here. | ||
550 | */ | 552 | */ |
551 | mutex_lock(&epmutex); | 553 | mutex_lock(&epmutex); |
552 | 554 | ||
@@ -785,9 +787,9 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, | |||
785 | goto error_unregister; | 787 | goto error_unregister; |
786 | 788 | ||
787 | /* Add the current item to the list of active epoll hook for this file */ | 789 | /* Add the current item to the list of active epoll hook for this file */ |
788 | spin_lock(&tfile->f_ep_lock); | 790 | spin_lock(&tfile->f_lock); |
789 | list_add_tail(&epi->fllink, &tfile->f_ep_links); | 791 | list_add_tail(&epi->fllink, &tfile->f_ep_links); |
790 | spin_unlock(&tfile->f_ep_lock); | 792 | spin_unlock(&tfile->f_lock); |
791 | 793 | ||
792 | /* | 794 | /* |
793 | * Add the current item to the RB tree. All RB tree operations are | 795 | * Add the current item to the RB tree. All RB tree operations are |
diff --git a/fs/fcntl.c b/fs/fcntl.c index bd215cc791da..d865ca66ccba 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -141,7 +141,7 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes) | |||
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
144 | #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) | 144 | #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) |
145 | 145 | ||
146 | static int setfl(int fd, struct file * filp, unsigned long arg) | 146 | static int setfl(int fd, struct file * filp, unsigned long arg) |
147 | { | 147 | { |
@@ -177,21 +177,21 @@ static int setfl(int fd, struct file * filp, unsigned long arg) | |||
177 | return error; | 177 | return error; |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * We still need a lock here for now to keep multiple FASYNC calls | 180 | * ->fasync() is responsible for setting the FASYNC bit. |
181 | * from racing with each other. | ||
182 | */ | 181 | */ |
183 | lock_kernel(); | 182 | if (((arg ^ filp->f_flags) & FASYNC) && filp->f_op && |
184 | if ((arg ^ filp->f_flags) & FASYNC) { | 183 | filp->f_op->fasync) { |
185 | if (filp->f_op && filp->f_op->fasync) { | 184 | error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); |
186 | error = filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0); | 185 | if (error < 0) |
187 | if (error < 0) | 186 | goto out; |
188 | goto out; | 187 | if (error > 0) |
189 | } | 188 | error = 0; |
190 | } | 189 | } |
191 | 190 | spin_lock(&filp->f_lock); | |
192 | filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); | 191 | filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); |
192 | spin_unlock(&filp->f_lock); | ||
193 | |||
193 | out: | 194 | out: |
194 | unlock_kernel(); | ||
195 | return error; | 195 | return error; |
196 | } | 196 | } |
197 | 197 | ||
@@ -516,7 +516,7 @@ static DEFINE_RWLOCK(fasync_lock); | |||
516 | static struct kmem_cache *fasync_cache __read_mostly; | 516 | static struct kmem_cache *fasync_cache __read_mostly; |
517 | 517 | ||
518 | /* | 518 | /* |
519 | * fasync_helper() is used by some character device drivers (mainly mice) | 519 | * fasync_helper() is used by almost all character device drivers |
520 | * to set up the fasync queue. It returns negative on error, 0 if it did | 520 | * to set up the fasync queue. It returns negative on error, 0 if it did |
521 | * no changes and positive if it added/deleted the entry. | 521 | * no changes and positive if it added/deleted the entry. |
522 | */ | 522 | */ |
@@ -555,6 +555,13 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap | |||
555 | result = 1; | 555 | result = 1; |
556 | } | 556 | } |
557 | out: | 557 | out: |
558 | /* Fix up FASYNC bit while still holding fasync_lock */ | ||
559 | spin_lock(&filp->f_lock); | ||
560 | if (on) | ||
561 | filp->f_flags |= FASYNC; | ||
562 | else | ||
563 | filp->f_flags &= ~FASYNC; | ||
564 | spin_unlock(&filp->f_lock); | ||
558 | write_unlock_irq(&fasync_lock); | 565 | write_unlock_irq(&fasync_lock); |
559 | return result; | 566 | return result; |
560 | } | 567 | } |
diff --git a/fs/file_table.c b/fs/file_table.c index da806aceae3f..b74a8e1da913 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -128,6 +128,7 @@ struct file *get_empty_filp(void) | |||
128 | atomic_long_set(&f->f_count, 1); | 128 | atomic_long_set(&f->f_count, 1); |
129 | rwlock_init(&f->f_owner.lock); | 129 | rwlock_init(&f->f_owner.lock); |
130 | f->f_cred = get_cred(cred); | 130 | f->f_cred = get_cred(cred); |
131 | spin_lock_init(&f->f_lock); | ||
131 | eventpoll_init_file(f); | 132 | eventpoll_init_file(f); |
132 | /* f->f_version: 0 */ | 133 | /* f->f_version: 0 */ |
133 | return f; | 134 | return f; |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 240ec63984cb..ac2d47e43926 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -404,10 +404,12 @@ static int ioctl_fionbio(struct file *filp, int __user *argp) | |||
404 | if (O_NONBLOCK != O_NDELAY) | 404 | if (O_NONBLOCK != O_NDELAY) |
405 | flag |= O_NDELAY; | 405 | flag |= O_NDELAY; |
406 | #endif | 406 | #endif |
407 | spin_lock(&filp->f_lock); | ||
407 | if (on) | 408 | if (on) |
408 | filp->f_flags |= flag; | 409 | filp->f_flags |= flag; |
409 | else | 410 | else |
410 | filp->f_flags &= ~flag; | 411 | filp->f_flags &= ~flag; |
412 | spin_unlock(&filp->f_lock); | ||
411 | return error; | 413 | return error; |
412 | } | 414 | } |
413 | 415 | ||
@@ -425,18 +427,12 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, | |||
425 | /* Did FASYNC state change ? */ | 427 | /* Did FASYNC state change ? */ |
426 | if ((flag ^ filp->f_flags) & FASYNC) { | 428 | if ((flag ^ filp->f_flags) & FASYNC) { |
427 | if (filp->f_op && filp->f_op->fasync) | 429 | if (filp->f_op && filp->f_op->fasync) |
430 | /* fasync() adjusts filp->f_flags */ | ||
428 | error = filp->f_op->fasync(fd, filp, on); | 431 | error = filp->f_op->fasync(fd, filp, on); |
429 | else | 432 | else |
430 | error = -ENOTTY; | 433 | error = -ENOTTY; |
431 | } | 434 | } |
432 | if (error) | 435 | return error < 0 ? error : 0; |
433 | return error; | ||
434 | |||
435 | if (on) | ||
436 | filp->f_flags |= FASYNC; | ||
437 | else | ||
438 | filp->f_flags &= ~FASYNC; | ||
439 | return error; | ||
440 | } | 436 | } |
441 | 437 | ||
442 | static int ioctl_fsfreeze(struct file *filp) | 438 | static int ioctl_fsfreeze(struct file *filp) |
@@ -499,17 +495,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
499 | break; | 495 | break; |
500 | 496 | ||
501 | case FIONBIO: | 497 | case FIONBIO: |
502 | /* BKL needed to avoid races tweaking f_flags */ | ||
503 | lock_kernel(); | ||
504 | error = ioctl_fionbio(filp, argp); | 498 | error = ioctl_fionbio(filp, argp); |
505 | unlock_kernel(); | ||
506 | break; | 499 | break; |
507 | 500 | ||
508 | case FIOASYNC: | 501 | case FIOASYNC: |
509 | /* BKL needed to avoid races tweaking f_flags */ | ||
510 | lock_kernel(); | ||
511 | error = ioctl_fioasync(fd, filp, argp); | 502 | error = ioctl_fioasync(fd, filp, argp); |
512 | unlock_kernel(); | ||
513 | break; | 503 | break; |
514 | 504 | ||
515 | case FIOQSIZE: | 505 | case FIOQSIZE: |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6e50aaa56ca2..c165a6403df0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -998,8 +998,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
998 | 998 | ||
999 | if (!EX_ISSYNC(exp)) | 999 | if (!EX_ISSYNC(exp)) |
1000 | stable = 0; | 1000 | stable = 0; |
1001 | if (stable && !EX_WGATHER(exp)) | 1001 | if (stable && !EX_WGATHER(exp)) { |
1002 | spin_lock(&file->f_lock); | ||
1002 | file->f_flags |= O_SYNC; | 1003 | file->f_flags |= O_SYNC; |
1004 | spin_unlock(&file->f_lock); | ||
1005 | } | ||
1003 | 1006 | ||
1004 | /* Write the data. */ | 1007 | /* Write the data. */ |
1005 | oldfs = get_fs(); set_fs(KERNEL_DS); | 1008 | oldfs = get_fs(); set_fs(KERNEL_DS); |
@@ -667,10 +667,7 @@ pipe_read_fasync(int fd, struct file *filp, int on) | |||
667 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); | 667 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); |
668 | mutex_unlock(&inode->i_mutex); | 668 | mutex_unlock(&inode->i_mutex); |
669 | 669 | ||
670 | if (retval < 0) | 670 | return retval; |
671 | return retval; | ||
672 | |||
673 | return 0; | ||
674 | } | 671 | } |
675 | 672 | ||
676 | 673 | ||
@@ -684,10 +681,7 @@ pipe_write_fasync(int fd, struct file *filp, int on) | |||
684 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); | 681 | retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); |
685 | mutex_unlock(&inode->i_mutex); | 682 | mutex_unlock(&inode->i_mutex); |
686 | 683 | ||
687 | if (retval < 0) | 684 | return retval; |
688 | return retval; | ||
689 | |||
690 | return 0; | ||
691 | } | 685 | } |
692 | 686 | ||
693 | 687 | ||
@@ -706,11 +700,7 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on) | |||
706 | fasync_helper(-1, filp, 0, &pipe->fasync_readers); | 700 | fasync_helper(-1, filp, 0, &pipe->fasync_readers); |
707 | } | 701 | } |
708 | mutex_unlock(&inode->i_mutex); | 702 | mutex_unlock(&inode->i_mutex); |
709 | 703 | return retval; | |
710 | if (retval < 0) | ||
711 | return retval; | ||
712 | |||
713 | return 0; | ||
714 | } | 704 | } |
715 | 705 | ||
716 | 706 | ||