aboutsummaryrefslogtreecommitdiff
path: root/fs/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 11:26:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-08-01 11:26:51 -0700
commitd65f5c5803d9cd6fa0b540a0dddf956be671bc36 (patch)
treed8b7e7197bd126ce857c9a368dd7573b531cb22f /fs/file.c
parenta8086ad803fc4d251edb9a49838bf99c7fdfb44f (diff)
parent8d66bf5481002b0960aa49aed0987c73f5d7816c (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.c61
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);