aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 23:25:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 23:25:04 -0400
commitaab174f0df5d72d31caccf281af5f614fa254578 (patch)
tree2a172c5009c4ac8755e858593154c258ce7709a0 /kernel
parentca41cc96b2813221b05af57d0355157924de5a07 (diff)
parent2bd2c1941f141ad780135ccc1cd08ca71a24f10a (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs update from Al Viro: - big one - consolidation of descriptor-related logics; almost all of that is moved to fs/file.c (BTW, I'm seriously tempted to rename the result to fd.c. As it is, we have a situation when file_table.c is about handling of struct file and file.c is about handling of descriptor tables; the reasons are historical - file_table.c used to be about a static array of struct file we used to have way back). A lot of stray ends got cleaned up and converted to saner primitives, disgusting mess in android/binder.c is still disgusting, but at least doesn't poke so much in descriptor table guts anymore. A bunch of relatively minor races got fixed in process, plus an ext4 struct file leak. - related thing - fget_light() partially unuglified; see fdget() in there (and yes, it generates the code as good as we used to have). - also related - bits of Cyrill's procfs stuff that got entangled into that work; _not_ all of it, just the initial move to fs/proc/fd.c and switch of fdinfo to seq_file. - Alex's fs/coredump.c spiltoff - the same story, had been easier to take that commit than mess with conflicts. The rest is a separate pile, this was just a mechanical code movement. - a few misc patches all over the place. Not all for this cycle, there'll be more (and quite a few currently sit in akpm's tree)." Fix up trivial conflicts in the android binder driver, and some fairly simple conflicts due to two different changes to the sock_alloc_file() interface ("take descriptor handling from sock_alloc_file() to callers" vs "net: Providing protocol type via system.sockprotoname xattr of /proc/PID/fd entries" adding a dentry name to the socket) * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (72 commits) MAX_LFS_FILESIZE should be a loff_t compat: fs: Generic compat_sys_sendfile implementation fs: push rcu_barrier() from deactivate_locked_super() to filesystems btrfs: reada_extent doesn't need kref for refcount coredump: move core dump functionality into its own file coredump: prevent double-free on an error path in core dumper usb/gadget: fix misannotations fcntl: fix misannotations ceph: don't abuse d_delete() on failure exits hypfs: ->d_parent is never NULL or negative vfs: delete surplus inode NULL check switch simple cases of fget_light to fdget new helpers: fdget()/fdput() switch o2hb_region_dev_write() to fget_light() proc_map_files_readdir(): don't bother with grabbing files make get_file() return its argument vhost_set_vring(): turn pollstart/pollstop into bool switch prctl_set_mm_exe_file() to fget_light() switch xfs_find_handle() to fget_light() switch xfs_swapext() to fget_light() ...
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c72
-rw-r--r--kernel/exit.c97
-rw-r--r--kernel/sys.c14
-rw-r--r--kernel/taskstats.c11
4 files changed, 44 insertions, 150 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index deec4e50eb30..f16f3c58f11a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -468,14 +468,13 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
468{ 468{
469 struct perf_cgroup *cgrp; 469 struct perf_cgroup *cgrp;
470 struct cgroup_subsys_state *css; 470 struct cgroup_subsys_state *css;
471 struct file *file; 471 struct fd f = fdget(fd);
472 int ret = 0, fput_needed; 472 int ret = 0;
473 473
474 file = fget_light(fd, &fput_needed); 474 if (!f.file)
475 if (!file)
476 return -EBADF; 475 return -EBADF;
477 476
478 css = cgroup_css_from_dir(file, perf_subsys_id); 477 css = cgroup_css_from_dir(f.file, perf_subsys_id);
479 if (IS_ERR(css)) { 478 if (IS_ERR(css)) {
480 ret = PTR_ERR(css); 479 ret = PTR_ERR(css);
481 goto out; 480 goto out;
@@ -501,7 +500,7 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
501 ret = -EINVAL; 500 ret = -EINVAL;
502 } 501 }
503out: 502out:
504 fput_light(file, fput_needed); 503 fdput(f);
505 return ret; 504 return ret;
506} 505}
507 506
@@ -3234,21 +3233,18 @@ unlock:
3234 3233
3235static const struct file_operations perf_fops; 3234static const struct file_operations perf_fops;
3236 3235
3237static struct file *perf_fget_light(int fd, int *fput_needed) 3236static inline int perf_fget_light(int fd, struct fd *p)
3238{ 3237{
3239 struct file *file; 3238 struct fd f = fdget(fd);
3240 3239 if (!f.file)
3241 file = fget_light(fd, fput_needed); 3240 return -EBADF;
3242 if (!file)
3243 return ERR_PTR(-EBADF);
3244 3241
3245 if (file->f_op != &perf_fops) { 3242 if (f.file->f_op != &perf_fops) {
3246 fput_light(file, *fput_needed); 3243 fdput(f);
3247 *fput_needed = 0; 3244 return -EBADF;
3248 return ERR_PTR(-EBADF);
3249 } 3245 }
3250 3246 *p = f;
3251 return file; 3247 return 0;
3252} 3248}
3253 3249
3254static int perf_event_set_output(struct perf_event *event, 3250static int perf_event_set_output(struct perf_event *event,
@@ -3280,22 +3276,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3280 3276
3281 case PERF_EVENT_IOC_SET_OUTPUT: 3277 case PERF_EVENT_IOC_SET_OUTPUT:
3282 { 3278 {
3283 struct file *output_file = NULL;
3284 struct perf_event *output_event = NULL;
3285 int fput_needed = 0;
3286 int ret; 3279 int ret;
3287
3288 if (arg != -1) { 3280 if (arg != -1) {
3289 output_file = perf_fget_light(arg, &fput_needed); 3281 struct perf_event *output_event;
3290 if (IS_ERR(output_file)) 3282 struct fd output;
3291 return PTR_ERR(output_file); 3283 ret = perf_fget_light(arg, &output);
3292 output_event = output_file->private_data; 3284 if (ret)
3285 return ret;
3286 output_event = output.file->private_data;
3287 ret = perf_event_set_output(event, output_event);
3288 fdput(output);
3289 } else {
3290 ret = perf_event_set_output(event, NULL);
3293 } 3291 }
3294
3295 ret = perf_event_set_output(event, output_event);
3296 if (output_event)
3297 fput_light(output_file, fput_needed);
3298
3299 return ret; 3292 return ret;
3300 } 3293 }
3301 3294
@@ -6443,12 +6436,11 @@ SYSCALL_DEFINE5(perf_event_open,
6443 struct perf_event_attr attr; 6436 struct perf_event_attr attr;
6444 struct perf_event_context *ctx; 6437 struct perf_event_context *ctx;
6445 struct file *event_file = NULL; 6438 struct file *event_file = NULL;
6446 struct file *group_file = NULL; 6439 struct fd group = {NULL, 0};
6447 struct task_struct *task = NULL; 6440 struct task_struct *task = NULL;
6448 struct pmu *pmu; 6441 struct pmu *pmu;
6449 int event_fd; 6442 int event_fd;
6450 int move_group = 0; 6443 int move_group = 0;
6451 int fput_needed = 0;
6452 int err; 6444 int err;
6453 6445
6454 /* for future expandability... */ 6446 /* for future expandability... */
@@ -6478,17 +6470,15 @@ SYSCALL_DEFINE5(perf_event_open,
6478 if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) 6470 if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1))
6479 return -EINVAL; 6471 return -EINVAL;
6480 6472
6481 event_fd = get_unused_fd_flags(O_RDWR); 6473 event_fd = get_unused_fd();
6482 if (event_fd < 0) 6474 if (event_fd < 0)
6483 return event_fd; 6475 return event_fd;
6484 6476
6485 if (group_fd != -1) { 6477 if (group_fd != -1) {
6486 group_file = perf_fget_light(group_fd, &fput_needed); 6478 err = perf_fget_light(group_fd, &group);
6487 if (IS_ERR(group_file)) { 6479 if (err)
6488 err = PTR_ERR(group_file);
6489 goto err_fd; 6480 goto err_fd;
6490 } 6481 group_leader = group.file->private_data;
6491 group_leader = group_file->private_data;
6492 if (flags & PERF_FLAG_FD_OUTPUT) 6482 if (flags & PERF_FLAG_FD_OUTPUT)
6493 output_event = group_leader; 6483 output_event = group_leader;
6494 if (flags & PERF_FLAG_FD_NO_GROUP) 6484 if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6664,7 +6654,7 @@ SYSCALL_DEFINE5(perf_event_open,
6664 * of the group leader will find the pointer to itself in 6654 * of the group leader will find the pointer to itself in
6665 * perf_group_detach(). 6655 * perf_group_detach().
6666 */ 6656 */
6667 fput_light(group_file, fput_needed); 6657 fdput(group);
6668 fd_install(event_fd, event_file); 6658 fd_install(event_fd, event_file);
6669 return event_fd; 6659 return event_fd;
6670 6660
@@ -6678,7 +6668,7 @@ err_task:
6678 if (task) 6668 if (task)
6679 put_task_struct(task); 6669 put_task_struct(task);
6680err_group_fd: 6670err_group_fd:
6681 fput_light(group_file, fput_needed); 6671 fdput(group);
6682err_fd: 6672err_fd:
6683 put_unused_fd(event_fd); 6673 put_unused_fd(event_fd);
6684 return err; 6674 return err;
diff --git a/kernel/exit.c b/kernel/exit.c
index 42f25952edd9..346616c0092c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -457,108 +457,13 @@ void daemonize(const char *name, ...)
457 /* Become as one with the init task */ 457 /* Become as one with the init task */
458 458
459 daemonize_fs_struct(); 459 daemonize_fs_struct();
460 exit_files(current); 460 daemonize_descriptors();
461 current->files = init_task.files;
462 atomic_inc(&current->files->count);
463 461
464 reparent_to_kthreadd(); 462 reparent_to_kthreadd();
465} 463}
466 464
467EXPORT_SYMBOL(daemonize); 465EXPORT_SYMBOL(daemonize);
468 466
469static void close_files(struct files_struct * files)
470{
471 int i, j;
472 struct fdtable *fdt;
473
474 j = 0;
475
476 /*
477 * It is safe to dereference the fd table without RCU or
478 * ->file_lock because this is the last reference to the
479 * files structure. But use RCU to shut RCU-lockdep up.
480 */
481 rcu_read_lock();
482 fdt = files_fdtable(files);
483 rcu_read_unlock();
484 for (;;) {
485 unsigned long set;
486 i = j * BITS_PER_LONG;
487 if (i >= fdt->max_fds)
488 break;
489 set = fdt->open_fds[j++];
490 while (set) {
491 if (set & 1) {
492 struct file * file = xchg(&fdt->fd[i], NULL);
493 if (file) {
494 filp_close(file, files);
495 cond_resched();
496 }
497 }
498 i++;
499 set >>= 1;
500 }
501 }
502}
503
504struct files_struct *get_files_struct(struct task_struct *task)
505{
506 struct files_struct *files;
507
508 task_lock(task);
509 files = task->files;
510 if (files)
511 atomic_inc(&files->count);
512 task_unlock(task);
513
514 return files;
515}
516
517void put_files_struct(struct files_struct *files)
518{
519 struct fdtable *fdt;
520
521 if (atomic_dec_and_test(&files->count)) {
522 close_files(files);
523 /*
524 * Free the fd and fdset arrays if we expanded them.
525 * If the fdtable was embedded, pass files for freeing
526 * at the end of the RCU grace period. Otherwise,
527 * you can free files immediately.
528 */
529 rcu_read_lock();
530 fdt = files_fdtable(files);
531 if (fdt != &files->fdtab)
532 kmem_cache_free(files_cachep, files);
533 free_fdtable(fdt);
534 rcu_read_unlock();
535 }
536}
537
538void reset_files_struct(struct files_struct *files)
539{
540 struct task_struct *tsk = current;
541 struct files_struct *old;
542
543 old = tsk->files;
544 task_lock(tsk);
545 tsk->files = files;
546 task_unlock(tsk);
547 put_files_struct(old);
548}
549
550void exit_files(struct task_struct *tsk)
551{
552 struct files_struct * files = tsk->files;
553
554 if (files) {
555 task_lock(tsk);
556 tsk->files = NULL;
557 task_unlock(tsk);
558 put_files_struct(files);
559 }
560}
561
562#ifdef CONFIG_MM_OWNER 467#ifdef CONFIG_MM_OWNER
563/* 468/*
564 * A task is exiting. If it owned this mm, find a new owner for the mm. 469 * A task is exiting. If it owned this mm, find a new owner for the mm.
diff --git a/kernel/sys.c b/kernel/sys.c
index 241507f23eca..f9492284e5d2 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1788,15 +1788,15 @@ SYSCALL_DEFINE1(umask, int, mask)
1788#ifdef CONFIG_CHECKPOINT_RESTORE 1788#ifdef CONFIG_CHECKPOINT_RESTORE
1789static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) 1789static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1790{ 1790{
1791 struct file *exe_file; 1791 struct fd exe;
1792 struct dentry *dentry; 1792 struct dentry *dentry;
1793 int err; 1793 int err;
1794 1794
1795 exe_file = fget(fd); 1795 exe = fdget(fd);
1796 if (!exe_file) 1796 if (!exe.file)
1797 return -EBADF; 1797 return -EBADF;
1798 1798
1799 dentry = exe_file->f_path.dentry; 1799 dentry = exe.file->f_path.dentry;
1800 1800
1801 /* 1801 /*
1802 * Because the original mm->exe_file points to executable file, make 1802 * Because the original mm->exe_file points to executable file, make
@@ -1805,7 +1805,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1805 */ 1805 */
1806 err = -EACCES; 1806 err = -EACCES;
1807 if (!S_ISREG(dentry->d_inode->i_mode) || 1807 if (!S_ISREG(dentry->d_inode->i_mode) ||
1808 exe_file->f_path.mnt->mnt_flags & MNT_NOEXEC) 1808 exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
1809 goto exit; 1809 goto exit;
1810 1810
1811 err = inode_permission(dentry->d_inode, MAY_EXEC); 1811 err = inode_permission(dentry->d_inode, MAY_EXEC);
@@ -1839,12 +1839,12 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
1839 goto exit_unlock; 1839 goto exit_unlock;
1840 1840
1841 err = 0; 1841 err = 0;
1842 set_mm_exe_file(mm, exe_file); 1842 set_mm_exe_file(mm, exe.file); /* this grabs a reference to exe.file */
1843exit_unlock: 1843exit_unlock:
1844 up_write(&mm->mmap_sem); 1844 up_write(&mm->mmap_sem);
1845 1845
1846exit: 1846exit:
1847 fput(exe_file); 1847 fdput(exe);
1848 return err; 1848 return err;
1849} 1849}
1850 1850
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 5eab1f3edfa5..610f0838d555 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -424,16 +424,15 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
424 struct nlattr *na; 424 struct nlattr *na;
425 size_t size; 425 size_t size;
426 u32 fd; 426 u32 fd;
427 struct file *file; 427 struct fd f;
428 int fput_needed;
429 428
430 na = info->attrs[CGROUPSTATS_CMD_ATTR_FD]; 429 na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
431 if (!na) 430 if (!na)
432 return -EINVAL; 431 return -EINVAL;
433 432
434 fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]); 433 fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
435 file = fget_light(fd, &fput_needed); 434 f = fdget(fd);
436 if (!file) 435 if (!f.file)
437 return 0; 436 return 0;
438 437
439 size = nla_total_size(sizeof(struct cgroupstats)); 438 size = nla_total_size(sizeof(struct cgroupstats));
@@ -453,7 +452,7 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
453 stats = nla_data(na); 452 stats = nla_data(na);
454 memset(stats, 0, sizeof(*stats)); 453 memset(stats, 0, sizeof(*stats));
455 454
456 rc = cgroupstats_build(stats, file->f_dentry); 455 rc = cgroupstats_build(stats, f.file->f_dentry);
457 if (rc < 0) { 456 if (rc < 0) {
458 nlmsg_free(rep_skb); 457 nlmsg_free(rep_skb);
459 goto err; 458 goto err;
@@ -462,7 +461,7 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
462 rc = send_reply(rep_skb, info); 461 rc = send_reply(rep_skb, info);
463 462
464err: 463err:
465 fput_light(file, fput_needed); 464 fdput(f);
466 return rc; 465 return rc;
467} 466}
468 467