diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/vfs_super.c | 7 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 23 | ||||
-rw-r--r-- | fs/binfmt_misc.c | 18 | ||||
-rw-r--r-- | fs/binfmt_som.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 29 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
-rw-r--r-- | fs/exec.c | 28 | ||||
-rw-r--r-- | fs/fcntl.c | 40 | ||||
-rw-r--r-- | fs/fuse/inode.c | 5 | ||||
-rw-r--r-- | fs/locks.c | 1 | ||||
-rw-r--r-- | fs/namespace.c | 9 | ||||
-rw-r--r-- | fs/nfs/super.c | 8 | ||||
-rw-r--r-- | fs/sysfs/file.c | 14 | ||||
-rw-r--r-- | fs/sysfs/group.c | 83 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 2 |
16 files changed, 149 insertions, 146 deletions
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 678c02f1ae23..a452ac67fc94 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -224,12 +224,11 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | static void | 226 | static void |
227 | v9fs_umount_begin(struct vfsmount *vfsmnt, int flags) | 227 | v9fs_umount_begin(struct super_block *sb) |
228 | { | 228 | { |
229 | struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info; | 229 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
230 | 230 | ||
231 | if (flags & MNT_FORCE) | 231 | v9fs_session_cancel(v9ses); |
232 | v9fs_session_cancel(v9ses); | ||
233 | } | 232 | } |
234 | 233 | ||
235 | static const struct super_operations v9fs_super_ops = { | 234 | static const struct super_operations v9fs_super_ops = { |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 5e1a4fb5cacb..9924581df6f6 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -543,7 +543,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
543 | unsigned long interp_load_addr = 0; | 543 | unsigned long interp_load_addr = 0; |
544 | unsigned long start_code, end_code, start_data, end_data; | 544 | unsigned long start_code, end_code, start_data, end_data; |
545 | unsigned long reloc_func_desc = 0; | 545 | unsigned long reloc_func_desc = 0; |
546 | struct files_struct *files; | ||
547 | int executable_stack = EXSTACK_DEFAULT; | 546 | int executable_stack = EXSTACK_DEFAULT; |
548 | unsigned long def_flags = 0; | 547 | unsigned long def_flags = 0; |
549 | struct { | 548 | struct { |
@@ -593,20 +592,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
593 | goto out_free_ph; | 592 | goto out_free_ph; |
594 | } | 593 | } |
595 | 594 | ||
596 | files = current->files; /* Refcounted so ok */ | ||
597 | retval = unshare_files(); | ||
598 | if (retval < 0) | ||
599 | goto out_free_ph; | ||
600 | if (files == current->files) { | ||
601 | put_files_struct(files); | ||
602 | files = NULL; | ||
603 | } | ||
604 | |||
605 | /* exec will make our files private anyway, but for the a.out | ||
606 | loader stuff we need to do it earlier */ | ||
607 | retval = get_unused_fd(); | 595 | retval = get_unused_fd(); |
608 | if (retval < 0) | 596 | if (retval < 0) |
609 | goto out_free_fh; | 597 | goto out_free_ph; |
610 | get_file(bprm->file); | 598 | get_file(bprm->file); |
611 | fd_install(elf_exec_fileno = retval, bprm->file); | 599 | fd_install(elf_exec_fileno = retval, bprm->file); |
612 | 600 | ||
@@ -728,12 +716,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
728 | if (retval) | 716 | if (retval) |
729 | goto out_free_dentry; | 717 | goto out_free_dentry; |
730 | 718 | ||
731 | /* Discard our unneeded old files struct */ | ||
732 | if (files) { | ||
733 | put_files_struct(files); | ||
734 | files = NULL; | ||
735 | } | ||
736 | |||
737 | /* OK, This is the point of no return */ | 719 | /* OK, This is the point of no return */ |
738 | current->flags &= ~PF_FORKNOEXEC; | 720 | current->flags &= ~PF_FORKNOEXEC; |
739 | current->mm->def_flags = def_flags; | 721 | current->mm->def_flags = def_flags; |
@@ -1016,9 +998,6 @@ out_free_interp: | |||
1016 | kfree(elf_interpreter); | 998 | kfree(elf_interpreter); |
1017 | out_free_file: | 999 | out_free_file: |
1018 | sys_close(elf_exec_fileno); | 1000 | sys_close(elf_exec_fileno); |
1019 | out_free_fh: | ||
1020 | if (files) | ||
1021 | reset_files_struct(current, files); | ||
1022 | out_free_ph: | 1001 | out_free_ph: |
1023 | kfree(elf_phdata); | 1002 | kfree(elf_phdata); |
1024 | goto out; | 1003 | goto out; |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index b53c7e5f41bb..dbf0ac0523de 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -110,7 +110,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
110 | char *iname_addr = iname; | 110 | char *iname_addr = iname; |
111 | int retval; | 111 | int retval; |
112 | int fd_binary = -1; | 112 | int fd_binary = -1; |
113 | struct files_struct *files = NULL; | ||
114 | 113 | ||
115 | retval = -ENOEXEC; | 114 | retval = -ENOEXEC; |
116 | if (!enabled) | 115 | if (!enabled) |
@@ -133,21 +132,13 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
133 | 132 | ||
134 | if (fmt->flags & MISC_FMT_OPEN_BINARY) { | 133 | if (fmt->flags & MISC_FMT_OPEN_BINARY) { |
135 | 134 | ||
136 | files = current->files; | ||
137 | retval = unshare_files(); | ||
138 | if (retval < 0) | ||
139 | goto _ret; | ||
140 | if (files == current->files) { | ||
141 | put_files_struct(files); | ||
142 | files = NULL; | ||
143 | } | ||
144 | /* if the binary should be opened on behalf of the | 135 | /* if the binary should be opened on behalf of the |
145 | * interpreter than keep it open and assign descriptor | 136 | * interpreter than keep it open and assign descriptor |
146 | * to it */ | 137 | * to it */ |
147 | fd_binary = get_unused_fd(); | 138 | fd_binary = get_unused_fd(); |
148 | if (fd_binary < 0) { | 139 | if (fd_binary < 0) { |
149 | retval = fd_binary; | 140 | retval = fd_binary; |
150 | goto _unshare; | 141 | goto _ret; |
151 | } | 142 | } |
152 | fd_install(fd_binary, bprm->file); | 143 | fd_install(fd_binary, bprm->file); |
153 | 144 | ||
@@ -205,10 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
205 | if (retval < 0) | 196 | if (retval < 0) |
206 | goto _error; | 197 | goto _error; |
207 | 198 | ||
208 | if (files) { | ||
209 | put_files_struct(files); | ||
210 | files = NULL; | ||
211 | } | ||
212 | _ret: | 199 | _ret: |
213 | return retval; | 200 | return retval; |
214 | _error: | 201 | _error: |
@@ -216,9 +203,6 @@ _error: | |||
216 | sys_close(fd_binary); | 203 | sys_close(fd_binary); |
217 | bprm->interp_flags = 0; | 204 | bprm->interp_flags = 0; |
218 | bprm->interp_data = 0; | 205 | bprm->interp_data = 0; |
219 | _unshare: | ||
220 | if (files) | ||
221 | reset_files_struct(current, files); | ||
222 | goto _ret; | 206 | goto _ret; |
223 | } | 207 | } |
224 | 208 | ||
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index 14c63527c762..fdc36bfd6a7b 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c | |||
@@ -194,7 +194,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
194 | unsigned long som_entry; | 194 | unsigned long som_entry; |
195 | struct som_hdr *som_ex; | 195 | struct som_hdr *som_ex; |
196 | struct som_exec_auxhdr *hpuxhdr; | 196 | struct som_exec_auxhdr *hpuxhdr; |
197 | struct files_struct *files; | ||
198 | 197 | ||
199 | /* Get the exec-header */ | 198 | /* Get the exec-header */ |
200 | som_ex = (struct som_hdr *) bprm->buf; | 199 | som_ex = (struct som_hdr *) bprm->buf; |
@@ -221,15 +220,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
221 | goto out_free; | 220 | goto out_free; |
222 | } | 221 | } |
223 | 222 | ||
224 | files = current->files; /* Refcounted so ok */ | ||
225 | retval = unshare_files(); | ||
226 | if (retval < 0) | ||
227 | goto out_free; | ||
228 | if (files == current->files) { | ||
229 | put_files_struct(files); | ||
230 | files = NULL; | ||
231 | } | ||
232 | |||
233 | retval = get_unused_fd(); | 223 | retval = get_unused_fd(); |
234 | if (retval < 0) | 224 | if (retval < 0) |
235 | goto out_free; | 225 | goto out_free; |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f53f41ff1665..95024c066d89 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -25,14 +25,26 @@ | |||
25 | 25 | ||
26 | static LIST_HEAD(cifs_dfs_automount_list); | 26 | static LIST_HEAD(cifs_dfs_automount_list); |
27 | 27 | ||
28 | /* | 28 | static void cifs_dfs_expire_automounts(struct work_struct *work); |
29 | * DFS functions | 29 | static DECLARE_DELAYED_WORK(cifs_dfs_automount_task, |
30 | */ | 30 | cifs_dfs_expire_automounts); |
31 | static int cifs_dfs_mountpoint_expiry_timeout = 500 * HZ; | ||
32 | |||
33 | static void cifs_dfs_expire_automounts(struct work_struct *work) | ||
34 | { | ||
35 | struct list_head *list = &cifs_dfs_automount_list; | ||
36 | |||
37 | mark_mounts_for_expiry(list); | ||
38 | if (!list_empty(list)) | ||
39 | schedule_delayed_work(&cifs_dfs_automount_task, | ||
40 | cifs_dfs_mountpoint_expiry_timeout); | ||
41 | } | ||
31 | 42 | ||
32 | void dfs_shrink_umount_helper(struct vfsmount *vfsmnt) | 43 | void cifs_dfs_release_automount_timer(void) |
33 | { | 44 | { |
34 | mark_mounts_for_expiry(&cifs_dfs_automount_list); | 45 | BUG_ON(!list_empty(&cifs_dfs_automount_list)); |
35 | mark_mounts_for_expiry(&cifs_dfs_automount_list); | 46 | cancel_delayed_work(&cifs_dfs_automount_task); |
47 | flush_scheduled_work(); | ||
36 | } | 48 | } |
37 | 49 | ||
38 | /** | 50 | /** |
@@ -261,10 +273,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, | |||
261 | err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist); | 273 | err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist); |
262 | switch (err) { | 274 | switch (err) { |
263 | case 0: | 275 | case 0: |
264 | dput(nd->path.dentry); | 276 | path_put(&nd->path); |
265 | mntput(nd->path.mnt); | ||
266 | nd->path.mnt = newmnt; | 277 | nd->path.mnt = newmnt; |
267 | nd->path.dentry = dget(newmnt->mnt_root); | 278 | nd->path.dentry = dget(newmnt->mnt_root); |
279 | schedule_delayed_work(&cifs_dfs_automount_task, | ||
280 | cifs_dfs_mountpoint_expiry_timeout); | ||
268 | break; | 281 | break; |
269 | case -EBUSY: | 282 | case -EBUSY: |
270 | /* someone else made a mount here whilst we were busy */ | 283 | /* someone else made a mount here whilst we were busy */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a04b17e5a9d0..39c2cbdface7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -466,16 +466,11 @@ static struct quotactl_ops cifs_quotactl_ops = { | |||
466 | }; | 466 | }; |
467 | #endif | 467 | #endif |
468 | 468 | ||
469 | static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags) | 469 | static void cifs_umount_begin(struct super_block *sb) |
470 | { | 470 | { |
471 | struct cifs_sb_info *cifs_sb; | 471 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
472 | struct cifsTconInfo *tcon; | 472 | struct cifsTconInfo *tcon; |
473 | 473 | ||
474 | dfs_shrink_umount_helper(vfsmnt); | ||
475 | |||
476 | if (!(flags & MNT_FORCE)) | ||
477 | return; | ||
478 | cifs_sb = CIFS_SB(vfsmnt->mnt_sb); | ||
479 | if (cifs_sb == NULL) | 474 | if (cifs_sb == NULL) |
480 | return; | 475 | return; |
481 | 476 | ||
@@ -1100,6 +1095,7 @@ exit_cifs(void) | |||
1100 | cFYI(DBG2, ("exit_cifs")); | 1095 | cFYI(DBG2, ("exit_cifs")); |
1101 | cifs_proc_clean(); | 1096 | cifs_proc_clean(); |
1102 | #ifdef CONFIG_CIFS_DFS_UPCALL | 1097 | #ifdef CONFIG_CIFS_DFS_UPCALL |
1098 | cifs_dfs_release_automount_timer(); | ||
1103 | unregister_key_type(&key_type_dns_resolver); | 1099 | unregister_key_type(&key_type_dns_resolver); |
1104 | #endif | 1100 | #endif |
1105 | #ifdef CONFIG_CIFS_UPCALL | 1101 | #ifdef CONFIG_CIFS_UPCALL |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0c83da4a7dab..50f9fdae19b3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -104,13 +104,7 @@ extern int mode_to_acl(struct inode *inode, const char *path, __u64); | |||
104 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 104 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
105 | const char *); | 105 | const char *); |
106 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 106 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
107 | #ifdef CONFIG_CIFS_DFS_UPCALL | 107 | extern void cifs_dfs_release_automount_timer(void); |
108 | extern void dfs_shrink_umount_helper(struct vfsmount *vfsmnt); | ||
109 | #else | ||
110 | static inline void dfs_shrink_umount_helper(struct vfsmount *vfsmnt) | ||
111 | { | ||
112 | } | ||
113 | #endif /* DFS_UPCALL */ | ||
114 | void cifs_proc_init(void); | 108 | void cifs_proc_init(void); |
115 | void cifs_proc_clean(void); | 109 | void cifs_proc_clean(void); |
116 | 110 | ||
@@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
953 | { | 953 | { |
954 | char * name; | 954 | char * name; |
955 | int i, ch, retval; | 955 | int i, ch, retval; |
956 | struct files_struct *files; | ||
957 | char tcomm[sizeof(current->comm)]; | 956 | char tcomm[sizeof(current->comm)]; |
958 | 957 | ||
959 | /* | 958 | /* |
@@ -965,26 +964,15 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
965 | goto out; | 964 | goto out; |
966 | 965 | ||
967 | /* | 966 | /* |
968 | * Make sure we have private file handles. Ask the | ||
969 | * fork helper to do the work for us and the exit | ||
970 | * helper to do the cleanup of the old one. | ||
971 | */ | ||
972 | files = current->files; /* refcounted so safe to hold */ | ||
973 | retval = unshare_files(); | ||
974 | if (retval) | ||
975 | goto out; | ||
976 | /* | ||
977 | * Release all of the old mmap stuff | 967 | * Release all of the old mmap stuff |
978 | */ | 968 | */ |
979 | retval = exec_mmap(bprm->mm); | 969 | retval = exec_mmap(bprm->mm); |
980 | if (retval) | 970 | if (retval) |
981 | goto mmap_failed; | 971 | goto out; |
982 | 972 | ||
983 | bprm->mm = NULL; /* We're using it now */ | 973 | bprm->mm = NULL; /* We're using it now */ |
984 | 974 | ||
985 | /* This is the point of no return */ | 975 | /* This is the point of no return */ |
986 | put_files_struct(files); | ||
987 | |||
988 | current->sas_ss_sp = current->sas_ss_size = 0; | 976 | current->sas_ss_sp = current->sas_ss_size = 0; |
989 | 977 | ||
990 | if (current->euid == current->uid && current->egid == current->gid) | 978 | if (current->euid == current->uid && current->egid == current->gid) |
@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1034 | 1022 | ||
1035 | return 0; | 1023 | return 0; |
1036 | 1024 | ||
1037 | mmap_failed: | ||
1038 | reset_files_struct(current, files); | ||
1039 | out: | 1025 | out: |
1040 | return retval; | 1026 | return retval; |
1041 | } | 1027 | } |
@@ -1283,12 +1269,17 @@ int do_execve(char * filename, | |||
1283 | struct linux_binprm *bprm; | 1269 | struct linux_binprm *bprm; |
1284 | struct file *file; | 1270 | struct file *file; |
1285 | unsigned long env_p; | 1271 | unsigned long env_p; |
1272 | struct files_struct *displaced; | ||
1286 | int retval; | 1273 | int retval; |
1287 | 1274 | ||
1275 | retval = unshare_files(&displaced); | ||
1276 | if (retval) | ||
1277 | goto out_ret; | ||
1278 | |||
1288 | retval = -ENOMEM; | 1279 | retval = -ENOMEM; |
1289 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); | 1280 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); |
1290 | if (!bprm) | 1281 | if (!bprm) |
1291 | goto out_ret; | 1282 | goto out_files; |
1292 | 1283 | ||
1293 | file = open_exec(filename); | 1284 | file = open_exec(filename); |
1294 | retval = PTR_ERR(file); | 1285 | retval = PTR_ERR(file); |
@@ -1343,6 +1334,8 @@ int do_execve(char * filename, | |||
1343 | security_bprm_free(bprm); | 1334 | security_bprm_free(bprm); |
1344 | acct_update_integrals(current); | 1335 | acct_update_integrals(current); |
1345 | kfree(bprm); | 1336 | kfree(bprm); |
1337 | if (displaced) | ||
1338 | put_files_struct(displaced); | ||
1346 | return retval; | 1339 | return retval; |
1347 | } | 1340 | } |
1348 | 1341 | ||
@@ -1363,6 +1356,9 @@ out_file: | |||
1363 | out_kfree: | 1356 | out_kfree: |
1364 | kfree(bprm); | 1357 | kfree(bprm); |
1365 | 1358 | ||
1359 | out_files: | ||
1360 | if (displaced) | ||
1361 | reset_files_struct(displaced); | ||
1366 | out_ret: | 1362 | out_ret: |
1367 | return retval; | 1363 | return retval; |
1368 | } | 1364 | } |
diff --git a/fs/fcntl.c b/fs/fcntl.c index e632da761fc1..3f3ac630ccde 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd) | |||
55 | * file_lock held for write. | 55 | * file_lock held for write. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | static int locate_fd(struct files_struct *files, | 58 | static int locate_fd(unsigned int orig_start, int cloexec) |
59 | struct file *file, unsigned int orig_start) | ||
60 | { | 59 | { |
60 | struct files_struct *files = current->files; | ||
61 | unsigned int newfd; | 61 | unsigned int newfd; |
62 | unsigned int start; | 62 | unsigned int start; |
63 | int error; | 63 | int error; |
64 | struct fdtable *fdt; | 64 | struct fdtable *fdt; |
65 | 65 | ||
66 | spin_lock(&files->file_lock); | ||
67 | |||
66 | error = -EINVAL; | 68 | error = -EINVAL; |
67 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 69 | if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
68 | goto out; | 70 | goto out; |
@@ -97,42 +99,28 @@ repeat: | |||
97 | if (error) | 99 | if (error) |
98 | goto repeat; | 100 | goto repeat; |
99 | 101 | ||
100 | /* | ||
101 | * We reacquired files_lock, so we are safe as long as | ||
102 | * we reacquire the fdtable pointer and use it while holding | ||
103 | * the lock, no one can free it during that time. | ||
104 | */ | ||
105 | if (start <= files->next_fd) | 102 | if (start <= files->next_fd) |
106 | files->next_fd = newfd + 1; | 103 | files->next_fd = newfd + 1; |
107 | 104 | ||
105 | FD_SET(newfd, fdt->open_fds); | ||
106 | if (cloexec) | ||
107 | FD_SET(newfd, fdt->close_on_exec); | ||
108 | else | ||
109 | FD_CLR(newfd, fdt->close_on_exec); | ||
108 | error = newfd; | 110 | error = newfd; |
109 | 111 | ||
110 | out: | 112 | out: |
113 | spin_unlock(&files->file_lock); | ||
111 | return error; | 114 | return error; |
112 | } | 115 | } |
113 | 116 | ||
114 | static int dupfd(struct file *file, unsigned int start, int cloexec) | 117 | static int dupfd(struct file *file, unsigned int start, int cloexec) |
115 | { | 118 | { |
116 | struct files_struct * files = current->files; | 119 | int fd = locate_fd(start, cloexec); |
117 | struct fdtable *fdt; | 120 | if (fd >= 0) |
118 | int fd; | ||
119 | |||
120 | spin_lock(&files->file_lock); | ||
121 | fd = locate_fd(files, file, start); | ||
122 | if (fd >= 0) { | ||
123 | /* locate_fd() may have expanded fdtable, load the ptr */ | ||
124 | fdt = files_fdtable(files); | ||
125 | FD_SET(fd, fdt->open_fds); | ||
126 | if (cloexec) | ||
127 | FD_SET(fd, fdt->close_on_exec); | ||
128 | else | ||
129 | FD_CLR(fd, fdt->close_on_exec); | ||
130 | spin_unlock(&files->file_lock); | ||
131 | fd_install(fd, file); | 121 | fd_install(fd, file); |
132 | } else { | 122 | else |
133 | spin_unlock(&files->file_lock); | ||
134 | fput(file); | 123 | fput(file); |
135 | } | ||
136 | 124 | ||
137 | return fd; | 125 | return fd; |
138 | } | 126 | } |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 033f7bdd47e8..4df34da2284a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -242,10 +242,9 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, | |||
242 | return inode; | 242 | return inode; |
243 | } | 243 | } |
244 | 244 | ||
245 | static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags) | 245 | static void fuse_umount_begin(struct super_block *sb) |
246 | { | 246 | { |
247 | if (flags & MNT_FORCE) | 247 | fuse_abort_conn(get_fuse_conn_super(sb)); |
248 | fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb)); | ||
249 | } | 248 | } |
250 | 249 | ||
251 | static void fuse_send_destroy(struct fuse_conn *fc) | 250 | static void fuse_send_destroy(struct fuse_conn *fc) |
diff --git a/fs/locks.c b/fs/locks.c index e1ea2fe03681..44d9a6a7ec50 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -236,6 +236,7 @@ void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) | |||
236 | new->fl_ops = NULL; | 236 | new->fl_ops = NULL; |
237 | new->fl_lmops = NULL; | 237 | new->fl_lmops = NULL; |
238 | } | 238 | } |
239 | EXPORT_SYMBOL(__locks_copy_lock); | ||
239 | 240 | ||
240 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) | 241 | void locks_copy_lock(struct file_lock *new, struct file_lock *fl) |
241 | { | 242 | { |
diff --git a/fs/namespace.c b/fs/namespace.c index 0505fb61aa74..f48f98110c30 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1061,10 +1061,11 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
1061 | * about for the moment. | 1061 | * about for the moment. |
1062 | */ | 1062 | */ |
1063 | 1063 | ||
1064 | lock_kernel(); | 1064 | if (flags & MNT_FORCE && sb->s_op->umount_begin) { |
1065 | if (sb->s_op->umount_begin) | 1065 | lock_kernel(); |
1066 | sb->s_op->umount_begin(mnt, flags); | 1066 | sb->s_op->umount_begin(sb); |
1067 | unlock_kernel(); | 1067 | unlock_kernel(); |
1068 | } | ||
1068 | 1069 | ||
1069 | /* | 1070 | /* |
1070 | * No sense to grab the lock for this test, but test itself looks | 1071 | * No sense to grab the lock for this test, but test itself looks |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 20a1cb1810fe..fa220dc74609 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -198,7 +198,7 @@ static match_table_t nfs_secflavor_tokens = { | |||
198 | }; | 198 | }; |
199 | 199 | ||
200 | 200 | ||
201 | static void nfs_umount_begin(struct vfsmount *, int); | 201 | static void nfs_umount_begin(struct super_block *); |
202 | static int nfs_statfs(struct dentry *, struct kstatfs *); | 202 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
203 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 203 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
204 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 204 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
@@ -647,13 +647,11 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) | |||
647 | * Begin unmount by attempting to remove all automounted mountpoints we added | 647 | * Begin unmount by attempting to remove all automounted mountpoints we added |
648 | * in response to xdev traversals and referrals | 648 | * in response to xdev traversals and referrals |
649 | */ | 649 | */ |
650 | static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | 650 | static void nfs_umount_begin(struct super_block *sb) |
651 | { | 651 | { |
652 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); | 652 | struct nfs_server *server = NFS_SB(sb); |
653 | struct rpc_clnt *rpc; | 653 | struct rpc_clnt *rpc; |
654 | 654 | ||
655 | if (!(flags & MNT_FORCE)) | ||
656 | return; | ||
657 | /* -EIO all pending I/O */ | 655 | /* -EIO all pending I/O */ |
658 | rpc = server->client_acl; | 656 | rpc = server->client_acl; |
659 | if (!IS_ERR(rpc)) | 657 | if (!IS_ERR(rpc)) |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index ade9a7e6a757..dbdfabbfd609 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -477,11 +477,10 @@ const struct file_operations sysfs_file_operations = { | |||
477 | .poll = sysfs_poll, | 477 | .poll = sysfs_poll, |
478 | }; | 478 | }; |
479 | 479 | ||
480 | 480 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | |
481 | int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | 481 | const struct attribute *attr, int type, mode_t amode) |
482 | int type) | ||
483 | { | 482 | { |
484 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 483 | umode_t mode = (amode & S_IALLUGO) | S_IFREG; |
485 | struct sysfs_addrm_cxt acxt; | 484 | struct sysfs_addrm_cxt acxt; |
486 | struct sysfs_dirent *sd; | 485 | struct sysfs_dirent *sd; |
487 | int rc; | 486 | int rc; |
@@ -502,6 +501,13 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | |||
502 | } | 501 | } |
503 | 502 | ||
504 | 503 | ||
504 | int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, | ||
505 | int type) | ||
506 | { | ||
507 | return sysfs_add_file_mode(dir_sd, attr, type, attr->mode); | ||
508 | } | ||
509 | |||
510 | |||
505 | /** | 511 | /** |
506 | * sysfs_create_file - create an attribute file for an object. | 512 | * sysfs_create_file - create an attribute file for an object. |
507 | * @kobj: object we're creating for. | 513 | * @kobj: object we're creating for. |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 477904915032..eeba38417b1d 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -23,35 +23,50 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | |||
23 | int i; | 23 | int i; |
24 | 24 | ||
25 | for (i = 0, attr = grp->attrs; *attr; i++, attr++) | 25 | for (i = 0, attr = grp->attrs; *attr; i++, attr++) |
26 | if (!grp->is_visible || | 26 | sysfs_hash_and_remove(dir_sd, (*attr)->name); |
27 | grp->is_visible(kobj, *attr, i)) | ||
28 | sysfs_hash_and_remove(dir_sd, (*attr)->name); | ||
29 | } | 27 | } |
30 | 28 | ||
31 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | 29 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, |
32 | const struct attribute_group *grp) | 30 | const struct attribute_group *grp, int update) |
33 | { | 31 | { |
34 | struct attribute *const* attr; | 32 | struct attribute *const* attr; |
35 | int error = 0, i; | 33 | int error = 0, i; |
36 | 34 | ||
37 | for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) | 35 | for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { |
38 | if (!grp->is_visible || | 36 | mode_t mode = 0; |
39 | grp->is_visible(kobj, *attr, i)) | 37 | |
40 | error |= | 38 | /* in update mode, we're changing the permissions or |
41 | sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); | 39 | * visibility. Do this by first removing then |
40 | * re-adding (if required) the file */ | ||
41 | if (update) | ||
42 | sysfs_hash_and_remove(dir_sd, (*attr)->name); | ||
43 | if (grp->is_visible) { | ||
44 | mode = grp->is_visible(kobj, *attr, i); | ||
45 | if (!mode) | ||
46 | continue; | ||
47 | } | ||
48 | error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR, | ||
49 | (*attr)->mode | mode); | ||
50 | if (unlikely(error)) | ||
51 | break; | ||
52 | } | ||
42 | if (error) | 53 | if (error) |
43 | remove_files(dir_sd, kobj, grp); | 54 | remove_files(dir_sd, kobj, grp); |
44 | return error; | 55 | return error; |
45 | } | 56 | } |
46 | 57 | ||
47 | 58 | ||
48 | int sysfs_create_group(struct kobject * kobj, | 59 | static int internal_create_group(struct kobject *kobj, int update, |
49 | const struct attribute_group * grp) | 60 | const struct attribute_group *grp) |
50 | { | 61 | { |
51 | struct sysfs_dirent *sd; | 62 | struct sysfs_dirent *sd; |
52 | int error; | 63 | int error; |
53 | 64 | ||
54 | BUG_ON(!kobj || !kobj->sd); | 65 | BUG_ON(!kobj || (!update && !kobj->sd)); |
66 | |||
67 | /* Updates may happen before the object has been instantiated */ | ||
68 | if (unlikely(update && !kobj->sd)) | ||
69 | return -EINVAL; | ||
55 | 70 | ||
56 | if (grp->name) { | 71 | if (grp->name) { |
57 | error = sysfs_create_subdir(kobj, grp->name, &sd); | 72 | error = sysfs_create_subdir(kobj, grp->name, &sd); |
@@ -60,7 +75,7 @@ int sysfs_create_group(struct kobject * kobj, | |||
60 | } else | 75 | } else |
61 | sd = kobj->sd; | 76 | sd = kobj->sd; |
62 | sysfs_get(sd); | 77 | sysfs_get(sd); |
63 | error = create_files(sd, kobj, grp); | 78 | error = create_files(sd, kobj, grp, update); |
64 | if (error) { | 79 | if (error) { |
65 | if (grp->name) | 80 | if (grp->name) |
66 | sysfs_remove_subdir(sd); | 81 | sysfs_remove_subdir(sd); |
@@ -69,6 +84,47 @@ int sysfs_create_group(struct kobject * kobj, | |||
69 | return error; | 84 | return error; |
70 | } | 85 | } |
71 | 86 | ||
87 | /** | ||
88 | * sysfs_create_group - given a directory kobject, create an attribute group | ||
89 | * @kobj: The kobject to create the group on | ||
90 | * @grp: The attribute group to create | ||
91 | * | ||
92 | * This function creates a group for the first time. It will explicitly | ||
93 | * warn and error if any of the attribute files being created already exist. | ||
94 | * | ||
95 | * Returns 0 on success or error. | ||
96 | */ | ||
97 | int sysfs_create_group(struct kobject *kobj, | ||
98 | const struct attribute_group *grp) | ||
99 | { | ||
100 | return internal_create_group(kobj, 0, grp); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * sysfs_update_group - given a directory kobject, create an attribute group | ||
105 | * @kobj: The kobject to create the group on | ||
106 | * @grp: The attribute group to create | ||
107 | * | ||
108 | * This function updates an attribute group. Unlike | ||
109 | * sysfs_create_group(), it will explicitly not warn or error if any | ||
110 | * of the attribute files being created already exist. Furthermore, | ||
111 | * if the visibility of the files has changed through the is_visible() | ||
112 | * callback, it will update the permissions and add or remove the | ||
113 | * relevant files. | ||
114 | * | ||
115 | * The primary use for this function is to call it after making a change | ||
116 | * that affects group visibility. | ||
117 | * | ||
118 | * Returns 0 on success or error. | ||
119 | */ | ||
120 | int sysfs_update_group(struct kobject *kobj, | ||
121 | const struct attribute_group *grp) | ||
122 | { | ||
123 | return internal_create_group(kobj, 1, grp); | ||
124 | } | ||
125 | |||
126 | |||
127 | |||
72 | void sysfs_remove_group(struct kobject * kobj, | 128 | void sysfs_remove_group(struct kobject * kobj, |
73 | const struct attribute_group * grp) | 129 | const struct attribute_group * grp) |
74 | { | 130 | { |
@@ -95,4 +151,5 @@ void sysfs_remove_group(struct kobject * kobj, | |||
95 | 151 | ||
96 | 152 | ||
97 | EXPORT_SYMBOL_GPL(sysfs_create_group); | 153 | EXPORT_SYMBOL_GPL(sysfs_create_group); |
154 | EXPORT_SYMBOL_GPL(sysfs_update_group); | ||
98 | EXPORT_SYMBOL_GPL(sysfs_remove_group); | 155 | EXPORT_SYMBOL_GPL(sysfs_remove_group); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index ff17f8da9b43..ce4e15f8aaeb 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -154,6 +154,8 @@ extern const struct file_operations sysfs_file_operations; | |||
154 | int sysfs_add_file(struct sysfs_dirent *dir_sd, | 154 | int sysfs_add_file(struct sysfs_dirent *dir_sd, |
155 | const struct attribute *attr, int type); | 155 | const struct attribute *attr, int type); |
156 | 156 | ||
157 | int sysfs_add_file_mode(struct sysfs_dirent *dir_sd, | ||
158 | const struct attribute *attr, int type, mode_t amode); | ||
157 | /* | 159 | /* |
158 | * bin.c | 160 | * bin.c |
159 | */ | 161 | */ |