diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-31 18:57:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-31 18:57:56 -0500 |
commit | b58602a4bac012b5f4fc12fe6b46ab237b610d5d (patch) | |
tree | 38929e210a723f67fe2b945f37264bf3aae3c2c4 | |
parent | db200df0b3530f673d8e9f5bd535e9e10305842a (diff) | |
parent | 1f3403fa640f9f7b135dee79f2d39d01c8ad4a08 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (34 commits)
nfsd race fixes: jfs
nfsd race fixes: reiserfs
nfsd race fixes: ext4
nfsd race fixes: ext3
nfsd race fixes: ext2
nfsd/create race fixes, infrastructure
filesystem notification: create fs/notify to contain all fs notification
fs/block_dev.c: __read_mostly improvement and sb_is_blkdev_sb utilization
kill ->dir_notify()
filp_cachep can be static in fs/file_table.c
fix f_count description in Documentation/filesystems/files.txt
make INIT_FS use the __RW_LOCK_UNLOCKED initialization
take init_fs to saner place
kill vfs_permission
pass a struct path * to may_open
kill walk_init_root
remove incorrect comment in inode_permission
expand some comments (d_path / seq_path)
correct wrong function name of d_put in kernel document and source comment
fix switch_names() breakage in short-to-short case
...
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))) |