mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
file: let pick_file() tell caller it's done
Let pick_file() report back that the fd it was passed exceeded the maximum fd in that fdtable. This allows us to simplify the caller of this helper because it doesn't need to care anymore whether the passed in max_fd is excessive. It can rely on pick_file() telling it that it's past the last valid fd. Cc: Christoph Hellwig <hch@lst.de> Cc: Giuseppe Scrivano <gscrivan@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
parent
9b5b872215
commit
f49fd6d3c0
33
fs/file.c
33
fs/file.c
@ -596,18 +596,32 @@ void fd_install(unsigned int fd, struct file *file)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(fd_install);
|
EXPORT_SYMBOL(fd_install);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pick_file - return file associatd with fd
|
||||||
|
* @files: file struct to retrieve file from
|
||||||
|
* @fd: file descriptor to retrieve file for
|
||||||
|
*
|
||||||
|
* If this functions returns an EINVAL error pointer the fd was beyond the
|
||||||
|
* current maximum number of file descriptors for that fdtable.
|
||||||
|
*
|
||||||
|
* Returns: The file associated with @fd, on error returns an error pointer.
|
||||||
|
*/
|
||||||
static struct file *pick_file(struct files_struct *files, unsigned fd)
|
static struct file *pick_file(struct files_struct *files, unsigned fd)
|
||||||
{
|
{
|
||||||
struct file *file = NULL;
|
struct file *file;
|
||||||
struct fdtable *fdt;
|
struct fdtable *fdt;
|
||||||
|
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
fdt = files_fdtable(files);
|
fdt = files_fdtable(files);
|
||||||
if (fd >= fdt->max_fds)
|
if (fd >= fdt->max_fds) {
|
||||||
|
file = ERR_PTR(-EINVAL);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
}
|
||||||
file = fdt->fd[fd];
|
file = fdt->fd[fd];
|
||||||
if (!file)
|
if (!file) {
|
||||||
|
file = ERR_PTR(-EBADF);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
}
|
||||||
rcu_assign_pointer(fdt->fd[fd], NULL);
|
rcu_assign_pointer(fdt->fd[fd], NULL);
|
||||||
__put_unused_fd(files, fd);
|
__put_unused_fd(files, fd);
|
||||||
|
|
||||||
@ -622,7 +636,7 @@ int close_fd(unsigned fd)
|
|||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
file = pick_file(files, fd);
|
file = pick_file(files, fd);
|
||||||
if (!file)
|
if (IS_ERR(file))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
return filp_close(file, files);
|
return filp_close(file, files);
|
||||||
@ -663,11 +677,16 @@ static inline void __range_close(struct files_struct *cur_fds, unsigned int fd,
|
|||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
file = pick_file(cur_fds, fd++);
|
file = pick_file(cur_fds, fd++);
|
||||||
if (!file)
|
if (!IS_ERR(file)) {
|
||||||
|
/* found a valid file to close */
|
||||||
|
filp_close(file, cur_fds);
|
||||||
|
cond_resched();
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
filp_close(file, cur_fds);
|
/* beyond the last fd in that table */
|
||||||
cond_resched();
|
if (PTR_ERR(file) == -EINVAL)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user