diff options
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 60 |
1 files changed, 38 insertions, 22 deletions
@@ -25,7 +25,10 @@ | |||
25 | 25 | ||
26 | int sysctl_nr_open __read_mostly = 1024*1024; | 26 | int sysctl_nr_open __read_mostly = 1024*1024; |
27 | int sysctl_nr_open_min = BITS_PER_LONG; | 27 | int sysctl_nr_open_min = BITS_PER_LONG; |
28 | int sysctl_nr_open_max = 1024 * 1024; /* raised later */ | 28 | /* our max() is unusable in constant expressions ;-/ */ |
29 | #define __const_max(x, y) ((x) < (y) ? (x) : (y)) | ||
30 | int sysctl_nr_open_max = __const_max(INT_MAX, ~(size_t)0/sizeof(void *)) & | ||
31 | -BITS_PER_LONG; | ||
29 | 32 | ||
30 | static void *alloc_fdmem(size_t size) | 33 | static void *alloc_fdmem(size_t size) |
31 | { | 34 | { |
@@ -34,7 +37,7 @@ static void *alloc_fdmem(size_t size) | |||
34 | * vmalloc() if the allocation size will be considered "large" by the VM. | 37 | * vmalloc() if the allocation size will be considered "large" by the VM. |
35 | */ | 38 | */ |
36 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { | 39 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
37 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); | 40 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY); |
38 | if (data != NULL) | 41 | if (data != NULL) |
39 | return data; | 42 | return data; |
40 | } | 43 | } |
@@ -429,12 +432,6 @@ void exit_files(struct task_struct *tsk) | |||
429 | } | 432 | } |
430 | } | 433 | } |
431 | 434 | ||
432 | void __init files_defer_init(void) | ||
433 | { | ||
434 | sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) & | ||
435 | -BITS_PER_LONG; | ||
436 | } | ||
437 | |||
438 | struct files_struct init_files = { | 435 | struct files_struct init_files = { |
439 | .count = ATOMIC_INIT(1), | 436 | .count = ATOMIC_INIT(1), |
440 | .fdt = &init_files.fdtab, | 437 | .fdt = &init_files.fdtab, |
@@ -497,7 +494,7 @@ repeat: | |||
497 | error = fd; | 494 | error = fd; |
498 | #if 1 | 495 | #if 1 |
499 | /* Sanity check */ | 496 | /* Sanity check */ |
500 | if (rcu_dereference_raw(fdt->fd[fd]) != NULL) { | 497 | if (rcu_access_pointer(fdt->fd[fd]) != NULL) { |
501 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); | 498 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); |
502 | rcu_assign_pointer(fdt->fd[fd], NULL); | 499 | rcu_assign_pointer(fdt->fd[fd], NULL); |
503 | } | 500 | } |
@@ -683,35 +680,54 @@ EXPORT_SYMBOL(fget_raw); | |||
683 | * The fput_needed flag returned by fget_light should be passed to the | 680 | * The fput_needed flag returned by fget_light should be passed to the |
684 | * corresponding fput_light. | 681 | * corresponding fput_light. |
685 | */ | 682 | */ |
686 | struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed) | 683 | static unsigned long __fget_light(unsigned int fd, fmode_t mask) |
687 | { | 684 | { |
688 | struct files_struct *files = current->files; | 685 | struct files_struct *files = current->files; |
689 | struct file *file; | 686 | struct file *file; |
690 | 687 | ||
691 | *fput_needed = 0; | ||
692 | if (atomic_read(&files->count) == 1) { | 688 | if (atomic_read(&files->count) == 1) { |
693 | file = __fcheck_files(files, fd); | 689 | file = __fcheck_files(files, fd); |
694 | if (file && (file->f_mode & mask)) | 690 | if (!file || unlikely(file->f_mode & mask)) |
695 | file = NULL; | 691 | return 0; |
692 | return (unsigned long)file; | ||
696 | } else { | 693 | } else { |
697 | file = __fget(fd, mask); | 694 | file = __fget(fd, mask); |
698 | if (file) | 695 | if (!file) |
699 | *fput_needed = 1; | 696 | return 0; |
697 | return FDPUT_FPUT | (unsigned long)file; | ||
700 | } | 698 | } |
701 | |||
702 | return file; | ||
703 | } | 699 | } |
704 | struct file *fget_light(unsigned int fd, int *fput_needed) | 700 | unsigned long __fdget(unsigned int fd) |
701 | { | ||
702 | return __fget_light(fd, FMODE_PATH); | ||
703 | } | ||
704 | EXPORT_SYMBOL(__fdget); | ||
705 | |||
706 | unsigned long __fdget_raw(unsigned int fd) | ||
705 | { | 707 | { |
706 | return __fget_light(fd, FMODE_PATH, fput_needed); | 708 | return __fget_light(fd, 0); |
707 | } | 709 | } |
708 | EXPORT_SYMBOL(fget_light); | ||
709 | 710 | ||
710 | struct file *fget_raw_light(unsigned int fd, int *fput_needed) | 711 | unsigned long __fdget_pos(unsigned int fd) |
711 | { | 712 | { |
712 | return __fget_light(fd, 0, fput_needed); | 713 | unsigned long v = __fdget(fd); |
714 | struct file *file = (struct file *)(v & ~3); | ||
715 | |||
716 | if (file && (file->f_mode & FMODE_ATOMIC_POS)) { | ||
717 | if (file_count(file) > 1) { | ||
718 | v |= FDPUT_POS_UNLOCK; | ||
719 | mutex_lock(&file->f_pos_lock); | ||
720 | } | ||
721 | } | ||
722 | return v; | ||
713 | } | 723 | } |
714 | 724 | ||
725 | /* | ||
726 | * We only lock f_pos if we have threads or if the file might be | ||
727 | * shared with another process. In both cases we'll have an elevated | ||
728 | * file count (done either by fdget() or by fork()). | ||
729 | */ | ||
730 | |||
715 | void set_close_on_exec(unsigned int fd, int flag) | 731 | void set_close_on_exec(unsigned int fd, int flag) |
716 | { | 732 | { |
717 | struct files_struct *files = current->files; | 733 | struct files_struct *files = current->files; |