diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-01 11:26:51 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-01 11:26:51 -0700 |
commit | d65f5c5803d9cd6fa0b540a0dddf956be671bc36 (patch) | |
tree | d8b7e7197bd126ce857c9a368dd7573b531cb22f /fs/file.c | |
parent | a8086ad803fc4d251edb9a49838bf99c7fdfb44f (diff) | |
parent | 8d66bf5481002b0960aa49aed0987c73f5d7816c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
[PATCH] pass struct path * to do_add_mount()
[PATCH] switch mtd and dm-table to lookup_bdev()
[patch 3/4] vfs: remove unused nameidata argument of may_create()
[PATCH] devpts: switch to IDA
[PATCH 2/2] proc: switch inode number allocation to IDA
[PATCH 1/2] proc: fix inode number bogorithmetic
[PATCH] fix bdev leak in block_dev.c do_open()
[PATCH] fix races and leaks in vfs_quota_on() users
[PATCH] clean dup2() up a bit
[PATCH] merge locate_fd() and get_unused_fd()
[PATCH] ipv4_static_sysctl_init() should be under CONFIG_SYSCTL
Re: BUG at security/selinux/avc.c:883 (was: Re: linux-next: Tree
Diffstat (limited to 'fs/file.c')
-rw-r--r-- | fs/file.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/file.c b/fs/file.c index d8773b19fe4..f313314f996 100644 --- a/fs/file.c +++ b/fs/file.c @@ -6,6 +6,7 @@ * Manage the dynamic fd arrays in the process files_struct. */ +#include <linux/module.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/time.h> @@ -432,3 +433,63 @@ struct files_struct init_files = { }, .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), }; + +/* + * allocate a file descriptor, mark it busy. + */ +int alloc_fd(unsigned start, unsigned flags) +{ + struct files_struct *files = current->files; + unsigned int fd; + int error; + struct fdtable *fdt; + + spin_lock(&files->file_lock); +repeat: + fdt = files_fdtable(files); + fd = start; + if (fd < files->next_fd) + fd = files->next_fd; + + if (fd < fdt->max_fds) + fd = find_next_zero_bit(fdt->open_fds->fds_bits, + fdt->max_fds, fd); + + error = expand_files(files, fd); + if (error < 0) + goto out; + + /* + * If we needed to expand the fs array we + * might have blocked - try again. + */ + if (error) + goto repeat; + + if (start <= files->next_fd) + files->next_fd = fd + 1; + + FD_SET(fd, fdt->open_fds); + if (flags & O_CLOEXEC) + FD_SET(fd, fdt->close_on_exec); + else + FD_CLR(fd, fdt->close_on_exec); + error = fd; +#if 1 + /* Sanity check */ + if (rcu_dereference(fdt->fd[fd]) != NULL) { + printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); + rcu_assign_pointer(fdt->fd[fd], NULL); + } +#endif + +out: + spin_unlock(&files->file_lock); + return error; +} + +int get_unused_fd(void) +{ + return alloc_fd(0, 0); +} +EXPORT_SYMBOL(get_unused_fd); |