diff options
author | David Howells <dhowells@redhat.com> | 2012-02-16 12:49:42 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-02-19 13:30:52 -0500 |
commit | 1dce27c5aa6770e9d195f2bb7db1db3d4dde5591 (patch) | |
tree | 4ad3ffeee95cb5b10e047b7cb9bdbb48cfc734e0 /fs | |
parent | 8b3d1cda4f5ff0d7c2ae910ea8fd03493996912f (diff) |
Wrap accesses to the fd_sets in struct fdtable
Wrap accesses to the fd_sets in struct fdtable (for recording open files and
close-on-exec flags) so that we can move away from using fd_sets since we
abuse the fd_set structs by not allocating the full-sized structure under
normal circumstances and by non-core code looking at the internals of the
fd_sets.
The first abuse means that use of FD_ZERO() on these fd_sets is not permitted,
since that cannot be told about their abnormal lengths.
This introduces six wrapper functions for setting, clearing and testing
close-on-exec flags and fd-is-open flags:
void __set_close_on_exec(int fd, struct fdtable *fdt);
void __clear_close_on_exec(int fd, struct fdtable *fdt);
bool close_on_exec(int fd, const struct fdtable *fdt);
void __set_open_fd(int fd, struct fdtable *fdt);
void __clear_open_fd(int fd, struct fdtable *fdt);
bool fd_is_open(int fd, const struct fdtable *fdt);
Note that I've prepended '__' to the names of the set/clear functions because
they require the caller to hold a lock to use them.
Note also that I haven't added wrappers for looking behind the scenes at the
the array. Possibly that should exist too.
Signed-off-by: David Howells <dhowells@redhat.com>
Link: http://lkml.kernel.org/r/20120216174942.23314.1364.stgit@warthog.procyon.org.uk
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/autofs4/dev-ioctl.c | 2 | ||||
-rw-r--r-- | fs/exec.c | 4 | ||||
-rw-r--r-- | fs/fcntl.c | 18 | ||||
-rw-r--r-- | fs/file.c | 8 | ||||
-rw-r--r-- | fs/open.c | 4 | ||||
-rw-r--r-- | fs/proc/base.c | 2 |
6 files changed, 19 insertions, 19 deletions
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 76741d8d7786..3dfd615afb6b 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -230,7 +230,7 @@ static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file) | |||
230 | fdt = files_fdtable(files); | 230 | fdt = files_fdtable(files); |
231 | BUG_ON(fdt->fd[fd] != NULL); | 231 | BUG_ON(fdt->fd[fd] != NULL); |
232 | rcu_assign_pointer(fdt->fd[fd], file); | 232 | rcu_assign_pointer(fdt->fd[fd], file); |
233 | FD_SET(fd, fdt->close_on_exec); | 233 | __set_close_on_exec(fd, fdt); |
234 | spin_unlock(&files->file_lock); | 234 | spin_unlock(&files->file_lock); |
235 | } | 235 | } |
236 | 236 | ||
@@ -2078,8 +2078,8 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) | |||
2078 | fd_install(0, rp); | 2078 | fd_install(0, rp); |
2079 | spin_lock(&cf->file_lock); | 2079 | spin_lock(&cf->file_lock); |
2080 | fdt = files_fdtable(cf); | 2080 | fdt = files_fdtable(cf); |
2081 | FD_SET(0, fdt->open_fds); | 2081 | __set_open_fd(0, fdt); |
2082 | FD_CLR(0, fdt->close_on_exec); | 2082 | __clear_close_on_exec(0, fdt); |
2083 | spin_unlock(&cf->file_lock); | 2083 | spin_unlock(&cf->file_lock); |
2084 | 2084 | ||
2085 | /* and disallow core files too */ | 2085 | /* and disallow core files too */ |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 22764c7c8382..75e7c1f3a080 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -32,20 +32,20 @@ void set_close_on_exec(unsigned int fd, int flag) | |||
32 | spin_lock(&files->file_lock); | 32 | spin_lock(&files->file_lock); |
33 | fdt = files_fdtable(files); | 33 | fdt = files_fdtable(files); |
34 | if (flag) | 34 | if (flag) |
35 | FD_SET(fd, fdt->close_on_exec); | 35 | __set_close_on_exec(fd, fdt); |
36 | else | 36 | else |
37 | FD_CLR(fd, fdt->close_on_exec); | 37 | __clear_close_on_exec(fd, fdt); |
38 | spin_unlock(&files->file_lock); | 38 | spin_unlock(&files->file_lock); |
39 | } | 39 | } |
40 | 40 | ||
41 | static int get_close_on_exec(unsigned int fd) | 41 | static bool get_close_on_exec(unsigned int fd) |
42 | { | 42 | { |
43 | struct files_struct *files = current->files; | 43 | struct files_struct *files = current->files; |
44 | struct fdtable *fdt; | 44 | struct fdtable *fdt; |
45 | int res; | 45 | bool res; |
46 | rcu_read_lock(); | 46 | rcu_read_lock(); |
47 | fdt = files_fdtable(files); | 47 | fdt = files_fdtable(files); |
48 | res = FD_ISSET(fd, fdt->close_on_exec); | 48 | res = close_on_exec(fd, fdt); |
49 | rcu_read_unlock(); | 49 | rcu_read_unlock(); |
50 | return res; | 50 | return res; |
51 | } | 51 | } |
@@ -90,15 +90,15 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) | |||
90 | err = -EBUSY; | 90 | err = -EBUSY; |
91 | fdt = files_fdtable(files); | 91 | fdt = files_fdtable(files); |
92 | tofree = fdt->fd[newfd]; | 92 | tofree = fdt->fd[newfd]; |
93 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) | 93 | if (!tofree && fd_is_open(newfd, fdt)) |
94 | goto out_unlock; | 94 | goto out_unlock; |
95 | get_file(file); | 95 | get_file(file); |
96 | rcu_assign_pointer(fdt->fd[newfd], file); | 96 | rcu_assign_pointer(fdt->fd[newfd], file); |
97 | FD_SET(newfd, fdt->open_fds); | 97 | __set_open_fd(newfd, fdt); |
98 | if (flags & O_CLOEXEC) | 98 | if (flags & O_CLOEXEC) |
99 | FD_SET(newfd, fdt->close_on_exec); | 99 | __set_close_on_exec(newfd, fdt); |
100 | else | 100 | else |
101 | FD_CLR(newfd, fdt->close_on_exec); | 101 | __clear_close_on_exec(newfd, fdt); |
102 | spin_unlock(&files->file_lock); | 102 | spin_unlock(&files->file_lock); |
103 | 103 | ||
104 | if (tofree) | 104 | if (tofree) |
@@ -366,7 +366,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
366 | * is partway through open(). So make sure that this | 366 | * is partway through open(). So make sure that this |
367 | * fd is available to the new process. | 367 | * fd is available to the new process. |
368 | */ | 368 | */ |
369 | FD_CLR(open_files - i, new_fdt->open_fds); | 369 | __clear_open_fd(open_files - i, new_fdt); |
370 | } | 370 | } |
371 | rcu_assign_pointer(*new_fds++, f); | 371 | rcu_assign_pointer(*new_fds++, f); |
372 | } | 372 | } |
@@ -460,11 +460,11 @@ repeat: | |||
460 | if (start <= files->next_fd) | 460 | if (start <= files->next_fd) |
461 | files->next_fd = fd + 1; | 461 | files->next_fd = fd + 1; |
462 | 462 | ||
463 | FD_SET(fd, fdt->open_fds); | 463 | __set_open_fd(fd, fdt); |
464 | if (flags & O_CLOEXEC) | 464 | if (flags & O_CLOEXEC) |
465 | FD_SET(fd, fdt->close_on_exec); | 465 | __set_close_on_exec(fd, fdt); |
466 | else | 466 | else |
467 | FD_CLR(fd, fdt->close_on_exec); | 467 | __clear_close_on_exec(fd, fdt); |
468 | error = fd; | 468 | error = fd; |
469 | #if 1 | 469 | #if 1 |
470 | /* Sanity check */ | 470 | /* Sanity check */ |
@@ -836,7 +836,7 @@ EXPORT_SYMBOL(dentry_open); | |||
836 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) | 836 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
837 | { | 837 | { |
838 | struct fdtable *fdt = files_fdtable(files); | 838 | struct fdtable *fdt = files_fdtable(files); |
839 | __FD_CLR(fd, fdt->open_fds); | 839 | __clear_open_fd(fd, fdt); |
840 | if (fd < files->next_fd) | 840 | if (fd < files->next_fd) |
841 | files->next_fd = fd; | 841 | files->next_fd = fd; |
842 | } | 842 | } |
@@ -1080,7 +1080,7 @@ SYSCALL_DEFINE1(close, unsigned int, fd) | |||
1080 | if (!filp) | 1080 | if (!filp) |
1081 | goto out_unlock; | 1081 | goto out_unlock; |
1082 | rcu_assign_pointer(fdt->fd[fd], NULL); | 1082 | rcu_assign_pointer(fdt->fd[fd], NULL); |
1083 | FD_CLR(fd, fdt->close_on_exec); | 1083 | __clear_close_on_exec(fd, fdt); |
1084 | __put_unused_fd(files, fd); | 1084 | __put_unused_fd(files, fd); |
1085 | spin_unlock(&files->file_lock); | 1085 | spin_unlock(&files->file_lock); |
1086 | retval = filp_close(filp, files); | 1086 | retval = filp_close(filp, files); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index d4548dd49b02..db6ab4b36a0b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1754,7 +1754,7 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info) | |||
1754 | 1754 | ||
1755 | fdt = files_fdtable(files); | 1755 | fdt = files_fdtable(files); |
1756 | f_flags = file->f_flags & ~O_CLOEXEC; | 1756 | f_flags = file->f_flags & ~O_CLOEXEC; |
1757 | if (FD_ISSET(fd, fdt->close_on_exec)) | 1757 | if (close_on_exec(fd, fdt)) |
1758 | f_flags |= O_CLOEXEC; | 1758 | f_flags |= O_CLOEXEC; |
1759 | 1759 | ||
1760 | if (path) { | 1760 | if (path) { |