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

📄 base.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 5 页
字号:
    *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0;    for (; namelen > 0; name += next_pos, namelen -= next_pos)    {	struct devfs_entry *de, *old;	if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL )	{	    de = _devfs_alloc_entry (name, next_pos, MODE_DIR);	    devfs_get (de);	    if ( !de || _devfs_append_entry (dir, de, FALSE, &old) )	    {		devfs_put (de);		if ( !old || !S_ISDIR (old->mode) )		{		    devfs_put (old);		    devfs_put (dir);		    return NULL;		}		de = old;  /*  Use the existing directory  */	    }	}	if (de == dir->parent)	{	    devfs_put (dir);	    devfs_put (de);	    return NULL;	}	devfs_put (dir);	dir = de;	if (name[next_pos] == '/') ++next_pos;    }    return dir;}   /*  End Function _devfs_make_parent_for_leaf  */static devfs_handle_t _devfs_prepare_leaf (devfs_handle_t *dir,					   const char *name, umode_t mode){    int namelen, leaf_pos;    struct devfs_entry *de;    namelen = strlen (name);    if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen,					       &leaf_pos) ) == NULL )    {	PRINTK ("(%s): could not create parent path\n", name);	return NULL;    }    if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) )	 == NULL )    {	PRINTK ("(%s): could not allocate entry\n", name);	devfs_put (*dir);	return NULL;    }    return de;}   /*  End Function _devfs_prepare_leaf  */static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,					const char *name, int namelen,					int traverse_symlink){    int next_pos = 0;    if (dir == NULL) dir = _devfs_get_root_entry ();    if (dir == NULL) return NULL;    devfs_get (dir);    for (; namelen > 0; name += next_pos, namelen -= next_pos)    {	struct devfs_entry *de, *link;	if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL )	{	    devfs_put (dir);	    return NULL;	}	if (S_ISLNK (de->mode) && traverse_symlink)	{   /*  Need to follow the link: this is a stack chomper  */	    link = _devfs_walk_path (dir, de->u.symlink.linkname,				     de->u.symlink.length, TRUE);	    devfs_put (de);	    if (!link)	    {		devfs_put (dir);		return NULL;	    }	    de = link;	}	devfs_put (dir);	dir = de;	if (name[next_pos] == '/') ++next_pos;    }    return dir;}   /*  End Function _devfs_walk_path  *//** *	_devfs_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. An implicit *	devfs_get() is performed. */static struct devfs_entry *_devfs_find_by_dev (struct devfs_entry *dir,					       unsigned int major,					       unsigned int minor, char type){    struct devfs_entry *entry, *de;    devfs_get (dir);    if (dir == NULL) return NULL;    if ( !S_ISDIR (dir->mode) )    {	PRINTK ("(%p): not a directory\n", dir);	devfs_put (dir);	return NULL;    }    /*  First search files in this directory  */    read_lock (&dir->u.dir.lock);    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) )	{	    devfs_get (entry);	    read_unlock (&dir->u.dir.lock);	    devfs_put (dir);	    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 = _devfs_find_by_dev (entry, major, minor, type);	if (de)	{	    read_unlock (&dir->u.dir.lock);	    devfs_put (dir);	    return de;	}    }    read_unlock (&dir->u.dir.lock);    devfs_put (dir);    return NULL;}   /*  End Function _devfs_find_by_dev  *//** *	_devfs_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 may be %NULL. *	@major: The major number. This is used if lookup by @name fails. *	@minor: The minor number. This is used if lookup by @name fails. *		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. * *	Returns the devfs_entry pointer on success, else %NULL. An implicit *	devfs_get() is performed. */static struct devfs_entry *_devfs_find_entry (devfs_handle_t dir,					      const char *name,					      unsigned int major,					      unsigned int minor,					      char type, int traverse_symlink){    struct devfs_entry *entry;    if (name != NULL)    {	unsigned int namelen = strlen (name);	if (name[0] == '/')	{	    /*  Skip leading pathname component  */	    if (namelen < 2)	    {		PRINTK ("(%s): too short\n", name);		return NULL;	    }	    for (++name, --namelen; (*name != '/') && (namelen > 0);		 ++name, --namelen);	    if (namelen < 2)	    {		PRINTK ("(%s): too short\n", name);		return NULL;	    }	    ++name;	    --namelen;	}	entry = _devfs_walk_path (dir, name, namelen, traverse_symlink);	if (entry != NULL) return entry;    }    /*  Have to search by major and minor: slow  */    if ( (major == 0) && (minor == 0) ) return NULL;    return _devfs_find_by_dev (root_entry, major, minor, type);}   /*  End Function _devfs_find_entry  */static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode){    if (inode == NULL) return NULL;    VERIFY_ENTRY ( (struct devfs_entry *) inode->u.generic_ip );    return inode->u.generic_ip;}   /*  End Function get_devfs_entry_from_vfs_inode  *//** *	free_dentry - Free the dentry for a device entry and invalidate inode. *	@de: The entry. * *	This must only be called after the entry has been unhooked from it's *	 parent directory. */static void free_dentry (struct devfs_entry *de){    struct dentry *dentry = de->inode.dentry;    if (!dentry) return;    spin_lock (&dcache_lock);    dget_locked (dentry);    spin_unlock (&dcache_lock);    /*  Forcefully remove the inode  */    if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;    d_drop (dentry);    dput (dentry);}   /*  End Function free_dentry  *//** *	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;    if (current == fs_info->devfsd_task) return (TRUE);    if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)    for (p = current->p_opptr; p != &init_task; p = p->p_opptr)    {	if (p == fs_info->devfsd_task) return (TRUE);    }#endif    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_last_event) ? FALSE : TRUE;}   /*  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_de - Notify the devfsd daemon of a change. *	@de: The devfs entry that has changed. This and all parent entries will *            have their reference counts incremented if the event was queued. *	@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_de (struct devfs_entry *de,			     unsigned short type, umode_t mode,			     uid_t uid, gid_t gid, struct fs_info *fs_info,			     int atomic){    struct devfsd_buf_entry *entry;    struct devfs_entry *curr;    if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE);    if ( ( entry = kmem_cache_alloc (devfsd_buf_cache,				     atomic ? SLAB_ATOMIC : SLAB_KERNEL) )	 == NULL )    {	atomic_inc (&fs_info->devfsd_overrun_count);	return (FALSE);    }    for (curr = de; curr != NULL; curr = curr->parent) devfs_get (curr);    entry->de = de;    entry->type = type;    entry->mode = mode;    entry->uid = uid;    entry->gid = gid;    entry->next = NULL;    spin_lock (&fs_info->devfsd_buffer_lock);    if (!fs_info->devfsd_first_event) fs_info->devfsd_first_event = entry;    if (fs_info->devfsd_last_event) fs_info->devfsd_last_event->next = entry;    fs_info->devfsd_last_event = entry;    spin_unlock (&fs_info->devfsd_buffer_lock);    wake_up_interruptible (&fs_info->devfsd_wait_queue);    return (TRUE);}   /*  End Function devfsd_notify_de  *//** *	devfsd_notify - Notify the devfsd daemon of a change. *	@de: The devfs entry that has changed. *	@type: The type of change event. *	@wait: If TRUE, the function waits for the daemon to finish processing *		the event. */static void devfsd_notify (struct devfs_entry *de,unsigned short type,int wait){    if (devfsd_notify_de (de, type, de->mode, current->euid,			  current->egid, &fs_info, 0) && wait)	wait_for_devfsd_finished (&fs_info);}   /*  End Function devfsd_notify  *//** *	devfs_register - Register a device entry. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		new name is relative to the root of the devfs. *	@name: The name of the entry. *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*). *	@major: The major number. Not needed for regular files. *	@minor: The minor number. Not needed for regular files. *	@mode: The default file mode. *	@ops: The &file_operations or &block_device_operations structure. *		This must not be externally deallocated. *	@info: An arbitrary pointer which will be written to the @private_data *		field of the &file structure passed to the device driver. You can set

⌨️ 快捷键说明

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