mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
Merge branch 'work.fdtable' into vfs.file
Bring in the fdtable changes for this cycle. Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
commit
2ec67bb4f9
@ -73,9 +73,7 @@ static struct spu_context *coredump_next_context(int *fd)
|
|||||||
return NULL;
|
return NULL;
|
||||||
*fd = n - 1;
|
*fd = n - 1;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_raw(*fd);
|
||||||
file = lookup_fdget_rcu(*fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file) {
|
if (file) {
|
||||||
ctx = SPUFS_I(file_inode(file))->i_ctx;
|
ctx = SPUFS_I(file_inode(file))->i_ctx;
|
||||||
get_spu_context(ctx);
|
get_spu_context(ctx);
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/filelock.h>
|
#include <linux/filelock.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/dnotify.h>
|
#include <linux/dnotify.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
204
fs/file.c
204
fs/file.c
@ -152,18 +152,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
|
|||||||
* 'unsigned long' in some places, but simply because that is how the Linux
|
* 'unsigned long' in some places, but simply because that is how the Linux
|
||||||
* kernel bitmaps are defined to work: they are not "bits in an array of bytes",
|
* kernel bitmaps are defined to work: they are not "bits in an array of bytes",
|
||||||
* they are very much "bits in an array of unsigned long".
|
* they are very much "bits in an array of unsigned long".
|
||||||
*
|
|
||||||
* The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
|
|
||||||
* by that "1024/sizeof(ptr)" before, we already know there are sufficient
|
|
||||||
* clear low bits. Clang seems to realize that, gcc ends up being confused.
|
|
||||||
*
|
|
||||||
* On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
|
|
||||||
* let's consider it documentation (and maybe a test-case for gcc to improve
|
|
||||||
* its code generation ;)
|
|
||||||
*/
|
*/
|
||||||
static struct fdtable * alloc_fdtable(unsigned int nr)
|
static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
|
||||||
{
|
{
|
||||||
struct fdtable *fdt;
|
struct fdtable *fdt;
|
||||||
|
unsigned int nr;
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -171,22 +164,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
|
|||||||
* Allocation steps are keyed to the size of the fdarray, since it
|
* Allocation steps are keyed to the size of the fdarray, since it
|
||||||
* grows far faster than any of the other dynamic data. We try to fit
|
* grows far faster than any of the other dynamic data. We try to fit
|
||||||
* the fdarray into comfortable page-tuned chunks: starting at 1024B
|
* the fdarray into comfortable page-tuned chunks: starting at 1024B
|
||||||
* and growing in powers of two from there on.
|
* and growing in powers of two from there on. Since we called only
|
||||||
|
* with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
|
||||||
|
* already gives BITS_PER_LONG slots), the above boils down to
|
||||||
|
* 1. use the smallest power of two large enough to give us that many
|
||||||
|
* slots.
|
||||||
|
* 2. on 32bit skip 64 and 128 - the minimal capacity we want there is
|
||||||
|
* 256 slots (i.e. 1Kb fd array).
|
||||||
|
* 3. on 64bit don't skip anything, 1Kb fd array means 128 slots there
|
||||||
|
* and we are never going to be asked for 64 or less.
|
||||||
*/
|
*/
|
||||||
nr /= (1024 / sizeof(struct file *));
|
if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
|
||||||
nr = roundup_pow_of_two(nr + 1);
|
nr = 256;
|
||||||
nr *= (1024 / sizeof(struct file *));
|
else
|
||||||
nr = ALIGN(nr, BITS_PER_LONG);
|
nr = roundup_pow_of_two(slots_wanted);
|
||||||
/*
|
/*
|
||||||
* Note that this can drive nr *below* what we had passed if sysctl_nr_open
|
* Note that this can drive nr *below* what we had passed if sysctl_nr_open
|
||||||
* had been set lower between the check in expand_files() and here. Deal
|
* had been set lower between the check in expand_files() and here.
|
||||||
* with that in caller, it's cheaper that way.
|
|
||||||
*
|
*
|
||||||
* We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
|
* We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
|
||||||
* bitmaps handling below becomes unpleasant, to put it mildly...
|
* bitmaps handling below becomes unpleasant, to put it mildly...
|
||||||
*/
|
*/
|
||||||
if (unlikely(nr > sysctl_nr_open))
|
if (unlikely(nr > sysctl_nr_open)) {
|
||||||
nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
|
nr = round_down(sysctl_nr_open, BITS_PER_LONG);
|
||||||
|
if (nr < slots_wanted)
|
||||||
|
return ERR_PTR(-EMFILE);
|
||||||
|
}
|
||||||
|
|
||||||
fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL_ACCOUNT);
|
fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL_ACCOUNT);
|
||||||
if (!fdt)
|
if (!fdt)
|
||||||
@ -215,14 +218,14 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
|
|||||||
out_fdt:
|
out_fdt:
|
||||||
kfree(fdt);
|
kfree(fdt);
|
||||||
out:
|
out:
|
||||||
return NULL;
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand the file descriptor table.
|
* Expand the file descriptor table.
|
||||||
* This function will allocate a new fdtable and both fd array and fdset, of
|
* This function will allocate a new fdtable and both fd array and fdset, of
|
||||||
* the given size.
|
* the given size.
|
||||||
* Return <0 error code on error; 1 on successful completion.
|
* Return <0 error code on error; 0 on successful completion.
|
||||||
* The files->file_lock should be held on entry, and will be held on exit.
|
* The files->file_lock should be held on entry, and will be held on exit.
|
||||||
*/
|
*/
|
||||||
static int expand_fdtable(struct files_struct *files, unsigned int nr)
|
static int expand_fdtable(struct files_struct *files, unsigned int nr)
|
||||||
@ -232,7 +235,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
|
|||||||
struct fdtable *new_fdt, *cur_fdt;
|
struct fdtable *new_fdt, *cur_fdt;
|
||||||
|
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
new_fdt = alloc_fdtable(nr);
|
new_fdt = alloc_fdtable(nr + 1);
|
||||||
|
|
||||||
/* make sure all fd_install() have seen resize_in_progress
|
/* make sure all fd_install() have seen resize_in_progress
|
||||||
* or have finished their rcu_read_lock_sched() section.
|
* or have finished their rcu_read_lock_sched() section.
|
||||||
@ -241,16 +244,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
|
|||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
if (!new_fdt)
|
if (IS_ERR(new_fdt))
|
||||||
return -ENOMEM;
|
return PTR_ERR(new_fdt);
|
||||||
/*
|
|
||||||
* extremely unlikely race - sysctl_nr_open decreased between the check in
|
|
||||||
* caller and alloc_fdtable(). Cheaper to catch it here...
|
|
||||||
*/
|
|
||||||
if (unlikely(new_fdt->max_fds <= nr)) {
|
|
||||||
__free_fdtable(new_fdt);
|
|
||||||
return -EMFILE;
|
|
||||||
}
|
|
||||||
cur_fdt = files_fdtable(files);
|
cur_fdt = files_fdtable(files);
|
||||||
BUG_ON(nr < cur_fdt->max_fds);
|
BUG_ON(nr < cur_fdt->max_fds);
|
||||||
copy_fdtable(new_fdt, cur_fdt);
|
copy_fdtable(new_fdt, cur_fdt);
|
||||||
@ -259,15 +254,14 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
|
|||||||
call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
|
call_rcu(&cur_fdt->rcu, free_fdtable_rcu);
|
||||||
/* coupled with smp_rmb() in fd_install() */
|
/* coupled with smp_rmb() in fd_install() */
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand files.
|
* Expand files.
|
||||||
* This function will expand the file structures, if the requested size exceeds
|
* This function will expand the file structures, if the requested size exceeds
|
||||||
* the current capacity and there is room for expansion.
|
* the current capacity and there is room for expansion.
|
||||||
* Return <0 error code on error; 0 when nothing done; 1 when files were
|
* Return <0 error code on error; 0 on success.
|
||||||
* expanded and execution may have blocked.
|
|
||||||
* The files->file_lock should be held on entry, and will be held on exit.
|
* The files->file_lock should be held on entry, and will be held on exit.
|
||||||
*/
|
*/
|
||||||
static int expand_files(struct files_struct *files, unsigned int nr)
|
static int expand_files(struct files_struct *files, unsigned int nr)
|
||||||
@ -275,14 +269,14 @@ static int expand_files(struct files_struct *files, unsigned int nr)
|
|||||||
__acquires(files->file_lock)
|
__acquires(files->file_lock)
|
||||||
{
|
{
|
||||||
struct fdtable *fdt;
|
struct fdtable *fdt;
|
||||||
int expanded = 0;
|
int error;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
fdt = files_fdtable(files);
|
fdt = files_fdtable(files);
|
||||||
|
|
||||||
/* Do we need to expand? */
|
/* Do we need to expand? */
|
||||||
if (nr < fdt->max_fds)
|
if (nr < fdt->max_fds)
|
||||||
return expanded;
|
return 0;
|
||||||
|
|
||||||
/* Can we expand? */
|
/* Can we expand? */
|
||||||
if (nr >= sysctl_nr_open)
|
if (nr >= sysctl_nr_open)
|
||||||
@ -290,7 +284,6 @@ static int expand_files(struct files_struct *files, unsigned int nr)
|
|||||||
|
|
||||||
if (unlikely(files->resize_in_progress)) {
|
if (unlikely(files->resize_in_progress)) {
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
expanded = 1;
|
|
||||||
wait_event(files->resize_wait, !files->resize_in_progress);
|
wait_event(files->resize_wait, !files->resize_in_progress);
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
goto repeat;
|
goto repeat;
|
||||||
@ -298,27 +291,28 @@ static int expand_files(struct files_struct *files, unsigned int nr)
|
|||||||
|
|
||||||
/* All good, so we try */
|
/* All good, so we try */
|
||||||
files->resize_in_progress = true;
|
files->resize_in_progress = true;
|
||||||
expanded = expand_fdtable(files, nr);
|
error = expand_fdtable(files, nr);
|
||||||
files->resize_in_progress = false;
|
files->resize_in_progress = false;
|
||||||
|
|
||||||
wake_up_all(&files->resize_wait);
|
wake_up_all(&files->resize_wait);
|
||||||
return expanded;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __set_close_on_exec(unsigned int fd, struct fdtable *fdt)
|
static inline void __set_close_on_exec(unsigned int fd, struct fdtable *fdt,
|
||||||
|
bool set)
|
||||||
{
|
{
|
||||||
__set_bit(fd, fdt->close_on_exec);
|
if (set) {
|
||||||
|
__set_bit(fd, fdt->close_on_exec);
|
||||||
|
} else {
|
||||||
|
if (test_bit(fd, fdt->close_on_exec))
|
||||||
|
__clear_bit(fd, fdt->close_on_exec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __clear_close_on_exec(unsigned int fd, struct fdtable *fdt)
|
static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt, bool set)
|
||||||
{
|
|
||||||
if (test_bit(fd, fdt->close_on_exec))
|
|
||||||
__clear_bit(fd, fdt->close_on_exec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt)
|
|
||||||
{
|
{
|
||||||
__set_bit(fd, fdt->open_fds);
|
__set_bit(fd, fdt->open_fds);
|
||||||
|
__set_close_on_exec(fd, fdt, set);
|
||||||
fd /= BITS_PER_LONG;
|
fd /= BITS_PER_LONG;
|
||||||
if (!~fdt->open_fds[fd])
|
if (!~fdt->open_fds[fd])
|
||||||
__set_bit(fd, fdt->full_fds_bits);
|
__set_bit(fd, fdt->full_fds_bits);
|
||||||
@ -327,7 +321,9 @@ static inline void __set_open_fd(unsigned int fd, struct fdtable *fdt)
|
|||||||
static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
|
static inline void __clear_open_fd(unsigned int fd, struct fdtable *fdt)
|
||||||
{
|
{
|
||||||
__clear_bit(fd, fdt->open_fds);
|
__clear_bit(fd, fdt->open_fds);
|
||||||
__clear_bit(fd / BITS_PER_LONG, fdt->full_fds_bits);
|
fd /= BITS_PER_LONG;
|
||||||
|
if (test_bit(fd, fdt->full_fds_bits))
|
||||||
|
__clear_bit(fd, fdt->full_fds_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
|
static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
|
||||||
@ -369,7 +365,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
|
|||||||
struct file **old_fds, **new_fds;
|
struct file **old_fds, **new_fds;
|
||||||
unsigned int open_files, i;
|
unsigned int open_files, i;
|
||||||
struct fdtable *old_fdt, *new_fdt;
|
struct fdtable *old_fdt, *new_fdt;
|
||||||
int error;
|
|
||||||
|
|
||||||
newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
|
newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
|
||||||
if (!newf)
|
if (!newf)
|
||||||
@ -401,17 +396,10 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
|
|||||||
if (new_fdt != &newf->fdtab)
|
if (new_fdt != &newf->fdtab)
|
||||||
__free_fdtable(new_fdt);
|
__free_fdtable(new_fdt);
|
||||||
|
|
||||||
new_fdt = alloc_fdtable(open_files - 1);
|
new_fdt = alloc_fdtable(open_files);
|
||||||
if (!new_fdt) {
|
if (IS_ERR(new_fdt)) {
|
||||||
error = -ENOMEM;
|
kmem_cache_free(files_cachep, newf);
|
||||||
goto out_release;
|
return ERR_CAST(new_fdt);
|
||||||
}
|
|
||||||
|
|
||||||
/* beyond sysctl_nr_open; nothing to do */
|
|
||||||
if (unlikely(new_fdt->max_fds < open_files)) {
|
|
||||||
__free_fdtable(new_fdt);
|
|
||||||
error = -EMFILE;
|
|
||||||
goto out_release;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -452,10 +440,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
|
|||||||
rcu_assign_pointer(newf->fdt, new_fdt);
|
rcu_assign_pointer(newf->fdt, new_fdt);
|
||||||
|
|
||||||
return newf;
|
return newf;
|
||||||
|
|
||||||
out_release:
|
|
||||||
kmem_cache_free(files_cachep, newf);
|
|
||||||
return ERR_PTR(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fdtable *close_files(struct files_struct * files)
|
static struct fdtable *close_files(struct files_struct * files)
|
||||||
@ -476,7 +460,7 @@ static struct fdtable *close_files(struct files_struct * files)
|
|||||||
set = fdt->open_fds[j++];
|
set = fdt->open_fds[j++];
|
||||||
while (set) {
|
while (set) {
|
||||||
if (set & 1) {
|
if (set & 1) {
|
||||||
struct file * file = xchg(&fdt->fd[i], NULL);
|
struct file *file = fdt->fd[i];
|
||||||
if (file) {
|
if (file) {
|
||||||
filp_close(file, files);
|
filp_close(file, files);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@ -533,6 +517,15 @@ static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start)
|
|||||||
unsigned int maxfd = fdt->max_fds; /* always multiple of BITS_PER_LONG */
|
unsigned int maxfd = fdt->max_fds; /* always multiple of BITS_PER_LONG */
|
||||||
unsigned int maxbit = maxfd / BITS_PER_LONG;
|
unsigned int maxbit = maxfd / BITS_PER_LONG;
|
||||||
unsigned int bitbit = start / BITS_PER_LONG;
|
unsigned int bitbit = start / BITS_PER_LONG;
|
||||||
|
unsigned int bit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to avoid looking at the second level bitmap
|
||||||
|
*/
|
||||||
|
bit = find_next_zero_bit(&fdt->open_fds[bitbit], BITS_PER_LONG,
|
||||||
|
start & (BITS_PER_LONG - 1));
|
||||||
|
if (bit < BITS_PER_LONG)
|
||||||
|
return bit + bitbit * BITS_PER_LONG;
|
||||||
|
|
||||||
bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG;
|
bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG;
|
||||||
if (bitbit >= maxfd)
|
if (bitbit >= maxfd)
|
||||||
@ -559,7 +552,7 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)
|
|||||||
if (fd < files->next_fd)
|
if (fd < files->next_fd)
|
||||||
fd = files->next_fd;
|
fd = files->next_fd;
|
||||||
|
|
||||||
if (fd < fdt->max_fds)
|
if (likely(fd < fdt->max_fds))
|
||||||
fd = find_next_fd(fdt, fd);
|
fd = find_next_fd(fdt, fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -567,36 +560,22 @@ static int alloc_fd(unsigned start, unsigned end, unsigned flags)
|
|||||||
* will limit the total number of files that can be opened.
|
* will limit the total number of files that can be opened.
|
||||||
*/
|
*/
|
||||||
error = -EMFILE;
|
error = -EMFILE;
|
||||||
if (fd >= end)
|
if (unlikely(fd >= end))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = expand_files(files, fd);
|
if (unlikely(fd >= fdt->max_fds)) {
|
||||||
if (error < 0)
|
error = expand_files(files, fd);
|
||||||
goto out;
|
if (error < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/*
|
|
||||||
* If we needed to expand the fs array we
|
|
||||||
* might have blocked - try again.
|
|
||||||
*/
|
|
||||||
if (error)
|
|
||||||
goto repeat;
|
goto repeat;
|
||||||
|
}
|
||||||
|
|
||||||
if (start <= files->next_fd)
|
if (start <= files->next_fd)
|
||||||
files->next_fd = fd + 1;
|
files->next_fd = fd + 1;
|
||||||
|
|
||||||
__set_open_fd(fd, fdt);
|
__set_open_fd(fd, fdt, flags & O_CLOEXEC);
|
||||||
if (flags & O_CLOEXEC)
|
|
||||||
__set_close_on_exec(fd, fdt);
|
|
||||||
else
|
|
||||||
__clear_close_on_exec(fd, fdt);
|
|
||||||
error = fd;
|
error = fd;
|
||||||
#if 1
|
|
||||||
/* Sanity check */
|
|
||||||
if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
|
|
||||||
printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
|
|
||||||
rcu_assign_pointer(fdt->fd[fd], NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
@ -662,7 +641,7 @@ void fd_install(unsigned int fd, struct file *file)
|
|||||||
rcu_read_unlock_sched();
|
rcu_read_unlock_sched();
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
fdt = files_fdtable(files);
|
fdt = files_fdtable(files);
|
||||||
BUG_ON(fdt->fd[fd] != NULL);
|
WARN_ON(fdt->fd[fd] != NULL);
|
||||||
rcu_assign_pointer(fdt->fd[fd], file);
|
rcu_assign_pointer(fdt->fd[fd], file);
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
return;
|
return;
|
||||||
@ -776,7 +755,7 @@ static inline void __range_close(struct files_struct *files, unsigned int fd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __close_range() - Close all file descriptors in a given range.
|
* sys_close_range() - Close all file descriptors in a given range.
|
||||||
*
|
*
|
||||||
* @fd: starting file descriptor to close
|
* @fd: starting file descriptor to close
|
||||||
* @max_fd: last file descriptor to close
|
* @max_fd: last file descriptor to close
|
||||||
@ -784,8 +763,10 @@ static inline void __range_close(struct files_struct *files, unsigned int fd,
|
|||||||
*
|
*
|
||||||
* This closes a range of file descriptors. All file descriptors
|
* This closes a range of file descriptors. All file descriptors
|
||||||
* from @fd up to and including @max_fd are closed.
|
* from @fd up to and including @max_fd are closed.
|
||||||
|
* Currently, errors to close a given file descriptor are ignored.
|
||||||
*/
|
*/
|
||||||
int __close_range(unsigned fd, unsigned max_fd, unsigned int flags)
|
SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd,
|
||||||
|
unsigned int, flags)
|
||||||
{
|
{
|
||||||
struct task_struct *me = current;
|
struct task_struct *me = current;
|
||||||
struct files_struct *cur_fds = me->files, *fds = NULL;
|
struct files_struct *cur_fds = me->files, *fds = NULL;
|
||||||
@ -1100,29 +1081,7 @@ struct file *fget_task(struct task_struct *task, unsigned int fd)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *lookup_fdget_rcu(unsigned int fd)
|
struct file *fget_task_next(struct task_struct *task, unsigned int *ret_fd)
|
||||||
{
|
|
||||||
return __fget_files_rcu(current->files, fd, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(lookup_fdget_rcu);
|
|
||||||
|
|
||||||
struct file *task_lookup_fdget_rcu(struct task_struct *task, unsigned int fd)
|
|
||||||
{
|
|
||||||
/* Must be called with rcu_read_lock held */
|
|
||||||
struct files_struct *files;
|
|
||||||
struct file *file = NULL;
|
|
||||||
|
|
||||||
task_lock(task);
|
|
||||||
files = task->files;
|
|
||||||
if (files)
|
|
||||||
file = __fget_files_rcu(files, fd, 0);
|
|
||||||
task_unlock(task);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *ret_fd)
|
|
||||||
{
|
{
|
||||||
/* Must be called with rcu_read_lock held */
|
/* Must be called with rcu_read_lock held */
|
||||||
struct files_struct *files;
|
struct files_struct *files;
|
||||||
@ -1132,17 +1091,19 @@ struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *
|
|||||||
task_lock(task);
|
task_lock(task);
|
||||||
files = task->files;
|
files = task->files;
|
||||||
if (files) {
|
if (files) {
|
||||||
|
rcu_read_lock();
|
||||||
for (; fd < files_fdtable(files)->max_fds; fd++) {
|
for (; fd < files_fdtable(files)->max_fds; fd++) {
|
||||||
file = __fget_files_rcu(files, fd, 0);
|
file = __fget_files_rcu(files, fd, 0);
|
||||||
if (file)
|
if (file)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
task_unlock(task);
|
task_unlock(task);
|
||||||
*ret_fd = fd;
|
*ret_fd = fd;
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(task_lookup_next_fdget_rcu);
|
EXPORT_SYMBOL(fget_task_next);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lightweight file lookup - no refcnt increment if fd table isn't shared.
|
* Lightweight file lookup - no refcnt increment if fd table isn't shared.
|
||||||
@ -1239,13 +1200,8 @@ void __f_unlock_pos(struct file *f)
|
|||||||
void set_close_on_exec(unsigned int fd, int flag)
|
void set_close_on_exec(unsigned int fd, int flag)
|
||||||
{
|
{
|
||||||
struct files_struct *files = current->files;
|
struct files_struct *files = current->files;
|
||||||
struct fdtable *fdt;
|
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
fdt = files_fdtable(files);
|
__set_close_on_exec(fd, files_fdtable(files), flag);
|
||||||
if (flag)
|
|
||||||
__set_close_on_exec(fd, fdt);
|
|
||||||
else
|
|
||||||
__clear_close_on_exec(fd, fdt);
|
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1286,11 +1242,7 @@ __releases(&files->file_lock)
|
|||||||
goto Ebusy;
|
goto Ebusy;
|
||||||
get_file(file);
|
get_file(file);
|
||||||
rcu_assign_pointer(fdt->fd[fd], file);
|
rcu_assign_pointer(fdt->fd[fd], file);
|
||||||
__set_open_fd(fd, fdt);
|
__set_open_fd(fd, fdt, flags & O_CLOEXEC);
|
||||||
if (flags & O_CLOEXEC)
|
|
||||||
__set_close_on_exec(fd, fdt);
|
|
||||||
else
|
|
||||||
__clear_close_on_exec(fd, fdt);
|
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
|
|
||||||
if (tofree)
|
if (tofree)
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <linux/lockref.h>
|
#include <linux/lockref.h>
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
|
|
||||||
#include "gfs2.h"
|
#include "gfs2.h"
|
||||||
@ -2768,25 +2767,18 @@ static struct file *gfs2_glockfd_next_file(struct gfs2_glockfd_iter *i)
|
|||||||
i->file = NULL;
|
i->file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
for(;; i->fd++) {
|
for(;; i->fd++) {
|
||||||
struct inode *inode;
|
i->file = fget_task_next(i->task, &i->fd);
|
||||||
|
|
||||||
i->file = task_lookup_next_fdget_rcu(i->task, &i->fd);
|
|
||||||
if (!i->file) {
|
if (!i->file) {
|
||||||
i->fd = 0;
|
i->fd = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = file_inode(i->file);
|
if (file_inode(i->file)->i_sb == i->sb)
|
||||||
if (inode->i_sb == i->sb)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
fput(i->file);
|
fput(i->file);
|
||||||
rcu_read_lock();
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
return i->file;
|
return i->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fsnotify_backend.h>
|
#include <linux/fsnotify_backend.h>
|
||||||
|
|
||||||
static int dir_notify_enable __read_mostly = 1;
|
static int dir_notify_enable __read_mostly = 1;
|
||||||
@ -347,9 +346,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned int arg)
|
|||||||
new_fsn_mark = NULL;
|
new_fsn_mark = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
f = fget_raw(fd);
|
||||||
f = lookup_fdget_rcu(fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
/* if (f != filp) means that we lost a race and another task/thread
|
/* if (f != filp) means that we lost a race and another task/thread
|
||||||
* actually closed the fd we are still playing with before we grabbed
|
* actually closed the fd we are still playing with before we grabbed
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#include <linux/fanotify.h>
|
#include <linux/fanotify.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fsnotify_backend.h>
|
#include <linux/fsnotify_backend.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#include <linux/fanotify.h>
|
#include <linux/fanotify.h>
|
||||||
#include <linux/fcntl.h>
|
#include <linux/fcntl.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/anon_inodes.h>
|
#include <linux/anon_inodes.h>
|
||||||
|
17
fs/open.c
17
fs/open.c
@ -1574,23 +1574,6 @@ SYSCALL_DEFINE1(close, unsigned int, fd)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* sys_close_range() - Close all file descriptors in a given range.
|
|
||||||
*
|
|
||||||
* @fd: starting file descriptor to close
|
|
||||||
* @max_fd: last file descriptor to close
|
|
||||||
* @flags: reserved for future extensions
|
|
||||||
*
|
|
||||||
* This closes a range of file descriptors. All file descriptors
|
|
||||||
* from @fd up to and including @max_fd are closed.
|
|
||||||
* Currently, errors to close a given file descriptor are ignored.
|
|
||||||
*/
|
|
||||||
SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd,
|
|
||||||
unsigned int, flags)
|
|
||||||
{
|
|
||||||
return __close_range(fd, max_fd, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine simulates a hangup on the tty, to arrange that users
|
* This routine simulates a hangup on the tty, to arrange that users
|
||||||
* are given clean terminals at login time.
|
* are given clean terminals at login time.
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
#include "overlayfs.h"
|
#include "overlayfs.h"
|
||||||
|
@ -58,7 +58,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/generic-radix-tree.h>
|
#include <linux/generic-radix-tree.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
12
fs/proc/fd.c
12
fs/proc/fd.c
@ -116,9 +116,7 @@ static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_task(task, fd);
|
||||||
file = task_lookup_fdget_rcu(task, fd);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file) {
|
if (file) {
|
||||||
*mode = file->f_mode;
|
*mode = file->f_mode;
|
||||||
fput(file);
|
fput(file);
|
||||||
@ -258,19 +256,17 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
|
|||||||
if (!dir_emit_dots(file, ctx))
|
if (!dir_emit_dots(file, ctx))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
for (fd = ctx->pos - 2;; fd++) {
|
for (fd = ctx->pos - 2;; fd++) {
|
||||||
struct file *f;
|
struct file *f;
|
||||||
struct fd_data data;
|
struct fd_data data;
|
||||||
char name[10 + 1];
|
char name[10 + 1];
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
f = task_lookup_next_fdget_rcu(p, &fd);
|
f = fget_task_next(p, &fd);
|
||||||
ctx->pos = fd + 2LL;
|
ctx->pos = fd + 2LL;
|
||||||
if (!f)
|
if (!f)
|
||||||
break;
|
break;
|
||||||
data.mode = f->f_mode;
|
data.mode = f->f_mode;
|
||||||
rcu_read_unlock();
|
|
||||||
fput(f);
|
fput(f);
|
||||||
data.fd = fd;
|
data.fd = fd;
|
||||||
|
|
||||||
@ -278,11 +274,9 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,
|
|||||||
if (!proc_fill_cache(file, ctx,
|
if (!proc_fill_cache(file, ctx,
|
||||||
name, len, instantiate, p,
|
name, len, instantiate, p,
|
||||||
&data))
|
&data))
|
||||||
goto out;
|
break;
|
||||||
cond_resched();
|
cond_resched();
|
||||||
rcu_read_lock();
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
out:
|
out:
|
||||||
put_task_struct(p);
|
put_task_struct(p);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -92,10 +92,6 @@ static inline struct file *files_lookup_fd_locked(struct files_struct *files, un
|
|||||||
return files_lookup_fd_raw(files, fd);
|
return files_lookup_fd_raw(files, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *lookup_fdget_rcu(unsigned int fd);
|
|
||||||
struct file *task_lookup_fdget_rcu(struct task_struct *task, unsigned int fd);
|
|
||||||
struct file *task_lookup_next_fdget_rcu(struct task_struct *task, unsigned int *fd);
|
|
||||||
|
|
||||||
static inline bool close_on_exec(unsigned int fd, const struct files_struct *files)
|
static inline bool close_on_exec(unsigned int fd, const struct files_struct *files)
|
||||||
{
|
{
|
||||||
return test_bit(fd, files_fdtable(files)->close_on_exec);
|
return test_bit(fd, files_fdtable(files)->close_on_exec);
|
||||||
@ -115,7 +111,6 @@ int iterate_fd(struct files_struct *, unsigned,
|
|||||||
const void *);
|
const void *);
|
||||||
|
|
||||||
extern int close_fd(unsigned int fd);
|
extern int close_fd(unsigned int fd);
|
||||||
extern int __close_range(unsigned int fd, unsigned int max_fd, unsigned int flags);
|
|
||||||
extern struct file *file_close_fd(unsigned int fd);
|
extern struct file *file_close_fd(unsigned int fd);
|
||||||
|
|
||||||
extern struct kmem_cache *files_cachep;
|
extern struct kmem_cache *files_cachep;
|
||||||
|
@ -72,6 +72,7 @@ static inline void fdput(struct fd fd)
|
|||||||
extern struct file *fget(unsigned int fd);
|
extern struct file *fget(unsigned int fd);
|
||||||
extern struct file *fget_raw(unsigned int fd);
|
extern struct file *fget_raw(unsigned int fd);
|
||||||
extern struct file *fget_task(struct task_struct *task, unsigned int fd);
|
extern struct file *fget_task(struct task_struct *task, unsigned int fd);
|
||||||
|
extern struct file *fget_task_next(struct task_struct *task, unsigned int *fd);
|
||||||
extern void __f_unlock_pos(struct file *);
|
extern void __f_unlock_pos(struct file *);
|
||||||
|
|
||||||
struct fd fdget(unsigned int fd);
|
struct fd fdget(unsigned int fd);
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <uapi/linux/btf.h>
|
#include <uapi/linux/btf.h>
|
||||||
#include <linux/bpf_lsm.h>
|
#include <linux/bpf_lsm.h>
|
||||||
#include <linux/btf_ids.h>
|
#include <linux/btf_ids.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/rcupdate_trace.h>
|
#include <linux/rcupdate_trace.h>
|
||||||
|
|
||||||
DEFINE_BPF_STORAGE_CACHE(inode_cache);
|
DEFINE_BPF_STORAGE_CACHE(inode_cache);
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <uapi/linux/btf.h>
|
#include <uapi/linux/btf.h>
|
||||||
#include <linux/btf_ids.h>
|
#include <linux/btf_ids.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/rcupdate_trace.h>
|
#include <linux/rcupdate_trace.h>
|
||||||
|
|
||||||
DEFINE_BPF_STORAGE_CACHE(task_cache);
|
DEFINE_BPF_STORAGE_CACHE(task_cache);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/bpf_mem_alloc.h>
|
#include <linux/bpf_mem_alloc.h>
|
||||||
#include <linux/btf_ids.h>
|
#include <linux/btf_ids.h>
|
||||||
@ -286,17 +285,14 @@ task_file_seq_get_next(struct bpf_iter_seq_task_file_info *info)
|
|||||||
curr_fd = 0;
|
curr_fd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
f = fget_task_next(curr_task, &curr_fd);
|
||||||
f = task_lookup_next_fdget_rcu(curr_task, &curr_fd);
|
|
||||||
if (f) {
|
if (f) {
|
||||||
/* set info->fd */
|
/* set info->fd */
|
||||||
info->fd = curr_fd;
|
info->fd = curr_fd;
|
||||||
rcu_read_unlock();
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the current task is done, go to the next task */
|
/* the current task is done, go to the next task */
|
||||||
rcu_read_unlock();
|
|
||||||
put_task_struct(curr_task);
|
put_task_struct(curr_task);
|
||||||
|
|
||||||
if (info->common.type == BPF_TASK_ITER_TID) {
|
if (info->common.type == BPF_TASK_ITER_TID) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <linux/acct.h>
|
#include <linux/acct.h>
|
||||||
#include <linux/tsacct_kern.h>
|
#include <linux/tsacct_kern.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
|
@ -63,9 +63,7 @@ get_file_raw_ptr(struct task_struct *task, unsigned int idx)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
rcu_read_lock();
|
file = fget_task(task, idx);
|
||||||
file = task_lookup_fdget_rcu(task, idx);
|
|
||||||
rcu_read_unlock();
|
|
||||||
if (file)
|
if (file)
|
||||||
fput(file);
|
fput(file);
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fs_struct.h>
|
#include <linux/fs_struct.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/inet.h>
|
#include <linux/inet.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
|
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/fdtable.h>
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user