/* * Return the total number of open files in the system
*/ staticlong get_nr_files(void)
{ return percpu_counter_read_positive(&nr_files);
}
/* * Return the maximum number of open files in the system
*/ unsignedlong get_max_files(void)
{ return files_stat.max_files;
}
EXPORT_SYMBOL_GPL(get_max_files);
spin_lock_init(&f->f_lock); /* * Note that f_pos_lock is only used for files raising * FMODE_ATOMIC_POS and directories. Other files such as pipes * don't need it and since f_pos_lock is in a union may reuse * the space for other purposes. They are expected to initialize * the respective member when opening the file.
*/
mutex_init(&f->f_pos_lock);
memset(&f->f_path, 0, sizeof(f->f_path));
memset(&f->f_ra, 0, sizeof(f->f_ra));
/* * We're SLAB_TYPESAFE_BY_RCU so initialize f_count last. While * fget-rcu pattern users need to be able to handle spurious * refcount bumps we should reinitialize the reused file first.
*/
file_ref_init(&f->f_ref, 1); /* * Disable permission and pre-content events for all files by default. * They may be enabled later by fsnotify_open_perm_and_set_mode().
*/
file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM); return 0;
}
/* 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 *alloc_empty_file(int flags, conststruct cred *cred)
{ staticlong old_max; struct file *f; int error;
/* * Privileged users can go above max_files
*/ if (unlikely(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_alloc(filp_cachep, GFP_KERNEL); if (unlikely(!f)) return ERR_PTR(-ENOMEM);
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);
}
/* * Variant of alloc_empty_file() that doesn't check and modify nr_files. * * This is only for kernel internal use, and the allocate file must not be * installed into file tables or such.
*/ struct file *alloc_empty_file_noaccount(int flags, conststruct cred *cred)
{ struct file *f; int error;
f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); if (unlikely(!f)) return ERR_PTR(-ENOMEM);
/* * Variant of alloc_empty_file() that allocates a backing_file container * and doesn't check and modify nr_files. * * This is only for kernel internal use, and the allocate file must not be * installed into file tables or such.
*/ struct file *alloc_empty_backing_file(int flags, conststruct cred *cred)
{ struct backing_file *ff; int error;
ff = kmem_cache_alloc(bfilp_cachep, GFP_KERNEL); if (unlikely(!ff)) return ERR_PTR(-ENOMEM);
/** * file_init_path - initialize a 'struct file' based on path * * @file: the file to set up * @path: the (dentry, vfsmount) pair for the new file * @fop: the 'struct file_operations' for the new file
*/ staticvoid file_init_path(struct file *file, conststruct path *path, conststruct file_operations *fop)
{
file->f_path = *path;
file->f_inode = path->dentry->d_inode;
file->f_mapping = path->dentry->d_inode->i_mapping;
file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
file->f_sb_err = file_sample_sb_err(file); if (fop->llseek)
file->f_mode |= FMODE_LSEEK; if ((file->f_mode & FMODE_READ) &&
likely(fop->read || fop->read_iter))
file->f_mode |= FMODE_CAN_READ; if ((file->f_mode & FMODE_WRITE) &&
likely(fop->write || fop->write_iter))
file->f_mode |= FMODE_CAN_WRITE;
file->f_iocb_flags = iocb_flags(file);
file->f_mode |= FMODE_OPENED;
file->f_op = fop; if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
i_readcount_inc(path->dentry->d_inode);
}
/** * alloc_file - allocate and initialize a 'struct file' * * @path: the (dentry, vfsmount) pair for the new file * @flags: O_... flags with which the new file will be opened * @fop: the 'struct file_operations' for the new file
*/ staticstruct file *alloc_file(conststruct path *path, int flags, conststruct file_operations *fop)
{ struct file *file;
ret = alloc_path_pseudo(name, inode, mnt, &path); if (ret) return ERR_PTR(ret);
file = alloc_file(&path, flags, fops); if (IS_ERR(file)) {
ihold(inode);
path_put(&path); return file;
} /* * Disable all fsnotify events for pseudo files by default. * They may be enabled by caller with file_set_fsnotify_mode().
*/
file_set_fsnotify_mode(file, FMODE_NONOTIFY); return file;
}
EXPORT_SYMBOL(alloc_file_pseudo);
ret = alloc_path_pseudo(name, inode, mnt, &path); if (ret) return ERR_PTR(ret);
file = alloc_empty_file_noaccount(flags, current_cred()); if (IS_ERR(file)) {
ihold(inode);
path_put(&path); return file;
}
file_init_path(file, &path, fops); /* * Disable all fsnotify events for pseudo files by default. * They may be enabled by caller with file_set_fsnotify_mode().
*/
file_set_fsnotify_mode(file, FMODE_NONOTIFY); return file;
}
EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount);
f = alloc_file(&base->f_path, flags, fops); if (!IS_ERR(f)) {
path_get(&f->f_path);
f->f_mapping = base->f_mapping;
} return f;
}
/* the real guts of fput() - releasing the last reference to file
*/ staticvoid __fput(struct file *file)
{ struct dentry *dentry = file->f_path.dentry; struct vfsmount *mnt = file->f_path.mnt; struct inode *inode = file->f_inode;
fmode_t mode = file->f_mode;
if (unlikely(!(file->f_mode & FMODE_OPENED))) goto out;
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);
security_file_release(file); if (unlikely(file->f_flags & FASYNC)) { if (file->f_op->fasync)
file->f_op->fasync(-1, file, 0);
} if (file->f_op->release)
file->f_op->release(inode, file); if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
!(mode & FMODE_PATH))) {
cdev_put(inode->i_cdev);
}
fops_put(file->f_op);
file_f_owner_release(file);
put_file_access(file);
dput(dentry); if (unlikely(mode & FMODE_NEED_UNMOUNT))
dissolve_on_fput(mnt);
mntput(mnt);
out:
file_free(file);
}
/* * 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);
flush_delayed_work(&delayed_fput_work);
}
EXPORT_SYMBOL_GPL(flush_delayed_fput);
if (unlikely(!(file->f_mode & (FMODE_BACKING | FMODE_OPENED)))) {
file_free(file); return;
}
if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
init_task_work(&file->f_task_work, ____fput); if (!task_work_add(task, &file->f_task_work, TWA_RESUME)) 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_llist, &delayed_fput_list))
schedule_delayed_work(&delayed_fput_work, 1);
}
void fput(struct file *file)
{ if (unlikely(file_ref_put(&file->f_ref)))
__fput_deferred(file);
}
EXPORT_SYMBOL(fput);
/* * 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 (file_ref_put(&file->f_ref))
__fput(file);
}
EXPORT_SYMBOL(__fput_sync);
/* * Equivalent to __fput_sync(), but optimized for being called with the last * reference. * * See file_ref_put_close() for details.
*/ void fput_close_sync(struct file *file)
{ if (likely(file_ref_put_close(&file->f_ref)))
__fput(file);
}
/* * Equivalent to fput(), but optimized for being called with the last * reference. * * See file_ref_put_close() for details.
*/ void fput_close(struct file *file)
{ if (file_ref_put_close(&file->f_ref))
__fput_deferred(file);
}
/* * 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)
{ unsignedlong n; unsignedlong nr_pages = totalram_pages(); unsignedlong memreserve = (nr_pages - nr_free_pages()) * 3/2;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.