cregit-Linux how code gets into the kernel

Release 4.7 fs/file_table.c

Directory: fs
/*
 *  linux/fs/file_table.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
 */

#include <linux/string.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/eventpoll.h>
#include <linux/rcupdate.h>
#include <linux/mount.h>
#include <linux/capability.h>
#include <linux/cdev.h>
#include <linux/fsnotify.h>
#include <linux/sysctl.h>
#include <linux/percpu_counter.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
#include <linux/task_work.h>
#include <linux/ima.h>
#include <linux/swap.h>

#include <linux/atomic.h>

#include "internal.h"

/* sysctl tunables... */

struct files_stat_struct files_stat = {
	.max_files = NR_FILE
};

/* SLAB cache for file structures */

static struct kmem_cache *filp_cachep __read_mostly;


static struct percpu_counter nr_files __cacheline_aligned_in_smp;


static void file_free_rcu(struct rcu_head *head) { struct file *f = container_of(head, struct file, f_u.fu_rcuhead); put_cred(f->f_cred); kmem_cache_free(filp_cachep, f); }

Contributors

PersonTokensPropCommitsCommitProp
dipankar sarmadipankar sarma3276.19%133.33%
david howellsdavid howells716.67%133.33%
eric dumazeteric dumazet37.14%133.33%
Total42100.00%3100.00%


static inline void file_free(struct file *f) { percpu_counter_dec(&nr_files); call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); }

Contributors

PersonTokensPropCommitsCommitProp
andrew mortonandrew morton1653.33%125.00%
dipankar sarmadipankar sarma1136.67%250.00%
eric dumazeteric dumazet310.00%125.00%
Total30100.00%4100.00%

/* * Return the total number of open files in the system */
static long get_nr_files(void) { return percpu_counter_read_positive(&nr_files); }

Contributors

PersonTokensPropCommitsCommitProp
dipankar sarmadipankar sarma1493.33%150.00%
eric dumazeteric dumazet16.67%150.00%
Total15100.00%2100.00%

/* * Return the maximum number of open files in the system */
unsigned long get_max_files(void) { return files_stat.max_files; }

Contributors

PersonTokensPropCommitsCommitProp
dipankar sarmadipankar sarma1184.62%150.00%
eric dumazeteric dumazet215.38%150.00%
Total13100.00%2100.00%

EXPORT_SYMBOL_GPL(get_max_files); /* * Handle nr_files sysctl */ #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
int proc_nr_files(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { files_stat.nr_files = get_nr_files(); return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); }

Contributors

PersonTokensPropCommitsCommitProp
dipankar sarmadipankar sarma4595.74%133.33%
joe perchesjoe perches12.13%133.33%
eric dumazeteric dumazet12.13%133.33%
Total47100.00%3100.00%

#else
int proc_nr_files(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { return -ENOSYS; }

Contributors

PersonTokensPropCommitsCommitProp
dipankar sarmadipankar sarma2996.67%150.00%
joe perchesjoe perches13.33%150.00%
Total30100.00%2100.00%

#endif /* Find an unused file structure and return a pointer to it. * Returns an error pointer if some error happend e.g. we over file * structures limit, run out of memory or operation is not permitted. * * Be very careful using this. You are responsible for * getting write access to any mount that you might assign * to this filp, if it is opened for write. If this is not * done, you will imbalance int the mount's writer count * and a warning at __fput() time. */
struct file *get_empty_filp(void) { const struct cred *cred = current_cred(); static long old_max; struct file *f; int error; /* * Privileged users can go above max_files */ if (get_nr_files() >= files_stat.max_files && !capable(CAP_SYS_ADMIN)) { /* * percpu_counters are inaccurate. Do an expensive check before * we go and fail. */ if (percpu_counter_sum_positive(&nr_files) >= files_stat.max_files) goto over; } f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL); if (unlikely(!f)) return ERR_PTR(-ENOMEM); percpu_counter_inc(&nr_files); f->f_cred = get_cred(cred); error = security_file_alloc(f); if (unlikely(error)) { file_free(f); return ERR_PTR(error); } atomic_long_set(&f->f_count, 1); rwlock_init(&f->f_owner.lock); spin_lock_init(&f->f_lock); mutex_init(&f->f_pos_lock); eventpoll_init_file(f); /* f->f_version: 0 */ return f; over: /* Ran out of filps - report that */ if (get_nr_files() > old_max) { pr_info("VFS: file-max limit %lu reached\n", get_max_files()); old_max = get_nr_files(); } return ERR_PTR(-ENFILE); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git5325.60%726.92%
al viroal viro4119.81%27.69%
dipankar sarmadipankar sarma2813.53%13.85%
andrew mortonandrew morton178.21%311.54%
benjamin lahaisebenjamin lahaise146.76%13.85%
kirill korotaevkirill korotaev94.35%13.85%
tetsuo handatetsuo handa94.35%13.85%
linus torvaldslinus torvalds83.86%13.85%
jonathan corbetjonathan corbet83.86%13.85%
david howellsdavid howells62.90%13.85%
stephen d. smalleystephen d. smalley41.93%13.85%
eric dumazeteric dumazet31.45%13.85%
thomas gleixnerthomas gleixner20.97%13.85%
james morrisjames morris20.97%13.85%
cheng renquancheng renquan10.48%13.85%
peter zijlstrapeter zijlstra10.48%13.85%
greg kroah-hartmangreg kroah-hartman10.48%13.85%
Total207100.00%26100.00%

/** * alloc_file - allocate and initialize a 'struct file' * * @path: the (dentry, vfsmount) pair for the new file * @mode: the mode with which the new file will be opened * @fop: the 'struct file_operations' for the new file */
struct file *alloc_file(struct path *path, fmode_t mode, const struct file_operations *fop) { struct file *file; file = get_empty_filp(); if (IS_ERR(file)) return file; file->f_path = *path; file->f_inode = path->dentry->d_inode; file->f_mapping = path->dentry->d_inode->i_mapping; if ((mode & FMODE_READ) && likely(fop->read || fop->read_iter)) mode |= FMODE_CAN_READ; if ((mode & FMODE_WRITE) && likely(fop->write || fop->write_iter)) mode |= FMODE_CAN_WRITE; file->f_mode = mode; file->f_op = fop; if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_inc(path->dentry->d_inode); return file; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro7045.45%872.73%
dave hansendave hansen6340.91%19.09%
mimi zoharmimi zohar2012.99%19.09%
anatol pomozovanatol pomozov10.65%19.09%
Total154100.00%11100.00%

EXPORT_SYMBOL(alloc_file); /* the real guts of fput() - releasing the last reference to file */
static void __fput(struct file *file) { struct dentry *dentry = file->f_path.dentry; struct vfsmount *mnt = file->f_path.mnt; struct inode *inode = file->f_inode; might_sleep(); fsnotify_close(file); /* * The function eventpoll_release() should be the first called * in the file cleanup chain. */ eventpoll_release(file); locks_remove_file(file); if (unlikely(file->f_flags & FASYNC)) { if (file->f_op->fasync) file->f_op->fasync(-1, file, 0); } ima_file_free(file); if (file->f_op->release) file->f_op->release(inode, file); security_file_free(file); if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL && !(file->f_mode & FMODE_PATH))) { cdev_put(inode->i_cdev); } fops_put(file->f_op); put_pid(file->f_owner.pid); if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_dec(inode); if (file->f_mode & FMODE_WRITER) { put_write_access(inode); __mnt_drop_write(mnt); } file->f_path.dentry = NULL; file->f_path.mnt = NULL; file->f_inode = NULL; file_free(file); dput(dentry); mntput(mnt); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro7027.45%516.67%
pre-gitpre-git5822.75%723.33%
mimi zoharmimi zohar2610.20%26.67%
linus torvaldslinus torvalds207.84%13.33%
josef 'jeff' sipekjosef 'jeff' sipek124.71%13.33%
miklos szeredimiklos szeredi114.31%13.33%
dave hansendave hansen103.92%13.33%
benjamin lahaisebenjamin lahaise93.53%13.33%
eric w. biedermaneric w. biederman93.53%13.33%
theodore tsotheodore tso72.75%13.33%
davide libenzidavide libenzi62.35%26.67%
robert loverobert love51.96%13.33%
stephen d. smalleystephen d. smalley41.57%13.33%
ingo molnaringo molnar31.18%13.33%
david howellsdavid howells20.78%13.33%
greg kroah-hartmangreg kroah-hartman10.39%13.33%
jeff laytonjeff layton10.39%13.33%
andrew mortonandrew morton10.39%13.33%
Total255100.00%30100.00%

static LLIST_HEAD(delayed_fput_list);
static void delayed_fput(struct work_struct *unused) { struct llist_node *node = llist_del_all(&delayed_fput_list); struct llist_node *next; for (; node; node = next) { next = llist_next(node); __fput(llist_entry(node, struct file, f_u.fu_llist)); } }

Contributors

PersonTokensPropCommitsCommitProp
oleg nesterovoleg nesterov3050.00%150.00%
al viroal viro3050.00%150.00%
Total60100.00%2100.00%


static void ____fput(struct callback_head *work) { __fput(container_of(work, struct file, f_u.fu_rcuhead)); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro26100.00%1100.00%
Total26100.00%1100.00%

/* * If kernel thread really needs to have the final fput() it has done * to complete, call this. The only user right now is the boot - we * *do* need to make sure our writes to binaries on initramfs has * not left us with opened struct file waiting for __fput() - execve() * won't work without that. Please, don't add more callers without * very good reasons; in particular, never call that with locks * held and never call that from a thread that might need to do * some work on any kind of umount. */
void flush_delayed_fput(void) { delayed_fput(NULL); }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro12100.00%1100.00%
Total12100.00%1100.00%

static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
void fput(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { struct task_struct *task = current; if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { init_task_work(&file->f_u.fu_rcuhead, ____fput); if (!task_work_add(task, &file->f_u.fu_rcuhead, true)) return; /* * After this task has run exit_task_work(), * task_work_add() will fail. Fall through to delayed * fput to avoid leaking *file. */ } if (llist_add(&file->f_u.fu_llist, &delayed_fput_list)) schedule_delayed_work(&delayed_fput_work, 1); } }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro6058.25%350.00%
oleg nesterovoleg nesterov4240.78%233.33%
andrew mortonandrew morton10.97%116.67%
Total103100.00%6100.00%

/* * synchronous analog of fput(); for kernel threads that might be needed * in some umount() (and thus can't use flush_delayed_fput() without * risking deadlocks), need to wait for completion of __fput() and know * for this specific struct file it won't involve anything that would * need them. Use only if you really need it - at the very least, * don't blindly convert fput() by kernel thread to that. */
void __fput_sync(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { struct task_struct *task = current; BUG_ON(!(task->flags & PF_KTHREAD)); __fput(file); } }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro46100.00%2100.00%
Total46100.00%2100.00%

EXPORT_SYMBOL(fput);
void put_filp(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { security_file_free(file); file_free(file); } }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git2578.12%342.86%
stephen d. smalleystephen d. smalley412.50%114.29%
greg kroah-hartmangreg kroah-hartman13.12%114.29%
al viroal viro13.12%114.29%
andrew mortonandrew morton13.12%114.29%
Total32100.00%7100.00%


void __init files_init(void) { filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); percpu_counter_init(&nr_files, 0, GFP_KERNEL); }

Contributors

PersonTokensPropCommitsCommitProp
eric dumazeteric dumazet2153.85%133.33%
mel gormanmel gorman1230.77%133.33%
andi kleenandi kleen615.38%133.33%
Total39100.00%3100.00%

/* * One file with associated inode and dcache is very roughly 1K. Per default * do not use more than 10% of our memory for files. */
void __init files_maxfiles_init(void) { unsigned long n; unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2; memreserve = min(memreserve, totalram_pages - 1); n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10; files_stat.max_files = max_t(unsigned long, n, NR_FILE); }

Contributors

PersonTokensPropCommitsCommitProp
mel gormanmel gorman4260.87%133.33%
andi kleenandi kleen1927.54%133.33%
eric dumazeteric dumazet811.59%133.33%
Total69100.00%3100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
al viroal viro39329.57%1618.18%
dipankar sarmadipankar sarma20615.50%22.27%
pre-gitpre-git16312.26%1820.45%
dave hansendave hansen735.49%22.27%
oleg nesterovoleg nesterov735.49%22.27%
mel gormanmel gorman584.36%11.14%
eric dumazeteric dumazet503.76%33.41%
mimi zoharmimi zohar463.46%22.27%
andrew mortonandrew morton403.01%44.55%
linus torvaldslinus torvalds282.11%22.27%
andi kleenandi kleen251.88%11.14%
benjamin lahaisebenjamin lahaise231.73%22.27%
david howellsdavid howells151.13%33.41%
stephen d. smalleystephen d. smalley151.13%11.14%
josef 'jeff' sipekjosef 'jeff' sipek120.90%11.14%
miklos szeredimiklos szeredi110.83%11.14%
eric w. biedermaneric w. biederman90.68%11.14%
tetsuo handatetsuo handa90.68%11.14%
davide libenzidavide libenzi90.68%33.41%
kirill korotaevkirill korotaev90.68%11.14%
robert loverobert love80.60%11.14%
jonathan corbetjonathan corbet80.60%11.14%
theodore tsotheodore tso70.53%11.14%
roland dreierroland dreier50.38%11.14%
dave jonesdave jones40.30%22.27%
christoph hellwigchristoph hellwig30.23%11.14%
greg kroah-hartmangreg kroah-hartman30.23%11.14%
randy dunlaprandy dunlap30.23%11.14%
nick pigginnick piggin30.23%11.14%
ingo molnaringo molnar30.23%11.14%
eric pariseric paris30.23%11.14%
joe perchesjoe perches20.15%11.14%
james morrisjames morris20.15%11.14%
thomas gleixnerthomas gleixner20.15%11.14%
anatol pomozovanatol pomozov10.08%11.14%
arun sharmaarun sharma10.08%11.14%
cheng renquancheng renquan10.08%11.14%
eric biggerseric biggers10.08%11.14%
peter zijlstrapeter zijlstra10.08%11.14%
jeff laytonjeff layton10.08%11.14%
Total1329100.00%88100.00%
Directory: fs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}