Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | /*
* linux/fs/file_table.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/init.h>
/* SLAB cache for filp's. */
static kmem_cache_t *filp_cache;
/* sysctl tunables... */
int nr_files = 0; /* read only */
int nr_free_files = 0; /* read only */
int max_files = NR_FILE;/* tunable */
/* Free list management, if you are here you must have f_count == 0 */
static struct file * free_filps = NULL;
void insert_file_free(struct file *file)
{
if((file->f_next = free_filps) != NULL)
free_filps->f_pprev = &file->f_next;
free_filps = file;
file->f_pprev = &free_filps;
nr_free_files++;
}
/* The list of in-use filp's must be exported (ugh...) */
struct file *inuse_filps = NULL;
static inline void put_inuse(struct file *file)
{
if((file->f_next = inuse_filps) != NULL)
inuse_filps->f_pprev = &file->f_next;
inuse_filps = file;
file->f_pprev = &inuse_filps;
}
void __init file_table_init(void)
{
filp_cache = kmem_cache_create("filp", sizeof(struct file),
0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if(!filp_cache)
panic("VFS: Cannot alloc filp SLAB cache.");
/*
* We could allocate the reserved files here, but really
* shouldn't need to: the normal boot process will create
* plenty of free files.
*/
}
/* Find an unused file structure and return a pointer to it.
* Returns NULL, if there are no more free file structures or
* we run out of memory.
*/
struct file * get_empty_filp(void)
{
static int old_max = 0;
struct file * f;
if (nr_free_files > NR_RESERVED_FILES) {
used_one:
f = free_filps;
remove_filp(f);
nr_free_files--;
new_one:
memset(f, 0, sizeof(*f));
f->f_count = 1;
f->f_version = ++event;
put_inuse(f);
return f;
}
/*
* Use a reserved one if we're the superuser
*/
if (nr_free_files && !current->euid)
goto used_one;
/*
* Allocate a new one if we're below the limit.
*/
if (nr_files < max_files) {
f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
if (f) {
nr_files++;
goto new_one;
}
/* Big problems... */
printk("VFS: filp allocation failed\n");
} else if (max_files > old_max) {
printk("VFS: file-max limit %d reached\n", max_files);
old_max = max_files;
}
return NULL;
}
/*
* Clear and initialize a (private) struct file for the given dentry,
* and call the open function (if any). The caller must verify that
* inode->i_op and inode->i_op->default_file_ops are not NULL.
*/
int init_private_file(struct file *filp, struct dentry *dentry, int mode)
{
memset(filp, 0, sizeof(*filp));
filp->f_mode = mode;
filp->f_count = 1;
filp->f_dentry = dentry;
filp->f_op = dentry->d_inode->i_op->default_file_ops;
if (filp->f_op->open)
return filp->f_op->open(dentry->d_inode, filp);
else
return 0;
}
|