Loading fs/fcntl.c +14 −73 Original line number Diff line number Diff line Loading @@ -49,73 +49,6 @@ static int get_close_on_exec(unsigned int fd) return res; } /* * locate_fd finds a free file descriptor in the open_fds fdset, * expanding the fd arrays if necessary. Must be called with the * file_lock held for write. */ static int locate_fd(unsigned int orig_start, int cloexec) { struct files_struct *files = current->files; unsigned int newfd; unsigned int start; int error; struct fdtable *fdt; spin_lock(&files->file_lock); repeat: fdt = files_fdtable(files); /* * Someone might have closed fd's in the range * orig_start..fdt->next_fd */ start = orig_start; if (start < files->next_fd) start = files->next_fd; newfd = start; if (start < fdt->max_fds) newfd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, start); error = expand_files(files, newfd); 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 = newfd + 1; FD_SET(newfd, fdt->open_fds); if (cloexec) FD_SET(newfd, fdt->close_on_exec); else FD_CLR(newfd, fdt->close_on_exec); error = newfd; out: spin_unlock(&files->file_lock); return error; } static int dupfd(struct file *file, unsigned int start, int cloexec) { int fd = locate_fd(start, cloexec); if (fd >= 0) fd_install(fd, file); else fput(file); return fd; } asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) { int err = -EBADF; Loading Loading @@ -196,8 +129,13 @@ asmlinkage long sys_dup(unsigned int fildes) int ret = -EBADF; struct file *file = fget(fildes); if (file) ret = dupfd(file, 0, 0); if (file) { ret = get_unused_fd(); if (ret >= 0) fd_install(ret, file); else fput(file); } return ret; } Loading Loading @@ -322,8 +260,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_DUPFD_CLOEXEC: if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) break; err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); if (err >= 0) { get_file(filp); err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); fd_install(err, filp); } break; case F_GETFD: err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; Loading fs/file.c +61 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); fs/open.c +0 −56 Original line number Diff line number Diff line Loading @@ -963,62 +963,6 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) } EXPORT_SYMBOL(dentry_open); /* * Find an empty file descriptor entry, and mark it busy. */ int get_unused_fd_flags(int flags) { struct files_struct * files = current->files; int fd, error; struct fdtable *fdt; spin_lock(&files->file_lock); repeat: fdt = files_fdtable(files); fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, files->next_fd); /* Do we need to expand the fd array or fd set? */ error = expand_files(files, fd); if (error < 0) goto out; if (error) { /* * If we needed to expand the fs array we * might have blocked - try again. */ goto repeat; } 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); files->next_fd = fd + 1; #if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); fdt->fd[fd] = NULL; } #endif error = fd; out: spin_unlock(&files->file_lock); return error; } int get_unused_fd(void) { return get_unused_fd_flags(0); } EXPORT_SYMBOL(get_unused_fd); static void __put_unused_fd(struct files_struct *files, unsigned int fd) { struct fdtable *fdt = files_fdtable(files); Loading include/linux/file.h +2 −1 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ extern struct file *fget(unsigned int fd); extern struct file *fget_light(unsigned int fd, int *fput_needed); extern void set_close_on_exec(unsigned int fd, int flag); extern void put_filp(struct file *); extern int alloc_fd(unsigned start, unsigned flags); extern int get_unused_fd(void); extern int get_unused_fd_flags(int flags); #define get_unused_fd_flags(flags) alloc_fd(0, (flags)) extern void put_unused_fd(unsigned int fd); extern void fd_install(unsigned int fd, struct file *file); Loading Loading
fs/fcntl.c +14 −73 Original line number Diff line number Diff line Loading @@ -49,73 +49,6 @@ static int get_close_on_exec(unsigned int fd) return res; } /* * locate_fd finds a free file descriptor in the open_fds fdset, * expanding the fd arrays if necessary. Must be called with the * file_lock held for write. */ static int locate_fd(unsigned int orig_start, int cloexec) { struct files_struct *files = current->files; unsigned int newfd; unsigned int start; int error; struct fdtable *fdt; spin_lock(&files->file_lock); repeat: fdt = files_fdtable(files); /* * Someone might have closed fd's in the range * orig_start..fdt->next_fd */ start = orig_start; if (start < files->next_fd) start = files->next_fd; newfd = start; if (start < fdt->max_fds) newfd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, start); error = expand_files(files, newfd); 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 = newfd + 1; FD_SET(newfd, fdt->open_fds); if (cloexec) FD_SET(newfd, fdt->close_on_exec); else FD_CLR(newfd, fdt->close_on_exec); error = newfd; out: spin_unlock(&files->file_lock); return error; } static int dupfd(struct file *file, unsigned int start, int cloexec) { int fd = locate_fd(start, cloexec); if (fd >= 0) fd_install(fd, file); else fput(file); return fd; } asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) { int err = -EBADF; Loading Loading @@ -196,8 +129,13 @@ asmlinkage long sys_dup(unsigned int fildes) int ret = -EBADF; struct file *file = fget(fildes); if (file) ret = dupfd(file, 0, 0); if (file) { ret = get_unused_fd(); if (ret >= 0) fd_install(ret, file); else fput(file); } return ret; } Loading Loading @@ -322,8 +260,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_DUPFD_CLOEXEC: if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) break; err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); if (err >= 0) { get_file(filp); err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); fd_install(err, filp); } break; case F_GETFD: err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; Loading
fs/file.c +61 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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);
fs/open.c +0 −56 Original line number Diff line number Diff line Loading @@ -963,62 +963,6 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) } EXPORT_SYMBOL(dentry_open); /* * Find an empty file descriptor entry, and mark it busy. */ int get_unused_fd_flags(int flags) { struct files_struct * files = current->files; int fd, error; struct fdtable *fdt; spin_lock(&files->file_lock); repeat: fdt = files_fdtable(files); fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, files->next_fd); /* Do we need to expand the fd array or fd set? */ error = expand_files(files, fd); if (error < 0) goto out; if (error) { /* * If we needed to expand the fs array we * might have blocked - try again. */ goto repeat; } 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); files->next_fd = fd + 1; #if 1 /* Sanity check */ if (fdt->fd[fd] != NULL) { printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); fdt->fd[fd] = NULL; } #endif error = fd; out: spin_unlock(&files->file_lock); return error; } int get_unused_fd(void) { return get_unused_fd_flags(0); } EXPORT_SYMBOL(get_unused_fd); static void __put_unused_fd(struct files_struct *files, unsigned int fd) { struct fdtable *fdt = files_fdtable(files); Loading
include/linux/file.h +2 −1 Original line number Diff line number Diff line Loading @@ -34,8 +34,9 @@ extern struct file *fget(unsigned int fd); extern struct file *fget_light(unsigned int fd, int *fput_needed); extern void set_close_on_exec(unsigned int fd, int flag); extern void put_filp(struct file *); extern int alloc_fd(unsigned start, unsigned flags); extern int get_unused_fd(void); extern int get_unused_fd_flags(int flags); #define get_unused_fd_flags(flags) alloc_fd(0, (flags)) extern void put_unused_fd(unsigned int fd); extern void fd_install(unsigned int fd, struct file *file); Loading