diff options
Diffstat (limited to 'fs')
198 files changed, 2560 insertions, 1083 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 43c9f7de0314..f867b8d3e973 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -39,8 +39,8 @@ | |||
39 | 39 | ||
40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; |
41 | extern struct address_space_operations v9fs_addr_operations; | 41 | extern struct address_space_operations v9fs_addr_operations; |
42 | extern struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; |
43 | extern struct file_operations v9fs_dir_operations; | 43 | extern const struct file_operations v9fs_dir_operations; |
44 | extern struct dentry_operations v9fs_dentry_operations; | 44 | extern struct dentry_operations v9fs_dentry_operations; |
45 | 45 | ||
46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 766f11f1215c..e32d5971039b 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -204,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
207 | struct file_operations v9fs_dir_operations = { | 207 | const struct file_operations v9fs_dir_operations = { |
208 | .read = generic_read_dir, | 208 | .read = generic_read_dir, |
209 | .readdir = v9fs_dir_readdir, | 209 | .readdir = v9fs_dir_readdir, |
210 | .open = v9fs_file_open, | 210 | .open = v9fs_file_open, |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 59e744163407..083dcfcd158e 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -266,7 +266,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
266 | return total; | 266 | return total; |
267 | } | 267 | } |
268 | 268 | ||
269 | struct file_operations v9fs_file_operations = { | 269 | const struct file_operations v9fs_file_operations = { |
270 | .llseek = generic_file_llseek, | 270 | .llseek = generic_file_llseek, |
271 | .read = v9fs_file_read, | 271 | .read = v9fs_file_read, |
272 | .write = v9fs_file_write, | 272 | .write = v9fs_file_write, |
diff --git a/fs/Makefile b/fs/Makefile index 080b3867be4d..f3a4f7077175 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ | |||
10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ | 10 | ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ |
11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ | 11 | attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ |
12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ | 12 | seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ |
13 | ioprio.o pnode.o drop_caches.o | 13 | ioprio.o pnode.o drop_caches.o splice.o |
14 | 14 | ||
15 | obj-$(CONFIG_INOTIFY) += inotify.o | 15 | obj-$(CONFIG_INOTIFY) += inotify.o |
16 | obj-$(CONFIG_EPOLL) += eventpoll.o | 16 | obj-$(CONFIG_EPOLL) += eventpoll.o |
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index f6cd01352cc8..29217ff36d44 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
@@ -85,7 +85,7 @@ void __adfs_error(struct super_block *sb, const char *function, | |||
85 | 85 | ||
86 | /* dir_*.c */ | 86 | /* dir_*.c */ |
87 | extern struct inode_operations adfs_dir_inode_operations; | 87 | extern struct inode_operations adfs_dir_inode_operations; |
88 | extern struct file_operations adfs_dir_operations; | 88 | extern const struct file_operations adfs_dir_operations; |
89 | extern struct dentry_operations adfs_dentry_operations; | 89 | extern struct dentry_operations adfs_dentry_operations; |
90 | extern struct adfs_dir_ops adfs_f_dir_ops; | 90 | extern struct adfs_dir_ops adfs_f_dir_ops; |
91 | extern struct adfs_dir_ops adfs_fplus_dir_ops; | 91 | extern struct adfs_dir_ops adfs_fplus_dir_ops; |
@@ -94,7 +94,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); | |||
94 | 94 | ||
95 | /* file.c */ | 95 | /* file.c */ |
96 | extern struct inode_operations adfs_file_inode_operations; | 96 | extern struct inode_operations adfs_file_inode_operations; |
97 | extern struct file_operations adfs_file_operations; | 97 | extern const struct file_operations adfs_file_operations; |
98 | 98 | ||
99 | static inline __u32 signed_asl(__u32 val, signed int shift) | 99 | static inline __u32 signed_asl(__u32 val, signed int shift) |
100 | { | 100 | { |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 0b4c3a028076..7b075fc397da 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -196,7 +196,7 @@ out: | |||
196 | return ret; | 196 | return ret; |
197 | } | 197 | } |
198 | 198 | ||
199 | struct file_operations adfs_dir_operations = { | 199 | const struct file_operations adfs_dir_operations = { |
200 | .read = generic_read_dir, | 200 | .read = generic_read_dir, |
201 | .readdir = adfs_readdir, | 201 | .readdir = adfs_readdir, |
202 | .fsync = file_fsync, | 202 | .fsync = file_fsync, |
diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 6af10885f9d6..1014b9f2117b 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include "adfs.h" | 26 | #include "adfs.h" |
27 | 27 | ||
28 | struct file_operations adfs_file_operations = { | 28 | const struct file_operations adfs_file_operations = { |
29 | .llseek = generic_file_llseek, | 29 | .llseek = generic_file_llseek, |
30 | .read = generic_file_read, | 30 | .read = generic_file_read, |
31 | .mmap = generic_file_mmap, | 31 | .mmap = generic_file_mmap, |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 0c6799f2137a..a43a876742b8 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
@@ -192,9 +192,9 @@ extern void affs_dir_truncate(struct inode *); | |||
192 | extern struct inode_operations affs_file_inode_operations; | 192 | extern struct inode_operations affs_file_inode_operations; |
193 | extern struct inode_operations affs_dir_inode_operations; | 193 | extern struct inode_operations affs_dir_inode_operations; |
194 | extern struct inode_operations affs_symlink_inode_operations; | 194 | extern struct inode_operations affs_symlink_inode_operations; |
195 | extern struct file_operations affs_file_operations; | 195 | extern const struct file_operations affs_file_operations; |
196 | extern struct file_operations affs_file_operations_ofs; | 196 | extern const struct file_operations affs_file_operations_ofs; |
197 | extern struct file_operations affs_dir_operations; | 197 | extern const struct file_operations affs_dir_operations; |
198 | extern struct address_space_operations affs_symlink_aops; | 198 | extern struct address_space_operations affs_symlink_aops; |
199 | extern struct address_space_operations affs_aops; | 199 | extern struct address_space_operations affs_aops; |
200 | extern struct address_space_operations affs_aops_ofs; | 200 | extern struct address_space_operations affs_aops_ofs; |
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 548efd0ee98c..5d9649fa1814 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | static int affs_readdir(struct file *, void *, filldir_t); | 18 | static int affs_readdir(struct file *, void *, filldir_t); |
19 | 19 | ||
20 | struct file_operations affs_dir_operations = { | 20 | const struct file_operations affs_dir_operations = { |
21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
22 | .readdir = affs_readdir, | 22 | .readdir = affs_readdir, |
23 | .fsync = file_fsync, | 23 | .fsync = file_fsync, |
diff --git a/fs/affs/file.c b/fs/affs/file.c index f72fb776ecdf..7076262af39b 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -25,7 +25,7 @@ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); | |||
25 | static int affs_file_open(struct inode *inode, struct file *filp); | 25 | static int affs_file_open(struct inode *inode, struct file *filp); |
26 | static int affs_file_release(struct inode *inode, struct file *filp); | 26 | static int affs_file_release(struct inode *inode, struct file *filp); |
27 | 27 | ||
28 | struct file_operations affs_file_operations = { | 28 | const struct file_operations affs_file_operations = { |
29 | .llseek = generic_file_llseek, | 29 | .llseek = generic_file_llseek, |
30 | .read = generic_file_read, | 30 | .read = generic_file_read, |
31 | .write = generic_file_write, | 31 | .write = generic_file_write, |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 5c61c24dab2a..a6dff6a4f204 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -32,7 +32,7 @@ static int afs_d_delete(struct dentry *dentry); | |||
32 | static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, | 32 | static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, |
33 | loff_t fpos, ino_t ino, unsigned dtype); | 33 | loff_t fpos, ino_t ino, unsigned dtype); |
34 | 34 | ||
35 | struct file_operations afs_dir_file_operations = { | 35 | const struct file_operations afs_dir_file_operations = { |
36 | .open = afs_dir_open, | 36 | .open = afs_dir_open, |
37 | .readdir = afs_dir_readdir, | 37 | .readdir = afs_dir_readdir, |
38 | }; | 38 | }; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ab8f87c66319..72febdf9a35a 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -64,7 +64,7 @@ extern struct cachefs_index_def afs_cache_cell_index_def; | |||
64 | * dir.c | 64 | * dir.c |
65 | */ | 65 | */ |
66 | extern struct inode_operations afs_dir_inode_operations; | 66 | extern struct inode_operations afs_dir_inode_operations; |
67 | extern struct file_operations afs_dir_file_operations; | 67 | extern const struct file_operations afs_dir_file_operations; |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * file.c | 70 | * file.c |
@@ -105,7 +105,7 @@ extern struct cachefs_netfs afs_cache_netfs; | |||
105 | * mntpt.c | 105 | * mntpt.c |
106 | */ | 106 | */ |
107 | extern struct inode_operations afs_mntpt_inode_operations; | 107 | extern struct inode_operations afs_mntpt_inode_operations; |
108 | extern struct file_operations afs_mntpt_file_operations; | 108 | extern const struct file_operations afs_mntpt_file_operations; |
109 | extern struct afs_timer afs_mntpt_expiry_timer; | 109 | extern struct afs_timer afs_mntpt_expiry_timer; |
110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; | 110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; |
111 | extern unsigned long afs_mntpt_expiry_timeout; | 111 | extern unsigned long afs_mntpt_expiry_timeout; |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 31ee06590de5..4e6eeb59b83c 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -32,7 +32,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, | |||
32 | static int afs_mntpt_open(struct inode *inode, struct file *file); | 32 | static int afs_mntpt_open(struct inode *inode, struct file *file); |
33 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); | 33 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); |
34 | 34 | ||
35 | struct file_operations afs_mntpt_file_operations = { | 35 | const struct file_operations afs_mntpt_file_operations = { |
36 | .open = afs_mntpt_open, | 36 | .open = afs_mntpt_open, |
37 | }; | 37 | }; |
38 | 38 | ||
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 9c81b8f7eef0..101d21b6c037 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
@@ -37,7 +37,7 @@ static struct seq_operations afs_proc_cells_ops = { | |||
37 | .show = afs_proc_cells_show, | 37 | .show = afs_proc_cells_show, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static struct file_operations afs_proc_cells_fops = { | 40 | static const struct file_operations afs_proc_cells_fops = { |
41 | .open = afs_proc_cells_open, | 41 | .open = afs_proc_cells_open, |
42 | .read = seq_read, | 42 | .read = seq_read, |
43 | .write = afs_proc_cells_write, | 43 | .write = afs_proc_cells_write, |
@@ -53,7 +53,7 @@ static ssize_t afs_proc_rootcell_write(struct file *file, | |||
53 | const char __user *buf, | 53 | const char __user *buf, |
54 | size_t size, loff_t *_pos); | 54 | size_t size, loff_t *_pos); |
55 | 55 | ||
56 | static struct file_operations afs_proc_rootcell_fops = { | 56 | static const struct file_operations afs_proc_rootcell_fops = { |
57 | .open = afs_proc_rootcell_open, | 57 | .open = afs_proc_rootcell_open, |
58 | .read = afs_proc_rootcell_read, | 58 | .read = afs_proc_rootcell_read, |
59 | .write = afs_proc_rootcell_write, | 59 | .write = afs_proc_rootcell_write, |
@@ -77,7 +77,7 @@ static struct seq_operations afs_proc_cell_volumes_ops = { | |||
77 | .show = afs_proc_cell_volumes_show, | 77 | .show = afs_proc_cell_volumes_show, |
78 | }; | 78 | }; |
79 | 79 | ||
80 | static struct file_operations afs_proc_cell_volumes_fops = { | 80 | static const struct file_operations afs_proc_cell_volumes_fops = { |
81 | .open = afs_proc_cell_volumes_open, | 81 | .open = afs_proc_cell_volumes_open, |
82 | .read = seq_read, | 82 | .read = seq_read, |
83 | .llseek = seq_lseek, | 83 | .llseek = seq_lseek, |
@@ -101,7 +101,7 @@ static struct seq_operations afs_proc_cell_vlservers_ops = { | |||
101 | .show = afs_proc_cell_vlservers_show, | 101 | .show = afs_proc_cell_vlservers_show, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static struct file_operations afs_proc_cell_vlservers_fops = { | 104 | static const struct file_operations afs_proc_cell_vlservers_fops = { |
105 | .open = afs_proc_cell_vlservers_open, | 105 | .open = afs_proc_cell_vlservers_open, |
106 | .read = seq_read, | 106 | .read = seq_read, |
107 | .llseek = seq_lseek, | 107 | .llseek = seq_lseek, |
@@ -124,7 +124,7 @@ static struct seq_operations afs_proc_cell_servers_ops = { | |||
124 | .show = afs_proc_cell_servers_show, | 124 | .show = afs_proc_cell_servers_show, |
125 | }; | 125 | }; |
126 | 126 | ||
127 | static struct file_operations afs_proc_cell_servers_fops = { | 127 | static const struct file_operations afs_proc_cell_servers_fops = { |
128 | .open = afs_proc_cell_servers_open, | 128 | .open = afs_proc_cell_servers_open, |
129 | .read = seq_read, | 129 | .read = seq_read, |
130 | .llseek = seq_lseek, | 130 | .llseek = seq_lseek, |
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 990c28da5aec..a62327f1bdff 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h | |||
@@ -146,7 +146,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info | |||
146 | 146 | ||
147 | extern struct inode_operations autofs_root_inode_operations; | 147 | extern struct inode_operations autofs_root_inode_operations; |
148 | extern struct inode_operations autofs_symlink_inode_operations; | 148 | extern struct inode_operations autofs_symlink_inode_operations; |
149 | extern struct file_operations autofs_root_operations; | 149 | extern const struct file_operations autofs_root_operations; |
150 | 150 | ||
151 | /* Initializing function */ | 151 | /* Initializing function */ |
152 | 152 | ||
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index 5ccfcf26310d..3fded389d06b 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c | |||
@@ -92,7 +92,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, | |||
92 | ; | 92 | ; |
93 | dput(dentry); | 93 | dput(dentry); |
94 | 94 | ||
95 | if ( may_umount(mnt) == 0 ) { | 95 | if ( may_umount(mnt) ) { |
96 | mntput(mnt); | 96 | mntput(mnt); |
97 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); | 97 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); |
98 | return ent; /* Expirable! */ | 98 | return ent; /* Expirable! */ |
diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 870e2cf33016..9cac08d6a873 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c | |||
@@ -26,7 +26,7 @@ static int autofs_root_rmdir(struct inode *,struct dentry *); | |||
26 | static int autofs_root_mkdir(struct inode *,struct dentry *,int); | 26 | static int autofs_root_mkdir(struct inode *,struct dentry *,int); |
27 | static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); | 27 | static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); |
28 | 28 | ||
29 | struct file_operations autofs_root_operations = { | 29 | const struct file_operations autofs_root_operations = { |
30 | .read = generic_read_dir, | 30 | .read = generic_read_dir, |
31 | .readdir = autofs_root_readdir, | 31 | .readdir = autofs_root_readdir, |
32 | .ioctl = autofs_root_ioctl, | 32 | .ioctl = autofs_root_ioctl, |
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index f54c5b21f876..57c4903614e5 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -3,6 +3,7 @@ | |||
3 | * linux/fs/autofs/autofs_i.h | 3 | * linux/fs/autofs/autofs_i.h |
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation - All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation - All Rights Reserved |
6 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> | ||
6 | * | 7 | * |
7 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
8 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
@@ -41,14 +42,6 @@ | |||
41 | 42 | ||
42 | #define AUTOFS_SUPER_MAGIC 0x0187 | 43 | #define AUTOFS_SUPER_MAGIC 0x0187 |
43 | 44 | ||
44 | /* | ||
45 | * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the | ||
46 | * kernel will keep the negative response cached for up to the time given | ||
47 | * here, although the time can be shorter if the kernel throws the dcache | ||
48 | * entry away. This probably should be settable from user space. | ||
49 | */ | ||
50 | #define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */ | ||
51 | |||
52 | /* Unified info structure. This is pointed to by both the dentry and | 45 | /* Unified info structure. This is pointed to by both the dentry and |
53 | inode structures. Each file in the filesystem has an instance of this | 46 | inode structures. Each file in the filesystem has an instance of this |
54 | structure. It holds a reference to the dentry, so dentries are never | 47 | structure. It holds a reference to the dentry, so dentries are never |
@@ -63,6 +56,7 @@ struct autofs_info { | |||
63 | 56 | ||
64 | struct autofs_sb_info *sbi; | 57 | struct autofs_sb_info *sbi; |
65 | unsigned long last_used; | 58 | unsigned long last_used; |
59 | atomic_t count; | ||
66 | 60 | ||
67 | mode_t mode; | 61 | mode_t mode; |
68 | size_t size; | 62 | size_t size; |
@@ -83,23 +77,37 @@ struct autofs_wait_queue { | |||
83 | int hash; | 77 | int hash; |
84 | int len; | 78 | int len; |
85 | char *name; | 79 | char *name; |
80 | u32 dev; | ||
81 | u64 ino; | ||
82 | uid_t uid; | ||
83 | gid_t gid; | ||
84 | pid_t pid; | ||
85 | pid_t tgid; | ||
86 | /* This is for status reporting upon return */ | 86 | /* This is for status reporting upon return */ |
87 | int status; | 87 | int status; |
88 | atomic_t notified; | 88 | atomic_t notify; |
89 | atomic_t wait_ctr; | 89 | atomic_t wait_ctr; |
90 | }; | 90 | }; |
91 | 91 | ||
92 | #define AUTOFS_SBI_MAGIC 0x6d4a556d | 92 | #define AUTOFS_SBI_MAGIC 0x6d4a556d |
93 | 93 | ||
94 | #define AUTOFS_TYPE_INDIRECT 0x0001 | ||
95 | #define AUTOFS_TYPE_DIRECT 0x0002 | ||
96 | #define AUTOFS_TYPE_OFFSET 0x0004 | ||
97 | |||
94 | struct autofs_sb_info { | 98 | struct autofs_sb_info { |
95 | u32 magic; | 99 | u32 magic; |
96 | struct dentry *root; | 100 | struct dentry *root; |
101 | int pipefd; | ||
97 | struct file *pipe; | 102 | struct file *pipe; |
98 | pid_t oz_pgrp; | 103 | pid_t oz_pgrp; |
99 | int catatonic; | 104 | int catatonic; |
100 | int version; | 105 | int version; |
101 | int sub_version; | 106 | int sub_version; |
107 | int min_proto; | ||
108 | int max_proto; | ||
102 | unsigned long exp_timeout; | 109 | unsigned long exp_timeout; |
110 | unsigned int type; | ||
103 | int reghost_enabled; | 111 | int reghost_enabled; |
104 | int needs_reghost; | 112 | int needs_reghost; |
105 | struct super_block *sb; | 113 | struct super_block *sb; |
@@ -166,8 +174,10 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *, | |||
166 | extern struct inode_operations autofs4_symlink_inode_operations; | 174 | extern struct inode_operations autofs4_symlink_inode_operations; |
167 | extern struct inode_operations autofs4_dir_inode_operations; | 175 | extern struct inode_operations autofs4_dir_inode_operations; |
168 | extern struct inode_operations autofs4_root_inode_operations; | 176 | extern struct inode_operations autofs4_root_inode_operations; |
169 | extern struct file_operations autofs4_dir_operations; | 177 | extern struct inode_operations autofs4_indirect_root_inode_operations; |
170 | extern struct file_operations autofs4_root_operations; | 178 | extern struct inode_operations autofs4_direct_root_inode_operations; |
179 | extern const struct file_operations autofs4_dir_operations; | ||
180 | extern const struct file_operations autofs4_root_operations; | ||
171 | 181 | ||
172 | /* Initializing function */ | 182 | /* Initializing function */ |
173 | 183 | ||
@@ -176,13 +186,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info | |||
176 | 186 | ||
177 | /* Queue management functions */ | 187 | /* Queue management functions */ |
178 | 188 | ||
179 | enum autofs_notify | ||
180 | { | ||
181 | NFY_NONE, | ||
182 | NFY_MOUNT, | ||
183 | NFY_EXPIRE | ||
184 | }; | ||
185 | |||
186 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); | 189 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); |
187 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); | 190 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); |
188 | void autofs4_catatonic_mode(struct autofs_sb_info *); | 191 | void autofs4_catatonic_mode(struct autofs_sb_info *); |
@@ -200,12 +203,22 @@ static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **de | |||
200 | return res; | 203 | return res; |
201 | } | 204 | } |
202 | 205 | ||
206 | static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi) | ||
207 | { | ||
208 | return new_encode_dev(sbi->sb->s_dev); | ||
209 | } | ||
210 | |||
211 | static inline u64 autofs4_get_ino(struct autofs_sb_info *sbi) | ||
212 | { | ||
213 | return sbi->sb->s_root->d_inode->i_ino; | ||
214 | } | ||
215 | |||
203 | static inline int simple_positive(struct dentry *dentry) | 216 | static inline int simple_positive(struct dentry *dentry) |
204 | { | 217 | { |
205 | return dentry->d_inode && !d_unhashed(dentry); | 218 | return dentry->d_inode && !d_unhashed(dentry); |
206 | } | 219 | } |
207 | 220 | ||
208 | static inline int simple_empty_nolock(struct dentry *dentry) | 221 | static inline int __simple_empty(struct dentry *dentry) |
209 | { | 222 | { |
210 | struct dentry *child; | 223 | struct dentry *child; |
211 | int ret = 0; | 224 | int ret = 0; |
@@ -217,3 +230,6 @@ static inline int simple_empty_nolock(struct dentry *dentry) | |||
217 | out: | 230 | out: |
218 | return ret; | 231 | return ret; |
219 | } | 232 | } |
233 | |||
234 | void autofs4_dentry_release(struct dentry *); | ||
235 | |||
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index dc39589df165..b8ce02607d66 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> | 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
7 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 7 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
8 | * | 8 | * |
9 | * This file is part of the Linux kernel and is made available under | 9 | * This file is part of the Linux kernel and is made available under |
10 | * the terms of the GNU General Public License, version 2, or at your | 10 | * the terms of the GNU General Public License, version 2, or at your |
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | static unsigned long now; | 17 | static unsigned long now; |
18 | 18 | ||
19 | /* Check if a dentry can be expired return 1 if it can else return 0 */ | 19 | /* Check if a dentry can be expired */ |
20 | static inline int autofs4_can_expire(struct dentry *dentry, | 20 | static inline int autofs4_can_expire(struct dentry *dentry, |
21 | unsigned long timeout, int do_now) | 21 | unsigned long timeout, int do_now) |
22 | { | 22 | { |
@@ -41,14 +41,14 @@ static inline int autofs4_can_expire(struct dentry *dentry, | |||
41 | attempts if expire fails the first time */ | 41 | attempts if expire fails the first time */ |
42 | ino->last_used = now; | 42 | ino->last_used = now; |
43 | } | 43 | } |
44 | |||
45 | return 1; | 44 | return 1; |
46 | } | 45 | } |
47 | 46 | ||
48 | /* Check a mount point for busyness return 1 if not busy, otherwise */ | 47 | /* Check a mount point for busyness */ |
49 | static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry) | 48 | static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) |
50 | { | 49 | { |
51 | int status = 0; | 50 | struct dentry *top = dentry; |
51 | int status = 1; | ||
52 | 52 | ||
53 | DPRINTK("dentry %p %.*s", | 53 | DPRINTK("dentry %p %.*s", |
54 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 54 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
@@ -63,9 +63,14 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry) | |||
63 | if (is_autofs4_dentry(dentry)) | 63 | if (is_autofs4_dentry(dentry)) |
64 | goto done; | 64 | goto done; |
65 | 65 | ||
66 | /* The big question */ | 66 | /* Update the expiry counter if fs is busy */ |
67 | if (may_umount_tree(mnt) == 0) | 67 | if (!may_umount_tree(mnt)) { |
68 | status = 1; | 68 | struct autofs_info *ino = autofs4_dentry_ino(top); |
69 | ino->last_used = jiffies; | ||
70 | goto done; | ||
71 | } | ||
72 | |||
73 | status = 0; | ||
69 | done: | 74 | done: |
70 | DPRINTK("returning = %d", status); | 75 | DPRINTK("returning = %d", status); |
71 | mntput(mnt); | 76 | mntput(mnt); |
@@ -73,78 +78,124 @@ done: | |||
73 | return status; | 78 | return status; |
74 | } | 79 | } |
75 | 80 | ||
81 | /* | ||
82 | * Calculate next entry in top down tree traversal. | ||
83 | * From next_mnt in namespace.c - elegant. | ||
84 | */ | ||
85 | static struct dentry *next_dentry(struct dentry *p, struct dentry *root) | ||
86 | { | ||
87 | struct list_head *next = p->d_subdirs.next; | ||
88 | |||
89 | if (next == &p->d_subdirs) { | ||
90 | while (1) { | ||
91 | if (p == root) | ||
92 | return NULL; | ||
93 | next = p->d_u.d_child.next; | ||
94 | if (next != &p->d_parent->d_subdirs) | ||
95 | break; | ||
96 | p = p->d_parent; | ||
97 | } | ||
98 | } | ||
99 | return list_entry(next, struct dentry, d_u.d_child); | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * Check a direct mount point for busyness. | ||
104 | * Direct mounts have similar expiry semantics to tree mounts. | ||
105 | * The tree is not busy iff no mountpoints are busy and there are no | ||
106 | * autofs submounts. | ||
107 | */ | ||
108 | static int autofs4_direct_busy(struct vfsmount *mnt, | ||
109 | struct dentry *top, | ||
110 | unsigned long timeout, | ||
111 | int do_now) | ||
112 | { | ||
113 | DPRINTK("top %p %.*s", | ||
114 | top, (int) top->d_name.len, top->d_name.name); | ||
115 | |||
116 | /* If it's busy update the expiry counters */ | ||
117 | if (!may_umount_tree(mnt)) { | ||
118 | struct autofs_info *ino = autofs4_dentry_ino(top); | ||
119 | if (ino) | ||
120 | ino->last_used = jiffies; | ||
121 | return 1; | ||
122 | } | ||
123 | |||
124 | /* Timeout of a direct mount is determined by its top dentry */ | ||
125 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
126 | return 1; | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
76 | /* Check a directory tree of mount points for busyness | 131 | /* Check a directory tree of mount points for busyness |
77 | * The tree is not busy iff no mountpoints are busy | 132 | * The tree is not busy iff no mountpoints are busy |
78 | * Return 1 if the tree is busy or 0 otherwise | ||
79 | */ | 133 | */ |
80 | static int autofs4_check_tree(struct vfsmount *mnt, | 134 | static int autofs4_tree_busy(struct vfsmount *mnt, |
81 | struct dentry *top, | 135 | struct dentry *top, |
82 | unsigned long timeout, | 136 | unsigned long timeout, |
83 | int do_now) | 137 | int do_now) |
84 | { | 138 | { |
85 | struct dentry *this_parent = top; | 139 | struct autofs_info *top_ino = autofs4_dentry_ino(top); |
86 | struct list_head *next; | 140 | struct dentry *p; |
87 | 141 | ||
88 | DPRINTK("parent %p %.*s", | 142 | DPRINTK("top %p %.*s", |
89 | top, (int)top->d_name.len, top->d_name.name); | 143 | top, (int)top->d_name.len, top->d_name.name); |
90 | 144 | ||
91 | /* Negative dentry - give up */ | 145 | /* Negative dentry - give up */ |
92 | if (!simple_positive(top)) | 146 | if (!simple_positive(top)) |
93 | return 0; | 147 | return 1; |
94 | |||
95 | /* Timeout of a tree mount is determined by its top dentry */ | ||
96 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
97 | return 0; | ||
98 | |||
99 | /* Is someone visiting anywhere in the tree ? */ | ||
100 | if (may_umount_tree(mnt)) | ||
101 | return 0; | ||
102 | 148 | ||
103 | spin_lock(&dcache_lock); | 149 | spin_lock(&dcache_lock); |
104 | repeat: | 150 | for (p = top; p; p = next_dentry(p, top)) { |
105 | next = this_parent->d_subdirs.next; | ||
106 | resume: | ||
107 | while (next != &this_parent->d_subdirs) { | ||
108 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | ||
109 | |||
110 | /* Negative dentry - give up */ | 151 | /* Negative dentry - give up */ |
111 | if (!simple_positive(dentry)) { | 152 | if (!simple_positive(p)) |
112 | next = next->next; | ||
113 | continue; | 153 | continue; |
114 | } | ||
115 | 154 | ||
116 | DPRINTK("dentry %p %.*s", | 155 | DPRINTK("dentry %p %.*s", |
117 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 156 | p, (int) p->d_name.len, p->d_name.name); |
118 | |||
119 | if (!simple_empty_nolock(dentry)) { | ||
120 | this_parent = dentry; | ||
121 | goto repeat; | ||
122 | } | ||
123 | 157 | ||
124 | dentry = dget(dentry); | 158 | p = dget(p); |
125 | spin_unlock(&dcache_lock); | 159 | spin_unlock(&dcache_lock); |
126 | 160 | ||
127 | if (d_mountpoint(dentry)) { | 161 | /* |
128 | /* First busy => tree busy */ | 162 | * Is someone visiting anywhere in the subtree ? |
129 | if (!autofs4_check_mount(mnt, dentry)) { | 163 | * If there's no mount we need to check the usage |
130 | dput(dentry); | 164 | * count for the autofs dentry. |
131 | return 0; | 165 | * If the fs is busy update the expiry counter. |
166 | */ | ||
167 | if (d_mountpoint(p)) { | ||
168 | if (autofs4_mount_busy(mnt, p)) { | ||
169 | top_ino->last_used = jiffies; | ||
170 | dput(p); | ||
171 | return 1; | ||
172 | } | ||
173 | } else { | ||
174 | struct autofs_info *ino = autofs4_dentry_ino(p); | ||
175 | unsigned int ino_count = atomic_read(&ino->count); | ||
176 | |||
177 | /* allow for dget above and top is already dgot */ | ||
178 | if (p == top) | ||
179 | ino_count += 2; | ||
180 | else | ||
181 | ino_count++; | ||
182 | |||
183 | if (atomic_read(&p->d_count) > ino_count) { | ||
184 | top_ino->last_used = jiffies; | ||
185 | dput(p); | ||
186 | return 1; | ||
132 | } | 187 | } |
133 | } | 188 | } |
134 | 189 | dput(p); | |
135 | dput(dentry); | ||
136 | spin_lock(&dcache_lock); | 190 | spin_lock(&dcache_lock); |
137 | next = next->next; | ||
138 | } | ||
139 | |||
140 | if (this_parent != top) { | ||
141 | next = this_parent->d_u.d_child.next; | ||
142 | this_parent = this_parent->d_parent; | ||
143 | goto resume; | ||
144 | } | 191 | } |
145 | spin_unlock(&dcache_lock); | 192 | spin_unlock(&dcache_lock); |
146 | 193 | ||
147 | return 1; | 194 | /* Timeout of a tree mount is ultimately determined by its top dentry */ |
195 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
196 | return 1; | ||
197 | |||
198 | return 0; | ||
148 | } | 199 | } |
149 | 200 | ||
150 | static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, | 201 | static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, |
@@ -152,58 +203,68 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, | |||
152 | unsigned long timeout, | 203 | unsigned long timeout, |
153 | int do_now) | 204 | int do_now) |
154 | { | 205 | { |
155 | struct dentry *this_parent = parent; | 206 | struct dentry *p; |
156 | struct list_head *next; | ||
157 | 207 | ||
158 | DPRINTK("parent %p %.*s", | 208 | DPRINTK("parent %p %.*s", |
159 | parent, (int)parent->d_name.len, parent->d_name.name); | 209 | parent, (int)parent->d_name.len, parent->d_name.name); |
160 | 210 | ||
161 | spin_lock(&dcache_lock); | 211 | spin_lock(&dcache_lock); |
162 | repeat: | 212 | for (p = parent; p; p = next_dentry(p, parent)) { |
163 | next = this_parent->d_subdirs.next; | ||
164 | resume: | ||
165 | while (next != &this_parent->d_subdirs) { | ||
166 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | ||
167 | |||
168 | /* Negative dentry - give up */ | 213 | /* Negative dentry - give up */ |
169 | if (!simple_positive(dentry)) { | 214 | if (!simple_positive(p)) |
170 | next = next->next; | ||
171 | continue; | 215 | continue; |
172 | } | ||
173 | 216 | ||
174 | DPRINTK("dentry %p %.*s", | 217 | DPRINTK("dentry %p %.*s", |
175 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 218 | p, (int) p->d_name.len, p->d_name.name); |
176 | |||
177 | if (!list_empty(&dentry->d_subdirs)) { | ||
178 | this_parent = dentry; | ||
179 | goto repeat; | ||
180 | } | ||
181 | 219 | ||
182 | dentry = dget(dentry); | 220 | p = dget(p); |
183 | spin_unlock(&dcache_lock); | 221 | spin_unlock(&dcache_lock); |
184 | 222 | ||
185 | if (d_mountpoint(dentry)) { | 223 | if (d_mountpoint(p)) { |
186 | /* Can we expire this guy */ | ||
187 | if (!autofs4_can_expire(dentry, timeout, do_now)) | ||
188 | goto cont; | ||
189 | |||
190 | /* Can we umount this guy */ | 224 | /* Can we umount this guy */ |
191 | if (autofs4_check_mount(mnt, dentry)) | 225 | if (autofs4_mount_busy(mnt, p)) |
192 | return dentry; | 226 | goto cont; |
193 | 227 | ||
228 | /* Can we expire this guy */ | ||
229 | if (autofs4_can_expire(p, timeout, do_now)) | ||
230 | return p; | ||
194 | } | 231 | } |
195 | cont: | 232 | cont: |
196 | dput(dentry); | 233 | dput(p); |
197 | spin_lock(&dcache_lock); | 234 | spin_lock(&dcache_lock); |
198 | next = next->next; | ||
199 | } | 235 | } |
236 | spin_unlock(&dcache_lock); | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | /* Check if we can expire a direct mount (possibly a tree) */ | ||
241 | static struct dentry *autofs4_expire_direct(struct super_block *sb, | ||
242 | struct vfsmount *mnt, | ||
243 | struct autofs_sb_info *sbi, | ||
244 | int how) | ||
245 | { | ||
246 | unsigned long timeout; | ||
247 | struct dentry *root = dget(sb->s_root); | ||
248 | int do_now = how & AUTOFS_EXP_IMMEDIATE; | ||
249 | |||
250 | if (!sbi->exp_timeout || !root) | ||
251 | return NULL; | ||
252 | |||
253 | now = jiffies; | ||
254 | timeout = sbi->exp_timeout; | ||
255 | |||
256 | /* Lock the tree as we must expire as a whole */ | ||
257 | spin_lock(&sbi->fs_lock); | ||
258 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | ||
259 | struct autofs_info *ino = autofs4_dentry_ino(root); | ||
200 | 260 | ||
201 | if (this_parent != parent) { | 261 | /* Set this flag early to catch sys_chdir and the like */ |
202 | next = this_parent->d_u.d_child.next; | 262 | ino->flags |= AUTOFS_INF_EXPIRING; |
203 | this_parent = this_parent->d_parent; | 263 | spin_unlock(&sbi->fs_lock); |
204 | goto resume; | 264 | return root; |
205 | } | 265 | } |
206 | spin_unlock(&dcache_lock); | 266 | spin_unlock(&sbi->fs_lock); |
267 | dput(root); | ||
207 | 268 | ||
208 | return NULL; | 269 | return NULL; |
209 | } | 270 | } |
@@ -214,10 +275,10 @@ cont: | |||
214 | * - it is unused by any user process | 275 | * - it is unused by any user process |
215 | * - it has been unused for exp_timeout time | 276 | * - it has been unused for exp_timeout time |
216 | */ | 277 | */ |
217 | static struct dentry *autofs4_expire(struct super_block *sb, | 278 | static struct dentry *autofs4_expire_indirect(struct super_block *sb, |
218 | struct vfsmount *mnt, | 279 | struct vfsmount *mnt, |
219 | struct autofs_sb_info *sbi, | 280 | struct autofs_sb_info *sbi, |
220 | int how) | 281 | int how) |
221 | { | 282 | { |
222 | unsigned long timeout; | 283 | unsigned long timeout; |
223 | struct dentry *root = sb->s_root; | 284 | struct dentry *root = sb->s_root; |
@@ -241,7 +302,7 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
241 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | 302 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); |
242 | 303 | ||
243 | /* Negative dentry - give up */ | 304 | /* Negative dentry - give up */ |
244 | if ( !simple_positive(dentry) ) { | 305 | if (!simple_positive(dentry)) { |
245 | next = next->next; | 306 | next = next->next; |
246 | continue; | 307 | continue; |
247 | } | 308 | } |
@@ -249,31 +310,36 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
249 | dentry = dget(dentry); | 310 | dentry = dget(dentry); |
250 | spin_unlock(&dcache_lock); | 311 | spin_unlock(&dcache_lock); |
251 | 312 | ||
252 | /* Case 1: indirect mount or top level direct mount */ | 313 | /* |
314 | * Case 1: (i) indirect mount or top level pseudo direct mount | ||
315 | * (autofs-4.1). | ||
316 | * (ii) indirect mount with offset mount, check the "/" | ||
317 | * offset (autofs-5.0+). | ||
318 | */ | ||
253 | if (d_mountpoint(dentry)) { | 319 | if (d_mountpoint(dentry)) { |
254 | DPRINTK("checking mountpoint %p %.*s", | 320 | DPRINTK("checking mountpoint %p %.*s", |
255 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 321 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
256 | 322 | ||
257 | /* Can we expire this guy */ | 323 | /* Can we umount this guy */ |
258 | if (!autofs4_can_expire(dentry, timeout, do_now)) | 324 | if (autofs4_mount_busy(mnt, dentry)) |
259 | goto next; | 325 | goto next; |
260 | 326 | ||
261 | /* Can we umount this guy */ | 327 | /* Can we expire this guy */ |
262 | if (autofs4_check_mount(mnt, dentry)) { | 328 | if (autofs4_can_expire(dentry, timeout, do_now)) { |
263 | expired = dentry; | 329 | expired = dentry; |
264 | break; | 330 | break; |
265 | } | 331 | } |
266 | goto next; | 332 | goto next; |
267 | } | 333 | } |
268 | 334 | ||
269 | if ( simple_empty(dentry) ) | 335 | if (simple_empty(dentry)) |
270 | goto next; | 336 | goto next; |
271 | 337 | ||
272 | /* Case 2: tree mount, expire iff entire tree is not busy */ | 338 | /* Case 2: tree mount, expire iff entire tree is not busy */ |
273 | if (!exp_leaves) { | 339 | if (!exp_leaves) { |
274 | /* Lock the tree as we must expire as a whole */ | 340 | /* Lock the tree as we must expire as a whole */ |
275 | spin_lock(&sbi->fs_lock); | 341 | spin_lock(&sbi->fs_lock); |
276 | if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { | 342 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { |
277 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 343 | struct autofs_info *inf = autofs4_dentry_ino(dentry); |
278 | 344 | ||
279 | /* Set this flag early to catch sys_chdir and the like */ | 345 | /* Set this flag early to catch sys_chdir and the like */ |
@@ -283,7 +349,10 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
283 | break; | 349 | break; |
284 | } | 350 | } |
285 | spin_unlock(&sbi->fs_lock); | 351 | spin_unlock(&sbi->fs_lock); |
286 | /* Case 3: direct mount, expire individual leaves */ | 352 | /* |
353 | * Case 3: pseudo direct mount, expire individual leaves | ||
354 | * (autofs-4.1). | ||
355 | */ | ||
287 | } else { | 356 | } else { |
288 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | 357 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); |
289 | if (expired) { | 358 | if (expired) { |
@@ -297,7 +366,7 @@ next: | |||
297 | next = next->next; | 366 | next = next->next; |
298 | } | 367 | } |
299 | 368 | ||
300 | if ( expired ) { | 369 | if (expired) { |
301 | DPRINTK("returning %p %.*s", | 370 | DPRINTK("returning %p %.*s", |
302 | expired, (int)expired->d_name.len, expired->d_name.name); | 371 | expired, (int)expired->d_name.len, expired->d_name.name); |
303 | spin_lock(&dcache_lock); | 372 | spin_lock(&dcache_lock); |
@@ -325,7 +394,7 @@ int autofs4_expire_run(struct super_block *sb, | |||
325 | pkt.hdr.proto_version = sbi->version; | 394 | pkt.hdr.proto_version = sbi->version; |
326 | pkt.hdr.type = autofs_ptype_expire; | 395 | pkt.hdr.type = autofs_ptype_expire; |
327 | 396 | ||
328 | if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL) | 397 | if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL) |
329 | return -EAGAIN; | 398 | return -EAGAIN; |
330 | 399 | ||
331 | pkt.len = dentry->d_name.len; | 400 | pkt.len = dentry->d_name.len; |
@@ -351,17 +420,22 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
351 | if (arg && get_user(do_now, arg)) | 420 | if (arg && get_user(do_now, arg)) |
352 | return -EFAULT; | 421 | return -EFAULT; |
353 | 422 | ||
354 | if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) { | 423 | if (sbi->type & AUTOFS_TYPE_DIRECT) |
355 | struct autofs_info *de_info = autofs4_dentry_ino(dentry); | 424 | dentry = autofs4_expire_direct(sb, mnt, sbi, do_now); |
425 | else | ||
426 | dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now); | ||
427 | |||
428 | if (dentry) { | ||
429 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
356 | 430 | ||
357 | /* This is synchronous because it makes the daemon a | 431 | /* This is synchronous because it makes the daemon a |
358 | little easier */ | 432 | little easier */ |
359 | de_info->flags |= AUTOFS_INF_EXPIRING; | 433 | ino->flags |= AUTOFS_INF_EXPIRING; |
360 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); | 434 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); |
361 | de_info->flags &= ~AUTOFS_INF_EXPIRING; | 435 | ino->flags &= ~AUTOFS_INF_EXPIRING; |
362 | dput(dentry); | 436 | dput(dentry); |
363 | } | 437 | } |
364 | 438 | ||
365 | return ret; | 439 | return ret; |
366 | } | 440 | } |
367 | 441 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 1ad98d48e550..fde78b110ddd 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * linux/fs/autofs/inode.c | 3 | * linux/fs/autofs/inode.c |
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> | ||
6 | * | 7 | * |
7 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
8 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
@@ -13,6 +14,7 @@ | |||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/file.h> | 16 | #include <linux/file.h> |
17 | #include <linux/seq_file.h> | ||
16 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
17 | #include <linux/parser.h> | 19 | #include <linux/parser.h> |
18 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
@@ -46,6 +48,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
46 | ino->size = 0; | 48 | ino->size = 0; |
47 | 49 | ||
48 | ino->last_used = jiffies; | 50 | ino->last_used = jiffies; |
51 | atomic_set(&ino->count, 0); | ||
49 | 52 | ||
50 | ino->sbi = sbi; | 53 | ino->sbi = sbi; |
51 | 54 | ||
@@ -64,10 +67,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
64 | 67 | ||
65 | void autofs4_free_ino(struct autofs_info *ino) | 68 | void autofs4_free_ino(struct autofs_info *ino) |
66 | { | 69 | { |
70 | struct autofs_info *p_ino; | ||
71 | |||
67 | if (ino->dentry) { | 72 | if (ino->dentry) { |
68 | ino->dentry->d_fsdata = NULL; | 73 | ino->dentry->d_fsdata = NULL; |
69 | if (ino->dentry->d_inode) | 74 | if (ino->dentry->d_inode) { |
75 | struct dentry *parent = ino->dentry->d_parent; | ||
76 | if (atomic_dec_and_test(&ino->count)) { | ||
77 | p_ino = autofs4_dentry_ino(parent); | ||
78 | if (p_ino && parent != ino->dentry) | ||
79 | atomic_dec(&p_ino->count); | ||
80 | } | ||
70 | dput(ino->dentry); | 81 | dput(ino->dentry); |
82 | } | ||
71 | ino->dentry = NULL; | 83 | ino->dentry = NULL; |
72 | } | 84 | } |
73 | if (ino->free) | 85 | if (ino->free) |
@@ -145,20 +157,44 @@ static void autofs4_put_super(struct super_block *sb) | |||
145 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 157 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
146 | 158 | ||
147 | /* Clean up and release dangling references */ | 159 | /* Clean up and release dangling references */ |
148 | if (sbi) | 160 | autofs4_force_release(sbi); |
149 | autofs4_force_release(sbi); | ||
150 | 161 | ||
151 | kfree(sbi); | 162 | kfree(sbi); |
152 | 163 | ||
153 | DPRINTK("shutting down"); | 164 | DPRINTK("shutting down"); |
154 | } | 165 | } |
155 | 166 | ||
167 | static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) | ||
168 | { | ||
169 | struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb); | ||
170 | |||
171 | if (!sbi) | ||
172 | return 0; | ||
173 | |||
174 | seq_printf(m, ",fd=%d", sbi->pipefd); | ||
175 | seq_printf(m, ",pgrp=%d", sbi->oz_pgrp); | ||
176 | seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); | ||
177 | seq_printf(m, ",minproto=%d", sbi->min_proto); | ||
178 | seq_printf(m, ",maxproto=%d", sbi->max_proto); | ||
179 | |||
180 | if (sbi->type & AUTOFS_TYPE_OFFSET) | ||
181 | seq_printf(m, ",offset"); | ||
182 | else if (sbi->type & AUTOFS_TYPE_DIRECT) | ||
183 | seq_printf(m, ",direct"); | ||
184 | else | ||
185 | seq_printf(m, ",indirect"); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
156 | static struct super_operations autofs4_sops = { | 190 | static struct super_operations autofs4_sops = { |
157 | .put_super = autofs4_put_super, | 191 | .put_super = autofs4_put_super, |
158 | .statfs = simple_statfs, | 192 | .statfs = simple_statfs, |
193 | .show_options = autofs4_show_options, | ||
159 | }; | 194 | }; |
160 | 195 | ||
161 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto}; | 196 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, |
197 | Opt_indirect, Opt_direct, Opt_offset}; | ||
162 | 198 | ||
163 | static match_table_t tokens = { | 199 | static match_table_t tokens = { |
164 | {Opt_fd, "fd=%u"}, | 200 | {Opt_fd, "fd=%u"}, |
@@ -167,11 +203,15 @@ static match_table_t tokens = { | |||
167 | {Opt_pgrp, "pgrp=%u"}, | 203 | {Opt_pgrp, "pgrp=%u"}, |
168 | {Opt_minproto, "minproto=%u"}, | 204 | {Opt_minproto, "minproto=%u"}, |
169 | {Opt_maxproto, "maxproto=%u"}, | 205 | {Opt_maxproto, "maxproto=%u"}, |
206 | {Opt_indirect, "indirect"}, | ||
207 | {Opt_direct, "direct"}, | ||
208 | {Opt_offset, "offset"}, | ||
170 | {Opt_err, NULL} | 209 | {Opt_err, NULL} |
171 | }; | 210 | }; |
172 | 211 | ||
173 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | 212 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, |
174 | pid_t *pgrp, int *minproto, int *maxproto) | 213 | pid_t *pgrp, unsigned int *type, |
214 | int *minproto, int *maxproto) | ||
175 | { | 215 | { |
176 | char *p; | 216 | char *p; |
177 | substring_t args[MAX_OPT_ARGS]; | 217 | substring_t args[MAX_OPT_ARGS]; |
@@ -225,6 +265,15 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | |||
225 | return 1; | 265 | return 1; |
226 | *maxproto = option; | 266 | *maxproto = option; |
227 | break; | 267 | break; |
268 | case Opt_indirect: | ||
269 | *type = AUTOFS_TYPE_INDIRECT; | ||
270 | break; | ||
271 | case Opt_direct: | ||
272 | *type = AUTOFS_TYPE_DIRECT; | ||
273 | break; | ||
274 | case Opt_offset: | ||
275 | *type = AUTOFS_TYPE_DIRECT | AUTOFS_TYPE_OFFSET; | ||
276 | break; | ||
228 | default: | 277 | default: |
229 | return 1; | 278 | return 1; |
230 | } | 279 | } |
@@ -243,6 +292,10 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) | |||
243 | return ino; | 292 | return ino; |
244 | } | 293 | } |
245 | 294 | ||
295 | static struct dentry_operations autofs4_sb_dentry_operations = { | ||
296 | .d_release = autofs4_dentry_release, | ||
297 | }; | ||
298 | |||
246 | int autofs4_fill_super(struct super_block *s, void *data, int silent) | 299 | int autofs4_fill_super(struct super_block *s, void *data, int silent) |
247 | { | 300 | { |
248 | struct inode * root_inode; | 301 | struct inode * root_inode; |
@@ -251,7 +304,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
251 | int pipefd; | 304 | int pipefd; |
252 | struct autofs_sb_info *sbi; | 305 | struct autofs_sb_info *sbi; |
253 | struct autofs_info *ino; | 306 | struct autofs_info *ino; |
254 | int minproto, maxproto; | ||
255 | 307 | ||
256 | sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL); | 308 | sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL); |
257 | if ( !sbi ) | 309 | if ( !sbi ) |
@@ -263,12 +315,16 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
263 | s->s_fs_info = sbi; | 315 | s->s_fs_info = sbi; |
264 | sbi->magic = AUTOFS_SBI_MAGIC; | 316 | sbi->magic = AUTOFS_SBI_MAGIC; |
265 | sbi->root = NULL; | 317 | sbi->root = NULL; |
318 | sbi->pipefd = -1; | ||
266 | sbi->catatonic = 0; | 319 | sbi->catatonic = 0; |
267 | sbi->exp_timeout = 0; | 320 | sbi->exp_timeout = 0; |
268 | sbi->oz_pgrp = process_group(current); | 321 | sbi->oz_pgrp = process_group(current); |
269 | sbi->sb = s; | 322 | sbi->sb = s; |
270 | sbi->version = 0; | 323 | sbi->version = 0; |
271 | sbi->sub_version = 0; | 324 | sbi->sub_version = 0; |
325 | sbi->type = 0; | ||
326 | sbi->min_proto = 0; | ||
327 | sbi->max_proto = 0; | ||
272 | mutex_init(&sbi->wq_mutex); | 328 | mutex_init(&sbi->wq_mutex); |
273 | spin_lock_init(&sbi->fs_lock); | 329 | spin_lock_init(&sbi->fs_lock); |
274 | sbi->queues = NULL; | 330 | sbi->queues = NULL; |
@@ -285,38 +341,46 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
285 | if (!ino) | 341 | if (!ino) |
286 | goto fail_free; | 342 | goto fail_free; |
287 | root_inode = autofs4_get_inode(s, ino); | 343 | root_inode = autofs4_get_inode(s, ino); |
288 | kfree(ino); | ||
289 | if (!root_inode) | 344 | if (!root_inode) |
290 | goto fail_free; | 345 | goto fail_ino; |
291 | 346 | ||
292 | root_inode->i_op = &autofs4_root_inode_operations; | ||
293 | root_inode->i_fop = &autofs4_root_operations; | ||
294 | root = d_alloc_root(root_inode); | 347 | root = d_alloc_root(root_inode); |
295 | pipe = NULL; | ||
296 | |||
297 | if (!root) | 348 | if (!root) |
298 | goto fail_iput; | 349 | goto fail_iput; |
350 | pipe = NULL; | ||
351 | |||
352 | root->d_op = &autofs4_sb_dentry_operations; | ||
353 | root->d_fsdata = ino; | ||
299 | 354 | ||
300 | /* Can this call block? */ | 355 | /* Can this call block? */ |
301 | if (parse_options(data, &pipefd, | 356 | if (parse_options(data, &pipefd, |
302 | &root_inode->i_uid, &root_inode->i_gid, | 357 | &root_inode->i_uid, &root_inode->i_gid, |
303 | &sbi->oz_pgrp, | 358 | &sbi->oz_pgrp, &sbi->type, |
304 | &minproto, &maxproto)) { | 359 | &sbi->min_proto, &sbi->max_proto)) { |
305 | printk("autofs: called with bogus options\n"); | 360 | printk("autofs: called with bogus options\n"); |
306 | goto fail_dput; | 361 | goto fail_dput; |
307 | } | 362 | } |
308 | 363 | ||
364 | root_inode->i_fop = &autofs4_root_operations; | ||
365 | root_inode->i_op = sbi->type & AUTOFS_TYPE_DIRECT ? | ||
366 | &autofs4_direct_root_inode_operations : | ||
367 | &autofs4_indirect_root_inode_operations; | ||
368 | |||
309 | /* Couldn't this be tested earlier? */ | 369 | /* Couldn't this be tested earlier? */ |
310 | if (maxproto < AUTOFS_MIN_PROTO_VERSION || | 370 | if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION || |
311 | minproto > AUTOFS_MAX_PROTO_VERSION) { | 371 | sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) { |
312 | printk("autofs: kernel does not match daemon version " | 372 | printk("autofs: kernel does not match daemon version " |
313 | "daemon (%d, %d) kernel (%d, %d)\n", | 373 | "daemon (%d, %d) kernel (%d, %d)\n", |
314 | minproto, maxproto, | 374 | sbi->min_proto, sbi->max_proto, |
315 | AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION); | 375 | AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION); |
316 | goto fail_dput; | 376 | goto fail_dput; |
317 | } | 377 | } |
318 | 378 | ||
319 | sbi->version = maxproto > AUTOFS_MAX_PROTO_VERSION ? AUTOFS_MAX_PROTO_VERSION : maxproto; | 379 | /* Establish highest kernel protocol version */ |
380 | if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION) | ||
381 | sbi->version = AUTOFS_MAX_PROTO_VERSION; | ||
382 | else | ||
383 | sbi->version = sbi->max_proto; | ||
320 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; | 384 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; |
321 | 385 | ||
322 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); | 386 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); |
@@ -329,6 +393,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
329 | if ( !pipe->f_op || !pipe->f_op->write ) | 393 | if ( !pipe->f_op || !pipe->f_op->write ) |
330 | goto fail_fput; | 394 | goto fail_fput; |
331 | sbi->pipe = pipe; | 395 | sbi->pipe = pipe; |
396 | sbi->pipefd = pipefd; | ||
332 | 397 | ||
333 | /* | 398 | /* |
334 | * Take a reference to the root dentry so we get a chance to | 399 | * Take a reference to the root dentry so we get a chance to |
@@ -356,6 +421,8 @@ fail_dput: | |||
356 | fail_iput: | 421 | fail_iput: |
357 | printk("autofs: get root dentry failed\n"); | 422 | printk("autofs: get root dentry failed\n"); |
358 | iput(root_inode); | 423 | iput(root_inode); |
424 | fail_ino: | ||
425 | kfree(ino); | ||
359 | fail_free: | 426 | fail_free: |
360 | kfree(sbi); | 427 | kfree(sbi); |
361 | fail_unlock: | 428 | fail_unlock: |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 62d8d4acb8bb..84e030c8ddd0 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> | 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
7 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 7 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
8 | * | 8 | * |
9 | * This file is part of the Linux kernel and is made available under | 9 | * This file is part of the Linux kernel and is made available under |
10 | * the terms of the GNU General Public License, version 2, or at your | 10 | * the terms of the GNU General Public License, version 2, or at your |
@@ -30,9 +30,9 @@ static int autofs4_dir_close(struct inode *inode, struct file *file); | |||
30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); | 30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); |
31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); | 31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); |
32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
33 | static int autofs4_dcache_readdir(struct file *, void *, filldir_t); | 33 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); |
34 | 34 | ||
35 | struct file_operations autofs4_root_operations = { | 35 | const struct file_operations autofs4_root_operations = { |
36 | .open = dcache_dir_open, | 36 | .open = dcache_dir_open, |
37 | .release = dcache_dir_close, | 37 | .release = dcache_dir_close, |
38 | .read = generic_read_dir, | 38 | .read = generic_read_dir, |
@@ -40,14 +40,14 @@ struct file_operations autofs4_root_operations = { | |||
40 | .ioctl = autofs4_root_ioctl, | 40 | .ioctl = autofs4_root_ioctl, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct file_operations autofs4_dir_operations = { | 43 | const struct file_operations autofs4_dir_operations = { |
44 | .open = autofs4_dir_open, | 44 | .open = autofs4_dir_open, |
45 | .release = autofs4_dir_close, | 45 | .release = autofs4_dir_close, |
46 | .read = generic_read_dir, | 46 | .read = generic_read_dir, |
47 | .readdir = autofs4_dir_readdir, | 47 | .readdir = autofs4_dir_readdir, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct inode_operations autofs4_root_inode_operations = { | 50 | struct inode_operations autofs4_indirect_root_inode_operations = { |
51 | .lookup = autofs4_lookup, | 51 | .lookup = autofs4_lookup, |
52 | .unlink = autofs4_dir_unlink, | 52 | .unlink = autofs4_dir_unlink, |
53 | .symlink = autofs4_dir_symlink, | 53 | .symlink = autofs4_dir_symlink, |
@@ -55,6 +55,14 @@ struct inode_operations autofs4_root_inode_operations = { | |||
55 | .rmdir = autofs4_dir_rmdir, | 55 | .rmdir = autofs4_dir_rmdir, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | struct inode_operations autofs4_direct_root_inode_operations = { | ||
59 | .lookup = autofs4_lookup, | ||
60 | .unlink = autofs4_dir_unlink, | ||
61 | .mkdir = autofs4_dir_mkdir, | ||
62 | .rmdir = autofs4_dir_rmdir, | ||
63 | .follow_link = autofs4_follow_link, | ||
64 | }; | ||
65 | |||
58 | struct inode_operations autofs4_dir_inode_operations = { | 66 | struct inode_operations autofs4_dir_inode_operations = { |
59 | .lookup = autofs4_lookup, | 67 | .lookup = autofs4_lookup, |
60 | .unlink = autofs4_dir_unlink, | 68 | .unlink = autofs4_dir_unlink, |
@@ -82,87 +90,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent, | |||
82 | 90 | ||
83 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); | 91 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); |
84 | 92 | ||
85 | return autofs4_dcache_readdir(file, dirent, filldir); | 93 | return dcache_readdir(file, dirent, filldir); |
86 | } | ||
87 | |||
88 | /* Update usage from here to top of tree, so that scan of | ||
89 | top-level directories will give a useful result */ | ||
90 | static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry) | ||
91 | { | ||
92 | struct dentry *top = dentry->d_sb->s_root; | ||
93 | |||
94 | spin_lock(&dcache_lock); | ||
95 | for(; dentry != top; dentry = dentry->d_parent) { | ||
96 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
97 | |||
98 | if (ino) { | ||
99 | touch_atime(mnt, dentry); | ||
100 | ino->last_used = jiffies; | ||
101 | } | ||
102 | } | ||
103 | spin_unlock(&dcache_lock); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * From 2.4 kernel readdir.c | ||
108 | */ | ||
109 | static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
110 | { | ||
111 | int i; | ||
112 | struct dentry *dentry = filp->f_dentry; | ||
113 | |||
114 | i = filp->f_pos; | ||
115 | switch (i) { | ||
116 | case 0: | ||
117 | if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0) | ||
118 | break; | ||
119 | i++; | ||
120 | filp->f_pos++; | ||
121 | /* fallthrough */ | ||
122 | case 1: | ||
123 | if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) | ||
124 | break; | ||
125 | i++; | ||
126 | filp->f_pos++; | ||
127 | /* fallthrough */ | ||
128 | default: { | ||
129 | struct list_head *list; | ||
130 | int j = i-2; | ||
131 | |||
132 | spin_lock(&dcache_lock); | ||
133 | list = dentry->d_subdirs.next; | ||
134 | |||
135 | for (;;) { | ||
136 | if (list == &dentry->d_subdirs) { | ||
137 | spin_unlock(&dcache_lock); | ||
138 | return 0; | ||
139 | } | ||
140 | if (!j) | ||
141 | break; | ||
142 | j--; | ||
143 | list = list->next; | ||
144 | } | ||
145 | |||
146 | while(1) { | ||
147 | struct dentry *de = list_entry(list, | ||
148 | struct dentry, d_u.d_child); | ||
149 | |||
150 | if (!d_unhashed(de) && de->d_inode) { | ||
151 | spin_unlock(&dcache_lock); | ||
152 | if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0) | ||
153 | break; | ||
154 | spin_lock(&dcache_lock); | ||
155 | } | ||
156 | filp->f_pos++; | ||
157 | list = list->next; | ||
158 | if (list != &dentry->d_subdirs) | ||
159 | continue; | ||
160 | spin_unlock(&dcache_lock); | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | return 0; | ||
166 | } | 94 | } |
167 | 95 | ||
168 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 96 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
@@ -170,8 +98,16 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
170 | struct dentry *dentry = file->f_dentry; | 98 | struct dentry *dentry = file->f_dentry; |
171 | struct vfsmount *mnt = file->f_vfsmnt; | 99 | struct vfsmount *mnt = file->f_vfsmnt; |
172 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 100 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
101 | struct dentry *cursor; | ||
173 | int status; | 102 | int status; |
174 | 103 | ||
104 | status = dcache_dir_open(inode, file); | ||
105 | if (status) | ||
106 | goto out; | ||
107 | |||
108 | cursor = file->private_data; | ||
109 | cursor->d_fsdata = NULL; | ||
110 | |||
175 | DPRINTK("file=%p dentry=%p %.*s", | 111 | DPRINTK("file=%p dentry=%p %.*s", |
176 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 112 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
177 | 113 | ||
@@ -180,12 +116,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
180 | 116 | ||
181 | if (autofs4_ispending(dentry)) { | 117 | if (autofs4_ispending(dentry)) { |
182 | DPRINTK("dentry busy"); | 118 | DPRINTK("dentry busy"); |
183 | return -EBUSY; | 119 | dcache_dir_close(inode, file); |
120 | status = -EBUSY; | ||
121 | goto out; | ||
184 | } | 122 | } |
185 | 123 | ||
124 | status = -ENOENT; | ||
186 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { | 125 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { |
187 | struct nameidata nd; | 126 | struct nameidata nd; |
188 | int empty; | 127 | int empty, ret; |
189 | 128 | ||
190 | /* In case there are stale directory dentrys from a failed mount */ | 129 | /* In case there are stale directory dentrys from a failed mount */ |
191 | spin_lock(&dcache_lock); | 130 | spin_lock(&dcache_lock); |
@@ -195,13 +134,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
195 | if (!empty) | 134 | if (!empty) |
196 | d_invalidate(dentry); | 135 | d_invalidate(dentry); |
197 | 136 | ||
198 | nd.dentry = dentry; | ||
199 | nd.mnt = mnt; | ||
200 | nd.flags = LOOKUP_DIRECTORY; | 137 | nd.flags = LOOKUP_DIRECTORY; |
201 | status = (dentry->d_op->d_revalidate)(dentry, &nd); | 138 | ret = (dentry->d_op->d_revalidate)(dentry, &nd); |
202 | 139 | ||
203 | if (!status) | 140 | if (!ret) { |
204 | return -ENOENT; | 141 | dcache_dir_close(inode, file); |
142 | goto out; | ||
143 | } | ||
205 | } | 144 | } |
206 | 145 | ||
207 | if (d_mountpoint(dentry)) { | 146 | if (d_mountpoint(dentry)) { |
@@ -212,25 +151,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
212 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { | 151 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { |
213 | dput(fp_dentry); | 152 | dput(fp_dentry); |
214 | mntput(fp_mnt); | 153 | mntput(fp_mnt); |
215 | return -ENOENT; | 154 | dcache_dir_close(inode, file); |
155 | goto out; | ||
216 | } | 156 | } |
217 | 157 | ||
218 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); | 158 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); |
219 | status = PTR_ERR(fp); | 159 | status = PTR_ERR(fp); |
220 | if (IS_ERR(fp)) { | 160 | if (IS_ERR(fp)) { |
221 | file->private_data = NULL; | 161 | dcache_dir_close(inode, file); |
222 | return status; | 162 | goto out; |
223 | } | 163 | } |
224 | file->private_data = fp; | 164 | cursor->d_fsdata = fp; |
225 | } | 165 | } |
226 | out: | ||
227 | return 0; | 166 | return 0; |
167 | out: | ||
168 | return status; | ||
228 | } | 169 | } |
229 | 170 | ||
230 | static int autofs4_dir_close(struct inode *inode, struct file *file) | 171 | static int autofs4_dir_close(struct inode *inode, struct file *file) |
231 | { | 172 | { |
232 | struct dentry *dentry = file->f_dentry; | 173 | struct dentry *dentry = file->f_dentry; |
233 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 174 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
175 | struct dentry *cursor = file->private_data; | ||
176 | int status = 0; | ||
234 | 177 | ||
235 | DPRINTK("file=%p dentry=%p %.*s", | 178 | DPRINTK("file=%p dentry=%p %.*s", |
236 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 179 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
@@ -240,26 +183,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file) | |||
240 | 183 | ||
241 | if (autofs4_ispending(dentry)) { | 184 | if (autofs4_ispending(dentry)) { |
242 | DPRINTK("dentry busy"); | 185 | DPRINTK("dentry busy"); |
243 | return -EBUSY; | 186 | status = -EBUSY; |
187 | goto out; | ||
244 | } | 188 | } |
245 | 189 | ||
246 | if (d_mountpoint(dentry)) { | 190 | if (d_mountpoint(dentry)) { |
247 | struct file *fp = file->private_data; | 191 | struct file *fp = cursor->d_fsdata; |
248 | 192 | if (!fp) { | |
249 | if (!fp) | 193 | status = -ENOENT; |
250 | return -ENOENT; | 194 | goto out; |
251 | 195 | } | |
252 | filp_close(fp, current->files); | 196 | filp_close(fp, current->files); |
253 | file->private_data = NULL; | ||
254 | } | 197 | } |
255 | out: | 198 | out: |
256 | return 0; | 199 | dcache_dir_close(inode, file); |
200 | return status; | ||
257 | } | 201 | } |
258 | 202 | ||
259 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) | 203 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) |
260 | { | 204 | { |
261 | struct dentry *dentry = file->f_dentry; | 205 | struct dentry *dentry = file->f_dentry; |
262 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 206 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
207 | struct dentry *cursor = file->private_data; | ||
263 | int status; | 208 | int status; |
264 | 209 | ||
265 | DPRINTK("file=%p dentry=%p %.*s", | 210 | DPRINTK("file=%p dentry=%p %.*s", |
@@ -274,7 +219,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
274 | } | 219 | } |
275 | 220 | ||
276 | if (d_mountpoint(dentry)) { | 221 | if (d_mountpoint(dentry)) { |
277 | struct file *fp = file->private_data; | 222 | struct file *fp = cursor->d_fsdata; |
278 | 223 | ||
279 | if (!fp) | 224 | if (!fp) |
280 | return -ENOENT; | 225 | return -ENOENT; |
@@ -289,27 +234,26 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
289 | return status; | 234 | return status; |
290 | } | 235 | } |
291 | out: | 236 | out: |
292 | return autofs4_dcache_readdir(file, dirent, filldir); | 237 | return dcache_readdir(file, dirent, filldir); |
293 | } | 238 | } |
294 | 239 | ||
295 | static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags) | 240 | static int try_to_fill_dentry(struct dentry *dentry, int flags) |
296 | { | 241 | { |
297 | struct super_block *sb = mnt->mnt_sb; | 242 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
298 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 243 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
299 | struct autofs_info *de_info = autofs4_dentry_ino(dentry); | ||
300 | int status = 0; | 244 | int status = 0; |
301 | 245 | ||
302 | /* Block on any pending expiry here; invalidate the dentry | 246 | /* Block on any pending expiry here; invalidate the dentry |
303 | when expiration is done to trigger mount request with a new | 247 | when expiration is done to trigger mount request with a new |
304 | dentry */ | 248 | dentry */ |
305 | if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) { | 249 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { |
306 | DPRINTK("waiting for expire %p name=%.*s", | 250 | DPRINTK("waiting for expire %p name=%.*s", |
307 | dentry, dentry->d_name.len, dentry->d_name.name); | 251 | dentry, dentry->d_name.len, dentry->d_name.name); |
308 | 252 | ||
309 | status = autofs4_wait(sbi, dentry, NFY_NONE); | 253 | status = autofs4_wait(sbi, dentry, NFY_NONE); |
310 | 254 | ||
311 | DPRINTK("expire done status=%d", status); | 255 | DPRINTK("expire done status=%d", status); |
312 | 256 | ||
313 | /* | 257 | /* |
314 | * If the directory still exists the mount request must | 258 | * If the directory still exists the mount request must |
315 | * continue otherwise it can't be followed at the right | 259 | * continue otherwise it can't be followed at the right |
@@ -317,34 +261,36 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
317 | */ | 261 | */ |
318 | status = d_invalidate(dentry); | 262 | status = d_invalidate(dentry); |
319 | if (status != -EBUSY) | 263 | if (status != -EBUSY) |
320 | return 0; | 264 | return -ENOENT; |
321 | } | 265 | } |
322 | 266 | ||
323 | DPRINTK("dentry=%p %.*s ino=%p", | 267 | DPRINTK("dentry=%p %.*s ino=%p", |
324 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 268 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
325 | 269 | ||
326 | /* Wait for a pending mount, triggering one if there isn't one already */ | 270 | /* |
271 | * Wait for a pending mount, triggering one if there | ||
272 | * isn't one already | ||
273 | */ | ||
327 | if (dentry->d_inode == NULL) { | 274 | if (dentry->d_inode == NULL) { |
328 | DPRINTK("waiting for mount name=%.*s", | 275 | DPRINTK("waiting for mount name=%.*s", |
329 | dentry->d_name.len, dentry->d_name.name); | 276 | dentry->d_name.len, dentry->d_name.name); |
330 | 277 | ||
331 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | 278 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); |
332 | 279 | ||
333 | DPRINTK("mount done status=%d", status); | 280 | DPRINTK("mount done status=%d", status); |
334 | 281 | ||
335 | if (status && dentry->d_inode) | 282 | if (status && dentry->d_inode) |
336 | return 0; /* Try to get the kernel to invalidate this dentry */ | 283 | return status; /* Try to get the kernel to invalidate this dentry */ |
337 | 284 | ||
338 | /* Turn this into a real negative dentry? */ | 285 | /* Turn this into a real negative dentry? */ |
339 | if (status == -ENOENT) { | 286 | if (status == -ENOENT) { |
340 | dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT; | ||
341 | spin_lock(&dentry->d_lock); | 287 | spin_lock(&dentry->d_lock); |
342 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 288 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
343 | spin_unlock(&dentry->d_lock); | 289 | spin_unlock(&dentry->d_lock); |
344 | return 1; | 290 | return status; |
345 | } else if (status) { | 291 | } else if (status) { |
346 | /* Return a negative dentry, but leave it "pending" */ | 292 | /* Return a negative dentry, but leave it "pending" */ |
347 | return 1; | 293 | return status; |
348 | } | 294 | } |
349 | /* Trigger mount for path component or follow link */ | 295 | /* Trigger mount for path component or follow link */ |
350 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || | 296 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || |
@@ -363,19 +309,87 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
363 | spin_lock(&dentry->d_lock); | 309 | spin_lock(&dentry->d_lock); |
364 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 310 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
365 | spin_unlock(&dentry->d_lock); | 311 | spin_unlock(&dentry->d_lock); |
366 | return 0; | 312 | return status; |
367 | } | 313 | } |
368 | } | 314 | } |
369 | 315 | ||
370 | /* We don't update the usages for the autofs daemon itself, this | 316 | /* Initialize expiry counter after successful mount */ |
371 | is necessary for recursive autofs mounts */ | 317 | if (ino) |
372 | if (!autofs4_oz_mode(sbi)) | 318 | ino->last_used = jiffies; |
373 | autofs4_update_usage(mnt, dentry); | ||
374 | 319 | ||
375 | spin_lock(&dentry->d_lock); | 320 | spin_lock(&dentry->d_lock); |
376 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 321 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
377 | spin_unlock(&dentry->d_lock); | 322 | spin_unlock(&dentry->d_lock); |
378 | return 1; | 323 | return status; |
324 | } | ||
325 | |||
326 | /* For autofs direct mounts the follow link triggers the mount */ | ||
327 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
328 | { | ||
329 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
330 | int oz_mode = autofs4_oz_mode(sbi); | ||
331 | unsigned int lookup_type; | ||
332 | int status; | ||
333 | |||
334 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", | ||
335 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, | ||
336 | nd->flags); | ||
337 | |||
338 | /* If it's our master or we shouldn't trigger a mount we're done */ | ||
339 | lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY); | ||
340 | if (oz_mode || !lookup_type) | ||
341 | goto done; | ||
342 | |||
343 | /* | ||
344 | * If a request is pending wait for it. | ||
345 | * If it's a mount then it won't be expired till at least | ||
346 | * a liitle later and if it's an expire then we might need | ||
347 | * to mount it again. | ||
348 | */ | ||
349 | if (autofs4_ispending(dentry)) { | ||
350 | DPRINTK("waiting for active request %p name=%.*s", | ||
351 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
352 | |||
353 | status = autofs4_wait(sbi, dentry, NFY_NONE); | ||
354 | |||
355 | DPRINTK("request done status=%d", status); | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * If the dentry contains directories then it is an | ||
360 | * autofs multi-mount with no root mount offset. So | ||
361 | * don't try to mount it again. | ||
362 | */ | ||
363 | spin_lock(&dcache_lock); | ||
364 | if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { | ||
365 | spin_unlock(&dcache_lock); | ||
366 | |||
367 | status = try_to_fill_dentry(dentry, 0); | ||
368 | if (status) | ||
369 | goto out_error; | ||
370 | |||
371 | /* | ||
372 | * The mount succeeded but if there is no root mount | ||
373 | * it must be an autofs multi-mount with no root offset | ||
374 | * so we don't need to follow the mount. | ||
375 | */ | ||
376 | if (d_mountpoint(dentry)) { | ||
377 | if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) { | ||
378 | status = -ENOENT; | ||
379 | goto out_error; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | goto done; | ||
384 | } | ||
385 | spin_unlock(&dcache_lock); | ||
386 | |||
387 | done: | ||
388 | return NULL; | ||
389 | |||
390 | out_error: | ||
391 | path_release(nd); | ||
392 | return ERR_PTR(status); | ||
379 | } | 393 | } |
380 | 394 | ||
381 | /* | 395 | /* |
@@ -384,47 +398,43 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
384 | * yet completely filled in, and revalidate has to delay such | 398 | * yet completely filled in, and revalidate has to delay such |
385 | * lookups.. | 399 | * lookups.. |
386 | */ | 400 | */ |
387 | static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd) | 401 | static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) |
388 | { | 402 | { |
389 | struct inode * dir = dentry->d_parent->d_inode; | 403 | struct inode *dir = dentry->d_parent->d_inode; |
390 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 404 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
391 | int oz_mode = autofs4_oz_mode(sbi); | 405 | int oz_mode = autofs4_oz_mode(sbi); |
392 | int flags = nd ? nd->flags : 0; | 406 | int flags = nd ? nd->flags : 0; |
393 | int status = 1; | 407 | int status = 0; |
394 | 408 | ||
395 | /* Pending dentry */ | 409 | /* Pending dentry */ |
396 | if (autofs4_ispending(dentry)) { | 410 | if (autofs4_ispending(dentry)) { |
397 | if (!oz_mode) | 411 | if (!oz_mode) |
398 | status = try_to_fill_dentry(nd->mnt, dentry, flags); | 412 | status = try_to_fill_dentry(dentry, flags); |
399 | return status; | 413 | return !status; |
400 | } | 414 | } |
401 | 415 | ||
402 | /* Negative dentry.. invalidate if "old" */ | 416 | /* Negative dentry.. invalidate if "old" */ |
403 | if (dentry->d_inode == NULL) | 417 | if (dentry->d_inode == NULL) |
404 | return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT); | 418 | return 0; |
405 | 419 | ||
406 | /* Check for a non-mountpoint directory with no contents */ | 420 | /* Check for a non-mountpoint directory with no contents */ |
407 | spin_lock(&dcache_lock); | 421 | spin_lock(&dcache_lock); |
408 | if (S_ISDIR(dentry->d_inode->i_mode) && | 422 | if (S_ISDIR(dentry->d_inode->i_mode) && |
409 | !d_mountpoint(dentry) && | 423 | !d_mountpoint(dentry) && |
410 | list_empty(&dentry->d_subdirs)) { | 424 | __simple_empty(dentry)) { |
411 | DPRINTK("dentry=%p %.*s, emptydir", | 425 | DPRINTK("dentry=%p %.*s, emptydir", |
412 | dentry, dentry->d_name.len, dentry->d_name.name); | 426 | dentry, dentry->d_name.len, dentry->d_name.name); |
413 | spin_unlock(&dcache_lock); | 427 | spin_unlock(&dcache_lock); |
414 | if (!oz_mode) | 428 | if (!oz_mode) |
415 | status = try_to_fill_dentry(nd->mnt, dentry, flags); | 429 | status = try_to_fill_dentry(dentry, flags); |
416 | return status; | 430 | return !status; |
417 | } | 431 | } |
418 | spin_unlock(&dcache_lock); | 432 | spin_unlock(&dcache_lock); |
419 | 433 | ||
420 | /* Update the usage list */ | ||
421 | if (!oz_mode) | ||
422 | autofs4_update_usage(nd->mnt, dentry); | ||
423 | |||
424 | return 1; | 434 | return 1; |
425 | } | 435 | } |
426 | 436 | ||
427 | static void autofs4_dentry_release(struct dentry *de) | 437 | void autofs4_dentry_release(struct dentry *de) |
428 | { | 438 | { |
429 | struct autofs_info *inf; | 439 | struct autofs_info *inf; |
430 | 440 | ||
@@ -462,12 +472,13 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
462 | DPRINTK("name = %.*s", | 472 | DPRINTK("name = %.*s", |
463 | dentry->d_name.len, dentry->d_name.name); | 473 | dentry->d_name.len, dentry->d_name.name); |
464 | 474 | ||
475 | /* File name too long to exist */ | ||
465 | if (dentry->d_name.len > NAME_MAX) | 476 | if (dentry->d_name.len > NAME_MAX) |
466 | return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */ | 477 | return ERR_PTR(-ENAMETOOLONG); |
467 | 478 | ||
468 | sbi = autofs4_sbi(dir->i_sb); | 479 | sbi = autofs4_sbi(dir->i_sb); |
469 | |||
470 | oz_mode = autofs4_oz_mode(sbi); | 480 | oz_mode = autofs4_oz_mode(sbi); |
481 | |||
471 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 482 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
472 | current->pid, process_group(current), sbi->catatonic, oz_mode); | 483 | current->pid, process_group(current), sbi->catatonic, oz_mode); |
473 | 484 | ||
@@ -519,7 +530,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
519 | * doesn't do the right thing for all system calls, but it should | 530 | * doesn't do the right thing for all system calls, but it should |
520 | * be OK for the operations we permit from an autofs. | 531 | * be OK for the operations we permit from an autofs. |
521 | */ | 532 | */ |
522 | if ( dentry->d_inode && d_unhashed(dentry) ) | 533 | if (dentry->d_inode && d_unhashed(dentry)) |
523 | return ERR_PTR(-ENOENT); | 534 | return ERR_PTR(-ENOENT); |
524 | 535 | ||
525 | return NULL; | 536 | return NULL; |
@@ -531,6 +542,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
531 | { | 542 | { |
532 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 543 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
533 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 544 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
545 | struct autofs_info *p_ino; | ||
534 | struct inode *inode; | 546 | struct inode *inode; |
535 | char *cp; | 547 | char *cp; |
536 | 548 | ||
@@ -564,6 +576,10 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
564 | 576 | ||
565 | dentry->d_fsdata = ino; | 577 | dentry->d_fsdata = ino; |
566 | ino->dentry = dget(dentry); | 578 | ino->dentry = dget(dentry); |
579 | atomic_inc(&ino->count); | ||
580 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
581 | if (p_ino && dentry->d_parent != dentry) | ||
582 | atomic_inc(&p_ino->count); | ||
567 | ino->inode = inode; | 583 | ino->inode = inode; |
568 | 584 | ||
569 | dir->i_mtime = CURRENT_TIME; | 585 | dir->i_mtime = CURRENT_TIME; |
@@ -590,11 +606,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
590 | { | 606 | { |
591 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 607 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
592 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 608 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
609 | struct autofs_info *p_ino; | ||
593 | 610 | ||
594 | /* This allows root to remove symlinks */ | 611 | /* This allows root to remove symlinks */ |
595 | if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) | 612 | if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) |
596 | return -EACCES; | 613 | return -EACCES; |
597 | 614 | ||
615 | if (atomic_dec_and_test(&ino->count)) { | ||
616 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
617 | if (p_ino && dentry->d_parent != dentry) | ||
618 | atomic_dec(&p_ino->count); | ||
619 | } | ||
598 | dput(ino->dentry); | 620 | dput(ino->dentry); |
599 | 621 | ||
600 | dentry->d_inode->i_size = 0; | 622 | dentry->d_inode->i_size = 0; |
@@ -611,6 +633,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
611 | { | 633 | { |
612 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 634 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
613 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 635 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
636 | struct autofs_info *p_ino; | ||
614 | 637 | ||
615 | if (!autofs4_oz_mode(sbi)) | 638 | if (!autofs4_oz_mode(sbi)) |
616 | return -EACCES; | 639 | return -EACCES; |
@@ -625,8 +648,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
625 | spin_unlock(&dentry->d_lock); | 648 | spin_unlock(&dentry->d_lock); |
626 | spin_unlock(&dcache_lock); | 649 | spin_unlock(&dcache_lock); |
627 | 650 | ||
651 | if (atomic_dec_and_test(&ino->count)) { | ||
652 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
653 | if (p_ino && dentry->d_parent != dentry) | ||
654 | atomic_dec(&p_ino->count); | ||
655 | } | ||
628 | dput(ino->dentry); | 656 | dput(ino->dentry); |
629 | |||
630 | dentry->d_inode->i_size = 0; | 657 | dentry->d_inode->i_size = 0; |
631 | dentry->d_inode->i_nlink = 0; | 658 | dentry->d_inode->i_nlink = 0; |
632 | 659 | ||
@@ -640,6 +667,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
640 | { | 667 | { |
641 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 668 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
642 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 669 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
670 | struct autofs_info *p_ino; | ||
643 | struct inode *inode; | 671 | struct inode *inode; |
644 | 672 | ||
645 | if ( !autofs4_oz_mode(sbi) ) | 673 | if ( !autofs4_oz_mode(sbi) ) |
@@ -662,6 +690,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
662 | 690 | ||
663 | dentry->d_fsdata = ino; | 691 | dentry->d_fsdata = ino; |
664 | ino->dentry = dget(dentry); | 692 | ino->dentry = dget(dentry); |
693 | atomic_inc(&ino->count); | ||
694 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
695 | if (p_ino && dentry->d_parent != dentry) | ||
696 | atomic_inc(&p_ino->count); | ||
665 | ino->inode = inode; | 697 | ino->inode = inode; |
666 | dir->i_nlink++; | 698 | dir->i_nlink++; |
667 | dir->i_mtime = CURRENT_TIME; | 699 | dir->i_mtime = CURRENT_TIME; |
@@ -745,7 +777,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p) | |||
745 | { | 777 | { |
746 | int status = 0; | 778 | int status = 0; |
747 | 779 | ||
748 | if (may_umount(mnt) == 0) | 780 | if (may_umount(mnt)) |
749 | status = 1; | 781 | status = 1; |
750 | 782 | ||
751 | DPRINTK("returning %d", status); | 783 | DPRINTK("returning %d", status); |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index be78e9378c03..142ab6aa2aa1 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * linux/fs/autofs/waitq.c | 3 | * linux/fs/autofs/waitq.c |
4 | * | 4 | * |
5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
6 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 6 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
7 | * | 7 | * |
8 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
9 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
@@ -33,7 +33,7 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
33 | sbi->catatonic = 1; | 33 | sbi->catatonic = 1; |
34 | wq = sbi->queues; | 34 | wq = sbi->queues; |
35 | sbi->queues = NULL; /* Erase all wait queues */ | 35 | sbi->queues = NULL; /* Erase all wait queues */ |
36 | while ( wq ) { | 36 | while (wq) { |
37 | nwq = wq->next; | 37 | nwq = wq->next; |
38 | wq->status = -ENOENT; /* Magic is gone - report failure */ | 38 | wq->status = -ENOENT; /* Magic is gone - report failure */ |
39 | kfree(wq->name); | 39 | kfree(wq->name); |
@@ -45,7 +45,6 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
45 | fput(sbi->pipe); /* Close the pipe */ | 45 | fput(sbi->pipe); /* Close the pipe */ |
46 | sbi->pipe = NULL; | 46 | sbi->pipe = NULL; |
47 | } | 47 | } |
48 | |||
49 | shrink_dcache_sb(sbi->sb); | 48 | shrink_dcache_sb(sbi->sb); |
50 | } | 49 | } |
51 | 50 | ||
@@ -98,7 +97,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
98 | 97 | ||
99 | pkt.hdr.proto_version = sbi->version; | 98 | pkt.hdr.proto_version = sbi->version; |
100 | pkt.hdr.type = type; | 99 | pkt.hdr.type = type; |
101 | if (type == autofs_ptype_missing) { | 100 | switch (type) { |
101 | /* Kernel protocol v4 missing and expire packets */ | ||
102 | case autofs_ptype_missing: | ||
103 | { | ||
102 | struct autofs_packet_missing *mp = &pkt.missing; | 104 | struct autofs_packet_missing *mp = &pkt.missing; |
103 | 105 | ||
104 | pktsz = sizeof(*mp); | 106 | pktsz = sizeof(*mp); |
@@ -107,7 +109,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
107 | mp->len = wq->len; | 109 | mp->len = wq->len; |
108 | memcpy(mp->name, wq->name, wq->len); | 110 | memcpy(mp->name, wq->name, wq->len); |
109 | mp->name[wq->len] = '\0'; | 111 | mp->name[wq->len] = '\0'; |
110 | } else if (type == autofs_ptype_expire_multi) { | 112 | break; |
113 | } | ||
114 | case autofs_ptype_expire_multi: | ||
115 | { | ||
111 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; | 116 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; |
112 | 117 | ||
113 | pktsz = sizeof(*ep); | 118 | pktsz = sizeof(*ep); |
@@ -116,7 +121,34 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
116 | ep->len = wq->len; | 121 | ep->len = wq->len; |
117 | memcpy(ep->name, wq->name, wq->len); | 122 | memcpy(ep->name, wq->name, wq->len); |
118 | ep->name[wq->len] = '\0'; | 123 | ep->name[wq->len] = '\0'; |
119 | } else { | 124 | break; |
125 | } | ||
126 | /* | ||
127 | * Kernel protocol v5 packet for handling indirect and direct | ||
128 | * mount missing and expire requests | ||
129 | */ | ||
130 | case autofs_ptype_missing_indirect: | ||
131 | case autofs_ptype_expire_indirect: | ||
132 | case autofs_ptype_missing_direct: | ||
133 | case autofs_ptype_expire_direct: | ||
134 | { | ||
135 | struct autofs_v5_packet *packet = &pkt.v5_packet; | ||
136 | |||
137 | pktsz = sizeof(*packet); | ||
138 | |||
139 | packet->wait_queue_token = wq->wait_queue_token; | ||
140 | packet->len = wq->len; | ||
141 | memcpy(packet->name, wq->name, wq->len); | ||
142 | packet->name[wq->len] = '\0'; | ||
143 | packet->dev = wq->dev; | ||
144 | packet->ino = wq->ino; | ||
145 | packet->uid = wq->uid; | ||
146 | packet->gid = wq->gid; | ||
147 | packet->pid = wq->pid; | ||
148 | packet->tgid = wq->tgid; | ||
149 | break; | ||
150 | } | ||
151 | default: | ||
120 | printk("autofs4_notify_daemon: bad type %d!\n", type); | 152 | printk("autofs4_notify_daemon: bad type %d!\n", type); |
121 | return; | 153 | return; |
122 | } | 154 | } |
@@ -162,21 +194,29 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
162 | { | 194 | { |
163 | struct autofs_wait_queue *wq; | 195 | struct autofs_wait_queue *wq; |
164 | char *name; | 196 | char *name; |
165 | int len, status; | 197 | unsigned int len = 0; |
198 | unsigned int hash = 0; | ||
199 | int status; | ||
166 | 200 | ||
167 | /* In catatonic mode, we don't wait for nobody */ | 201 | /* In catatonic mode, we don't wait for nobody */ |
168 | if ( sbi->catatonic ) | 202 | if (sbi->catatonic) |
169 | return -ENOENT; | 203 | return -ENOENT; |
170 | 204 | ||
171 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); | 205 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); |
172 | if (!name) | 206 | if (!name) |
173 | return -ENOMEM; | 207 | return -ENOMEM; |
174 | 208 | ||
175 | len = autofs4_getpath(sbi, dentry, &name); | 209 | /* If this is a direct mount request create a dummy name */ |
176 | if (!len) { | 210 | if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT)) |
177 | kfree(name); | 211 | len = sprintf(name, "%p", dentry); |
178 | return -ENOENT; | 212 | else { |
213 | len = autofs4_getpath(sbi, dentry, &name); | ||
214 | if (!len) { | ||
215 | kfree(name); | ||
216 | return -ENOENT; | ||
217 | } | ||
179 | } | 218 | } |
219 | hash = full_name_hash(name, len); | ||
180 | 220 | ||
181 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | 221 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { |
182 | kfree(name); | 222 | kfree(name); |
@@ -190,7 +230,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
190 | break; | 230 | break; |
191 | } | 231 | } |
192 | 232 | ||
193 | if ( !wq ) { | 233 | if (!wq) { |
194 | /* Can't wait for an expire if there's no mount */ | 234 | /* Can't wait for an expire if there's no mount */ |
195 | if (notify == NFY_NONE && !d_mountpoint(dentry)) { | 235 | if (notify == NFY_NONE && !d_mountpoint(dentry)) { |
196 | kfree(name); | 236 | kfree(name); |
@@ -200,7 +240,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
200 | 240 | ||
201 | /* Create a new wait queue */ | 241 | /* Create a new wait queue */ |
202 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); | 242 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); |
203 | if ( !wq ) { | 243 | if (!wq) { |
204 | kfree(name); | 244 | kfree(name); |
205 | mutex_unlock(&sbi->wq_mutex); | 245 | mutex_unlock(&sbi->wq_mutex); |
206 | return -ENOMEM; | 246 | return -ENOMEM; |
@@ -212,12 +252,18 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
212 | wq->next = sbi->queues; | 252 | wq->next = sbi->queues; |
213 | sbi->queues = wq; | 253 | sbi->queues = wq; |
214 | init_waitqueue_head(&wq->queue); | 254 | init_waitqueue_head(&wq->queue); |
215 | wq->hash = dentry->d_name.hash; | 255 | wq->hash = hash; |
216 | wq->name = name; | 256 | wq->name = name; |
217 | wq->len = len; | 257 | wq->len = len; |
258 | wq->dev = autofs4_get_dev(sbi); | ||
259 | wq->ino = autofs4_get_ino(sbi); | ||
260 | wq->uid = current->uid; | ||
261 | wq->gid = current->gid; | ||
262 | wq->pid = current->pid; | ||
263 | wq->tgid = current->tgid; | ||
218 | wq->status = -EINTR; /* Status return if interrupted */ | 264 | wq->status = -EINTR; /* Status return if interrupted */ |
219 | atomic_set(&wq->wait_ctr, 2); | 265 | atomic_set(&wq->wait_ctr, 2); |
220 | atomic_set(&wq->notified, 1); | 266 | atomic_set(&wq->notify, 1); |
221 | mutex_unlock(&sbi->wq_mutex); | 267 | mutex_unlock(&sbi->wq_mutex); |
222 | } else { | 268 | } else { |
223 | atomic_inc(&wq->wait_ctr); | 269 | atomic_inc(&wq->wait_ctr); |
@@ -227,9 +273,26 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
227 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 273 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |
228 | } | 274 | } |
229 | 275 | ||
230 | if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) { | 276 | if (notify != NFY_NONE && atomic_read(&wq->notify)) { |
231 | int type = (notify == NFY_MOUNT ? | 277 | int type; |
232 | autofs_ptype_missing : autofs_ptype_expire_multi); | 278 | |
279 | atomic_dec(&wq->notify); | ||
280 | |||
281 | if (sbi->version < 5) { | ||
282 | if (notify == NFY_MOUNT) | ||
283 | type = autofs_ptype_missing; | ||
284 | else | ||
285 | type = autofs_ptype_expire_multi; | ||
286 | } else { | ||
287 | if (notify == NFY_MOUNT) | ||
288 | type = (sbi->type & AUTOFS_TYPE_DIRECT) ? | ||
289 | autofs_ptype_missing_direct : | ||
290 | autofs_ptype_missing_indirect; | ||
291 | else | ||
292 | type = (sbi->type & AUTOFS_TYPE_DIRECT) ? | ||
293 | autofs_ptype_expire_direct : | ||
294 | autofs_ptype_expire_indirect; | ||
295 | } | ||
233 | 296 | ||
234 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", | 297 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", |
235 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 298 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |
@@ -240,14 +303,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
240 | 303 | ||
241 | /* wq->name is NULL if and only if the lock is already released */ | 304 | /* wq->name is NULL if and only if the lock is already released */ |
242 | 305 | ||
243 | if ( sbi->catatonic ) { | 306 | if (sbi->catatonic) { |
244 | /* We might have slept, so check again for catatonic mode */ | 307 | /* We might have slept, so check again for catatonic mode */ |
245 | wq->status = -ENOENT; | 308 | wq->status = -ENOENT; |
246 | kfree(wq->name); | 309 | kfree(wq->name); |
247 | wq->name = NULL; | 310 | wq->name = NULL; |
248 | } | 311 | } |
249 | 312 | ||
250 | if ( wq->name ) { | 313 | if (wq->name) { |
251 | /* Block all but "shutdown" signals while waiting */ | 314 | /* Block all but "shutdown" signals while waiting */ |
252 | sigset_t oldset; | 315 | sigset_t oldset; |
253 | unsigned long irqflags; | 316 | unsigned long irqflags; |
@@ -283,12 +346,12 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok | |||
283 | struct autofs_wait_queue *wq, **wql; | 346 | struct autofs_wait_queue *wq, **wql; |
284 | 347 | ||
285 | mutex_lock(&sbi->wq_mutex); | 348 | mutex_lock(&sbi->wq_mutex); |
286 | for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) { | 349 | for (wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next) { |
287 | if ( wq->wait_queue_token == wait_queue_token ) | 350 | if (wq->wait_queue_token == wait_queue_token) |
288 | break; | 351 | break; |
289 | } | 352 | } |
290 | 353 | ||
291 | if ( !wq ) { | 354 | if (!wq) { |
292 | mutex_unlock(&sbi->wq_mutex); | 355 | mutex_unlock(&sbi->wq_mutex); |
293 | return -EINVAL; | 356 | return -EINVAL; |
294 | } | 357 | } |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index e172180a1d8c..80599ae33966 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -22,7 +22,7 @@ static int return_EIO(void) | |||
22 | 22 | ||
23 | #define EIO_ERROR ((void *) (return_EIO)) | 23 | #define EIO_ERROR ((void *) (return_EIO)) |
24 | 24 | ||
25 | static struct file_operations bad_file_ops = | 25 | static const struct file_operations bad_file_ops = |
26 | { | 26 | { |
27 | .llseek = EIO_ERROR, | 27 | .llseek = EIO_ERROR, |
28 | .aio_read = EIO_ERROR, | 28 | .aio_read = EIO_ERROR, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 044a59587829..68ebd10f345d 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -64,7 +64,7 @@ static const struct super_operations befs_sops = { | |||
64 | /* slab cache for befs_inode_info objects */ | 64 | /* slab cache for befs_inode_info objects */ |
65 | static kmem_cache_t *befs_inode_cachep; | 65 | static kmem_cache_t *befs_inode_cachep; |
66 | 66 | ||
67 | static struct file_operations befs_dir_operations = { | 67 | static const struct file_operations befs_dir_operations = { |
68 | .read = generic_read_dir, | 68 | .read = generic_read_dir, |
69 | .readdir = befs_readdir, | 69 | .readdir = befs_readdir, |
70 | }; | 70 | }; |
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 1fbc53f14aba..9d791004b21c 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h | |||
@@ -49,11 +49,11 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) | |||
49 | 49 | ||
50 | /* file.c */ | 50 | /* file.c */ |
51 | extern struct inode_operations bfs_file_inops; | 51 | extern struct inode_operations bfs_file_inops; |
52 | extern struct file_operations bfs_file_operations; | 52 | extern const struct file_operations bfs_file_operations; |
53 | extern struct address_space_operations bfs_aops; | 53 | extern struct address_space_operations bfs_aops; |
54 | 54 | ||
55 | /* dir.c */ | 55 | /* dir.c */ |
56 | extern struct inode_operations bfs_dir_inops; | 56 | extern struct inode_operations bfs_dir_inops; |
57 | extern struct file_operations bfs_dir_operations; | 57 | extern const struct file_operations bfs_dir_operations; |
58 | 58 | ||
59 | #endif /* _FS_BFS_BFS_H */ | 59 | #endif /* _FS_BFS_BFS_H */ |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 5af928fa0449..26fad9621738 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -70,7 +70,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) | |||
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
72 | 72 | ||
73 | struct file_operations bfs_dir_operations = { | 73 | const struct file_operations bfs_dir_operations = { |
74 | .read = generic_read_dir, | 74 | .read = generic_read_dir, |
75 | .readdir = bfs_readdir, | 75 | .readdir = bfs_readdir, |
76 | .fsync = file_fsync, | 76 | .fsync = file_fsync, |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 807723b65daf..d83cd74a2e4e 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #define dprintf(x...) | 17 | #define dprintf(x...) |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | struct file_operations bfs_file_operations = { | 20 | const struct file_operations bfs_file_operations = { |
21 | .llseek = generic_file_llseek, | 21 | .llseek = generic_file_llseek, |
22 | .read = generic_file_read, | 22 | .read = generic_file_read, |
23 | .write = generic_file_write, | 23 | .write = generic_file_write, |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 6a7b730c206b..d73d75591a39 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -600,7 +600,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, | |||
600 | return count; | 600 | return count; |
601 | } | 601 | } |
602 | 602 | ||
603 | static struct file_operations bm_entry_operations = { | 603 | static const struct file_operations bm_entry_operations = { |
604 | .read = bm_entry_read, | 604 | .read = bm_entry_read, |
605 | .write = bm_entry_write, | 605 | .write = bm_entry_write, |
606 | }; | 606 | }; |
@@ -668,7 +668,7 @@ out: | |||
668 | return count; | 668 | return count; |
669 | } | 669 | } |
670 | 670 | ||
671 | static struct file_operations bm_register_operations = { | 671 | static const struct file_operations bm_register_operations = { |
672 | .write = bm_register_write, | 672 | .write = bm_register_write, |
673 | }; | 673 | }; |
674 | 674 | ||
@@ -715,7 +715,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer, | |||
715 | return count; | 715 | return count; |
716 | } | 716 | } |
717 | 717 | ||
718 | static struct file_operations bm_status_operations = { | 718 | static const struct file_operations bm_status_operations = { |
719 | .read = bm_status_read, | 719 | .read = bm_status_read, |
720 | .write = bm_status_write, | 720 | .write = bm_status_write, |
721 | }; | 721 | }; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5983d42df015..af88c43043d5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -266,6 +266,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
266 | mutex_init(&bdev->bd_mount_mutex); | 266 | mutex_init(&bdev->bd_mount_mutex); |
267 | INIT_LIST_HEAD(&bdev->bd_inodes); | 267 | INIT_LIST_HEAD(&bdev->bd_inodes); |
268 | INIT_LIST_HEAD(&bdev->bd_list); | 268 | INIT_LIST_HEAD(&bdev->bd_list); |
269 | #ifdef CONFIG_SYSFS | ||
270 | INIT_LIST_HEAD(&bdev->bd_holder_list); | ||
271 | #endif | ||
269 | inode_init_once(&ei->vfs_inode); | 272 | inode_init_once(&ei->vfs_inode); |
270 | } | 273 | } |
271 | } | 274 | } |
@@ -490,6 +493,300 @@ void bd_release(struct block_device *bdev) | |||
490 | 493 | ||
491 | EXPORT_SYMBOL(bd_release); | 494 | EXPORT_SYMBOL(bd_release); |
492 | 495 | ||
496 | #ifdef CONFIG_SYSFS | ||
497 | /* | ||
498 | * Functions for bd_claim_by_kobject / bd_release_from_kobject | ||
499 | * | ||
500 | * If a kobject is passed to bd_claim_by_kobject() | ||
501 | * and the kobject has a parent directory, | ||
502 | * following symlinks are created: | ||
503 | * o from the kobject to the claimed bdev | ||
504 | * o from "holders" directory of the bdev to the parent of the kobject | ||
505 | * bd_release_from_kobject() removes these symlinks. | ||
506 | * | ||
507 | * Example: | ||
508 | * If /dev/dm-0 maps to /dev/sda, kobject corresponding to | ||
509 | * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then: | ||
510 | * /sys/block/dm-0/slaves/sda --> /sys/block/sda | ||
511 | * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 | ||
512 | */ | ||
513 | |||
514 | static struct kobject *bdev_get_kobj(struct block_device *bdev) | ||
515 | { | ||
516 | if (bdev->bd_contains != bdev) | ||
517 | return kobject_get(&bdev->bd_part->kobj); | ||
518 | else | ||
519 | return kobject_get(&bdev->bd_disk->kobj); | ||
520 | } | ||
521 | |||
522 | static struct kobject *bdev_get_holder(struct block_device *bdev) | ||
523 | { | ||
524 | if (bdev->bd_contains != bdev) | ||
525 | return kobject_get(bdev->bd_part->holder_dir); | ||
526 | else | ||
527 | return kobject_get(bdev->bd_disk->holder_dir); | ||
528 | } | ||
529 | |||
530 | static void add_symlink(struct kobject *from, struct kobject *to) | ||
531 | { | ||
532 | if (!from || !to) | ||
533 | return; | ||
534 | sysfs_create_link(from, to, kobject_name(to)); | ||
535 | } | ||
536 | |||
537 | static void del_symlink(struct kobject *from, struct kobject *to) | ||
538 | { | ||
539 | if (!from || !to) | ||
540 | return; | ||
541 | sysfs_remove_link(from, kobject_name(to)); | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * 'struct bd_holder' contains pointers to kobjects symlinked by | ||
546 | * bd_claim_by_kobject. | ||
547 | * It's connected to bd_holder_list which is protected by bdev->bd_sem. | ||
548 | */ | ||
549 | struct bd_holder { | ||
550 | struct list_head list; /* chain of holders of the bdev */ | ||
551 | int count; /* references from the holder */ | ||
552 | struct kobject *sdir; /* holder object, e.g. "/block/dm-0/slaves" */ | ||
553 | struct kobject *hdev; /* e.g. "/block/dm-0" */ | ||
554 | struct kobject *hdir; /* e.g. "/block/sda/holders" */ | ||
555 | struct kobject *sdev; /* e.g. "/block/sda" */ | ||
556 | }; | ||
557 | |||
558 | /* | ||
559 | * Get references of related kobjects at once. | ||
560 | * Returns 1 on success. 0 on failure. | ||
561 | * | ||
562 | * Should call bd_holder_release_dirs() after successful use. | ||
563 | */ | ||
564 | static int bd_holder_grab_dirs(struct block_device *bdev, | ||
565 | struct bd_holder *bo) | ||
566 | { | ||
567 | if (!bdev || !bo) | ||
568 | return 0; | ||
569 | |||
570 | bo->sdir = kobject_get(bo->sdir); | ||
571 | if (!bo->sdir) | ||
572 | return 0; | ||
573 | |||
574 | bo->hdev = kobject_get(bo->sdir->parent); | ||
575 | if (!bo->hdev) | ||
576 | goto fail_put_sdir; | ||
577 | |||
578 | bo->sdev = bdev_get_kobj(bdev); | ||
579 | if (!bo->sdev) | ||
580 | goto fail_put_hdev; | ||
581 | |||
582 | bo->hdir = bdev_get_holder(bdev); | ||
583 | if (!bo->hdir) | ||
584 | goto fail_put_sdev; | ||
585 | |||
586 | return 1; | ||
587 | |||
588 | fail_put_sdev: | ||
589 | kobject_put(bo->sdev); | ||
590 | fail_put_hdev: | ||
591 | kobject_put(bo->hdev); | ||
592 | fail_put_sdir: | ||
593 | kobject_put(bo->sdir); | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | /* Put references of related kobjects at once. */ | ||
599 | static void bd_holder_release_dirs(struct bd_holder *bo) | ||
600 | { | ||
601 | kobject_put(bo->hdir); | ||
602 | kobject_put(bo->sdev); | ||
603 | kobject_put(bo->hdev); | ||
604 | kobject_put(bo->sdir); | ||
605 | } | ||
606 | |||
607 | static struct bd_holder *alloc_bd_holder(struct kobject *kobj) | ||
608 | { | ||
609 | struct bd_holder *bo; | ||
610 | |||
611 | bo = kzalloc(sizeof(*bo), GFP_KERNEL); | ||
612 | if (!bo) | ||
613 | return NULL; | ||
614 | |||
615 | bo->count = 1; | ||
616 | bo->sdir = kobj; | ||
617 | |||
618 | return bo; | ||
619 | } | ||
620 | |||
621 | static void free_bd_holder(struct bd_holder *bo) | ||
622 | { | ||
623 | kfree(bo); | ||
624 | } | ||
625 | |||
626 | /** | ||
627 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship | ||
628 | * | ||
629 | * @bdev: block device to be bd_claimed | ||
630 | * @bo: preallocated and initialized by alloc_bd_holder() | ||
631 | * | ||
632 | * If there is no matching entry with @bo in @bdev->bd_holder_list, | ||
633 | * add @bo to the list, create symlinks. | ||
634 | * | ||
635 | * Returns 1 if @bo was added to the list. | ||
636 | * Returns 0 if @bo wasn't used by any reason and should be freed. | ||
637 | */ | ||
638 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | ||
639 | { | ||
640 | struct bd_holder *tmp; | ||
641 | |||
642 | if (!bo) | ||
643 | return 0; | ||
644 | |||
645 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) { | ||
646 | if (tmp->sdir == bo->sdir) { | ||
647 | tmp->count++; | ||
648 | return 0; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | if (!bd_holder_grab_dirs(bdev, bo)) | ||
653 | return 0; | ||
654 | |||
655 | add_symlink(bo->sdir, bo->sdev); | ||
656 | add_symlink(bo->hdir, bo->hdev); | ||
657 | list_add_tail(&bo->list, &bdev->bd_holder_list); | ||
658 | return 1; | ||
659 | } | ||
660 | |||
661 | /** | ||
662 | * del_bd_holder - delete sysfs symlinks for bd_claim() relationship | ||
663 | * | ||
664 | * @bdev: block device to be bd_claimed | ||
665 | * @kobj: holder's kobject | ||
666 | * | ||
667 | * If there is matching entry with @kobj in @bdev->bd_holder_list | ||
668 | * and no other bd_claim() from the same kobject, | ||
669 | * remove the struct bd_holder from the list, delete symlinks for it. | ||
670 | * | ||
671 | * Returns a pointer to the struct bd_holder when it's removed from the list | ||
672 | * and ready to be freed. | ||
673 | * Returns NULL if matching claim isn't found or there is other bd_claim() | ||
674 | * by the same kobject. | ||
675 | */ | ||
676 | static struct bd_holder *del_bd_holder(struct block_device *bdev, | ||
677 | struct kobject *kobj) | ||
678 | { | ||
679 | struct bd_holder *bo; | ||
680 | |||
681 | list_for_each_entry(bo, &bdev->bd_holder_list, list) { | ||
682 | if (bo->sdir == kobj) { | ||
683 | bo->count--; | ||
684 | BUG_ON(bo->count < 0); | ||
685 | if (!bo->count) { | ||
686 | list_del(&bo->list); | ||
687 | del_symlink(bo->sdir, bo->sdev); | ||
688 | del_symlink(bo->hdir, bo->hdev); | ||
689 | bd_holder_release_dirs(bo); | ||
690 | return bo; | ||
691 | } | ||
692 | break; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | return NULL; | ||
697 | } | ||
698 | |||
699 | /** | ||
700 | * bd_claim_by_kobject - bd_claim() with additional kobject signature | ||
701 | * | ||
702 | * @bdev: block device to be claimed | ||
703 | * @holder: holder's signature | ||
704 | * @kobj: holder's kobject | ||
705 | * | ||
706 | * Do bd_claim() and if it succeeds, create sysfs symlinks between | ||
707 | * the bdev and the holder's kobject. | ||
708 | * Use bd_release_from_kobject() when relesing the claimed bdev. | ||
709 | * | ||
710 | * Returns 0 on success. (same as bd_claim()) | ||
711 | * Returns errno on failure. | ||
712 | */ | ||
713 | static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | ||
714 | struct kobject *kobj) | ||
715 | { | ||
716 | int res; | ||
717 | struct bd_holder *bo; | ||
718 | |||
719 | if (!kobj) | ||
720 | return -EINVAL; | ||
721 | |||
722 | bo = alloc_bd_holder(kobj); | ||
723 | if (!bo) | ||
724 | return -ENOMEM; | ||
725 | |||
726 | mutex_lock(&bdev->bd_mutex); | ||
727 | res = bd_claim(bdev, holder); | ||
728 | if (res || !add_bd_holder(bdev, bo)) | ||
729 | free_bd_holder(bo); | ||
730 | mutex_unlock(&bdev->bd_mutex); | ||
731 | |||
732 | return res; | ||
733 | } | ||
734 | |||
735 | /** | ||
736 | * bd_release_from_kobject - bd_release() with additional kobject signature | ||
737 | * | ||
738 | * @bdev: block device to be released | ||
739 | * @kobj: holder's kobject | ||
740 | * | ||
741 | * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject(). | ||
742 | */ | ||
743 | static void bd_release_from_kobject(struct block_device *bdev, | ||
744 | struct kobject *kobj) | ||
745 | { | ||
746 | struct bd_holder *bo; | ||
747 | |||
748 | if (!kobj) | ||
749 | return; | ||
750 | |||
751 | mutex_lock(&bdev->bd_mutex); | ||
752 | bd_release(bdev); | ||
753 | if ((bo = del_bd_holder(bdev, kobj))) | ||
754 | free_bd_holder(bo); | ||
755 | mutex_unlock(&bdev->bd_mutex); | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * bd_claim_by_disk - wrapper function for bd_claim_by_kobject() | ||
760 | * | ||
761 | * @bdev: block device to be claimed | ||
762 | * @holder: holder's signature | ||
763 | * @disk: holder's gendisk | ||
764 | * | ||
765 | * Call bd_claim_by_kobject() with getting @disk->slave_dir. | ||
766 | */ | ||
767 | int bd_claim_by_disk(struct block_device *bdev, void *holder, | ||
768 | struct gendisk *disk) | ||
769 | { | ||
770 | return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir)); | ||
771 | } | ||
772 | EXPORT_SYMBOL_GPL(bd_claim_by_disk); | ||
773 | |||
774 | /** | ||
775 | * bd_release_from_disk - wrapper function for bd_release_from_kobject() | ||
776 | * | ||
777 | * @bdev: block device to be claimed | ||
778 | * @disk: holder's gendisk | ||
779 | * | ||
780 | * Call bd_release_from_kobject() and put @disk->slave_dir. | ||
781 | */ | ||
782 | void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk) | ||
783 | { | ||
784 | bd_release_from_kobject(bdev, disk->slave_dir); | ||
785 | kobject_put(disk->slave_dir); | ||
786 | } | ||
787 | EXPORT_SYMBOL_GPL(bd_release_from_disk); | ||
788 | #endif | ||
789 | |||
493 | /* | 790 | /* |
494 | * Tries to open block device by device number. Use it ONLY if you | 791 | * Tries to open block device by device number. Use it ONLY if you |
495 | * really do not have anything better - i.e. when you are behind a | 792 | * really do not have anything better - i.e. when you are behind a |
@@ -790,7 +1087,7 @@ struct address_space_operations def_blk_aops = { | |||
790 | .direct_IO = blkdev_direct_IO, | 1087 | .direct_IO = blkdev_direct_IO, |
791 | }; | 1088 | }; |
792 | 1089 | ||
793 | struct file_operations def_blk_fops = { | 1090 | const struct file_operations def_blk_fops = { |
794 | .open = blkdev_open, | 1091 | .open = blkdev_open, |
795 | .release = blkdev_close, | 1092 | .release = blkdev_close, |
796 | .llseek = block_llseek, | 1093 | .llseek = block_llseek, |
diff --git a/fs/buffer.c b/fs/buffer.c index d597758dd129..23f1f3a68077 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -493,7 +493,7 @@ static void free_more_memory(void) | |||
493 | wakeup_pdflush(1024); | 493 | wakeup_pdflush(1024); |
494 | yield(); | 494 | yield(); |
495 | 495 | ||
496 | for_each_pgdat(pgdat) { | 496 | for_each_online_pgdat(pgdat) { |
497 | zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; | 497 | zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; |
498 | if (*zones) | 498 | if (*zones) |
499 | try_to_free_pages(zones, GFP_NOFS); | 499 | try_to_free_pages(zones, GFP_NOFS); |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 8c6eb04d31e2..4e1b849f912f 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -250,7 +250,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
250 | } | 250 | } |
251 | 251 | ||
252 | int register_chrdev(unsigned int major, const char *name, | 252 | int register_chrdev(unsigned int major, const char *name, |
253 | struct file_operations *fops) | 253 | const struct file_operations *fops) |
254 | { | 254 | { |
255 | struct char_device_struct *cd; | 255 | struct char_device_struct *cd; |
256 | struct cdev *cdev; | 256 | struct cdev *cdev; |
@@ -406,7 +406,7 @@ static void cdev_purge(struct cdev *cdev) | |||
406 | * is contain the open that then fills in the correct operations | 406 | * is contain the open that then fills in the correct operations |
407 | * depending on the special file... | 407 | * depending on the special file... |
408 | */ | 408 | */ |
409 | struct file_operations def_chr_fops = { | 409 | const struct file_operations def_chr_fops = { |
410 | .open = chrdev_open, | 410 | .open = chrdev_open, |
411 | }; | 411 | }; |
412 | 412 | ||
@@ -473,7 +473,7 @@ struct cdev *cdev_alloc(void) | |||
473 | return p; | 473 | return p; |
474 | } | 474 | } |
475 | 475 | ||
476 | void cdev_init(struct cdev *cdev, struct file_operations *fops) | 476 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) |
477 | { | 477 | { |
478 | memset(cdev, 0, sizeof *cdev); | 478 | memset(cdev, 0, sizeof *cdev); |
479 | INIT_LIST_HEAD(&cdev->list); | 479 | INIT_LIST_HEAD(&cdev->list); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 6b99b51d6694..4bbc544857bc 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -583,7 +583,7 @@ struct inode_operations cifs_symlink_inode_ops = { | |||
583 | #endif | 583 | #endif |
584 | }; | 584 | }; |
585 | 585 | ||
586 | struct file_operations cifs_file_ops = { | 586 | const struct file_operations cifs_file_ops = { |
587 | .read = do_sync_read, | 587 | .read = do_sync_read, |
588 | .write = do_sync_write, | 588 | .write = do_sync_write, |
589 | .readv = generic_file_readv, | 589 | .readv = generic_file_readv, |
@@ -607,7 +607,7 @@ struct file_operations cifs_file_ops = { | |||
607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
608 | }; | 608 | }; |
609 | 609 | ||
610 | struct file_operations cifs_file_direct_ops = { | 610 | const struct file_operations cifs_file_direct_ops = { |
611 | /* no mmap, no aio, no readv - | 611 | /* no mmap, no aio, no readv - |
612 | BB reevaluate whether they can be done with directio, no cache */ | 612 | BB reevaluate whether they can be done with directio, no cache */ |
613 | .read = cifs_user_read, | 613 | .read = cifs_user_read, |
@@ -626,7 +626,7 @@ struct file_operations cifs_file_direct_ops = { | |||
626 | .dir_notify = cifs_dir_notify, | 626 | .dir_notify = cifs_dir_notify, |
627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
628 | }; | 628 | }; |
629 | struct file_operations cifs_file_nobrl_ops = { | 629 | const struct file_operations cifs_file_nobrl_ops = { |
630 | .read = do_sync_read, | 630 | .read = do_sync_read, |
631 | .write = do_sync_write, | 631 | .write = do_sync_write, |
632 | .readv = generic_file_readv, | 632 | .readv = generic_file_readv, |
@@ -649,7 +649,7 @@ struct file_operations cifs_file_nobrl_ops = { | |||
649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
650 | }; | 650 | }; |
651 | 651 | ||
652 | struct file_operations cifs_file_direct_nobrl_ops = { | 652 | const struct file_operations cifs_file_direct_nobrl_ops = { |
653 | /* no mmap, no aio, no readv - | 653 | /* no mmap, no aio, no readv - |
654 | BB reevaluate whether they can be done with directio, no cache */ | 654 | BB reevaluate whether they can be done with directio, no cache */ |
655 | .read = cifs_user_read, | 655 | .read = cifs_user_read, |
@@ -668,7 +668,7 @@ struct file_operations cifs_file_direct_nobrl_ops = { | |||
668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
669 | }; | 669 | }; |
670 | 670 | ||
671 | struct file_operations cifs_dir_ops = { | 671 | const struct file_operations cifs_dir_ops = { |
672 | .readdir = cifs_readdir, | 672 | .readdir = cifs_readdir, |
673 | .release = cifs_closedir, | 673 | .release = cifs_closedir, |
674 | .read = generic_read_dir, | 674 | .read = generic_read_dir, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb22559..74f405ae4da3 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -61,10 +61,10 @@ extern struct inode_operations cifs_file_inode_ops; | |||
61 | extern struct inode_operations cifs_symlink_inode_ops; | 61 | extern struct inode_operations cifs_symlink_inode_ops; |
62 | 62 | ||
63 | /* Functions related to files and directories */ | 63 | /* Functions related to files and directories */ |
64 | extern struct file_operations cifs_file_ops; | 64 | extern const struct file_operations cifs_file_ops; |
65 | extern struct file_operations cifs_file_direct_ops; /* if directio mount */ | 65 | extern const struct file_operations cifs_file_direct_ops; /* if directio mount */ |
66 | extern struct file_operations cifs_file_nobrl_ops; | 66 | extern const struct file_operations cifs_file_nobrl_ops; |
67 | extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ | 67 | extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ |
68 | extern int cifs_open(struct inode *inode, struct file *file); | 68 | extern int cifs_open(struct inode *inode, struct file *file); |
69 | extern int cifs_close(struct inode *inode, struct file *file); | 69 | extern int cifs_close(struct inode *inode, struct file *file); |
70 | extern int cifs_closedir(struct inode *inode, struct file *file); | 70 | extern int cifs_closedir(struct inode *inode, struct file *file); |
@@ -76,7 +76,7 @@ extern int cifs_lock(struct file *, int, struct file_lock *); | |||
76 | extern int cifs_fsync(struct file *, struct dentry *, int); | 76 | extern int cifs_fsync(struct file *, struct dentry *, int); |
77 | extern int cifs_flush(struct file *); | 77 | extern int cifs_flush(struct file *); |
78 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 78 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
79 | extern struct file_operations cifs_dir_ops; | 79 | extern const struct file_operations cifs_dir_ops; |
80 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 80 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
81 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 81 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
82 | extern int cifs_dir_notify(struct file *, unsigned long arg); | 82 | extern int cifs_dir_notify(struct file *, unsigned long arg); |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 54f76de8a686..71f2ea632e53 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -82,7 +82,7 @@ struct inode_operations coda_dir_inode_operations = | |||
82 | .setattr = coda_setattr, | 82 | .setattr = coda_setattr, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | struct file_operations coda_dir_operations = { | 85 | const struct file_operations coda_dir_operations = { |
86 | .llseek = generic_file_llseek, | 86 | .llseek = generic_file_llseek, |
87 | .read = generic_read_dir, | 87 | .read = generic_read_dir, |
88 | .readdir = coda_readdir, | 88 | .readdir = coda_readdir, |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 146a991d6eb5..7c2642431fa5 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
@@ -288,7 +288,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) | |||
288 | return err; | 288 | return err; |
289 | } | 289 | } |
290 | 290 | ||
291 | struct file_operations coda_file_operations = { | 291 | const struct file_operations coda_file_operations = { |
292 | .llseek = generic_file_llseek, | 292 | .llseek = generic_file_llseek, |
293 | .read = coda_file_read, | 293 | .read = coda_file_read, |
294 | .write = coda_file_write, | 294 | .write = coda_file_write, |
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 127714936c66..214822be87bd 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
@@ -36,7 +36,7 @@ struct inode_operations coda_ioctl_inode_operations = | |||
36 | .setattr = coda_setattr, | 36 | .setattr = coda_setattr, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct file_operations coda_ioctl_operations = { | 39 | const struct file_operations coda_ioctl_operations = { |
40 | .owner = THIS_MODULE, | 40 | .owner = THIS_MODULE, |
41 | .ioctl = coda_pioctl, | 41 | .ioctl = coda_pioctl, |
42 | }; | 42 | }; |
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 98c74fe2e139..6c6771db36da 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
@@ -342,7 +342,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) | |||
342 | } | 342 | } |
343 | 343 | ||
344 | 344 | ||
345 | static struct file_operations coda_psdev_fops = { | 345 | static const struct file_operations coda_psdev_fops = { |
346 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
347 | .read = coda_psdev_read, | 347 | .read = coda_psdev_read, |
348 | .write = coda_psdev_write, | 348 | .write = coda_psdev_write, |
diff --git a/fs/compat.c b/fs/compat.c index ef5a0771592d..7f8e26ea427c 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1639,15 +1639,6 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1639 | * This is a virtual copy of sys_select from fs/select.c and probably | 1639 | * This is a virtual copy of sys_select from fs/select.c and probably |
1640 | * should be compared to it from time to time | 1640 | * should be compared to it from time to time |
1641 | */ | 1641 | */ |
1642 | static void *select_bits_alloc(int size) | ||
1643 | { | ||
1644 | return kmalloc(6 * size, GFP_KERNEL); | ||
1645 | } | ||
1646 | |||
1647 | static void select_bits_free(void *bits, int size) | ||
1648 | { | ||
1649 | kfree(bits); | ||
1650 | } | ||
1651 | 1642 | ||
1652 | /* | 1643 | /* |
1653 | * We can actually return ERESTARTSYS instead of EINTR, but I'd | 1644 | * We can actually return ERESTARTSYS instead of EINTR, but I'd |
@@ -1686,7 +1677,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1686 | */ | 1677 | */ |
1687 | ret = -ENOMEM; | 1678 | ret = -ENOMEM; |
1688 | size = FDS_BYTES(n); | 1679 | size = FDS_BYTES(n); |
1689 | bits = select_bits_alloc(size); | 1680 | bits = kmalloc(6 * size, GFP_KERNEL); |
1690 | if (!bits) | 1681 | if (!bits) |
1691 | goto out_nofds; | 1682 | goto out_nofds; |
1692 | fds.in = (unsigned long *) bits; | 1683 | fds.in = (unsigned long *) bits; |
@@ -1720,7 +1711,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
1720 | compat_set_fd_set(n, exp, fds.res_ex); | 1711 | compat_set_fd_set(n, exp, fds.res_ex); |
1721 | 1712 | ||
1722 | out: | 1713 | out: |
1723 | select_bits_free(bits, size); | 1714 | kfree(bits); |
1724 | out_nofds: | 1715 | out_nofds: |
1725 | return ret; | 1716 | return ret; |
1726 | } | 1717 | } |
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index f70e46951b37..3f4ff7a242b9 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
@@ -72,9 +72,9 @@ extern void configfs_release_fs(void); | |||
72 | 72 | ||
73 | extern struct rw_semaphore configfs_rename_sem; | 73 | extern struct rw_semaphore configfs_rename_sem; |
74 | extern struct super_block * configfs_sb; | 74 | extern struct super_block * configfs_sb; |
75 | extern struct file_operations configfs_dir_operations; | 75 | extern const struct file_operations configfs_dir_operations; |
76 | extern struct file_operations configfs_file_operations; | 76 | extern const struct file_operations configfs_file_operations; |
77 | extern struct file_operations bin_fops; | 77 | extern const struct file_operations bin_fops; |
78 | extern struct inode_operations configfs_dir_inode_operations; | 78 | extern struct inode_operations configfs_dir_inode_operations; |
79 | extern struct inode_operations configfs_symlink_inode_operations; | 79 | extern struct inode_operations configfs_symlink_inode_operations; |
80 | 80 | ||
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index ca60e3abef45..8ed9b06a9828 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1027,7 +1027,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
1027 | return offset; | 1027 | return offset; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | struct file_operations configfs_dir_operations = { | 1030 | const struct file_operations configfs_dir_operations = { |
1031 | .open = configfs_dir_open, | 1031 | .open = configfs_dir_open, |
1032 | .release = configfs_dir_close, | 1032 | .release = configfs_dir_close, |
1033 | .llseek = configfs_dir_lseek, | 1033 | .llseek = configfs_dir_lseek, |
diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 3921920d8716..f499803743e0 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c | |||
@@ -322,7 +322,7 @@ static int configfs_release(struct inode * inode, struct file * filp) | |||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
325 | struct file_operations configfs_file_operations = { | 325 | const struct file_operations configfs_file_operations = { |
326 | .read = configfs_read_file, | 326 | .read = configfs_read_file, |
327 | .write = configfs_write_file, | 327 | .write = configfs_write_file, |
328 | .llseek = generic_file_llseek, | 328 | .llseek = generic_file_llseek, |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index acc1b2c10a86..9efcc3a164e8 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | static struct super_operations cramfs_ops; | 30 | static struct super_operations cramfs_ops; |
31 | static struct inode_operations cramfs_dir_inode_operations; | 31 | static struct inode_operations cramfs_dir_inode_operations; |
32 | static struct file_operations cramfs_directory_operations; | 32 | static const struct file_operations cramfs_directory_operations; |
33 | static struct address_space_operations cramfs_aops; | 33 | static struct address_space_operations cramfs_aops; |
34 | 34 | ||
35 | static DEFINE_MUTEX(read_mutex); | 35 | static DEFINE_MUTEX(read_mutex); |
@@ -512,7 +512,7 @@ static struct address_space_operations cramfs_aops = { | |||
512 | /* | 512 | /* |
513 | * A directory can only readdir | 513 | * A directory can only readdir |
514 | */ | 514 | */ |
515 | static struct file_operations cramfs_directory_operations = { | 515 | static const struct file_operations cramfs_directory_operations = { |
516 | .llseek = generic_file_llseek, | 516 | .llseek = generic_file_llseek, |
517 | .read = generic_read_dir, | 517 | .read = generic_read_dir, |
518 | .readdir = cramfs_readdir, | 518 | .readdir = cramfs_readdir, |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 40c4fc973fad..66a505422e5c 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -39,7 +39,7 @@ static int default_open(struct inode *inode, struct file *file) | |||
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | struct file_operations debugfs_file_operations = { | 42 | const struct file_operations debugfs_file_operations = { |
43 | .read = default_read_file, | 43 | .read = default_read_file, |
44 | .write = default_write_file, | 44 | .write = default_write_file, |
45 | .open = default_open, | 45 | .open = default_open, |
@@ -213,7 +213,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf, | |||
213 | return count; | 213 | return count; |
214 | } | 214 | } |
215 | 215 | ||
216 | static struct file_operations fops_bool = { | 216 | static const struct file_operations fops_bool = { |
217 | .read = read_file_bool, | 217 | .read = read_file_bool, |
218 | .write = write_file_bool, | 218 | .write = write_file_bool, |
219 | .open = default_open, | 219 | .open = default_open, |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d4f1a2cddd47..85d166cdcae4 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -191,7 +191,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
191 | */ | 191 | */ |
192 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 192 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
193 | struct dentry *parent, void *data, | 193 | struct dentry *parent, void *data, |
194 | struct file_operations *fops) | 194 | const struct file_operations *fops) |
195 | { | 195 | { |
196 | struct dentry *dentry = NULL; | 196 | struct dentry *dentry = NULL; |
197 | int error; | 197 | int error; |
diff --git a/fs/devfs/base.c b/fs/devfs/base.c index b621521e09d4..52f5059c4f31 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c | |||
@@ -856,14 +856,14 @@ static int devfsd_close(struct inode *inode, struct file *file); | |||
856 | #ifdef CONFIG_DEVFS_DEBUG | 856 | #ifdef CONFIG_DEVFS_DEBUG |
857 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, | 857 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, |
858 | loff_t * ppos); | 858 | loff_t * ppos); |
859 | static struct file_operations stat_fops = { | 859 | static const struct file_operations stat_fops = { |
860 | .open = nonseekable_open, | 860 | .open = nonseekable_open, |
861 | .read = stat_read, | 861 | .read = stat_read, |
862 | }; | 862 | }; |
863 | #endif | 863 | #endif |
864 | 864 | ||
865 | /* Devfs daemon file operations */ | 865 | /* Devfs daemon file operations */ |
866 | static struct file_operations devfsd_fops = { | 866 | static const struct file_operations devfsd_fops = { |
867 | .open = nonseekable_open, | 867 | .open = nonseekable_open, |
868 | .read = devfsd_read, | 868 | .read = devfsd_read, |
869 | .ioctl = devfsd_ioctl, | 869 | .ioctl = devfsd_ioctl, |
@@ -1842,8 +1842,8 @@ static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, | |||
1842 | 1842 | ||
1843 | static struct inode_operations devfs_iops; | 1843 | static struct inode_operations devfs_iops; |
1844 | static struct inode_operations devfs_dir_iops; | 1844 | static struct inode_operations devfs_dir_iops; |
1845 | static struct file_operations devfs_fops; | 1845 | static const struct file_operations devfs_fops; |
1846 | static struct file_operations devfs_dir_fops; | 1846 | static const struct file_operations devfs_dir_fops; |
1847 | static struct inode_operations devfs_symlink_iops; | 1847 | static struct inode_operations devfs_symlink_iops; |
1848 | 1848 | ||
1849 | static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) | 1849 | static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) |
@@ -2061,11 +2061,11 @@ static int devfs_open(struct inode *inode, struct file *file) | |||
2061 | return err; | 2061 | return err; |
2062 | } /* End Function devfs_open */ | 2062 | } /* End Function devfs_open */ |
2063 | 2063 | ||
2064 | static struct file_operations devfs_fops = { | 2064 | static const struct file_operations devfs_fops = { |
2065 | .open = devfs_open, | 2065 | .open = devfs_open, |
2066 | }; | 2066 | }; |
2067 | 2067 | ||
2068 | static struct file_operations devfs_dir_fops = { | 2068 | static const struct file_operations devfs_dir_fops = { |
2069 | .read = generic_read_dir, | 2069 | .read = generic_read_dir, |
2070 | .readdir = devfs_readdir, | 2070 | .readdir = devfs_readdir, |
2071 | }; | 2071 | }; |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 9d1d2aa73e42..910a8ed74b5d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -524,8 +524,6 @@ static int get_more_blocks(struct dio *dio) | |||
524 | */ | 524 | */ |
525 | ret = dio->page_errors; | 525 | ret = dio->page_errors; |
526 | if (ret == 0) { | 526 | if (ret == 0) { |
527 | map_bh->b_state = 0; | ||
528 | map_bh->b_size = 0; | ||
529 | BUG_ON(dio->block_in_file >= dio->final_block_in_request); | 527 | BUG_ON(dio->block_in_file >= dio->final_block_in_request); |
530 | fs_startblk = dio->block_in_file >> dio->blkfactor; | 528 | fs_startblk = dio->block_in_file >> dio->blkfactor; |
531 | dio_count = dio->final_block_in_request - dio->block_in_file; | 529 | dio_count = dio->final_block_in_request - dio->block_in_file; |
@@ -534,6 +532,9 @@ static int get_more_blocks(struct dio *dio) | |||
534 | if (dio_count & blkmask) | 532 | if (dio_count & blkmask) |
535 | fs_count++; | 533 | fs_count++; |
536 | 534 | ||
535 | map_bh->b_state = 0; | ||
536 | map_bh->b_size = fs_count << dio->inode->i_blkbits; | ||
537 | |||
537 | create = dio->rw == WRITE; | 538 | create = dio->rw == WRITE; |
538 | if (dio->lock_type == DIO_LOCKING) { | 539 | if (dio->lock_type == DIO_LOCKING) { |
539 | if (dio->block_in_file < (i_size_read(dio->inode) >> | 540 | if (dio->block_in_file < (i_size_read(dio->inode) >> |
@@ -542,13 +543,13 @@ static int get_more_blocks(struct dio *dio) | |||
542 | } else if (dio->lock_type == DIO_NO_LOCKING) { | 543 | } else if (dio->lock_type == DIO_NO_LOCKING) { |
543 | create = 0; | 544 | create = 0; |
544 | } | 545 | } |
546 | |||
545 | /* | 547 | /* |
546 | * For writes inside i_size we forbid block creations: only | 548 | * For writes inside i_size we forbid block creations: only |
547 | * overwrites are permitted. We fall back to buffered writes | 549 | * overwrites are permitted. We fall back to buffered writes |
548 | * at a higher level for inside-i_size block-instantiating | 550 | * at a higher level for inside-i_size block-instantiating |
549 | * writes. | 551 | * writes. |
550 | */ | 552 | */ |
551 | map_bh->b_size = fs_count << dio->blkbits; | ||
552 | ret = (*dio->get_block)(dio->inode, fs_startblk, | 553 | ret = (*dio->get_block)(dio->inode, fs_startblk, |
553 | map_bh, create); | 554 | map_bh, create); |
554 | } | 555 | } |
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 777c614ff360..17f5b2d3c16a 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | static int efs_readdir(struct file *, void *, filldir_t); | 11 | static int efs_readdir(struct file *, void *, filldir_t); |
12 | 12 | ||
13 | struct file_operations efs_dir_operations = { | 13 | const struct file_operations efs_dir_operations = { |
14 | .read = generic_read_dir, | 14 | .read = generic_read_dir, |
15 | .readdir = efs_readdir, | 15 | .readdir = efs_readdir, |
16 | }; | 16 | }; |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index e067a06c6464..242fe1a66ce5 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -290,7 +290,7 @@ static kmem_cache_t *pwq_cache __read_mostly; | |||
290 | static struct vfsmount *eventpoll_mnt __read_mostly; | 290 | static struct vfsmount *eventpoll_mnt __read_mostly; |
291 | 291 | ||
292 | /* File callbacks that implement the eventpoll file behaviour */ | 292 | /* File callbacks that implement the eventpoll file behaviour */ |
293 | static struct file_operations eventpoll_fops = { | 293 | static const struct file_operations eventpoll_fops = { |
294 | .release = ep_eventpoll_close, | 294 | .release = ep_eventpoll_close, |
295 | .poll = ep_eventpoll_poll | 295 | .poll = ep_eventpoll_poll |
296 | }; | 296 | }; |
@@ -616,6 +616,15 @@ static int de_thread(struct task_struct *tsk) | |||
616 | kmem_cache_free(sighand_cachep, newsighand); | 616 | kmem_cache_free(sighand_cachep, newsighand); |
617 | return -EAGAIN; | 617 | return -EAGAIN; |
618 | } | 618 | } |
619 | |||
620 | /* | ||
621 | * child_reaper ignores SIGKILL, change it now. | ||
622 | * Reparenting needs write_lock on tasklist_lock, | ||
623 | * so it is safe to do it under read_lock. | ||
624 | */ | ||
625 | if (unlikely(current->group_leader == child_reaper)) | ||
626 | child_reaper = current; | ||
627 | |||
619 | zap_other_threads(current); | 628 | zap_other_threads(current); |
620 | read_unlock(&tasklist_lock); | 629 | read_unlock(&tasklist_lock); |
621 | 630 | ||
@@ -699,22 +708,30 @@ static int de_thread(struct task_struct *tsk) | |||
699 | remove_parent(current); | 708 | remove_parent(current); |
700 | remove_parent(leader); | 709 | remove_parent(leader); |
701 | 710 | ||
702 | switch_exec_pids(leader, current); | 711 | |
712 | /* Become a process group leader with the old leader's pid. | ||
713 | * Note: The old leader also uses thispid until release_task | ||
714 | * is called. Odd but simple and correct. | ||
715 | */ | ||
716 | detach_pid(current, PIDTYPE_PID); | ||
717 | current->pid = leader->pid; | ||
718 | attach_pid(current, PIDTYPE_PID, current->pid); | ||
719 | attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); | ||
720 | attach_pid(current, PIDTYPE_SID, current->signal->session); | ||
721 | list_add_tail(¤t->tasks, &init_task.tasks); | ||
703 | 722 | ||
704 | current->parent = current->real_parent = leader->real_parent; | 723 | current->parent = current->real_parent = leader->real_parent; |
705 | leader->parent = leader->real_parent = child_reaper; | 724 | leader->parent = leader->real_parent = child_reaper; |
706 | current->group_leader = current; | 725 | current->group_leader = current; |
707 | leader->group_leader = leader; | 726 | leader->group_leader = leader; |
708 | 727 | ||
709 | add_parent(current, current->parent); | 728 | add_parent(current); |
710 | add_parent(leader, leader->parent); | 729 | add_parent(leader); |
711 | if (ptrace) { | 730 | if (ptrace) { |
712 | current->ptrace = ptrace; | 731 | current->ptrace = ptrace; |
713 | __ptrace_link(current, parent); | 732 | __ptrace_link(current, parent); |
714 | } | 733 | } |
715 | 734 | ||
716 | list_del(¤t->tasks); | ||
717 | list_add_tail(¤t->tasks, &init_task.tasks); | ||
718 | current->exit_signal = SIGCHLD; | 735 | current->exit_signal = SIGCHLD; |
719 | 736 | ||
720 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); | 737 | BUG_ON(leader->exit_state != EXIT_ZOMBIE); |
@@ -751,7 +768,6 @@ no_thread_group: | |||
751 | /* | 768 | /* |
752 | * Move our state over to newsighand and switch it in. | 769 | * Move our state over to newsighand and switch it in. |
753 | */ | 770 | */ |
754 | spin_lock_init(&newsighand->siglock); | ||
755 | atomic_set(&newsighand->count, 1); | 771 | atomic_set(&newsighand->count, 1); |
756 | memcpy(newsighand->action, oldsighand->action, | 772 | memcpy(newsighand->action, oldsighand->action, |
757 | sizeof(newsighand->action)); | 773 | sizeof(newsighand->action)); |
@@ -768,7 +784,7 @@ no_thread_group: | |||
768 | write_unlock_irq(&tasklist_lock); | 784 | write_unlock_irq(&tasklist_lock); |
769 | 785 | ||
770 | if (atomic_dec_and_test(&oldsighand->count)) | 786 | if (atomic_dec_and_test(&oldsighand->count)) |
771 | sighand_free(oldsighand); | 787 | kmem_cache_free(sighand_cachep, oldsighand); |
772 | } | 788 | } |
773 | 789 | ||
774 | BUG_ON(!thread_group_leader(current)); | 790 | BUG_ON(!thread_group_leader(current)); |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 0165388c425c..d672aa9f4061 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -658,7 +658,7 @@ not_empty: | |||
658 | return 0; | 658 | return 0; |
659 | } | 659 | } |
660 | 660 | ||
661 | struct file_operations ext2_dir_operations = { | 661 | const struct file_operations ext2_dir_operations = { |
662 | .llseek = generic_file_llseek, | 662 | .llseek = generic_file_llseek, |
663 | .read = generic_read_dir, | 663 | .read = generic_read_dir, |
664 | .readdir = ext2_readdir, | 664 | .readdir = ext2_readdir, |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 11035ac7986f..9f74a62be555 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -154,12 +154,12 @@ extern void ext2_write_super (struct super_block *); | |||
154 | */ | 154 | */ |
155 | 155 | ||
156 | /* dir.c */ | 156 | /* dir.c */ |
157 | extern struct file_operations ext2_dir_operations; | 157 | extern const struct file_operations ext2_dir_operations; |
158 | 158 | ||
159 | /* file.c */ | 159 | /* file.c */ |
160 | extern struct inode_operations ext2_file_inode_operations; | 160 | extern struct inode_operations ext2_file_inode_operations; |
161 | extern struct file_operations ext2_file_operations; | 161 | extern const struct file_operations ext2_file_operations; |
162 | extern struct file_operations ext2_xip_file_operations; | 162 | extern const struct file_operations ext2_xip_file_operations; |
163 | 163 | ||
164 | /* inode.c */ | 164 | /* inode.c */ |
165 | extern struct address_space_operations ext2_aops; | 165 | extern struct address_space_operations ext2_aops; |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index a484412fc782..23e2c7ccec1d 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
@@ -39,7 +39,7 @@ static int ext2_release_file (struct inode * inode, struct file * filp) | |||
39 | * We have mostly NULL's here: the current defaults are ok for | 39 | * We have mostly NULL's here: the current defaults are ok for |
40 | * the ext2 filesystem. | 40 | * the ext2 filesystem. |
41 | */ | 41 | */ |
42 | struct file_operations ext2_file_operations = { | 42 | const struct file_operations ext2_file_operations = { |
43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
44 | .read = generic_file_read, | 44 | .read = generic_file_read, |
45 | .write = generic_file_write, | 45 | .write = generic_file_write, |
@@ -53,10 +53,12 @@ struct file_operations ext2_file_operations = { | |||
53 | .readv = generic_file_readv, | 53 | .readv = generic_file_readv, |
54 | .writev = generic_file_writev, | 54 | .writev = generic_file_writev, |
55 | .sendfile = generic_file_sendfile, | 55 | .sendfile = generic_file_sendfile, |
56 | .splice_read = generic_file_splice_read, | ||
57 | .splice_write = generic_file_splice_write, | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | #ifdef CONFIG_EXT2_FS_XIP | 60 | #ifdef CONFIG_EXT2_FS_XIP |
59 | struct file_operations ext2_xip_file_operations = { | 61 | const struct file_operations ext2_xip_file_operations = { |
60 | .llseek = generic_file_llseek, | 62 | .llseek = generic_file_llseek, |
61 | .read = xip_file_read, | 63 | .read = xip_file_read, |
62 | .write = xip_file_write, | 64 | .write = xip_file_write, |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 38bd3f6ec147..f37528ed222e 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
39 | static int ext3_release_dir (struct inode * inode, | 39 | static int ext3_release_dir (struct inode * inode, |
40 | struct file * filp); | 40 | struct file * filp); |
41 | 41 | ||
42 | struct file_operations ext3_dir_operations = { | 42 | const struct file_operations ext3_dir_operations = { |
43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
44 | .read = generic_read_dir, | 44 | .read = generic_read_dir, |
45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ | 45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ |
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 59098ea56711..1efefb630ea9 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
@@ -105,7 +105,7 @@ force_commit: | |||
105 | return ret; | 105 | return ret; |
106 | } | 106 | } |
107 | 107 | ||
108 | struct file_operations ext3_file_operations = { | 108 | const struct file_operations ext3_file_operations = { |
109 | .llseek = generic_file_llseek, | 109 | .llseek = generic_file_llseek, |
110 | .read = do_sync_read, | 110 | .read = do_sync_read, |
111 | .write = do_sync_write, | 111 | .write = do_sync_write, |
@@ -119,6 +119,8 @@ struct file_operations ext3_file_operations = { | |||
119 | .release = ext3_release_file, | 119 | .release = ext3_release_file, |
120 | .fsync = ext3_sync_file, | 120 | .fsync = ext3_sync_file, |
121 | .sendfile = generic_file_sendfile, | 121 | .sendfile = generic_file_sendfile, |
122 | .splice_read = generic_file_splice_read, | ||
123 | .splice_write = generic_file_splice_write, | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | struct inode_operations ext3_file_inode_operations = { | 126 | struct inode_operations ext3_file_inode_operations = { |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 4095bc149eb1..698b85bb1dd4 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -741,7 +741,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, | |||
741 | return ret; | 741 | return ret; |
742 | } | 742 | } |
743 | 743 | ||
744 | struct file_operations fat_dir_operations = { | 744 | const struct file_operations fat_dir_operations = { |
745 | .read = generic_read_dir, | 745 | .read = generic_read_dir, |
746 | .readdir = fat_readdir, | 746 | .readdir = fat_readdir, |
747 | .ioctl = fat_dir_ioctl, | 747 | .ioctl = fat_dir_ioctl, |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 88aa1ae13f9f..1ee25232e6af 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -112,7 +112,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | struct file_operations fat_file_operations = { | 115 | const struct file_operations fat_file_operations = { |
116 | .llseek = generic_file_llseek, | 116 | .llseek = generic_file_llseek, |
117 | .read = do_sync_read, | 117 | .read = do_sync_read, |
118 | .write = do_sync_write, | 118 | .write = do_sync_write, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 404bfc9f7385..c1ce284f8a94 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -1435,9 +1435,6 @@ out_fail: | |||
1435 | 1435 | ||
1436 | EXPORT_SYMBOL_GPL(fat_fill_super); | 1436 | EXPORT_SYMBOL_GPL(fat_fill_super); |
1437 | 1437 | ||
1438 | int __init fat_cache_init(void); | ||
1439 | void fat_cache_destroy(void); | ||
1440 | |||
1441 | static int __init init_fat_fs(void) | 1438 | static int __init init_fat_fs(void) |
1442 | { | 1439 | { |
1443 | int err; | 1440 | int err; |
@@ -145,6 +145,6 @@ err_nocleanup: | |||
145 | * is contain the open that then fills in the correct operations | 145 | * is contain the open that then fills in the correct operations |
146 | * depending on the access mode of the file... | 146 | * depending on the access mode of the file... |
147 | */ | 147 | */ |
148 | struct file_operations def_fifo_fops = { | 148 | const struct file_operations def_fifo_fops = { |
149 | .open = fifo_open, /* will set read or write pipe_fops */ | 149 | .open = fifo_open, /* will set read or write pipe_fops */ |
150 | }; | 150 | }; |
@@ -373,6 +373,6 @@ static void __devinit fdtable_defer_list_init(int cpu) | |||
373 | void __init files_defer_init(void) | 373 | void __init files_defer_init(void) |
374 | { | 374 | { |
375 | int i; | 375 | int i; |
376 | for_each_cpu(i) | 376 | for_each_possible_cpu(i) |
377 | fdtable_defer_list_init(i); | 377 | fdtable_defer_list_init(i); |
378 | } | 378 | } |
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 927acf70c591..1cf1fe8466a2 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h | |||
@@ -63,7 +63,7 @@ extern void vxfs_clear_inode(struct inode *); | |||
63 | 63 | ||
64 | /* vxfs_lookup.c */ | 64 | /* vxfs_lookup.c */ |
65 | extern struct inode_operations vxfs_dir_inode_ops; | 65 | extern struct inode_operations vxfs_dir_inode_ops; |
66 | extern struct file_operations vxfs_dir_operations; | 66 | extern const struct file_operations vxfs_dir_operations; |
67 | 67 | ||
68 | /* vxfs_olt.c */ | 68 | /* vxfs_olt.c */ |
69 | extern int vxfs_read_olt(struct super_block *, u_long); | 69 | extern int vxfs_read_olt(struct super_block *, u_long); |
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 554eb455722c..29cce456c7ce 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c | |||
@@ -56,7 +56,7 @@ struct inode_operations vxfs_dir_inode_ops = { | |||
56 | .lookup = vxfs_lookup, | 56 | .lookup = vxfs_lookup, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | struct file_operations vxfs_dir_operations = { | 59 | const struct file_operations vxfs_dir_operations = { |
60 | .readdir = vxfs_readdir, | 60 | .readdir = vxfs_readdir, |
61 | }; | 61 | }; |
62 | 62 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0c9a2ee54c91..23d1f52eb1b8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -922,7 +922,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file) | |||
922 | return 0; | 922 | return 0; |
923 | } | 923 | } |
924 | 924 | ||
925 | struct file_operations fuse_dev_operations = { | 925 | const struct file_operations fuse_dev_operations = { |
926 | .owner = THIS_MODULE, | 926 | .owner = THIS_MODULE, |
927 | .llseek = no_llseek, | 927 | .llseek = no_llseek, |
928 | .read = fuse_dev_read, | 928 | .read = fuse_dev_read, |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c72a8a97935c..256355b80256 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1170,7 +1170,7 @@ static struct inode_operations fuse_dir_inode_operations = { | |||
1170 | .removexattr = fuse_removexattr, | 1170 | .removexattr = fuse_removexattr, |
1171 | }; | 1171 | }; |
1172 | 1172 | ||
1173 | static struct file_operations fuse_dir_operations = { | 1173 | static const struct file_operations fuse_dir_operations = { |
1174 | .llseek = generic_file_llseek, | 1174 | .llseek = generic_file_llseek, |
1175 | .read = generic_read_dir, | 1175 | .read = generic_read_dir, |
1176 | .readdir = fuse_readdir, | 1176 | .readdir = fuse_readdir, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6f05379b0a0d..975f2697e866 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | 14 | ||
15 | static struct file_operations fuse_direct_io_file_operations; | 15 | static const struct file_operations fuse_direct_io_file_operations; |
16 | 16 | ||
17 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | 17 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, |
18 | struct fuse_open_out *outargp) | 18 | struct fuse_open_out *outargp) |
@@ -611,7 +611,7 @@ static int fuse_set_page_dirty(struct page *page) | |||
611 | return 0; | 611 | return 0; |
612 | } | 612 | } |
613 | 613 | ||
614 | static struct file_operations fuse_file_operations = { | 614 | static const struct file_operations fuse_file_operations = { |
615 | .llseek = generic_file_llseek, | 615 | .llseek = generic_file_llseek, |
616 | .read = generic_file_read, | 616 | .read = generic_file_read, |
617 | .write = generic_file_write, | 617 | .write = generic_file_write, |
@@ -623,7 +623,7 @@ static struct file_operations fuse_file_operations = { | |||
623 | .sendfile = generic_file_sendfile, | 623 | .sendfile = generic_file_sendfile, |
624 | }; | 624 | }; |
625 | 625 | ||
626 | static struct file_operations fuse_direct_io_file_operations = { | 626 | static const struct file_operations fuse_direct_io_file_operations = { |
627 | .llseek = generic_file_llseek, | 627 | .llseek = generic_file_llseek, |
628 | .read = fuse_direct_read, | 628 | .read = fuse_direct_read, |
629 | .write = fuse_direct_write, | 629 | .write = fuse_direct_write, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 4a83adfec968..a16a04fcf41e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -346,7 +346,7 @@ static inline u64 get_node_id(struct inode *inode) | |||
346 | } | 346 | } |
347 | 347 | ||
348 | /** Device operations */ | 348 | /** Device operations */ |
349 | extern struct file_operations fuse_dev_operations; | 349 | extern const struct file_operations fuse_dev_operations; |
350 | 350 | ||
351 | /** | 351 | /** |
352 | * This is the single global spinlock which protects FUSE's structures | 352 | * This is the single global spinlock which protects FUSE's structures |
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 534e5a7480ef..7cd8cc03aea7 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -313,7 +313,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
313 | return res; | 313 | return res; |
314 | } | 314 | } |
315 | 315 | ||
316 | struct file_operations hfs_dir_operations = { | 316 | const struct file_operations hfs_dir_operations = { |
317 | .read = generic_read_dir, | 317 | .read = generic_read_dir, |
318 | .readdir = hfs_readdir, | 318 | .readdir = hfs_readdir, |
319 | .llseek = generic_file_llseek, | 319 | .llseek = generic_file_llseek, |
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 18ce47ab1b71..3ed8663a8db1 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h | |||
@@ -169,7 +169,7 @@ extern int hfs_cat_move(u32, struct inode *, struct qstr *, | |||
169 | extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *); | 169 | extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *); |
170 | 170 | ||
171 | /* dir.c */ | 171 | /* dir.c */ |
172 | extern struct file_operations hfs_dir_operations; | 172 | extern const struct file_operations hfs_dir_operations; |
173 | extern struct inode_operations hfs_dir_inode_operations; | 173 | extern struct inode_operations hfs_dir_inode_operations; |
174 | 174 | ||
175 | /* extent.c */ | 175 | /* extent.c */ |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 2c564701724f..2d4ced22201b 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "hfs_fs.h" | 17 | #include "hfs_fs.h" |
18 | #include "btree.h" | 18 | #include "btree.h" |
19 | 19 | ||
20 | static struct file_operations hfs_file_operations; | 20 | static const struct file_operations hfs_file_operations; |
21 | static struct inode_operations hfs_file_inode_operations; | 21 | static struct inode_operations hfs_file_inode_operations; |
22 | 22 | ||
23 | /*================ Variable-like macros ================*/ | 23 | /*================ Variable-like macros ================*/ |
@@ -601,7 +601,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) | |||
601 | } | 601 | } |
602 | 602 | ||
603 | 603 | ||
604 | static struct file_operations hfs_file_operations = { | 604 | static const struct file_operations hfs_file_operations = { |
605 | .llseek = generic_file_llseek, | 605 | .llseek = generic_file_llseek, |
606 | .read = generic_file_read, | 606 | .read = generic_file_read, |
607 | .write = generic_file_write, | 607 | .write = generic_file_write, |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 01a6fe3a395c..1f9ece0de326 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -483,7 +483,7 @@ struct inode_operations hfsplus_dir_inode_operations = { | |||
483 | .rename = hfsplus_rename, | 483 | .rename = hfsplus_rename, |
484 | }; | 484 | }; |
485 | 485 | ||
486 | struct file_operations hfsplus_dir_operations = { | 486 | const struct file_operations hfsplus_dir_operations = { |
487 | .read = generic_read_dir, | 487 | .read = generic_read_dir, |
488 | .readdir = hfsplus_readdir, | 488 | .readdir = hfsplus_readdir, |
489 | .ioctl = hfsplus_ioctl, | 489 | .ioctl = hfsplus_ioctl, |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9fbe4d2aeece..acf66dba3e01 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -280,7 +280,7 @@ static struct inode_operations hfsplus_file_inode_operations = { | |||
280 | .listxattr = hfsplus_listxattr, | 280 | .listxattr = hfsplus_listxattr, |
281 | }; | 281 | }; |
282 | 282 | ||
283 | static struct file_operations hfsplus_file_operations = { | 283 | static const struct file_operations hfsplus_file_operations = { |
284 | .llseek = generic_file_llseek, | 284 | .llseek = generic_file_llseek, |
285 | .read = generic_file_read, | 285 | .read = generic_file_read, |
286 | .write = generic_file_write, | 286 | .write = generic_file_write, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index b3ad0bd0312f..bf0f8e16e433 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -384,7 +384,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
384 | return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); | 384 | return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); |
385 | } | 385 | } |
386 | 386 | ||
387 | static struct file_operations hostfs_file_fops = { | 387 | static const struct file_operations hostfs_file_fops = { |
388 | .llseek = generic_file_llseek, | 388 | .llseek = generic_file_llseek, |
389 | .read = generic_file_read, | 389 | .read = generic_file_read, |
390 | .sendfile = generic_file_sendfile, | 390 | .sendfile = generic_file_sendfile, |
@@ -399,7 +399,7 @@ static struct file_operations hostfs_file_fops = { | |||
399 | .fsync = hostfs_fsync, | 399 | .fsync = hostfs_fsync, |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static struct file_operations hostfs_dir_fops = { | 402 | static const struct file_operations hostfs_dir_fops = { |
403 | .llseek = generic_file_llseek, | 403 | .llseek = generic_file_llseek, |
404 | .readdir = hostfs_readdir, | 404 | .readdir = hostfs_readdir, |
405 | .read = generic_read_dir, | 405 | .read = generic_read_dir, |
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index b97809deba66..23b7cee72123 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c | |||
@@ -360,7 +360,6 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out, | |||
360 | spare_out[2] = buf.f_spare[2]; | 360 | spare_out[2] = buf.f_spare[2]; |
361 | spare_out[3] = buf.f_spare[3]; | 361 | spare_out[3] = buf.f_spare[3]; |
362 | spare_out[4] = buf.f_spare[4]; | 362 | spare_out[4] = buf.f_spare[4]; |
363 | spare_out[5] = buf.f_spare[5]; | ||
364 | return(0); | 363 | return(0); |
365 | } | 364 | } |
366 | 365 | ||
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 5591f9623aa2..ecc9180645ae 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
@@ -310,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
310 | return ERR_PTR(-ENOENT); | 310 | return ERR_PTR(-ENOENT); |
311 | } | 311 | } |
312 | 312 | ||
313 | struct file_operations hpfs_dir_ops = | 313 | const struct file_operations hpfs_dir_ops = |
314 | { | 314 | { |
315 | .llseek = hpfs_dir_lseek, | 315 | .llseek = hpfs_dir_lseek, |
316 | .read = generic_read_dir, | 316 | .read = generic_read_dir, |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 7c995ac4081b..d3b9fffe45a1 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -119,7 +119,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, | |||
119 | return retval; | 119 | return retval; |
120 | } | 120 | } |
121 | 121 | ||
122 | struct file_operations hpfs_file_ops = | 122 | const struct file_operations hpfs_file_ops = |
123 | { | 123 | { |
124 | .llseek = generic_file_llseek, | 124 | .llseek = generic_file_llseek, |
125 | .read = generic_file_read, | 125 | .read = generic_file_read, |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 4c6473ab3b34..29b7a3e55173 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -240,7 +240,7 @@ void hpfs_set_dentry_operations(struct dentry *); | |||
240 | /* dir.c */ | 240 | /* dir.c */ |
241 | 241 | ||
242 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 242 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
243 | extern struct file_operations hpfs_dir_ops; | 243 | extern const struct file_operations hpfs_dir_ops; |
244 | 244 | ||
245 | /* dnode.c */ | 245 | /* dnode.c */ |
246 | 246 | ||
@@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); | |||
266 | /* file.c */ | 266 | /* file.c */ |
267 | 267 | ||
268 | int hpfs_file_fsync(struct file *, struct dentry *, int); | 268 | int hpfs_file_fsync(struct file *, struct dentry *, int); |
269 | extern struct file_operations hpfs_file_ops; | 269 | extern const struct file_operations hpfs_file_ops; |
270 | extern struct inode_operations hpfs_file_iops; | 270 | extern struct inode_operations hpfs_file_iops; |
271 | extern struct address_space_operations hpfs_aops; | 271 | extern struct address_space_operations hpfs_aops; |
272 | 272 | ||
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index a44dc5897399..2ba20cdb5baa 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
@@ -558,7 +558,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) | |||
558 | return(default_llseek(file, off, where)); | 558 | return(default_llseek(file, off, where)); |
559 | } | 559 | } |
560 | 560 | ||
561 | static struct file_operations hppfs_file_fops = { | 561 | static const struct file_operations hppfs_file_fops = { |
562 | .owner = NULL, | 562 | .owner = NULL, |
563 | .llseek = hppfs_llseek, | 563 | .llseek = hppfs_llseek, |
564 | .read = hppfs_read, | 564 | .read = hppfs_read, |
@@ -609,7 +609,7 @@ static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
609 | return(0); | 609 | return(0); |
610 | } | 610 | } |
611 | 611 | ||
612 | static struct file_operations hppfs_dir_fops = { | 612 | static const struct file_operations hppfs_dir_fops = { |
613 | .owner = NULL, | 613 | .owner = NULL, |
614 | .readdir = hppfs_readdir, | 614 | .readdir = hppfs_readdir, |
615 | .open = hppfs_dir_open, | 615 | .open = hppfs_dir_open, |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 25fa8bba8cb5..3a5b4e923455 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | static struct super_operations hugetlbfs_ops; | 36 | static struct super_operations hugetlbfs_ops; |
37 | static struct address_space_operations hugetlbfs_aops; | 37 | static struct address_space_operations hugetlbfs_aops; |
38 | struct file_operations hugetlbfs_file_operations; | 38 | const struct file_operations hugetlbfs_file_operations; |
39 | static struct inode_operations hugetlbfs_dir_inode_operations; | 39 | static struct inode_operations hugetlbfs_dir_inode_operations; |
40 | static struct inode_operations hugetlbfs_inode_operations; | 40 | static struct inode_operations hugetlbfs_inode_operations; |
41 | 41 | ||
@@ -566,7 +566,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | |||
566 | inode_init_once(&ei->vfs_inode); | 566 | inode_init_once(&ei->vfs_inode); |
567 | } | 567 | } |
568 | 568 | ||
569 | struct file_operations hugetlbfs_file_operations = { | 569 | const struct file_operations hugetlbfs_file_operations = { |
570 | .mmap = hugetlbfs_file_mmap, | 570 | .mmap = hugetlbfs_file_mmap, |
571 | .fsync = simple_sync_file, | 571 | .fsync = simple_sync_file, |
572 | .get_unmapped_area = hugetlb_get_unmapped_area, | 572 | .get_unmapped_area = hugetlb_get_unmapped_area, |
diff --git a/fs/inode.c b/fs/inode.c index 1fddf2803af8..32b7c3375021 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -104,7 +104,7 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
104 | { | 104 | { |
105 | static struct address_space_operations empty_aops; | 105 | static struct address_space_operations empty_aops; |
106 | static struct inode_operations empty_iops; | 106 | static struct inode_operations empty_iops; |
107 | static struct file_operations empty_fops; | 107 | static const struct file_operations empty_fops; |
108 | struct inode *inode; | 108 | struct inode *inode; |
109 | 109 | ||
110 | if (sb->s_op->alloc_inode) | 110 | if (sb->s_op->alloc_inode) |
diff --git a/fs/inotify.c b/fs/inotify.c index f48a3dae0712..367c487c014b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -920,7 +920,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, | |||
920 | return ret; | 920 | return ret; |
921 | } | 921 | } |
922 | 922 | ||
923 | static struct file_operations inotify_fops = { | 923 | static const struct file_operations inotify_fops = { |
924 | .poll = inotify_poll, | 924 | .poll = inotify_poll, |
925 | .read = inotify_read, | 925 | .read = inotify_read, |
926 | .release = inotify_release, | 926 | .release = inotify_release, |
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 7901ac9f97ab..5440ea292c69 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | static int isofs_readdir(struct file *, void *, filldir_t); | 17 | static int isofs_readdir(struct file *, void *, filldir_t); |
18 | 18 | ||
19 | struct file_operations isofs_dir_operations = | 19 | const struct file_operations isofs_dir_operations = |
20 | { | 20 | { |
21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
22 | .readdir = isofs_readdir, | 22 | .readdir = isofs_readdir, |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 439a19b1bf3e..b87ba066f5e7 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
@@ -175,6 +175,6 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | extern struct inode_operations isofs_dir_inode_operations; | 177 | extern struct inode_operations isofs_dir_inode_operations; |
178 | extern struct file_operations isofs_dir_operations; | 178 | extern const struct file_operations isofs_dir_operations; |
179 | extern struct address_space_operations isofs_symlink_aops; | 179 | extern struct address_space_operations isofs_symlink_aops; |
180 | extern struct export_operations isofs_export_ops; | 180 | extern struct export_operations isofs_export_ops; |
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 5a4519e834da..020cc097c539 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c | |||
@@ -55,9 +55,9 @@ | |||
55 | static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); | 55 | static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); |
56 | 56 | ||
57 | static struct super_operations jffs_ops; | 57 | static struct super_operations jffs_ops; |
58 | static struct file_operations jffs_file_operations; | 58 | static const struct file_operations jffs_file_operations; |
59 | static struct inode_operations jffs_file_inode_operations; | 59 | static struct inode_operations jffs_file_inode_operations; |
60 | static struct file_operations jffs_dir_operations; | 60 | static const struct file_operations jffs_dir_operations; |
61 | static struct inode_operations jffs_dir_inode_operations; | 61 | static struct inode_operations jffs_dir_inode_operations; |
62 | static struct address_space_operations jffs_address_operations; | 62 | static struct address_space_operations jffs_address_operations; |
63 | 63 | ||
@@ -1629,7 +1629,7 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync) | |||
1629 | } | 1629 | } |
1630 | 1630 | ||
1631 | 1631 | ||
1632 | static struct file_operations jffs_file_operations = | 1632 | static const struct file_operations jffs_file_operations = |
1633 | { | 1633 | { |
1634 | .open = generic_file_open, | 1634 | .open = generic_file_open, |
1635 | .llseek = generic_file_llseek, | 1635 | .llseek = generic_file_llseek, |
@@ -1649,7 +1649,7 @@ static struct inode_operations jffs_file_inode_operations = | |||
1649 | }; | 1649 | }; |
1650 | 1650 | ||
1651 | 1651 | ||
1652 | static struct file_operations jffs_dir_operations = | 1652 | static const struct file_operations jffs_dir_operations = |
1653 | { | 1653 | { |
1654 | .readdir = jffs_readdir, | 1654 | .readdir = jffs_readdir, |
1655 | }; | 1655 | }; |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index a7bf9cb2567f..8bc7a5018e40 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -37,7 +37,7 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); | |||
37 | static int jffs2_rename (struct inode *, struct dentry *, | 37 | static int jffs2_rename (struct inode *, struct dentry *, |
38 | struct inode *, struct dentry *); | 38 | struct inode *, struct dentry *); |
39 | 39 | ||
40 | struct file_operations jffs2_dir_operations = | 40 | const struct file_operations jffs2_dir_operations = |
41 | { | 41 | { |
42 | .read = generic_read_dir, | 42 | .read = generic_read_dir, |
43 | .readdir = jffs2_readdir, | 43 | .readdir = jffs2_readdir, |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 935f273dc57b..9f4171213e58 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -38,7 +38,7 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) | |||
38 | return 0; | 38 | return 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | struct file_operations jffs2_file_operations = | 41 | const struct file_operations jffs2_file_operations = |
42 | { | 42 | { |
43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
44 | .open = generic_file_open, | 44 | .open = generic_file_open, |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 59e7a393200c..d307cf548625 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -159,11 +159,11 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); | |||
159 | void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); | 159 | void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); |
160 | 160 | ||
161 | /* dir.c */ | 161 | /* dir.c */ |
162 | extern struct file_operations jffs2_dir_operations; | 162 | extern const struct file_operations jffs2_dir_operations; |
163 | extern struct inode_operations jffs2_dir_inode_operations; | 163 | extern struct inode_operations jffs2_dir_inode_operations; |
164 | 164 | ||
165 | /* file.c */ | 165 | /* file.c */ |
166 | extern struct file_operations jffs2_file_operations; | 166 | extern const struct file_operations jffs2_file_operations; |
167 | extern struct inode_operations jffs2_file_inode_operations; | 167 | extern struct inode_operations jffs2_file_inode_operations; |
168 | extern struct address_space_operations jffs2_file_address_operations; | 168 | extern struct address_space_operations jffs2_file_address_operations; |
169 | int jffs2_fsync(struct file *, struct dentry *, int); | 169 | int jffs2_fsync(struct file *, struct dentry *, int); |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index e1ac6e497e2b..1c9745be5ada 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
@@ -100,7 +100,7 @@ struct inode_operations jfs_file_inode_operations = { | |||
100 | #endif | 100 | #endif |
101 | }; | 101 | }; |
102 | 102 | ||
103 | struct file_operations jfs_file_operations = { | 103 | const struct file_operations jfs_file_operations = { |
104 | .open = jfs_open, | 104 | .open = jfs_open, |
105 | .llseek = generic_file_llseek, | 105 | .llseek = generic_file_llseek, |
106 | .write = generic_file_write, | 106 | .write = generic_file_write, |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 095d471b9f9a..c30072674464 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
@@ -35,9 +35,9 @@ extern void jfs_set_inode_flags(struct inode *); | |||
35 | 35 | ||
36 | extern struct address_space_operations jfs_aops; | 36 | extern struct address_space_operations jfs_aops; |
37 | extern struct inode_operations jfs_dir_inode_operations; | 37 | extern struct inode_operations jfs_dir_inode_operations; |
38 | extern struct file_operations jfs_dir_operations; | 38 | extern const struct file_operations jfs_dir_operations; |
39 | extern struct inode_operations jfs_file_inode_operations; | 39 | extern struct inode_operations jfs_file_inode_operations; |
40 | extern struct file_operations jfs_file_operations; | 40 | extern const struct file_operations jfs_file_operations; |
41 | extern struct inode_operations jfs_symlink_inode_operations; | 41 | extern struct inode_operations jfs_symlink_inode_operations; |
42 | extern struct dentry_operations jfs_ci_dentry_operations; | 42 | extern struct dentry_operations jfs_ci_dentry_operations; |
43 | #endif /* _H_JFS_INODE */ | 43 | #endif /* _H_JFS_INODE */ |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 309cee575f7d..09ea03f62277 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -1519,7 +1519,7 @@ struct inode_operations jfs_dir_inode_operations = { | |||
1519 | #endif | 1519 | #endif |
1520 | }; | 1520 | }; |
1521 | 1521 | ||
1522 | struct file_operations jfs_dir_operations = { | 1522 | const struct file_operations jfs_dir_operations = { |
1523 | .read = generic_read_dir, | 1523 | .read = generic_read_dir, |
1524 | .readdir = jfs_readdir, | 1524 | .readdir = jfs_readdir, |
1525 | .fsync = jfs_fsync, | 1525 | .fsync = jfs_fsync, |
diff --git a/fs/libfs.c b/fs/libfs.c index 4fdeaceb892c..7145ba7a48d0 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -179,7 +179,7 @@ ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t | |||
179 | return -EISDIR; | 179 | return -EISDIR; |
180 | } | 180 | } |
181 | 181 | ||
182 | struct file_operations simple_dir_operations = { | 182 | const struct file_operations simple_dir_operations = { |
183 | .open = dcache_dir_open, | 183 | .open = dcache_dir_open, |
184 | .release = dcache_dir_close, | 184 | .release = dcache_dir_close, |
185 | .llseek = dcache_dir_lseek, | 185 | .llseek = dcache_dir_lseek, |
diff --git a/fs/mbcache.c b/fs/mbcache.c index 73e754fea2d8..e4fde1ab22cd 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -311,7 +311,7 @@ fail: | |||
311 | /* | 311 | /* |
312 | * mb_cache_shrink() | 312 | * mb_cache_shrink() |
313 | * | 313 | * |
314 | * Removes all cache entires of a device from the cache. All cache entries | 314 | * Removes all cache entries of a device from the cache. All cache entries |
315 | * currently in use cannot be freed, and thus remain in the cache. All others | 315 | * currently in use cannot be freed, and thus remain in the cache. All others |
316 | * are freed. | 316 | * are freed. |
317 | * | 317 | * |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 732502aabc05..69224d1fe043 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -14,7 +14,7 @@ typedef struct minix_dir_entry minix_dirent; | |||
14 | 14 | ||
15 | static int minix_readdir(struct file *, void *, filldir_t); | 15 | static int minix_readdir(struct file *, void *, filldir_t); |
16 | 16 | ||
17 | struct file_operations minix_dir_operations = { | 17 | const struct file_operations minix_dir_operations = { |
18 | .read = generic_read_dir, | 18 | .read = generic_read_dir, |
19 | .readdir = minix_readdir, | 19 | .readdir = minix_readdir, |
20 | .fsync = minix_sync_file, | 20 | .fsync = minix_sync_file, |
diff --git a/fs/minix/file.c b/fs/minix/file.c index f1d77acb3f01..420b32882a10 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c | |||
@@ -15,7 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | int minix_sync_file(struct file *, struct dentry *, int); | 16 | int minix_sync_file(struct file *, struct dentry *, int); |
17 | 17 | ||
18 | struct file_operations minix_file_operations = { | 18 | const struct file_operations minix_file_operations = { |
19 | .llseek = generic_file_llseek, | 19 | .llseek = generic_file_llseek, |
20 | .read = generic_file_read, | 20 | .read = generic_file_read, |
21 | .write = generic_file_write, | 21 | .write = generic_file_write, |
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index e42a8bb89001..c55b77cdcc8e 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
@@ -81,8 +81,8 @@ extern int minix_sync_file(struct file *, struct dentry *, int); | |||
81 | 81 | ||
82 | extern struct inode_operations minix_file_inode_operations; | 82 | extern struct inode_operations minix_file_inode_operations; |
83 | extern struct inode_operations minix_dir_inode_operations; | 83 | extern struct inode_operations minix_dir_inode_operations; |
84 | extern struct file_operations minix_file_operations; | 84 | extern const struct file_operations minix_file_operations; |
85 | extern struct file_operations minix_dir_operations; | 85 | extern const struct file_operations minix_dir_operations; |
86 | extern struct dentry_operations minix_dentry_operations; | 86 | extern struct dentry_operations minix_dentry_operations; |
87 | 87 | ||
88 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) | 88 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) |
diff --git a/fs/namei.c b/fs/namei.c index 98dc2e134362..22f6e8d16aa8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -546,6 +546,22 @@ struct path { | |||
546 | struct dentry *dentry; | 546 | struct dentry *dentry; |
547 | }; | 547 | }; |
548 | 548 | ||
549 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
550 | { | ||
551 | dput(path->dentry); | ||
552 | if (path->mnt != nd->mnt) | ||
553 | mntput(path->mnt); | ||
554 | } | ||
555 | |||
556 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
557 | { | ||
558 | dput(nd->dentry); | ||
559 | if (nd->mnt != path->mnt) | ||
560 | mntput(nd->mnt); | ||
561 | nd->mnt = path->mnt; | ||
562 | nd->dentry = path->dentry; | ||
563 | } | ||
564 | |||
549 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) | 565 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
550 | { | 566 | { |
551 | int error; | 567 | int error; |
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
555 | touch_atime(path->mnt, dentry); | 571 | touch_atime(path->mnt, dentry); |
556 | nd_set_link(nd, NULL); | 572 | nd_set_link(nd, NULL); |
557 | 573 | ||
558 | if (path->mnt == nd->mnt) | 574 | if (path->mnt != nd->mnt) { |
559 | mntget(path->mnt); | 575 | path_to_nameidata(path, nd); |
576 | dget(dentry); | ||
577 | } | ||
578 | mntget(path->mnt); | ||
560 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); | 579 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); |
561 | error = PTR_ERR(cookie); | 580 | error = PTR_ERR(cookie); |
562 | if (!IS_ERR(cookie)) { | 581 | if (!IS_ERR(cookie)) { |
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
573 | return error; | 592 | return error; |
574 | } | 593 | } |
575 | 594 | ||
576 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
577 | { | ||
578 | dput(path->dentry); | ||
579 | if (path->mnt != nd->mnt) | ||
580 | mntput(path->mnt); | ||
581 | } | ||
582 | |||
583 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
584 | { | ||
585 | dput(nd->dentry); | ||
586 | if (nd->mnt != path->mnt) | ||
587 | mntput(nd->mnt); | ||
588 | nd->mnt = path->mnt; | ||
589 | nd->dentry = path->dentry; | ||
590 | } | ||
591 | |||
592 | /* | 595 | /* |
593 | * This limits recursive symlink follows to 8, while | 596 | * This limits recursive symlink follows to 8, while |
594 | * limiting consecutive symlinks to 40. | 597 | * limiting consecutive symlinks to 40. |
diff --git a/fs/namespace.c b/fs/namespace.c index e069a4c5e389..bf478addb852 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -459,9 +459,9 @@ int may_umount_tree(struct vfsmount *mnt) | |||
459 | spin_unlock(&vfsmount_lock); | 459 | spin_unlock(&vfsmount_lock); |
460 | 460 | ||
461 | if (actual_refs > minimum_refs) | 461 | if (actual_refs > minimum_refs) |
462 | return -EBUSY; | 462 | return 0; |
463 | 463 | ||
464 | return 0; | 464 | return 1; |
465 | } | 465 | } |
466 | 466 | ||
467 | EXPORT_SYMBOL(may_umount_tree); | 467 | EXPORT_SYMBOL(may_umount_tree); |
@@ -481,10 +481,10 @@ EXPORT_SYMBOL(may_umount_tree); | |||
481 | */ | 481 | */ |
482 | int may_umount(struct vfsmount *mnt) | 482 | int may_umount(struct vfsmount *mnt) |
483 | { | 483 | { |
484 | int ret = 0; | 484 | int ret = 1; |
485 | spin_lock(&vfsmount_lock); | 485 | spin_lock(&vfsmount_lock); |
486 | if (propagate_mount_busy(mnt, 2)) | 486 | if (propagate_mount_busy(mnt, 2)) |
487 | ret = -EBUSY; | 487 | ret = 0; |
488 | spin_unlock(&vfsmount_lock); | 488 | spin_unlock(&vfsmount_lock); |
489 | return ret; | 489 | return ret; |
490 | } | 490 | } |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index cfd76f431dc0..f0860c602d8b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -49,7 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *); | |||
49 | #define ncp_symlink NULL | 49 | #define ncp_symlink NULL |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | struct file_operations ncp_dir_operations = | 52 | const struct file_operations ncp_dir_operations = |
53 | { | 53 | { |
54 | .read = generic_read_dir, | 54 | .read = generic_read_dir, |
55 | .readdir = ncp_readdir, | 55 | .readdir = ncp_readdir, |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index ebdad8f6398f..e6b7c67cf057 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -283,7 +283,7 @@ static int ncp_release(struct inode *inode, struct file *file) { | |||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | struct file_operations ncp_file_operations = | 286 | const struct file_operations ncp_file_operations = |
287 | { | 287 | { |
288 | .llseek = remote_llseek, | 288 | .llseek = remote_llseek, |
289 | .read = ncp_file_read, | 289 | .read = ncp_file_read, |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 06c48b385c94..a23f34894167 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -54,7 +54,7 @@ static int nfs_rename(struct inode *, struct dentry *, | |||
54 | static int nfs_fsync_dir(struct file *, struct dentry *, int); | 54 | static int nfs_fsync_dir(struct file *, struct dentry *, int); |
55 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 55 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
56 | 56 | ||
57 | struct file_operations nfs_dir_operations = { | 57 | const struct file_operations nfs_dir_operations = { |
58 | .llseek = nfs_llseek_dir, | 58 | .llseek = nfs_llseek_dir, |
59 | .read = generic_read_dir, | 59 | .read = generic_read_dir, |
60 | .readdir = nfs_readdir, | 60 | .readdir = nfs_readdir, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index dee49a0cb995..f1df2c8d9259 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -49,7 +49,7 @@ static int nfs_check_flags(int flags); | |||
49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); |
50 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 50 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
51 | 51 | ||
52 | struct file_operations nfs_file_operations = { | 52 | const struct file_operations nfs_file_operations = { |
53 | .llseek = nfs_file_llseek, | 53 | .llseek = nfs_file_llseek, |
54 | .read = do_sync_read, | 54 | .read = do_sync_read, |
55 | .write = do_sync_write, | 55 | .write = do_sync_write, |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 417ec02df44f..c340be0a3f59 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max); | |||
57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; | 58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; |
59 | 59 | ||
60 | static inline int svc_expkey_hash(struct svc_expkey *item) | 60 | static void expkey_put(struct kref *ref) |
61 | { | 61 | { |
62 | int hash = item->ek_fsidtype; | 62 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); |
63 | char * cp = (char*)item->ek_fsid; | ||
64 | int len = key_len(item->ek_fsidtype); | ||
65 | 63 | ||
66 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); | 64 | if (test_bit(CACHE_VALID, &key->h.flags) && |
67 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | 65 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) { |
68 | return hash & EXPKEY_HASHMASK; | 66 | dput(key->ek_dentry); |
69 | } | 67 | mntput(key->ek_mnt); |
70 | |||
71 | void expkey_put(struct cache_head *item, struct cache_detail *cd) | ||
72 | { | ||
73 | if (cache_put(item, cd)) { | ||
74 | struct svc_expkey *key = container_of(item, struct svc_expkey, h); | ||
75 | if (test_bit(CACHE_VALID, &item->flags) && | ||
76 | !test_bit(CACHE_NEGATIVE, &item->flags)) | ||
77 | exp_put(key->ek_export); | ||
78 | auth_domain_put(key->ek_client); | ||
79 | kfree(key); | ||
80 | } | 68 | } |
69 | auth_domain_put(key->ek_client); | ||
70 | kfree(key); | ||
81 | } | 71 | } |
82 | 72 | ||
83 | static void expkey_request(struct cache_detail *cd, | 73 | static void expkey_request(struct cache_detail *cd, |
@@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd, | |||
95 | (*bpp)[-1] = '\n'; | 85 | (*bpp)[-1] = '\n'; |
96 | } | 86 | } |
97 | 87 | ||
98 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int); | 88 | static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); |
89 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); | ||
90 | static struct cache_detail svc_expkey_cache; | ||
91 | |||
99 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | 92 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) |
100 | { | 93 | { |
101 | /* client fsidtype fsid [path] */ | 94 | /* client fsidtype fsid [path] */ |
@@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
106 | int fsidtype; | 99 | int fsidtype; |
107 | char *ep; | 100 | char *ep; |
108 | struct svc_expkey key; | 101 | struct svc_expkey key; |
102 | struct svc_expkey *ek; | ||
109 | 103 | ||
110 | if (mesg[mlen-1] != '\n') | 104 | if (mesg[mlen-1] != '\n') |
111 | return -EINVAL; | 105 | return -EINVAL; |
@@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
150 | key.ek_fsidtype = fsidtype; | 144 | key.ek_fsidtype = fsidtype; |
151 | memcpy(key.ek_fsid, buf, len); | 145 | memcpy(key.ek_fsid, buf, len); |
152 | 146 | ||
147 | ek = svc_expkey_lookup(&key); | ||
148 | err = -ENOMEM; | ||
149 | if (!ek) | ||
150 | goto out; | ||
151 | |||
153 | /* now we want a pathname, or empty meaning NEGATIVE */ | 152 | /* now we want a pathname, or empty meaning NEGATIVE */ |
153 | err = -EINVAL; | ||
154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) | 154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) |
155 | goto out; | 155 | goto out; |
156 | dprintk("Path seems to be <%s>\n", buf); | 156 | dprintk("Path seems to be <%s>\n", buf); |
157 | err = 0; | 157 | err = 0; |
158 | if (len == 0) { | 158 | if (len == 0) { |
159 | struct svc_expkey *ek; | ||
160 | set_bit(CACHE_NEGATIVE, &key.h.flags); | 159 | set_bit(CACHE_NEGATIVE, &key.h.flags); |
161 | ek = svc_expkey_lookup(&key, 1); | 160 | ek = svc_expkey_update(&key, ek); |
162 | if (ek) | 161 | if (ek) |
163 | expkey_put(&ek->h, &svc_expkey_cache); | 162 | cache_put(&ek->h, &svc_expkey_cache); |
163 | else err = -ENOMEM; | ||
164 | } else { | 164 | } else { |
165 | struct nameidata nd; | 165 | struct nameidata nd; |
166 | struct svc_expkey *ek; | ||
167 | struct svc_export *exp; | ||
168 | err = path_lookup(buf, 0, &nd); | 166 | err = path_lookup(buf, 0, &nd); |
169 | if (err) | 167 | if (err) |
170 | goto out; | 168 | goto out; |
171 | 169 | ||
172 | dprintk("Found the path %s\n", buf); | 170 | dprintk("Found the path %s\n", buf); |
173 | exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); | 171 | key.ek_mnt = nd.mnt; |
174 | 172 | key.ek_dentry = nd.dentry; | |
175 | err = -ENOENT; | ||
176 | if (!exp) | ||
177 | goto out_nd; | ||
178 | key.ek_export = exp; | ||
179 | dprintk("And found export\n"); | ||
180 | 173 | ||
181 | ek = svc_expkey_lookup(&key, 1); | 174 | ek = svc_expkey_update(&key, ek); |
182 | if (ek) | 175 | if (ek) |
183 | expkey_put(&ek->h, &svc_expkey_cache); | 176 | cache_put(&ek->h, &svc_expkey_cache); |
184 | exp_put(exp); | 177 | else |
185 | err = 0; | 178 | err = -ENOMEM; |
186 | out_nd: | ||
187 | path_release(&nd); | 179 | path_release(&nd); |
188 | } | 180 | } |
189 | cache_flush(); | 181 | cache_flush(); |
@@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m, | |||
214 | if (test_bit(CACHE_VALID, &h->flags) && | 206 | if (test_bit(CACHE_VALID, &h->flags) && |
215 | !test_bit(CACHE_NEGATIVE, &h->flags)) { | 207 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
216 | seq_printf(m, " "); | 208 | seq_printf(m, " "); |
217 | seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n"); | 209 | seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n"); |
218 | } | 210 | } |
219 | seq_printf(m, "\n"); | 211 | seq_printf(m, "\n"); |
220 | return 0; | 212 | return 0; |
221 | } | 213 | } |
222 | |||
223 | struct cache_detail svc_expkey_cache = { | ||
224 | .owner = THIS_MODULE, | ||
225 | .hash_size = EXPKEY_HASHMAX, | ||
226 | .hash_table = expkey_table, | ||
227 | .name = "nfsd.fh", | ||
228 | .cache_put = expkey_put, | ||
229 | .cache_request = expkey_request, | ||
230 | .cache_parse = expkey_parse, | ||
231 | .cache_show = expkey_show, | ||
232 | }; | ||
233 | 214 | ||
234 | static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b) | 215 | static inline int expkey_match (struct cache_head *a, struct cache_head *b) |
235 | { | 216 | { |
236 | if (a->ek_fsidtype != b->ek_fsidtype || | 217 | struct svc_expkey *orig = container_of(a, struct svc_expkey, h); |
237 | a->ek_client != b->ek_client || | 218 | struct svc_expkey *new = container_of(b, struct svc_expkey, h); |
238 | memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0) | 219 | |
220 | if (orig->ek_fsidtype != new->ek_fsidtype || | ||
221 | orig->ek_client != new->ek_client || | ||
222 | memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0) | ||
239 | return 0; | 223 | return 0; |
240 | return 1; | 224 | return 1; |
241 | } | 225 | } |
242 | 226 | ||
243 | static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item) | 227 | static inline void expkey_init(struct cache_head *cnew, |
228 | struct cache_head *citem) | ||
244 | { | 229 | { |
245 | cache_get(&item->ek_client->h); | 230 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); |
231 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
232 | |||
233 | kref_get(&item->ek_client->ref); | ||
246 | new->ek_client = item->ek_client; | 234 | new->ek_client = item->ek_client; |
247 | new->ek_fsidtype = item->ek_fsidtype; | 235 | new->ek_fsidtype = item->ek_fsidtype; |
248 | new->ek_fsid[0] = item->ek_fsid[0]; | 236 | new->ek_fsid[0] = item->ek_fsid[0]; |
@@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it | |||
250 | new->ek_fsid[2] = item->ek_fsid[2]; | 238 | new->ek_fsid[2] = item->ek_fsid[2]; |
251 | } | 239 | } |
252 | 240 | ||
253 | static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) | 241 | static inline void expkey_update(struct cache_head *cnew, |
242 | struct cache_head *citem) | ||
243 | { | ||
244 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); | ||
245 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
246 | |||
247 | new->ek_mnt = mntget(item->ek_mnt); | ||
248 | new->ek_dentry = dget(item->ek_dentry); | ||
249 | } | ||
250 | |||
251 | static struct cache_head *expkey_alloc(void) | ||
254 | { | 252 | { |
255 | cache_get(&item->ek_export->h); | 253 | struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL); |
256 | new->ek_export = item->ek_export; | 254 | if (i) |
255 | return &i->h; | ||
256 | else | ||
257 | return NULL; | ||
257 | } | 258 | } |
258 | 259 | ||
259 | static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ | 260 | static struct cache_detail svc_expkey_cache = { |
261 | .owner = THIS_MODULE, | ||
262 | .hash_size = EXPKEY_HASHMAX, | ||
263 | .hash_table = expkey_table, | ||
264 | .name = "nfsd.fh", | ||
265 | .cache_put = expkey_put, | ||
266 | .cache_request = expkey_request, | ||
267 | .cache_parse = expkey_parse, | ||
268 | .cache_show = expkey_show, | ||
269 | .match = expkey_match, | ||
270 | .init = expkey_init, | ||
271 | .update = expkey_update, | ||
272 | .alloc = expkey_alloc, | ||
273 | }; | ||
260 | 274 | ||
261 | #define EXPORT_HASHBITS 8 | 275 | static struct svc_expkey * |
262 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | 276 | svc_expkey_lookup(struct svc_expkey *item) |
263 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | 277 | { |
278 | struct cache_head *ch; | ||
279 | int hash = item->ek_fsidtype; | ||
280 | char * cp = (char*)item->ek_fsid; | ||
281 | int len = key_len(item->ek_fsidtype); | ||
264 | 282 | ||
265 | static struct cache_head *export_table[EXPORT_HASHMAX]; | 283 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
284 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | ||
285 | hash &= EXPKEY_HASHMASK; | ||
266 | 286 | ||
267 | static inline int svc_export_hash(struct svc_export *item) | 287 | ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, |
288 | hash); | ||
289 | if (ch) | ||
290 | return container_of(ch, struct svc_expkey, h); | ||
291 | else | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static struct svc_expkey * | ||
296 | svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | ||
268 | { | 297 | { |
269 | int rv; | 298 | struct cache_head *ch; |
299 | int hash = new->ek_fsidtype; | ||
300 | char * cp = (char*)new->ek_fsid; | ||
301 | int len = key_len(new->ek_fsidtype); | ||
270 | 302 | ||
271 | rv = hash_ptr(item->ex_client, EXPORT_HASHBITS); | 303 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
272 | rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS); | 304 | hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS); |
273 | rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS); | 305 | hash &= EXPKEY_HASHMASK; |
274 | return rv; | 306 | |
307 | ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, | ||
308 | &old->h, hash); | ||
309 | if (ch) | ||
310 | return container_of(ch, struct svc_expkey, h); | ||
311 | else | ||
312 | return NULL; | ||
275 | } | 313 | } |
276 | 314 | ||
277 | void svc_export_put(struct cache_head *item, struct cache_detail *cd) | 315 | |
316 | #define EXPORT_HASHBITS 8 | ||
317 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | ||
318 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | ||
319 | |||
320 | static struct cache_head *export_table[EXPORT_HASHMAX]; | ||
321 | |||
322 | static void svc_export_put(struct kref *ref) | ||
278 | { | 323 | { |
279 | if (cache_put(item, cd)) { | 324 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
280 | struct svc_export *exp = container_of(item, struct svc_export, h); | 325 | dput(exp->ex_dentry); |
281 | dput(exp->ex_dentry); | 326 | mntput(exp->ex_mnt); |
282 | mntput(exp->ex_mnt); | 327 | auth_domain_put(exp->ex_client); |
283 | auth_domain_put(exp->ex_client); | 328 | kfree(exp); |
284 | kfree(exp); | ||
285 | } | ||
286 | } | 329 | } |
287 | 330 | ||
288 | static void svc_export_request(struct cache_detail *cd, | 331 | static void svc_export_request(struct cache_detail *cd, |
@@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd, | |||
304 | (*bpp)[-1] = '\n'; | 347 | (*bpp)[-1] = '\n'; |
305 | } | 348 | } |
306 | 349 | ||
307 | static struct svc_export *svc_export_lookup(struct svc_export *, int); | 350 | static struct svc_export *svc_export_update(struct svc_export *new, |
351 | struct svc_export *old); | ||
352 | static struct svc_export *svc_export_lookup(struct svc_export *); | ||
308 | 353 | ||
309 | static int check_export(struct inode *inode, int flags) | 354 | static int check_export(struct inode *inode, int flags) |
310 | { | 355 | { |
@@ -417,11 +462,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
417 | if (err) goto out; | 462 | if (err) goto out; |
418 | } | 463 | } |
419 | 464 | ||
420 | expp = svc_export_lookup(&exp, 1); | 465 | expp = svc_export_lookup(&exp); |
421 | if (expp) | 466 | if (expp) |
422 | exp_put(expp); | 467 | expp = svc_export_update(&exp, expp); |
423 | err = 0; | 468 | else |
469 | err = -ENOMEM; | ||
424 | cache_flush(); | 470 | cache_flush(); |
471 | if (expp == NULL) | ||
472 | err = -ENOMEM; | ||
473 | else | ||
474 | exp_put(expp); | ||
425 | out: | 475 | out: |
426 | if (nd.dentry) | 476 | if (nd.dentry) |
427 | path_release(&nd); | 477 | path_release(&nd); |
@@ -455,6 +505,46 @@ static int svc_export_show(struct seq_file *m, | |||
455 | seq_puts(m, ")\n"); | 505 | seq_puts(m, ")\n"); |
456 | return 0; | 506 | return 0; |
457 | } | 507 | } |
508 | static int svc_export_match(struct cache_head *a, struct cache_head *b) | ||
509 | { | ||
510 | struct svc_export *orig = container_of(a, struct svc_export, h); | ||
511 | struct svc_export *new = container_of(b, struct svc_export, h); | ||
512 | return orig->ex_client == new->ex_client && | ||
513 | orig->ex_dentry == new->ex_dentry && | ||
514 | orig->ex_mnt == new->ex_mnt; | ||
515 | } | ||
516 | |||
517 | static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | ||
518 | { | ||
519 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
520 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
521 | |||
522 | kref_get(&item->ex_client->ref); | ||
523 | new->ex_client = item->ex_client; | ||
524 | new->ex_dentry = dget(item->ex_dentry); | ||
525 | new->ex_mnt = mntget(item->ex_mnt); | ||
526 | } | ||
527 | |||
528 | static void export_update(struct cache_head *cnew, struct cache_head *citem) | ||
529 | { | ||
530 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
531 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
532 | |||
533 | new->ex_flags = item->ex_flags; | ||
534 | new->ex_anon_uid = item->ex_anon_uid; | ||
535 | new->ex_anon_gid = item->ex_anon_gid; | ||
536 | new->ex_fsid = item->ex_fsid; | ||
537 | } | ||
538 | |||
539 | static struct cache_head *svc_export_alloc(void) | ||
540 | { | ||
541 | struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); | ||
542 | if (i) | ||
543 | return &i->h; | ||
544 | else | ||
545 | return NULL; | ||
546 | } | ||
547 | |||
458 | struct cache_detail svc_export_cache = { | 548 | struct cache_detail svc_export_cache = { |
459 | .owner = THIS_MODULE, | 549 | .owner = THIS_MODULE, |
460 | .hash_size = EXPORT_HASHMAX, | 550 | .hash_size = EXPORT_HASHMAX, |
@@ -464,34 +554,49 @@ struct cache_detail svc_export_cache = { | |||
464 | .cache_request = svc_export_request, | 554 | .cache_request = svc_export_request, |
465 | .cache_parse = svc_export_parse, | 555 | .cache_parse = svc_export_parse, |
466 | .cache_show = svc_export_show, | 556 | .cache_show = svc_export_show, |
557 | .match = svc_export_match, | ||
558 | .init = svc_export_init, | ||
559 | .update = export_update, | ||
560 | .alloc = svc_export_alloc, | ||
467 | }; | 561 | }; |
468 | 562 | ||
469 | static inline int svc_export_match(struct svc_export *a, struct svc_export *b) | 563 | static struct svc_export * |
564 | svc_export_lookup(struct svc_export *exp) | ||
470 | { | 565 | { |
471 | return a->ex_client == b->ex_client && | 566 | struct cache_head *ch; |
472 | a->ex_dentry == b->ex_dentry && | 567 | int hash; |
473 | a->ex_mnt == b->ex_mnt; | 568 | hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); |
474 | } | 569 | hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); |
475 | static inline void svc_export_init(struct svc_export *new, struct svc_export *item) | 570 | hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); |
476 | { | 571 | |
477 | cache_get(&item->ex_client->h); | 572 | ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, |
478 | new->ex_client = item->ex_client; | 573 | hash); |
479 | new->ex_dentry = dget(item->ex_dentry); | 574 | if (ch) |
480 | new->ex_mnt = mntget(item->ex_mnt); | 575 | return container_of(ch, struct svc_export, h); |
576 | else | ||
577 | return NULL; | ||
481 | } | 578 | } |
482 | 579 | ||
483 | static inline void svc_export_update(struct svc_export *new, struct svc_export *item) | 580 | static struct svc_export * |
581 | svc_export_update(struct svc_export *new, struct svc_export *old) | ||
484 | { | 582 | { |
485 | new->ex_flags = item->ex_flags; | 583 | struct cache_head *ch; |
486 | new->ex_anon_uid = item->ex_anon_uid; | 584 | int hash; |
487 | new->ex_anon_gid = item->ex_anon_gid; | 585 | hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); |
488 | new->ex_fsid = item->ex_fsid; | 586 | hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); |
587 | hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); | ||
588 | |||
589 | ch = sunrpc_cache_update(&svc_export_cache, &new->h, | ||
590 | &old->h, | ||
591 | hash); | ||
592 | if (ch) | ||
593 | return container_of(ch, struct svc_export, h); | ||
594 | else | ||
595 | return NULL; | ||
489 | } | 596 | } |
490 | 597 | ||
491 | static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */ | ||
492 | 598 | ||
493 | 599 | static struct svc_expkey * | |
494 | struct svc_expkey * | ||
495 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | 600 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) |
496 | { | 601 | { |
497 | struct svc_expkey key, *ek; | 602 | struct svc_expkey key, *ek; |
@@ -504,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | |||
504 | key.ek_fsidtype = fsid_type; | 609 | key.ek_fsidtype = fsid_type; |
505 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 610 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
506 | 611 | ||
507 | ek = svc_expkey_lookup(&key, 0); | 612 | ek = svc_expkey_lookup(&key); |
508 | if (ek != NULL) | 613 | if (ek != NULL) |
509 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) | 614 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) |
510 | ek = ERR_PTR(err); | 615 | ek = ERR_PTR(err); |
@@ -519,13 +624,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, | |||
519 | key.ek_client = clp; | 624 | key.ek_client = clp; |
520 | key.ek_fsidtype = fsid_type; | 625 | key.ek_fsidtype = fsid_type; |
521 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 626 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
522 | key.ek_export = exp; | 627 | key.ek_mnt = exp->ex_mnt; |
628 | key.ek_dentry = exp->ex_dentry; | ||
523 | key.h.expiry_time = NEVER; | 629 | key.h.expiry_time = NEVER; |
524 | key.h.flags = 0; | 630 | key.h.flags = 0; |
525 | 631 | ||
526 | ek = svc_expkey_lookup(&key, 1); | 632 | ek = svc_expkey_lookup(&key); |
633 | if (ek) | ||
634 | ek = svc_expkey_update(&key,ek); | ||
527 | if (ek) { | 635 | if (ek) { |
528 | expkey_put(&ek->h, &svc_expkey_cache); | 636 | cache_put(&ek->h, &svc_expkey_cache); |
529 | return 0; | 637 | return 0; |
530 | } | 638 | } |
531 | return -ENOMEM; | 639 | return -ENOMEM; |
@@ -573,7 +681,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
573 | key.ex_mnt = mnt; | 681 | key.ex_mnt = mnt; |
574 | key.ex_dentry = dentry; | 682 | key.ex_dentry = dentry; |
575 | 683 | ||
576 | exp = svc_export_lookup(&key, 0); | 684 | exp = svc_export_lookup(&key); |
577 | if (exp != NULL) | 685 | if (exp != NULL) |
578 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { | 686 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { |
579 | case 0: break; | 687 | case 0: break; |
@@ -654,7 +762,7 @@ static void exp_fsid_unhash(struct svc_export *exp) | |||
654 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); | 762 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); |
655 | if (ek && !IS_ERR(ek)) { | 763 | if (ek && !IS_ERR(ek)) { |
656 | ek->h.expiry_time = get_seconds()-1; | 764 | ek->h.expiry_time = get_seconds()-1; |
657 | expkey_put(&ek->h, &svc_expkey_cache); | 765 | cache_put(&ek->h, &svc_expkey_cache); |
658 | } | 766 | } |
659 | svc_expkey_cache.nextcheck = get_seconds(); | 767 | svc_expkey_cache.nextcheck = get_seconds(); |
660 | } | 768 | } |
@@ -692,7 +800,7 @@ static void exp_unhash(struct svc_export *exp) | |||
692 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); | 800 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); |
693 | if (ek && !IS_ERR(ek)) { | 801 | if (ek && !IS_ERR(ek)) { |
694 | ek->h.expiry_time = get_seconds()-1; | 802 | ek->h.expiry_time = get_seconds()-1; |
695 | expkey_put(&ek->h, &svc_expkey_cache); | 803 | cache_put(&ek->h, &svc_expkey_cache); |
696 | } | 804 | } |
697 | svc_expkey_cache.nextcheck = get_seconds(); | 805 | svc_expkey_cache.nextcheck = get_seconds(); |
698 | } | 806 | } |
@@ -741,8 +849,8 @@ exp_export(struct nfsctl_export *nxp) | |||
741 | if ((nxp->ex_flags & NFSEXP_FSID) && | 849 | if ((nxp->ex_flags & NFSEXP_FSID) && |
742 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && | 850 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && |
743 | !IS_ERR(fsid_key) && | 851 | !IS_ERR(fsid_key) && |
744 | fsid_key->ek_export && | 852 | fsid_key->ek_mnt && |
745 | fsid_key->ek_export != exp) | 853 | (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) |
746 | goto finish; | 854 | goto finish; |
747 | 855 | ||
748 | if (exp) { | 856 | if (exp) { |
@@ -775,13 +883,13 @@ exp_export(struct nfsctl_export *nxp) | |||
775 | new.ex_anon_gid = nxp->ex_anon_gid; | 883 | new.ex_anon_gid = nxp->ex_anon_gid; |
776 | new.ex_fsid = nxp->ex_dev; | 884 | new.ex_fsid = nxp->ex_dev; |
777 | 885 | ||
778 | exp = svc_export_lookup(&new, 1); | 886 | exp = svc_export_lookup(&new); |
887 | if (exp) | ||
888 | exp = svc_export_update(&new, exp); | ||
779 | 889 | ||
780 | if (exp == NULL) | 890 | if (!exp) |
781 | goto finish; | 891 | goto finish; |
782 | 892 | ||
783 | err = 0; | ||
784 | |||
785 | if (exp_hash(clp, exp) || | 893 | if (exp_hash(clp, exp) || |
786 | exp_fsid_hash(clp, exp)) { | 894 | exp_fsid_hash(clp, exp)) { |
787 | /* failed to create at least one index */ | 895 | /* failed to create at least one index */ |
@@ -794,7 +902,7 @@ finish: | |||
794 | if (exp) | 902 | if (exp) |
795 | exp_put(exp); | 903 | exp_put(exp); |
796 | if (fsid_key && !IS_ERR(fsid_key)) | 904 | if (fsid_key && !IS_ERR(fsid_key)) |
797 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 905 | cache_put(&fsid_key->h, &svc_expkey_cache); |
798 | if (clp) | 906 | if (clp) |
799 | auth_domain_put(clp); | 907 | auth_domain_put(clp); |
800 | path_release(&nd); | 908 | path_release(&nd); |
@@ -912,6 +1020,24 @@ out: | |||
912 | return err; | 1020 | return err; |
913 | } | 1021 | } |
914 | 1022 | ||
1023 | struct svc_export * | ||
1024 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | ||
1025 | struct cache_req *reqp) | ||
1026 | { | ||
1027 | struct svc_export *exp; | ||
1028 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | ||
1029 | if (!ek || IS_ERR(ek)) | ||
1030 | return ERR_PTR(PTR_ERR(ek)); | ||
1031 | |||
1032 | exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); | ||
1033 | cache_put(&ek->h, &svc_expkey_cache); | ||
1034 | |||
1035 | if (!exp || IS_ERR(exp)) | ||
1036 | return ERR_PTR(PTR_ERR(exp)); | ||
1037 | return exp; | ||
1038 | } | ||
1039 | |||
1040 | |||
915 | /* | 1041 | /* |
916 | * Called when we need the filehandle for the root of the pseudofs, | 1042 | * Called when we need the filehandle for the root of the pseudofs, |
917 | * for a given NFSv4 client. The root is defined to be the | 1043 | * for a given NFSv4 client. The root is defined to be the |
@@ -922,6 +1048,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
922 | struct cache_req *creq) | 1048 | struct cache_req *creq) |
923 | { | 1049 | { |
924 | struct svc_expkey *fsid_key; | 1050 | struct svc_expkey *fsid_key; |
1051 | struct svc_export *exp; | ||
925 | int rv; | 1052 | int rv; |
926 | u32 fsidv[2]; | 1053 | u32 fsidv[2]; |
927 | 1054 | ||
@@ -933,9 +1060,15 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
933 | if (!fsid_key || IS_ERR(fsid_key)) | 1060 | if (!fsid_key || IS_ERR(fsid_key)) |
934 | return nfserr_perm; | 1061 | return nfserr_perm; |
935 | 1062 | ||
936 | rv = fh_compose(fhp, fsid_key->ek_export, | 1063 | exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); |
937 | fsid_key->ek_export->ex_dentry, NULL); | 1064 | if (exp == NULL) |
938 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 1065 | rv = nfserr_perm; |
1066 | else if (IS_ERR(exp)) | ||
1067 | rv = nfserrno(PTR_ERR(exp)); | ||
1068 | else | ||
1069 | rv = fh_compose(fhp, exp, | ||
1070 | fsid_key->ek_dentry, NULL); | ||
1071 | cache_put(&fsid_key->h, &svc_expkey_cache); | ||
939 | return rv; | 1072 | return rv; |
940 | } | 1073 | } |
941 | 1074 | ||
@@ -1054,7 +1187,7 @@ static int e_show(struct seq_file *m, void *p) | |||
1054 | cache_get(&exp->h); | 1187 | cache_get(&exp->h); |
1055 | if (cache_check(&svc_export_cache, &exp->h, NULL)) | 1188 | if (cache_check(&svc_export_cache, &exp->h, NULL)) |
1056 | return 0; | 1189 | return 0; |
1057 | if (cache_put(&exp->h, &svc_export_cache)) BUG(); | 1190 | cache_put(&exp->h, &svc_export_cache); |
1058 | return svc_export_show(m, &svc_export_cache, cp); | 1191 | return svc_export_show(m, &svc_export_cache, cp); |
1059 | } | 1192 | } |
1060 | 1193 | ||
@@ -1129,7 +1262,6 @@ exp_delclient(struct nfsctl_client *ncp) | |||
1129 | */ | 1262 | */ |
1130 | if (dom) { | 1263 | if (dom) { |
1131 | err = auth_unix_forget_old(dom); | 1264 | err = auth_unix_forget_old(dom); |
1132 | dom->h.expiry_time = get_seconds(); | ||
1133 | auth_domain_put(dom); | 1265 | auth_domain_put(dom); |
1134 | } | 1266 | } |
1135 | 1267 | ||
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 13369650cdf9..4b6aa60dfceb 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
@@ -76,21 +76,18 @@ struct ent { | |||
76 | char authname[IDMAP_NAMESZ]; | 76 | char authname[IDMAP_NAMESZ]; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | #define DefineSimpleCacheLookupMap(STRUCT, FUNC) \ | ||
80 | DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \ | ||
81 | (struct STRUCT *item, int set), /*no setup */, \ | ||
82 | & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \ | ||
83 | STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0) | ||
84 | |||
85 | /* Common entry handling */ | 79 | /* Common entry handling */ |
86 | 80 | ||
87 | #define ENT_HASHBITS 8 | 81 | #define ENT_HASHBITS 8 |
88 | #define ENT_HASHMAX (1 << ENT_HASHBITS) | 82 | #define ENT_HASHMAX (1 << ENT_HASHBITS) |
89 | #define ENT_HASHMASK (ENT_HASHMAX - 1) | 83 | #define ENT_HASHMASK (ENT_HASHMAX - 1) |
90 | 84 | ||
91 | static inline void | 85 | static void |
92 | ent_init(struct ent *new, struct ent *itm) | 86 | ent_init(struct cache_head *cnew, struct cache_head *citm) |
93 | { | 87 | { |
88 | struct ent *new = container_of(cnew, struct ent, h); | ||
89 | struct ent *itm = container_of(citm, struct ent, h); | ||
90 | |||
94 | new->id = itm->id; | 91 | new->id = itm->id; |
95 | new->type = itm->type; | 92 | new->type = itm->type; |
96 | 93 | ||
@@ -98,19 +95,21 @@ ent_init(struct ent *new, struct ent *itm) | |||
98 | strlcpy(new->authname, itm->authname, sizeof(new->name)); | 95 | strlcpy(new->authname, itm->authname, sizeof(new->name)); |
99 | } | 96 | } |
100 | 97 | ||
101 | static inline void | 98 | static void |
102 | ent_update(struct ent *new, struct ent *itm) | 99 | ent_put(struct kref *ref) |
103 | { | 100 | { |
104 | ent_init(new, itm); | 101 | struct ent *map = container_of(ref, struct ent, h.ref); |
102 | kfree(map); | ||
105 | } | 103 | } |
106 | 104 | ||
107 | static void | 105 | static struct cache_head * |
108 | ent_put(struct cache_head *ch, struct cache_detail *cd) | 106 | ent_alloc(void) |
109 | { | 107 | { |
110 | if (cache_put(ch, cd)) { | 108 | struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL); |
111 | struct ent *map = container_of(ch, struct ent, h); | 109 | if (e) |
112 | kfree(map); | 110 | return &e->h; |
113 | } | 111 | else |
112 | return NULL; | ||
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* |
@@ -149,9 +148,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
149 | (*bpp)[-1] = '\n'; | 148 | (*bpp)[-1] = '\n'; |
150 | } | 149 | } |
151 | 150 | ||
152 | static inline int | 151 | static int |
153 | idtoname_match(struct ent *a, struct ent *b) | 152 | idtoname_match(struct cache_head *ca, struct cache_head *cb) |
154 | { | 153 | { |
154 | struct ent *a = container_of(ca, struct ent, h); | ||
155 | struct ent *b = container_of(cb, struct ent, h); | ||
156 | |||
155 | return (a->id == b->id && a->type == b->type && | 157 | return (a->id == b->id && a->type == b->type && |
156 | strcmp(a->authname, b->authname) == 0); | 158 | strcmp(a->authname, b->authname) == 0); |
157 | } | 159 | } |
@@ -184,7 +186,8 @@ warn_no_idmapd(struct cache_detail *detail) | |||
184 | 186 | ||
185 | 187 | ||
186 | static int idtoname_parse(struct cache_detail *, char *, int); | 188 | static int idtoname_parse(struct cache_detail *, char *, int); |
187 | static struct ent *idtoname_lookup(struct ent *, int); | 189 | static struct ent *idtoname_lookup(struct ent *); |
190 | static struct ent *idtoname_update(struct ent *, struct ent *); | ||
188 | 191 | ||
189 | static struct cache_detail idtoname_cache = { | 192 | static struct cache_detail idtoname_cache = { |
190 | .owner = THIS_MODULE, | 193 | .owner = THIS_MODULE, |
@@ -196,6 +199,10 @@ static struct cache_detail idtoname_cache = { | |||
196 | .cache_parse = idtoname_parse, | 199 | .cache_parse = idtoname_parse, |
197 | .cache_show = idtoname_show, | 200 | .cache_show = idtoname_show, |
198 | .warn_no_listener = warn_no_idmapd, | 201 | .warn_no_listener = warn_no_idmapd, |
202 | .match = idtoname_match, | ||
203 | .init = ent_init, | ||
204 | .update = ent_init, | ||
205 | .alloc = ent_alloc, | ||
199 | }; | 206 | }; |
200 | 207 | ||
201 | int | 208 | int |
@@ -238,6 +245,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
238 | if (ent.h.expiry_time == 0) | 245 | if (ent.h.expiry_time == 0) |
239 | goto out; | 246 | goto out; |
240 | 247 | ||
248 | error = -ENOMEM; | ||
249 | res = idtoname_lookup(&ent); | ||
250 | if (!res) | ||
251 | goto out; | ||
252 | |||
241 | /* Name */ | 253 | /* Name */ |
242 | error = qword_get(&buf, buf1, PAGE_SIZE); | 254 | error = qword_get(&buf, buf1, PAGE_SIZE); |
243 | if (error == -EINVAL) | 255 | if (error == -EINVAL) |
@@ -252,10 +264,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
252 | memcpy(ent.name, buf1, sizeof(ent.name)); | 264 | memcpy(ent.name, buf1, sizeof(ent.name)); |
253 | } | 265 | } |
254 | error = -ENOMEM; | 266 | error = -ENOMEM; |
255 | if ((res = idtoname_lookup(&ent, 1)) == NULL) | 267 | res = idtoname_update(&ent, res); |
268 | if (res == NULL) | ||
256 | goto out; | 269 | goto out; |
257 | 270 | ||
258 | ent_put(&res->h, &idtoname_cache); | 271 | cache_put(&res->h, &idtoname_cache); |
259 | 272 | ||
260 | error = 0; | 273 | error = 0; |
261 | out: | 274 | out: |
@@ -264,7 +277,31 @@ out: | |||
264 | return error; | 277 | return error; |
265 | } | 278 | } |
266 | 279 | ||
267 | static DefineSimpleCacheLookupMap(ent, idtoname); | 280 | |
281 | static struct ent * | ||
282 | idtoname_lookup(struct ent *item) | ||
283 | { | ||
284 | struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, | ||
285 | &item->h, | ||
286 | idtoname_hash(item)); | ||
287 | if (ch) | ||
288 | return container_of(ch, struct ent, h); | ||
289 | else | ||
290 | return NULL; | ||
291 | } | ||
292 | |||
293 | static struct ent * | ||
294 | idtoname_update(struct ent *new, struct ent *old) | ||
295 | { | ||
296 | struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, | ||
297 | &new->h, &old->h, | ||
298 | idtoname_hash(new)); | ||
299 | if (ch) | ||
300 | return container_of(ch, struct ent, h); | ||
301 | else | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
268 | 305 | ||
269 | /* | 306 | /* |
270 | * Name -> ID cache | 307 | * Name -> ID cache |
@@ -291,9 +328,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
291 | (*bpp)[-1] = '\n'; | 328 | (*bpp)[-1] = '\n'; |
292 | } | 329 | } |
293 | 330 | ||
294 | static inline int | 331 | static int |
295 | nametoid_match(struct ent *a, struct ent *b) | 332 | nametoid_match(struct cache_head *ca, struct cache_head *cb) |
296 | { | 333 | { |
334 | struct ent *a = container_of(ca, struct ent, h); | ||
335 | struct ent *b = container_of(cb, struct ent, h); | ||
336 | |||
297 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && | 337 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && |
298 | strcmp(a->authname, b->authname) == 0); | 338 | strcmp(a->authname, b->authname) == 0); |
299 | } | 339 | } |
@@ -317,7 +357,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) | |||
317 | return 0; | 357 | return 0; |
318 | } | 358 | } |
319 | 359 | ||
320 | static struct ent *nametoid_lookup(struct ent *, int); | 360 | static struct ent *nametoid_lookup(struct ent *); |
361 | static struct ent *nametoid_update(struct ent *, struct ent *); | ||
321 | static int nametoid_parse(struct cache_detail *, char *, int); | 362 | static int nametoid_parse(struct cache_detail *, char *, int); |
322 | 363 | ||
323 | static struct cache_detail nametoid_cache = { | 364 | static struct cache_detail nametoid_cache = { |
@@ -330,6 +371,10 @@ static struct cache_detail nametoid_cache = { | |||
330 | .cache_parse = nametoid_parse, | 371 | .cache_parse = nametoid_parse, |
331 | .cache_show = nametoid_show, | 372 | .cache_show = nametoid_show, |
332 | .warn_no_listener = warn_no_idmapd, | 373 | .warn_no_listener = warn_no_idmapd, |
374 | .match = nametoid_match, | ||
375 | .init = ent_init, | ||
376 | .update = ent_init, | ||
377 | .alloc = ent_alloc, | ||
333 | }; | 378 | }; |
334 | 379 | ||
335 | static int | 380 | static int |
@@ -379,10 +424,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen) | |||
379 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 424 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
380 | 425 | ||
381 | error = -ENOMEM; | 426 | error = -ENOMEM; |
382 | if ((res = nametoid_lookup(&ent, 1)) == NULL) | 427 | res = nametoid_lookup(&ent); |
428 | if (res == NULL) | ||
429 | goto out; | ||
430 | res = nametoid_update(&ent, res); | ||
431 | if (res == NULL) | ||
383 | goto out; | 432 | goto out; |
384 | 433 | ||
385 | ent_put(&res->h, &nametoid_cache); | 434 | cache_put(&res->h, &nametoid_cache); |
386 | error = 0; | 435 | error = 0; |
387 | out: | 436 | out: |
388 | kfree(buf1); | 437 | kfree(buf1); |
@@ -390,7 +439,30 @@ out: | |||
390 | return (error); | 439 | return (error); |
391 | } | 440 | } |
392 | 441 | ||
393 | static DefineSimpleCacheLookupMap(ent, nametoid); | 442 | |
443 | static struct ent * | ||
444 | nametoid_lookup(struct ent *item) | ||
445 | { | ||
446 | struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, | ||
447 | &item->h, | ||
448 | nametoid_hash(item)); | ||
449 | if (ch) | ||
450 | return container_of(ch, struct ent, h); | ||
451 | else | ||
452 | return NULL; | ||
453 | } | ||
454 | |||
455 | static struct ent * | ||
456 | nametoid_update(struct ent *new, struct ent *old) | ||
457 | { | ||
458 | struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, | ||
459 | &new->h, &old->h, | ||
460 | nametoid_hash(new)); | ||
461 | if (ch) | ||
462 | return container_of(ch, struct ent, h); | ||
463 | else | ||
464 | return NULL; | ||
465 | } | ||
394 | 466 | ||
395 | /* | 467 | /* |
396 | * Exported API | 468 | * Exported API |
@@ -458,24 +530,24 @@ idmap_defer(struct cache_req *req) | |||
458 | } | 530 | } |
459 | 531 | ||
460 | static inline int | 532 | static inline int |
461 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 533 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
462 | struct cache_detail *detail, struct ent **item, | 534 | struct cache_detail *detail, struct ent **item, |
463 | struct idmap_defer_req *mdr) | 535 | struct idmap_defer_req *mdr) |
464 | { | 536 | { |
465 | *item = lookup_fn(key, 0); | 537 | *item = lookup_fn(key); |
466 | if (!*item) | 538 | if (!*item) |
467 | return -ENOMEM; | 539 | return -ENOMEM; |
468 | return cache_check(detail, &(*item)->h, &mdr->req); | 540 | return cache_check(detail, &(*item)->h, &mdr->req); |
469 | } | 541 | } |
470 | 542 | ||
471 | static inline int | 543 | static inline int |
472 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | 544 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *), |
473 | struct ent *key, struct cache_detail *detail, | 545 | struct ent *key, struct cache_detail *detail, |
474 | struct ent **item) | 546 | struct ent **item) |
475 | { | 547 | { |
476 | int ret = -ENOMEM; | 548 | int ret = -ENOMEM; |
477 | 549 | ||
478 | *item = lookup_fn(key, 0); | 550 | *item = lookup_fn(key); |
479 | if (!*item) | 551 | if (!*item) |
480 | goto out_err; | 552 | goto out_err; |
481 | ret = -ETIMEDOUT; | 553 | ret = -ETIMEDOUT; |
@@ -488,7 +560,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | |||
488 | goto out_put; | 560 | goto out_put; |
489 | return 0; | 561 | return 0; |
490 | out_put: | 562 | out_put: |
491 | ent_put(&(*item)->h, detail); | 563 | cache_put(&(*item)->h, detail); |
492 | out_err: | 564 | out_err: |
493 | *item = NULL; | 565 | *item = NULL; |
494 | return ret; | 566 | return ret; |
@@ -496,7 +568,7 @@ out_err: | |||
496 | 568 | ||
497 | static int | 569 | static int |
498 | idmap_lookup(struct svc_rqst *rqstp, | 570 | idmap_lookup(struct svc_rqst *rqstp, |
499 | struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 571 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
500 | struct cache_detail *detail, struct ent **item) | 572 | struct cache_detail *detail, struct ent **item) |
501 | { | 573 | { |
502 | struct idmap_defer_req *mdr; | 574 | struct idmap_defer_req *mdr; |
@@ -539,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
539 | if (ret) | 611 | if (ret) |
540 | return ret; | 612 | return ret; |
541 | *id = item->id; | 613 | *id = item->id; |
542 | ent_put(&item->h, &nametoid_cache); | 614 | cache_put(&item->h, &nametoid_cache); |
543 | return 0; | 615 | return 0; |
544 | } | 616 | } |
545 | 617 | ||
@@ -561,7 +633,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
561 | ret = strlen(item->name); | 633 | ret = strlen(item->name); |
562 | BUG_ON(ret > IDMAP_NAMESZ); | 634 | BUG_ON(ret > IDMAP_NAMESZ); |
563 | memcpy(name, item->name, ret); | 635 | memcpy(name, item->name, ret); |
564 | ent_put(&item->h, &idtoname_cache); | 636 | cache_put(&item->h, &idtoname_cache); |
565 | return ret; | 637 | return ret; |
566 | } | 638 | } |
567 | 639 | ||
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c8960aff0968..3ef017b3b5bd 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -134,7 +134,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size | |||
134 | return simple_transaction_read(file, buf, size, pos); | 134 | return simple_transaction_read(file, buf, size, pos); |
135 | } | 135 | } |
136 | 136 | ||
137 | static struct file_operations transaction_ops = { | 137 | static const struct file_operations transaction_ops = { |
138 | .write = nfsctl_transaction_write, | 138 | .write = nfsctl_transaction_write, |
139 | .read = nfsctl_transaction_read, | 139 | .read = nfsctl_transaction_read, |
140 | .release = simple_transaction_release, | 140 | .release = simple_transaction_release, |
@@ -146,7 +146,7 @@ static int exports_open(struct inode *inode, struct file *file) | |||
146 | return seq_open(file, &nfs_exports_op); | 146 | return seq_open(file, &nfs_exports_op); |
147 | } | 147 | } |
148 | 148 | ||
149 | static struct file_operations exports_operations = { | 149 | static const struct file_operations exports_operations = { |
150 | .open = exports_open, | 150 | .open = exports_open, |
151 | .read = seq_read, | 151 | .read = seq_read, |
152 | .llseek = seq_lseek, | 152 | .llseek = seq_lseek, |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 7a3e397b4ed3..3f2ec2e6d06c 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -506,7 +506,7 @@ fh_put(struct svc_fh *fhp) | |||
506 | nfsd_nr_put++; | 506 | nfsd_nr_put++; |
507 | } | 507 | } |
508 | if (exp) { | 508 | if (exp) { |
509 | svc_export_put(&exp->h, &svc_export_cache); | 509 | cache_put(&exp->h, &svc_export_cache); |
510 | fhp->fh_export = NULL; | 510 | fhp->fh_export = NULL; |
511 | } | 511 | } |
512 | return; | 512 | return; |
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 1cf955bcc526..57265d563804 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c | |||
@@ -80,7 +80,7 @@ static int nfsd_proc_open(struct inode *inode, struct file *file) | |||
80 | return single_open(file, nfsd_proc_show, NULL); | 80 | return single_open(file, nfsd_proc_show, NULL); |
81 | } | 81 | } |
82 | 82 | ||
83 | static struct file_operations nfsd_proc_fops = { | 83 | static const struct file_operations nfsd_proc_fops = { |
84 | .owner = THIS_MODULE, | 84 | .owner = THIS_MODULE, |
85 | .open = nfsd_proc_open, | 85 | .open = nfsd_proc_open, |
86 | .read = seq_read, | 86 | .read = seq_read, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5320e5afaddb..31018333dc38 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -706,7 +706,7 @@ nfsd_close(struct file *filp) | |||
706 | * after it. | 706 | * after it. |
707 | */ | 707 | */ |
708 | static inline int nfsd_dosync(struct file *filp, struct dentry *dp, | 708 | static inline int nfsd_dosync(struct file *filp, struct dentry *dp, |
709 | struct file_operations *fop) | 709 | const struct file_operations *fop) |
710 | { | 710 | { |
711 | struct inode *inode = dp->d_inode; | 711 | struct inode *inode = dp->d_inode; |
712 | int (*fsync) (struct file *, struct dentry *, int); | 712 | int (*fsync) (struct file *, struct dentry *, int); |
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 9d9ed3fe371d..d1e2c6f9f05e 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
@@ -1553,7 +1553,7 @@ static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry, | |||
1553 | 1553 | ||
1554 | #endif /* NTFS_RW */ | 1554 | #endif /* NTFS_RW */ |
1555 | 1555 | ||
1556 | struct file_operations ntfs_dir_ops = { | 1556 | const struct file_operations ntfs_dir_ops = { |
1557 | .llseek = generic_file_llseek, /* Seek inside directory. */ | 1557 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
1558 | .read = generic_read_dir, /* Return -EISDIR. */ | 1558 | .read = generic_read_dir, /* Return -EISDIR. */ |
1559 | .readdir = ntfs_readdir, /* Read directory contents. */ | 1559 | .readdir = ntfs_readdir, /* Read directory contents. */ |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index f5d057e4acc2..c63a83e8da98 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -2294,7 +2294,7 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry, | |||
2294 | 2294 | ||
2295 | #endif /* NTFS_RW */ | 2295 | #endif /* NTFS_RW */ |
2296 | 2296 | ||
2297 | struct file_operations ntfs_file_ops = { | 2297 | const struct file_operations ntfs_file_ops = { |
2298 | .llseek = generic_file_llseek, /* Seek inside file. */ | 2298 | .llseek = generic_file_llseek, /* Seek inside file. */ |
2299 | .read = generic_file_read, /* Read from file. */ | 2299 | .read = generic_file_read, /* Read from file. */ |
2300 | .aio_read = generic_file_aio_read, /* Async read from file. */ | 2300 | .aio_read = generic_file_aio_read, /* Async read from file. */ |
@@ -2337,6 +2337,6 @@ struct inode_operations ntfs_file_inode_ops = { | |||
2337 | #endif /* NTFS_RW */ | 2337 | #endif /* NTFS_RW */ |
2338 | }; | 2338 | }; |
2339 | 2339 | ||
2340 | struct file_operations ntfs_empty_file_ops = {}; | 2340 | const struct file_operations ntfs_empty_file_ops = {}; |
2341 | 2341 | ||
2342 | struct inode_operations ntfs_empty_inode_ops = {}; | 2342 | struct inode_operations ntfs_empty_inode_ops = {}; |
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index 166142960b53..bf7b3d7c0930 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
@@ -60,13 +60,13 @@ extern struct kmem_cache *ntfs_index_ctx_cache; | |||
60 | extern struct address_space_operations ntfs_aops; | 60 | extern struct address_space_operations ntfs_aops; |
61 | extern struct address_space_operations ntfs_mst_aops; | 61 | extern struct address_space_operations ntfs_mst_aops; |
62 | 62 | ||
63 | extern struct file_operations ntfs_file_ops; | 63 | extern const struct file_operations ntfs_file_ops; |
64 | extern struct inode_operations ntfs_file_inode_ops; | 64 | extern struct inode_operations ntfs_file_inode_ops; |
65 | 65 | ||
66 | extern struct file_operations ntfs_dir_ops; | 66 | extern const struct file_operations ntfs_dir_ops; |
67 | extern struct inode_operations ntfs_dir_inode_ops; | 67 | extern struct inode_operations ntfs_dir_inode_ops; |
68 | 68 | ||
69 | extern struct file_operations ntfs_empty_file_ops; | 69 | extern const struct file_operations ntfs_empty_file_ops; |
70 | extern struct inode_operations ntfs_empty_inode_ops; | 70 | extern struct inode_operations ntfs_empty_inode_ops; |
71 | 71 | ||
72 | extern struct export_operations ntfs_export_ops; | 72 | extern struct export_operations ntfs_export_ops; |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 84f153aca692..64cd52860c87 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -2017,7 +2017,7 @@ out: | |||
2017 | return ret; | 2017 | return ret; |
2018 | } | 2018 | } |
2019 | 2019 | ||
2020 | static struct file_operations ocfs2_dlm_debug_fops = { | 2020 | static const struct file_operations ocfs2_dlm_debug_fops = { |
2021 | .open = ocfs2_dlm_debug_open, | 2021 | .open = ocfs2_dlm_debug_open, |
2022 | .release = ocfs2_dlm_debug_release, | 2022 | .release = ocfs2_dlm_debug_release, |
2023 | .read = seq_read, | 2023 | .read = seq_read, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 4b4cbadd5838..34e903a6a46b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1176,7 +1176,7 @@ struct inode_operations ocfs2_special_file_iops = { | |||
1176 | .getattr = ocfs2_getattr, | 1176 | .getattr = ocfs2_getattr, |
1177 | }; | 1177 | }; |
1178 | 1178 | ||
1179 | struct file_operations ocfs2_fops = { | 1179 | const struct file_operations ocfs2_fops = { |
1180 | .read = do_sync_read, | 1180 | .read = do_sync_read, |
1181 | .write = do_sync_write, | 1181 | .write = do_sync_write, |
1182 | .sendfile = generic_file_sendfile, | 1182 | .sendfile = generic_file_sendfile, |
@@ -1188,7 +1188,7 @@ struct file_operations ocfs2_fops = { | |||
1188 | .aio_write = ocfs2_file_aio_write, | 1188 | .aio_write = ocfs2_file_aio_write, |
1189 | }; | 1189 | }; |
1190 | 1190 | ||
1191 | struct file_operations ocfs2_dops = { | 1191 | const struct file_operations ocfs2_dops = { |
1192 | .read = generic_read_dir, | 1192 | .read = generic_read_dir, |
1193 | .readdir = ocfs2_readdir, | 1193 | .readdir = ocfs2_readdir, |
1194 | .fsync = ocfs2_sync_file, | 1194 | .fsync = ocfs2_sync_file, |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index a5ea33b24060..740c9e7ca599 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
@@ -26,8 +26,8 @@ | |||
26 | #ifndef OCFS2_FILE_H | 26 | #ifndef OCFS2_FILE_H |
27 | #define OCFS2_FILE_H | 27 | #define OCFS2_FILE_H |
28 | 28 | ||
29 | extern struct file_operations ocfs2_fops; | 29 | extern const struct file_operations ocfs2_fops; |
30 | extern struct file_operations ocfs2_dops; | 30 | extern const struct file_operations ocfs2_dops; |
31 | extern struct inode_operations ocfs2_file_iops; | 31 | extern struct inode_operations ocfs2_file_iops; |
32 | extern struct inode_operations ocfs2_special_file_iops; | 32 | extern struct inode_operations ocfs2_special_file_iops; |
33 | struct ocfs2_alloc_context; | 33 | struct ocfs2_alloc_context; |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index aeb0106890e4..0f14276a2e51 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
@@ -581,17 +581,17 @@ int property_release (struct inode *inode, struct file *filp) | |||
581 | return 0; | 581 | return 0; |
582 | } | 582 | } |
583 | 583 | ||
584 | static struct file_operations openpromfs_prop_ops = { | 584 | static const struct file_operations openpromfs_prop_ops = { |
585 | .read = property_read, | 585 | .read = property_read, |
586 | .write = property_write, | 586 | .write = property_write, |
587 | .release = property_release, | 587 | .release = property_release, |
588 | }; | 588 | }; |
589 | 589 | ||
590 | static struct file_operations openpromfs_nodenum_ops = { | 590 | static const struct file_operations openpromfs_nodenum_ops = { |
591 | .read = nodenum_read, | 591 | .read = nodenum_read, |
592 | }; | 592 | }; |
593 | 593 | ||
594 | static struct file_operations openprom_operations = { | 594 | static const struct file_operations openprom_operations = { |
595 | .read = generic_read_dir, | 595 | .read = generic_read_dir, |
596 | .readdir = openpromfs_readdir, | 596 | .readdir = openpromfs_readdir, |
597 | }; | 597 | }; |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f924f459bdb8..af0cb4b9e784 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -297,6 +297,25 @@ struct kobj_type ktype_part = { | |||
297 | .sysfs_ops = &part_sysfs_ops, | 297 | .sysfs_ops = &part_sysfs_ops, |
298 | }; | 298 | }; |
299 | 299 | ||
300 | static inline void partition_sysfs_add_subdir(struct hd_struct *p) | ||
301 | { | ||
302 | struct kobject *k; | ||
303 | |||
304 | k = kobject_get(&p->kobj); | ||
305 | p->holder_dir = kobject_add_dir(k, "holders"); | ||
306 | kobject_put(k); | ||
307 | } | ||
308 | |||
309 | static inline void disk_sysfs_add_subdirs(struct gendisk *disk) | ||
310 | { | ||
311 | struct kobject *k; | ||
312 | |||
313 | k = kobject_get(&disk->kobj); | ||
314 | disk->holder_dir = kobject_add_dir(k, "holders"); | ||
315 | disk->slave_dir = kobject_add_dir(k, "slaves"); | ||
316 | kobject_put(k); | ||
317 | } | ||
318 | |||
300 | void delete_partition(struct gendisk *disk, int part) | 319 | void delete_partition(struct gendisk *disk, int part) |
301 | { | 320 | { |
302 | struct hd_struct *p = disk->part[part-1]; | 321 | struct hd_struct *p = disk->part[part-1]; |
@@ -310,6 +329,8 @@ void delete_partition(struct gendisk *disk, int part) | |||
310 | p->ios[0] = p->ios[1] = 0; | 329 | p->ios[0] = p->ios[1] = 0; |
311 | p->sectors[0] = p->sectors[1] = 0; | 330 | p->sectors[0] = p->sectors[1] = 0; |
312 | devfs_remove("%s/part%d", disk->devfs_name, part); | 331 | devfs_remove("%s/part%d", disk->devfs_name, part); |
332 | if (p->holder_dir) | ||
333 | kobject_unregister(p->holder_dir); | ||
313 | kobject_unregister(&p->kobj); | 334 | kobject_unregister(&p->kobj); |
314 | } | 335 | } |
315 | 336 | ||
@@ -337,6 +358,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | |||
337 | p->kobj.parent = &disk->kobj; | 358 | p->kobj.parent = &disk->kobj; |
338 | p->kobj.ktype = &ktype_part; | 359 | p->kobj.ktype = &ktype_part; |
339 | kobject_register(&p->kobj); | 360 | kobject_register(&p->kobj); |
361 | partition_sysfs_add_subdir(p); | ||
340 | disk->part[part-1] = p; | 362 | disk->part[part-1] = p; |
341 | } | 363 | } |
342 | 364 | ||
@@ -383,6 +405,7 @@ void register_disk(struct gendisk *disk) | |||
383 | if ((err = kobject_add(&disk->kobj))) | 405 | if ((err = kobject_add(&disk->kobj))) |
384 | return; | 406 | return; |
385 | disk_sysfs_symlinks(disk); | 407 | disk_sysfs_symlinks(disk); |
408 | disk_sysfs_add_subdirs(disk); | ||
386 | kobject_uevent(&disk->kobj, KOBJ_ADD); | 409 | kobject_uevent(&disk->kobj, KOBJ_ADD); |
387 | 410 | ||
388 | /* No minors to use for partitions */ | 411 | /* No minors to use for partitions */ |
@@ -483,6 +506,10 @@ void del_gendisk(struct gendisk *disk) | |||
483 | 506 | ||
484 | devfs_remove_disk(disk); | 507 | devfs_remove_disk(disk); |
485 | 508 | ||
509 | if (disk->holder_dir) | ||
510 | kobject_unregister(disk->holder_dir); | ||
511 | if (disk->slave_dir) | ||
512 | kobject_unregister(disk->slave_dir); | ||
486 | if (disk->driverfs_dev) { | 513 | if (disk->driverfs_dev) { |
487 | char *disk_name = make_block_name(disk); | 514 | char *disk_name = make_block_name(disk); |
488 | sysfs_remove_link(&disk->kobj, "device"); | 515 | sysfs_remove_link(&disk->kobj, "device"); |
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c index bb22cdd0cb14..813292f21210 100644 --- a/fs/partitions/mac.c +++ b/fs/partitions/mac.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "mac.h" | 12 | #include "mac.h" |
13 | 13 | ||
14 | #ifdef CONFIG_PPC_PMAC | 14 | #ifdef CONFIG_PPC_PMAC |
15 | #include <asm/machdep.h> | ||
15 | extern void note_bootable_part(dev_t dev, int part, int goodness); | 16 | extern void note_bootable_part(dev_t dev, int part, int goodness); |
16 | #endif | 17 | #endif |
17 | 18 | ||
@@ -79,7 +80,7 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
79 | * If this is the first bootable partition, tell the | 80 | * If this is the first bootable partition, tell the |
80 | * setup code, in case it wants to make this the root. | 81 | * setup code, in case it wants to make this the root. |
81 | */ | 82 | */ |
82 | if (_machine == _MACH_Pmac) { | 83 | if (machine_is(powermac)) { |
83 | int goodness = 0; | 84 | int goodness = 0; |
84 | 85 | ||
85 | mac_fix_string(part->processor, 16); | 86 | mac_fix_string(part->processor, 16); |
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pipe_fs_i.h> | 15 | #include <linux/pipe_fs_i.h> |
16 | #include <linux/uio.h> | 16 | #include <linux/uio.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/pagemap.h> | ||
18 | 19 | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include <asm/ioctls.h> | 21 | #include <asm/ioctls.h> |
@@ -94,11 +95,20 @@ static void anon_pipe_buf_release(struct pipe_inode_info *info, struct pipe_buff | |||
94 | { | 95 | { |
95 | struct page *page = buf->page; | 96 | struct page *page = buf->page; |
96 | 97 | ||
97 | if (info->tmp_page) { | 98 | /* |
98 | __free_page(page); | 99 | * If nobody else uses this page, and we don't already have a |
100 | * temporary page, let's keep track of it as a one-deep | ||
101 | * allocation cache | ||
102 | */ | ||
103 | if (page_count(page) == 1 && !info->tmp_page) { | ||
104 | info->tmp_page = page; | ||
99 | return; | 105 | return; |
100 | } | 106 | } |
101 | info->tmp_page = page; | 107 | |
108 | /* | ||
109 | * Otherwise just release our reference to it | ||
110 | */ | ||
111 | page_cache_release(page); | ||
102 | } | 112 | } |
103 | 113 | ||
104 | static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf) | 114 | static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf) |
@@ -111,11 +121,19 @@ static void anon_pipe_buf_unmap(struct pipe_inode_info *info, struct pipe_buffer | |||
111 | kunmap(buf->page); | 121 | kunmap(buf->page); |
112 | } | 122 | } |
113 | 123 | ||
124 | static int anon_pipe_buf_steal(struct pipe_inode_info *info, | ||
125 | struct pipe_buffer *buf) | ||
126 | { | ||
127 | buf->stolen = 1; | ||
128 | return 0; | ||
129 | } | ||
130 | |||
114 | static struct pipe_buf_operations anon_pipe_buf_ops = { | 131 | static struct pipe_buf_operations anon_pipe_buf_ops = { |
115 | .can_merge = 1, | 132 | .can_merge = 1, |
116 | .map = anon_pipe_buf_map, | 133 | .map = anon_pipe_buf_map, |
117 | .unmap = anon_pipe_buf_unmap, | 134 | .unmap = anon_pipe_buf_unmap, |
118 | .release = anon_pipe_buf_release, | 135 | .release = anon_pipe_buf_release, |
136 | .steal = anon_pipe_buf_steal, | ||
119 | }; | 137 | }; |
120 | 138 | ||
121 | static ssize_t | 139 | static ssize_t |
@@ -152,6 +170,11 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
152 | chars = total_len; | 170 | chars = total_len; |
153 | 171 | ||
154 | addr = ops->map(filp, info, buf); | 172 | addr = ops->map(filp, info, buf); |
173 | if (IS_ERR(addr)) { | ||
174 | if (!ret) | ||
175 | ret = PTR_ERR(addr); | ||
176 | break; | ||
177 | } | ||
155 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); | 178 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); |
156 | ops->unmap(info, buf); | 179 | ops->unmap(info, buf); |
157 | if (unlikely(error)) { | 180 | if (unlikely(error)) { |
@@ -254,8 +277,16 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
254 | struct pipe_buf_operations *ops = buf->ops; | 277 | struct pipe_buf_operations *ops = buf->ops; |
255 | int offset = buf->offset + buf->len; | 278 | int offset = buf->offset + buf->len; |
256 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { | 279 | if (ops->can_merge && offset + chars <= PAGE_SIZE) { |
257 | void *addr = ops->map(filp, info, buf); | 280 | void *addr; |
258 | int error = pipe_iov_copy_from_user(offset + addr, iov, chars); | 281 | int error; |
282 | |||
283 | addr = ops->map(filp, info, buf); | ||
284 | if (IS_ERR(addr)) { | ||
285 | error = PTR_ERR(addr); | ||
286 | goto out; | ||
287 | } | ||
288 | error = pipe_iov_copy_from_user(offset + addr, iov, | ||
289 | chars); | ||
259 | ops->unmap(info, buf); | 290 | ops->unmap(info, buf); |
260 | ret = error; | 291 | ret = error; |
261 | do_wakeup = 1; | 292 | do_wakeup = 1; |
@@ -568,7 +599,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp) | |||
568 | * The file_operations structs are not static because they | 599 | * The file_operations structs are not static because they |
569 | * are also used in linux/fs/fifo.c to do operations on FIFOs. | 600 | * are also used in linux/fs/fifo.c to do operations on FIFOs. |
570 | */ | 601 | */ |
571 | struct file_operations read_fifo_fops = { | 602 | const struct file_operations read_fifo_fops = { |
572 | .llseek = no_llseek, | 603 | .llseek = no_llseek, |
573 | .read = pipe_read, | 604 | .read = pipe_read, |
574 | .readv = pipe_readv, | 605 | .readv = pipe_readv, |
@@ -580,7 +611,7 @@ struct file_operations read_fifo_fops = { | |||
580 | .fasync = pipe_read_fasync, | 611 | .fasync = pipe_read_fasync, |
581 | }; | 612 | }; |
582 | 613 | ||
583 | struct file_operations write_fifo_fops = { | 614 | const struct file_operations write_fifo_fops = { |
584 | .llseek = no_llseek, | 615 | .llseek = no_llseek, |
585 | .read = bad_pipe_r, | 616 | .read = bad_pipe_r, |
586 | .write = pipe_write, | 617 | .write = pipe_write, |
@@ -592,7 +623,7 @@ struct file_operations write_fifo_fops = { | |||
592 | .fasync = pipe_write_fasync, | 623 | .fasync = pipe_write_fasync, |
593 | }; | 624 | }; |
594 | 625 | ||
595 | struct file_operations rdwr_fifo_fops = { | 626 | const struct file_operations rdwr_fifo_fops = { |
596 | .llseek = no_llseek, | 627 | .llseek = no_llseek, |
597 | .read = pipe_read, | 628 | .read = pipe_read, |
598 | .readv = pipe_readv, | 629 | .readv = pipe_readv, |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 47b7a20d45eb..4ba03009cf72 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -560,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) | |||
560 | struct file * filp = list_entry(p, struct file, f_u.fu_list); | 560 | struct file * filp = list_entry(p, struct file, f_u.fu_list); |
561 | struct dentry * dentry = filp->f_dentry; | 561 | struct dentry * dentry = filp->f_dentry; |
562 | struct inode * inode; | 562 | struct inode * inode; |
563 | struct file_operations *fops; | 563 | const struct file_operations *fops; |
564 | 564 | ||
565 | if (dentry->d_op != &proc_dentry_operations) | 565 | if (dentry->d_op != &proc_dentry_operations) |
566 | continue; | 566 | continue; |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 95a1cf32b838..0502f17b860d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -30,7 +30,7 @@ do { \ | |||
30 | 30 | ||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); | 33 | extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); |
34 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); | 34 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); |
35 | extern int proc_tid_stat(struct task_struct *, char *); | 35 | extern int proc_tid_stat(struct task_struct *, char *); |
36 | extern int proc_tgid_stat(struct task_struct *, char *); | 36 | extern int proc_tgid_stat(struct task_struct *, char *); |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index adc2cd95169a..17f6e8fa1397 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp) | |||
31 | 31 | ||
32 | static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); | 32 | static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); |
33 | 33 | ||
34 | struct file_operations proc_kcore_operations = { | 34 | const struct file_operations proc_kcore_operations = { |
35 | .read = read_kcore, | 35 | .read = read_kcore, |
36 | .open = open_kcore, | 36 | .open = open_kcore, |
37 | }; | 37 | }; |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index 10d37bf25206..ff3b90b56e9d 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
@@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | 49 | ||
50 | struct file_operations proc_kmsg_operations = { | 50 | const struct file_operations proc_kmsg_operations = { |
51 | .read = kmsg_read, | 51 | .read = kmsg_read, |
52 | .poll = kmsg_poll, | 52 | .poll = kmsg_poll, |
53 | .open = kmsg_open, | 53 | .open = kmsg_open, |
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 596b4b4f1cc8..abdf068bc27f 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c | |||
@@ -52,7 +52,8 @@ static int property_read_proc(char *page, char **start, off_t off, | |||
52 | * Add a property to a node | 52 | * Add a property to a node |
53 | */ | 53 | */ |
54 | static struct proc_dir_entry * | 54 | static struct proc_dir_entry * |
55 | __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) | 55 | __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp, |
56 | const char *name) | ||
56 | { | 57 | { |
57 | struct proc_dir_entry *ent; | 58 | struct proc_dir_entry *ent; |
58 | 59 | ||
@@ -60,14 +61,14 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) | |||
60 | * Unfortunately proc_register puts each new entry | 61 | * Unfortunately proc_register puts each new entry |
61 | * at the beginning of the list. So we rearrange them. | 62 | * at the beginning of the list. So we rearrange them. |
62 | */ | 63 | */ |
63 | ent = create_proc_read_entry(pp->name, | 64 | ent = create_proc_read_entry(name, |
64 | strncmp(pp->name, "security-", 9) | 65 | strncmp(name, "security-", 9) |
65 | ? S_IRUGO : S_IRUSR, de, | 66 | ? S_IRUGO : S_IRUSR, de, |
66 | property_read_proc, pp); | 67 | property_read_proc, pp); |
67 | if (ent == NULL) | 68 | if (ent == NULL) |
68 | return NULL; | 69 | return NULL; |
69 | 70 | ||
70 | if (!strncmp(pp->name, "security-", 9)) | 71 | if (!strncmp(name, "security-", 9)) |
71 | ent->size = 0; /* don't leak number of password chars */ | 72 | ent->size = 0; /* don't leak number of password chars */ |
72 | else | 73 | else |
73 | ent->size = pp->length; | 74 | ent->size = pp->length; |
@@ -78,7 +79,7 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) | |||
78 | 79 | ||
79 | void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) | 80 | void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) |
80 | { | 81 | { |
81 | __proc_device_tree_add_prop(pde, prop); | 82 | __proc_device_tree_add_prop(pde, prop, prop->name); |
82 | } | 83 | } |
83 | 84 | ||
84 | void proc_device_tree_remove_prop(struct proc_dir_entry *pde, | 85 | void proc_device_tree_remove_prop(struct proc_dir_entry *pde, |
@@ -106,6 +107,69 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde, | |||
106 | } | 107 | } |
107 | 108 | ||
108 | /* | 109 | /* |
110 | * Various dodgy firmware might give us nodes and/or properties with | ||
111 | * conflicting names. That's generally ok, except for exporting via /proc, | ||
112 | * so munge names here to ensure they're unique. | ||
113 | */ | ||
114 | |||
115 | static int duplicate_name(struct proc_dir_entry *de, const char *name) | ||
116 | { | ||
117 | struct proc_dir_entry *ent; | ||
118 | int found = 0; | ||
119 | |||
120 | spin_lock(&proc_subdir_lock); | ||
121 | |||
122 | for (ent = de->subdir; ent != NULL; ent = ent->next) { | ||
123 | if (strcmp(ent->name, name) == 0) { | ||
124 | found = 1; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | spin_unlock(&proc_subdir_lock); | ||
130 | |||
131 | return found; | ||
132 | } | ||
133 | |||
134 | static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de, | ||
135 | const char *name) | ||
136 | { | ||
137 | char *fixed_name; | ||
138 | int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */ | ||
139 | int i = 1, size; | ||
140 | |||
141 | realloc: | ||
142 | fixed_name = kmalloc(fixup_len, GFP_KERNEL); | ||
143 | if (fixed_name == NULL) { | ||
144 | printk(KERN_ERR "device-tree: Out of memory trying to fixup " | ||
145 | "name \"%s\"\n", name); | ||
146 | return name; | ||
147 | } | ||
148 | |||
149 | retry: | ||
150 | size = snprintf(fixed_name, fixup_len, "%s#%d", name, i); | ||
151 | size++; /* account for NULL */ | ||
152 | |||
153 | if (size > fixup_len) { | ||
154 | /* We ran out of space, free and reallocate. */ | ||
155 | kfree(fixed_name); | ||
156 | fixup_len = size; | ||
157 | goto realloc; | ||
158 | } | ||
159 | |||
160 | if (duplicate_name(de, fixed_name)) { | ||
161 | /* Multiple duplicates. Retry with a different offset. */ | ||
162 | i++; | ||
163 | goto retry; | ||
164 | } | ||
165 | |||
166 | printk(KERN_WARNING "device-tree: Duplicate name in %s, " | ||
167 | "renamed to \"%s\"\n", np->full_name, fixed_name); | ||
168 | |||
169 | return fixed_name; | ||
170 | } | ||
171 | |||
172 | /* | ||
109 | * Process a node, adding entries for its children and its properties. | 173 | * Process a node, adding entries for its children and its properties. |
110 | */ | 174 | */ |
111 | void proc_device_tree_add_node(struct device_node *np, | 175 | void proc_device_tree_add_node(struct device_node *np, |
@@ -118,37 +182,30 @@ void proc_device_tree_add_node(struct device_node *np, | |||
118 | 182 | ||
119 | set_node_proc_entry(np, de); | 183 | set_node_proc_entry(np, de); |
120 | for (child = NULL; (child = of_get_next_child(np, child));) { | 184 | for (child = NULL; (child = of_get_next_child(np, child));) { |
185 | /* Use everything after the last slash, or the full name */ | ||
121 | p = strrchr(child->full_name, '/'); | 186 | p = strrchr(child->full_name, '/'); |
122 | if (!p) | 187 | if (!p) |
123 | p = child->full_name; | 188 | p = child->full_name; |
124 | else | 189 | else |
125 | ++p; | 190 | ++p; |
191 | |||
192 | if (duplicate_name(de, p)) | ||
193 | p = fixup_name(np, de, p); | ||
194 | |||
126 | ent = proc_mkdir(p, de); | 195 | ent = proc_mkdir(p, de); |
127 | if (ent == 0) | 196 | if (ent == 0) |
128 | break; | 197 | break; |
129 | proc_device_tree_add_node(child, ent); | 198 | proc_device_tree_add_node(child, ent); |
130 | } | 199 | } |
131 | of_node_put(child); | 200 | of_node_put(child); |
201 | |||
132 | for (pp = np->properties; pp != 0; pp = pp->next) { | 202 | for (pp = np->properties; pp != 0; pp = pp->next) { |
133 | /* | 203 | p = pp->name; |
134 | * Yet another Apple device-tree bogosity: on some machines, | 204 | |
135 | * they have properties & nodes with the same name. Those | 205 | if (duplicate_name(de, p)) |
136 | * properties are quite unimportant for us though, thus we | 206 | p = fixup_name(np, de, p); |
137 | * simply "skip" them here, but we do have to check. | ||
138 | */ | ||
139 | spin_lock(&proc_subdir_lock); | ||
140 | for (ent = de->subdir; ent != NULL; ent = ent->next) | ||
141 | if (!strcmp(ent->name, pp->name)) | ||
142 | break; | ||
143 | spin_unlock(&proc_subdir_lock); | ||
144 | if (ent != NULL) { | ||
145 | printk(KERN_WARNING "device-tree: property \"%s\" name" | ||
146 | " conflicts with node in %s\n", pp->name, | ||
147 | np->full_name); | ||
148 | continue; | ||
149 | } | ||
150 | 207 | ||
151 | ent = __proc_device_tree_add_prop(de, pp); | 208 | ent = __proc_device_tree_add_prop(de, pp, p); |
152 | if (ent == 0) | 209 | if (ent == 0) |
153 | break; | 210 | break; |
154 | } | 211 | } |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 1e9ea37d457e..ef5a3323f4b5 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -534,7 +534,7 @@ static int show_stat(struct seq_file *p, void *v) | |||
534 | if (wall_to_monotonic.tv_nsec) | 534 | if (wall_to_monotonic.tv_nsec) |
535 | --jif; | 535 | --jif; |
536 | 536 | ||
537 | for_each_cpu(i) { | 537 | for_each_possible_cpu(i) { |
538 | int j; | 538 | int j; |
539 | 539 | ||
540 | user = cputime64_add(user, kstat_cpu(i).cpustat.user); | 540 | user = cputime64_add(user, kstat_cpu(i).cpustat.user); |
@@ -731,7 +731,7 @@ static struct file_operations proc_sysrq_trigger_operations = { | |||
731 | 731 | ||
732 | struct proc_dir_entry *proc_root_kcore; | 732 | struct proc_dir_entry *proc_root_kcore; |
733 | 733 | ||
734 | void create_seq_entry(char *name, mode_t mode, struct file_operations *f) | 734 | void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) |
735 | { | 735 | { |
736 | struct proc_dir_entry *entry; | 736 | struct proc_dir_entry *entry; |
737 | entry = create_proc_entry(name, mode, NULL); | 737 | entry = create_proc_entry(name, mode, NULL); |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 4063fb32f78c..7efa73d44c9a 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
@@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp) | |||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | struct file_operations proc_vmcore_operations = { | 175 | const struct file_operations proc_vmcore_operations = { |
176 | .read = read_vmcore, | 176 | .read = read_vmcore, |
177 | .open = open_vmcore, | 177 | .open = open_vmcore, |
178 | }; | 178 | }; |
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 7a8f5595c26f..9031948fefd0 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c | |||
@@ -81,7 +81,7 @@ out: | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | struct file_operations qnx4_dir_operations = | 84 | const struct file_operations qnx4_dir_operations = |
85 | { | 85 | { |
86 | .read = generic_read_dir, | 86 | .read = generic_read_dir, |
87 | .readdir = qnx4_readdir, | 87 | .readdir = qnx4_readdir, |
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index c33963fded9e..62af4b1348bd 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * We have mostly NULL's here: the current defaults are ok for | 19 | * We have mostly NULL's here: the current defaults are ok for |
20 | * the qnx4 filesystem. | 20 | * the qnx4 filesystem. |
21 | */ | 21 | */ |
22 | struct file_operations qnx4_file_operations = | 22 | const struct file_operations qnx4_file_operations = |
23 | { | 23 | { |
24 | .llseek = generic_file_llseek, | 24 | .llseek = generic_file_llseek, |
25 | .read = generic_file_read, | 25 | .read = generic_file_read, |
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 6ada2095b9ac..00a933eb820c 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c | |||
@@ -32,7 +32,7 @@ struct address_space_operations ramfs_aops = { | |||
32 | .commit_write = simple_commit_write | 32 | .commit_write = simple_commit_write |
33 | }; | 33 | }; |
34 | 34 | ||
35 | struct file_operations ramfs_file_operations = { | 35 | const struct file_operations ramfs_file_operations = { |
36 | .read = generic_file_read, | 36 | .read = generic_file_read, |
37 | .write = generic_file_write, | 37 | .write = generic_file_write, |
38 | .mmap = generic_file_mmap, | 38 | .mmap = generic_file_mmap, |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index b1ca234068f6..f443a84b98a5 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -33,7 +33,7 @@ struct address_space_operations ramfs_aops = { | |||
33 | .commit_write = simple_commit_write | 33 | .commit_write = simple_commit_write |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct file_operations ramfs_file_operations = { | 36 | const struct file_operations ramfs_file_operations = { |
37 | .mmap = ramfs_nommu_mmap, | 37 | .mmap = ramfs_nommu_mmap, |
38 | .get_unmapped_area = ramfs_nommu_get_unmapped_area, | 38 | .get_unmapped_area = ramfs_nommu_get_unmapped_area, |
39 | .read = generic_file_read, | 39 | .read = generic_file_read, |
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index 272c8a7120b0..313237631b49 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h | |||
@@ -11,5 +11,5 @@ | |||
11 | 11 | ||
12 | 12 | ||
13 | extern struct address_space_operations ramfs_aops; | 13 | extern struct address_space_operations ramfs_aops; |
14 | extern struct file_operations ramfs_file_operations; | 14 | extern const struct file_operations ramfs_file_operations; |
15 | extern struct inode_operations ramfs_file_inode_operations; | 15 | extern struct inode_operations ramfs_file_inode_operations; |
diff --git a/fs/read_write.c b/fs/read_write.c index 34b1bf259efd..6256ca81a718 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include <asm/unistd.h> | 20 | #include <asm/unistd.h> |
21 | 21 | ||
22 | struct file_operations generic_ro_fops = { | 22 | const struct file_operations generic_ro_fops = { |
23 | .llseek = generic_file_llseek, | 23 | .llseek = generic_file_llseek, |
24 | .read = generic_file_read, | 24 | .read = generic_file_read, |
25 | .mmap = generic_file_readonly_mmap, | 25 | .mmap = generic_file_readonly_mmap, |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d71ac6579289..973c819f8033 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
@@ -18,7 +18,7 @@ static int reiserfs_readdir(struct file *, void *, filldir_t); | |||
18 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, | 18 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, |
19 | int datasync); | 19 | int datasync); |
20 | 20 | ||
21 | struct file_operations reiserfs_dir_operations = { | 21 | const struct file_operations reiserfs_dir_operations = { |
22 | .read = generic_read_dir, | 22 | .read = generic_read_dir, |
23 | .readdir = reiserfs_readdir, | 23 | .readdir = reiserfs_readdir, |
24 | .fsync = reiserfs_dir_fsync, | 24 | .fsync = reiserfs_dir_fsync, |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index d0c1e865963e..cf6e1cf40351 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -1566,7 +1566,7 @@ static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf, | |||
1566 | return generic_file_aio_write(iocb, buf, count, pos); | 1566 | return generic_file_aio_write(iocb, buf, count, pos); |
1567 | } | 1567 | } |
1568 | 1568 | ||
1569 | struct file_operations reiserfs_file_operations = { | 1569 | const struct file_operations reiserfs_file_operations = { |
1570 | .read = generic_file_read, | 1570 | .read = generic_file_read, |
1571 | .write = reiserfs_file_write, | 1571 | .write = reiserfs_file_write, |
1572 | .ioctl = reiserfs_ioctl, | 1572 | .ioctl = reiserfs_ioctl, |
@@ -1576,6 +1576,8 @@ struct file_operations reiserfs_file_operations = { | |||
1576 | .sendfile = generic_file_sendfile, | 1576 | .sendfile = generic_file_sendfile, |
1577 | .aio_read = generic_file_aio_read, | 1577 | .aio_read = generic_file_aio_read, |
1578 | .aio_write = reiserfs_aio_write, | 1578 | .aio_write = reiserfs_aio_write, |
1579 | .splice_read = generic_file_splice_read, | ||
1580 | .splice_write = generic_file_splice_write, | ||
1579 | }; | 1581 | }; |
1580 | 1582 | ||
1581 | struct inode_operations reiserfs_file_inode_operations = { | 1583 | struct inode_operations reiserfs_file_inode_operations = { |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index ef6caed9336b..731688e1cfe3 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
@@ -470,7 +470,7 @@ static int r_open(struct inode *inode, struct file *file) | |||
470 | return ret; | 470 | return ret; |
471 | } | 471 | } |
472 | 472 | ||
473 | static struct file_operations r_file_operations = { | 473 | static const struct file_operations r_file_operations = { |
474 | .open = r_open, | 474 | .open = r_open, |
475 | .read = seq_read, | 475 | .read = seq_read, |
476 | .llseek = seq_lseek, | 476 | .llseek = seq_lseek, |
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index c2fc424d7d5c..9b9eda7b335c 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
@@ -463,7 +463,7 @@ static struct address_space_operations romfs_aops = { | |||
463 | .readpage = romfs_readpage | 463 | .readpage = romfs_readpage |
464 | }; | 464 | }; |
465 | 465 | ||
466 | static struct file_operations romfs_dir_operations = { | 466 | static const struct file_operations romfs_dir_operations = { |
467 | .read = generic_read_dir, | 467 | .read = generic_read_dir, |
468 | .readdir = romfs_readdir, | 468 | .readdir = romfs_readdir, |
469 | }; | 469 | }; |
diff --git a/fs/select.c b/fs/select.c index 1815a57d2255..b3a3a1326af6 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -29,12 +29,6 @@ | |||
29 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) | 29 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) |
30 | #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) | 30 | #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) |
31 | 31 | ||
32 | struct poll_table_entry { | ||
33 | struct file * filp; | ||
34 | wait_queue_t wait; | ||
35 | wait_queue_head_t * wait_address; | ||
36 | }; | ||
37 | |||
38 | struct poll_table_page { | 32 | struct poll_table_page { |
39 | struct poll_table_page * next; | 33 | struct poll_table_page * next; |
40 | struct poll_table_entry * entry; | 34 | struct poll_table_entry * entry; |
@@ -64,13 +58,23 @@ void poll_initwait(struct poll_wqueues *pwq) | |||
64 | init_poll_funcptr(&pwq->pt, __pollwait); | 58 | init_poll_funcptr(&pwq->pt, __pollwait); |
65 | pwq->error = 0; | 59 | pwq->error = 0; |
66 | pwq->table = NULL; | 60 | pwq->table = NULL; |
61 | pwq->inline_index = 0; | ||
67 | } | 62 | } |
68 | 63 | ||
69 | EXPORT_SYMBOL(poll_initwait); | 64 | EXPORT_SYMBOL(poll_initwait); |
70 | 65 | ||
66 | static void free_poll_entry(struct poll_table_entry *entry) | ||
67 | { | ||
68 | remove_wait_queue(entry->wait_address,&entry->wait); | ||
69 | fput(entry->filp); | ||
70 | } | ||
71 | |||
71 | void poll_freewait(struct poll_wqueues *pwq) | 72 | void poll_freewait(struct poll_wqueues *pwq) |
72 | { | 73 | { |
73 | struct poll_table_page * p = pwq->table; | 74 | struct poll_table_page * p = pwq->table; |
75 | int i; | ||
76 | for (i = 0; i < pwq->inline_index; i++) | ||
77 | free_poll_entry(pwq->inline_entries + i); | ||
74 | while (p) { | 78 | while (p) { |
75 | struct poll_table_entry * entry; | 79 | struct poll_table_entry * entry; |
76 | struct poll_table_page *old; | 80 | struct poll_table_page *old; |
@@ -78,8 +82,7 @@ void poll_freewait(struct poll_wqueues *pwq) | |||
78 | entry = p->entry; | 82 | entry = p->entry; |
79 | do { | 83 | do { |
80 | entry--; | 84 | entry--; |
81 | remove_wait_queue(entry->wait_address,&entry->wait); | 85 | free_poll_entry(entry); |
82 | fput(entry->filp); | ||
83 | } while (entry > p->entries); | 86 | } while (entry > p->entries); |
84 | old = p; | 87 | old = p; |
85 | p = p->next; | 88 | p = p->next; |
@@ -89,12 +92,14 @@ void poll_freewait(struct poll_wqueues *pwq) | |||
89 | 92 | ||
90 | EXPORT_SYMBOL(poll_freewait); | 93 | EXPORT_SYMBOL(poll_freewait); |
91 | 94 | ||
92 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | 95 | static struct poll_table_entry *poll_get_entry(poll_table *_p) |
93 | poll_table *_p) | ||
94 | { | 96 | { |
95 | struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); | 97 | struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); |
96 | struct poll_table_page *table = p->table; | 98 | struct poll_table_page *table = p->table; |
97 | 99 | ||
100 | if (p->inline_index < N_INLINE_POLL_ENTRIES) | ||
101 | return p->inline_entries + p->inline_index++; | ||
102 | |||
98 | if (!table || POLL_TABLE_FULL(table)) { | 103 | if (!table || POLL_TABLE_FULL(table)) { |
99 | struct poll_table_page *new_table; | 104 | struct poll_table_page *new_table; |
100 | 105 | ||
@@ -102,7 +107,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
102 | if (!new_table) { | 107 | if (!new_table) { |
103 | p->error = -ENOMEM; | 108 | p->error = -ENOMEM; |
104 | __set_current_state(TASK_RUNNING); | 109 | __set_current_state(TASK_RUNNING); |
105 | return; | 110 | return NULL; |
106 | } | 111 | } |
107 | new_table->entry = new_table->entries; | 112 | new_table->entry = new_table->entries; |
108 | new_table->next = table; | 113 | new_table->next = table; |
@@ -110,16 +115,21 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
110 | table = new_table; | 115 | table = new_table; |
111 | } | 116 | } |
112 | 117 | ||
113 | /* Add a new entry */ | 118 | return table->entry++; |
114 | { | 119 | } |
115 | struct poll_table_entry * entry = table->entry; | 120 | |
116 | table->entry = entry+1; | 121 | /* Add a new entry */ |
117 | get_file(filp); | 122 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, |
118 | entry->filp = filp; | 123 | poll_table *p) |
119 | entry->wait_address = wait_address; | 124 | { |
120 | init_waitqueue_entry(&entry->wait, current); | 125 | struct poll_table_entry *entry = poll_get_entry(p); |
121 | add_wait_queue(wait_address,&entry->wait); | 126 | if (!entry) |
122 | } | 127 | return; |
128 | get_file(filp); | ||
129 | entry->filp = filp; | ||
130 | entry->wait_address = wait_address; | ||
131 | init_waitqueue_entry(&entry->wait, current); | ||
132 | add_wait_queue(wait_address,&entry->wait); | ||
123 | } | 133 | } |
124 | 134 | ||
125 | #define FDS_IN(fds, n) (fds->in + n) | 135 | #define FDS_IN(fds, n) (fds->in + n) |
@@ -210,7 +220,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
210 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { | 220 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { |
211 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; | 221 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; |
212 | unsigned long res_in = 0, res_out = 0, res_ex = 0; | 222 | unsigned long res_in = 0, res_out = 0, res_ex = 0; |
213 | struct file_operations *f_op = NULL; | 223 | const struct file_operations *f_op = NULL; |
214 | struct file *file = NULL; | 224 | struct file *file = NULL; |
215 | 225 | ||
216 | in = *inp++; out = *outp++; ex = *exp++; | 226 | in = *inp++; out = *outp++; ex = *exp++; |
@@ -221,17 +231,18 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
221 | } | 231 | } |
222 | 232 | ||
223 | for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { | 233 | for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { |
234 | int fput_needed; | ||
224 | if (i >= n) | 235 | if (i >= n) |
225 | break; | 236 | break; |
226 | if (!(bit & all_bits)) | 237 | if (!(bit & all_bits)) |
227 | continue; | 238 | continue; |
228 | file = fget(i); | 239 | file = fget_light(i, &fput_needed); |
229 | if (file) { | 240 | if (file) { |
230 | f_op = file->f_op; | 241 | f_op = file->f_op; |
231 | mask = DEFAULT_POLLMASK; | 242 | mask = DEFAULT_POLLMASK; |
232 | if (f_op && f_op->poll) | 243 | if (f_op && f_op->poll) |
233 | mask = (*f_op->poll)(file, retval ? NULL : wait); | 244 | mask = (*f_op->poll)(file, retval ? NULL : wait); |
234 | fput(file); | 245 | fput_light(file, fput_needed); |
235 | if ((mask & POLLIN_SET) && (in & bit)) { | 246 | if ((mask & POLLIN_SET) && (in & bit)) { |
236 | res_in |= bit; | 247 | res_in |= bit; |
237 | retval++; | 248 | retval++; |
@@ -284,16 +295,6 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
284 | return retval; | 295 | return retval; |
285 | } | 296 | } |
286 | 297 | ||
287 | static void *select_bits_alloc(int size) | ||
288 | { | ||
289 | return kmalloc(6 * size, GFP_KERNEL); | ||
290 | } | ||
291 | |||
292 | static void select_bits_free(void *bits, int size) | ||
293 | { | ||
294 | kfree(bits); | ||
295 | } | ||
296 | |||
297 | /* | 298 | /* |
298 | * We can actually return ERESTARTSYS instead of EINTR, but I'd | 299 | * We can actually return ERESTARTSYS instead of EINTR, but I'd |
299 | * like to be certain this leads to no problems. So I return | 300 | * like to be certain this leads to no problems. So I return |
@@ -312,6 +313,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
312 | char *bits; | 313 | char *bits; |
313 | int ret, size, max_fdset; | 314 | int ret, size, max_fdset; |
314 | struct fdtable *fdt; | 315 | struct fdtable *fdt; |
316 | /* Allocate small arguments on the stack to save memory and be faster */ | ||
317 | char stack_fds[SELECT_STACK_ALLOC]; | ||
315 | 318 | ||
316 | ret = -EINVAL; | 319 | ret = -EINVAL; |
317 | if (n < 0) | 320 | if (n < 0) |
@@ -332,7 +335,10 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
332 | */ | 335 | */ |
333 | ret = -ENOMEM; | 336 | ret = -ENOMEM; |
334 | size = FDS_BYTES(n); | 337 | size = FDS_BYTES(n); |
335 | bits = select_bits_alloc(size); | 338 | if (6*size < SELECT_STACK_ALLOC) |
339 | bits = stack_fds; | ||
340 | else | ||
341 | bits = kmalloc(6 * size, GFP_KERNEL); | ||
336 | if (!bits) | 342 | if (!bits) |
337 | goto out_nofds; | 343 | goto out_nofds; |
338 | fds.in = (unsigned long *) bits; | 344 | fds.in = (unsigned long *) bits; |
@@ -367,7 +373,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
367 | ret = -EFAULT; | 373 | ret = -EFAULT; |
368 | 374 | ||
369 | out: | 375 | out: |
370 | select_bits_free(bits, size); | 376 | if (bits != stack_fds) |
377 | kfree(bits); | ||
371 | out_nofds: | 378 | out_nofds: |
372 | return ret; | 379 | return ret; |
373 | } | 380 | } |
@@ -551,14 +558,15 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage, | |||
551 | fdp = fdpage+i; | 558 | fdp = fdpage+i; |
552 | fd = fdp->fd; | 559 | fd = fdp->fd; |
553 | if (fd >= 0) { | 560 | if (fd >= 0) { |
554 | struct file * file = fget(fd); | 561 | int fput_needed; |
562 | struct file * file = fget_light(fd, &fput_needed); | ||
555 | mask = POLLNVAL; | 563 | mask = POLLNVAL; |
556 | if (file != NULL) { | 564 | if (file != NULL) { |
557 | mask = DEFAULT_POLLMASK; | 565 | mask = DEFAULT_POLLMASK; |
558 | if (file->f_op && file->f_op->poll) | 566 | if (file->f_op && file->f_op->poll) |
559 | mask = file->f_op->poll(file, *pwait); | 567 | mask = file->f_op->poll(file, *pwait); |
560 | mask &= fdp->events | POLLERR | POLLHUP; | 568 | mask &= fdp->events | POLLERR | POLLHUP; |
561 | fput(file); | 569 | fput_light(file, fput_needed); |
562 | } | 570 | } |
563 | if (mask) { | 571 | if (mask) { |
564 | *pwait = NULL; | 572 | *pwait = NULL; |
@@ -619,6 +627,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
619 | return count; | 627 | return count; |
620 | } | 628 | } |
621 | 629 | ||
630 | #define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \ | ||
631 | sizeof(struct pollfd)) | ||
632 | |||
622 | int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | 633 | int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) |
623 | { | 634 | { |
624 | struct poll_wqueues table; | 635 | struct poll_wqueues table; |
@@ -628,6 +639,9 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
628 | struct poll_list *walk; | 639 | struct poll_list *walk; |
629 | struct fdtable *fdt; | 640 | struct fdtable *fdt; |
630 | int max_fdset; | 641 | int max_fdset; |
642 | /* Allocate small arguments on the stack to save memory and be faster */ | ||
643 | char stack_pps[POLL_STACK_ALLOC]; | ||
644 | struct poll_list *stack_pp = NULL; | ||
631 | 645 | ||
632 | /* Do a sanity check on nfds ... */ | 646 | /* Do a sanity check on nfds ... */ |
633 | rcu_read_lock(); | 647 | rcu_read_lock(); |
@@ -645,14 +659,23 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
645 | err = -ENOMEM; | 659 | err = -ENOMEM; |
646 | while(i!=0) { | 660 | while(i!=0) { |
647 | struct poll_list *pp; | 661 | struct poll_list *pp; |
648 | pp = kmalloc(sizeof(struct poll_list)+ | 662 | int num, size; |
649 | sizeof(struct pollfd)* | 663 | if (stack_pp == NULL) |
650 | (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i), | 664 | num = N_STACK_PPS; |
651 | GFP_KERNEL); | 665 | else |
652 | if(pp==NULL) | 666 | num = POLLFD_PER_PAGE; |
653 | goto out_fds; | 667 | if (num > i) |
668 | num = i; | ||
669 | size = sizeof(struct poll_list) + sizeof(struct pollfd)*num; | ||
670 | if (!stack_pp) | ||
671 | stack_pp = pp = (struct poll_list *)stack_pps; | ||
672 | else { | ||
673 | pp = kmalloc(size, GFP_KERNEL); | ||
674 | if (!pp) | ||
675 | goto out_fds; | ||
676 | } | ||
654 | pp->next=NULL; | 677 | pp->next=NULL; |
655 | pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i); | 678 | pp->len = num; |
656 | if (head == NULL) | 679 | if (head == NULL) |
657 | head = pp; | 680 | head = pp; |
658 | else | 681 | else |
@@ -660,7 +683,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
660 | 683 | ||
661 | walk = pp; | 684 | walk = pp; |
662 | if (copy_from_user(pp->entries, ufds + nfds-i, | 685 | if (copy_from_user(pp->entries, ufds + nfds-i, |
663 | sizeof(struct pollfd)*pp->len)) { | 686 | sizeof(struct pollfd)*num)) { |
664 | err = -EFAULT; | 687 | err = -EFAULT; |
665 | goto out_fds; | 688 | goto out_fds; |
666 | } | 689 | } |
@@ -689,7 +712,8 @@ out_fds: | |||
689 | walk = head; | 712 | walk = head; |
690 | while(walk!=NULL) { | 713 | while(walk!=NULL) { |
691 | struct poll_list *pp = walk->next; | 714 | struct poll_list *pp = walk->next; |
692 | kfree(walk); | 715 | if (walk != stack_pp) |
716 | kfree(walk); | ||
693 | walk = pp; | 717 | walk = pp; |
694 | } | 718 | } |
695 | poll_freewait(&table); | 719 | poll_freewait(&table); |
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 0424d06b147e..34c7a11d91f0 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c | |||
@@ -34,7 +34,7 @@ static int smb_rename(struct inode *, struct dentry *, | |||
34 | static int smb_make_node(struct inode *,struct dentry *,int,dev_t); | 34 | static int smb_make_node(struct inode *,struct dentry *,int,dev_t); |
35 | static int smb_link(struct dentry *, struct inode *, struct dentry *); | 35 | static int smb_link(struct dentry *, struct inode *, struct dentry *); |
36 | 36 | ||
37 | struct file_operations smb_dir_operations = | 37 | const struct file_operations smb_dir_operations = |
38 | { | 38 | { |
39 | .read = generic_read_dir, | 39 | .read = generic_read_dir, |
40 | .readdir = smb_readdir, | 40 | .readdir = smb_readdir, |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 7042e62726a4..c56bd99a9701 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
@@ -401,7 +401,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
401 | return error; | 401 | return error; |
402 | } | 402 | } |
403 | 403 | ||
404 | struct file_operations smb_file_operations = | 404 | const struct file_operations smb_file_operations = |
405 | { | 405 | { |
406 | .llseek = remote_llseek, | 406 | .llseek = remote_llseek, |
407 | .read = smb_file_read, | 407 | .read = smb_file_read, |
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index e866ec8660d0..47664597e6b1 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h | |||
@@ -35,7 +35,7 @@ extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const | |||
35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); | 35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); |
36 | extern void smb_install_null_ops(struct smb_ops *ops); | 36 | extern void smb_install_null_ops(struct smb_ops *ops); |
37 | /* dir.c */ | 37 | /* dir.c */ |
38 | extern struct file_operations smb_dir_operations; | 38 | extern const struct file_operations smb_dir_operations; |
39 | extern struct inode_operations smb_dir_inode_operations; | 39 | extern struct inode_operations smb_dir_inode_operations; |
40 | extern struct inode_operations smb_dir_inode_operations_unix; | 40 | extern struct inode_operations smb_dir_inode_operations_unix; |
41 | extern void smb_new_dentry(struct dentry *dentry); | 41 | extern void smb_new_dentry(struct dentry *dentry); |
@@ -64,7 +64,7 @@ extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat | |||
64 | extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); | 64 | extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); |
65 | /* file.c */ | 65 | /* file.c */ |
66 | extern struct address_space_operations smb_file_aops; | 66 | extern struct address_space_operations smb_file_aops; |
67 | extern struct file_operations smb_file_operations; | 67 | extern const struct file_operations smb_file_operations; |
68 | extern struct inode_operations smb_file_inode_operations; | 68 | extern struct inode_operations smb_file_inode_operations; |
69 | /* ioctl.c */ | 69 | /* ioctl.c */ |
70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); | 70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); |
diff --git a/fs/splice.c b/fs/splice.c new file mode 100644 index 000000000000..4a026f95884f --- /dev/null +++ b/fs/splice.c | |||
@@ -0,0 +1,659 @@ | |||
1 | /* | ||
2 | * "splice": joining two ropes together by interweaving their strands. | ||
3 | * | ||
4 | * This is the "extended pipe" functionality, where a pipe is used as | ||
5 | * an arbitrary in-memory buffer. Think of a pipe as a small kernel | ||
6 | * buffer that you can use to transfer data from one end to the other. | ||
7 | * | ||
8 | * The traditional unix read/write is extended with a "splice()" operation | ||
9 | * that transfers data buffers to or from a pipe buffer. | ||
10 | * | ||
11 | * Named by Larry McVoy, original implementation from Linus, extended by | ||
12 | * Jens to support splicing to files and fixing the initial implementation | ||
13 | * bugs. | ||
14 | * | ||
15 | * Copyright (C) 2005 Jens Axboe <axboe@suse.de> | ||
16 | * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org> | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/file.h> | ||
21 | #include <linux/pagemap.h> | ||
22 | #include <linux/pipe_fs_i.h> | ||
23 | #include <linux/mm_inline.h> | ||
24 | #include <linux/swap.h> | ||
25 | |||
26 | /* | ||
27 | * Passed to the actors | ||
28 | */ | ||
29 | struct splice_desc { | ||
30 | unsigned int len, total_len; /* current and remaining length */ | ||
31 | unsigned int flags; /* splice flags */ | ||
32 | struct file *file; /* file to read/write */ | ||
33 | loff_t pos; /* file position */ | ||
34 | }; | ||
35 | |||
36 | static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, | ||
37 | struct pipe_buffer *buf) | ||
38 | { | ||
39 | struct page *page = buf->page; | ||
40 | |||
41 | WARN_ON(!PageLocked(page)); | ||
42 | WARN_ON(!PageUptodate(page)); | ||
43 | |||
44 | if (!remove_mapping(page_mapping(page), page)) | ||
45 | return 1; | ||
46 | |||
47 | if (PageLRU(page)) { | ||
48 | struct zone *zone = page_zone(page); | ||
49 | |||
50 | spin_lock_irq(&zone->lru_lock); | ||
51 | BUG_ON(!PageLRU(page)); | ||
52 | __ClearPageLRU(page); | ||
53 | del_page_from_lru(zone, page); | ||
54 | spin_unlock_irq(&zone->lru_lock); | ||
55 | } | ||
56 | |||
57 | buf->stolen = 1; | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void page_cache_pipe_buf_release(struct pipe_inode_info *info, | ||
62 | struct pipe_buffer *buf) | ||
63 | { | ||
64 | page_cache_release(buf->page); | ||
65 | buf->page = NULL; | ||
66 | buf->stolen = 0; | ||
67 | } | ||
68 | |||
69 | static void *page_cache_pipe_buf_map(struct file *file, | ||
70 | struct pipe_inode_info *info, | ||
71 | struct pipe_buffer *buf) | ||
72 | { | ||
73 | struct page *page = buf->page; | ||
74 | |||
75 | lock_page(page); | ||
76 | |||
77 | if (!PageUptodate(page)) { | ||
78 | unlock_page(page); | ||
79 | return ERR_PTR(-EIO); | ||
80 | } | ||
81 | |||
82 | if (!page->mapping) { | ||
83 | unlock_page(page); | ||
84 | return ERR_PTR(-ENODATA); | ||
85 | } | ||
86 | |||
87 | return kmap(buf->page); | ||
88 | } | ||
89 | |||
90 | static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info, | ||
91 | struct pipe_buffer *buf) | ||
92 | { | ||
93 | if (!buf->stolen) | ||
94 | unlock_page(buf->page); | ||
95 | kunmap(buf->page); | ||
96 | } | ||
97 | |||
98 | static struct pipe_buf_operations page_cache_pipe_buf_ops = { | ||
99 | .can_merge = 0, | ||
100 | .map = page_cache_pipe_buf_map, | ||
101 | .unmap = page_cache_pipe_buf_unmap, | ||
102 | .release = page_cache_pipe_buf_release, | ||
103 | .steal = page_cache_pipe_buf_steal, | ||
104 | }; | ||
105 | |||
106 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | ||
107 | int nr_pages, unsigned long offset, | ||
108 | unsigned long len) | ||
109 | { | ||
110 | struct pipe_inode_info *info; | ||
111 | int ret, do_wakeup, i; | ||
112 | |||
113 | ret = 0; | ||
114 | do_wakeup = 0; | ||
115 | i = 0; | ||
116 | |||
117 | mutex_lock(PIPE_MUTEX(*inode)); | ||
118 | |||
119 | info = inode->i_pipe; | ||
120 | for (;;) { | ||
121 | int bufs; | ||
122 | |||
123 | if (!PIPE_READERS(*inode)) { | ||
124 | send_sig(SIGPIPE, current, 0); | ||
125 | if (!ret) | ||
126 | ret = -EPIPE; | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | bufs = info->nrbufs; | ||
131 | if (bufs < PIPE_BUFFERS) { | ||
132 | int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1); | ||
133 | struct pipe_buffer *buf = info->bufs + newbuf; | ||
134 | struct page *page = pages[i++]; | ||
135 | unsigned long this_len; | ||
136 | |||
137 | this_len = PAGE_CACHE_SIZE - offset; | ||
138 | if (this_len > len) | ||
139 | this_len = len; | ||
140 | |||
141 | buf->page = page; | ||
142 | buf->offset = offset; | ||
143 | buf->len = this_len; | ||
144 | buf->ops = &page_cache_pipe_buf_ops; | ||
145 | info->nrbufs = ++bufs; | ||
146 | do_wakeup = 1; | ||
147 | |||
148 | ret += this_len; | ||
149 | len -= this_len; | ||
150 | offset = 0; | ||
151 | if (!--nr_pages) | ||
152 | break; | ||
153 | if (!len) | ||
154 | break; | ||
155 | if (bufs < PIPE_BUFFERS) | ||
156 | continue; | ||
157 | |||
158 | break; | ||
159 | } | ||
160 | |||
161 | if (signal_pending(current)) { | ||
162 | if (!ret) | ||
163 | ret = -ERESTARTSYS; | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | if (do_wakeup) { | ||
168 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | ||
169 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, | ||
170 | POLL_IN); | ||
171 | do_wakeup = 0; | ||
172 | } | ||
173 | |||
174 | PIPE_WAITING_WRITERS(*inode)++; | ||
175 | pipe_wait(inode); | ||
176 | PIPE_WAITING_WRITERS(*inode)--; | ||
177 | } | ||
178 | |||
179 | mutex_unlock(PIPE_MUTEX(*inode)); | ||
180 | |||
181 | if (do_wakeup) { | ||
182 | wake_up_interruptible(PIPE_WAIT(*inode)); | ||
183 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); | ||
184 | } | ||
185 | |||
186 | while (i < nr_pages) | ||
187 | page_cache_release(pages[i++]); | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static int __generic_file_splice_read(struct file *in, struct inode *pipe, | ||
193 | size_t len) | ||
194 | { | ||
195 | struct address_space *mapping = in->f_mapping; | ||
196 | unsigned int offset, nr_pages; | ||
197 | struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS]; | ||
198 | struct page *page; | ||
199 | pgoff_t index, pidx; | ||
200 | int i, j; | ||
201 | |||
202 | index = in->f_pos >> PAGE_CACHE_SHIFT; | ||
203 | offset = in->f_pos & ~PAGE_CACHE_MASK; | ||
204 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
205 | |||
206 | if (nr_pages > PIPE_BUFFERS) | ||
207 | nr_pages = PIPE_BUFFERS; | ||
208 | |||
209 | /* | ||
210 | * initiate read-ahead on this page range | ||
211 | */ | ||
212 | do_page_cache_readahead(mapping, in, index, nr_pages); | ||
213 | |||
214 | /* | ||
215 | * Get as many pages from the page cache as possible.. | ||
216 | * Start IO on the page cache entries we create (we | ||
217 | * can assume that any pre-existing ones we find have | ||
218 | * already had IO started on them). | ||
219 | */ | ||
220 | i = find_get_pages(mapping, index, nr_pages, pages); | ||
221 | |||
222 | /* | ||
223 | * common case - we found all pages and they are contiguous, | ||
224 | * kick them off | ||
225 | */ | ||
226 | if (i && (pages[i - 1]->index == index + i - 1)) | ||
227 | goto splice_them; | ||
228 | |||
229 | /* | ||
230 | * fill shadow[] with pages at the right locations, so we only | ||
231 | * have to fill holes | ||
232 | */ | ||
233 | memset(shadow, 0, i * sizeof(struct page *)); | ||
234 | for (j = 0, pidx = index; j < i; pidx++, j++) | ||
235 | shadow[pages[j]->index - pidx] = pages[j]; | ||
236 | |||
237 | /* | ||
238 | * now fill in the holes | ||
239 | */ | ||
240 | for (i = 0, pidx = index; i < nr_pages; pidx++, i++) { | ||
241 | int error; | ||
242 | |||
243 | if (shadow[i]) | ||
244 | continue; | ||
245 | |||
246 | /* | ||
247 | * no page there, look one up / create it | ||
248 | */ | ||
249 | page = find_or_create_page(mapping, pidx, | ||
250 | mapping_gfp_mask(mapping)); | ||
251 | if (!page) | ||
252 | break; | ||
253 | |||
254 | if (PageUptodate(page)) | ||
255 | unlock_page(page); | ||
256 | else { | ||
257 | error = mapping->a_ops->readpage(in, page); | ||
258 | |||
259 | if (unlikely(error)) { | ||
260 | page_cache_release(page); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | shadow[i] = page; | ||
265 | } | ||
266 | |||
267 | if (!i) { | ||
268 | for (i = 0; i < nr_pages; i++) { | ||
269 | if (shadow[i]) | ||
270 | page_cache_release(shadow[i]); | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | memcpy(pages, shadow, i * sizeof(struct page *)); | ||
276 | |||
277 | /* | ||
278 | * Now we splice them into the pipe.. | ||
279 | */ | ||
280 | splice_them: | ||
281 | return move_to_pipe(pipe, pages, i, offset, len); | ||
282 | } | ||
283 | |||
284 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | ||
285 | size_t len, unsigned int flags) | ||
286 | { | ||
287 | ssize_t spliced; | ||
288 | int ret; | ||
289 | |||
290 | ret = 0; | ||
291 | spliced = 0; | ||
292 | while (len) { | ||
293 | ret = __generic_file_splice_read(in, pipe, len); | ||
294 | |||
295 | if (ret <= 0) | ||
296 | break; | ||
297 | |||
298 | in->f_pos += ret; | ||
299 | len -= ret; | ||
300 | spliced += ret; | ||
301 | } | ||
302 | |||
303 | if (spliced) | ||
304 | return spliced; | ||
305 | |||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage(). | ||
311 | */ | ||
312 | static int pipe_to_sendpage(struct pipe_inode_info *info, | ||
313 | struct pipe_buffer *buf, struct splice_desc *sd) | ||
314 | { | ||
315 | struct file *file = sd->file; | ||
316 | loff_t pos = sd->pos; | ||
317 | unsigned int offset; | ||
318 | ssize_t ret; | ||
319 | void *ptr; | ||
320 | |||
321 | /* | ||
322 | * sub-optimal, but we are limited by the pipe ->map. we don't | ||
323 | * need a kmap'ed buffer here, we just want to make sure we | ||
324 | * have the page pinned if the pipe page originates from the | ||
325 | * page cache | ||
326 | */ | ||
327 | ptr = buf->ops->map(file, info, buf); | ||
328 | if (IS_ERR(ptr)) | ||
329 | return PTR_ERR(ptr); | ||
330 | |||
331 | offset = pos & ~PAGE_CACHE_MASK; | ||
332 | |||
333 | ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos, | ||
334 | sd->len < sd->total_len); | ||
335 | |||
336 | buf->ops->unmap(info, buf); | ||
337 | if (ret == sd->len) | ||
338 | return 0; | ||
339 | |||
340 | return -EIO; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * This is a little more tricky than the file -> pipe splicing. There are | ||
345 | * basically three cases: | ||
346 | * | ||
347 | * - Destination page already exists in the address space and there | ||
348 | * are users of it. For that case we have no other option that | ||
349 | * copying the data. Tough luck. | ||
350 | * - Destination page already exists in the address space, but there | ||
351 | * are no users of it. Make sure it's uptodate, then drop it. Fall | ||
352 | * through to last case. | ||
353 | * - Destination page does not exist, we can add the pipe page to | ||
354 | * the page cache and avoid the copy. | ||
355 | * | ||
356 | * For now we just do the slower thing and always copy pages over, it's | ||
357 | * easier than migrating pages from the pipe to the target file. For the | ||
358 | * case of doing file | file splicing, the migrate approach had some LRU | ||
359 | * nastiness... | ||
360 | */ | ||
361 | static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | ||
362 | struct splice_desc *sd) | ||
363 | { | ||
364 | struct file *file = sd->file; | ||
365 | struct address_space *mapping = file->f_mapping; | ||
366 | unsigned int offset; | ||
367 | struct page *page; | ||
368 | pgoff_t index; | ||
369 | char *src; | ||
370 | int ret; | ||
371 | |||
372 | /* | ||
373 | * after this, page will be locked and unmapped | ||
374 | */ | ||
375 | src = buf->ops->map(file, info, buf); | ||
376 | if (IS_ERR(src)) | ||
377 | return PTR_ERR(src); | ||
378 | |||
379 | index = sd->pos >> PAGE_CACHE_SHIFT; | ||
380 | offset = sd->pos & ~PAGE_CACHE_MASK; | ||
381 | |||
382 | /* | ||
383 | * reuse buf page, if SPLICE_F_MOVE is set | ||
384 | */ | ||
385 | if (sd->flags & SPLICE_F_MOVE) { | ||
386 | if (buf->ops->steal(info, buf)) | ||
387 | goto find_page; | ||
388 | |||
389 | page = buf->page; | ||
390 | if (add_to_page_cache_lru(page, mapping, index, | ||
391 | mapping_gfp_mask(mapping))) | ||
392 | goto find_page; | ||
393 | } else { | ||
394 | find_page: | ||
395 | ret = -ENOMEM; | ||
396 | page = find_or_create_page(mapping, index, | ||
397 | mapping_gfp_mask(mapping)); | ||
398 | if (!page) | ||
399 | goto out; | ||
400 | |||
401 | /* | ||
402 | * If the page is uptodate, it is also locked. If it isn't | ||
403 | * uptodate, we can mark it uptodate if we are filling the | ||
404 | * full page. Otherwise we need to read it in first... | ||
405 | */ | ||
406 | if (!PageUptodate(page)) { | ||
407 | if (sd->len < PAGE_CACHE_SIZE) { | ||
408 | ret = mapping->a_ops->readpage(file, page); | ||
409 | if (unlikely(ret)) | ||
410 | goto out; | ||
411 | |||
412 | lock_page(page); | ||
413 | |||
414 | if (!PageUptodate(page)) { | ||
415 | /* | ||
416 | * page got invalidated, repeat | ||
417 | */ | ||
418 | if (!page->mapping) { | ||
419 | unlock_page(page); | ||
420 | page_cache_release(page); | ||
421 | goto find_page; | ||
422 | } | ||
423 | ret = -EIO; | ||
424 | goto out; | ||
425 | } | ||
426 | } else { | ||
427 | WARN_ON(!PageLocked(page)); | ||
428 | SetPageUptodate(page); | ||
429 | } | ||
430 | } | ||
431 | } | ||
432 | |||
433 | ret = mapping->a_ops->prepare_write(file, page, 0, sd->len); | ||
434 | if (ret) | ||
435 | goto out; | ||
436 | |||
437 | if (!buf->stolen) { | ||
438 | char *dst = kmap_atomic(page, KM_USER0); | ||
439 | |||
440 | memcpy(dst + offset, src + buf->offset, sd->len); | ||
441 | flush_dcache_page(page); | ||
442 | kunmap_atomic(dst, KM_USER0); | ||
443 | } | ||
444 | |||
445 | ret = mapping->a_ops->commit_write(file, page, 0, sd->len); | ||
446 | if (ret < 0) | ||
447 | goto out; | ||
448 | |||
449 | set_page_dirty(page); | ||
450 | ret = write_one_page(page, 0); | ||
451 | out: | ||
452 | if (ret < 0) | ||
453 | unlock_page(page); | ||
454 | if (!buf->stolen) | ||
455 | page_cache_release(page); | ||
456 | buf->ops->unmap(info, buf); | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, | ||
461 | struct splice_desc *); | ||
462 | |||
463 | static ssize_t move_from_pipe(struct inode *inode, struct file *out, | ||
464 | size_t len, unsigned int flags, | ||
465 | splice_actor *actor) | ||
466 | { | ||
467 | struct pipe_inode_info *info; | ||
468 | int ret, do_wakeup, err; | ||
469 | struct splice_desc sd; | ||
470 | |||
471 | ret = 0; | ||
472 | do_wakeup = 0; | ||
473 | |||
474 | sd.total_len = len; | ||
475 | sd.flags = flags; | ||
476 | sd.file = out; | ||
477 | sd.pos = out->f_pos; | ||
478 | |||
479 | mutex_lock(PIPE_MUTEX(*inode)); | ||
480 | |||
481 | info = inode->i_pipe; | ||
482 | for (;;) { | ||
483 | int bufs = info->nrbufs; | ||
484 | |||
485 | if (bufs) { | ||
486 | int curbuf = info->curbuf; | ||
487 | struct pipe_buffer *buf = info->bufs + curbuf; | ||
488 | struct pipe_buf_operations *ops = buf->ops; | ||
489 | |||
490 | sd.len = buf->len; | ||
491 | if (sd.len > sd.total_len) | ||
492 | sd.len = sd.total_len; | ||
493 | |||
494 | err = actor(info, buf, &sd); | ||
495 | if (err) { | ||
496 | if (!ret && err != -ENODATA) | ||
497 | ret = err; | ||
498 | |||
499 | break; | ||
500 | } | ||
501 | |||
502 | ret += sd.len; | ||
503 | buf->offset += sd.len; | ||
504 | buf->len -= sd.len; | ||
505 | if (!buf->len) { | ||
506 | buf->ops = NULL; | ||
507 | ops->release(info, buf); | ||
508 | curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); | ||
509 | info->curbuf = curbuf; | ||
510 | info->nrbufs = --bufs; | ||
511 | do_wakeup = 1; | ||
512 | } | ||
513 | |||
514 | sd.pos += sd.len; | ||
515 | sd.total_len -= sd.len; | ||
516 | if (!sd.total_len) | ||
517 | break; | ||
518 | } | ||
519 | |||
520 | if (bufs) | ||
521 | continue; | ||
522 | if (!PIPE_WRITERS(*inode)) | ||
523 | break; | ||
524 | if (!PIPE_WAITING_WRITERS(*inode)) { | ||
525 | if (ret) | ||
526 | break; | ||
527 | } | ||
528 | |||
529 | if (signal_pending(current)) { | ||
530 | if (!ret) | ||
531 | ret = -ERESTARTSYS; | ||
532 | break; | ||
533 | } | ||
534 | |||
535 | if (do_wakeup) { | ||
536 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | ||
537 | kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT); | ||
538 | do_wakeup = 0; | ||
539 | } | ||
540 | |||
541 | pipe_wait(inode); | ||
542 | } | ||
543 | |||
544 | mutex_unlock(PIPE_MUTEX(*inode)); | ||
545 | |||
546 | if (do_wakeup) { | ||
547 | wake_up_interruptible(PIPE_WAIT(*inode)); | ||
548 | kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); | ||
549 | } | ||
550 | |||
551 | mutex_lock(&out->f_mapping->host->i_mutex); | ||
552 | out->f_pos = sd.pos; | ||
553 | mutex_unlock(&out->f_mapping->host->i_mutex); | ||
554 | return ret; | ||
555 | |||
556 | } | ||
557 | |||
558 | ssize_t generic_file_splice_write(struct inode *inode, struct file *out, | ||
559 | size_t len, unsigned int flags) | ||
560 | { | ||
561 | return move_from_pipe(inode, out, len, flags, pipe_to_file); | ||
562 | } | ||
563 | |||
564 | ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | ||
565 | size_t len, unsigned int flags) | ||
566 | { | ||
567 | return move_from_pipe(inode, out, len, flags, pipe_to_sendpage); | ||
568 | } | ||
569 | |||
570 | static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | ||
571 | unsigned int flags) | ||
572 | { | ||
573 | loff_t pos; | ||
574 | int ret; | ||
575 | |||
576 | if (!out->f_op || !out->f_op->splice_write) | ||
577 | return -EINVAL; | ||
578 | |||
579 | if (!(out->f_mode & FMODE_WRITE)) | ||
580 | return -EBADF; | ||
581 | |||
582 | pos = out->f_pos; | ||
583 | ret = rw_verify_area(WRITE, out, &pos, len); | ||
584 | if (unlikely(ret < 0)) | ||
585 | return ret; | ||
586 | |||
587 | return out->f_op->splice_write(pipe, out, len, flags); | ||
588 | } | ||
589 | |||
590 | static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | ||
591 | unsigned int flags) | ||
592 | { | ||
593 | loff_t pos, isize, left; | ||
594 | int ret; | ||
595 | |||
596 | if (!in->f_op || !in->f_op->splice_read) | ||
597 | return -EINVAL; | ||
598 | |||
599 | if (!(in->f_mode & FMODE_READ)) | ||
600 | return -EBADF; | ||
601 | |||
602 | pos = in->f_pos; | ||
603 | ret = rw_verify_area(READ, in, &pos, len); | ||
604 | if (unlikely(ret < 0)) | ||
605 | return ret; | ||
606 | |||
607 | isize = i_size_read(in->f_mapping->host); | ||
608 | if (unlikely(in->f_pos >= isize)) | ||
609 | return 0; | ||
610 | |||
611 | left = isize - in->f_pos; | ||
612 | if (left < len) | ||
613 | len = left; | ||
614 | |||
615 | return in->f_op->splice_read(in, pipe, len, flags); | ||
616 | } | ||
617 | |||
618 | static long do_splice(struct file *in, struct file *out, size_t len, | ||
619 | unsigned int flags) | ||
620 | { | ||
621 | struct inode *pipe; | ||
622 | |||
623 | pipe = in->f_dentry->d_inode; | ||
624 | if (pipe->i_pipe) | ||
625 | return do_splice_from(pipe, out, len, flags); | ||
626 | |||
627 | pipe = out->f_dentry->d_inode; | ||
628 | if (pipe->i_pipe) | ||
629 | return do_splice_to(in, pipe, len, flags); | ||
630 | |||
631 | return -EINVAL; | ||
632 | } | ||
633 | |||
634 | asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags) | ||
635 | { | ||
636 | long error; | ||
637 | struct file *in, *out; | ||
638 | int fput_in, fput_out; | ||
639 | |||
640 | if (unlikely(!len)) | ||
641 | return 0; | ||
642 | |||
643 | error = -EBADF; | ||
644 | in = fget_light(fdin, &fput_in); | ||
645 | if (in) { | ||
646 | if (in->f_mode & FMODE_READ) { | ||
647 | out = fget_light(fdout, &fput_out); | ||
648 | if (out) { | ||
649 | if (out->f_mode & FMODE_WRITE) | ||
650 | error = do_splice(in, out, len, flags); | ||
651 | fput_light(out, fput_out); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | fput_light(in, fput_in); | ||
656 | } | ||
657 | |||
658 | return error; | ||
659 | } | ||
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 78899eeab974..c16a93c353c0 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file) | |||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | struct file_operations bin_fops = { | 166 | const struct file_operations bin_fops = { |
167 | .read = read, | 167 | .read = read, |
168 | .write = write, | 168 | .write = write, |
169 | .mmap = mmap, | 169 | .mmap = mmap, |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9ee956864445..f26880a4785e 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -503,7 +503,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
503 | return offset; | 503 | return offset; |
504 | } | 504 | } |
505 | 505 | ||
506 | struct file_operations sysfs_dir_operations = { | 506 | const struct file_operations sysfs_dir_operations = { |
507 | .open = sysfs_dir_open, | 507 | .open = sysfs_dir_open, |
508 | .release = sysfs_dir_close, | 508 | .release = sysfs_dir_close, |
509 | .llseek = sysfs_dir_lseek, | 509 | .llseek = sysfs_dir_lseek, |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 5e83e7246788..830f76fa098c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -348,7 +348,7 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | struct file_operations sysfs_file_operations = { | 351 | const struct file_operations sysfs_file_operations = { |
352 | .read = sysfs_read_file, | 352 | .read = sysfs_read_file, |
353 | .write = sysfs_write_file, | 353 | .write = sysfs_write_file, |
354 | .llseek = generic_file_llseek, | 354 | .llseek = generic_file_llseek, |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cf11d5b789d9..32958a7c50e9 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -21,9 +21,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | |||
21 | 21 | ||
22 | extern struct rw_semaphore sysfs_rename_sem; | 22 | extern struct rw_semaphore sysfs_rename_sem; |
23 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
24 | extern struct file_operations sysfs_dir_operations; | 24 | extern const struct file_operations sysfs_dir_operations; |
25 | extern struct file_operations sysfs_file_operations; | 25 | extern const struct file_operations sysfs_file_operations; |
26 | extern struct file_operations bin_fops; | 26 | extern const struct file_operations bin_fops; |
27 | extern struct inode_operations sysfs_dir_inode_operations; | 27 | extern struct inode_operations sysfs_dir_inode_operations; |
28 | extern struct inode_operations sysfs_symlink_inode_operations; | 28 | extern struct inode_operations sysfs_symlink_inode_operations; |
29 | 29 | ||
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index cce8b05cba5a..8c66e9270dd6 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | static int sysv_readdir(struct file *, void *, filldir_t); | 21 | static int sysv_readdir(struct file *, void *, filldir_t); |
22 | 22 | ||
23 | struct file_operations sysv_dir_operations = { | 23 | const struct file_operations sysv_dir_operations = { |
24 | .read = generic_read_dir, | 24 | .read = generic_read_dir, |
25 | .readdir = sysv_readdir, | 25 | .readdir = sysv_readdir, |
26 | .fsync = sysv_sync_file, | 26 | .fsync = sysv_sync_file, |
diff --git a/fs/sysv/file.c b/fs/sysv/file.c index da69abc06240..a59e303135fa 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * We have mostly NULLs here: the current defaults are OK for | 19 | * We have mostly NULLs here: the current defaults are OK for |
20 | * the coh filesystem. | 20 | * the coh filesystem. |
21 | */ | 21 | */ |
22 | struct file_operations sysv_file_operations = { | 22 | const struct file_operations sysv_file_operations = { |
23 | .llseek = generic_file_llseek, | 23 | .llseek = generic_file_llseek, |
24 | .read = generic_file_read, | 24 | .read = generic_file_read, |
25 | .write = generic_file_write, | 25 | .write = generic_file_write, |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index b7f9b4a42aab..393a480e4deb 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
@@ -159,8 +159,8 @@ extern ino_t sysv_inode_by_name(struct dentry *); | |||
159 | extern struct inode_operations sysv_file_inode_operations; | 159 | extern struct inode_operations sysv_file_inode_operations; |
160 | extern struct inode_operations sysv_dir_inode_operations; | 160 | extern struct inode_operations sysv_dir_inode_operations; |
161 | extern struct inode_operations sysv_fast_symlink_inode_operations; | 161 | extern struct inode_operations sysv_fast_symlink_inode_operations; |
162 | extern struct file_operations sysv_file_operations; | 162 | extern const struct file_operations sysv_file_operations; |
163 | extern struct file_operations sysv_dir_operations; | 163 | extern const struct file_operations sysv_dir_operations; |
164 | extern struct address_space_operations sysv_aops; | 164 | extern struct address_space_operations sysv_aops; |
165 | extern struct super_operations sysv_sops; | 165 | extern struct super_operations sysv_sops; |
166 | extern struct dentry_operations sysv_dentry_operations; | 166 | extern struct dentry_operations sysv_dentry_operations; |
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index f5222527fe39..8c28efa3b8ff 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -42,7 +42,7 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *); | |||
42 | 42 | ||
43 | /* readdir and lookup functions */ | 43 | /* readdir and lookup functions */ |
44 | 44 | ||
45 | struct file_operations udf_dir_operations = { | 45 | const struct file_operations udf_dir_operations = { |
46 | .read = generic_read_dir, | 46 | .read = generic_read_dir, |
47 | .readdir = udf_readdir, | 47 | .readdir = udf_readdir, |
48 | .ioctl = udf_ioctl, | 48 | .ioctl = udf_ioctl, |
diff --git a/fs/udf/file.c b/fs/udf/file.c index a6f2acc1f15c..e34b00e303f1 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -248,7 +248,7 @@ static int udf_release_file(struct inode * inode, struct file * filp) | |||
248 | return 0; | 248 | return 0; |
249 | } | 249 | } |
250 | 250 | ||
251 | struct file_operations udf_file_operations = { | 251 | const struct file_operations udf_file_operations = { |
252 | .read = generic_file_read, | 252 | .read = generic_file_read, |
253 | .ioctl = udf_ioctl, | 253 | .ioctl = udf_ioctl, |
254 | .open = generic_file_open, | 254 | .open = generic_file_open, |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1d5800e0cbe7..023e19ba5a2e 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -44,9 +44,9 @@ struct buffer_head; | |||
44 | struct super_block; | 44 | struct super_block; |
45 | 45 | ||
46 | extern struct inode_operations udf_dir_inode_operations; | 46 | extern struct inode_operations udf_dir_inode_operations; |
47 | extern struct file_operations udf_dir_operations; | 47 | extern const struct file_operations udf_dir_operations; |
48 | extern struct inode_operations udf_file_inode_operations; | 48 | extern struct inode_operations udf_file_inode_operations; |
49 | extern struct file_operations udf_file_operations; | 49 | extern const struct file_operations udf_file_operations; |
50 | extern struct address_space_operations udf_aops; | 50 | extern struct address_space_operations udf_aops; |
51 | extern struct address_space_operations udf_adinicb_aops; | 51 | extern struct address_space_operations udf_adinicb_aops; |
52 | extern struct address_space_operations udf_symlink_aops; | 52 | extern struct address_space_operations udf_symlink_aops; |
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 7c10c68902ae..1a561202d3f4 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
@@ -620,7 +620,7 @@ int ufs_empty_dir (struct inode * inode) | |||
620 | return 1; | 620 | return 1; |
621 | } | 621 | } |
622 | 622 | ||
623 | struct file_operations ufs_dir_operations = { | 623 | const struct file_operations ufs_dir_operations = { |
624 | .read = generic_read_dir, | 624 | .read = generic_read_dir, |
625 | .readdir = ufs_readdir, | 625 | .readdir = ufs_readdir, |
626 | .fsync = file_fsync, | 626 | .fsync = file_fsync, |
diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 62ad481810ef..312fd3f86313 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * the ufs filesystem. | 31 | * the ufs filesystem. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | struct file_operations ufs_file_operations = { | 34 | const struct file_operations ufs_file_operations = { |
35 | .llseek = generic_file_llseek, | 35 | .llseek = generic_file_llseek, |
36 | .read = generic_file_read, | 36 | .read = generic_file_read, |
37 | .write = generic_file_write, | 37 | .write = generic_file_write, |
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h index 16b44c3c2362..1b262b790d9c 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/linux-2.6/mrlock.h | |||
@@ -79,7 +79,7 @@ static inline void mrdemote(mrlock_t *mrp) | |||
79 | * Debug-only routine, without some platform-specific asm code, we can | 79 | * Debug-only routine, without some platform-specific asm code, we can |
80 | * now only answer requests regarding whether we hold the lock for write | 80 | * now only answer requests regarding whether we hold the lock for write |
81 | * (reader state is outside our visibility, we only track writer state). | 81 | * (reader state is outside our visibility, we only track writer state). |
82 | * Note: means !ismrlocked would give false positivies, so don't do that. | 82 | * Note: means !ismrlocked would give false positives, so don't do that. |
83 | */ | 83 | */ |
84 | static inline int ismrlocked(mrlock_t *mrp, int type) | 84 | static inline int ismrlocked(mrlock_t *mrp, int type) |
85 | { | 85 | { |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c02f7c5b7462..6cbbd165c60d 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -372,7 +372,7 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) | |||
372 | * assumes that all buffers on the page are started at the same time. | 372 | * assumes that all buffers on the page are started at the same time. |
373 | * | 373 | * |
374 | * The fix is two passes across the ioend list - one to start writeback on the | 374 | * The fix is two passes across the ioend list - one to start writeback on the |
375 | * bufferheads, and then the second one submit them for I/O. | 375 | * buffer_heads, and then submit them for I/O on the second pass. |
376 | */ | 376 | */ |
377 | STATIC void | 377 | STATIC void |
378 | xfs_submit_ioend( | 378 | xfs_submit_ioend( |
@@ -699,7 +699,7 @@ xfs_convert_page( | |||
699 | 699 | ||
700 | /* | 700 | /* |
701 | * page_dirty is initially a count of buffers on the page before | 701 | * page_dirty is initially a count of buffers on the page before |
702 | * EOF and is decrememted as we move each into a cleanable state. | 702 | * EOF and is decremented as we move each into a cleanable state. |
703 | * | 703 | * |
704 | * Derivation: | 704 | * Derivation: |
705 | * | 705 | * |
@@ -842,7 +842,7 @@ xfs_cluster_write( | |||
842 | * page if possible. | 842 | * page if possible. |
843 | * The bh->b_state's cannot know if any of the blocks or which block for | 843 | * The bh->b_state's cannot know if any of the blocks or which block for |
844 | * that matter are dirty due to mmap writes, and therefore bh uptodate is | 844 | * that matter are dirty due to mmap writes, and therefore bh uptodate is |
845 | * only vaild if the page itself isn't completely uptodate. Some layers | 845 | * only valid if the page itself isn't completely uptodate. Some layers |
846 | * may clear the page dirty flag prior to calling write page, under the | 846 | * may clear the page dirty flag prior to calling write page, under the |
847 | * assumption the entire page will be written out; by not writing out the | 847 | * assumption the entire page will be written out; by not writing out the |
848 | * whole page the page can be reused before all valid dirty data is | 848 | * whole page the page can be reused before all valid dirty data is |
@@ -892,7 +892,7 @@ xfs_page_state_convert( | |||
892 | 892 | ||
893 | /* | 893 | /* |
894 | * page_dirty is initially a count of buffers on the page before | 894 | * page_dirty is initially a count of buffers on the page before |
895 | * EOF and is decrememted as we move each into a cleanable state. | 895 | * EOF and is decremented as we move each into a cleanable state. |
896 | * | 896 | * |
897 | * Derivation: | 897 | * Derivation: |
898 | * | 898 | * |
@@ -1223,10 +1223,9 @@ free_buffers: | |||
1223 | } | 1223 | } |
1224 | 1224 | ||
1225 | STATIC int | 1225 | STATIC int |
1226 | __xfs_get_block( | 1226 | __xfs_get_blocks( |
1227 | struct inode *inode, | 1227 | struct inode *inode, |
1228 | sector_t iblock, | 1228 | sector_t iblock, |
1229 | unsigned long blocks, | ||
1230 | struct buffer_head *bh_result, | 1229 | struct buffer_head *bh_result, |
1231 | int create, | 1230 | int create, |
1232 | int direct, | 1231 | int direct, |
@@ -1236,22 +1235,17 @@ __xfs_get_block( | |||
1236 | xfs_iomap_t iomap; | 1235 | xfs_iomap_t iomap; |
1237 | xfs_off_t offset; | 1236 | xfs_off_t offset; |
1238 | ssize_t size; | 1237 | ssize_t size; |
1239 | int retpbbm = 1; | 1238 | int niomap = 1; |
1240 | int error; | 1239 | int error; |
1241 | 1240 | ||
1242 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 1241 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
1243 | if (blocks) | 1242 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); |
1244 | size = (ssize_t) min_t(xfs_off_t, LONG_MAX, | 1243 | size = bh_result->b_size; |
1245 | (xfs_off_t)blocks << inode->i_blkbits); | ||
1246 | else | ||
1247 | size = 1 << inode->i_blkbits; | ||
1248 | |||
1249 | VOP_BMAP(vp, offset, size, | 1244 | VOP_BMAP(vp, offset, size, |
1250 | create ? flags : BMAPI_READ, &iomap, &retpbbm, error); | 1245 | create ? flags : BMAPI_READ, &iomap, &niomap, error); |
1251 | if (error) | 1246 | if (error) |
1252 | return -error; | 1247 | return -error; |
1253 | 1248 | if (niomap == 0) | |
1254 | if (retpbbm == 0) | ||
1255 | return 0; | 1249 | return 0; |
1256 | 1250 | ||
1257 | if (iomap.iomap_bn != IOMAP_DADDR_NULL) { | 1251 | if (iomap.iomap_bn != IOMAP_DADDR_NULL) { |
@@ -1271,12 +1265,16 @@ __xfs_get_block( | |||
1271 | } | 1265 | } |
1272 | } | 1266 | } |
1273 | 1267 | ||
1274 | /* If this is a realtime file, data might be on a new device */ | 1268 | /* |
1269 | * If this is a realtime file, data may be on a different device. | ||
1270 | * to that pointed to from the buffer_head b_bdev currently. | ||
1271 | */ | ||
1275 | bh_result->b_bdev = iomap.iomap_target->bt_bdev; | 1272 | bh_result->b_bdev = iomap.iomap_target->bt_bdev; |
1276 | 1273 | ||
1277 | /* If we previously allocated a block out beyond eof and | 1274 | /* |
1278 | * we are now coming back to use it then we will need to | 1275 | * If we previously allocated a block out beyond eof and we are |
1279 | * flag it as new even if it has a disk address. | 1276 | * now coming back to use it then we will need to flag it as new |
1277 | * even if it has a disk address. | ||
1280 | */ | 1278 | */ |
1281 | if (create && | 1279 | if (create && |
1282 | ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || | 1280 | ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || |
@@ -1292,26 +1290,24 @@ __xfs_get_block( | |||
1292 | } | 1290 | } |
1293 | } | 1291 | } |
1294 | 1292 | ||
1295 | if (blocks) { | 1293 | if (direct || size > (1 << inode->i_blkbits)) { |
1296 | ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0); | 1294 | ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0); |
1297 | offset = min_t(xfs_off_t, | 1295 | offset = min_t(xfs_off_t, |
1298 | iomap.iomap_bsize - iomap.iomap_delta, | 1296 | iomap.iomap_bsize - iomap.iomap_delta, size); |
1299 | (xfs_off_t)blocks << inode->i_blkbits); | 1297 | bh_result->b_size = (ssize_t)min_t(xfs_off_t, LONG_MAX, offset); |
1300 | bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset); | ||
1301 | } | 1298 | } |
1302 | 1299 | ||
1303 | return 0; | 1300 | return 0; |
1304 | } | 1301 | } |
1305 | 1302 | ||
1306 | int | 1303 | int |
1307 | xfs_get_block( | 1304 | xfs_get_blocks( |
1308 | struct inode *inode, | 1305 | struct inode *inode, |
1309 | sector_t iblock, | 1306 | sector_t iblock, |
1310 | struct buffer_head *bh_result, | 1307 | struct buffer_head *bh_result, |
1311 | int create) | 1308 | int create) |
1312 | { | 1309 | { |
1313 | return __xfs_get_block(inode, iblock, | 1310 | return __xfs_get_blocks(inode, iblock, |
1314 | bh_result->b_size >> inode->i_blkbits, | ||
1315 | bh_result, create, 0, BMAPI_WRITE); | 1311 | bh_result, create, 0, BMAPI_WRITE); |
1316 | } | 1312 | } |
1317 | 1313 | ||
@@ -1322,8 +1318,7 @@ xfs_get_blocks_direct( | |||
1322 | struct buffer_head *bh_result, | 1318 | struct buffer_head *bh_result, |
1323 | int create) | 1319 | int create) |
1324 | { | 1320 | { |
1325 | return __xfs_get_block(inode, iblock, | 1321 | return __xfs_get_blocks(inode, iblock, |
1326 | bh_result->b_size >> inode->i_blkbits, | ||
1327 | bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT); | 1322 | bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT); |
1328 | } | 1323 | } |
1329 | 1324 | ||
@@ -1339,9 +1334,9 @@ xfs_end_io_direct( | |||
1339 | /* | 1334 | /* |
1340 | * Non-NULL private data means we need to issue a transaction to | 1335 | * Non-NULL private data means we need to issue a transaction to |
1341 | * convert a range from unwritten to written extents. This needs | 1336 | * convert a range from unwritten to written extents. This needs |
1342 | * to happen from process contect but aio+dio I/O completion | 1337 | * to happen from process context but aio+dio I/O completion |
1343 | * happens from irq context so we need to defer it to a workqueue. | 1338 | * happens from irq context so we need to defer it to a workqueue. |
1344 | * This is not nessecary for synchronous direct I/O, but we do | 1339 | * This is not necessary for synchronous direct I/O, but we do |
1345 | * it anyway to keep the code uniform and simpler. | 1340 | * it anyway to keep the code uniform and simpler. |
1346 | * | 1341 | * |
1347 | * The core direct I/O code might be changed to always call the | 1342 | * The core direct I/O code might be changed to always call the |
@@ -1358,7 +1353,7 @@ xfs_end_io_direct( | |||
1358 | } | 1353 | } |
1359 | 1354 | ||
1360 | /* | 1355 | /* |
1361 | * blockdev_direct_IO can return an error even afer the I/O | 1356 | * blockdev_direct_IO can return an error even after the I/O |
1362 | * completion handler was called. Thus we need to protect | 1357 | * completion handler was called. Thus we need to protect |
1363 | * against double-freeing. | 1358 | * against double-freeing. |
1364 | */ | 1359 | */ |
@@ -1405,7 +1400,7 @@ xfs_vm_prepare_write( | |||
1405 | unsigned int from, | 1400 | unsigned int from, |
1406 | unsigned int to) | 1401 | unsigned int to) |
1407 | { | 1402 | { |
1408 | return block_prepare_write(page, from, to, xfs_get_block); | 1403 | return block_prepare_write(page, from, to, xfs_get_blocks); |
1409 | } | 1404 | } |
1410 | 1405 | ||
1411 | STATIC sector_t | 1406 | STATIC sector_t |
@@ -1422,7 +1417,7 @@ xfs_vm_bmap( | |||
1422 | VOP_RWLOCK(vp, VRWLOCK_READ); | 1417 | VOP_RWLOCK(vp, VRWLOCK_READ); |
1423 | VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); | 1418 | VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); |
1424 | VOP_RWUNLOCK(vp, VRWLOCK_READ); | 1419 | VOP_RWUNLOCK(vp, VRWLOCK_READ); |
1425 | return generic_block_bmap(mapping, block, xfs_get_block); | 1420 | return generic_block_bmap(mapping, block, xfs_get_blocks); |
1426 | } | 1421 | } |
1427 | 1422 | ||
1428 | STATIC int | 1423 | STATIC int |
@@ -1430,7 +1425,7 @@ xfs_vm_readpage( | |||
1430 | struct file *unused, | 1425 | struct file *unused, |
1431 | struct page *page) | 1426 | struct page *page) |
1432 | { | 1427 | { |
1433 | return mpage_readpage(page, xfs_get_block); | 1428 | return mpage_readpage(page, xfs_get_blocks); |
1434 | } | 1429 | } |
1435 | 1430 | ||
1436 | STATIC int | 1431 | STATIC int |
@@ -1440,7 +1435,7 @@ xfs_vm_readpages( | |||
1440 | struct list_head *pages, | 1435 | struct list_head *pages, |
1441 | unsigned nr_pages) | 1436 | unsigned nr_pages) |
1442 | { | 1437 | { |
1443 | return mpage_readpages(mapping, pages, nr_pages, xfs_get_block); | 1438 | return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks); |
1444 | } | 1439 | } |
1445 | 1440 | ||
1446 | STATIC void | 1441 | STATIC void |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 795699f121d2..60716543c68b 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -41,6 +41,6 @@ typedef struct xfs_ioend { | |||
41 | } xfs_ioend_t; | 41 | } xfs_ioend_t; |
42 | 42 | ||
43 | extern struct address_space_operations xfs_address_space_operations; | 43 | extern struct address_space_operations xfs_address_space_operations; |
44 | extern int xfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 44 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); |
45 | 45 | ||
46 | #endif /* __XFS_IOPS_H__ */ | 46 | #endif /* __XFS_IOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h index e5b0559700a4..e794ca4efc76 100644 --- a/fs/xfs/linux-2.6/xfs_export.h +++ b/fs/xfs/linux-2.6/xfs_export.h | |||
@@ -54,7 +54,7 @@ | |||
54 | * Note, the NFS filehandle also includes an fsid portion which | 54 | * Note, the NFS filehandle also includes an fsid portion which |
55 | * may have an inode number in it. That number is hardcoded to | 55 | * may have an inode number in it. That number is hardcoded to |
56 | * 32bits and there is no way for XFS to intercept it. In | 56 | * 32bits and there is no way for XFS to intercept it. In |
57 | * practice this means when exporting an XFS filesytem with 64bit | 57 | * practice this means when exporting an XFS filesystem with 64bit |
58 | * inodes you should either export the mountpoint (rather than | 58 | * inodes you should either export the mountpoint (rather than |
59 | * a subdirectory) or use the "fsid" export option. | 59 | * a subdirectory) or use the "fsid" export option. |
60 | */ | 60 | */ |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 185567a6a561..85997b1205f5 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -528,7 +528,7 @@ open_exec_out: | |||
528 | } | 528 | } |
529 | #endif /* HAVE_FOP_OPEN_EXEC */ | 529 | #endif /* HAVE_FOP_OPEN_EXEC */ |
530 | 530 | ||
531 | struct file_operations xfs_file_operations = { | 531 | const struct file_operations xfs_file_operations = { |
532 | .llseek = generic_file_llseek, | 532 | .llseek = generic_file_llseek, |
533 | .read = do_sync_read, | 533 | .read = do_sync_read, |
534 | .write = do_sync_write, | 534 | .write = do_sync_write, |
@@ -550,7 +550,7 @@ struct file_operations xfs_file_operations = { | |||
550 | #endif | 550 | #endif |
551 | }; | 551 | }; |
552 | 552 | ||
553 | struct file_operations xfs_invis_file_operations = { | 553 | const struct file_operations xfs_invis_file_operations = { |
554 | .llseek = generic_file_llseek, | 554 | .llseek = generic_file_llseek, |
555 | .read = do_sync_read, | 555 | .read = do_sync_read, |
556 | .write = do_sync_write, | 556 | .write = do_sync_write, |
@@ -570,7 +570,7 @@ struct file_operations xfs_invis_file_operations = { | |||
570 | }; | 570 | }; |
571 | 571 | ||
572 | 572 | ||
573 | struct file_operations xfs_dir_file_operations = { | 573 | const struct file_operations xfs_dir_file_operations = { |
574 | .read = generic_read_dir, | 574 | .read = generic_read_dir, |
575 | .readdir = xfs_file_readdir, | 575 | .readdir = xfs_file_readdir, |
576 | .unlocked_ioctl = xfs_file_ioctl, | 576 | .unlocked_ioctl = xfs_file_ioctl, |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index b6321abd9a81..251bfe451a3f 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -72,7 +72,7 @@ xfs_ioctl32_flock( | |||
72 | copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || | 72 | copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || |
73 | copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) | 73 | copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) |
74 | return -EFAULT; | 74 | return -EFAULT; |
75 | 75 | ||
76 | return (unsigned long)p; | 76 | return (unsigned long)p; |
77 | } | 77 | } |
78 | 78 | ||
@@ -107,11 +107,15 @@ xfs_ioctl32_bulkstat( | |||
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | STATIC long | 109 | STATIC long |
110 | xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) | 110 | xfs_compat_ioctl( |
111 | int mode, | ||
112 | struct file *file, | ||
113 | unsigned cmd, | ||
114 | unsigned long arg) | ||
111 | { | 115 | { |
116 | struct inode *inode = file->f_dentry->d_inode; | ||
117 | vnode_t *vp = vn_from_inode(inode); | ||
112 | int error; | 118 | int error; |
113 | struct inode *inode = f->f_dentry->d_inode; | ||
114 | vnode_t *vp = vn_to_inode(inode); | ||
115 | 119 | ||
116 | switch (cmd) { | 120 | switch (cmd) { |
117 | case XFS_IOC_DIOINFO: | 121 | case XFS_IOC_DIOINFO: |
@@ -189,7 +193,7 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) | |||
189 | return -ENOIOCTLCMD; | 193 | return -ENOIOCTLCMD; |
190 | } | 194 | } |
191 | 195 | ||
192 | VOP_IOCTL(vp, inode, f, mode, cmd, (void __user *)arg, error); | 196 | VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error); |
193 | VMODIFY(vp); | 197 | VMODIFY(vp); |
194 | 198 | ||
195 | return error; | 199 | return error; |
@@ -197,18 +201,18 @@ xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) | |||
197 | 201 | ||
198 | long | 202 | long |
199 | xfs_file_compat_ioctl( | 203 | xfs_file_compat_ioctl( |
200 | struct file *f, | 204 | struct file *file, |
201 | unsigned cmd, | 205 | unsigned cmd, |
202 | unsigned long arg) | 206 | unsigned long arg) |
203 | { | 207 | { |
204 | return xfs_compat_ioctl(0, f, cmd, arg); | 208 | return xfs_compat_ioctl(0, file, cmd, arg); |
205 | } | 209 | } |
206 | 210 | ||
207 | long | 211 | long |
208 | xfs_file_compat_invis_ioctl( | 212 | xfs_file_compat_invis_ioctl( |
209 | struct file *f, | 213 | struct file *file, |
210 | unsigned cmd, | 214 | unsigned cmd, |
211 | unsigned long arg) | 215 | unsigned long arg) |
212 | { | 216 | { |
213 | return xfs_compat_ioctl(IO_INVIS, f, cmd, arg); | 217 | return xfs_compat_ioctl(IO_INVIS, file, cmd, arg); |
214 | } | 218 | } |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index af487437bd7e..149237304fb6 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -708,7 +708,7 @@ STATIC void | |||
708 | xfs_vn_truncate( | 708 | xfs_vn_truncate( |
709 | struct inode *inode) | 709 | struct inode *inode) |
710 | { | 710 | { |
711 | block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_block); | 711 | block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks); |
712 | } | 712 | } |
713 | 713 | ||
714 | STATIC int | 714 | STATIC int |
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index a8417d7af5f9..ad6173da5678 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h | |||
@@ -22,9 +22,9 @@ extern struct inode_operations xfs_inode_operations; | |||
22 | extern struct inode_operations xfs_dir_inode_operations; | 22 | extern struct inode_operations xfs_dir_inode_operations; |
23 | extern struct inode_operations xfs_symlink_inode_operations; | 23 | extern struct inode_operations xfs_symlink_inode_operations; |
24 | 24 | ||
25 | extern struct file_operations xfs_file_operations; | 25 | extern const struct file_operations xfs_file_operations; |
26 | extern struct file_operations xfs_dir_file_operations; | 26 | extern const struct file_operations xfs_dir_file_operations; |
27 | extern struct file_operations xfs_invis_file_operations; | 27 | extern const struct file_operations xfs_invis_file_operations; |
28 | 28 | ||
29 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, | 29 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, |
30 | int, unsigned int, void __user *); | 30 | int, unsigned int, void __user *); |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 0169360475c4..84ddf1893894 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -681,7 +681,7 @@ start: | |||
681 | eventsent = 1; | 681 | eventsent = 1; |
682 | 682 | ||
683 | /* | 683 | /* |
684 | * The iolock was dropped and reaquired in XFS_SEND_DATA | 684 | * The iolock was dropped and reacquired in XFS_SEND_DATA |
685 | * so we have to recheck the size when appending. | 685 | * so we have to recheck the size when appending. |
686 | * We will only "goto start;" once, since having sent the | 686 | * We will only "goto start;" once, since having sent the |
687 | * event prevents another call to XFS_SEND_DATA, which is | 687 | * event prevents another call to XFS_SEND_DATA, which is |
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 8fed356db055..841200c03092 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h | |||
@@ -92,7 +92,7 @@ typedef enum { | |||
92 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ | 92 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ |
93 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ | 93 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ |
94 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ | 94 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ |
95 | #define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */ | 95 | #define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */ |
96 | 96 | ||
97 | typedef int (*vfs_mount_t)(bhv_desc_t *, | 97 | typedef int (*vfs_mount_t)(bhv_desc_t *, |
98 | struct xfs_mount_args *, struct cred *); | 98 | struct xfs_mount_args *, struct cred *); |
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index e4e5f05b841b..546f48af882a 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c | |||
@@ -221,7 +221,7 @@ xfs_qm_dqunpin_wait( | |||
221 | * as possible. | 221 | * as possible. |
222 | * | 222 | * |
223 | * We must not be holding the AIL_LOCK at this point. Calling incore() to | 223 | * We must not be holding the AIL_LOCK at this point. Calling incore() to |
224 | * search the buffercache can be a time consuming thing, and AIL_LOCK is a | 224 | * search the buffer cache can be a time consuming thing, and AIL_LOCK is a |
225 | * spinlock. | 225 | * spinlock. |
226 | */ | 226 | */ |
227 | STATIC void | 227 | STATIC void |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 1fb757ef3f41..73c1e5e80c07 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -289,7 +289,7 @@ xfs_qm_rele_quotafs_ref( | |||
289 | 289 | ||
290 | /* | 290 | /* |
291 | * This is called at mount time from xfs_mountfs to initialize the quotainfo | 291 | * This is called at mount time from xfs_mountfs to initialize the quotainfo |
292 | * structure and start the global quotamanager (xfs_Gqm) if it hasn't done | 292 | * structure and start the global quota manager (xfs_Gqm) if it hasn't done |
293 | * so already. Note that the superblock has not been read in yet. | 293 | * so already. Note that the superblock has not been read in yet. |
294 | */ | 294 | */ |
295 | void | 295 | void |
@@ -807,7 +807,7 @@ xfs_qm_dqattach_one( | |||
807 | * Given a udquot and gdquot, attach a ptr to the group dquot in the | 807 | * Given a udquot and gdquot, attach a ptr to the group dquot in the |
808 | * udquot as a hint for future lookups. The idea sounds simple, but the | 808 | * udquot as a hint for future lookups. The idea sounds simple, but the |
809 | * execution isn't, because the udquot might have a group dquot attached | 809 | * execution isn't, because the udquot might have a group dquot attached |
810 | * already and getting rid of that gets us into lock ordering contraints. | 810 | * already and getting rid of that gets us into lock ordering constraints. |
811 | * The process is complicated more by the fact that the dquots may or may not | 811 | * The process is complicated more by the fact that the dquots may or may not |
812 | * be locked on entry. | 812 | * be locked on entry. |
813 | */ | 813 | */ |
@@ -1094,10 +1094,10 @@ xfs_qm_sync( | |||
1094 | } | 1094 | } |
1095 | /* | 1095 | /* |
1096 | * If we can't grab the flush lock then if the caller | 1096 | * If we can't grab the flush lock then if the caller |
1097 | * really wanted us to give this our best shot, | 1097 | * really wanted us to give this our best shot, so |
1098 | * see if we can give a push to the buffer before we wait | 1098 | * see if we can give a push to the buffer before we wait |
1099 | * on the flush lock. At this point, we know that | 1099 | * on the flush lock. At this point, we know that |
1100 | * eventhough the dquot is being flushed, | 1100 | * even though the dquot is being flushed, |
1101 | * it has (new) dirty data. | 1101 | * it has (new) dirty data. |
1102 | */ | 1102 | */ |
1103 | xfs_qm_dqflock_pushbuf_wait(dqp); | 1103 | xfs_qm_dqflock_pushbuf_wait(dqp); |
@@ -1491,7 +1491,7 @@ xfs_qm_reset_dqcounts( | |||
1491 | /* | 1491 | /* |
1492 | * Do a sanity check, and if needed, repair the dqblk. Don't | 1492 | * Do a sanity check, and if needed, repair the dqblk. Don't |
1493 | * output any warnings because it's perfectly possible to | 1493 | * output any warnings because it's perfectly possible to |
1494 | * find unitialized dquot blks. See comment in xfs_qm_dqcheck. | 1494 | * find uninitialised dquot blks. See comment in xfs_qm_dqcheck. |
1495 | */ | 1495 | */ |
1496 | (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR, | 1496 | (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR, |
1497 | "xfs_quotacheck"); | 1497 | "xfs_quotacheck"); |
@@ -1580,7 +1580,7 @@ xfs_qm_dqiterate( | |||
1580 | 1580 | ||
1581 | error = 0; | 1581 | error = 0; |
1582 | /* | 1582 | /* |
1583 | * This looks racey, but we can't keep an inode lock across a | 1583 | * This looks racy, but we can't keep an inode lock across a |
1584 | * trans_reserve. But, this gets called during quotacheck, and that | 1584 | * trans_reserve. But, this gets called during quotacheck, and that |
1585 | * happens only at mount time which is single threaded. | 1585 | * happens only at mount time which is single threaded. |
1586 | */ | 1586 | */ |
@@ -1824,7 +1824,7 @@ xfs_qm_dqusage_adjust( | |||
1824 | * we have to start from the beginning anyway. | 1824 | * we have to start from the beginning anyway. |
1825 | * Once we're done, we'll log all the dquot bufs. | 1825 | * Once we're done, we'll log all the dquot bufs. |
1826 | * | 1826 | * |
1827 | * The *QUOTA_ON checks below may look pretty racey, but quotachecks | 1827 | * The *QUOTA_ON checks below may look pretty racy, but quotachecks |
1828 | * and quotaoffs don't race. (Quotachecks happen at mount time only). | 1828 | * and quotaoffs don't race. (Quotachecks happen at mount time only). |
1829 | */ | 1829 | */ |
1830 | if (XFS_IS_UQUOTA_ON(mp)) { | 1830 | if (XFS_IS_UQUOTA_ON(mp)) { |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 676884394aae..c55db463bbf2 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -912,7 +912,7 @@ xfs_qm_export_dquot( | |||
912 | 912 | ||
913 | /* | 913 | /* |
914 | * Internally, we don't reset all the timers when quota enforcement | 914 | * Internally, we don't reset all the timers when quota enforcement |
915 | * gets turned off. No need to confuse the userlevel code, | 915 | * gets turned off. No need to confuse the user level code, |
916 | * so return zeroes in that case. | 916 | * so return zeroes in that case. |
917 | */ | 917 | */ |
918 | if (! XFS_IS_QUOTA_ENFORCED(mp)) { | 918 | if (! XFS_IS_QUOTA_ENFORCED(mp)) { |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 3290975d31f7..d8e131ec0aa8 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -804,7 +804,7 @@ xfs_trans_reserve_quota_bydquots( | |||
804 | } | 804 | } |
805 | 805 | ||
806 | /* | 806 | /* |
807 | * Didnt change anything critical, so, no need to log | 807 | * Didn't change anything critical, so, no need to log |
808 | */ | 808 | */ |
809 | return (0); | 809 | return (0); |
810 | } | 810 | } |
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 4ff0f4e41c61..2539af34eb63 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -395,7 +395,7 @@ xfs_acl_allow_set( | |||
395 | * The access control process to determine the access permission: | 395 | * The access control process to determine the access permission: |
396 | * if uid == file owner id, use the file owner bits. | 396 | * if uid == file owner id, use the file owner bits. |
397 | * if gid == file owner group id, use the file group bits. | 397 | * if gid == file owner group id, use the file group bits. |
398 | * scan ACL for a maching user or group, and use matched entry | 398 | * scan ACL for a matching user or group, and use matched entry |
399 | * permission. Use total permissions of all matching group entries, | 399 | * permission. Use total permissions of all matching group entries, |
400 | * until all acl entries are exhausted. The final permission produced | 400 | * until all acl entries are exhausted. The final permission produced |
401 | * by matching acl entry or entries needs to be & with group permission. | 401 | * by matching acl entry or entries needs to be & with group permission. |
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index a96e2ffce0cc..dc2361dd740a 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
@@ -179,7 +179,7 @@ typedef struct xfs_perag | |||
179 | { | 179 | { |
180 | char pagf_init; /* this agf's entry is initialized */ | 180 | char pagf_init; /* this agf's entry is initialized */ |
181 | char pagi_init; /* this agi's entry is initialized */ | 181 | char pagi_init; /* this agi's entry is initialized */ |
182 | char pagf_metadata; /* the agf is prefered to be metadata */ | 182 | char pagf_metadata; /* the agf is preferred to be metadata */ |
183 | char pagi_inodeok; /* The agi is ok for inodes */ | 183 | char pagi_inodeok; /* The agi is ok for inodes */ |
184 | __uint8_t pagf_levels[XFS_BTNUM_AGF]; | 184 | __uint8_t pagf_levels[XFS_BTNUM_AGF]; |
185 | /* # of levels in bno & cnt btree */ | 185 | /* # of levels in bno & cnt btree */ |
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index f4328e1e2a74..64ee07db0d5e 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -511,7 +511,7 @@ STATIC void | |||
511 | xfs_alloc_trace_busy( | 511 | xfs_alloc_trace_busy( |
512 | char *name, /* function tag string */ | 512 | char *name, /* function tag string */ |
513 | char *str, /* additional string */ | 513 | char *str, /* additional string */ |
514 | xfs_mount_t *mp, /* file system mount poing */ | 514 | xfs_mount_t *mp, /* file system mount point */ |
515 | xfs_agnumber_t agno, /* allocation group number */ | 515 | xfs_agnumber_t agno, /* allocation group number */ |
516 | xfs_agblock_t agbno, /* a.g. relative block number */ | 516 | xfs_agblock_t agbno, /* a.g. relative block number */ |
517 | xfs_extlen_t len, /* length of extent */ | 517 | xfs_extlen_t len, /* length of extent */ |
@@ -1843,7 +1843,7 @@ xfs_alloc_fix_freelist( | |||
1843 | } else | 1843 | } else |
1844 | agbp = NULL; | 1844 | agbp = NULL; |
1845 | 1845 | ||
1846 | /* If this is a metadata prefered pag and we are user data | 1846 | /* If this is a metadata preferred pag and we are user data |
1847 | * then try somewhere else if we are not being asked to | 1847 | * then try somewhere else if we are not being asked to |
1848 | * try harder at this point | 1848 | * try harder at this point |
1849 | */ | 1849 | */ |
@@ -2458,7 +2458,7 @@ error0: | |||
2458 | /* | 2458 | /* |
2459 | * AG Busy list management | 2459 | * AG Busy list management |
2460 | * The busy list contains block ranges that have been freed but whose | 2460 | * The busy list contains block ranges that have been freed but whose |
2461 | * transacations have not yet hit disk. If any block listed in a busy | 2461 | * transactions have not yet hit disk. If any block listed in a busy |
2462 | * list is reused, the transaction that freed it must be forced to disk | 2462 | * list is reused, the transaction that freed it must be forced to disk |
2463 | * before continuing to use the block. | 2463 | * before continuing to use the block. |
2464 | * | 2464 | * |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 3546dea27b7d..2d1f8928b267 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -68,7 +68,7 @@ typedef struct xfs_alloc_arg { | |||
68 | xfs_alloctype_t otype; /* original allocation type */ | 68 | xfs_alloctype_t otype; /* original allocation type */ |
69 | char wasdel; /* set if allocation was prev delayed */ | 69 | char wasdel; /* set if allocation was prev delayed */ |
70 | char wasfromfl; /* set if allocation is from freelist */ | 70 | char wasfromfl; /* set if allocation is from freelist */ |
71 | char isfl; /* set if is freelist blocks - !actg */ | 71 | char isfl; /* set if is freelist blocks - !acctg */ |
72 | char userdata; /* set if this is user data */ | 72 | char userdata; /* set if this is user data */ |
73 | } xfs_alloc_arg_t; | 73 | } xfs_alloc_arg_t; |
74 | 74 | ||
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 093fac476bda..b6e1e02bbb28 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -294,7 +294,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen, | |||
294 | xfs_trans_ihold(args.trans, dp); | 294 | xfs_trans_ihold(args.trans, dp); |
295 | 295 | ||
296 | /* | 296 | /* |
297 | * If the attribute list is non-existant or a shortform list, | 297 | * If the attribute list is non-existent or a shortform list, |
298 | * upgrade it to a single-leaf-block attribute list. | 298 | * upgrade it to a single-leaf-block attribute list. |
299 | */ | 299 | */ |
300 | if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || | 300 | if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || |
@@ -1584,7 +1584,7 @@ out: | |||
1584 | * Fill in the disk block numbers in the state structure for the buffers | 1584 | * Fill in the disk block numbers in the state structure for the buffers |
1585 | * that are attached to the state structure. | 1585 | * that are attached to the state structure. |
1586 | * This is done so that we can quickly reattach ourselves to those buffers | 1586 | * This is done so that we can quickly reattach ourselves to those buffers |
1587 | * after some set of transaction commit's has released these buffers. | 1587 | * after some set of transaction commits have released these buffers. |
1588 | */ | 1588 | */ |
1589 | STATIC int | 1589 | STATIC int |
1590 | xfs_attr_fillstate(xfs_da_state_t *state) | 1590 | xfs_attr_fillstate(xfs_da_state_t *state) |
@@ -1631,7 +1631,7 @@ xfs_attr_fillstate(xfs_da_state_t *state) | |||
1631 | /* | 1631 | /* |
1632 | * Reattach the buffers to the state structure based on the disk block | 1632 | * Reattach the buffers to the state structure based on the disk block |
1633 | * numbers stored in the state structure. | 1633 | * numbers stored in the state structure. |
1634 | * This is done after some set of transaction commit's has released those | 1634 | * This is done after some set of transaction commits have released those |
1635 | * buffers from our grip. | 1635 | * buffers from our grip. |
1636 | */ | 1636 | */ |
1637 | STATIC int | 1637 | STATIC int |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 717682747bd2..9462be86aa14 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -524,7 +524,7 @@ xfs_attr_shortform_compare(const void *a, const void *b) | |||
524 | 524 | ||
525 | /* | 525 | /* |
526 | * Copy out entries of shortform attribute lists for attr_list(). | 526 | * Copy out entries of shortform attribute lists for attr_list(). |
527 | * Shortform atrtribute lists are not stored in hashval sorted order. | 527 | * Shortform attribute lists are not stored in hashval sorted order. |
528 | * If the output buffer is not large enough to hold them all, then we | 528 | * If the output buffer is not large enough to hold them all, then we |
529 | * we have to calculate each entries' hashvalue and sort them before | 529 | * we have to calculate each entries' hashvalue and sort them before |
530 | * we can begin returning them to the user. | 530 | * we can begin returning them to the user. |
@@ -1541,7 +1541,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1541 | /* | 1541 | /* |
1542 | * Check for the degenerate case of the block being empty. | 1542 | * Check for the degenerate case of the block being empty. |
1543 | * If the block is empty, we'll simply delete it, no need to | 1543 | * If the block is empty, we'll simply delete it, no need to |
1544 | * coalesce it with a sibling block. We choose (aribtrarily) | 1544 | * coalesce it with a sibling block. We choose (arbitrarily) |
1545 | * to merge with the forward block unless it is NULL. | 1545 | * to merge with the forward block unless it is NULL. |
1546 | */ | 1546 | */ |
1547 | if (count == 0) { | 1547 | if (count == 0) { |
diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c index 9880adae3938..f4fe3715a803 100644 --- a/fs/xfs/xfs_behavior.c +++ b/fs/xfs/xfs_behavior.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * The behavior chain is ordered based on the 'position' number which | 31 | * The behavior chain is ordered based on the 'position' number which |
32 | * lives in the first field of the ops vector (higher numbers first). | 32 | * lives in the first field of the ops vector (higher numbers first). |
33 | * | 33 | * |
34 | * Attemps to insert duplicate ops result in an EINVAL return code. | 34 | * Attempts to insert duplicate ops result in an EINVAL return code. |
35 | * Otherwise, return 0 to indicate success. | 35 | * Otherwise, return 0 to indicate success. |
36 | */ | 36 | */ |
37 | int | 37 | int |
@@ -84,7 +84,7 @@ bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) | |||
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Remove a behavior descriptor from a position in a behavior chain; | 86 | * Remove a behavior descriptor from a position in a behavior chain; |
87 | * the postition is guaranteed not to be the first position. | 87 | * the position is guaranteed not to be the first position. |
88 | * Should only be called by the bhv_remove() macro. | 88 | * Should only be called by the bhv_remove() macro. |
89 | */ | 89 | */ |
90 | void | 90 | void |
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h index 2cd89bb5ab10..1d8ff103201c 100644 --- a/fs/xfs/xfs_behavior.h +++ b/fs/xfs/xfs_behavior.h | |||
@@ -39,7 +39,7 @@ | |||
39 | * behaviors is synchronized with operations-in-progress (oip's) so that | 39 | * behaviors is synchronized with operations-in-progress (oip's) so that |
40 | * the oip's always see a consistent view of the chain. | 40 | * the oip's always see a consistent view of the chain. |
41 | * | 41 | * |
42 | * The term "interpostion" is used to refer to the act of inserting | 42 | * The term "interposition" is used to refer to the act of inserting |
43 | * a behavior such that it interposes on (i.e., is inserted in front | 43 | * a behavior such that it interposes on (i.e., is inserted in front |
44 | * of) a particular other behavior. A key example of this is when a | 44 | * of) a particular other behavior. A key example of this is when a |
45 | * system implementing distributed single system image wishes to | 45 | * system implementing distributed single system image wishes to |
@@ -51,7 +51,7 @@ | |||
51 | * | 51 | * |
52 | * Behavior synchronization is logic which is necessary under certain | 52 | * Behavior synchronization is logic which is necessary under certain |
53 | * circumstances that there is no conflict between ongoing operations | 53 | * circumstances that there is no conflict between ongoing operations |
54 | * traversing the behavior chain and those dunamically modifying the | 54 | * traversing the behavior chain and those dynamically modifying the |
55 | * behavior chain. Because behavior synchronization adds extra overhead | 55 | * behavior chain. Because behavior synchronization adds extra overhead |
56 | * to virtual operation invocation, we want to restrict, as much as | 56 | * to virtual operation invocation, we want to restrict, as much as |
57 | * we can, the requirement for this extra code, to those situations | 57 | * we can, the requirement for this extra code, to those situations |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 2d702e4a74a3..d384e489705f 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -3467,113 +3467,6 @@ done: | |||
3467 | return error; | 3467 | return error; |
3468 | } | 3468 | } |
3469 | 3469 | ||
3470 | xfs_bmbt_rec_t * /* pointer to found extent entry */ | ||
3471 | xfs_bmap_do_search_extents( | ||
3472 | xfs_bmbt_rec_t *base, /* base of extent list */ | ||
3473 | xfs_extnum_t lastx, /* last extent index used */ | ||
3474 | xfs_extnum_t nextents, /* number of file extents */ | ||
3475 | xfs_fileoff_t bno, /* block number searched for */ | ||
3476 | int *eofp, /* out: end of file found */ | ||
3477 | xfs_extnum_t *lastxp, /* out: last extent index */ | ||
3478 | xfs_bmbt_irec_t *gotp, /* out: extent entry found */ | ||
3479 | xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ | ||
3480 | { | ||
3481 | xfs_bmbt_rec_t *ep; /* extent list entry pointer */ | ||
3482 | xfs_bmbt_irec_t got; /* extent list entry, decoded */ | ||
3483 | int high; /* high index of binary search */ | ||
3484 | int low; /* low index of binary search */ | ||
3485 | |||
3486 | /* | ||
3487 | * Initialize the extent entry structure to catch access to | ||
3488 | * uninitialized br_startblock field. | ||
3489 | */ | ||
3490 | got.br_startoff = 0xffa5a5a5a5a5a5a5LL; | ||
3491 | got.br_blockcount = 0xa55a5a5a5a5a5a5aLL; | ||
3492 | got.br_state = XFS_EXT_INVALID; | ||
3493 | |||
3494 | #if XFS_BIG_BLKNOS | ||
3495 | got.br_startblock = 0xffffa5a5a5a5a5a5LL; | ||
3496 | #else | ||
3497 | got.br_startblock = 0xffffa5a5; | ||
3498 | #endif | ||
3499 | |||
3500 | if (lastx != NULLEXTNUM && lastx < nextents) | ||
3501 | ep = base + lastx; | ||
3502 | else | ||
3503 | ep = NULL; | ||
3504 | prevp->br_startoff = NULLFILEOFF; | ||
3505 | if (ep && bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep)) && | ||
3506 | bno < got.br_startoff + | ||
3507 | (got.br_blockcount = xfs_bmbt_get_blockcount(ep))) | ||
3508 | *eofp = 0; | ||
3509 | else if (ep && lastx < nextents - 1 && | ||
3510 | bno >= (got.br_startoff = xfs_bmbt_get_startoff(ep + 1)) && | ||
3511 | bno < got.br_startoff + | ||
3512 | (got.br_blockcount = xfs_bmbt_get_blockcount(ep + 1))) { | ||
3513 | lastx++; | ||
3514 | ep++; | ||
3515 | *eofp = 0; | ||
3516 | } else if (nextents == 0) | ||
3517 | *eofp = 1; | ||
3518 | else if (bno == 0 && | ||
3519 | (got.br_startoff = xfs_bmbt_get_startoff(base)) == 0) { | ||
3520 | ep = base; | ||
3521 | lastx = 0; | ||
3522 | got.br_blockcount = xfs_bmbt_get_blockcount(ep); | ||
3523 | *eofp = 0; | ||
3524 | } else { | ||
3525 | low = 0; | ||
3526 | high = nextents - 1; | ||
3527 | /* binary search the extents array */ | ||
3528 | while (low <= high) { | ||
3529 | XFS_STATS_INC(xs_cmp_exlist); | ||
3530 | lastx = (low + high) >> 1; | ||
3531 | ep = base + lastx; | ||
3532 | got.br_startoff = xfs_bmbt_get_startoff(ep); | ||
3533 | got.br_blockcount = xfs_bmbt_get_blockcount(ep); | ||
3534 | if (bno < got.br_startoff) | ||
3535 | high = lastx - 1; | ||
3536 | else if (bno >= got.br_startoff + got.br_blockcount) | ||
3537 | low = lastx + 1; | ||
3538 | else { | ||
3539 | got.br_startblock = xfs_bmbt_get_startblock(ep); | ||
3540 | got.br_state = xfs_bmbt_get_state(ep); | ||
3541 | *eofp = 0; | ||
3542 | *lastxp = lastx; | ||
3543 | *gotp = got; | ||
3544 | return ep; | ||
3545 | } | ||
3546 | } | ||
3547 | if (bno >= got.br_startoff + got.br_blockcount) { | ||
3548 | lastx++; | ||
3549 | if (lastx == nextents) { | ||
3550 | *eofp = 1; | ||
3551 | got.br_startblock = xfs_bmbt_get_startblock(ep); | ||
3552 | got.br_state = xfs_bmbt_get_state(ep); | ||
3553 | *prevp = got; | ||
3554 | ep = NULL; | ||
3555 | } else { | ||
3556 | *eofp = 0; | ||
3557 | xfs_bmbt_get_all(ep, prevp); | ||
3558 | ep++; | ||
3559 | got.br_startoff = xfs_bmbt_get_startoff(ep); | ||
3560 | got.br_blockcount = xfs_bmbt_get_blockcount(ep); | ||
3561 | } | ||
3562 | } else { | ||
3563 | *eofp = 0; | ||
3564 | if (ep > base) | ||
3565 | xfs_bmbt_get_all(ep - 1, prevp); | ||
3566 | } | ||
3567 | } | ||
3568 | if (ep) { | ||
3569 | got.br_startblock = xfs_bmbt_get_startblock(ep); | ||
3570 | got.br_state = xfs_bmbt_get_state(ep); | ||
3571 | } | ||
3572 | *lastxp = lastx; | ||
3573 | *gotp = got; | ||
3574 | return ep; | ||
3575 | } | ||
3576 | |||
3577 | /* | 3470 | /* |
3578 | * Search the extent records for the entry containing block bno. | 3471 | * Search the extent records for the entry containing block bno. |
3579 | * If bno lies in a hole, point to the next entry. If bno lies | 3472 | * If bno lies in a hole, point to the next entry. If bno lies |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 011ccaa9a1c0..f83399c89ce3 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -362,14 +362,6 @@ xfs_bmbt_rec_t * | |||
362 | xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, | 362 | xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *, |
363 | xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); | 363 | xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); |
364 | 364 | ||
365 | /* | ||
366 | * Search an extent list for the extent which includes block | ||
367 | * bno. | ||
368 | */ | ||
369 | xfs_bmbt_rec_t *xfs_bmap_do_search_extents(xfs_bmbt_rec_t *, | ||
370 | xfs_extnum_t, xfs_extnum_t, xfs_fileoff_t, int *, | ||
371 | xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *); | ||
372 | |||
373 | #endif /* __KERNEL__ */ | 365 | #endif /* __KERNEL__ */ |
374 | 366 | ||
375 | #endif /* __XFS_BMAP_H__ */ | 367 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 07e2324152b1..5fed15682dda 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -98,12 +98,12 @@ xfs_buf_item_flush_log_debug( | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * This function is called to verify that our caller's have logged | 101 | * This function is called to verify that our callers have logged |
102 | * all the bytes that they changed. | 102 | * all the bytes that they changed. |
103 | * | 103 | * |
104 | * It does this by comparing the original copy of the buffer stored in | 104 | * It does this by comparing the original copy of the buffer stored in |
105 | * the buf log item's bli_orig array to the current copy of the buffer | 105 | * the buf log item's bli_orig array to the current copy of the buffer |
106 | * and ensuring that all bytes which miscompare are set in the bli_logged | 106 | * and ensuring that all bytes which mismatch are set in the bli_logged |
107 | * array of the buf log item. | 107 | * array of the buf log item. |
108 | */ | 108 | */ |
109 | STATIC void | 109 | STATIC void |
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h index 433ec537f9bd..d0035c6e9514 100644 --- a/fs/xfs/xfs_cap.h +++ b/fs/xfs/xfs_cap.h | |||
@@ -38,7 +38,7 @@ typedef struct xfs_cap_set { | |||
38 | /* | 38 | /* |
39 | * For Linux, we take the bitfields directly from capability.h | 39 | * For Linux, we take the bitfields directly from capability.h |
40 | * and no longer attempt to keep this attribute ondisk compatible | 40 | * and no longer attempt to keep this attribute ondisk compatible |
41 | * with IRIX. Since this attribute is only set on exectuables, | 41 | * with IRIX. Since this attribute is only set on executables, |
42 | * it just doesn't make much sense to try. We do use a different | 42 | * it just doesn't make much sense to try. We do use a different |
43 | * named attribute though, to avoid confusion. | 43 | * named attribute though, to avoid confusion. |
44 | */ | 44 | */ |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 4bae3a76c678..8988b9051175 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -840,7 +840,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) | |||
840 | /* | 840 | /* |
841 | * Check for the degenerate case of the block being empty. | 841 | * Check for the degenerate case of the block being empty. |
842 | * If the block is empty, we'll simply delete it, no need to | 842 | * If the block is empty, we'll simply delete it, no need to |
843 | * coalesce it with a sibling block. We choose (aribtrarily) | 843 | * coalesce it with a sibling block. We choose (arbitrarily) |
844 | * to merge with the forward block unless it is NULL. | 844 | * to merge with the forward block unless it is NULL. |
845 | */ | 845 | */ |
846 | if (count == 0) { | 846 | if (count == 0) { |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index bd5cee6aa51a..972ded595476 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -533,7 +533,7 @@ xfs_dir2_block_getdents( | |||
533 | 533 | ||
534 | /* | 534 | /* |
535 | * Reached the end of the block. | 535 | * Reached the end of the block. |
536 | * Set the offset to a nonexistent block 1 and return. | 536 | * Set the offset to a non-existent block 1 and return. |
537 | */ | 537 | */ |
538 | *eofp = 1; | 538 | *eofp = 1; |
539 | 539 | ||
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 08648b18265c..0f5e2f2ce6ec 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -515,7 +515,7 @@ xfs_dir2_leaf_addname( | |||
515 | ASSERT(be32_to_cpu(leaf->ents[highstale].address) == | 515 | ASSERT(be32_to_cpu(leaf->ents[highstale].address) == |
516 | XFS_DIR2_NULL_DATAPTR); | 516 | XFS_DIR2_NULL_DATAPTR); |
517 | /* | 517 | /* |
518 | * Copy entries down to copver the stale entry | 518 | * Copy entries down to cover the stale entry |
519 | * and make room for the new entry. | 519 | * and make room for the new entry. |
520 | */ | 520 | */ |
521 | if (highstale - index > 0) | 521 | if (highstale - index > 0) |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index af556f16a0c7..ac511ab9c52d 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -830,7 +830,7 @@ xfs_dir2_leafn_rebalance( | |||
830 | state->inleaf = 1; | 830 | state->inleaf = 1; |
831 | blk2->index = 0; | 831 | blk2->index = 0; |
832 | cmn_err(CE_ALERT, | 832 | cmn_err(CE_ALERT, |
833 | "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting orignal leaf: " | 833 | "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: " |
834 | "blk1->index %d\n", | 834 | "blk1->index %d\n", |
835 | blk1->index); | 835 | blk1->index); |
836 | } | 836 | } |
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c index ee88751c3be6..6d711869262f 100644 --- a/fs/xfs/xfs_dir_leaf.c +++ b/fs/xfs/xfs_dir_leaf.c | |||
@@ -1341,7 +1341,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1341 | /* | 1341 | /* |
1342 | * Check for the degenerate case of the block being empty. | 1342 | * Check for the degenerate case of the block being empty. |
1343 | * If the block is empty, we'll simply delete it, no need to | 1343 | * If the block is empty, we'll simply delete it, no need to |
1344 | * coalesce it with a sibling block. We choose (aribtrarily) | 1344 | * coalesce it with a sibling block. We choose (arbitrarily) |
1345 | * to merge with the forward block unless it is NULL. | 1345 | * to merge with the forward block unless it is NULL. |
1346 | */ | 1346 | */ |
1347 | if (count == 0) { | 1347 | if (count == 0) { |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 56caa88713ab..dfa3527b20a7 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -477,7 +477,7 @@ xfs_fs_counts( | |||
477 | * | 477 | * |
478 | * xfs_reserve_blocks is called to set m_resblks | 478 | * xfs_reserve_blocks is called to set m_resblks |
479 | * in the in-core mount table. The number of unused reserved blocks | 479 | * in the in-core mount table. The number of unused reserved blocks |
480 | * is kept in m_resbls_avail. | 480 | * is kept in m_resblks_avail. |
481 | * | 481 | * |
482 | * Reserve the requested number of blocks if available. Otherwise return | 482 | * Reserve the requested number of blocks if available. Otherwise return |
483 | * as many as possible to satisfy the request. The actual number | 483 | * as many as possible to satisfy the request. The actual number |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0024892841a3..4eeb856183b1 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -136,7 +136,7 @@ xfs_ialloc_ag_alloc( | |||
136 | int ninodes; /* num inodes per buf */ | 136 | int ninodes; /* num inodes per buf */ |
137 | xfs_agino_t thisino; /* current inode number, for loop */ | 137 | xfs_agino_t thisino; /* current inode number, for loop */ |
138 | int version; /* inode version number to use */ | 138 | int version; /* inode version number to use */ |
139 | int isaligned; /* inode allocation at stripe unit */ | 139 | int isaligned = 0; /* inode allocation at stripe unit */ |
140 | /* boundary */ | 140 | /* boundary */ |
141 | 141 | ||
142 | args.tp = tp; | 142 | args.tp = tp; |
@@ -152,47 +152,75 @@ xfs_ialloc_ag_alloc( | |||
152 | return XFS_ERROR(ENOSPC); | 152 | return XFS_ERROR(ENOSPC); |
153 | args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp); | 153 | args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp); |
154 | /* | 154 | /* |
155 | * Set the alignment for the allocation. | 155 | * First try to allocate inodes contiguous with the last-allocated |
156 | * If stripe alignment is turned on then align at stripe unit | 156 | * chunk of inodes. If the filesystem is striped, this will fill |
157 | * boundary. | 157 | * an entire stripe unit with inodes. |
158 | * If the cluster size is smaller than a filesystem block | 158 | */ |
159 | * then we're doing I/O for inodes in filesystem block size pieces, | ||
160 | * so don't need alignment anyway. | ||
161 | */ | ||
162 | isaligned = 0; | ||
163 | if (args.mp->m_sinoalign) { | ||
164 | ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN)); | ||
165 | args.alignment = args.mp->m_dalign; | ||
166 | isaligned = 1; | ||
167 | } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) && | ||
168 | args.mp->m_sb.sb_inoalignmt >= | ||
169 | XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp))) | ||
170 | args.alignment = args.mp->m_sb.sb_inoalignmt; | ||
171 | else | ||
172 | args.alignment = 1; | ||
173 | agi = XFS_BUF_TO_AGI(agbp); | 159 | agi = XFS_BUF_TO_AGI(agbp); |
174 | /* | 160 | newino = be32_to_cpu(agi->agi_newino); |
175 | * Need to figure out where to allocate the inode blocks. | 161 | if(likely(newino != NULLAGINO)) { |
176 | * Ideally they should be spaced out through the a.g. | 162 | args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) + |
177 | * For now, just allocate blocks up front. | 163 | XFS_IALLOC_BLOCKS(args.mp); |
178 | */ | 164 | args.fsbno = XFS_AGB_TO_FSB(args.mp, |
179 | args.agbno = be32_to_cpu(agi->agi_root); | 165 | be32_to_cpu(agi->agi_seqno), args.agbno); |
180 | args.fsbno = XFS_AGB_TO_FSB(args.mp, be32_to_cpu(agi->agi_seqno), | 166 | args.type = XFS_ALLOCTYPE_THIS_BNO; |
181 | args.agbno); | 167 | args.mod = args.total = args.wasdel = args.isfl = |
182 | /* | 168 | args.userdata = args.minalignslop = 0; |
183 | * Allocate a fixed-size extent of inodes. | 169 | args.prod = 1; |
184 | */ | 170 | args.alignment = 1; |
185 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 171 | /* |
186 | args.mod = args.total = args.wasdel = args.isfl = args.userdata = | 172 | * Allow space for the inode btree to split. |
187 | args.minalignslop = 0; | 173 | */ |
188 | args.prod = 1; | 174 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; |
189 | /* | 175 | if ((error = xfs_alloc_vextent(&args))) |
190 | * Allow space for the inode btree to split. | 176 | return error; |
191 | */ | 177 | } else |
192 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; | 178 | args.fsbno = NULLFSBLOCK; |
193 | if ((error = xfs_alloc_vextent(&args))) | ||
194 | return error; | ||
195 | 179 | ||
180 | if (unlikely(args.fsbno == NULLFSBLOCK)) { | ||
181 | /* | ||
182 | * Set the alignment for the allocation. | ||
183 | * If stripe alignment is turned on then align at stripe unit | ||
184 | * boundary. | ||
185 | * If the cluster size is smaller than a filesystem block | ||
186 | * then we're doing I/O for inodes in filesystem block size | ||
187 | * pieces, so don't need alignment anyway. | ||
188 | */ | ||
189 | isaligned = 0; | ||
190 | if (args.mp->m_sinoalign) { | ||
191 | ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN)); | ||
192 | args.alignment = args.mp->m_dalign; | ||
193 | isaligned = 1; | ||
194 | } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) && | ||
195 | args.mp->m_sb.sb_inoalignmt >= | ||
196 | XFS_B_TO_FSBT(args.mp, | ||
197 | XFS_INODE_CLUSTER_SIZE(args.mp))) | ||
198 | args.alignment = args.mp->m_sb.sb_inoalignmt; | ||
199 | else | ||
200 | args.alignment = 1; | ||
201 | /* | ||
202 | * Need to figure out where to allocate the inode blocks. | ||
203 | * Ideally they should be spaced out through the a.g. | ||
204 | * For now, just allocate blocks up front. | ||
205 | */ | ||
206 | args.agbno = be32_to_cpu(agi->agi_root); | ||
207 | args.fsbno = XFS_AGB_TO_FSB(args.mp, | ||
208 | be32_to_cpu(agi->agi_seqno), args.agbno); | ||
209 | /* | ||
210 | * Allocate a fixed-size extent of inodes. | ||
211 | */ | ||
212 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
213 | args.mod = args.total = args.wasdel = args.isfl = | ||
214 | args.userdata = args.minalignslop = 0; | ||
215 | args.prod = 1; | ||
216 | /* | ||
217 | * Allow space for the inode btree to split. | ||
218 | */ | ||
219 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; | ||
220 | if ((error = xfs_alloc_vextent(&args))) | ||
221 | return error; | ||
222 | } | ||
223 | |||
196 | /* | 224 | /* |
197 | * If stripe alignment is turned on, then try again with cluster | 225 | * If stripe alignment is turned on, then try again with cluster |
198 | * alignment. | 226 | * alignment. |
@@ -1023,7 +1051,7 @@ xfs_difree( | |||
1023 | rec.ir_freecount++; | 1051 | rec.ir_freecount++; |
1024 | 1052 | ||
1025 | /* | 1053 | /* |
1026 | * When an inode cluster is free, it becomes elgible for removal | 1054 | * When an inode cluster is free, it becomes eligible for removal |
1027 | */ | 1055 | */ |
1028 | if ((mp->m_flags & XFS_MOUNT_IDELETE) && | 1056 | if ((mp->m_flags & XFS_MOUNT_IDELETE) && |
1029 | (rec.ir_freecount == XFS_IALLOC_INODES(mp))) { | 1057 | (rec.ir_freecount == XFS_IALLOC_INODES(mp))) { |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 3ce35a6f700b..bb33113eef9f 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -509,7 +509,7 @@ retry: | |||
509 | } else { | 509 | } else { |
510 | /* | 510 | /* |
511 | * If the inode is not fully constructed due to | 511 | * If the inode is not fully constructed due to |
512 | * filehandle mistmatches wait for the inode to go | 512 | * filehandle mismatches wait for the inode to go |
513 | * away and try again. | 513 | * away and try again. |
514 | * | 514 | * |
515 | * iget_locked will call __wait_on_freeing_inode | 515 | * iget_locked will call __wait_on_freeing_inode |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 88a517fad07b..48146bdc6bdd 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -160,7 +160,7 @@ xfs_inotobp( | |||
160 | xfs_dinode_t *dip; | 160 | xfs_dinode_t *dip; |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * Call the space managment code to find the location of the | 163 | * Call the space management code to find the location of the |
164 | * inode on disk. | 164 | * inode on disk. |
165 | */ | 165 | */ |
166 | imap.im_blkno = 0; | 166 | imap.im_blkno = 0; |
@@ -837,7 +837,7 @@ xfs_dic2xflags( | |||
837 | 837 | ||
838 | /* | 838 | /* |
839 | * Given a mount structure and an inode number, return a pointer | 839 | * Given a mount structure and an inode number, return a pointer |
840 | * to a newly allocated in-core inode coresponding to the given | 840 | * to a newly allocated in-core inode corresponding to the given |
841 | * inode number. | 841 | * inode number. |
842 | * | 842 | * |
843 | * Initialize the inode's attributes and extent pointers if it | 843 | * Initialize the inode's attributes and extent pointers if it |
@@ -2723,7 +2723,7 @@ xfs_ipin( | |||
2723 | /* | 2723 | /* |
2724 | * Decrement the pin count of the given inode, and wake up | 2724 | * Decrement the pin count of the given inode, and wake up |
2725 | * anyone in xfs_iwait_unpin() if the count goes to 0. The | 2725 | * anyone in xfs_iwait_unpin() if the count goes to 0. The |
2726 | * inode must have been previoulsy pinned with a call to xfs_ipin(). | 2726 | * inode must have been previously pinned with a call to xfs_ipin(). |
2727 | */ | 2727 | */ |
2728 | void | 2728 | void |
2729 | xfs_iunpin( | 2729 | xfs_iunpin( |
@@ -3690,7 +3690,7 @@ void | |||
3690 | xfs_iext_add( | 3690 | xfs_iext_add( |
3691 | xfs_ifork_t *ifp, /* inode fork pointer */ | 3691 | xfs_ifork_t *ifp, /* inode fork pointer */ |
3692 | xfs_extnum_t idx, /* index to begin adding exts */ | 3692 | xfs_extnum_t idx, /* index to begin adding exts */ |
3693 | int ext_diff) /* nubmer of extents to add */ | 3693 | int ext_diff) /* number of extents to add */ |
3694 | { | 3694 | { |
3695 | int byte_diff; /* new bytes being added */ | 3695 | int byte_diff; /* new bytes being added */ |
3696 | int new_size; /* size of extents after adding */ | 3696 | int new_size; /* size of extents after adding */ |
@@ -4038,7 +4038,7 @@ xfs_iext_remove_indirect( | |||
4038 | xfs_extnum_t ext_diff; /* extents to remove in current list */ | 4038 | xfs_extnum_t ext_diff; /* extents to remove in current list */ |
4039 | xfs_extnum_t nex1; /* number of extents before idx */ | 4039 | xfs_extnum_t nex1; /* number of extents before idx */ |
4040 | xfs_extnum_t nex2; /* extents after idx + count */ | 4040 | xfs_extnum_t nex2; /* extents after idx + count */ |
4041 | int nlists; /* entries in indirecton array */ | 4041 | int nlists; /* entries in indirection array */ |
4042 | int page_idx = idx; /* index in target extent list */ | 4042 | int page_idx = idx; /* index in target extent list */ |
4043 | 4043 | ||
4044 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | 4044 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); |
@@ -4291,9 +4291,9 @@ xfs_iext_bno_to_ext( | |||
4291 | xfs_filblks_t blockcount = 0; /* number of blocks in extent */ | 4291 | xfs_filblks_t blockcount = 0; /* number of blocks in extent */ |
4292 | xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */ | 4292 | xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */ |
4293 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ | 4293 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ |
4294 | int high; /* upper boundry in search */ | 4294 | int high; /* upper boundary in search */ |
4295 | xfs_extnum_t idx = 0; /* index of target extent */ | 4295 | xfs_extnum_t idx = 0; /* index of target extent */ |
4296 | int low; /* lower boundry in search */ | 4296 | int low; /* lower boundary in search */ |
4297 | xfs_extnum_t nextents; /* number of file extents */ | 4297 | xfs_extnum_t nextents; /* number of file extents */ |
4298 | xfs_fileoff_t startoff = 0; /* start offset of extent */ | 4298 | xfs_fileoff_t startoff = 0; /* start offset of extent */ |
4299 | 4299 | ||
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 36aa1fcb90a5..7497a481b2f5 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -580,7 +580,7 @@ xfs_inode_item_unpin_remove( | |||
580 | * been or is in the process of being flushed, then (ideally) we'd like to | 580 | * been or is in the process of being flushed, then (ideally) we'd like to |
581 | * see if the inode's buffer is still incore, and if so give it a nudge. | 581 | * see if the inode's buffer is still incore, and if so give it a nudge. |
582 | * We delay doing so until the pushbuf routine, though, to avoid holding | 582 | * We delay doing so until the pushbuf routine, though, to avoid holding |
583 | * the AIL lock across a call to the blackhole which is the buffercache. | 583 | * the AIL lock across a call to the blackhole which is the buffer cache. |
584 | * Also we don't want to sleep in any device strategy routines, which can happen | 584 | * Also we don't want to sleep in any device strategy routines, which can happen |
585 | * if we do the subsequent bawrite in here. | 585 | * if we do the subsequent bawrite in here. |
586 | */ | 586 | */ |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 32247b6bfee7..94068d014f27 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -272,7 +272,7 @@ xfs_bulkstat( | |||
272 | size_t statstruct_size, /* sizeof struct filling */ | 272 | size_t statstruct_size, /* sizeof struct filling */ |
273 | char __user *ubuffer, /* buffer with inode stats */ | 273 | char __user *ubuffer, /* buffer with inode stats */ |
274 | int flags, /* defined in xfs_itable.h */ | 274 | int flags, /* defined in xfs_itable.h */ |
275 | int *done) /* 1 if there're more stats to get */ | 275 | int *done) /* 1 if there are more stats to get */ |
276 | { | 276 | { |
277 | xfs_agblock_t agbno=0;/* allocation group block number */ | 277 | xfs_agblock_t agbno=0;/* allocation group block number */ |
278 | xfs_buf_t *agbp; /* agi header buffer */ | 278 | xfs_buf_t *agbp; /* agi header buffer */ |
@@ -676,7 +676,7 @@ xfs_bulkstat_single( | |||
676 | xfs_mount_t *mp, /* mount point for filesystem */ | 676 | xfs_mount_t *mp, /* mount point for filesystem */ |
677 | xfs_ino_t *lastinop, /* inode to return */ | 677 | xfs_ino_t *lastinop, /* inode to return */ |
678 | char __user *buffer, /* buffer with inode stats */ | 678 | char __user *buffer, /* buffer with inode stats */ |
679 | int *done) /* 1 if there're more stats to get */ | 679 | int *done) /* 1 if there are more stats to get */ |
680 | { | 680 | { |
681 | int count; /* count value for bulkstat call */ | 681 | int count; /* count value for bulkstat call */ |
682 | int error; /* return value */ | 682 | int error; /* return value */ |
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 047d834ed210..11eb4e1b18c4 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h | |||
@@ -60,7 +60,7 @@ xfs_bulkstat( | |||
60 | size_t statstruct_size,/* sizeof struct that we're filling */ | 60 | size_t statstruct_size,/* sizeof struct that we're filling */ |
61 | char __user *ubuffer,/* buffer with inode stats */ | 61 | char __user *ubuffer,/* buffer with inode stats */ |
62 | int flags, /* flag to control access method */ | 62 | int flags, /* flag to control access method */ |
63 | int *done); /* 1 if there're more stats to get */ | 63 | int *done); /* 1 if there are more stats to get */ |
64 | 64 | ||
65 | int | 65 | int |
66 | xfs_bulkstat_single( | 66 | xfs_bulkstat_single( |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 9176995160ed..32e841d2f26d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -59,7 +59,7 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | |||
59 | int num_bblks); | 59 | int num_bblks); |
60 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); | 60 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); |
61 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); | 61 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); |
62 | STATIC void xlog_unalloc_log(xlog_t *log); | 62 | STATIC void xlog_dealloc_log(xlog_t *log); |
63 | STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], | 63 | STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], |
64 | int nentries, xfs_log_ticket_t tic, | 64 | int nentries, xfs_log_ticket_t tic, |
65 | xfs_lsn_t *start_lsn, | 65 | xfs_lsn_t *start_lsn, |
@@ -304,7 +304,7 @@ xfs_log_done(xfs_mount_t *mp, | |||
304 | if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 || | 304 | if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 || |
305 | (flags & XFS_LOG_REL_PERM_RESERV)) { | 305 | (flags & XFS_LOG_REL_PERM_RESERV)) { |
306 | /* | 306 | /* |
307 | * Release ticket if not permanent reservation or a specifc | 307 | * Release ticket if not permanent reservation or a specific |
308 | * request has been made to release a permanent reservation. | 308 | * request has been made to release a permanent reservation. |
309 | */ | 309 | */ |
310 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)"); | 310 | xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)"); |
@@ -511,7 +511,7 @@ xfs_log_mount(xfs_mount_t *mp, | |||
511 | vfsp->vfs_flag |= VFS_RDONLY; | 511 | vfsp->vfs_flag |= VFS_RDONLY; |
512 | if (error) { | 512 | if (error) { |
513 | cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); | 513 | cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); |
514 | xlog_unalloc_log(mp->m_log); | 514 | xlog_dealloc_log(mp->m_log); |
515 | return error; | 515 | return error; |
516 | } | 516 | } |
517 | } | 517 | } |
@@ -667,7 +667,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
667 | * | 667 | * |
668 | * Go through the motions of sync'ing and releasing | 668 | * Go through the motions of sync'ing and releasing |
669 | * the iclog, even though no I/O will actually happen, | 669 | * the iclog, even though no I/O will actually happen, |
670 | * we need to wait for other log I/O's that may already | 670 | * we need to wait for other log I/Os that may already |
671 | * be in progress. Do this as a separate section of | 671 | * be in progress. Do this as a separate section of |
672 | * code so we'll know if we ever get stuck here that | 672 | * code so we'll know if we ever get stuck here that |
673 | * we're in this odd situation of trying to unmount | 673 | * we're in this odd situation of trying to unmount |
@@ -704,7 +704,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
704 | void | 704 | void |
705 | xfs_log_unmount_dealloc(xfs_mount_t *mp) | 705 | xfs_log_unmount_dealloc(xfs_mount_t *mp) |
706 | { | 706 | { |
707 | xlog_unalloc_log(mp->m_log); | 707 | xlog_dealloc_log(mp->m_log); |
708 | } | 708 | } |
709 | 709 | ||
710 | /* | 710 | /* |
@@ -1492,7 +1492,7 @@ xlog_sync(xlog_t *log, | |||
1492 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1492 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
1493 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); | 1493 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); |
1494 | 1494 | ||
1495 | /* account for internal log which does't start at block #0 */ | 1495 | /* account for internal log which doesn't start at block #0 */ |
1496 | XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart); | 1496 | XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart); |
1497 | XFS_BUF_WRITE(bp); | 1497 | XFS_BUF_WRITE(bp); |
1498 | if ((error = XFS_bwrite(bp))) { | 1498 | if ((error = XFS_bwrite(bp))) { |
@@ -1506,10 +1506,10 @@ xlog_sync(xlog_t *log, | |||
1506 | 1506 | ||
1507 | 1507 | ||
1508 | /* | 1508 | /* |
1509 | * Unallocate a log structure | 1509 | * Deallocate a log structure |
1510 | */ | 1510 | */ |
1511 | void | 1511 | void |
1512 | xlog_unalloc_log(xlog_t *log) | 1512 | xlog_dealloc_log(xlog_t *log) |
1513 | { | 1513 | { |
1514 | xlog_in_core_t *iclog, *next_iclog; | 1514 | xlog_in_core_t *iclog, *next_iclog; |
1515 | xlog_ticket_t *tic, *next_tic; | 1515 | xlog_ticket_t *tic, *next_tic; |
@@ -1539,7 +1539,7 @@ xlog_unalloc_log(xlog_t *log) | |||
1539 | if ((log->l_ticket_cnt != log->l_ticket_tcnt) && | 1539 | if ((log->l_ticket_cnt != log->l_ticket_tcnt) && |
1540 | !XLOG_FORCED_SHUTDOWN(log)) { | 1540 | !XLOG_FORCED_SHUTDOWN(log)) { |
1541 | xfs_fs_cmn_err(CE_WARN, log->l_mp, | 1541 | xfs_fs_cmn_err(CE_WARN, log->l_mp, |
1542 | "xlog_unalloc_log: (cnt: %d, total: %d)", | 1542 | "xlog_dealloc_log: (cnt: %d, total: %d)", |
1543 | log->l_ticket_cnt, log->l_ticket_tcnt); | 1543 | log->l_ticket_cnt, log->l_ticket_tcnt); |
1544 | /* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */ | 1544 | /* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */ |
1545 | 1545 | ||
@@ -1562,7 +1562,7 @@ xlog_unalloc_log(xlog_t *log) | |||
1562 | #endif | 1562 | #endif |
1563 | log->l_mp->m_log = NULL; | 1563 | log->l_mp->m_log = NULL; |
1564 | kmem_free(log, sizeof(xlog_t)); | 1564 | kmem_free(log, sizeof(xlog_t)); |
1565 | } /* xlog_unalloc_log */ | 1565 | } /* xlog_dealloc_log */ |
1566 | 1566 | ||
1567 | /* | 1567 | /* |
1568 | * Update counters atomically now that memcpy is done. | 1568 | * Update counters atomically now that memcpy is done. |
@@ -2829,7 +2829,7 @@ xlog_state_release_iclog(xlog_t *log, | |||
2829 | 2829 | ||
2830 | /* | 2830 | /* |
2831 | * We let the log lock go, so it's possible that we hit a log I/O | 2831 | * We let the log lock go, so it's possible that we hit a log I/O |
2832 | * error or someother SHUTDOWN condition that marks the iclog | 2832 | * error or some other SHUTDOWN condition that marks the iclog |
2833 | * as XLOG_STATE_IOERROR before the bwrite. However, we know that | 2833 | * as XLOG_STATE_IOERROR before the bwrite. However, we know that |
2834 | * this iclog has consistent data, so we ignore IOERROR | 2834 | * this iclog has consistent data, so we ignore IOERROR |
2835 | * flags after this point. | 2835 | * flags after this point. |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 4b2ac88dbb83..eacb3d4987f2 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #ifdef __KERNEL__ | 28 | #ifdef __KERNEL__ |
29 | /* | 29 | /* |
30 | * By comparing each compnent, we don't have to worry about extra | 30 | * By comparing each component, we don't have to worry about extra |
31 | * endian issues in treating two 32 bit numbers as one 64 bit number | 31 | * endian issues in treating two 32 bit numbers as one 64 bit number |
32 | */ | 32 | */ |
33 | static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) | 33 | static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index add13f507ed2..1f0016b0b4ec 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -583,7 +583,7 @@ xlog_find_head( | |||
583 | * x | x ... | x - 1 | x | 583 | * x | x ... | x - 1 | x |
584 | * Another case that fits this picture would be | 584 | * Another case that fits this picture would be |
585 | * x | x + 1 | x ... | x | 585 | * x | x + 1 | x ... | x |
586 | * In this case the head really is somwhere at the end of the | 586 | * In this case the head really is somewhere at the end of the |
587 | * log, as one of the latest writes at the beginning was | 587 | * log, as one of the latest writes at the beginning was |
588 | * incomplete. | 588 | * incomplete. |
589 | * One more case is | 589 | * One more case is |
@@ -2799,7 +2799,7 @@ xlog_recover_do_trans( | |||
2799 | * we don't need to worry about the block number being | 2799 | * we don't need to worry about the block number being |
2800 | * truncated in > 1 TB buffers because in user-land, | 2800 | * truncated in > 1 TB buffers because in user-land, |
2801 | * we're now n32 or 64-bit so xfs_daddr_t is 64-bits so | 2801 | * we're now n32 or 64-bit so xfs_daddr_t is 64-bits so |
2802 | * the blkno's will get through the user-mode buffer | 2802 | * the blknos will get through the user-mode buffer |
2803 | * cache properly. The only bad case is o32 kernels | 2803 | * cache properly. The only bad case is o32 kernels |
2804 | * where xfs_daddr_t is 32-bits but mount will warn us | 2804 | * where xfs_daddr_t is 32-bits but mount will warn us |
2805 | * off a > 1 TB filesystem before we get here. | 2805 | * off a > 1 TB filesystem before we get here. |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 20e8abc16d18..72e7e78bfff8 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -393,7 +393,7 @@ xfs_initialize_perag( | |||
393 | break; | 393 | break; |
394 | } | 394 | } |
395 | 395 | ||
396 | /* This ag is prefered for inodes */ | 396 | /* This ag is preferred for inodes */ |
397 | pag = &mp->m_perag[index]; | 397 | pag = &mp->m_perag[index]; |
398 | pag->pagi_inodeok = 1; | 398 | pag->pagi_inodeok = 1; |
399 | if (index < max_metadata) | 399 | if (index < max_metadata) |
@@ -1728,7 +1728,7 @@ xfs_mount_log_sbunit( | |||
1728 | * We cannot use the hotcpu_register() function because it does | 1728 | * We cannot use the hotcpu_register() function because it does |
1729 | * not allow notifier instances. We need a notifier per filesystem | 1729 | * not allow notifier instances. We need a notifier per filesystem |
1730 | * as we need to be able to identify the filesystem to balance | 1730 | * as we need to be able to identify the filesystem to balance |
1731 | * the counters out. This is acheived by having a notifier block | 1731 | * the counters out. This is achieved by having a notifier block |
1732 | * embedded in the xfs_mount_t and doing pointer magic to get the | 1732 | * embedded in the xfs_mount_t and doing pointer magic to get the |
1733 | * mount pointer from the notifier block address. | 1733 | * mount pointer from the notifier block address. |
1734 | */ | 1734 | */ |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index ebd73960e9db..66cbee79864e 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -379,7 +379,7 @@ typedef struct xfs_mount { | |||
379 | #endif | 379 | #endif |
380 | int m_dalign; /* stripe unit */ | 380 | int m_dalign; /* stripe unit */ |
381 | int m_swidth; /* stripe width */ | 381 | int m_swidth; /* stripe width */ |
382 | int m_sinoalign; /* stripe unit inode alignmnt */ | 382 | int m_sinoalign; /* stripe unit inode alignment */ |
383 | int m_attr_magicpct;/* 37% of the blocksize */ | 383 | int m_attr_magicpct;/* 37% of the blocksize */ |
384 | int m_dir_magicpct; /* 37% of the dir blocksize */ | 384 | int m_dir_magicpct; /* 37% of the dir blocksize */ |
385 | __uint8_t m_mk_sharedro; /* mark shared ro on unmount */ | 385 | __uint8_t m_mk_sharedro; /* mark shared ro on unmount */ |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 82a08baf437b..4f6a034de7f7 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -31,7 +31,7 @@ | |||
31 | typedef __uint32_t xfs_dqid_t; | 31 | typedef __uint32_t xfs_dqid_t; |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Eventhough users may not have quota limits occupying all 64-bits, | 34 | * Even though users may not have quota limits occupying all 64-bits, |
35 | * they may need 64-bit accounting. Hence, 64-bit quota-counters, | 35 | * they may need 64-bit accounting. Hence, 64-bit quota-counters, |
36 | * and quota-limits. This is a waste in the common case, but hey ... | 36 | * and quota-limits. This is a waste in the common case, but hey ... |
37 | */ | 37 | */ |
@@ -246,7 +246,7 @@ typedef struct xfs_qoff_logformat { | |||
246 | #ifdef __KERNEL__ | 246 | #ifdef __KERNEL__ |
247 | /* | 247 | /* |
248 | * This check is done typically without holding the inode lock; | 248 | * This check is done typically without holding the inode lock; |
249 | * that may seem racey, but it is harmless in the context that it is used. | 249 | * that may seem racy, but it is harmless in the context that it is used. |
250 | * The inode cannot go inactive as long a reference is kept, and | 250 | * The inode cannot go inactive as long a reference is kept, and |
251 | * therefore if dquot(s) were attached, they'll stay consistent. | 251 | * therefore if dquot(s) were attached, they'll stay consistent. |
252 | * If, for example, the ownership of the inode changes while | 252 | * If, for example, the ownership of the inode changes while |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 2918956553a5..8d056cef5d1f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -490,7 +490,7 @@ xfs_trans_mod_sb( | |||
490 | case XFS_TRANS_SB_RES_FREXTENTS: | 490 | case XFS_TRANS_SB_RES_FREXTENTS: |
491 | /* | 491 | /* |
492 | * The allocation has already been applied to the | 492 | * The allocation has already been applied to the |
493 | * in-core superblocks's counter. This should only | 493 | * in-core superblock's counter. This should only |
494 | * be applied to the on-disk superblock. | 494 | * be applied to the on-disk superblock. |
495 | */ | 495 | */ |
496 | ASSERT(delta < 0); | 496 | ASSERT(delta < 0); |
@@ -611,7 +611,7 @@ xfs_trans_apply_sb_deltas( | |||
611 | 611 | ||
612 | if (whole) | 612 | if (whole) |
613 | /* | 613 | /* |
614 | * Log the whole thing, the fields are discontiguous. | 614 | * Log the whole thing, the fields are noncontiguous. |
615 | */ | 615 | */ |
616 | xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1); | 616 | xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1); |
617 | else | 617 | else |
@@ -669,7 +669,7 @@ xfs_trans_unreserve_and_mod_sb( | |||
669 | /* | 669 | /* |
670 | * Apply any superblock modifications to the in-core version. | 670 | * Apply any superblock modifications to the in-core version. |
671 | * The t_res_fdblocks_delta and t_res_frextents_delta fields are | 671 | * The t_res_fdblocks_delta and t_res_frextents_delta fields are |
672 | * explicity NOT applied to the in-core superblock. | 672 | * explicitly NOT applied to the in-core superblock. |
673 | * The idea is that that has already been done. | 673 | * The idea is that that has already been done. |
674 | */ | 674 | */ |
675 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { | 675 | if (tp->t_flags & XFS_TRANS_SB_DIRTY) { |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index e48befa4e337..100d9a4b38ee 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -354,7 +354,7 @@ typedef struct xfs_trans { | |||
354 | xfs_lsn_t t_commit_lsn; /* log seq num of end of | 354 | xfs_lsn_t t_commit_lsn; /* log seq num of end of |
355 | * transaction. */ | 355 | * transaction. */ |
356 | struct xfs_mount *t_mountp; /* ptr to fs mount struct */ | 356 | struct xfs_mount *t_mountp; /* ptr to fs mount struct */ |
357 | struct xfs_dquot_acct *t_dqinfo; /* accting info for dquots */ | 357 | struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */ |
358 | xfs_trans_callback_t t_callback; /* transaction callback */ | 358 | xfs_trans_callback_t t_callback; /* transaction callback */ |
359 | void *t_callarg; /* callback arg */ | 359 | void *t_callarg; /* callback arg */ |
360 | unsigned int t_flags; /* misc flags */ | 360 | unsigned int t_flags; /* misc flags */ |
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index e341409172d2..7c5894d59f81 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c | |||
@@ -272,7 +272,7 @@ xfs_trans_log_inode( | |||
272 | * This is to coordinate with the xfs_iflush() and xfs_iflush_done() | 272 | * This is to coordinate with the xfs_iflush() and xfs_iflush_done() |
273 | * routines in the eventual clearing of the ilf_fields bits. | 273 | * routines in the eventual clearing of the ilf_fields bits. |
274 | * See the big comment in xfs_iflush() for an explanation of | 274 | * See the big comment in xfs_iflush() for an explanation of |
275 | * this coorination mechanism. | 275 | * this coordination mechanism. |
276 | */ | 276 | */ |
277 | flags |= ip->i_itemp->ili_last_fields; | 277 | flags |= ip->i_itemp->ili_last_fields; |
278 | ip->i_itemp->ili_format.ilf_fields |= flags; | 278 | ip->i_itemp->ili_format.ilf_fields |= flags; |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index d4ec4dfaf19c..504d2a80747a 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -880,10 +880,10 @@ xfs_statvfs( | |||
880 | * determine if they should be flushed sync, async, or | 880 | * determine if they should be flushed sync, async, or |
881 | * delwri. | 881 | * delwri. |
882 | * SYNC_CLOSE - This flag is passed when the system is being | 882 | * SYNC_CLOSE - This flag is passed when the system is being |
883 | * unmounted. We should sync and invalidate everthing. | 883 | * unmounted. We should sync and invalidate everything. |
884 | * SYNC_FSDATA - This indicates that the caller would like to make | 884 | * SYNC_FSDATA - This indicates that the caller would like to make |
885 | * sure the superblock is safe on disk. We can ensure | 885 | * sure the superblock is safe on disk. We can ensure |
886 | * this by simply makeing sure the log gets flushed | 886 | * this by simply making sure the log gets flushed |
887 | * if SYNC_BDFLUSH is set, and by actually writing it | 887 | * if SYNC_BDFLUSH is set, and by actually writing it |
888 | * out otherwise. | 888 | * out otherwise. |
889 | * | 889 | * |
@@ -908,7 +908,7 @@ xfs_sync( | |||
908 | * | 908 | * |
909 | * This routine supports all of the flags defined for the generic VFS_SYNC | 909 | * This routine supports all of the flags defined for the generic VFS_SYNC |
910 | * interface as explained above under xfs_sync. In the interests of not | 910 | * interface as explained above under xfs_sync. In the interests of not |
911 | * changing interfaces within the 6.5 family, additional internallly- | 911 | * changing interfaces within the 6.5 family, additional internally- |
912 | * required functions are specified within a separate xflags parameter, | 912 | * required functions are specified within a separate xflags parameter, |
913 | * only available by calling this routine. | 913 | * only available by calling this routine. |
914 | * | 914 | * |
@@ -1090,7 +1090,7 @@ xfs_sync_inodes( | |||
1090 | * If this is just vfs_sync() or pflushd() calling | 1090 | * If this is just vfs_sync() or pflushd() calling |
1091 | * then we can skip inodes for which it looks like | 1091 | * then we can skip inodes for which it looks like |
1092 | * there is nothing to do. Since we don't have the | 1092 | * there is nothing to do. Since we don't have the |
1093 | * inode locked this is racey, but these are periodic | 1093 | * inode locked this is racy, but these are periodic |
1094 | * calls so it doesn't matter. For the others we want | 1094 | * calls so it doesn't matter. For the others we want |
1095 | * to know for sure, so we at least try to lock them. | 1095 | * to know for sure, so we at least try to lock them. |
1096 | */ | 1096 | */ |
@@ -1429,7 +1429,7 @@ xfs_sync_inodes( | |||
1429 | * | 1429 | * |
1430 | * This routine supports all of the flags defined for the generic VFS_SYNC | 1430 | * This routine supports all of the flags defined for the generic VFS_SYNC |
1431 | * interface as explained above under xfs_sync. In the interests of not | 1431 | * interface as explained above under xfs_sync. In the interests of not |
1432 | * changing interfaces within the 6.5 family, additional internallly- | 1432 | * changing interfaces within the 6.5 family, additional internally- |
1433 | * required functions are specified within a separate xflags parameter, | 1433 | * required functions are specified within a separate xflags parameter, |
1434 | * only available by calling this routine. | 1434 | * only available by calling this routine. |
1435 | * | 1435 | * |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 0f0a64e81db9..de49601919c1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -848,7 +848,7 @@ xfs_setattr( | |||
848 | * If this is a synchronous mount, make sure that the | 848 | * If this is a synchronous mount, make sure that the |
849 | * transaction goes to disk before returning to the user. | 849 | * transaction goes to disk before returning to the user. |
850 | * This is slightly sub-optimal in that truncates require | 850 | * This is slightly sub-optimal in that truncates require |
851 | * two sync transactions instead of one for wsync filesytems. | 851 | * two sync transactions instead of one for wsync filesystems. |
852 | * One for the truncate and one for the timestamps since we | 852 | * One for the truncate and one for the timestamps since we |
853 | * don't want to change the timestamps unless we're sure the | 853 | * don't want to change the timestamps unless we're sure the |
854 | * truncate worked. Truncates are less than 1% of the laddis | 854 | * truncate worked. Truncates are less than 1% of the laddis |
@@ -1170,7 +1170,7 @@ xfs_fsync( | |||
1170 | 1170 | ||
1171 | /* | 1171 | /* |
1172 | * If this inode is on the RT dev we need to flush that | 1172 | * If this inode is on the RT dev we need to flush that |
1173 | * cache aswell. | 1173 | * cache as well. |
1174 | */ | 1174 | */ |
1175 | if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) | 1175 | if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) |
1176 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | 1176 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); |
@@ -1380,7 +1380,7 @@ xfs_inactive_symlink_rmt( | |||
1380 | */ | 1380 | */ |
1381 | ntp = xfs_trans_dup(tp); | 1381 | ntp = xfs_trans_dup(tp); |
1382 | /* | 1382 | /* |
1383 | * Commit the transaction containing extent freeing and EFD's. | 1383 | * Commit the transaction containing extent freeing and EFDs. |
1384 | * If we get an error on the commit here or on the reserve below, | 1384 | * If we get an error on the commit here or on the reserve below, |
1385 | * we need to unlock the inode since the new transaction doesn't | 1385 | * we need to unlock the inode since the new transaction doesn't |
1386 | * have the inode attached. | 1386 | * have the inode attached. |
@@ -2023,7 +2023,7 @@ xfs_create( | |||
2023 | XFS_QM_DQRELE(mp, gdqp); | 2023 | XFS_QM_DQRELE(mp, gdqp); |
2024 | 2024 | ||
2025 | /* | 2025 | /* |
2026 | * Propogate the fact that the vnode changed after the | 2026 | * Propagate the fact that the vnode changed after the |
2027 | * xfs_inode locks have been released. | 2027 | * xfs_inode locks have been released. |
2028 | */ | 2028 | */ |
2029 | VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3); | 2029 | VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3); |
@@ -2370,7 +2370,7 @@ xfs_remove( | |||
2370 | * for a log reservation. Since we'll have to wait for the | 2370 | * for a log reservation. Since we'll have to wait for the |
2371 | * inactive code to complete before returning from xfs_iget, | 2371 | * inactive code to complete before returning from xfs_iget, |
2372 | * we need to make sure that we don't have log space reserved | 2372 | * we need to make sure that we don't have log space reserved |
2373 | * when we call xfs_iget. Instead we get an unlocked referece | 2373 | * when we call xfs_iget. Instead we get an unlocked reference |
2374 | * to the inode before getting our log reservation. | 2374 | * to the inode before getting our log reservation. |
2375 | */ | 2375 | */ |
2376 | error = xfs_get_dir_entry(dentry, &ip); | 2376 | error = xfs_get_dir_entry(dentry, &ip); |
@@ -3020,7 +3020,7 @@ xfs_rmdir( | |||
3020 | * for a log reservation. Since we'll have to wait for the | 3020 | * for a log reservation. Since we'll have to wait for the |
3021 | * inactive code to complete before returning from xfs_iget, | 3021 | * inactive code to complete before returning from xfs_iget, |
3022 | * we need to make sure that we don't have log space reserved | 3022 | * we need to make sure that we don't have log space reserved |
3023 | * when we call xfs_iget. Instead we get an unlocked referece | 3023 | * when we call xfs_iget. Instead we get an unlocked reference |
3024 | * to the inode before getting our log reservation. | 3024 | * to the inode before getting our log reservation. |
3025 | */ | 3025 | */ |
3026 | error = xfs_get_dir_entry(dentry, &cdp); | 3026 | error = xfs_get_dir_entry(dentry, &cdp); |