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

📄 base.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    if ( name && (namelen < 1) ) namelen = strlen (name);    if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL )	return NULL;    /*  Magic: this will set the ctime to zero, thus subsequent lookups will	trigger the call to <update_devfs_inode_from_entry>  */    memset (new, 0, sizeof *new + namelen);    new->parent = parent;    if (name) memcpy (new->name, name, namelen);    new->namelen = namelen;    new->inode.ino = fs_info.num_inodes + FIRST_INODE;    new->inode.nlink = 1;    fs_info.table[fs_info.num_inodes] = new;    ++fs_info.num_inodes;    if (parent == NULL) return new;    new->prev = parent->u.dir.last;    /*  Insert into the parent directory's list of children  */    if (parent->u.dir.first == NULL) parent->u.dir.first = new;    else parent->u.dir.last->next = new;    parent->u.dir.last = new;    return new;}   /*  End Function create_entry  */static void update_devfs_inode_from_entry (struct devfs_entry *de){    if (de == NULL) return;    if ( S_ISDIR (de->mode) )    {	de->inode.mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;	de->inode.uid = 0;	de->inode.gid = 0;    }    else if ( S_ISLNK (de->mode) )    {	de->inode.mode = S_IFLNK | S_IRUGO | S_IXUGO;	de->inode.uid = 0;	de->inode.gid = 0;    }    else if ( S_ISFIFO (de->mode) )    {	de->inode.mode = de->mode;	de->inode.uid = de->u.fifo.uid;	de->inode.gid = de->u.fifo.gid;    }    else    {	if (de->u.fcb.auto_owner)	    de->inode.mode = (de->mode & ~S_IALLUGO) | S_IRUGO | S_IWUGO;	else de->inode.mode = de->mode;	de->inode.uid = de->u.fcb.default_uid;	de->inode.gid = de->u.fcb.default_gid;    }}   /*  End Function update_devfs_inode_from_entry  *//** *	get_root_entry - Get the root devfs entry. * *	Returns the root devfs entry on success, else %NULL. */static struct devfs_entry *get_root_entry (void){    struct devfs_entry *new;    /*  Always ensure the root is created  */    if (root_entry != NULL) return root_entry;    if ( ( root_entry = create_entry (NULL, NULL, 0) ) == NULL ) return NULL;    root_entry->registered = TRUE;    root_entry->mode = S_IFDIR;    /*  Force an inode update, because lookup() is never done for the root  */    update_devfs_inode_from_entry (root_entry);    /*  And create the entry for ".devfsd"  */    if ( ( new = create_entry (root_entry, ".devfsd", 0) ) == NULL )	return NULL;    new->registered = TRUE;    new->u.fcb.u.device.major = next_devnum_char >> 8;    new->u.fcb.u.device.minor = next_devnum_char & 0xff;    ++next_devnum_char;    new->mode = S_IFCHR | S_IRUSR | S_IWUSR;    new->u.fcb.default_uid = 0;    new->u.fcb.default_gid = 0;    new->u.fcb.ops = &devfsd_fops;    return root_entry;}   /*  End Function get_root_entry  *//** *	search_for_entry - Search for an entry in the devfs tree. *	@dir: The parent directory to search from. If this is %NULL the root is used *	@name: The name of the entry. *	@namelen: The number of characters in @name. *	@mkdir: If %TRUE intermediate directories are created as needed. *	@mkfile: If %TRUE the file entry is created if it doesn't exist. *	@is_new: If the returned entry was newly made, %TRUE is written here. If * 		this is %NULL nothing is written here. *	@traverse_symlink: If %TRUE then symbolic links are traversed. * *	If the entry is created, then it will be in the unregistered state. *	Returns a pointer to the entry on success, else %NULL. */static struct devfs_entry *search_for_entry (struct devfs_entry *dir,					     const char *name,					     unsigned int namelen, int mkdir,					     int mkfile, int *is_new,					     int traverse_symlink){    int len;    const char *subname, *stop, *ptr;    struct devfs_entry *entry;    if (is_new) *is_new = FALSE;    if (dir == NULL) dir = get_root_entry ();    if (dir == NULL) return NULL;    /*  Extract one filename component  */    subname = name;    stop = name + namelen;    while (subname < stop)    {	/*  Search for a possible '/'  */	for (ptr = subname; (ptr < stop) && (*ptr != '/'); ++ptr);	if (ptr >= stop)	{	    /*  Look for trailing component  */	    len = stop - subname;	    entry = search_for_entry_in_dir (dir, subname, len,					     traverse_symlink);	    if (entry != NULL) return entry;	    if (!mkfile) return NULL;	    entry = create_entry (dir, subname, len);	    if (entry && is_new) *is_new = TRUE;	    return entry;	}	/*  Found '/': search for directory  */	if (strncmp (subname, "../", 3) == 0)	{	    /*  Going up  */	    dir = dir->parent;	    if (dir == NULL) return NULL;  /*  Cannot escape from devfs  */	    subname += 3;	    continue;	}	len = ptr - subname;	entry = search_for_entry_in_dir (dir, subname, len, traverse_symlink);	if (!entry && !mkdir) return NULL;	if (entry == NULL)	{	    /*  Make it  */	    if ( ( entry = create_entry (dir, subname, len) ) == NULL )		return NULL;	    entry->mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;	    if (is_new) *is_new = TRUE;	}	if ( !S_ISDIR (entry->mode) )	{	    printk ("%s: existing non-directory entry\n", DEVFS_NAME);	    return NULL;	}	/*  Ensure an unregistered entry is re-registered and visible  */	entry->registered = TRUE;	entry->hide = FALSE;	subname = ptr + 1;	dir = entry;    }    return NULL;}   /*  End Function search_for_entry  *//** *	find_by_dev - Find a devfs entry in a directory. *	@dir: The directory where to search *	@major: The major number to search for. *	@minor: The minor number to search for. *	@type: The type of special file to search for. This may be either *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK. * *	Returns the devfs_entry pointer on success, else %NULL. */static struct devfs_entry *find_by_dev (struct devfs_entry *dir,					unsigned int major, unsigned int minor,					char type){    struct devfs_entry *entry, *de;    if (dir == NULL) return NULL;    if ( !S_ISDIR (dir->mode) )    {	printk ("%s: find_by_dev(): not a directory\n", DEVFS_NAME);	return NULL;    }    /*  First search files in this directory  */    for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)    {	if ( !S_ISCHR (entry->mode) && !S_ISBLK (entry->mode) ) continue;	if ( S_ISCHR (entry->mode) && (type != DEVFS_SPECIAL_CHR) ) continue;	if ( S_ISBLK (entry->mode) && (type != DEVFS_SPECIAL_BLK) ) continue;	if ( (entry->u.fcb.u.device.major == major) &&	     (entry->u.fcb.u.device.minor == minor) ) return entry;	/*  Not found: try the next one  */    }    /*  Now recursively search the subdirectories: this is a stack chomper  */    for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)    {	if ( !S_ISDIR (entry->mode) ) continue;	de = find_by_dev (entry, major, minor, type);	if (de) return de;    }    return NULL;}   /*  End Function find_by_dev  *//** *	find_entry - Find a devfs entry. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		name is relative to the root of the devfs. *	@name: The name of the entry. This is ignored if @handle is not %NULL. *	@namelen: The number of characters in @name, not including a %NULL *		terminator. If this is 0, then @name must be %NULL-terminated and the *		length is computed internally. *	@major: The major number. This is used if @handle and @name are %NULL. *	@minor: The minor number. This is used if @handle and @name are %NULL. *		NOTE: If @major and @minor are both 0, searching by major and minor *		numbers is disabled. *	@type: The type of special file to search for. This may be either *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK. *	@traverse_symlink: If %TRUE then symbolic links are traversed. * *	FIXME: What the hell is @handle? - ch *	Returns the devfs_entry pointer on success, else %NULL. */static struct devfs_entry *find_entry (devfs_handle_t dir,				       const char *name, unsigned int namelen,				       unsigned int major, unsigned int minor,				       char type, int traverse_symlink){    struct devfs_entry *entry;    if (name != NULL)    {	if (namelen < 1) namelen = strlen (name);	if (name[0] == '/')	{	    /*  Skip leading pathname component  */	    if (namelen < 2)	    {		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);		return NULL;	    }	    for (++name, --namelen; (*name != '/') && (namelen > 0);		 ++name, --namelen);	    if (namelen < 2)	    {		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);		return NULL;	    }	    ++name;	    --namelen;	}	entry = search_for_entry (dir, name, namelen, FALSE, FALSE, NULL,				  traverse_symlink);	if (entry != NULL) return entry;    }    /*  Have to search by major and minor: slow  */    if ( (major == 0) && (minor == 0) ) return NULL;    return find_by_dev (root_entry, major, minor, type);}   /*  End Function find_entry  */static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode){    struct fs_info *fs_info;    if (inode == NULL) return NULL;    if (inode->i_ino < FIRST_INODE) return NULL;    fs_info = inode->i_sb->u.generic_sbp;    if (fs_info == NULL) return NULL;    if (inode->i_ino - FIRST_INODE >= fs_info->num_inodes) return NULL;    return fs_info->table[inode->i_ino - FIRST_INODE];}   /*  End Function get_devfs_entry_from_vfs_inode  *//** *	free_dentries - Free the dentries for a device entry and invalidate inodes. *	@de: The entry. */static void free_dentries (struct devfs_entry *de){    struct dentry *dentry;    spin_lock(&dcache_lock);    dentry = de->inode.dentry;    if (dentry != NULL)    {	dget_locked (dentry);	de->inode.dentry = NULL;	spin_unlock(&dcache_lock);	/*  Forcefully remove the inode  */	if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;	d_drop (dentry);	dput (dentry);    } else	spin_unlock(&dcache_lock);}   /*  End Function free_dentries  *//** *	is_devfsd_or_child - Test if the current process is devfsd or one of its children. *	@fs_info: The filesystem information. * *	Returns %TRUE if devfsd or child, else %FALSE. */static int is_devfsd_or_child (struct fs_info *fs_info){    struct task_struct *p;    for (p = current; p != &init_task; p = p->p_opptr)    {	if (p == fs_info->devfsd_task) return (TRUE);    }    return (FALSE);}   /*  End Function is_devfsd_or_child  *//** *	devfsd_queue_empty - Test if devfsd has work pending in its event queue. *	@fs_info: The filesystem information. * *	Returns %TRUE if the queue is empty, else %FALSE. */static inline int devfsd_queue_empty (struct fs_info *fs_info){    return (fs_info->devfsd_buf_out == fs_info->devfsd_buf_in) ? TRUE : FALSE;}   /*  End Function devfsd_queue_empty  *//** *	wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue. *	@fs_info: The filesystem information. * *	Returns %TRUE if no more waiting will be required, else %FALSE. */static int wait_for_devfsd_finished (struct fs_info *fs_info){    DECLARE_WAITQUEUE (wait, current);    if (fs_info->devfsd_task == NULL) return (TRUE);    if (devfsd_queue_empty (fs_info) && fs_info->devfsd_sleeping) return TRUE;    if ( is_devfsd_or_child (fs_info) ) return (FALSE);    add_wait_queue (&fs_info->revalidate_wait_queue, &wait);    current->state = TASK_UNINTERRUPTIBLE;    if (!devfsd_queue_empty (fs_info) || !fs_info->devfsd_sleeping)	if (fs_info->devfsd_task) schedule();    remove_wait_queue (&fs_info->revalidate_wait_queue, &wait);    current->state = TASK_RUNNING;    return (TRUE);}   /*  End Function wait_for_devfsd_finished  *//** *	devfsd_notify_one - Notify a single devfsd daemon of a change. *	@data: Data to be passed. *	@type: The type of change. *	@mode: The mode of the entry. *	@uid: The user ID. *	@gid: The group ID. *	@fs_info: The filesystem info. * *	Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. */static int devfsd_notify_one (void *data, unsigned int type, umode_t mode,			      uid_t uid, gid_t gid, struct fs_info *fs_info){    unsigned int next_pos;    unsigned long flags;    struct devfsd_buf_entry *entry;    static spinlock_t lock = SPIN_LOCK_UNLOCKED;    if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE);    next_pos = fs_info->devfsd_buf_in + 1;    if (next_pos >= devfsd_buf_size) next_pos = 0;    if (next_pos == fs_info->devfsd_buf_out)    {	/*  Running up the arse of the reader: drop it  */	atomic_inc (&fs_info->devfsd_overrun_count);	return (FALSE);    }    spin_lock_irqsave (&lock, flags);

⌨️ 快捷键说明

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