diff options
81 files changed, 696 insertions, 351 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 23d2f4460deb..ccec55394380 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -394,7 +394,6 @@ prototypes: | |||
| 394 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, | 394 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, |
| 395 | unsigned long, unsigned long, unsigned long); | 395 | unsigned long, unsigned long, unsigned long); |
| 396 | int (*check_flags)(int); | 396 | int (*check_flags)(int); |
| 397 | int (*dir_notify)(struct file *, unsigned long); | ||
| 398 | }; | 397 | }; |
| 399 | 398 | ||
| 400 | locking rules: | 399 | locking rules: |
| @@ -424,7 +423,6 @@ sendfile: no | |||
| 424 | sendpage: no | 423 | sendpage: no |
| 425 | get_unmapped_area: no | 424 | get_unmapped_area: no |
| 426 | check_flags: no | 425 | check_flags: no |
| 427 | dir_notify: no | ||
| 428 | 426 | ||
| 429 | ->llseek() locking has moved from llseek to the individual llseek | 427 | ->llseek() locking has moved from llseek to the individual llseek |
| 430 | implementations. If your fs is not using generic_file_llseek, you | 428 | implementations. If your fs is not using generic_file_llseek, you |
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt index bb0142f61084..ac2facc50d2a 100644 --- a/Documentation/filesystems/files.txt +++ b/Documentation/filesystems/files.txt | |||
| @@ -76,13 +76,13 @@ the fdtable structure - | |||
| 76 | 5. Handling of the file structures is special. Since the look-up | 76 | 5. Handling of the file structures is special. Since the look-up |
| 77 | of the fd (fget()/fget_light()) are lock-free, it is possible | 77 | of the fd (fget()/fget_light()) are lock-free, it is possible |
| 78 | that look-up may race with the last put() operation on the | 78 | that look-up may race with the last put() operation on the |
| 79 | file structure. This is avoided using atomic_inc_not_zero() | 79 | file structure. This is avoided using atomic_long_inc_not_zero() |
| 80 | on ->f_count : | 80 | on ->f_count : |
| 81 | 81 | ||
| 82 | rcu_read_lock(); | 82 | rcu_read_lock(); |
| 83 | file = fcheck_files(files, fd); | 83 | file = fcheck_files(files, fd); |
| 84 | if (file) { | 84 | if (file) { |
| 85 | if (atomic_inc_not_zero(&file->f_count)) | 85 | if (atomic_long_inc_not_zero(&file->f_count)) |
| 86 | *fput_needed = 1; | 86 | *fput_needed = 1; |
| 87 | else | 87 | else |
| 88 | /* Didn't get the reference, someone's freed */ | 88 | /* Didn't get the reference, someone's freed */ |
| @@ -92,7 +92,7 @@ the fdtable structure - | |||
| 92 | .... | 92 | .... |
| 93 | return file; | 93 | return file; |
| 94 | 94 | ||
| 95 | atomic_inc_not_zero() detects if refcounts is already zero or | 95 | atomic_long_inc_not_zero() detects if refcounts is already zero or |
| 96 | goes to zero during increment. If it does, we fail | 96 | goes to zero during increment. If it does, we fail |
| 97 | fget()/fget_light(). | 97 | fget()/fget_light(). |
| 98 | 98 | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 5579bda58a6d..ef19afa186a9 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -733,7 +733,6 @@ struct file_operations { | |||
| 733 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 733 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
| 734 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 734 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
| 735 | int (*check_flags)(int); | 735 | int (*check_flags)(int); |
| 736 | int (*dir_notify)(struct file *filp, unsigned long arg); | ||
| 737 | int (*flock) (struct file *, int, struct file_lock *); | 736 | int (*flock) (struct file *, int, struct file_lock *); |
| 738 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); | 737 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); |
| 739 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); | 738 | ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); |
| @@ -800,8 +799,6 @@ otherwise noted. | |||
| 800 | 799 | ||
| 801 | check_flags: called by the fcntl(2) system call for F_SETFL command | 800 | check_flags: called by the fcntl(2) system call for F_SETFL command |
| 802 | 801 | ||
| 803 | dir_notify: called by the fcntl(2) system call for F_NOTIFY command | ||
| 804 | |||
| 805 | flock: called by the flock(2) system call | 802 | flock: called by the flock(2) system call |
| 806 | 803 | ||
| 807 | splice_write: called by the VFS to splice data from a pipe to a file. This | 804 | splice_write: called by the VFS to splice data from a pipe to a file. This |
| @@ -931,7 +928,7 @@ manipulate dentries: | |||
| 931 | d_lookup: look up a dentry given its parent and path name component | 928 | d_lookup: look up a dentry given its parent and path name component |
| 932 | It looks up the child of that given name from the dcache | 929 | It looks up the child of that given name from the dcache |
| 933 | hash table. If it is found, the reference count is incremented | 930 | hash table. If it is found, the reference count is incremented |
| 934 | and the dentry is returned. The caller must use d_put() | 931 | and the dentry is returned. The caller must use dput() |
| 935 | to free the dentry when it finishes using it. | 932 | to free the dentry when it finishes using it. |
| 936 | 933 | ||
| 937 | For further information on dentry locking, please refer to the document | 934 | For further information on dentry locking, please refer to the document |
diff --git a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c index 1f762189fa64..c2938e574a40 100644 --- a/arch/alpha/kernel/init_task.c +++ b/arch/alpha/kernel/init_task.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | static struct fs_struct init_fs = INIT_FS; | ||
| 12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c index 0bbf80625395..e859af349467 100644 --- a/arch/arm/kernel/init_task.c +++ b/arch/arm/kernel/init_task.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
| 14 | 14 | ||
| 15 | static struct fs_struct init_fs = INIT_FS; | ||
| 16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c index 44058469c6ec..993d56ee3cf3 100644 --- a/arch/avr32/kernel/init_task.c +++ b/arch/avr32/kernel/init_task.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
| 15 | 15 | ||
| 16 | static struct fs_struct init_fs = INIT_FS; | ||
| 17 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 18 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 19 | struct mm_struct init_mm = INIT_MM(init_mm); | 18 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c index 6bdba7b21109..2c228c020978 100644 --- a/arch/blackfin/kernel/init_task.c +++ b/arch/blackfin/kernel/init_task.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/mqueue.h> | 33 | #include <linux/mqueue.h> |
| 34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
| 35 | 35 | ||
| 36 | static struct fs_struct init_fs = INIT_FS; | ||
| 37 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 36 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 38 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 37 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 39 | 38 | ||
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 5933656db5a2..60816e876455 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | * setup. | 37 | * setup. |
| 38 | */ | 38 | */ |
| 39 | 39 | ||
| 40 | static struct fs_struct init_fs = INIT_FS; | ||
| 41 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 40 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 42 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 41 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 43 | struct mm_struct init_mm = INIT_MM(init_mm); | 42 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c index e2198815b630..29429a8b7f6a 100644 --- a/arch/frv/kernel/init_task.c +++ b/arch/frv/kernel/init_task.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | static struct fs_struct init_fs = INIT_FS; | ||
| 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 16 | struct mm_struct init_mm = INIT_MM(init_mm); | 15 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c index 93a4899e46c2..cb5dc552da97 100644 --- a/arch/h8300/kernel/init_task.c +++ b/arch/h8300/kernel/init_task.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
| 13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
| 14 | 14 | ||
| 15 | static struct fs_struct init_fs = INIT_FS; | ||
| 16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c index 9d7e1c66faf4..5b0e830c6f33 100644 --- a/arch/ia64/kernel/init_task.c +++ b/arch/ia64/kernel/init_task.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
| 18 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
| 19 | 19 | ||
| 20 | static struct fs_struct init_fs = INIT_FS; | ||
| 21 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 20 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 22 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 21 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 23 | struct mm_struct init_mm = INIT_MM(init_mm); | 22 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c index 0d658dbb6766..016885c6f260 100644 --- a/arch/m32r/kernel/init_task.c +++ b/arch/m32r/kernel/init_task.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
| 12 | #include <asm/pgtable.h> | 12 | #include <asm/pgtable.h> |
| 13 | 13 | ||
| 14 | static struct fs_struct init_fs = INIT_FS; | ||
| 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 17 | struct mm_struct init_mm = INIT_MM(init_mm); | 16 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 3042c2bc8c58..632ce016014d 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | * alignment requirements and potentially different initial | 40 | * alignment requirements and potentially different initial |
| 41 | * setup. | 41 | * setup. |
| 42 | */ | 42 | */ |
| 43 | static struct fs_struct init_fs = INIT_FS; | ||
| 44 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 43 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 45 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 44 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 46 | struct mm_struct init_mm = INIT_MM(init_mm); | 45 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c index 344c01aede08..fe282de1d596 100644 --- a/arch/m68knommu/kernel/init_task.c +++ b/arch/m68knommu/kernel/init_task.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
| 13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
| 14 | 14 | ||
| 15 | static struct fs_struct init_fs = INIT_FS; | ||
| 16 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 17 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 18 | struct mm_struct init_mm = INIT_MM(init_mm); | 17 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c index d72487ad7c15..149cd914526e 100644 --- a/arch/mips/kernel/init_task.c +++ b/arch/mips/kernel/init_task.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
| 10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
| 11 | 11 | ||
| 12 | static struct fs_struct init_fs = INIT_FS; | ||
| 13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 15 | struct mm_struct init_mm = INIT_MM(init_mm); | 14 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c index af16f6e5c918..5ac3566f8c98 100644 --- a/arch/mn10300/kernel/init_task.c +++ b/arch/mn10300/kernel/init_task.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
| 19 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
| 20 | 20 | ||
| 21 | static struct fs_struct init_fs = INIT_FS; | ||
| 22 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 21 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 23 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 22 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 24 | struct mm_struct init_mm = INIT_MM(init_mm); | 23 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c index f5941c086551..1e25a45d64c1 100644 --- a/arch/parisc/kernel/init_task.c +++ b/arch/parisc/kernel/init_task.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
| 35 | #include <asm/pgalloc.h> | 35 | #include <asm/pgalloc.h> |
| 36 | 36 | ||
| 37 | static struct fs_struct init_fs = INIT_FS; | ||
| 38 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 37 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 39 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 38 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 40 | struct mm_struct init_mm = INIT_MM(init_mm); | 39 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c index 4c85b8d56478..688b329800bd 100644 --- a/arch/powerpc/kernel/init_task.c +++ b/arch/powerpc/kernel/init_task.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <linux/mqueue.h> | 7 | #include <linux/mqueue.h> |
| 8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
| 9 | 9 | ||
| 10 | static struct fs_struct init_fs = INIT_FS; | ||
| 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 10 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 11 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 13 | struct mm_struct init_mm = INIT_MM(init_mm); | 12 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c index 2949126d28d1..6b793aeda72e 100644 --- a/arch/powerpc/oprofile/cell/spu_task_sync.c +++ b/arch/powerpc/oprofile/cell/spu_task_sync.c | |||
| @@ -297,7 +297,7 @@ static inline unsigned long fast_get_dcookie(struct path *path) | |||
| 297 | { | 297 | { |
| 298 | unsigned long cookie; | 298 | unsigned long cookie; |
| 299 | 299 | ||
| 300 | if (path->dentry->d_cookie) | 300 | if (path->dentry->d_flags & DCACHE_COOKIE) |
| 301 | return (unsigned long)path->dentry; | 301 | return (unsigned long)path->dentry; |
| 302 | get_dcookie(path, &cookie); | 302 | get_dcookie(path, &cookie); |
| 303 | return cookie; | 303 | return cookie; |
diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c index e80716843619..7db95c0b8693 100644 --- a/arch/s390/kernel/init_task.c +++ b/arch/s390/kernel/init_task.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
| 17 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
| 18 | 18 | ||
| 19 | static struct fs_struct init_fs = INIT_FS; | ||
| 20 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 19 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 21 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 20 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 22 | struct mm_struct init_mm = INIT_MM(init_mm); | 21 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c index b151a25cb14d..80c35ff71d56 100644 --- a/arch/sh/kernel/init_task.c +++ b/arch/sh/kernel/init_task.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 8 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
| 9 | 9 | ||
| 10 | static struct fs_struct init_fs = INIT_FS; | ||
| 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 10 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 11 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 13 | struct pt_regs fake_swapper_regs; | 12 | struct pt_regs fake_swapper_regs; |
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c index 62126e4cec54..f28cb8278e98 100644 --- a/arch/sparc/kernel/init_task.c +++ b/arch/sparc/kernel/init_task.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
| 9 | #include <asm/uaccess.h> | 9 | #include <asm/uaccess.h> |
| 10 | 10 | ||
| 11 | static struct fs_struct init_fs = INIT_FS; | ||
| 12 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 11 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 13 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 12 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index 910eda8fca18..806d381947bf 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "linux/mqueue.h" | 10 | #include "linux/mqueue.h" |
| 11 | #include "asm/uaccess.h" | 11 | #include "asm/uaccess.h" |
| 12 | 12 | ||
| 13 | static struct fs_struct init_fs = INIT_FS; | ||
| 14 | struct mm_struct init_mm = INIT_MM(init_mm); | 13 | struct mm_struct init_mm = INIT_MM(init_mm); |
| 15 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 16 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c index d39918076bb4..df3bf269beab 100644 --- a/arch/x86/kernel/init_task.c +++ b/arch/x86/kernel/init_task.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
| 11 | #include <asm/desc.h> | 11 | #include <asm/desc.h> |
| 12 | 12 | ||
| 13 | static struct fs_struct init_fs = INIT_FS; | ||
| 14 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 13 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 15 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 14 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 16 | struct mm_struct init_mm = INIT_MM(init_mm); | 15 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c index 3df469dbe814..e07f5c9fcd35 100644 --- a/arch/xtensa/kernel/init_task.c +++ b/arch/xtensa/kernel/init_task.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 23 | 23 | ||
| 24 | static struct fs_struct init_fs = INIT_FS; | ||
| 25 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | 24 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); |
| 26 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | 25 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); |
| 27 | struct mm_struct init_mm = INIT_MM(init_mm); | 26 | struct mm_struct init_mm = INIT_MM(init_mm); |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 737bd9484822..65e8294a9e29 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
| @@ -200,7 +200,7 @@ static inline unsigned long fast_get_dcookie(struct path *path) | |||
| 200 | { | 200 | { |
| 201 | unsigned long cookie; | 201 | unsigned long cookie; |
| 202 | 202 | ||
| 203 | if (path->dentry->d_cookie) | 203 | if (path->dentry->d_flags & DCACHE_COOKIE) |
| 204 | return (unsigned long)path->dentry; | 204 | return (unsigned long)path->dentry; |
| 205 | get_dcookie(path, &cookie); | 205 | get_dcookie(path, &cookie); |
| 206 | return cookie; | 206 | return cookie; |
diff --git a/fs/Kconfig b/fs/Kconfig index 522469a7eca3..ff0e81980207 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -270,44 +270,7 @@ config OCFS2_COMPAT_JBD | |||
| 270 | 270 | ||
| 271 | endif # BLOCK | 271 | endif # BLOCK |
| 272 | 272 | ||
| 273 | config DNOTIFY | 273 | source "fs/notify/Kconfig" |
| 274 | bool "Dnotify support" | ||
| 275 | default y | ||
| 276 | help | ||
| 277 | Dnotify is a directory-based per-fd file change notification system | ||
| 278 | that uses signals to communicate events to user-space. There exist | ||
| 279 | superior alternatives, but some applications may still rely on | ||
| 280 | dnotify. | ||
| 281 | |||
| 282 | If unsure, say Y. | ||
| 283 | |||
| 284 | config INOTIFY | ||
| 285 | bool "Inotify file change notification support" | ||
| 286 | default y | ||
| 287 | ---help--- | ||
| 288 | Say Y here to enable inotify support. Inotify is a file change | ||
| 289 | notification system and a replacement for dnotify. Inotify fixes | ||
| 290 | numerous shortcomings in dnotify and introduces several new features | ||
| 291 | including multiple file events, one-shot support, and unmount | ||
| 292 | notification. | ||
| 293 | |||
| 294 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
| 295 | |||
| 296 | If unsure, say Y. | ||
| 297 | |||
| 298 | config INOTIFY_USER | ||
| 299 | bool "Inotify support for userspace" | ||
| 300 | depends on INOTIFY | ||
| 301 | default y | ||
| 302 | ---help--- | ||
| 303 | Say Y here to enable inotify support for userspace, including the | ||
| 304 | associated system calls. Inotify allows monitoring of both files and | ||
| 305 | directories via a single open fd. Events are read from the file | ||
| 306 | descriptor, which is also select()- and poll()-able. | ||
| 307 | |||
| 308 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
| 309 | |||
| 310 | If unsure, say Y. | ||
| 311 | 274 | ||
| 312 | config QUOTA | 275 | config QUOTA |
| 313 | bool "Quota support" | 276 | bool "Quota support" |
diff --git a/fs/Makefile b/fs/Makefile index d9f8afe6f0c4..e6f423d1d228 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -20,8 +20,7 @@ obj-y += no-block.o | |||
| 20 | endif | 20 | endif |
| 21 | 21 | ||
| 22 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o | 22 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o |
| 23 | obj-$(CONFIG_INOTIFY) += inotify.o | 23 | obj-y += notify/ |
| 24 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | ||
| 25 | obj-$(CONFIG_EPOLL) += eventpoll.o | 24 | obj-$(CONFIG_EPOLL) += eventpoll.o |
| 26 | obj-$(CONFIG_ANON_INODES) += anon_inodes.o | 25 | obj-$(CONFIG_ANON_INODES) += anon_inodes.o |
| 27 | obj-$(CONFIG_SIGNALFD) += signalfd.o | 26 | obj-$(CONFIG_SIGNALFD) += signalfd.o |
| @@ -57,8 +56,6 @@ obj-$(CONFIG_QFMT_V1) += quota_v1.o | |||
| 57 | obj-$(CONFIG_QFMT_V2) += quota_v2.o | 56 | obj-$(CONFIG_QFMT_V2) += quota_v2.o |
| 58 | obj-$(CONFIG_QUOTACTL) += quota.o | 57 | obj-$(CONFIG_QUOTACTL) += quota.o |
| 59 | 58 | ||
| 60 | obj-$(CONFIG_DNOTIFY) += dnotify.o | ||
| 61 | |||
| 62 | obj-$(CONFIG_PROC_FS) += proc/ | 59 | obj-$(CONFIG_PROC_FS) += proc/ |
| 63 | obj-y += partitions/ | 60 | obj-y += partitions/ |
| 64 | obj-$(CONFIG_SYSFS) += sysfs/ | 61 | obj-$(CONFIG_SYSFS) += sysfs/ |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 5f1538c03b1b..a05287a23f62 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
| @@ -132,11 +132,6 @@ static int bad_file_check_flags(int flags) | |||
| 132 | return -EIO; | 132 | return -EIO; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | static int bad_file_dir_notify(struct file *file, unsigned long arg) | ||
| 136 | { | ||
| 137 | return -EIO; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl) | 135 | static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl) |
| 141 | { | 136 | { |
| 142 | return -EIO; | 137 | return -EIO; |
| @@ -179,7 +174,6 @@ static const struct file_operations bad_file_ops = | |||
| 179 | .sendpage = bad_file_sendpage, | 174 | .sendpage = bad_file_sendpage, |
| 180 | .get_unmapped_area = bad_file_get_unmapped_area, | 175 | .get_unmapped_area = bad_file_get_unmapped_area, |
| 181 | .check_flags = bad_file_check_flags, | 176 | .check_flags = bad_file_check_flags, |
| 182 | .dir_notify = bad_file_dir_notify, | ||
| 183 | .flock = bad_file_flock, | 177 | .flock = bad_file_flock, |
| 184 | .splice_write = bad_file_splice_write, | 178 | .splice_write = bad_file_splice_write, |
| 185 | .splice_read = bad_file_splice_read, | 179 | .splice_read = bad_file_splice_read, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index b6dfee37c7b7..d06cb023ad02 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
| @@ -378,7 +378,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) | |||
| 378 | inode->i_size = 0; | 378 | inode->i_size = 0; |
| 379 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; | 379 | inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; |
| 380 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, | 380 | strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink, |
| 381 | BEFS_SYMLINK_LEN); | 381 | BEFS_SYMLINK_LEN - 1); |
| 382 | befs_ino->i_data.symlink[BEFS_SYMLINK_LEN - 1] = '\0'; | ||
| 382 | } else { | 383 | } else { |
| 383 | int num_blks; | 384 | int num_blks; |
| 384 | 385 | ||
| @@ -477,6 +478,8 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 477 | kfree(link); | 478 | kfree(link); |
| 478 | befs_error(sb, "Failed to read entire long symlink"); | 479 | befs_error(sb, "Failed to read entire long symlink"); |
| 479 | link = ERR_PTR(-EIO); | 480 | link = ERR_PTR(-EIO); |
| 481 | } else { | ||
| 482 | link[len - 1] = '\0'; | ||
| 480 | } | 483 | } |
| 481 | } else { | 484 | } else { |
| 482 | link = befs_ino->i_data.symlink; | 485 | link = befs_ino->i_data.symlink; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 99e0ae1a4c78..349a26c10001 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -326,12 +326,13 @@ static struct file_system_type bd_type = { | |||
| 326 | .kill_sb = kill_anon_super, | 326 | .kill_sb = kill_anon_super, |
| 327 | }; | 327 | }; |
| 328 | 328 | ||
| 329 | static struct vfsmount *bd_mnt __read_mostly; | 329 | struct super_block *blockdev_superblock __read_mostly; |
| 330 | struct super_block *blockdev_superblock; | ||
| 331 | 330 | ||
| 332 | void __init bdev_cache_init(void) | 331 | void __init bdev_cache_init(void) |
| 333 | { | 332 | { |
| 334 | int err; | 333 | int err; |
| 334 | struct vfsmount *bd_mnt; | ||
| 335 | |||
| 335 | bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), | 336 | bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), |
| 336 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| | 337 | 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| |
| 337 | SLAB_MEM_SPREAD|SLAB_PANIC), | 338 | SLAB_MEM_SPREAD|SLAB_PANIC), |
| @@ -373,7 +374,7 @@ struct block_device *bdget(dev_t dev) | |||
| 373 | struct block_device *bdev; | 374 | struct block_device *bdev; |
| 374 | struct inode *inode; | 375 | struct inode *inode; |
| 375 | 376 | ||
| 376 | inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), | 377 | inode = iget5_locked(blockdev_superblock, hash(dev), |
| 377 | bdev_test, bdev_set, &dev); | 378 | bdev_test, bdev_set, &dev); |
| 378 | 379 | ||
| 379 | if (!inode) | 380 | if (!inode) |
| @@ -463,7 +464,7 @@ void bd_forget(struct inode *inode) | |||
| 463 | 464 | ||
| 464 | spin_lock(&bdev_lock); | 465 | spin_lock(&bdev_lock); |
| 465 | if (inode->i_bdev) { | 466 | if (inode->i_bdev) { |
| 466 | if (inode->i_sb != blockdev_superblock) | 467 | if (!sb_is_blkdev_sb(inode->i_sb)) |
| 467 | bdev = inode->i_bdev; | 468 | bdev = inode->i_bdev; |
| 468 | __bd_forget(inode); | 469 | __bd_forget(inode); |
| 469 | } | 470 | } |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 6ba43fb346fb..9948c0030e86 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
| @@ -5,7 +5,7 @@ obj-$(CONFIG_CIFS) += cifs.o | |||
| 5 | 5 | ||
| 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
| 7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ |
| 8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \ | 8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
| 9 | readdir.o ioctl.o sess.o export.o cifsacl.o | 9 | readdir.o ioctl.o sess.o export.o cifsacl.o |
| 10 | 10 | ||
| 11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | 11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0005a194a75c..13ea53251dcf 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -747,7 +747,6 @@ const struct file_operations cifs_file_ops = { | |||
| 747 | #endif /* CONFIG_CIFS_POSIX */ | 747 | #endif /* CONFIG_CIFS_POSIX */ |
| 748 | 748 | ||
| 749 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 749 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 750 | .dir_notify = cifs_dir_notify, | ||
| 751 | .setlease = cifs_setlease, | 750 | .setlease = cifs_setlease, |
| 752 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 751 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 753 | }; | 752 | }; |
| @@ -768,7 +767,6 @@ const struct file_operations cifs_file_direct_ops = { | |||
| 768 | #endif /* CONFIG_CIFS_POSIX */ | 767 | #endif /* CONFIG_CIFS_POSIX */ |
| 769 | .llseek = cifs_llseek, | 768 | .llseek = cifs_llseek, |
| 770 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 769 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 771 | .dir_notify = cifs_dir_notify, | ||
| 772 | .setlease = cifs_setlease, | 770 | .setlease = cifs_setlease, |
| 773 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 771 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 774 | }; | 772 | }; |
| @@ -789,7 +787,6 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
| 789 | #endif /* CONFIG_CIFS_POSIX */ | 787 | #endif /* CONFIG_CIFS_POSIX */ |
| 790 | 788 | ||
| 791 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 789 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 792 | .dir_notify = cifs_dir_notify, | ||
| 793 | .setlease = cifs_setlease, | 790 | .setlease = cifs_setlease, |
| 794 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 791 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 795 | }; | 792 | }; |
| @@ -809,7 +806,6 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
| 809 | #endif /* CONFIG_CIFS_POSIX */ | 806 | #endif /* CONFIG_CIFS_POSIX */ |
| 810 | .llseek = cifs_llseek, | 807 | .llseek = cifs_llseek, |
| 811 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 808 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 812 | .dir_notify = cifs_dir_notify, | ||
| 813 | .setlease = cifs_setlease, | 809 | .setlease = cifs_setlease, |
| 814 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 810 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 815 | }; | 811 | }; |
| @@ -818,9 +814,6 @@ const struct file_operations cifs_dir_ops = { | |||
| 818 | .readdir = cifs_readdir, | 814 | .readdir = cifs_readdir, |
| 819 | .release = cifs_closedir, | 815 | .release = cifs_closedir, |
| 820 | .read = generic_read_dir, | 816 | .read = generic_read_dir, |
| 821 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 822 | .dir_notify = cifs_dir_notify, | ||
| 823 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
| 824 | .unlocked_ioctl = cifs_ioctl, | 817 | .unlocked_ioctl = cifs_ioctl, |
| 825 | .llseek = generic_file_llseek, | 818 | .llseek = generic_file_llseek, |
| 826 | }; | 819 | }; |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 2ce04c73d74e..7ac481841f87 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -76,7 +76,6 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | |||
| 76 | extern const struct file_operations cifs_dir_ops; | 76 | extern const struct file_operations cifs_dir_ops; |
| 77 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 77 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
| 78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 78 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
| 79 | extern int cifs_dir_notify(struct file *, unsigned long arg); | ||
| 80 | 79 | ||
| 81 | /* Functions related to dir entries */ | 80 | /* Functions related to dir entries */ |
| 82 | extern struct dentry_operations cifs_dentry_ops; | 81 | extern struct dentry_operations cifs_dentry_ops; |
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c deleted file mode 100644 index 5a57581eb4b2..000000000000 --- a/fs/cifs/fcntl.c +++ /dev/null | |||
| @@ -1,118 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * fs/cifs/fcntl.c | ||
| 3 | * | ||
| 4 | * vfs operations that deal with the file control API | ||
| 5 | * | ||
| 6 | * Copyright (C) International Business Machines Corp., 2003,2004 | ||
| 7 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
| 8 | * | ||
| 9 | * This library is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU Lesser General Public License as published | ||
| 11 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This library is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
| 17 | * the GNU Lesser General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU Lesser General Public License | ||
| 20 | * along with this library; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | #include <linux/fs.h> | ||
| 24 | #include <linux/stat.h> | ||
| 25 | #include <linux/fcntl.h> | ||
| 26 | #include "cifsglob.h" | ||
| 27 | #include "cifsproto.h" | ||
| 28 | #include "cifs_unicode.h" | ||
| 29 | #include "cifs_debug.h" | ||
| 30 | #include "cifsfs.h" | ||
| 31 | |||
| 32 | static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) | ||
| 33 | { | ||
| 34 | __u32 cifs_ntfy_flags = 0; | ||
| 35 | |||
| 36 | /* No way on Linux VFS to ask to monitor xattr | ||
| 37 | changes (and no stream support either */ | ||
| 38 | if (fcntl_notify_flags & DN_ACCESS) | ||
| 39 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; | ||
| 40 | if (fcntl_notify_flags & DN_MODIFY) { | ||
| 41 | /* What does this mean on directories? */ | ||
| 42 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | | ||
| 43 | FILE_NOTIFY_CHANGE_SIZE; | ||
| 44 | } | ||
| 45 | if (fcntl_notify_flags & DN_CREATE) { | ||
| 46 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | | ||
| 47 | FILE_NOTIFY_CHANGE_LAST_WRITE; | ||
| 48 | } | ||
| 49 | if (fcntl_notify_flags & DN_DELETE) | ||
| 50 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; | ||
| 51 | if (fcntl_notify_flags & DN_RENAME) { | ||
| 52 | /* BB review this - checking various server behaviors */ | ||
| 53 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | | ||
| 54 | FILE_NOTIFY_CHANGE_FILE_NAME; | ||
| 55 | } | ||
| 56 | if (fcntl_notify_flags & DN_ATTRIB) { | ||
| 57 | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | | ||
| 58 | FILE_NOTIFY_CHANGE_ATTRIBUTES; | ||
| 59 | } | ||
| 60 | /* if (fcntl_notify_flags & DN_MULTISHOT) { | ||
| 61 | cifs_ntfy_flags |= ; | ||
| 62 | } */ /* BB fixme - not sure how to handle this with CIFS yet */ | ||
| 63 | |||
| 64 | return cifs_ntfy_flags; | ||
| 65 | } | ||
| 66 | |||
| 67 | int cifs_dir_notify(struct file *file, unsigned long arg) | ||
| 68 | { | ||
| 69 | int xid; | ||
| 70 | int rc = -EINVAL; | ||
| 71 | int oplock = 0; | ||
| 72 | struct cifs_sb_info *cifs_sb; | ||
| 73 | struct cifsTconInfo *pTcon; | ||
| 74 | char *full_path = NULL; | ||
| 75 | __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; | ||
| 76 | __u16 netfid; | ||
| 77 | |||
| 78 | if (experimEnabled == 0) | ||
| 79 | return 0; | ||
| 80 | |||
| 81 | xid = GetXid(); | ||
| 82 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
| 83 | pTcon = cifs_sb->tcon; | ||
| 84 | |||
| 85 | full_path = build_path_from_dentry(file->f_path.dentry); | ||
| 86 | |||
| 87 | if (full_path == NULL) { | ||
| 88 | rc = -ENOMEM; | ||
| 89 | } else { | ||
| 90 | cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg)); | ||
| 91 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | ||
| 92 | GENERIC_READ | SYNCHRONIZE, 0 /* create options */, | ||
| 93 | &netfid, &oplock, NULL, cifs_sb->local_nls, | ||
| 94 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 95 | /* BB fixme - add this handle to a notify handle list */ | ||
| 96 | if (rc) { | ||
| 97 | cFYI(1, ("Could not open directory for notify")); | ||
| 98 | } else { | ||
| 99 | filter = convert_to_cifs_notify_flags(arg); | ||
| 100 | if (filter != 0) { | ||
| 101 | rc = CIFSSMBNotify(xid, pTcon, | ||
| 102 | 0 /* no subdirs */, netfid, | ||
| 103 | filter, file, arg & DN_MULTISHOT, | ||
| 104 | cifs_sb->local_nls); | ||
| 105 | } else { | ||
| 106 | rc = -EINVAL; | ||
| 107 | } | ||
| 108 | /* BB add code to close file eventually (at unmount | ||
| 109 | it would close automatically but may be a way | ||
| 110 | to do it easily when inode freed or when | ||
| 111 | notify info is cleared/changed */ | ||
| 112 | cFYI(1, ("notify rc %d", rc)); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | FreeXid(xid); | ||
| 117 | return rc; | ||
| 118 | } | ||
diff --git a/fs/dcache.c b/fs/dcache.c index a1d86c7f3e66..e88c23b85a32 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
| 35 | #include "internal.h" | 35 | #include "internal.h" |
| 36 | 36 | ||
| 37 | |||
| 38 | int sysctl_vfs_cache_pressure __read_mostly = 100; | 37 | int sysctl_vfs_cache_pressure __read_mostly = 100; |
| 39 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); | 38 | EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); |
| 40 | 39 | ||
| @@ -948,9 +947,6 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
| 948 | dentry->d_op = NULL; | 947 | dentry->d_op = NULL; |
| 949 | dentry->d_fsdata = NULL; | 948 | dentry->d_fsdata = NULL; |
| 950 | dentry->d_mounted = 0; | 949 | dentry->d_mounted = 0; |
| 951 | #ifdef CONFIG_PROFILING | ||
| 952 | dentry->d_cookie = NULL; | ||
| 953 | #endif | ||
| 954 | INIT_HLIST_NODE(&dentry->d_hash); | 950 | INIT_HLIST_NODE(&dentry->d_hash); |
| 955 | INIT_LIST_HEAD(&dentry->d_lru); | 951 | INIT_LIST_HEAD(&dentry->d_lru); |
| 956 | INIT_LIST_HEAD(&dentry->d_subdirs); | 952 | INIT_LIST_HEAD(&dentry->d_subdirs); |
| @@ -1336,7 +1332,7 @@ err_out: | |||
| 1336 | * | 1332 | * |
| 1337 | * Searches the children of the parent dentry for the name in question. If | 1333 | * Searches the children of the parent dentry for the name in question. If |
| 1338 | * the dentry is found its reference count is incremented and the dentry | 1334 | * the dentry is found its reference count is incremented and the dentry |
| 1339 | * is returned. The caller must use d_put to free the entry when it has | 1335 | * is returned. The caller must use dput to free the entry when it has |
| 1340 | * finished using it. %NULL is returned on failure. | 1336 | * finished using it. %NULL is returned on failure. |
| 1341 | * | 1337 | * |
| 1342 | * __d_lookup is dcache_lock free. The hash list is protected using RCU. | 1338 | * __d_lookup is dcache_lock free. The hash list is protected using RCU. |
| @@ -1620,8 +1616,11 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
| 1620 | */ | 1616 | */ |
| 1621 | memcpy(dentry->d_iname, target->d_name.name, | 1617 | memcpy(dentry->d_iname, target->d_name.name, |
| 1622 | target->d_name.len + 1); | 1618 | target->d_name.len + 1); |
| 1619 | dentry->d_name.len = target->d_name.len; | ||
| 1620 | return; | ||
| 1623 | } | 1621 | } |
| 1624 | } | 1622 | } |
| 1623 | do_switch(dentry->d_name.len, target->d_name.len); | ||
| 1625 | } | 1624 | } |
| 1626 | 1625 | ||
| 1627 | /* | 1626 | /* |
| @@ -1681,7 +1680,6 @@ already_unhashed: | |||
| 1681 | 1680 | ||
| 1682 | /* Switch the names.. */ | 1681 | /* Switch the names.. */ |
| 1683 | switch_names(dentry, target); | 1682 | switch_names(dentry, target); |
| 1684 | do_switch(dentry->d_name.len, target->d_name.len); | ||
| 1685 | do_switch(dentry->d_name.hash, target->d_name.hash); | 1683 | do_switch(dentry->d_name.hash, target->d_name.hash); |
| 1686 | 1684 | ||
| 1687 | /* ... and switch the parents */ | 1685 | /* ... and switch the parents */ |
| @@ -1791,7 +1789,6 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | |||
| 1791 | struct dentry *dparent, *aparent; | 1789 | struct dentry *dparent, *aparent; |
| 1792 | 1790 | ||
| 1793 | switch_names(dentry, anon); | 1791 | switch_names(dentry, anon); |
| 1794 | do_switch(dentry->d_name.len, anon->d_name.len); | ||
| 1795 | do_switch(dentry->d_name.hash, anon->d_name.hash); | 1792 | do_switch(dentry->d_name.hash, anon->d_name.hash); |
| 1796 | 1793 | ||
| 1797 | dparent = dentry->d_parent; | 1794 | dparent = dentry->d_parent; |
| @@ -1911,7 +1908,8 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) | |||
| 1911 | * Convert a dentry into an ASCII path name. If the entry has been deleted | 1908 | * Convert a dentry into an ASCII path name. If the entry has been deleted |
| 1912 | * the string " (deleted)" is appended. Note that this is ambiguous. | 1909 | * the string " (deleted)" is appended. Note that this is ambiguous. |
| 1913 | * | 1910 | * |
| 1914 | * Returns the buffer or an error code if the path was too long. | 1911 | * Returns a pointer into the buffer or an error code if the |
| 1912 | * path was too long. | ||
| 1915 | * | 1913 | * |
| 1916 | * "buflen" should be positive. Caller holds the dcache_lock. | 1914 | * "buflen" should be positive. Caller holds the dcache_lock. |
| 1917 | * | 1915 | * |
| @@ -1987,7 +1985,10 @@ Elong: | |||
| 1987 | * Convert a dentry into an ASCII path name. If the entry has been deleted | 1985 | * Convert a dentry into an ASCII path name. If the entry has been deleted |
| 1988 | * the string " (deleted)" is appended. Note that this is ambiguous. | 1986 | * the string " (deleted)" is appended. Note that this is ambiguous. |
| 1989 | * | 1987 | * |
| 1990 | * Returns the buffer or an error code if the path was too long. | 1988 | * Returns a pointer into the buffer or an error code if the path was |
| 1989 | * too long. Note: Callers should use the returned pointer, not the passed | ||
| 1990 | * in buffer, to use the name! The implementation often starts at an offset | ||
| 1991 | * into the buffer, and may leave 0 bytes at the start. | ||
| 1991 | * | 1992 | * |
| 1992 | * "buflen" should be positive. | 1993 | * "buflen" should be positive. |
| 1993 | */ | 1994 | */ |
| @@ -2313,9 +2314,6 @@ static void __init dcache_init(void) | |||
| 2313 | /* SLAB cache for __getname() consumers */ | 2314 | /* SLAB cache for __getname() consumers */ |
| 2314 | struct kmem_cache *names_cachep __read_mostly; | 2315 | struct kmem_cache *names_cachep __read_mostly; |
| 2315 | 2316 | ||
| 2316 | /* SLAB cache for file structures */ | ||
| 2317 | struct kmem_cache *filp_cachep __read_mostly; | ||
| 2318 | |||
| 2319 | EXPORT_SYMBOL(d_genocide); | 2317 | EXPORT_SYMBOL(d_genocide); |
| 2320 | 2318 | ||
| 2321 | void __init vfs_caches_init_early(void) | 2319 | void __init vfs_caches_init_early(void) |
| @@ -2337,9 +2335,6 @@ void __init vfs_caches_init(unsigned long mempages) | |||
| 2337 | names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, | 2335 | names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, |
| 2338 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 2336 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); |
| 2339 | 2337 | ||
| 2340 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | ||
| 2341 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | ||
| 2342 | |||
| 2343 | dcache_init(); | 2338 | dcache_init(); |
| 2344 | inode_init(); | 2339 | inode_init(); |
| 2345 | files_init(mempages); | 2340 | files_init(mempages); |
diff --git a/fs/dcookies.c b/fs/dcookies.c index 855d4b1d619a..180e9fec4ad8 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c | |||
| @@ -93,10 +93,15 @@ static struct dcookie_struct *alloc_dcookie(struct path *path) | |||
| 93 | { | 93 | { |
| 94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, | 94 | struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, |
| 95 | GFP_KERNEL); | 95 | GFP_KERNEL); |
| 96 | struct dentry *d; | ||
| 96 | if (!dcs) | 97 | if (!dcs) |
| 97 | return NULL; | 98 | return NULL; |
| 98 | 99 | ||
| 99 | path->dentry->d_cookie = dcs; | 100 | d = path->dentry; |
| 101 | spin_lock(&d->d_lock); | ||
| 102 | d->d_flags |= DCACHE_COOKIE; | ||
| 103 | spin_unlock(&d->d_lock); | ||
| 104 | |||
| 100 | dcs->path = *path; | 105 | dcs->path = *path; |
| 101 | path_get(path); | 106 | path_get(path); |
| 102 | hash_dcookie(dcs); | 107 | hash_dcookie(dcs); |
| @@ -119,14 +124,14 @@ int get_dcookie(struct path *path, unsigned long *cookie) | |||
| 119 | goto out; | 124 | goto out; |
| 120 | } | 125 | } |
| 121 | 126 | ||
| 122 | dcs = path->dentry->d_cookie; | 127 | if (path->dentry->d_flags & DCACHE_COOKIE) { |
| 123 | 128 | dcs = find_dcookie((unsigned long)path->dentry); | |
| 124 | if (!dcs) | 129 | } else { |
| 125 | dcs = alloc_dcookie(path); | 130 | dcs = alloc_dcookie(path); |
| 126 | 131 | if (!dcs) { | |
| 127 | if (!dcs) { | 132 | err = -ENOMEM; |
| 128 | err = -ENOMEM; | 133 | goto out; |
| 129 | goto out; | 134 | } |
| 130 | } | 135 | } |
| 131 | 136 | ||
| 132 | *cookie = dcookie_value(dcs); | 137 | *cookie = dcookie_value(dcs); |
| @@ -251,7 +256,12 @@ out_kmem: | |||
| 251 | 256 | ||
| 252 | static void free_dcookie(struct dcookie_struct * dcs) | 257 | static void free_dcookie(struct dcookie_struct * dcs) |
| 253 | { | 258 | { |
| 254 | dcs->path.dentry->d_cookie = NULL; | 259 | struct dentry *d = dcs->path.dentry; |
| 260 | |||
| 261 | spin_lock(&d->d_lock); | ||
| 262 | d->d_flags &= ~DCACHE_COOKIE; | ||
| 263 | spin_unlock(&d->d_lock); | ||
| 264 | |||
| 255 | path_put(&dcs->path); | 265 | path_put(&dcs->path); |
| 256 | kmem_cache_free(dcookie_cache, dcs); | 266 | kmem_cache_free(dcookie_cache, dcs); |
| 257 | } | 267 | } |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 89209f00f9c7..5e78fc179886 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -673,10 +673,11 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 673 | ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " | 673 | ecryptfs_printk(KERN_DEBUG, "Calling readlink w/ " |
| 674 | "dentry->d_name.name = [%s]\n", dentry->d_name.name); | 674 | "dentry->d_name.name = [%s]\n", dentry->d_name.name); |
| 675 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); | 675 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); |
| 676 | buf[rc] = '\0'; | ||
| 677 | set_fs(old_fs); | 676 | set_fs(old_fs); |
| 678 | if (rc < 0) | 677 | if (rc < 0) |
| 679 | goto out_free; | 678 | goto out_free; |
| 679 | else | ||
| 680 | buf[rc] = '\0'; | ||
| 680 | rc = 0; | 681 | rc = 0; |
| 681 | nd_set_link(nd, buf); | 682 | nd_set_link(nd, buf); |
| 682 | goto out; | 683 | goto out; |
| @@ -127,7 +127,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
| 127 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 127 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
| 128 | goto exit; | 128 | goto exit; |
| 129 | 129 | ||
| 130 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | 130 | error = inode_permission(nd.path.dentry->d_inode, |
| 131 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
| 131 | if (error) | 132 | if (error) |
| 132 | goto exit; | 133 | goto exit; |
| 133 | 134 | ||
| @@ -680,7 +681,7 @@ struct file *open_exec(const char *name) | |||
| 680 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 681 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
| 681 | goto out_path_put; | 682 | goto out_path_put; |
| 682 | 683 | ||
| 683 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); | 684 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
| 684 | if (err) | 685 | if (err) |
| 685 | goto out_path_put; | 686 | goto out_path_put; |
| 686 | 687 | ||
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 8d0add625870..c454d5db28a5 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
| @@ -585,7 +585,10 @@ got: | |||
| 585 | spin_lock(&sbi->s_next_gen_lock); | 585 | spin_lock(&sbi->s_next_gen_lock); |
| 586 | inode->i_generation = sbi->s_next_generation++; | 586 | inode->i_generation = sbi->s_next_generation++; |
| 587 | spin_unlock(&sbi->s_next_gen_lock); | 587 | spin_unlock(&sbi->s_next_gen_lock); |
| 588 | insert_inode_hash(inode); | 588 | if (insert_inode_locked(inode) < 0) { |
| 589 | err = -EINVAL; | ||
| 590 | goto fail_drop; | ||
| 591 | } | ||
| 589 | 592 | ||
| 590 | if (DQUOT_ALLOC_INODE(inode)) { | 593 | if (DQUOT_ALLOC_INODE(inode)) { |
| 591 | err = -EDQUOT; | 594 | err = -EDQUOT; |
| @@ -612,6 +615,7 @@ fail_drop: | |||
| 612 | DQUOT_DROP(inode); | 615 | DQUOT_DROP(inode); |
| 613 | inode->i_flags |= S_NOQUOTA; | 616 | inode->i_flags |= S_NOQUOTA; |
| 614 | inode->i_nlink = 0; | 617 | inode->i_nlink = 0; |
| 618 | unlock_new_inode(inode); | ||
| 615 | iput(inode); | 619 | iput(inode); |
| 616 | return ERR_PTR(err); | 620 | return ERR_PTR(err); |
| 617 | 621 | ||
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 7658b33e2653..02b39a5deb74 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/buffer_head.h> | 32 | #include <linux/buffer_head.h> |
| 33 | #include <linux/mpage.h> | 33 | #include <linux/mpage.h> |
| 34 | #include <linux/fiemap.h> | 34 | #include <linux/fiemap.h> |
| 35 | #include <linux/namei.h> | ||
| 35 | #include "ext2.h" | 36 | #include "ext2.h" |
| 36 | #include "acl.h" | 37 | #include "acl.h" |
| 37 | #include "xip.h" | 38 | #include "xip.h" |
| @@ -1286,9 +1287,11 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
| 1286 | else | 1287 | else |
| 1287 | inode->i_mapping->a_ops = &ext2_aops; | 1288 | inode->i_mapping->a_ops = &ext2_aops; |
| 1288 | } else if (S_ISLNK(inode->i_mode)) { | 1289 | } else if (S_ISLNK(inode->i_mode)) { |
| 1289 | if (ext2_inode_is_fast_symlink(inode)) | 1290 | if (ext2_inode_is_fast_symlink(inode)) { |
| 1290 | inode->i_op = &ext2_fast_symlink_inode_operations; | 1291 | inode->i_op = &ext2_fast_symlink_inode_operations; |
| 1291 | else { | 1292 | nd_terminate_link(ei->i_data, inode->i_size, |
| 1293 | sizeof(ei->i_data) - 1); | ||
| 1294 | } else { | ||
| 1292 | inode->i_op = &ext2_symlink_inode_operations; | 1295 | inode->i_op = &ext2_symlink_inode_operations; |
| 1293 | if (test_opt(inode->i_sb, NOBH)) | 1296 | if (test_opt(inode->i_sb, NOBH)) |
| 1294 | inode->i_mapping->a_ops = &ext2_nobh_aops; | 1297 | inode->i_mapping->a_ops = &ext2_nobh_aops; |
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 2a747252ec12..90ea17998a73 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
| @@ -41,9 +41,11 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) | |||
| 41 | int err = ext2_add_link(dentry, inode); | 41 | int err = ext2_add_link(dentry, inode); |
| 42 | if (!err) { | 42 | if (!err) { |
| 43 | d_instantiate(dentry, inode); | 43 | d_instantiate(dentry, inode); |
| 44 | unlock_new_inode(inode); | ||
| 44 | return 0; | 45 | return 0; |
| 45 | } | 46 | } |
| 46 | inode_dec_link_count(inode); | 47 | inode_dec_link_count(inode); |
| 48 | unlock_new_inode(inode); | ||
| 47 | iput(inode); | 49 | iput(inode); |
| 48 | return err; | 50 | return err; |
| 49 | } | 51 | } |
| @@ -170,6 +172,7 @@ out: | |||
| 170 | 172 | ||
| 171 | out_fail: | 173 | out_fail: |
| 172 | inode_dec_link_count(inode); | 174 | inode_dec_link_count(inode); |
| 175 | unlock_new_inode(inode); | ||
| 173 | iput (inode); | 176 | iput (inode); |
| 174 | goto out; | 177 | goto out; |
| 175 | } | 178 | } |
| @@ -178,6 +181,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, | |||
| 178 | struct dentry *dentry) | 181 | struct dentry *dentry) |
| 179 | { | 182 | { |
| 180 | struct inode *inode = old_dentry->d_inode; | 183 | struct inode *inode = old_dentry->d_inode; |
| 184 | int err; | ||
| 181 | 185 | ||
| 182 | if (inode->i_nlink >= EXT2_LINK_MAX) | 186 | if (inode->i_nlink >= EXT2_LINK_MAX) |
| 183 | return -EMLINK; | 187 | return -EMLINK; |
| @@ -186,7 +190,14 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, | |||
| 186 | inode_inc_link_count(inode); | 190 | inode_inc_link_count(inode); |
| 187 | atomic_inc(&inode->i_count); | 191 | atomic_inc(&inode->i_count); |
| 188 | 192 | ||
| 189 | return ext2_add_nondir(dentry, inode); | 193 | err = ext2_add_link(dentry, inode); |
| 194 | if (!err) { | ||
| 195 | d_instantiate(dentry, inode); | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | inode_dec_link_count(inode); | ||
| 199 | iput(inode); | ||
| 200 | return err; | ||
| 190 | } | 201 | } |
| 191 | 202 | ||
| 192 | static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) | 203 | static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) |
| @@ -222,12 +233,14 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode) | |||
| 222 | goto out_fail; | 233 | goto out_fail; |
| 223 | 234 | ||
| 224 | d_instantiate(dentry, inode); | 235 | d_instantiate(dentry, inode); |
| 236 | unlock_new_inode(inode); | ||
| 225 | out: | 237 | out: |
| 226 | return err; | 238 | return err; |
| 227 | 239 | ||
| 228 | out_fail: | 240 | out_fail: |
| 229 | inode_dec_link_count(inode); | 241 | inode_dec_link_count(inode); |
| 230 | inode_dec_link_count(inode); | 242 | inode_dec_link_count(inode); |
| 243 | unlock_new_inode(inode); | ||
| 231 | iput(inode); | 244 | iput(inode); |
| 232 | out_dir: | 245 | out_dir: |
| 233 | inode_dec_link_count(dir); | 246 | inode_dec_link_count(dir); |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 490bd0ed7896..5655fbcbd11f 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
| @@ -579,7 +579,10 @@ got: | |||
| 579 | ext3_set_inode_flags(inode); | 579 | ext3_set_inode_flags(inode); |
| 580 | if (IS_DIRSYNC(inode)) | 580 | if (IS_DIRSYNC(inode)) |
| 581 | handle->h_sync = 1; | 581 | handle->h_sync = 1; |
| 582 | insert_inode_hash(inode); | 582 | if (insert_inode_locked(inode) < 0) { |
| 583 | err = -EINVAL; | ||
| 584 | goto fail_drop; | ||
| 585 | } | ||
| 583 | spin_lock(&sbi->s_next_gen_lock); | 586 | spin_lock(&sbi->s_next_gen_lock); |
| 584 | inode->i_generation = sbi->s_next_generation++; | 587 | inode->i_generation = sbi->s_next_generation++; |
| 585 | spin_unlock(&sbi->s_next_gen_lock); | 588 | spin_unlock(&sbi->s_next_gen_lock); |
| @@ -627,6 +630,7 @@ fail_drop: | |||
| 627 | DQUOT_DROP(inode); | 630 | DQUOT_DROP(inode); |
| 628 | inode->i_flags |= S_NOQUOTA; | 631 | inode->i_flags |= S_NOQUOTA; |
| 629 | inode->i_nlink = 0; | 632 | inode->i_nlink = 0; |
| 633 | unlock_new_inode(inode); | ||
| 630 | iput(inode); | 634 | iput(inode); |
| 631 | brelse(bitmap_bh); | 635 | brelse(bitmap_bh); |
| 632 | return ERR_PTR(err); | 636 | return ERR_PTR(err); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index f8424ad89971..c4bdccf976b5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/uio.h> | 37 | #include <linux/uio.h> |
| 38 | #include <linux/bio.h> | 38 | #include <linux/bio.h> |
| 39 | #include <linux/fiemap.h> | 39 | #include <linux/fiemap.h> |
| 40 | #include <linux/namei.h> | ||
| 40 | #include "xattr.h" | 41 | #include "xattr.h" |
| 41 | #include "acl.h" | 42 | #include "acl.h" |
| 42 | 43 | ||
| @@ -2817,9 +2818,11 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) | |||
| 2817 | inode->i_op = &ext3_dir_inode_operations; | 2818 | inode->i_op = &ext3_dir_inode_operations; |
| 2818 | inode->i_fop = &ext3_dir_operations; | 2819 | inode->i_fop = &ext3_dir_operations; |
| 2819 | } else if (S_ISLNK(inode->i_mode)) { | 2820 | } else if (S_ISLNK(inode->i_mode)) { |
| 2820 | if (ext3_inode_is_fast_symlink(inode)) | 2821 | if (ext3_inode_is_fast_symlink(inode)) { |
| 2821 | inode->i_op = &ext3_fast_symlink_inode_operations; | 2822 | inode->i_op = &ext3_fast_symlink_inode_operations; |
| 2822 | else { | 2823 | nd_terminate_link(ei->i_data, inode->i_size, |
| 2824 | sizeof(ei->i_data) - 1); | ||
| 2825 | } else { | ||
| 2823 | inode->i_op = &ext3_symlink_inode_operations; | 2826 | inode->i_op = &ext3_symlink_inode_operations; |
| 2824 | ext3_set_aops(inode); | 2827 | ext3_set_aops(inode); |
| 2825 | } | 2828 | } |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 3e5edc92aa0b..297ea8dfac7c 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -1652,9 +1652,11 @@ static int ext3_add_nondir(handle_t *handle, | |||
| 1652 | if (!err) { | 1652 | if (!err) { |
| 1653 | ext3_mark_inode_dirty(handle, inode); | 1653 | ext3_mark_inode_dirty(handle, inode); |
| 1654 | d_instantiate(dentry, inode); | 1654 | d_instantiate(dentry, inode); |
| 1655 | unlock_new_inode(inode); | ||
| 1655 | return 0; | 1656 | return 0; |
| 1656 | } | 1657 | } |
| 1657 | drop_nlink(inode); | 1658 | drop_nlink(inode); |
| 1659 | unlock_new_inode(inode); | ||
| 1658 | iput(inode); | 1660 | iput(inode); |
| 1659 | return err; | 1661 | return err; |
| 1660 | } | 1662 | } |
| @@ -1765,6 +1767,7 @@ retry: | |||
| 1765 | dir_block = ext3_bread (handle, inode, 0, 1, &err); | 1767 | dir_block = ext3_bread (handle, inode, 0, 1, &err); |
| 1766 | if (!dir_block) { | 1768 | if (!dir_block) { |
| 1767 | drop_nlink(inode); /* is this nlink == 0? */ | 1769 | drop_nlink(inode); /* is this nlink == 0? */ |
| 1770 | unlock_new_inode(inode); | ||
| 1768 | ext3_mark_inode_dirty(handle, inode); | 1771 | ext3_mark_inode_dirty(handle, inode); |
| 1769 | iput (inode); | 1772 | iput (inode); |
| 1770 | goto out_stop; | 1773 | goto out_stop; |
| @@ -1792,6 +1795,7 @@ retry: | |||
| 1792 | err = ext3_add_entry (handle, dentry, inode); | 1795 | err = ext3_add_entry (handle, dentry, inode); |
| 1793 | if (err) { | 1796 | if (err) { |
| 1794 | inode->i_nlink = 0; | 1797 | inode->i_nlink = 0; |
| 1798 | unlock_new_inode(inode); | ||
| 1795 | ext3_mark_inode_dirty(handle, inode); | 1799 | ext3_mark_inode_dirty(handle, inode); |
| 1796 | iput (inode); | 1800 | iput (inode); |
| 1797 | goto out_stop; | 1801 | goto out_stop; |
| @@ -1800,6 +1804,7 @@ retry: | |||
| 1800 | ext3_update_dx_flag(dir); | 1804 | ext3_update_dx_flag(dir); |
| 1801 | ext3_mark_inode_dirty(handle, dir); | 1805 | ext3_mark_inode_dirty(handle, dir); |
| 1802 | d_instantiate(dentry, inode); | 1806 | d_instantiate(dentry, inode); |
| 1807 | unlock_new_inode(inode); | ||
| 1803 | out_stop: | 1808 | out_stop: |
| 1804 | ext3_journal_stop(handle); | 1809 | ext3_journal_stop(handle); |
| 1805 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 1810 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
| @@ -2174,6 +2179,7 @@ retry: | |||
| 2174 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2179 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
| 2175 | if (err) { | 2180 | if (err) { |
| 2176 | drop_nlink(inode); | 2181 | drop_nlink(inode); |
| 2182 | unlock_new_inode(inode); | ||
| 2177 | ext3_mark_inode_dirty(handle, inode); | 2183 | ext3_mark_inode_dirty(handle, inode); |
| 2178 | iput (inode); | 2184 | iput (inode); |
| 2179 | goto out_stop; | 2185 | goto out_stop; |
| @@ -2221,7 +2227,14 @@ retry: | |||
| 2221 | inc_nlink(inode); | 2227 | inc_nlink(inode); |
| 2222 | atomic_inc(&inode->i_count); | 2228 | atomic_inc(&inode->i_count); |
| 2223 | 2229 | ||
| 2224 | err = ext3_add_nondir(handle, dentry, inode); | 2230 | err = ext3_add_entry(handle, dentry, inode); |
| 2231 | if (!err) { | ||
| 2232 | ext3_mark_inode_dirty(handle, inode); | ||
| 2233 | d_instantiate(dentry, inode); | ||
| 2234 | } else { | ||
| 2235 | drop_nlink(inode); | ||
| 2236 | iput(inode); | ||
| 2237 | } | ||
| 2225 | ext3_journal_stop(handle); | 2238 | ext3_journal_stop(handle); |
| 2226 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 2239 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
| 2227 | goto retry; | 2240 | goto retry; |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 08cac9fcace2..6e6052879aa2 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -826,7 +826,10 @@ got: | |||
| 826 | ext4_set_inode_flags(inode); | 826 | ext4_set_inode_flags(inode); |
| 827 | if (IS_DIRSYNC(inode)) | 827 | if (IS_DIRSYNC(inode)) |
| 828 | handle->h_sync = 1; | 828 | handle->h_sync = 1; |
| 829 | insert_inode_hash(inode); | 829 | if (insert_inode_locked(inode) < 0) { |
| 830 | err = -EINVAL; | ||
| 831 | goto fail_drop; | ||
| 832 | } | ||
| 830 | spin_lock(&sbi->s_next_gen_lock); | 833 | spin_lock(&sbi->s_next_gen_lock); |
| 831 | inode->i_generation = sbi->s_next_generation++; | 834 | inode->i_generation = sbi->s_next_generation++; |
| 832 | spin_unlock(&sbi->s_next_gen_lock); | 835 | spin_unlock(&sbi->s_next_gen_lock); |
| @@ -881,6 +884,7 @@ fail_drop: | |||
| 881 | DQUOT_DROP(inode); | 884 | DQUOT_DROP(inode); |
| 882 | inode->i_flags |= S_NOQUOTA; | 885 | inode->i_flags |= S_NOQUOTA; |
| 883 | inode->i_nlink = 0; | 886 | inode->i_nlink = 0; |
| 887 | unlock_new_inode(inode); | ||
| 884 | iput(inode); | 888 | iput(inode); |
| 885 | brelse(bitmap_bh); | 889 | brelse(bitmap_bh); |
| 886 | return ERR_PTR(err); | 890 | return ERR_PTR(err); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index be21a5ae33cb..7c3325e0b005 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/writeback.h> | 34 | #include <linux/writeback.h> |
| 35 | #include <linux/pagevec.h> | 35 | #include <linux/pagevec.h> |
| 36 | #include <linux/mpage.h> | 36 | #include <linux/mpage.h> |
| 37 | #include <linux/namei.h> | ||
| 37 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
| 38 | #include <linux/bio.h> | 39 | #include <linux/bio.h> |
| 39 | #include "ext4_jbd2.h" | 40 | #include "ext4_jbd2.h" |
| @@ -4164,9 +4165,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
| 4164 | inode->i_op = &ext4_dir_inode_operations; | 4165 | inode->i_op = &ext4_dir_inode_operations; |
| 4165 | inode->i_fop = &ext4_dir_operations; | 4166 | inode->i_fop = &ext4_dir_operations; |
| 4166 | } else if (S_ISLNK(inode->i_mode)) { | 4167 | } else if (S_ISLNK(inode->i_mode)) { |
| 4167 | if (ext4_inode_is_fast_symlink(inode)) | 4168 | if (ext4_inode_is_fast_symlink(inode)) { |
| 4168 | inode->i_op = &ext4_fast_symlink_inode_operations; | 4169 | inode->i_op = &ext4_fast_symlink_inode_operations; |
| 4169 | else { | 4170 | nd_terminate_link(ei->i_data, inode->i_size, |
| 4171 | sizeof(ei->i_data) - 1); | ||
| 4172 | } else { | ||
| 4170 | inode->i_op = &ext4_symlink_inode_operations; | 4173 | inode->i_op = &ext4_symlink_inode_operations; |
| 4171 | ext4_set_aops(inode); | 4174 | ext4_set_aops(inode); |
| 4172 | } | 4175 | } |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 63adcb792988..da98a9012fa5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -1693,9 +1693,11 @@ static int ext4_add_nondir(handle_t *handle, | |||
| 1693 | if (!err) { | 1693 | if (!err) { |
| 1694 | ext4_mark_inode_dirty(handle, inode); | 1694 | ext4_mark_inode_dirty(handle, inode); |
| 1695 | d_instantiate(dentry, inode); | 1695 | d_instantiate(dentry, inode); |
| 1696 | unlock_new_inode(inode); | ||
| 1696 | return 0; | 1697 | return 0; |
| 1697 | } | 1698 | } |
| 1698 | drop_nlink(inode); | 1699 | drop_nlink(inode); |
| 1700 | unlock_new_inode(inode); | ||
| 1699 | iput(inode); | 1701 | iput(inode); |
| 1700 | return err; | 1702 | return err; |
| 1701 | } | 1703 | } |
| @@ -1830,6 +1832,7 @@ retry: | |||
| 1830 | if (err) { | 1832 | if (err) { |
| 1831 | out_clear_inode: | 1833 | out_clear_inode: |
| 1832 | clear_nlink(inode); | 1834 | clear_nlink(inode); |
| 1835 | unlock_new_inode(inode); | ||
| 1833 | ext4_mark_inode_dirty(handle, inode); | 1836 | ext4_mark_inode_dirty(handle, inode); |
| 1834 | iput(inode); | 1837 | iput(inode); |
| 1835 | goto out_stop; | 1838 | goto out_stop; |
| @@ -1838,6 +1841,7 @@ out_clear_inode: | |||
| 1838 | ext4_update_dx_flag(dir); | 1841 | ext4_update_dx_flag(dir); |
| 1839 | ext4_mark_inode_dirty(handle, dir); | 1842 | ext4_mark_inode_dirty(handle, dir); |
| 1840 | d_instantiate(dentry, inode); | 1843 | d_instantiate(dentry, inode); |
| 1844 | unlock_new_inode(inode); | ||
| 1841 | out_stop: | 1845 | out_stop: |
| 1842 | ext4_journal_stop(handle); | 1846 | ext4_journal_stop(handle); |
| 1843 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 1847 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
| @@ -2212,6 +2216,7 @@ retry: | |||
| 2212 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 2216 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); |
| 2213 | if (err) { | 2217 | if (err) { |
| 2214 | clear_nlink(inode); | 2218 | clear_nlink(inode); |
| 2219 | unlock_new_inode(inode); | ||
| 2215 | ext4_mark_inode_dirty(handle, inode); | 2220 | ext4_mark_inode_dirty(handle, inode); |
| 2216 | iput(inode); | 2221 | iput(inode); |
| 2217 | goto out_stop; | 2222 | goto out_stop; |
| @@ -2262,7 +2267,14 @@ retry: | |||
| 2262 | ext4_inc_count(handle, inode); | 2267 | ext4_inc_count(handle, inode); |
| 2263 | atomic_inc(&inode->i_count); | 2268 | atomic_inc(&inode->i_count); |
| 2264 | 2269 | ||
| 2265 | err = ext4_add_nondir(handle, dentry, inode); | 2270 | err = ext4_add_entry(handle, dentry, inode); |
| 2271 | if (!err) { | ||
| 2272 | ext4_mark_inode_dirty(handle, inode); | ||
| 2273 | d_instantiate(dentry, inode); | ||
| 2274 | } else { | ||
| 2275 | drop_nlink(inode); | ||
| 2276 | iput(inode); | ||
| 2277 | } | ||
| 2266 | ext4_journal_stop(handle); | 2278 | ext4_journal_stop(handle); |
| 2267 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 2279 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
| 2268 | goto retry; | 2280 | goto retry; |
diff --git a/fs/file_table.c b/fs/file_table.c index 0fbcacc3ea75..bbeeac6efa1a 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -32,6 +32,9 @@ struct files_stat_struct files_stat = { | |||
| 32 | /* public. Not pretty! */ | 32 | /* public. Not pretty! */ |
| 33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); | 33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); |
| 34 | 34 | ||
| 35 | /* SLAB cache for file structures */ | ||
| 36 | static struct kmem_cache *filp_cachep __read_mostly; | ||
| 37 | |||
| 35 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; | 38 | static struct percpu_counter nr_files __cacheline_aligned_in_smp; |
| 36 | 39 | ||
| 37 | static inline void file_free_rcu(struct rcu_head *head) | 40 | static inline void file_free_rcu(struct rcu_head *head) |
| @@ -397,7 +400,12 @@ too_bad: | |||
| 397 | void __init files_init(unsigned long mempages) | 400 | void __init files_init(unsigned long mempages) |
| 398 | { | 401 | { |
| 399 | int n; | 402 | int n; |
| 400 | /* One file with associated inode and dcache is very roughly 1K. | 403 | |
| 404 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | ||
| 405 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | ||
| 406 | |||
| 407 | /* | ||
| 408 | * One file with associated inode and dcache is very roughly 1K. | ||
| 401 | * Per default don't use more than 10% of our memory for files. | 409 | * Per default don't use more than 10% of our memory for files. |
| 402 | */ | 410 | */ |
| 403 | 411 | ||
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 9f3f2ceb73f0..03a6ea5e99f7 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c | |||
| @@ -325,8 +325,10 @@ vxfs_iget(struct super_block *sbp, ino_t ino) | |||
| 325 | if (!VXFS_ISIMMED(vip)) { | 325 | if (!VXFS_ISIMMED(vip)) { |
| 326 | ip->i_op = &page_symlink_inode_operations; | 326 | ip->i_op = &page_symlink_inode_operations; |
| 327 | ip->i_mapping->a_ops = &vxfs_aops; | 327 | ip->i_mapping->a_ops = &vxfs_aops; |
| 328 | } else | 328 | } else { |
| 329 | ip->i_op = &vxfs_immed_symlink_iops; | 329 | ip->i_op = &vxfs_immed_symlink_iops; |
| 330 | vip->vii_immed.vi_immed[ip->i_size] = '\0'; | ||
| 331 | } | ||
| 330 | } else | 332 | } else |
| 331 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); | 333 | init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); |
| 332 | 334 | ||
diff --git a/fs/inode.c b/fs/inode.c index 098a2443196f..7de1cda92489 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1032,6 +1032,65 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino) | |||
| 1032 | 1032 | ||
| 1033 | EXPORT_SYMBOL(iget_locked); | 1033 | EXPORT_SYMBOL(iget_locked); |
| 1034 | 1034 | ||
| 1035 | int insert_inode_locked(struct inode *inode) | ||
| 1036 | { | ||
| 1037 | struct super_block *sb = inode->i_sb; | ||
| 1038 | ino_t ino = inode->i_ino; | ||
| 1039 | struct hlist_head *head = inode_hashtable + hash(sb, ino); | ||
| 1040 | struct inode *old; | ||
| 1041 | |||
| 1042 | inode->i_state |= I_LOCK|I_NEW; | ||
| 1043 | while (1) { | ||
| 1044 | spin_lock(&inode_lock); | ||
| 1045 | old = find_inode_fast(sb, head, ino); | ||
| 1046 | if (likely(!old)) { | ||
| 1047 | hlist_add_head(&inode->i_hash, head); | ||
| 1048 | spin_unlock(&inode_lock); | ||
| 1049 | return 0; | ||
| 1050 | } | ||
| 1051 | __iget(old); | ||
| 1052 | spin_unlock(&inode_lock); | ||
| 1053 | wait_on_inode(old); | ||
| 1054 | if (unlikely(!hlist_unhashed(&old->i_hash))) { | ||
| 1055 | iput(old); | ||
| 1056 | return -EBUSY; | ||
| 1057 | } | ||
| 1058 | iput(old); | ||
| 1059 | } | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | EXPORT_SYMBOL(insert_inode_locked); | ||
| 1063 | |||
| 1064 | int insert_inode_locked4(struct inode *inode, unsigned long hashval, | ||
| 1065 | int (*test)(struct inode *, void *), void *data) | ||
| 1066 | { | ||
| 1067 | struct super_block *sb = inode->i_sb; | ||
| 1068 | struct hlist_head *head = inode_hashtable + hash(sb, hashval); | ||
| 1069 | struct inode *old; | ||
| 1070 | |||
| 1071 | inode->i_state |= I_LOCK|I_NEW; | ||
| 1072 | |||
| 1073 | while (1) { | ||
| 1074 | spin_lock(&inode_lock); | ||
| 1075 | old = find_inode(sb, head, test, data); | ||
| 1076 | if (likely(!old)) { | ||
| 1077 | hlist_add_head(&inode->i_hash, head); | ||
| 1078 | spin_unlock(&inode_lock); | ||
| 1079 | return 0; | ||
| 1080 | } | ||
| 1081 | __iget(old); | ||
| 1082 | spin_unlock(&inode_lock); | ||
| 1083 | wait_on_inode(old); | ||
| 1084 | if (unlikely(!hlist_unhashed(&old->i_hash))) { | ||
| 1085 | iput(old); | ||
| 1086 | return -EBUSY; | ||
| 1087 | } | ||
| 1088 | iput(old); | ||
| 1089 | } | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | EXPORT_SYMBOL(insert_inode_locked4); | ||
| 1093 | |||
| 1035 | /** | 1094 | /** |
| 1036 | * __insert_inode_hash - hash an inode | 1095 | * __insert_inode_hash - hash an inode |
| 1037 | * @inode: unhashed inode | 1096 | * @inode: unhashed inode |
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index 70022fd1c539..d4d142c2edd4 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c | |||
| @@ -79,7 +79,8 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
| 79 | inode = new_inode(sb); | 79 | inode = new_inode(sb); |
| 80 | if (!inode) { | 80 | if (!inode) { |
| 81 | jfs_warn("ialloc: new_inode returned NULL!"); | 81 | jfs_warn("ialloc: new_inode returned NULL!"); |
| 82 | return ERR_PTR(-ENOMEM); | 82 | rc = -ENOMEM; |
| 83 | goto fail; | ||
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | jfs_inode = JFS_IP(inode); | 86 | jfs_inode = JFS_IP(inode); |
| @@ -89,8 +90,12 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
| 89 | jfs_warn("ialloc: diAlloc returned %d!", rc); | 90 | jfs_warn("ialloc: diAlloc returned %d!", rc); |
| 90 | if (rc == -EIO) | 91 | if (rc == -EIO) |
| 91 | make_bad_inode(inode); | 92 | make_bad_inode(inode); |
| 92 | iput(inode); | 93 | goto fail_put; |
| 93 | return ERR_PTR(rc); | 94 | } |
| 95 | |||
| 96 | if (insert_inode_locked(inode) < 0) { | ||
| 97 | rc = -EINVAL; | ||
| 98 | goto fail_unlock; | ||
| 94 | } | 99 | } |
| 95 | 100 | ||
| 96 | inode->i_uid = current_fsuid(); | 101 | inode->i_uid = current_fsuid(); |
| @@ -112,11 +117,8 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
| 112 | * Allocate inode to quota. | 117 | * Allocate inode to quota. |
| 113 | */ | 118 | */ |
| 114 | if (DQUOT_ALLOC_INODE(inode)) { | 119 | if (DQUOT_ALLOC_INODE(inode)) { |
| 115 | DQUOT_DROP(inode); | 120 | rc = -EDQUOT; |
| 116 | inode->i_flags |= S_NOQUOTA; | 121 | goto fail_drop; |
| 117 | inode->i_nlink = 0; | ||
| 118 | iput(inode); | ||
| 119 | return ERR_PTR(-EDQUOT); | ||
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | inode->i_mode = mode; | 124 | inode->i_mode = mode; |
| @@ -158,4 +160,15 @@ struct inode *ialloc(struct inode *parent, umode_t mode) | |||
| 158 | jfs_info("ialloc returns inode = 0x%p\n", inode); | 160 | jfs_info("ialloc returns inode = 0x%p\n", inode); |
| 159 | 161 | ||
| 160 | return inode; | 162 | return inode; |
| 163 | |||
| 164 | fail_drop: | ||
| 165 | DQUOT_DROP(inode); | ||
| 166 | inode->i_flags |= S_NOQUOTA; | ||
| 167 | fail_unlock: | ||
| 168 | inode->i_nlink = 0; | ||
| 169 | unlock_new_inode(inode); | ||
| 170 | fail_put: | ||
| 171 | iput(inode); | ||
| 172 | fail: | ||
| 173 | return ERR_PTR(rc); | ||
| 161 | } | 174 | } |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index cc3cedffbfa1..b4de56b851e4 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
| @@ -155,7 +155,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
| 155 | ip->i_fop = &jfs_file_operations; | 155 | ip->i_fop = &jfs_file_operations; |
| 156 | ip->i_mapping->a_ops = &jfs_aops; | 156 | ip->i_mapping->a_ops = &jfs_aops; |
| 157 | 157 | ||
| 158 | insert_inode_hash(ip); | ||
| 159 | mark_inode_dirty(ip); | 158 | mark_inode_dirty(ip); |
| 160 | 159 | ||
| 161 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 160 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
| @@ -171,9 +170,12 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
| 171 | if (rc) { | 170 | if (rc) { |
| 172 | free_ea_wmap(ip); | 171 | free_ea_wmap(ip); |
| 173 | ip->i_nlink = 0; | 172 | ip->i_nlink = 0; |
| 173 | unlock_new_inode(ip); | ||
| 174 | iput(ip); | 174 | iput(ip); |
| 175 | } else | 175 | } else { |
| 176 | d_instantiate(dentry, ip); | 176 | d_instantiate(dentry, ip); |
| 177 | unlock_new_inode(ip); | ||
| 178 | } | ||
| 177 | 179 | ||
| 178 | out2: | 180 | out2: |
| 179 | free_UCSname(&dname); | 181 | free_UCSname(&dname); |
| @@ -289,7 +291,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
| 289 | ip->i_op = &jfs_dir_inode_operations; | 291 | ip->i_op = &jfs_dir_inode_operations; |
| 290 | ip->i_fop = &jfs_dir_operations; | 292 | ip->i_fop = &jfs_dir_operations; |
| 291 | 293 | ||
| 292 | insert_inode_hash(ip); | ||
| 293 | mark_inode_dirty(ip); | 294 | mark_inode_dirty(ip); |
| 294 | 295 | ||
| 295 | /* update parent directory inode */ | 296 | /* update parent directory inode */ |
| @@ -306,9 +307,12 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
| 306 | if (rc) { | 307 | if (rc) { |
| 307 | free_ea_wmap(ip); | 308 | free_ea_wmap(ip); |
| 308 | ip->i_nlink = 0; | 309 | ip->i_nlink = 0; |
| 310 | unlock_new_inode(ip); | ||
| 309 | iput(ip); | 311 | iput(ip); |
| 310 | } else | 312 | } else { |
| 311 | d_instantiate(dentry, ip); | 313 | d_instantiate(dentry, ip); |
| 314 | unlock_new_inode(ip); | ||
| 315 | } | ||
| 312 | 316 | ||
| 313 | out2: | 317 | out2: |
| 314 | free_UCSname(&dname); | 318 | free_UCSname(&dname); |
| @@ -1019,7 +1023,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
| 1019 | goto out3; | 1023 | goto out3; |
| 1020 | } | 1024 | } |
| 1021 | 1025 | ||
| 1022 | insert_inode_hash(ip); | ||
| 1023 | mark_inode_dirty(ip); | 1026 | mark_inode_dirty(ip); |
| 1024 | 1027 | ||
| 1025 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 1028 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
| @@ -1039,9 +1042,12 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
| 1039 | if (rc) { | 1042 | if (rc) { |
| 1040 | free_ea_wmap(ip); | 1043 | free_ea_wmap(ip); |
| 1041 | ip->i_nlink = 0; | 1044 | ip->i_nlink = 0; |
| 1045 | unlock_new_inode(ip); | ||
| 1042 | iput(ip); | 1046 | iput(ip); |
| 1043 | } else | 1047 | } else { |
| 1044 | d_instantiate(dentry, ip); | 1048 | d_instantiate(dentry, ip); |
| 1049 | unlock_new_inode(ip); | ||
| 1050 | } | ||
| 1045 | 1051 | ||
| 1046 | out2: | 1052 | out2: |
| 1047 | free_UCSname(&dname); | 1053 | free_UCSname(&dname); |
| @@ -1399,7 +1405,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1399 | jfs_ip->dev = new_encode_dev(rdev); | 1405 | jfs_ip->dev = new_encode_dev(rdev); |
| 1400 | init_special_inode(ip, ip->i_mode, rdev); | 1406 | init_special_inode(ip, ip->i_mode, rdev); |
| 1401 | 1407 | ||
| 1402 | insert_inode_hash(ip); | ||
| 1403 | mark_inode_dirty(ip); | 1408 | mark_inode_dirty(ip); |
| 1404 | 1409 | ||
| 1405 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 1410 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
| @@ -1417,9 +1422,12 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1417 | if (rc) { | 1422 | if (rc) { |
| 1418 | free_ea_wmap(ip); | 1423 | free_ea_wmap(ip); |
| 1419 | ip->i_nlink = 0; | 1424 | ip->i_nlink = 0; |
| 1425 | unlock_new_inode(ip); | ||
| 1420 | iput(ip); | 1426 | iput(ip); |
| 1421 | } else | 1427 | } else { |
| 1422 | d_instantiate(dentry, ip); | 1428 | d_instantiate(dentry, ip); |
| 1429 | unlock_new_inode(ip); | ||
| 1430 | } | ||
| 1423 | 1431 | ||
| 1424 | out1: | 1432 | out1: |
| 1425 | free_UCSname(&dname); | 1433 | free_UCSname(&dname); |
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..dd5c9f0bf829 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -226,6 +226,16 @@ int generic_permission(struct inode *inode, int mask, | |||
| 226 | return -EACCES; | 226 | return -EACCES; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | /** | ||
| 230 | * inode_permission - check for access rights to a given inode | ||
| 231 | * @inode: inode to check permission on | ||
| 232 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
| 233 | * | ||
| 234 | * Used to check for read/write/execute permissions on an inode. | ||
| 235 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
| 236 | * for filesystem access without changing the "normal" uids which | ||
| 237 | * are used for other things. | ||
| 238 | */ | ||
| 229 | int inode_permission(struct inode *inode, int mask) | 239 | int inode_permission(struct inode *inode, int mask) |
| 230 | { | 240 | { |
| 231 | int retval; | 241 | int retval; |
| @@ -247,7 +257,6 @@ int inode_permission(struct inode *inode, int mask) | |||
| 247 | return -EACCES; | 257 | return -EACCES; |
| 248 | } | 258 | } |
| 249 | 259 | ||
| 250 | /* Ordinary permission routines do not understand MAY_APPEND. */ | ||
| 251 | if (inode->i_op && inode->i_op->permission) | 260 | if (inode->i_op && inode->i_op->permission) |
| 252 | retval = inode->i_op->permission(inode, mask); | 261 | retval = inode->i_op->permission(inode, mask); |
| 253 | else | 262 | else |
| @@ -265,21 +274,6 @@ int inode_permission(struct inode *inode, int mask) | |||
| 265 | } | 274 | } |
| 266 | 275 | ||
| 267 | /** | 276 | /** |
| 268 | * vfs_permission - check for access rights to a given path | ||
| 269 | * @nd: lookup result that describes the path | ||
| 270 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
| 271 | * | ||
| 272 | * Used to check for read/write/execute permissions on a path. | ||
| 273 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
| 274 | * for filesystem access without changing the "normal" uids which | ||
| 275 | * are used for other things. | ||
| 276 | */ | ||
| 277 | int vfs_permission(struct nameidata *nd, int mask) | ||
| 278 | { | ||
| 279 | return inode_permission(nd->path.dentry->d_inode, mask); | ||
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * file_permission - check for additional access rights to a given file | 277 | * file_permission - check for additional access rights to a given file |
| 284 | * @file: file to check access rights for | 278 | * @file: file to check access rights for |
| 285 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 279 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
| @@ -289,7 +283,7 @@ int vfs_permission(struct nameidata *nd, int mask) | |||
| 289 | * | 283 | * |
| 290 | * Note: | 284 | * Note: |
| 291 | * Do not use this function in new code. All access checks should | 285 | * Do not use this function in new code. All access checks should |
| 292 | * be done using vfs_permission(). | 286 | * be done using inode_permission(). |
| 293 | */ | 287 | */ |
| 294 | int file_permission(struct file *file, int mask) | 288 | int file_permission(struct file *file, int mask) |
| 295 | { | 289 | { |
| @@ -527,18 +521,6 @@ out_unlock: | |||
| 527 | return result; | 521 | return result; |
| 528 | } | 522 | } |
| 529 | 523 | ||
| 530 | /* SMP-safe */ | ||
| 531 | static __always_inline void | ||
| 532 | walk_init_root(const char *name, struct nameidata *nd) | ||
| 533 | { | ||
| 534 | struct fs_struct *fs = current->fs; | ||
| 535 | |||
| 536 | read_lock(&fs->lock); | ||
| 537 | nd->path = fs->root; | ||
| 538 | path_get(&fs->root); | ||
| 539 | read_unlock(&fs->lock); | ||
| 540 | } | ||
| 541 | |||
| 542 | /* | 524 | /* |
| 543 | * Wrapper to retry pathname resolution whenever the underlying | 525 | * Wrapper to retry pathname resolution whenever the underlying |
| 544 | * file system returns an ESTALE. | 526 | * file system returns an ESTALE. |
| @@ -576,9 +558,16 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
| 576 | goto fail; | 558 | goto fail; |
| 577 | 559 | ||
| 578 | if (*link == '/') { | 560 | if (*link == '/') { |
| 561 | struct fs_struct *fs = current->fs; | ||
| 562 | |||
| 579 | path_put(&nd->path); | 563 | path_put(&nd->path); |
| 580 | walk_init_root(link, nd); | 564 | |
| 565 | read_lock(&fs->lock); | ||
| 566 | nd->path = fs->root; | ||
| 567 | path_get(&fs->root); | ||
| 568 | read_unlock(&fs->lock); | ||
| 581 | } | 569 | } |
| 570 | |||
| 582 | res = link_path_walk(link, nd); | 571 | res = link_path_walk(link, nd); |
| 583 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 572 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
| 584 | return res; | 573 | return res; |
| @@ -859,7 +848,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
| 859 | nd->flags |= LOOKUP_CONTINUE; | 848 | nd->flags |= LOOKUP_CONTINUE; |
| 860 | err = exec_permission_lite(inode); | 849 | err = exec_permission_lite(inode); |
| 861 | if (err == -EAGAIN) | 850 | if (err == -EAGAIN) |
| 862 | err = vfs_permission(nd, MAY_EXEC); | 851 | err = inode_permission(nd->path.dentry->d_inode, |
| 852 | MAY_EXEC); | ||
| 863 | if (err) | 853 | if (err) |
| 864 | break; | 854 | break; |
| 865 | 855 | ||
| @@ -1493,9 +1483,9 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 1493 | return error; | 1483 | return error; |
| 1494 | } | 1484 | } |
| 1495 | 1485 | ||
| 1496 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1486 | int may_open(struct path *path, int acc_mode, int flag) |
| 1497 | { | 1487 | { |
| 1498 | struct dentry *dentry = nd->path.dentry; | 1488 | struct dentry *dentry = path->dentry; |
| 1499 | struct inode *inode = dentry->d_inode; | 1489 | struct inode *inode = dentry->d_inode; |
| 1500 | int error; | 1490 | int error; |
| 1501 | 1491 | ||
| @@ -1516,13 +1506,13 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
| 1516 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1506 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
| 1517 | flag &= ~O_TRUNC; | 1507 | flag &= ~O_TRUNC; |
| 1518 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1508 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
| 1519 | if (nd->path.mnt->mnt_flags & MNT_NODEV) | 1509 | if (path->mnt->mnt_flags & MNT_NODEV) |
| 1520 | return -EACCES; | 1510 | return -EACCES; |
| 1521 | 1511 | ||
| 1522 | flag &= ~O_TRUNC; | 1512 | flag &= ~O_TRUNC; |
| 1523 | } | 1513 | } |
| 1524 | 1514 | ||
| 1525 | error = vfs_permission(nd, acc_mode); | 1515 | error = inode_permission(inode, acc_mode); |
| 1526 | if (error) | 1516 | if (error) |
| 1527 | return error; | 1517 | return error; |
| 1528 | /* | 1518 | /* |
| @@ -1556,6 +1546,9 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
| 1556 | * Refuse to truncate files with mandatory locks held on them. | 1546 | * Refuse to truncate files with mandatory locks held on them. |
| 1557 | */ | 1547 | */ |
| 1558 | error = locks_verify_locked(inode); | 1548 | error = locks_verify_locked(inode); |
| 1549 | if (!error) | ||
| 1550 | error = security_path_truncate(path, 0, | ||
| 1551 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
| 1559 | if (!error) { | 1552 | if (!error) { |
| 1560 | DQUOT_INIT(inode); | 1553 | DQUOT_INIT(inode); |
| 1561 | 1554 | ||
| @@ -1586,14 +1579,18 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, | |||
| 1586 | 1579 | ||
| 1587 | if (!IS_POSIXACL(dir->d_inode)) | 1580 | if (!IS_POSIXACL(dir->d_inode)) |
| 1588 | mode &= ~current->fs->umask; | 1581 | mode &= ~current->fs->umask; |
| 1582 | error = security_path_mknod(&nd->path, path->dentry, mode, 0); | ||
| 1583 | if (error) | ||
| 1584 | goto out_unlock; | ||
| 1589 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1585 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
| 1586 | out_unlock: | ||
| 1590 | mutex_unlock(&dir->d_inode->i_mutex); | 1587 | mutex_unlock(&dir->d_inode->i_mutex); |
| 1591 | dput(nd->path.dentry); | 1588 | dput(nd->path.dentry); |
| 1592 | nd->path.dentry = path->dentry; | 1589 | nd->path.dentry = path->dentry; |
| 1593 | if (error) | 1590 | if (error) |
| 1594 | return error; | 1591 | return error; |
| 1595 | /* Don't check for write permission, don't truncate */ | 1592 | /* Don't check for write permission, don't truncate */ |
| 1596 | return may_open(nd, 0, flag & ~O_TRUNC); | 1593 | return may_open(&nd->path, 0, flag & ~O_TRUNC); |
| 1597 | } | 1594 | } |
| 1598 | 1595 | ||
| 1599 | /* | 1596 | /* |
| @@ -1779,7 +1776,7 @@ ok: | |||
| 1779 | if (error) | 1776 | if (error) |
| 1780 | goto exit; | 1777 | goto exit; |
| 1781 | } | 1778 | } |
| 1782 | error = may_open(&nd, acc_mode, flag); | 1779 | error = may_open(&nd.path, acc_mode, flag); |
| 1783 | if (error) { | 1780 | if (error) { |
| 1784 | if (will_write) | 1781 | if (will_write) |
| 1785 | mnt_drop_write(nd.path.mnt); | 1782 | mnt_drop_write(nd.path.mnt); |
| @@ -1999,6 +1996,9 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
| 1999 | error = mnt_want_write(nd.path.mnt); | 1996 | error = mnt_want_write(nd.path.mnt); |
| 2000 | if (error) | 1997 | if (error) |
| 2001 | goto out_dput; | 1998 | goto out_dput; |
| 1999 | error = security_path_mknod(&nd.path, dentry, mode, dev); | ||
| 2000 | if (error) | ||
| 2001 | goto out_drop_write; | ||
| 2002 | switch (mode & S_IFMT) { | 2002 | switch (mode & S_IFMT) { |
| 2003 | case 0: case S_IFREG: | 2003 | case 0: case S_IFREG: |
| 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2004 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
| @@ -2011,6 +2011,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
| 2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2011 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
| 2012 | break; | 2012 | break; |
| 2013 | } | 2013 | } |
| 2014 | out_drop_write: | ||
| 2014 | mnt_drop_write(nd.path.mnt); | 2015 | mnt_drop_write(nd.path.mnt); |
| 2015 | out_dput: | 2016 | out_dput: |
| 2016 | dput(dentry); | 2017 | dput(dentry); |
| @@ -2070,7 +2071,11 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
| 2070 | error = mnt_want_write(nd.path.mnt); | 2071 | error = mnt_want_write(nd.path.mnt); |
| 2071 | if (error) | 2072 | if (error) |
| 2072 | goto out_dput; | 2073 | goto out_dput; |
| 2074 | error = security_path_mkdir(&nd.path, dentry, mode); | ||
| 2075 | if (error) | ||
| 2076 | goto out_drop_write; | ||
| 2073 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2077 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
| 2078 | out_drop_write: | ||
| 2074 | mnt_drop_write(nd.path.mnt); | 2079 | mnt_drop_write(nd.path.mnt); |
| 2075 | out_dput: | 2080 | out_dput: |
| 2076 | dput(dentry); | 2081 | dput(dentry); |
| @@ -2180,7 +2185,11 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
| 2180 | error = mnt_want_write(nd.path.mnt); | 2185 | error = mnt_want_write(nd.path.mnt); |
| 2181 | if (error) | 2186 | if (error) |
| 2182 | goto exit3; | 2187 | goto exit3; |
| 2188 | error = security_path_rmdir(&nd.path, dentry); | ||
| 2189 | if (error) | ||
| 2190 | goto exit4; | ||
| 2183 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2191 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
| 2192 | exit4: | ||
| 2184 | mnt_drop_write(nd.path.mnt); | 2193 | mnt_drop_write(nd.path.mnt); |
| 2185 | exit3: | 2194 | exit3: |
| 2186 | dput(dentry); | 2195 | dput(dentry); |
| @@ -2265,7 +2274,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 2265 | error = mnt_want_write(nd.path.mnt); | 2274 | error = mnt_want_write(nd.path.mnt); |
| 2266 | if (error) | 2275 | if (error) |
| 2267 | goto exit2; | 2276 | goto exit2; |
| 2277 | error = security_path_unlink(&nd.path, dentry); | ||
| 2278 | if (error) | ||
| 2279 | goto exit3; | ||
| 2268 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2280 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
| 2281 | exit3: | ||
| 2269 | mnt_drop_write(nd.path.mnt); | 2282 | mnt_drop_write(nd.path.mnt); |
| 2270 | exit2: | 2283 | exit2: |
| 2271 | dput(dentry); | 2284 | dput(dentry); |
| @@ -2346,7 +2359,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
| 2346 | error = mnt_want_write(nd.path.mnt); | 2359 | error = mnt_want_write(nd.path.mnt); |
| 2347 | if (error) | 2360 | if (error) |
| 2348 | goto out_dput; | 2361 | goto out_dput; |
| 2362 | error = security_path_symlink(&nd.path, dentry, from); | ||
| 2363 | if (error) | ||
| 2364 | goto out_drop_write; | ||
| 2349 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); | 2365 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
| 2366 | out_drop_write: | ||
| 2350 | mnt_drop_write(nd.path.mnt); | 2367 | mnt_drop_write(nd.path.mnt); |
| 2351 | out_dput: | 2368 | out_dput: |
| 2352 | dput(dentry); | 2369 | dput(dentry); |
| @@ -2443,7 +2460,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
| 2443 | error = mnt_want_write(nd.path.mnt); | 2460 | error = mnt_want_write(nd.path.mnt); |
| 2444 | if (error) | 2461 | if (error) |
| 2445 | goto out_dput; | 2462 | goto out_dput; |
| 2463 | error = security_path_link(old_path.dentry, &nd.path, new_dentry); | ||
| 2464 | if (error) | ||
| 2465 | goto out_drop_write; | ||
| 2446 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); | 2466 | error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
| 2467 | out_drop_write: | ||
| 2447 | mnt_drop_write(nd.path.mnt); | 2468 | mnt_drop_write(nd.path.mnt); |
| 2448 | out_dput: | 2469 | out_dput: |
| 2449 | dput(new_dentry); | 2470 | dput(new_dentry); |
| @@ -2679,8 +2700,13 @@ asmlinkage long sys_renameat(int olddfd, const char __user *oldname, | |||
| 2679 | error = mnt_want_write(oldnd.path.mnt); | 2700 | error = mnt_want_write(oldnd.path.mnt); |
| 2680 | if (error) | 2701 | if (error) |
| 2681 | goto exit5; | 2702 | goto exit5; |
| 2703 | error = security_path_rename(&oldnd.path, old_dentry, | ||
| 2704 | &newnd.path, new_dentry); | ||
| 2705 | if (error) | ||
| 2706 | goto exit6; | ||
| 2682 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2707 | error = vfs_rename(old_dir->d_inode, old_dentry, |
| 2683 | new_dir->d_inode, new_dentry); | 2708 | new_dir->d_inode, new_dentry); |
| 2709 | exit6: | ||
| 2684 | mnt_drop_write(oldnd.path.mnt); | 2710 | mnt_drop_write(oldnd.path.mnt); |
| 2685 | exit5: | 2711 | exit5: |
| 2686 | dput(new_dentry); | 2712 | dput(new_dentry); |
| @@ -2750,13 +2776,16 @@ int vfs_follow_link(struct nameidata *nd, const char *link) | |||
| 2750 | /* get the link contents into pagecache */ | 2776 | /* get the link contents into pagecache */ |
| 2751 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 2777 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
| 2752 | { | 2778 | { |
| 2753 | struct page * page; | 2779 | char *kaddr; |
| 2780 | struct page *page; | ||
| 2754 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2781 | struct address_space *mapping = dentry->d_inode->i_mapping; |
| 2755 | page = read_mapping_page(mapping, 0, NULL); | 2782 | page = read_mapping_page(mapping, 0, NULL); |
| 2756 | if (IS_ERR(page)) | 2783 | if (IS_ERR(page)) |
| 2757 | return (char*)page; | 2784 | return (char*)page; |
| 2758 | *ppage = page; | 2785 | *ppage = page; |
| 2759 | return kmap(page); | 2786 | kaddr = kmap(page); |
| 2787 | nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1); | ||
| 2788 | return kaddr; | ||
| 2760 | } | 2789 | } |
| 2761 | 2790 | ||
| 2762 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 2791 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
| @@ -2849,7 +2878,6 @@ EXPORT_SYMBOL(path_lookup); | |||
| 2849 | EXPORT_SYMBOL(kern_path); | 2878 | EXPORT_SYMBOL(kern_path); |
| 2850 | EXPORT_SYMBOL(vfs_path_lookup); | 2879 | EXPORT_SYMBOL(vfs_path_lookup); |
| 2851 | EXPORT_SYMBOL(inode_permission); | 2880 | EXPORT_SYMBOL(inode_permission); |
| 2852 | EXPORT_SYMBOL(vfs_permission); | ||
| 2853 | EXPORT_SYMBOL(file_permission); | 2881 | EXPORT_SYMBOL(file_permission); |
| 2854 | EXPORT_SYMBOL(unlock_rename); | 2882 | EXPORT_SYMBOL(unlock_rename); |
| 2855 | EXPORT_SYMBOL(vfs_create); | 2883 | EXPORT_SYMBOL(vfs_create); |
| @@ -2865,3 +2893,10 @@ EXPORT_SYMBOL(vfs_symlink); | |||
| 2865 | EXPORT_SYMBOL(vfs_unlink); | 2893 | EXPORT_SYMBOL(vfs_unlink); |
| 2866 | EXPORT_SYMBOL(dentry_unhash); | 2894 | EXPORT_SYMBOL(dentry_unhash); |
| 2867 | EXPORT_SYMBOL(generic_readlink); | 2895 | EXPORT_SYMBOL(generic_readlink); |
| 2896 | |||
| 2897 | /* to be mentioned only in INIT_TASK */ | ||
| 2898 | struct fs_struct init_fs = { | ||
| 2899 | .count = ATOMIC_INIT(1), | ||
| 2900 | .lock = __RW_LOCK_UNLOCKED(init_fs.lock), | ||
| 2901 | .umask = 0022, | ||
| 2902 | }; | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 1c09cab8f7cf..a40685d800a8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1990,7 +1990,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
| 1990 | if (!new_ns->root) { | 1990 | if (!new_ns->root) { |
| 1991 | up_write(&namespace_sem); | 1991 | up_write(&namespace_sem); |
| 1992 | kfree(new_ns); | 1992 | kfree(new_ns); |
| 1993 | return ERR_PTR(-ENOMEM);; | 1993 | return ERR_PTR(-ENOMEM); |
| 1994 | } | 1994 | } |
| 1995 | spin_lock(&vfsmount_lock); | 1995 | spin_lock(&vfsmount_lock); |
| 1996 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); | 1996 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); |
diff --git a/fs/nfsctl.c b/fs/nfsctl.c index b1acbd6ab6fb..b27451909dff 100644 --- a/fs/nfsctl.c +++ b/fs/nfsctl.c | |||
| @@ -38,9 +38,10 @@ static struct file *do_open(char *name, int flags) | |||
| 38 | return ERR_PTR(error); | 38 | return ERR_PTR(error); |
| 39 | 39 | ||
| 40 | if (flags == O_RDWR) | 40 | if (flags == O_RDWR) |
| 41 | error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); | 41 | error = may_open(&nd.path, MAY_READ|MAY_WRITE, |
| 42 | FMODE_READ|FMODE_WRITE); | ||
| 42 | else | 43 | else |
| 43 | error = may_open(&nd, MAY_WRITE, FMODE_WRITE); | 44 | error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE); |
| 44 | 45 | ||
| 45 | if (!error) | 46 | if (!error) |
| 46 | return dentry_open(nd.path.dentry, nd.path.mnt, flags, | 47 | return dentry_open(nd.path.dentry, nd.path.mnt, flags, |
diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig new file mode 100644 index 000000000000..50914d7303c6 --- /dev/null +++ b/fs/notify/Kconfig | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | source "fs/notify/dnotify/Kconfig" | ||
| 2 | source "fs/notify/inotify/Kconfig" | ||
diff --git a/fs/notify/Makefile b/fs/notify/Makefile new file mode 100644 index 000000000000..5a95b6010ce7 --- /dev/null +++ b/fs/notify/Makefile | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | obj-y += dnotify/ | ||
| 2 | obj-y += inotify/ | ||
diff --git a/fs/notify/dnotify/Kconfig b/fs/notify/dnotify/Kconfig new file mode 100644 index 000000000000..26adf5dfa646 --- /dev/null +++ b/fs/notify/dnotify/Kconfig | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | config DNOTIFY | ||
| 2 | bool "Dnotify support" | ||
| 3 | default y | ||
| 4 | help | ||
| 5 | Dnotify is a directory-based per-fd file change notification system | ||
| 6 | that uses signals to communicate events to user-space. There exist | ||
| 7 | superior alternatives, but some applications may still rely on | ||
| 8 | dnotify. | ||
| 9 | |||
| 10 | If unsure, say Y. | ||
diff --git a/fs/notify/dnotify/Makefile b/fs/notify/dnotify/Makefile new file mode 100644 index 000000000000..f145251dcadb --- /dev/null +++ b/fs/notify/dnotify/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_DNOTIFY) += dnotify.o | |||
diff --git a/fs/dnotify.c b/fs/notify/dnotify/dnotify.c index 676073b8dda5..b0aa2cde80bd 100644 --- a/fs/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
| @@ -115,9 +115,6 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
| 115 | dn->dn_next = inode->i_dnotify; | 115 | dn->dn_next = inode->i_dnotify; |
| 116 | inode->i_dnotify = dn; | 116 | inode->i_dnotify = dn; |
| 117 | spin_unlock(&inode->i_lock); | 117 | spin_unlock(&inode->i_lock); |
| 118 | |||
| 119 | if (filp->f_op && filp->f_op->dir_notify) | ||
| 120 | return filp->f_op->dir_notify(filp, arg); | ||
| 121 | return 0; | 118 | return 0; |
| 122 | 119 | ||
| 123 | out_free: | 120 | out_free: |
diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig new file mode 100644 index 000000000000..446792841023 --- /dev/null +++ b/fs/notify/inotify/Kconfig | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | config INOTIFY | ||
| 2 | bool "Inotify file change notification support" | ||
| 3 | default y | ||
| 4 | ---help--- | ||
| 5 | Say Y here to enable inotify support. Inotify is a file change | ||
| 6 | notification system and a replacement for dnotify. Inotify fixes | ||
| 7 | numerous shortcomings in dnotify and introduces several new features | ||
| 8 | including multiple file events, one-shot support, and unmount | ||
| 9 | notification. | ||
| 10 | |||
| 11 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
| 12 | |||
| 13 | If unsure, say Y. | ||
| 14 | |||
| 15 | config INOTIFY_USER | ||
| 16 | bool "Inotify support for userspace" | ||
| 17 | depends on INOTIFY | ||
| 18 | default y | ||
| 19 | ---help--- | ||
| 20 | Say Y here to enable inotify support for userspace, including the | ||
| 21 | associated system calls. Inotify allows monitoring of both files and | ||
| 22 | directories via a single open fd. Events are read from the file | ||
| 23 | descriptor, which is also select()- and poll()-able. | ||
| 24 | |||
| 25 | For more information, see <file:Documentation/filesystems/inotify.txt> | ||
| 26 | |||
| 27 | If unsure, say Y. | ||
diff --git a/fs/notify/inotify/Makefile b/fs/notify/inotify/Makefile new file mode 100644 index 000000000000..e290f3bb9d8d --- /dev/null +++ b/fs/notify/inotify/Makefile | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | obj-$(CONFIG_INOTIFY) += inotify.o | ||
| 2 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | ||
diff --git a/fs/inotify.c b/fs/notify/inotify/inotify.c index dae3f28f30d4..dae3f28f30d4 100644 --- a/fs/inotify.c +++ b/fs/notify/inotify/inotify.c | |||
diff --git a/fs/inotify_user.c b/fs/notify/inotify/inotify_user.c index e2425bbd871f..400f8064a548 100644 --- a/fs/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
| @@ -76,10 +76,10 @@ struct inotify_device { | |||
| 76 | struct mutex ev_mutex; /* protects event queue */ | 76 | struct mutex ev_mutex; /* protects event queue */ |
| 77 | struct mutex up_mutex; /* synchronizes watch updates */ | 77 | struct mutex up_mutex; /* synchronizes watch updates */ |
| 78 | struct list_head events; /* list of queued events */ | 78 | struct list_head events; /* list of queued events */ |
| 79 | atomic_t count; /* reference count */ | ||
| 80 | struct user_struct *user; /* user who opened this dev */ | 79 | struct user_struct *user; /* user who opened this dev */ |
| 81 | struct inotify_handle *ih; /* inotify handle */ | 80 | struct inotify_handle *ih; /* inotify handle */ |
| 82 | struct fasync_struct *fa; /* async notification */ | 81 | struct fasync_struct *fa; /* async notification */ |
| 82 | atomic_t count; /* reference count */ | ||
| 83 | unsigned int queue_size; /* size of the queue (bytes) */ | 83 | unsigned int queue_size; /* size of the queue (bytes) */ |
| 84 | unsigned int event_count; /* number of pending events */ | 84 | unsigned int event_count; /* number of pending events */ |
| 85 | unsigned int max_events; /* maximum number of events */ | 85 | unsigned int max_events; /* maximum number of events */ |
| @@ -272,6 +272,8 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
| 272 | goto put_write_and_out; | 272 | goto put_write_and_out; |
| 273 | 273 | ||
| 274 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
| 275 | if (!error) | ||
| 276 | error = security_path_truncate(&path, length, 0); | ||
| 275 | if (!error) { | 277 | if (!error) { |
| 276 | DQUOT_INIT(inode); | 278 | DQUOT_INIT(inode); |
| 277 | error = do_truncate(path.dentry, length, 0, NULL); | 279 | error = do_truncate(path.dentry, length, 0, NULL); |
| @@ -329,6 +331,9 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
| 329 | 331 | ||
| 330 | error = locks_verify_truncate(inode, file, length); | 332 | error = locks_verify_truncate(inode, file, length); |
| 331 | if (!error) | 333 | if (!error) |
| 334 | error = security_path_truncate(&file->f_path, length, | ||
| 335 | ATTR_MTIME|ATTR_CTIME); | ||
| 336 | if (!error) | ||
| 332 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 337 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
| 333 | out_putf: | 338 | out_putf: |
| 334 | fput(file); | 339 | fput(file); |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6c4c2c69449f..145c2d3e5e01 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -1753,6 +1753,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
| 1753 | struct inode *inode) | 1753 | struct inode *inode) |
| 1754 | { | 1754 | { |
| 1755 | struct super_block *sb; | 1755 | struct super_block *sb; |
| 1756 | struct reiserfs_iget_args args; | ||
| 1756 | INITIALIZE_PATH(path_to_key); | 1757 | INITIALIZE_PATH(path_to_key); |
| 1757 | struct cpu_key key; | 1758 | struct cpu_key key; |
| 1758 | struct item_head ih; | 1759 | struct item_head ih; |
| @@ -1780,6 +1781,14 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
| 1780 | err = -ENOMEM; | 1781 | err = -ENOMEM; |
| 1781 | goto out_bad_inode; | 1782 | goto out_bad_inode; |
| 1782 | } | 1783 | } |
| 1784 | args.objectid = inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid); | ||
| 1785 | memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE); | ||
| 1786 | args.dirid = le32_to_cpu(ih.ih_key.k_dir_id); | ||
| 1787 | if (insert_inode_locked4(inode, args.objectid, | ||
| 1788 | reiserfs_find_actor, &args) < 0) { | ||
| 1789 | err = -EINVAL; | ||
| 1790 | goto out_bad_inode; | ||
| 1791 | } | ||
| 1783 | if (old_format_only(sb)) | 1792 | if (old_format_only(sb)) |
| 1784 | /* not a perfect generation count, as object ids can be reused, but | 1793 | /* not a perfect generation count, as object ids can be reused, but |
| 1785 | ** this is as good as reiserfs can do right now. | 1794 | ** this is as good as reiserfs can do right now. |
| @@ -1859,13 +1868,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
| 1859 | } else { | 1868 | } else { |
| 1860 | inode2sd(&sd, inode, inode->i_size); | 1869 | inode2sd(&sd, inode, inode->i_size); |
| 1861 | } | 1870 | } |
| 1862 | // these do not go to on-disk stat data | ||
| 1863 | inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid); | ||
| 1864 | |||
| 1865 | // store in in-core inode the key of stat data and version all | 1871 | // store in in-core inode the key of stat data and version all |
| 1866 | // object items will have (directory items will have old offset | 1872 | // object items will have (directory items will have old offset |
| 1867 | // format, other new objects will consist of new items) | 1873 | // format, other new objects will consist of new items) |
| 1868 | memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE); | ||
| 1869 | if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode)) | 1874 | if (old_format_only(sb) || S_ISDIR(mode) || S_ISLNK(mode)) |
| 1870 | set_inode_item_key_version(inode, KEY_FORMAT_3_5); | 1875 | set_inode_item_key_version(inode, KEY_FORMAT_3_5); |
| 1871 | else | 1876 | else |
| @@ -1929,7 +1934,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
| 1929 | reiserfs_mark_inode_private(inode); | 1934 | reiserfs_mark_inode_private(inode); |
| 1930 | } | 1935 | } |
| 1931 | 1936 | ||
| 1932 | insert_inode_hash(inode); | ||
| 1933 | reiserfs_update_sd(th, inode); | 1937 | reiserfs_update_sd(th, inode); |
| 1934 | reiserfs_check_path(&path_to_key); | 1938 | reiserfs_check_path(&path_to_key); |
| 1935 | 1939 | ||
| @@ -1956,6 +1960,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
| 1956 | out_inserted_sd: | 1960 | out_inserted_sd: |
| 1957 | inode->i_nlink = 0; | 1961 | inode->i_nlink = 0; |
| 1958 | th->t_trans_id = 0; /* so the caller can't use this handle later */ | 1962 | th->t_trans_id = 0; /* so the caller can't use this handle later */ |
| 1963 | unlock_new_inode(inode); /* OK to do even if we hadn't locked it */ | ||
| 1959 | 1964 | ||
| 1960 | /* If we were inheriting an ACL, we need to release the lock so that | 1965 | /* If we were inheriting an ACL, we need to release the lock so that |
| 1961 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking | 1966 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 4f322e5ed840..738967f6c8ee 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
| @@ -646,6 +646,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 646 | err = journal_end(&th, dir->i_sb, jbegin_count); | 646 | err = journal_end(&th, dir->i_sb, jbegin_count); |
| 647 | if (err) | 647 | if (err) |
| 648 | retval = err; | 648 | retval = err; |
| 649 | unlock_new_inode(inode); | ||
| 649 | iput(inode); | 650 | iput(inode); |
| 650 | goto out_failed; | 651 | goto out_failed; |
| 651 | } | 652 | } |
| @@ -653,6 +654,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 653 | reiserfs_update_inode_transaction(dir); | 654 | reiserfs_update_inode_transaction(dir); |
| 654 | 655 | ||
| 655 | d_instantiate(dentry, inode); | 656 | d_instantiate(dentry, inode); |
| 657 | unlock_new_inode(inode); | ||
| 656 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 658 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
| 657 | 659 | ||
| 658 | out_failed: | 660 | out_failed: |
| @@ -727,11 +729,13 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode, | |||
| 727 | err = journal_end(&th, dir->i_sb, jbegin_count); | 729 | err = journal_end(&th, dir->i_sb, jbegin_count); |
| 728 | if (err) | 730 | if (err) |
| 729 | retval = err; | 731 | retval = err; |
| 732 | unlock_new_inode(inode); | ||
| 730 | iput(inode); | 733 | iput(inode); |
| 731 | goto out_failed; | 734 | goto out_failed; |
| 732 | } | 735 | } |
| 733 | 736 | ||
| 734 | d_instantiate(dentry, inode); | 737 | d_instantiate(dentry, inode); |
| 738 | unlock_new_inode(inode); | ||
| 735 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 739 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
| 736 | 740 | ||
| 737 | out_failed: | 741 | out_failed: |
| @@ -812,6 +816,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 812 | err = journal_end(&th, dir->i_sb, jbegin_count); | 816 | err = journal_end(&th, dir->i_sb, jbegin_count); |
| 813 | if (err) | 817 | if (err) |
| 814 | retval = err; | 818 | retval = err; |
| 819 | unlock_new_inode(inode); | ||
| 815 | iput(inode); | 820 | iput(inode); |
| 816 | goto out_failed; | 821 | goto out_failed; |
| 817 | } | 822 | } |
| @@ -819,6 +824,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 819 | reiserfs_update_sd(&th, dir); | 824 | reiserfs_update_sd(&th, dir); |
| 820 | 825 | ||
| 821 | d_instantiate(dentry, inode); | 826 | d_instantiate(dentry, inode); |
| 827 | unlock_new_inode(inode); | ||
| 822 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 828 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
| 823 | out_failed: | 829 | out_failed: |
| 824 | if (locked) | 830 | if (locked) |
| @@ -1096,11 +1102,13 @@ static int reiserfs_symlink(struct inode *parent_dir, | |||
| 1096 | err = journal_end(&th, parent_dir->i_sb, jbegin_count); | 1102 | err = journal_end(&th, parent_dir->i_sb, jbegin_count); |
| 1097 | if (err) | 1103 | if (err) |
| 1098 | retval = err; | 1104 | retval = err; |
| 1105 | unlock_new_inode(inode); | ||
| 1099 | iput(inode); | 1106 | iput(inode); |
| 1100 | goto out_failed; | 1107 | goto out_failed; |
| 1101 | } | 1108 | } |
| 1102 | 1109 | ||
| 1103 | d_instantiate(dentry, inode); | 1110 | d_instantiate(dentry, inode); |
| 1111 | unlock_new_inode(inode); | ||
| 1104 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); | 1112 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); |
| 1105 | out_failed: | 1113 | out_failed: |
| 1106 | reiserfs_write_unlock(parent_dir->i_sb); | 1114 | reiserfs_write_unlock(parent_dir->i_sb); |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 16c211558c22..99d8b8cfc9b7 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
| @@ -389,8 +389,14 @@ char *mangle_path(char *s, char *p, char *esc) | |||
| 389 | } | 389 | } |
| 390 | EXPORT_SYMBOL(mangle_path); | 390 | EXPORT_SYMBOL(mangle_path); |
| 391 | 391 | ||
| 392 | /* | 392 | /** |
| 393 | * return the absolute path of 'dentry' residing in mount 'mnt'. | 393 | * seq_path - seq_file interface to print a pathname |
| 394 | * @m: the seq_file handle | ||
| 395 | * @path: the struct path to print | ||
| 396 | * @esc: set of characters to escape in the output | ||
| 397 | * | ||
| 398 | * return the absolute path of 'path', as represented by the | ||
| 399 | * dentry / mnt pair in the path parameter. | ||
| 394 | */ | 400 | */ |
| 395 | int seq_path(struct seq_file *m, struct path *path, char *esc) | 401 | int seq_path(struct seq_file *m, struct path *path, char *esc) |
| 396 | { | 402 | { |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index df0d435baa48..3d81bf58dae2 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
| 29 | #include <linux/vfs.h> | 29 | #include <linux/vfs.h> |
| 30 | #include <linux/namei.h> | ||
| 30 | #include <asm/byteorder.h> | 31 | #include <asm/byteorder.h> |
| 31 | #include "sysv.h" | 32 | #include "sysv.h" |
| 32 | 33 | ||
| @@ -163,8 +164,11 @@ void sysv_set_inode(struct inode *inode, dev_t rdev) | |||
| 163 | if (inode->i_blocks) { | 164 | if (inode->i_blocks) { |
| 164 | inode->i_op = &sysv_symlink_inode_operations; | 165 | inode->i_op = &sysv_symlink_inode_operations; |
| 165 | inode->i_mapping->a_ops = &sysv_aops; | 166 | inode->i_mapping->a_ops = &sysv_aops; |
| 166 | } else | 167 | } else { |
| 167 | inode->i_op = &sysv_fast_symlink_inode_operations; | 168 | inode->i_op = &sysv_fast_symlink_inode_operations; |
| 169 | nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size, | ||
| 170 | sizeof(SYSV_I(inode)->i_data) - 1); | ||
| 171 | } | ||
| 168 | } else | 172 | } else |
| 169 | init_special_inode(inode, inode->i_mode, rdev); | 173 | init_special_inode(inode, inode->i_mode, rdev); |
| 170 | } | 174 | } |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index a37359d0bad1..c66d22487bf8 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
| @@ -75,14 +75,22 @@ full_name_hash(const unsigned char *name, unsigned int len) | |||
| 75 | return end_name_hash(hash); | 75 | return end_name_hash(hash); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | struct dcookie_struct; | 78 | /* |
| 79 | 79 | * Try to keep struct dentry aligned on 64 byte cachelines (this will | |
| 80 | #define DNAME_INLINE_LEN_MIN 36 | 80 | * give reasonable cacheline footprint with larger lines without the |
| 81 | * large memory footprint increase). | ||
| 82 | */ | ||
| 83 | #ifdef CONFIG_64BIT | ||
| 84 | #define DNAME_INLINE_LEN_MIN 32 /* 192 bytes */ | ||
| 85 | #else | ||
| 86 | #define DNAME_INLINE_LEN_MIN 40 /* 128 bytes */ | ||
| 87 | #endif | ||
| 81 | 88 | ||
| 82 | struct dentry { | 89 | struct dentry { |
| 83 | atomic_t d_count; | 90 | atomic_t d_count; |
| 84 | unsigned int d_flags; /* protected by d_lock */ | 91 | unsigned int d_flags; /* protected by d_lock */ |
| 85 | spinlock_t d_lock; /* per dentry lock */ | 92 | spinlock_t d_lock; /* per dentry lock */ |
| 93 | int d_mounted; | ||
| 86 | struct inode *d_inode; /* Where the name belongs to - NULL is | 94 | struct inode *d_inode; /* Where the name belongs to - NULL is |
| 87 | * negative */ | 95 | * negative */ |
| 88 | /* | 96 | /* |
| @@ -107,10 +115,7 @@ struct dentry { | |||
| 107 | struct dentry_operations *d_op; | 115 | struct dentry_operations *d_op; |
| 108 | struct super_block *d_sb; /* The root of the dentry tree */ | 116 | struct super_block *d_sb; /* The root of the dentry tree */ |
| 109 | void *d_fsdata; /* fs-specific data */ | 117 | void *d_fsdata; /* fs-specific data */ |
| 110 | #ifdef CONFIG_PROFILING | 118 | |
| 111 | struct dcookie_struct *d_cookie; /* cookie, if any */ | ||
| 112 | #endif | ||
| 113 | int d_mounted; | ||
| 114 | unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ | 119 | unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ |
| 115 | }; | 120 | }; |
| 116 | 121 | ||
| @@ -177,6 +182,8 @@ d_iput: no no no yes | |||
| 177 | 182 | ||
| 178 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ | 183 | #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ |
| 179 | 184 | ||
| 185 | #define DCACHE_COOKIE 0x0040 /* For use by dcookie subsystem */ | ||
| 186 | |||
| 180 | extern spinlock_t dcache_lock; | 187 | extern spinlock_t dcache_lock; |
| 181 | extern seqlock_t rename_lock; | 188 | extern seqlock_t rename_lock; |
| 182 | 189 | ||
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 4aab6f12cfab..09d6c5bbdddd 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h | |||
| @@ -57,8 +57,6 @@ struct files_struct { | |||
| 57 | 57 | ||
| 58 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) | 58 | #define files_fdtable(files) (rcu_dereference((files)->fdt)) |
| 59 | 59 | ||
| 60 | extern struct kmem_cache *filp_cachep; | ||
| 61 | |||
| 62 | struct file_operations; | 60 | struct file_operations; |
| 63 | struct vfsmount; | 61 | struct vfsmount; |
| 64 | struct dentry; | 62 | struct dentry; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 001ded4845b4..e2170ee21e18 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | /* Fixed constants first: */ | 22 | /* Fixed constants first: */ |
| 23 | #undef NR_OPEN | 23 | #undef NR_OPEN |
| 24 | extern int sysctl_nr_open; | ||
| 25 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ | 24 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ |
| 26 | 25 | ||
| 27 | #define BLOCK_SIZE_BITS 10 | 26 | #define BLOCK_SIZE_BITS 10 |
| @@ -38,21 +37,13 @@ struct files_stat_struct { | |||
| 38 | int nr_free_files; /* read only */ | 37 | int nr_free_files; /* read only */ |
| 39 | int max_files; /* tunable */ | 38 | int max_files; /* tunable */ |
| 40 | }; | 39 | }; |
| 41 | extern struct files_stat_struct files_stat; | ||
| 42 | extern int get_max_files(void); | ||
| 43 | 40 | ||
| 44 | struct inodes_stat_t { | 41 | struct inodes_stat_t { |
| 45 | int nr_inodes; | 42 | int nr_inodes; |
| 46 | int nr_unused; | 43 | int nr_unused; |
| 47 | int dummy[5]; /* padding for sysctl ABI compatibility */ | 44 | int dummy[5]; /* padding for sysctl ABI compatibility */ |
| 48 | }; | 45 | }; |
| 49 | extern struct inodes_stat_t inodes_stat; | ||
| 50 | 46 | ||
| 51 | extern int leases_enable, lease_break_time; | ||
| 52 | |||
| 53 | #ifdef CONFIG_DNOTIFY | ||
| 54 | extern int dir_notify_enable; | ||
| 55 | #endif | ||
| 56 | 47 | ||
| 57 | #define NR_FILE 8192 /* this can well be larger on a larger system */ | 48 | #define NR_FILE 8192 /* this can well be larger on a larger system */ |
| 58 | 49 | ||
| @@ -330,6 +321,15 @@ extern void __init inode_init(void); | |||
| 330 | extern void __init inode_init_early(void); | 321 | extern void __init inode_init_early(void); |
| 331 | extern void __init files_init(unsigned long); | 322 | extern void __init files_init(unsigned long); |
| 332 | 323 | ||
| 324 | extern struct files_stat_struct files_stat; | ||
| 325 | extern int get_max_files(void); | ||
| 326 | extern int sysctl_nr_open; | ||
| 327 | extern struct inodes_stat_t inodes_stat; | ||
| 328 | extern int leases_enable, lease_break_time; | ||
| 329 | #ifdef CONFIG_DNOTIFY | ||
| 330 | extern int dir_notify_enable; | ||
| 331 | #endif | ||
| 332 | |||
| 333 | struct buffer_head; | 333 | struct buffer_head; |
| 334 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 334 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
| 335 | struct buffer_head *bh_result, int create); | 335 | struct buffer_head *bh_result, int create); |
| @@ -1212,7 +1212,6 @@ extern void unlock_super(struct super_block *); | |||
| 1212 | /* | 1212 | /* |
| 1213 | * VFS helper functions.. | 1213 | * VFS helper functions.. |
| 1214 | */ | 1214 | */ |
| 1215 | extern int vfs_permission(struct nameidata *, int); | ||
| 1216 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 1215 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); |
| 1217 | extern int vfs_mkdir(struct inode *, struct dentry *, int); | 1216 | extern int vfs_mkdir(struct inode *, struct dentry *, int); |
| 1218 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); | 1217 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); |
| @@ -1310,7 +1309,6 @@ struct file_operations { | |||
| 1310 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 1309 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
| 1311 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 1310 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
| 1312 | int (*check_flags)(int); | 1311 | int (*check_flags)(int); |
| 1313 | int (*dir_notify)(struct file *filp, unsigned long arg); | ||
| 1314 | int (*flock) (struct file *, int, struct file_lock *); | 1312 | int (*flock) (struct file *, int, struct file_lock *); |
| 1315 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); | 1313 | ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); |
| 1316 | ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); | 1314 | ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); |
| @@ -1869,7 +1867,7 @@ extern void free_write_pipe(struct file *); | |||
| 1869 | 1867 | ||
| 1870 | extern struct file *do_filp_open(int dfd, const char *pathname, | 1868 | extern struct file *do_filp_open(int dfd, const char *pathname, |
| 1871 | int open_flag, int mode); | 1869 | int open_flag, int mode); |
| 1872 | extern int may_open(struct nameidata *, int, int); | 1870 | extern int may_open(struct path *, int, int); |
| 1873 | 1871 | ||
| 1874 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); | 1872 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); |
| 1875 | extern struct file * open_exec(const char *); | 1873 | extern struct file * open_exec(const char *); |
| @@ -1904,6 +1902,8 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); | |||
| 1904 | 1902 | ||
| 1905 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); | 1903 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); |
| 1906 | extern struct inode * iget_locked(struct super_block *, unsigned long); | 1904 | extern struct inode * iget_locked(struct super_block *, unsigned long); |
| 1905 | extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *); | ||
| 1906 | extern int insert_inode_locked(struct inode *); | ||
| 1907 | extern void unlock_new_inode(struct inode *); | 1907 | extern void unlock_new_inode(struct inode *); |
| 1908 | 1908 | ||
| 1909 | extern void __iget(struct inode * inode); | 1909 | extern void __iget(struct inode * inode); |
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 9e5a06e78d02..a97c053d3a9a 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h | |||
| @@ -10,12 +10,6 @@ struct fs_struct { | |||
| 10 | struct path root, pwd; | 10 | struct path root, pwd; |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | #define INIT_FS { \ | ||
| 14 | .count = ATOMIC_INIT(1), \ | ||
| 15 | .lock = RW_LOCK_UNLOCKED, \ | ||
| 16 | .umask = 0022, \ | ||
| 17 | } | ||
| 18 | |||
| 19 | extern struct kmem_cache *fs_cachep; | 13 | extern struct kmem_cache *fs_cachep; |
| 20 | 14 | ||
| 21 | extern void exit_fs(struct task_struct *); | 15 | extern void exit_fs(struct task_struct *); |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 959f5522d10a..2f3c2d4ef73b 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <net/net_namespace.h> | 12 | #include <net/net_namespace.h> |
| 13 | 13 | ||
| 14 | extern struct files_struct init_files; | 14 | extern struct files_struct init_files; |
| 15 | extern struct fs_struct init_fs; | ||
| 15 | 16 | ||
| 16 | #define INIT_KIOCTX(name, which_mm) \ | 17 | #define INIT_KIOCTX(name, which_mm) \ |
| 17 | { \ | 18 | { \ |
diff --git a/include/linux/namei.h b/include/linux/namei.h index 99eb80306dc5..fc2e03579877 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
| @@ -94,4 +94,9 @@ static inline char *nd_get_link(struct nameidata *nd) | |||
| 94 | return nd->saved_names[nd->depth]; | 94 | return nd->saved_names[nd->depth]; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static inline void nd_terminate_link(void *name, size_t len, size_t maxlen) | ||
| 98 | { | ||
| 99 | ((char *) name)[min(len, maxlen)] = '\0'; | ||
| 100 | } | ||
| 101 | |||
| 97 | #endif /* _LINUX_NAMEI_H */ | 102 | #endif /* _LINUX_NAMEI_H */ |
diff --git a/include/linux/security.h b/include/linux/security.h index 3416cb85e77b..b92b5e453f64 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -335,17 +335,37 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 335 | * @dir contains the inode structure of the parent directory of the new link. | 335 | * @dir contains the inode structure of the parent directory of the new link. |
| 336 | * @new_dentry contains the dentry structure for the new link. | 336 | * @new_dentry contains the dentry structure for the new link. |
| 337 | * Return 0 if permission is granted. | 337 | * Return 0 if permission is granted. |
| 338 | * @path_link: | ||
| 339 | * Check permission before creating a new hard link to a file. | ||
| 340 | * @old_dentry contains the dentry structure for an existing link | ||
| 341 | * to the file. | ||
| 342 | * @new_dir contains the path structure of the parent directory of | ||
| 343 | * the new link. | ||
| 344 | * @new_dentry contains the dentry structure for the new link. | ||
| 345 | * Return 0 if permission is granted. | ||
| 338 | * @inode_unlink: | 346 | * @inode_unlink: |
| 339 | * Check the permission to remove a hard link to a file. | 347 | * Check the permission to remove a hard link to a file. |
| 340 | * @dir contains the inode structure of parent directory of the file. | 348 | * @dir contains the inode structure of parent directory of the file. |
| 341 | * @dentry contains the dentry structure for file to be unlinked. | 349 | * @dentry contains the dentry structure for file to be unlinked. |
| 342 | * Return 0 if permission is granted. | 350 | * Return 0 if permission is granted. |
| 351 | * @path_unlink: | ||
| 352 | * Check the permission to remove a hard link to a file. | ||
| 353 | * @dir contains the path structure of parent directory of the file. | ||
| 354 | * @dentry contains the dentry structure for file to be unlinked. | ||
| 355 | * Return 0 if permission is granted. | ||
| 343 | * @inode_symlink: | 356 | * @inode_symlink: |
| 344 | * Check the permission to create a symbolic link to a file. | 357 | * Check the permission to create a symbolic link to a file. |
| 345 | * @dir contains the inode structure of parent directory of the symbolic link. | 358 | * @dir contains the inode structure of parent directory of the symbolic link. |
| 346 | * @dentry contains the dentry structure of the symbolic link. | 359 | * @dentry contains the dentry structure of the symbolic link. |
| 347 | * @old_name contains the pathname of file. | 360 | * @old_name contains the pathname of file. |
| 348 | * Return 0 if permission is granted. | 361 | * Return 0 if permission is granted. |
| 362 | * @path_symlink: | ||
| 363 | * Check the permission to create a symbolic link to a file. | ||
| 364 | * @dir contains the path structure of parent directory of | ||
| 365 | * the symbolic link. | ||
| 366 | * @dentry contains the dentry structure of the symbolic link. | ||
| 367 | * @old_name contains the pathname of file. | ||
| 368 | * Return 0 if permission is granted. | ||
| 349 | * @inode_mkdir: | 369 | * @inode_mkdir: |
| 350 | * Check permissions to create a new directory in the existing directory | 370 | * Check permissions to create a new directory in the existing directory |
| 351 | * associated with inode strcture @dir. | 371 | * associated with inode strcture @dir. |
| @@ -353,11 +373,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 353 | * @dentry contains the dentry structure of new directory. | 373 | * @dentry contains the dentry structure of new directory. |
| 354 | * @mode contains the mode of new directory. | 374 | * @mode contains the mode of new directory. |
| 355 | * Return 0 if permission is granted. | 375 | * Return 0 if permission is granted. |
| 376 | * @path_mkdir: | ||
| 377 | * Check permissions to create a new directory in the existing directory | ||
| 378 | * associated with path strcture @path. | ||
| 379 | * @dir containst the path structure of parent of the directory | ||
| 380 | * to be created. | ||
| 381 | * @dentry contains the dentry structure of new directory. | ||
| 382 | * @mode contains the mode of new directory. | ||
| 383 | * Return 0 if permission is granted. | ||
| 356 | * @inode_rmdir: | 384 | * @inode_rmdir: |
| 357 | * Check the permission to remove a directory. | 385 | * Check the permission to remove a directory. |
| 358 | * @dir contains the inode structure of parent of the directory to be removed. | 386 | * @dir contains the inode structure of parent of the directory to be removed. |
| 359 | * @dentry contains the dentry structure of directory to be removed. | 387 | * @dentry contains the dentry structure of directory to be removed. |
| 360 | * Return 0 if permission is granted. | 388 | * Return 0 if permission is granted. |
| 389 | * @path_rmdir: | ||
| 390 | * Check the permission to remove a directory. | ||
| 391 | * @dir contains the path structure of parent of the directory to be | ||
| 392 | * removed. | ||
| 393 | * @dentry contains the dentry structure of directory to be removed. | ||
| 394 | * Return 0 if permission is granted. | ||
| 361 | * @inode_mknod: | 395 | * @inode_mknod: |
| 362 | * Check permissions when creating a special file (or a socket or a fifo | 396 | * Check permissions when creating a special file (or a socket or a fifo |
| 363 | * file created via the mknod system call). Note that if mknod operation | 397 | * file created via the mknod system call). Note that if mknod operation |
| @@ -368,6 +402,15 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 368 | * @mode contains the mode of the new file. | 402 | * @mode contains the mode of the new file. |
| 369 | * @dev contains the device number. | 403 | * @dev contains the device number. |
| 370 | * Return 0 if permission is granted. | 404 | * Return 0 if permission is granted. |
| 405 | * @path_mknod: | ||
| 406 | * Check permissions when creating a file. Note that this hook is called | ||
| 407 | * even if mknod operation is being done for a regular file. | ||
| 408 | * @dir contains the path structure of parent of the new file. | ||
| 409 | * @dentry contains the dentry structure of the new file. | ||
| 410 | * @mode contains the mode of the new file. | ||
| 411 | * @dev contains the undecoded device number. Use new_decode_dev() to get | ||
| 412 | * the decoded device number. | ||
| 413 | * Return 0 if permission is granted. | ||
| 371 | * @inode_rename: | 414 | * @inode_rename: |
| 372 | * Check for permission to rename a file or directory. | 415 | * Check for permission to rename a file or directory. |
| 373 | * @old_dir contains the inode structure for parent of the old link. | 416 | * @old_dir contains the inode structure for parent of the old link. |
| @@ -375,6 +418,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 375 | * @new_dir contains the inode structure for parent of the new link. | 418 | * @new_dir contains the inode structure for parent of the new link. |
| 376 | * @new_dentry contains the dentry structure of the new link. | 419 | * @new_dentry contains the dentry structure of the new link. |
| 377 | * Return 0 if permission is granted. | 420 | * Return 0 if permission is granted. |
| 421 | * @path_rename: | ||
| 422 | * Check for permission to rename a file or directory. | ||
| 423 | * @old_dir contains the path structure for parent of the old link. | ||
| 424 | * @old_dentry contains the dentry structure of the old link. | ||
| 425 | * @new_dir contains the path structure for parent of the new link. | ||
| 426 | * @new_dentry contains the dentry structure of the new link. | ||
| 427 | * Return 0 if permission is granted. | ||
| 378 | * @inode_readlink: | 428 | * @inode_readlink: |
| 379 | * Check the permission to read the symbolic link. | 429 | * Check the permission to read the symbolic link. |
| 380 | * @dentry contains the dentry structure for the file link. | 430 | * @dentry contains the dentry structure for the file link. |
| @@ -403,6 +453,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 403 | * @dentry contains the dentry structure for the file. | 453 | * @dentry contains the dentry structure for the file. |
| 404 | * @attr is the iattr structure containing the new file attributes. | 454 | * @attr is the iattr structure containing the new file attributes. |
| 405 | * Return 0 if permission is granted. | 455 | * Return 0 if permission is granted. |
| 456 | * @path_truncate: | ||
| 457 | * Check permission before truncating a file. | ||
| 458 | * @path contains the path structure for the file. | ||
| 459 | * @length is the new length of the file. | ||
| 460 | * @time_attrs is the flags passed to do_truncate(). | ||
| 461 | * Return 0 if permission is granted. | ||
| 406 | * @inode_getattr: | 462 | * @inode_getattr: |
| 407 | * Check permission before obtaining file attributes. | 463 | * Check permission before obtaining file attributes. |
| 408 | * @mnt is the vfsmount where the dentry was looked up | 464 | * @mnt is the vfsmount where the dentry was looked up |
| @@ -1331,6 +1387,22 @@ struct security_operations { | |||
| 1331 | struct super_block *newsb); | 1387 | struct super_block *newsb); |
| 1332 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1388 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
| 1333 | 1389 | ||
| 1390 | #ifdef CONFIG_SECURITY_PATH | ||
| 1391 | int (*path_unlink) (struct path *dir, struct dentry *dentry); | ||
| 1392 | int (*path_mkdir) (struct path *dir, struct dentry *dentry, int mode); | ||
| 1393 | int (*path_rmdir) (struct path *dir, struct dentry *dentry); | ||
| 1394 | int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, | ||
| 1395 | unsigned int dev); | ||
| 1396 | int (*path_truncate) (struct path *path, loff_t length, | ||
| 1397 | unsigned int time_attrs); | ||
| 1398 | int (*path_symlink) (struct path *dir, struct dentry *dentry, | ||
| 1399 | const char *old_name); | ||
| 1400 | int (*path_link) (struct dentry *old_dentry, struct path *new_dir, | ||
| 1401 | struct dentry *new_dentry); | ||
| 1402 | int (*path_rename) (struct path *old_dir, struct dentry *old_dentry, | ||
| 1403 | struct path *new_dir, struct dentry *new_dentry); | ||
| 1404 | #endif | ||
| 1405 | |||
| 1334 | int (*inode_alloc_security) (struct inode *inode); | 1406 | int (*inode_alloc_security) (struct inode *inode); |
| 1335 | void (*inode_free_security) (struct inode *inode); | 1407 | void (*inode_free_security) (struct inode *inode); |
| 1336 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | 1408 | int (*inode_init_security) (struct inode *inode, struct inode *dir, |
| @@ -2705,6 +2777,71 @@ static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi | |||
| 2705 | 2777 | ||
| 2706 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 2778 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
| 2707 | 2779 | ||
| 2780 | #ifdef CONFIG_SECURITY_PATH | ||
| 2781 | int security_path_unlink(struct path *dir, struct dentry *dentry); | ||
| 2782 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode); | ||
| 2783 | int security_path_rmdir(struct path *dir, struct dentry *dentry); | ||
| 2784 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
| 2785 | unsigned int dev); | ||
| 2786 | int security_path_truncate(struct path *path, loff_t length, | ||
| 2787 | unsigned int time_attrs); | ||
| 2788 | int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 2789 | const char *old_name); | ||
| 2790 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 2791 | struct dentry *new_dentry); | ||
| 2792 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
| 2793 | struct path *new_dir, struct dentry *new_dentry); | ||
| 2794 | #else /* CONFIG_SECURITY_PATH */ | ||
| 2795 | static inline int security_path_unlink(struct path *dir, struct dentry *dentry) | ||
| 2796 | { | ||
| 2797 | return 0; | ||
| 2798 | } | ||
| 2799 | |||
| 2800 | static inline int security_path_mkdir(struct path *dir, struct dentry *dentry, | ||
| 2801 | int mode) | ||
| 2802 | { | ||
| 2803 | return 0; | ||
| 2804 | } | ||
| 2805 | |||
| 2806 | static inline int security_path_rmdir(struct path *dir, struct dentry *dentry) | ||
| 2807 | { | ||
| 2808 | return 0; | ||
| 2809 | } | ||
| 2810 | |||
| 2811 | static inline int security_path_mknod(struct path *dir, struct dentry *dentry, | ||
| 2812 | int mode, unsigned int dev) | ||
| 2813 | { | ||
| 2814 | return 0; | ||
| 2815 | } | ||
| 2816 | |||
| 2817 | static inline int security_path_truncate(struct path *path, loff_t length, | ||
| 2818 | unsigned int time_attrs) | ||
| 2819 | { | ||
| 2820 | return 0; | ||
| 2821 | } | ||
| 2822 | |||
| 2823 | static inline int security_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 2824 | const char *old_name) | ||
| 2825 | { | ||
| 2826 | return 0; | ||
| 2827 | } | ||
| 2828 | |||
| 2829 | static inline int security_path_link(struct dentry *old_dentry, | ||
| 2830 | struct path *new_dir, | ||
| 2831 | struct dentry *new_dentry) | ||
| 2832 | { | ||
| 2833 | return 0; | ||
| 2834 | } | ||
| 2835 | |||
| 2836 | static inline int security_path_rename(struct path *old_dir, | ||
| 2837 | struct dentry *old_dentry, | ||
| 2838 | struct path *new_dir, | ||
| 2839 | struct dentry *new_dentry) | ||
| 2840 | { | ||
| 2841 | return 0; | ||
| 2842 | } | ||
| 2843 | #endif /* CONFIG_SECURITY_PATH */ | ||
| 2844 | |||
| 2708 | #ifdef CONFIG_KEYS | 2845 | #ifdef CONFIG_KEYS |
| 2709 | #ifdef CONFIG_SECURITY | 2846 | #ifdef CONFIG_SECURITY |
| 2710 | 2847 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index c6250d0055d2..d1b89820ab4f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -836,7 +836,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 836 | err = mnt_want_write(nd.path.mnt); | 836 | err = mnt_want_write(nd.path.mnt); |
| 837 | if (err) | 837 | if (err) |
| 838 | goto out_mknod_dput; | 838 | goto out_mknod_dput; |
| 839 | err = security_path_mknod(&nd.path, dentry, mode, 0); | ||
| 840 | if (err) | ||
| 841 | goto out_mknod_drop_write; | ||
| 839 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); | 842 | err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); |
| 843 | out_mknod_drop_write: | ||
| 840 | mnt_drop_write(nd.path.mnt); | 844 | mnt_drop_write(nd.path.mnt); |
| 841 | if (err) | 845 | if (err) |
| 842 | goto out_mknod_dput; | 846 | goto out_mknod_dput; |
diff --git a/security/Kconfig b/security/Kconfig index d9f47ce7e207..9438535d7fd0 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
| @@ -81,6 +81,15 @@ config SECURITY_NETWORK_XFRM | |||
| 81 | IPSec. | 81 | IPSec. |
| 82 | If you are unsure how to answer this question, answer N. | 82 | If you are unsure how to answer this question, answer N. |
| 83 | 83 | ||
| 84 | config SECURITY_PATH | ||
| 85 | bool "Security hooks for pathname based access control" | ||
| 86 | depends on SECURITY | ||
| 87 | help | ||
| 88 | This enables the security hooks for pathname based access control. | ||
| 89 | If enabled, a security module can use these hooks to | ||
| 90 | implement pathname based access controls. | ||
| 91 | If you are unsure how to answer this question, answer N. | ||
| 92 | |||
| 84 | config SECURITY_FILE_CAPABILITIES | 93 | config SECURITY_FILE_CAPABILITIES |
| 85 | bool "File POSIX Capabilities" | 94 | bool "File POSIX Capabilities" |
| 86 | default n | 95 | default n |
diff --git a/security/capability.c b/security/capability.c index 2dce66fcb992..c545bd1300b5 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -263,6 +263,53 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid) | |||
| 263 | *secid = 0; | 263 | *secid = 0; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | #ifdef CONFIG_SECURITY_PATH | ||
| 267 | static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode, | ||
| 268 | unsigned int dev) | ||
| 269 | { | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode) | ||
| 274 | { | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int cap_path_rmdir(struct path *dir, struct dentry *dentry) | ||
| 279 | { | ||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 283 | static int cap_path_unlink(struct path *dir, struct dentry *dentry) | ||
| 284 | { | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int cap_path_symlink(struct path *dir, struct dentry *dentry, | ||
| 289 | const char *old_name) | ||
| 290 | { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int cap_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 295 | struct dentry *new_dentry) | ||
| 296 | { | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int cap_path_rename(struct path *old_path, struct dentry *old_dentry, | ||
| 301 | struct path *new_path, struct dentry *new_dentry) | ||
| 302 | { | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static int cap_path_truncate(struct path *path, loff_t length, | ||
| 307 | unsigned int time_attrs) | ||
| 308 | { | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | |||
| 266 | static int cap_file_permission(struct file *file, int mask) | 313 | static int cap_file_permission(struct file *file, int mask) |
| 267 | { | 314 | { |
| 268 | return 0; | 315 | return 0; |
| @@ -883,6 +930,16 @@ void security_fixup_ops(struct security_operations *ops) | |||
| 883 | set_to_cap_if_null(ops, inode_setsecurity); | 930 | set_to_cap_if_null(ops, inode_setsecurity); |
| 884 | set_to_cap_if_null(ops, inode_listsecurity); | 931 | set_to_cap_if_null(ops, inode_listsecurity); |
| 885 | set_to_cap_if_null(ops, inode_getsecid); | 932 | set_to_cap_if_null(ops, inode_getsecid); |
| 933 | #ifdef CONFIG_SECURITY_PATH | ||
| 934 | set_to_cap_if_null(ops, path_mknod); | ||
| 935 | set_to_cap_if_null(ops, path_mkdir); | ||
| 936 | set_to_cap_if_null(ops, path_rmdir); | ||
| 937 | set_to_cap_if_null(ops, path_unlink); | ||
| 938 | set_to_cap_if_null(ops, path_symlink); | ||
| 939 | set_to_cap_if_null(ops, path_link); | ||
| 940 | set_to_cap_if_null(ops, path_rename); | ||
| 941 | set_to_cap_if_null(ops, path_truncate); | ||
| 942 | #endif | ||
| 886 | set_to_cap_if_null(ops, file_permission); | 943 | set_to_cap_if_null(ops, file_permission); |
| 887 | set_to_cap_if_null(ops, file_alloc_security); | 944 | set_to_cap_if_null(ops, file_alloc_security); |
| 888 | set_to_cap_if_null(ops, file_free_security); | 945 | set_to_cap_if_null(ops, file_free_security); |
diff --git a/security/security.c b/security/security.c index d85dbb37c972..678d4d07b852 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -355,6 +355,72 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 355 | } | 355 | } |
| 356 | EXPORT_SYMBOL(security_inode_init_security); | 356 | EXPORT_SYMBOL(security_inode_init_security); |
| 357 | 357 | ||
| 358 | #ifdef CONFIG_SECURITY_PATH | ||
| 359 | int security_path_mknod(struct path *path, struct dentry *dentry, int mode, | ||
| 360 | unsigned int dev) | ||
| 361 | { | ||
| 362 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 363 | return 0; | ||
| 364 | return security_ops->path_mknod(path, dentry, mode, dev); | ||
| 365 | } | ||
| 366 | EXPORT_SYMBOL(security_path_mknod); | ||
| 367 | |||
| 368 | int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) | ||
| 369 | { | ||
| 370 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 371 | return 0; | ||
| 372 | return security_ops->path_mkdir(path, dentry, mode); | ||
| 373 | } | ||
| 374 | |||
| 375 | int security_path_rmdir(struct path *path, struct dentry *dentry) | ||
| 376 | { | ||
| 377 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 378 | return 0; | ||
| 379 | return security_ops->path_rmdir(path, dentry); | ||
| 380 | } | ||
| 381 | |||
| 382 | int security_path_unlink(struct path *path, struct dentry *dentry) | ||
| 383 | { | ||
| 384 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 385 | return 0; | ||
| 386 | return security_ops->path_unlink(path, dentry); | ||
| 387 | } | ||
| 388 | |||
| 389 | int security_path_symlink(struct path *path, struct dentry *dentry, | ||
| 390 | const char *old_name) | ||
| 391 | { | ||
| 392 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 393 | return 0; | ||
| 394 | return security_ops->path_symlink(path, dentry, old_name); | ||
| 395 | } | ||
| 396 | |||
| 397 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
| 398 | struct dentry *new_dentry) | ||
| 399 | { | ||
| 400 | if (unlikely(IS_PRIVATE(old_dentry->d_inode))) | ||
| 401 | return 0; | ||
| 402 | return security_ops->path_link(old_dentry, new_dir, new_dentry); | ||
| 403 | } | ||
| 404 | |||
| 405 | int security_path_rename(struct path *old_dir, struct dentry *old_dentry, | ||
| 406 | struct path *new_dir, struct dentry *new_dentry) | ||
| 407 | { | ||
| 408 | if (unlikely(IS_PRIVATE(old_dentry->d_inode) || | ||
| 409 | (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode)))) | ||
| 410 | return 0; | ||
| 411 | return security_ops->path_rename(old_dir, old_dentry, new_dir, | ||
| 412 | new_dentry); | ||
| 413 | } | ||
| 414 | |||
| 415 | int security_path_truncate(struct path *path, loff_t length, | ||
| 416 | unsigned int time_attrs) | ||
| 417 | { | ||
| 418 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
| 419 | return 0; | ||
| 420 | return security_ops->path_truncate(path, length, time_attrs); | ||
| 421 | } | ||
| 422 | #endif | ||
| 423 | |||
| 358 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) | 424 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) |
| 359 | { | 425 | { |
| 360 | if (unlikely(IS_PRIVATE(dir))) | 426 | if (unlikely(IS_PRIVATE(dir))) |
