⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 base.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 5 页
字号:
    time_t ctime;    unsigned int ino;            /*  Inode number as seen in the VFS         */    uid_t uid;    gid_t gid;};struct devfs_entry{#ifdef CONFIG_DEVFS_DEBUG    unsigned int magic_number;#endif    void *info;    atomic_t refcount;           /*  When this drops to zero, it's unused    */    union     {	struct directory_type dir;	struct fcb_type fcb;	struct symlink_type symlink;	const char *name;        /*  Only used for (mode == 0)               */    }    u;    struct devfs_entry *prev;    /*  Previous entry in the parent directory  */    struct devfs_entry *next;    /*  Next entry in the parent directory      */    struct devfs_entry *parent;  /*  The parent directory                    */    struct devfs_entry *slave;   /*  Another entry to unregister             */    struct devfs_inode inode;    umode_t mode;    unsigned short namelen;      /*  I think 64k+ filenames are a way off... */    unsigned char hide:1;    unsigned char vfs_deletable:1;/*  Whether the VFS may delete the entry   */    char name[1];                /*  This is just a dummy: the allocated array				     is bigger. This is NULL-terminated      */};/*  The root of the device tree  */static struct devfs_entry *root_entry;struct devfsd_buf_entry{    struct devfs_entry *de;      /*  The name is generated with this         */    unsigned short type;         /*  The type of event                       */    umode_t mode;    uid_t uid;    gid_t gid;    struct devfsd_buf_entry *next;};struct fs_info                  /*  This structure is for the mounted devfs  */{    struct super_block *sb;    spinlock_t devfsd_buffer_lock;  /*  Lock when inserting/deleting events  */    struct devfsd_buf_entry *devfsd_first_event;    struct devfsd_buf_entry *devfsd_last_event;    volatile int devfsd_sleeping;    volatile struct task_struct *devfsd_task;    volatile pid_t devfsd_pgrp;    volatile struct file *devfsd_file;    struct devfsd_notify_struct *devfsd_info;    volatile unsigned long devfsd_event_mask;    atomic_t devfsd_overrun_count;    wait_queue_head_t devfsd_wait_queue;      /*  Wake devfsd on input       */    wait_queue_head_t revalidate_wait_queue;  /*  Wake when devfsd sleeps    */};static struct fs_info fs_info = {devfsd_buffer_lock: SPIN_LOCK_UNLOCKED};static kmem_cache_t *devfsd_buf_cache;#ifdef CONFIG_DEVFS_DEBUGstatic unsigned int devfs_debug_init __initdata = DEBUG_NONE;static unsigned int devfs_debug = DEBUG_NONE;static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED;static unsigned int stat_num_entries;static unsigned int stat_num_bytes;#endifstatic unsigned char poison_array[8] =    {0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a};#ifdef CONFIG_DEVFS_MOUNTstatic unsigned int boot_options = OPTION_MOUNT;#elsestatic unsigned int boot_options = OPTION_NONE;#endif/*  Forward function declarations  */static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,					const char *name, int namelen,					int traverse_symlink);static ssize_t devfsd_read (struct file *file, char *buf, size_t len,			    loff_t *ppos);static int devfsd_ioctl (struct inode *inode, struct file *file,			 unsigned int cmd, unsigned long arg);static int devfsd_close (struct inode *inode, struct file *file);#ifdef CONFIG_DEVFS_DEBUGstatic int stat_read (struct file *file, char *buf, size_t len,			    loff_t *ppos);static struct file_operations stat_fops ={    read:    stat_read,};#endif/*  Devfs daemon file operations  */static struct file_operations devfsd_fops ={    read:    devfsd_read,    ioctl:   devfsd_ioctl,    release: devfsd_close,};/*  Support functions follow  *//** *	devfs_get - Get a reference to a devfs entry. *	@de:  The devfs entry. */static struct devfs_entry *devfs_get (struct devfs_entry *de){    VERIFY_ENTRY (de);    if (de) atomic_inc (&de->refcount);    return de;}   /*  End Function devfs_get  *//** *	devfs_put - Put (release) a reference to a devfs entry. *	@de:  The handle to the devfs entry. */void devfs_put (devfs_handle_t de){    if (!de) return;    VERIFY_ENTRY (de);    if (de->info == POISON_PTR) OOPS ("(%p): poisoned pointer\n", de);    if ( !atomic_dec_and_test (&de->refcount) ) return;    if (de == root_entry) OOPS ("(%p): root entry being freed\n", de);    DPRINTK (DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n",	     de->name, de, de->parent,	     de->parent ? de->parent->name : "no parent");    if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);    if ( ( S_ISCHR (de->mode) || S_ISBLK (de->mode) ) && de->u.fcb.autogen )    {	devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :			       DEVFS_SPECIAL_BLK,			       mk_kdev (de->u.fcb.u.device.major,					de->u.fcb.u.device.minor) );    }    WRITE_ENTRY_MAGIC (de, 0);#ifdef CONFIG_DEVFS_DEBUG    spin_lock (&stat_lock);    --stat_num_entries;    stat_num_bytes -= sizeof *de + de->namelen;    if ( S_ISLNK (de->mode) ) stat_num_bytes -= de->u.symlink.length + 1;    spin_unlock (&stat_lock);#endif    de->info = POISON_PTR;    kfree (de);}   /*  End Function devfs_put  *//** *	_devfs_search_dir - Search for a devfs entry in a directory. *	@dir:  The directory to search. *	@name:  The name of the entry to search for. *	@namelen:  The number of characters in @name. * *  Search for a devfs entry in a directory and returns a pointer to the entry *   on success, else %NULL. The directory must be locked already. *   An implicit devfs_get() is performed on the returned entry. */static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir,					      const char *name,					      unsigned int namelen){    struct devfs_entry *curr;    if ( !S_ISDIR (dir->mode) )    {	PRINTK ("(%s): not a directory\n", dir->name);	return NULL;    }    for (curr = dir->u.dir.first; curr != NULL; curr = curr->next)    {	if (curr->namelen != namelen) continue;	if (memcmp (curr->name, name, namelen) == 0) break;	/*  Not found: try the next one  */    }    return devfs_get (curr);}   /*  End Function _devfs_search_dir  *//** *	_devfs_alloc_entry - Allocate a devfs entry. *	@name:  The name of the entry. *	@namelen:  The number of characters in @name. * *  Allocate a devfs entry and returns a pointer to the entry on success, else *   %NULL. */static struct devfs_entry *_devfs_alloc_entry (const char *name,					       unsigned int namelen,					       umode_t mode){    struct devfs_entry *new;    static unsigned long inode_counter = FIRST_INODE;    static spinlock_t counter_lock = SPIN_LOCK_UNLOCKED;    if ( name && (namelen < 1) ) namelen = strlen (name);    if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL )	return NULL;    memset (new, 0, sizeof *new + namelen);  /*  Will set '\0' on name  */    new->mode = mode;    if ( S_ISDIR (mode) ) rwlock_init (&new->u.dir.lock);    atomic_set (&new->refcount, 1);    spin_lock (&counter_lock);    new->inode.ino = inode_counter++;    spin_unlock (&counter_lock);    if (name) memcpy (new->name, name, namelen);    new->namelen = namelen;    WRITE_ENTRY_MAGIC (new, MAGIC_VALUE);#ifdef CONFIG_DEVFS_DEBUG    spin_lock (&stat_lock);    ++stat_num_entries;    stat_num_bytes += sizeof *new + namelen;    spin_unlock (&stat_lock);#endif    return new;}   /*  End Function _devfs_alloc_entry  *//** *	_devfs_append_entry - Append a devfs entry to a directory's child list. *	@dir:  The directory to add to. *	@de:  The devfs entry to append. *	@removable: If TRUE, increment the count of removable devices for %dir. *	@old_de: If an existing entry exists, it will be written here. This may *		 be %NULL. An implicit devfs_get() is performed on this entry. * *  Append a devfs entry to a directory's list of children, checking first to *   see if an entry of the same name exists. The directory will be locked. *   The value 0 is returned on success, else a negative error code. *   On failure, an implicit devfs_put() is performed on %de. */static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de,				int removable, devfs_handle_t *old_de){    int retval;    if (old_de) *old_de = NULL;    if ( !S_ISDIR (dir->mode) )    {	PRINTK ("(%s): dir: \"%s\" is not a directory\n", de->name, dir->name);	devfs_put (de);	return -ENOTDIR;    }    write_lock (&dir->u.dir.lock);    if (dir->u.dir.no_more_additions) retval = -ENOENT;    else    {	struct devfs_entry *old;	old = _devfs_search_dir (dir, de->name, de->namelen);	if (old_de) *old_de = old;	else devfs_put (old);	if (old == NULL)	{	    de->parent = dir;	    de->prev = dir->u.dir.last;	    /*  Append to the directory's list of children  */	    if (dir->u.dir.first == NULL) dir->u.dir.first = de;	    else dir->u.dir.last->next = de;	    dir->u.dir.last = de;	    if (removable) ++dir->u.dir.num_removable;	    retval = 0;	}	else retval = -EEXIST;    }    write_unlock (&dir->u.dir.lock);    if (retval) devfs_put (de);    return retval;}   /*  End Function _devfs_append_entry  *//** *	_devfs_get_root_entry - Get the root devfs entry. * *	Returns the root devfs entry on success, else %NULL. */static struct devfs_entry *_devfs_get_root_entry (void){    kdev_t devnum;    struct devfs_entry *new;    static spinlock_t root_lock = SPIN_LOCK_UNLOCKED;    /*  Always ensure the root is created  */    if (root_entry) return root_entry;    if ( ( new = _devfs_alloc_entry (NULL, 0,MODE_DIR) ) == NULL ) return NULL;    spin_lock (&root_lock);    if (root_entry)    {	spin_unlock (&root_lock);	devfs_put (new);	return (root_entry);    }    root_entry = new;    spin_unlock (&root_lock);    /*  And create the entry for ".devfsd"  */    if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )	 == NULL ) return NULL;    devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);    new->u.fcb.u.device.major = major (devnum);    new->u.fcb.u.device.minor = minor (devnum);    new->u.fcb.ops = &devfsd_fops;    _devfs_append_entry (root_entry, new, FALSE, NULL);#ifdef CONFIG_DEVFS_DEBUG    if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )	 == NULL ) return NULL;    devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);    new->u.fcb.u.device.major = major (devnum);    new->u.fcb.u.device.minor = minor (devnum);    new->u.fcb.ops = &stat_fops;    _devfs_append_entry (root_entry, new, FALSE, NULL);#endif    return root_entry;}   /*  End Function _devfs_get_root_entry  *//** *	_devfs_descend - Descend down a tree using the next component name. *	@dir:  The directory to search. *	@name:  The component name to search for. *	@namelen:  The length of %name. *	@next_pos:  The position of the next '/' or '\0' is written here. * *  Descend into a directory, searching for a component. This function forms *   the core of a tree-walking algorithm. The directory will be locked. *   The devfs entry corresponding to the component is returned. If there is *   no matching entry, %NULL is returned. *   An implicit devfs_get() is performed on the returned entry. */static struct devfs_entry *_devfs_descend (struct devfs_entry *dir,					   const char *name, int namelen,					   int *next_pos){    const char *stop, *ptr;    struct devfs_entry *entry;    if ( (namelen >= 3) && (strncmp (name, "../", 3) == 0) )    {   /*  Special-case going to parent directory  */	*next_pos = 3;	return devfs_get (dir->parent);    }    stop = name + namelen;    /*  Search for a possible '/'  */    for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr);    *next_pos = ptr - name;    read_lock (&dir->u.dir.lock);    entry = _devfs_search_dir (dir, name, *next_pos);    read_unlock (&dir->u.dir.lock);    return entry;}   /*  End Function _devfs_descend  */static devfs_handle_t _devfs_make_parent_for_leaf (struct devfs_entry *dir,						   const char *name,						   int namelen, int *leaf_pos){    int next_pos = 0;    if (dir == NULL) dir = _devfs_get_root_entry ();    if (dir == NULL) return NULL;    devfs_get (dir);    /*  Search for possible trailing component and ignore it  */    for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -