[PATCH] merge locate_fd() and get_unused_fd()
New primitive: alloc_fd(start, flags). get_unused_fd() and get_unused_fd_flags() become wrappers on top of it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
61
fs/file.c
61
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);
|
||||
|
Reference in New Issue
Block a user