diff options
| -rw-r--r-- | drivers/ata/libata-core.c | 3 | ||||
| -rw-r--r-- | fs/file.c | 56 | ||||
| -rw-r--r-- | fs/file_table.c | 1 | ||||
| -rw-r--r-- | fs/namei.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 8 | ||||
| -rw-r--r-- | fs/open.c | 4 | ||||
| -rw-r--r-- | fs/read_write.c | 40 | ||||
| -rw-r--r-- | include/linux/file.h | 27 | ||||
| -rw-r--r-- | include/linux/fs.h | 8 | ||||
| -rw-r--r-- | net/socket.c | 13 |
10 files changed, 108 insertions, 54 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 65d3f1b5966c..8cb2522d592a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -4225,8 +4225,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
| 4225 | 4225 | ||
| 4226 | /* devices that don't properly handle queued TRIM commands */ | 4226 | /* devices that don't properly handle queued TRIM commands */ |
| 4227 | { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4227 | { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4228 | { "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | 4228 | { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, |
| 4229 | { "Crucial_CT???M500SSD3", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, | ||
| 4230 | 4229 | ||
| 4231 | /* | 4230 | /* |
| 4232 | * Some WD SATA-I drives spin up and down erratically when the link | 4231 | * Some WD SATA-I drives spin up and down erratically when the link |
| @@ -683,35 +683,65 @@ EXPORT_SYMBOL(fget_raw); | |||
| 683 | * The fput_needed flag returned by fget_light should be passed to the | 683 | * The fput_needed flag returned by fget_light should be passed to the |
| 684 | * corresponding fput_light. | 684 | * corresponding fput_light. |
| 685 | */ | 685 | */ |
| 686 | struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) | 686 | static unsigned long __fget_light(unsigned int fd, fmode_t mask) |
| 687 | { | 687 | { |
| 688 | struct files_struct *files = current->files; | 688 | struct files_struct *files = current->files; |
| 689 | struct file *file; | 689 | struct file *file; |
| 690 | 690 | ||
| 691 | *fput_needed = 0; | ||
| 692 | if (atomic_read(&files->count) == 1) { | 691 | if (atomic_read(&files->count) == 1) { |
| 693 | file = __fcheck_files(files, fd); | 692 | file = __fcheck_files(files, fd); |
| 694 | if (file && (file->f_mode & mask)) | 693 | if (!file || unlikely(file->f_mode & mask)) |
| 695 | file = NULL; | 694 | return 0; |
| 695 | return (unsigned long)file; | ||
| 696 | } else { | 696 | } else { |
| 697 | file = __fget(fd, mask); | 697 | file = __fget(fd, mask); |
| 698 | if (file) | 698 | if (!file) |
| 699 | *fput_needed = 1; | 699 | return 0; |
| 700 | return FDPUT_FPUT | (unsigned long)file; | ||
| 700 | } | 701 | } |
| 701 | |||
| 702 | return file; | ||
| 703 | } | 702 | } |
| 704 | struct file *fget_light(unsigned int fd, int *fput_needed) | 703 | unsigned long __fdget(unsigned int fd) |
| 705 | { | 704 | { |
| 706 | return __fget_light(fd, FMODE_PATH, fput_needed); | 705 | return __fget_light(fd, FMODE_PATH); |
| 707 | } | 706 | } |
| 708 | EXPORT_SYMBOL(fget_light); | 707 | EXPORT_SYMBOL(__fdget); |
| 709 | 708 | ||
| 710 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | 709 | unsigned long __fdget_raw(unsigned int fd) |
| 711 | { | 710 | { |
| 712 | return __fget_light(fd, 0, fput_needed); | 711 | return __fget_light(fd, 0); |
| 712 | } | ||
| 713 | |||
| 714 | unsigned long __fdget_pos(unsigned int fd) | ||
| 715 | { | ||
| 716 | struct files_struct *files = current->files; | ||
| 717 | struct file *file; | ||
| 718 | unsigned long v; | ||
| 719 | |||
| 720 | if (atomic_read(&files->count) == 1) { | ||
| 721 | file = __fcheck_files(files, fd); | ||
| 722 | v = 0; | ||
| 723 | } else { | ||
| 724 | file = __fget(fd, 0); | ||
| 725 | v = FDPUT_FPUT; | ||
| 726 | } | ||
| 727 | if (!file) | ||
| 728 | return 0; | ||
| 729 | |||
| 730 | if (file->f_mode & FMODE_ATOMIC_POS) { | ||
| 731 | if (file_count(file) > 1) { | ||
| 732 | v |= FDPUT_POS_UNLOCK; | ||
| 733 | mutex_lock(&file->f_pos_lock); | ||
| 734 | } | ||
| 735 | } | ||
| 736 | return v | (unsigned long)file; | ||
| 713 | } | 737 | } |
| 714 | 738 | ||
| 739 | /* | ||
| 740 | * We only lock f_pos if we have threads or if the file might be | ||
| 741 | * shared with another process. In both cases we'll have an elevated | ||
| 742 | * file count (done either by fdget() or by fork()). | ||
| 743 | */ | ||
| 744 | |||
| 715 | void set_close_on_exec(unsigned int fd, int flag) | 745 | void set_close_on_exec(unsigned int fd, int flag) |
| 716 | { | 746 | { |
| 717 | struct files_struct *files = current->files; | 747 | struct files_struct *files = current->files; |
diff --git a/fs/file_table.c b/fs/file_table.c index 5fff9030be34..5b24008ea4f6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -135,6 +135,7 @@ struct file *get_empty_filp(void) | |||
| 135 | atomic_long_set(&f->f_count, 1); | 135 | atomic_long_set(&f->f_count, 1); |
| 136 | rwlock_init(&f->f_owner.lock); | 136 | rwlock_init(&f->f_owner.lock); |
| 137 | spin_lock_init(&f->f_lock); | 137 | spin_lock_init(&f->f_lock); |
| 138 | mutex_init(&f->f_pos_lock); | ||
| 138 | eventpoll_init_file(f); | 139 | eventpoll_init_file(f); |
| 139 | /* f->f_version: 0 */ | 140 | /* f->f_version: 0 */ |
| 140 | return f; | 141 | return f; |
diff --git a/fs/namei.c b/fs/namei.c index 385f7817bfcc..2f730ef9b4b3 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -1884,7 +1884,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1884 | 1884 | ||
| 1885 | nd->path = f.file->f_path; | 1885 | nd->path = f.file->f_path; |
| 1886 | if (flags & LOOKUP_RCU) { | 1886 | if (flags & LOOKUP_RCU) { |
| 1887 | if (f.need_put) | 1887 | if (f.flags & FDPUT_FPUT) |
| 1888 | *fp = f.file; | 1888 | *fp = f.file; |
| 1889 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1889 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
| 1890 | rcu_read_lock(); | 1890 | rcu_read_lock(); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8450262bcf2a..51632c40e896 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2393,8 +2393,8 @@ out_dio: | |||
| 2393 | 2393 | ||
| 2394 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || | 2394 | if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || |
| 2395 | ((file->f_flags & O_DIRECT) && !direct_io)) { | 2395 | ((file->f_flags & O_DIRECT) && !direct_io)) { |
| 2396 | ret = filemap_fdatawrite_range(file->f_mapping, pos, | 2396 | ret = filemap_fdatawrite_range(file->f_mapping, *ppos, |
| 2397 | pos + count - 1); | 2397 | *ppos + count - 1); |
| 2398 | if (ret < 0) | 2398 | if (ret < 0) |
| 2399 | written = ret; | 2399 | written = ret; |
| 2400 | 2400 | ||
| @@ -2407,8 +2407,8 @@ out_dio: | |||
| 2407 | } | 2407 | } |
| 2408 | 2408 | ||
| 2409 | if (!ret) | 2409 | if (!ret) |
| 2410 | ret = filemap_fdatawait_range(file->f_mapping, pos, | 2410 | ret = filemap_fdatawait_range(file->f_mapping, *ppos, |
| 2411 | pos + count - 1); | 2411 | *ppos + count - 1); |
| 2412 | } | 2412 | } |
| 2413 | 2413 | ||
| 2414 | /* | 2414 | /* |
| @@ -705,6 +705,10 @@ static int do_dentry_open(struct file *f, | |||
| 705 | return 0; | 705 | return 0; |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ | ||
| 709 | if (S_ISREG(inode->i_mode)) | ||
| 710 | f->f_mode |= FMODE_ATOMIC_POS; | ||
| 711 | |||
| 708 | f->f_op = fops_get(inode->i_fop); | 712 | f->f_op = fops_get(inode->i_fop); |
| 709 | if (unlikely(WARN_ON(!f->f_op))) { | 713 | if (unlikely(WARN_ON(!f->f_op))) { |
| 710 | error = -ENODEV; | 714 | error = -ENODEV; |
diff --git a/fs/read_write.c b/fs/read_write.c index edc5746a902a..54e19b9392dc 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence) | |||
| 264 | } | 264 | } |
| 265 | EXPORT_SYMBOL(vfs_llseek); | 265 | EXPORT_SYMBOL(vfs_llseek); |
| 266 | 266 | ||
| 267 | static inline struct fd fdget_pos(int fd) | ||
| 268 | { | ||
| 269 | return __to_fd(__fdget_pos(fd)); | ||
| 270 | } | ||
| 271 | |||
| 272 | static inline void fdput_pos(struct fd f) | ||
| 273 | { | ||
| 274 | if (f.flags & FDPUT_POS_UNLOCK) | ||
| 275 | mutex_unlock(&f.file->f_pos_lock); | ||
| 276 | fdput(f); | ||
| 277 | } | ||
| 278 | |||
| 267 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) | 279 | SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) |
| 268 | { | 280 | { |
| 269 | off_t retval; | 281 | off_t retval; |
| 270 | struct fd f = fdget(fd); | 282 | struct fd f = fdget_pos(fd); |
| 271 | if (!f.file) | 283 | if (!f.file) |
| 272 | return -EBADF; | 284 | return -EBADF; |
| 273 | 285 | ||
| @@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence) | |||
| 278 | if (res != (loff_t)retval) | 290 | if (res != (loff_t)retval) |
| 279 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ | 291 | retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ |
| 280 | } | 292 | } |
| 281 | fdput(f); | 293 | fdput_pos(f); |
| 282 | return retval; | 294 | return retval; |
| 283 | } | 295 | } |
| 284 | 296 | ||
| @@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos) | |||
| 498 | 510 | ||
| 499 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | 511 | SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) |
| 500 | { | 512 | { |
| 501 | struct fd f = fdget(fd); | 513 | struct fd f = fdget_pos(fd); |
| 502 | ssize_t ret = -EBADF; | 514 | ssize_t ret = -EBADF; |
| 503 | 515 | ||
| 504 | if (f.file) { | 516 | if (f.file) { |
| @@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | |||
| 506 | ret = vfs_read(f.file, buf, count, &pos); | 518 | ret = vfs_read(f.file, buf, count, &pos); |
| 507 | if (ret >= 0) | 519 | if (ret >= 0) |
| 508 | file_pos_write(f.file, pos); | 520 | file_pos_write(f.file, pos); |
| 509 | fdput(f); | 521 | fdput_pos(f); |
| 510 | } | 522 | } |
| 511 | return ret; | 523 | return ret; |
| 512 | } | 524 | } |
| @@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) | |||
| 514 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | 526 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, |
| 515 | size_t, count) | 527 | size_t, count) |
| 516 | { | 528 | { |
| 517 | struct fd f = fdget(fd); | 529 | struct fd f = fdget_pos(fd); |
| 518 | ssize_t ret = -EBADF; | 530 | ssize_t ret = -EBADF; |
| 519 | 531 | ||
| 520 | if (f.file) { | 532 | if (f.file) { |
| @@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, | |||
| 522 | ret = vfs_write(f.file, buf, count, &pos); | 534 | ret = vfs_write(f.file, buf, count, &pos); |
| 523 | if (ret >= 0) | 535 | if (ret >= 0) |
| 524 | file_pos_write(f.file, pos); | 536 | file_pos_write(f.file, pos); |
| 525 | fdput(f); | 537 | fdput_pos(f); |
| 526 | } | 538 | } |
| 527 | 539 | ||
| 528 | return ret; | 540 | return ret; |
| @@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev); | |||
| 797 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | 809 | SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, |
| 798 | unsigned long, vlen) | 810 | unsigned long, vlen) |
| 799 | { | 811 | { |
| 800 | struct fd f = fdget(fd); | 812 | struct fd f = fdget_pos(fd); |
| 801 | ssize_t ret = -EBADF; | 813 | ssize_t ret = -EBADF; |
| 802 | 814 | ||
| 803 | if (f.file) { | 815 | if (f.file) { |
| @@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
| 805 | ret = vfs_readv(f.file, vec, vlen, &pos); | 817 | ret = vfs_readv(f.file, vec, vlen, &pos); |
| 806 | if (ret >= 0) | 818 | if (ret >= 0) |
| 807 | file_pos_write(f.file, pos); | 819 | file_pos_write(f.file, pos); |
| 808 | fdput(f); | 820 | fdput_pos(f); |
| 809 | } | 821 | } |
| 810 | 822 | ||
| 811 | if (ret > 0) | 823 | if (ret > 0) |
| @@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec, | |||
| 817 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | 829 | SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, |
| 818 | unsigned long, vlen) | 830 | unsigned long, vlen) |
| 819 | { | 831 | { |
| 820 | struct fd f = fdget(fd); | 832 | struct fd f = fdget_pos(fd); |
| 821 | ssize_t ret = -EBADF; | 833 | ssize_t ret = -EBADF; |
| 822 | 834 | ||
| 823 | if (f.file) { | 835 | if (f.file) { |
| @@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, | |||
| 825 | ret = vfs_writev(f.file, vec, vlen, &pos); | 837 | ret = vfs_writev(f.file, vec, vlen, &pos); |
| 826 | if (ret >= 0) | 838 | if (ret >= 0) |
| 827 | file_pos_write(f.file, pos); | 839 | file_pos_write(f.file, pos); |
| 828 | fdput(f); | 840 | fdput_pos(f); |
| 829 | } | 841 | } |
| 830 | 842 | ||
| 831 | if (ret > 0) | 843 | if (ret > 0) |
| @@ -968,7 +980,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
| 968 | const struct compat_iovec __user *,vec, | 980 | const struct compat_iovec __user *,vec, |
| 969 | compat_ulong_t, vlen) | 981 | compat_ulong_t, vlen) |
| 970 | { | 982 | { |
| 971 | struct fd f = fdget(fd); | 983 | struct fd f = fdget_pos(fd); |
| 972 | ssize_t ret; | 984 | ssize_t ret; |
| 973 | loff_t pos; | 985 | loff_t pos; |
| 974 | 986 | ||
| @@ -978,7 +990,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd, | |||
| 978 | ret = compat_readv(f.file, vec, vlen, &pos); | 990 | ret = compat_readv(f.file, vec, vlen, &pos); |
| 979 | if (ret >= 0) | 991 | if (ret >= 0) |
| 980 | f.file->f_pos = pos; | 992 | f.file->f_pos = pos; |
| 981 | fdput(f); | 993 | fdput_pos(f); |
| 982 | return ret; | 994 | return ret; |
| 983 | } | 995 | } |
| 984 | 996 | ||
| @@ -1035,7 +1047,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
| 1035 | const struct compat_iovec __user *, vec, | 1047 | const struct compat_iovec __user *, vec, |
| 1036 | compat_ulong_t, vlen) | 1048 | compat_ulong_t, vlen) |
| 1037 | { | 1049 | { |
| 1038 | struct fd f = fdget(fd); | 1050 | struct fd f = fdget_pos(fd); |
| 1039 | ssize_t ret; | 1051 | ssize_t ret; |
| 1040 | loff_t pos; | 1052 | loff_t pos; |
| 1041 | 1053 | ||
| @@ -1045,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd, | |||
| 1045 | ret = compat_writev(f.file, vec, vlen, &pos); | 1057 | ret = compat_writev(f.file, vec, vlen, &pos); |
| 1046 | if (ret >= 0) | 1058 | if (ret >= 0) |
| 1047 | f.file->f_pos = pos; | 1059 | f.file->f_pos = pos; |
| 1048 | fdput(f); | 1060 | fdput_pos(f); |
| 1049 | return ret; | 1061 | return ret; |
| 1050 | } | 1062 | } |
| 1051 | 1063 | ||
diff --git a/include/linux/file.h b/include/linux/file.h index cbacf4faf447..4d69123377a2 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
| @@ -28,33 +28,36 @@ static inline void fput_light(struct file *file, int fput_needed) | |||
| 28 | 28 | ||
| 29 | struct fd { | 29 | struct fd { |
| 30 | struct file *file; | 30 | struct file *file; |
| 31 | int need_put; | 31 | unsigned int flags; |
| 32 | }; | 32 | }; |
| 33 | #define FDPUT_FPUT 1 | ||
| 34 | #define FDPUT_POS_UNLOCK 2 | ||
| 33 | 35 | ||
| 34 | static inline void fdput(struct fd fd) | 36 | static inline void fdput(struct fd fd) |
| 35 | { | 37 | { |
| 36 | if (fd.need_put) | 38 | if (fd.flags & FDPUT_FPUT) |
| 37 | fput(fd.file); | 39 | fput(fd.file); |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | extern struct file *fget(unsigned int fd); | 42 | extern struct file *fget(unsigned int fd); |
| 41 | extern struct file *fget_light(unsigned int fd, int *fput_needed); | 43 | extern struct file *fget_raw(unsigned int fd); |
| 44 | extern unsigned long __fdget(unsigned int fd); | ||
| 45 | extern unsigned long __fdget_raw(unsigned int fd); | ||
| 46 | extern unsigned long __fdget_pos(unsigned int fd); | ||
| 42 | 47 | ||
| 43 | static inline struct fd fdget(unsigned int fd) | 48 | static inline struct fd __to_fd(unsigned long v) |
| 44 | { | 49 | { |
| 45 | int b; | 50 | return (struct fd){(struct file *)(v & ~3),v & 3}; |
| 46 | struct file *f = fget_light(fd, &b); | ||
| 47 | return (struct fd){f,b}; | ||
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | extern struct file *fget_raw(unsigned int fd); | 53 | static inline struct fd fdget(unsigned int fd) |
| 51 | extern struct file *fget_raw_light(unsigned int fd, int *fput_needed); | 54 | { |
| 55 | return __to_fd(__fdget(fd)); | ||
| 56 | } | ||
| 52 | 57 | ||
| 53 | static inline struct fd fdget_raw(unsigned int fd) | 58 | static inline struct fd fdget_raw(unsigned int fd) |
| 54 | { | 59 | { |
| 55 | int b; | 60 | return __to_fd(__fdget_raw(fd)); |
| 56 | struct file *f = fget_raw_light(fd, &b); | ||
| 57 | return (struct fd){f,b}; | ||
| 58 | } | 61 | } |
| 59 | 62 | ||
| 60 | extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); | 63 | extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 60829565e552..23b2a35d712e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -123,6 +123,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | |||
| 123 | /* File is opened with O_PATH; almost nothing can be done with it */ | 123 | /* File is opened with O_PATH; almost nothing can be done with it */ |
| 124 | #define FMODE_PATH ((__force fmode_t)0x4000) | 124 | #define FMODE_PATH ((__force fmode_t)0x4000) |
| 125 | 125 | ||
| 126 | /* File needs atomic accesses to f_pos */ | ||
| 127 | #define FMODE_ATOMIC_POS ((__force fmode_t)0x8000) | ||
| 128 | |||
| 126 | /* File was opened by fanotify and shouldn't generate fanotify events */ | 129 | /* File was opened by fanotify and shouldn't generate fanotify events */ |
| 127 | #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) | 130 | #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) |
| 128 | 131 | ||
| @@ -780,13 +783,14 @@ struct file { | |||
| 780 | const struct file_operations *f_op; | 783 | const struct file_operations *f_op; |
| 781 | 784 | ||
| 782 | /* | 785 | /* |
| 783 | * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR. | 786 | * Protects f_ep_links, f_flags. |
| 784 | * Must not be taken from IRQ context. | 787 | * Must not be taken from IRQ context. |
| 785 | */ | 788 | */ |
| 786 | spinlock_t f_lock; | 789 | spinlock_t f_lock; |
| 787 | atomic_long_t f_count; | 790 | atomic_long_t f_count; |
| 788 | unsigned int f_flags; | 791 | unsigned int f_flags; |
| 789 | fmode_t f_mode; | 792 | fmode_t f_mode; |
| 793 | struct mutex f_pos_lock; | ||
| 790 | loff_t f_pos; | 794 | loff_t f_pos; |
| 791 | struct fown_struct f_owner; | 795 | struct fown_struct f_owner; |
| 792 | const struct cred *f_cred; | 796 | const struct cred *f_cred; |
| @@ -808,7 +812,7 @@ struct file { | |||
| 808 | #ifdef CONFIG_DEBUG_WRITECOUNT | 812 | #ifdef CONFIG_DEBUG_WRITECOUNT |
| 809 | unsigned long f_mnt_write_state; | 813 | unsigned long f_mnt_write_state; |
| 810 | #endif | 814 | #endif |
| 811 | }; | 815 | } __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */ |
| 812 | 816 | ||
| 813 | struct file_handle { | 817 | struct file_handle { |
| 814 | __u32 handle_bytes; | 818 | __u32 handle_bytes; |
diff --git a/net/socket.c b/net/socket.c index 879933aaed4c..fd8d86e06f95 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup); | |||
| 450 | 450 | ||
| 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) | 451 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) |
| 452 | { | 452 | { |
| 453 | struct file *file; | 453 | struct fd f = fdget(fd); |
| 454 | struct socket *sock; | 454 | struct socket *sock; |
| 455 | 455 | ||
| 456 | *err = -EBADF; | 456 | *err = -EBADF; |
| 457 | file = fget_light(fd, fput_needed); | 457 | if (f.file) { |
| 458 | if (file) { | 458 | sock = sock_from_file(f.file, err); |
| 459 | sock = sock_from_file(file, err); | 459 | if (likely(sock)) { |
| 460 | if (sock) | 460 | *fput_needed = f.flags; |
| 461 | return sock; | 461 | return sock; |
| 462 | fput_light(file, *fput_needed); | 462 | } |
| 463 | fdput(f); | ||
| 463 | } | 464 | } |
| 464 | return NULL; | 465 | return NULL; |
| 465 | } | 466 | } |
