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

📄 dcache.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 3 页
字号:
	check_lock();	memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); 	old_name = target->d_name.name;	new_name = dentry->d_name.name;	if (old_name == target->d_iname)		old_name = dentry->d_iname;	if (new_name == dentry->d_iname)		new_name = target->d_iname;	target->d_name.name = new_name;	dentry->d_name.name = old_name;}/* * We cannibalize "target" when moving dentry on top of it, * because it's going to be thrown away anyway. We could be more * polite about it, though. * * This forceful removal will result in ugly /proc output if * somebody holds a file open that got deleted due to a rename. * We could be nicer about the deleted file, and let it show * up under the name it got deleted rather than the name that * deleted it. * * Careful with the hash switch. The hash switch depends on * the fact that any list-entry can be a head of the list. * Think about it. */ /** * d_move - move a dentry * @dentry: entry to move * @target: new dentry * * Update the dcache to reflect the move of a file name. Negative * dcache entries should not be moved in this way. */  void d_move(struct dentry * dentry, struct dentry * target){	check_lock();	if (!dentry->d_inode)		printk(KERN_WARNING "VFS: moving negative dcache entry\n");	spin_lock(&dcache_lock);	/* Move the dentry to the target hash queue */	list_del(&dentry->d_hash);	list_add(&dentry->d_hash, &target->d_hash);	/* Unhash the target: dput() will then get rid of it */	list_del_init(&target->d_hash);	list_del(&dentry->d_child);	list_del(&target->d_child);	/* Switch the parents and the names.. */	switch_names(dentry, target);	do_switch(dentry->d_parent, target->d_parent);	do_switch(dentry->d_name.len, target->d_name.len);	do_switch(dentry->d_name.hash, target->d_name.hash);	/* And add them back to the (new) parent lists */	list_add(&target->d_child, &target->d_parent->d_subdirs);	list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);	spin_unlock(&dcache_lock);}/** * d_path - return the path of a dentry * @dentry: dentry to report * @vfsmnt: vfsmnt to which the dentry belongs * @root: root dentry * @rootmnt: vfsmnt to which the root dentry belongs * @buffer: buffer to return value in * @buflen: buffer length * * Convert a dentry into an ASCII path name. If the entry has been deleted * the string " (deleted)" is appended. Note that this is ambiguous. Returns * the buffer. * * "buflen" should be %PAGE_SIZE or more. Caller holds the dcache_lock. */char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,		struct dentry *root, struct vfsmount *rootmnt,		char *buffer, int buflen){	char * end = buffer+buflen;	char * retval;	int namelen;	*--end = '\0';	buflen--;	if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) {		buflen -= 10;		end -= 10;		memcpy(end, " (deleted)", 10);	}	/* Get '/' right */	retval = end-1;	*retval = '/';	for (;;) {		struct dentry * parent;		if (dentry == root && vfsmnt == rootmnt)			break;		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {			/* Global root? */			if (vfsmnt->mnt_parent == vfsmnt)				goto global_root;			dentry = vfsmnt->mnt_mountpoint;			vfsmnt = vfsmnt->mnt_parent;			continue;		}		parent = dentry->d_parent;		namelen = dentry->d_name.len;		buflen -= namelen + 1;		if (buflen < 0)			break;		end -= namelen;		memcpy(end, dentry->d_name.name, namelen);		*--end = '/';		retval = end;		dentry = parent;	}	return retval;global_root:	namelen = dentry->d_name.len;	buflen -= namelen;	if (buflen >= 0) {		retval -= namelen-1;	/* hit the slash */		memcpy(retval, dentry->d_name.name, namelen);	}	return retval;}/* * NOTE! The user-level library version returns a * character pointer. The kernel system call just * returns the length of the buffer filled (which * includes the ending '\0' character), or a negative * error value. So libc would do something like * *	char *getcwd(char * buf, size_t size) *	{ *		int retval; * *		retval = sys_getcwd(buf, size); *		if (retval >= 0) *			return buf; *		errno = -retval; *		return NULL; *	} */asmlinkage long sys_getcwd(char *buf, unsigned long size){	int error;	struct vfsmount *pwdmnt, *rootmnt;	struct dentry *pwd, *root;	char *page = (char *) __get_free_page(GFP_USER);	if (!page)		return -ENOMEM;	read_lock(&current->fs->lock);	pwdmnt = mntget(current->fs->pwdmnt);	pwd = dget(current->fs->pwd);	rootmnt = mntget(current->fs->rootmnt);	root = dget(current->fs->root);	read_unlock(&current->fs->lock);	error = -ENOENT;	/* Has the current directory has been unlinked? */	spin_lock(&dcache_lock);	if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash)) {		unsigned long len;		char * cwd;		cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);		spin_unlock(&dcache_lock);		error = -ERANGE;		len = PAGE_SIZE + page - cwd;		if (len <= size) {			error = len;			if (copy_to_user(buf, cwd, len))				error = -EFAULT;		}	} else		spin_unlock(&dcache_lock);	dput(pwd);	mntput(pwdmnt);	dput(root);	mntput(rootmnt);	free_page((unsigned long) page);	return error;}/* * Test whether new_dentry is a subdirectory of old_dentry. * * Trivially implemented using the dcache structure *//** * is_subdir - is new dentry a subdirectory of old_dentry * @new_dentry: new dentry * @old_dentry: old dentry * * Returns 1 if new_dentry is a subdirectory of the parent (at any depth). * Returns 0 otherwise. */  int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry){	int result;	result = 0;	for (;;) {		if (new_dentry != old_dentry) {			struct dentry * parent = new_dentry->d_parent;			if (parent == new_dentry)				break;			new_dentry = parent;			continue;		}		result = 1;		break;	}	return result;}void d_genocide(struct dentry *root){	struct dentry *this_parent = root;	struct list_head *next;	spin_lock(&dcache_lock);repeat:	next = this_parent->d_subdirs.next;resume:	while (next != &this_parent->d_subdirs) {		struct list_head *tmp = next;		struct dentry *dentry = list_entry(tmp, struct dentry, d_child);		next = tmp->next;		if (d_unhashed(dentry)||!dentry->d_inode)			continue;		if (!list_empty(&dentry->d_subdirs)) {			this_parent = dentry;			goto repeat;		}		atomic_dec(&dentry->d_count);	}	if (this_parent != root) {		next = this_parent->d_child.next; 		atomic_dec(&this_parent->d_count);		this_parent = this_parent->d_parent;		goto resume;	}	spin_unlock(&dcache_lock);}/** * find_inode_number - check for dentry with name * @dir: directory to check * @name: Name to find. * * Check whether a dentry already exists for the given name, * and return the inode number if it has an inode. Otherwise * 0 is returned. * * This routine is used to post-process directory listings for * filesystems using synthetic inode numbers, and is necessary * to keep getcwd() working. */ ino_t find_inode_number(struct dentry *dir, struct qstr *name){	struct dentry * dentry;	ino_t ino = 0;	/*	 * Check for a fs-specific hash function. Note that we must	 * calculate the standard hash first, as the d_op->d_hash()	 * routine may choose to leave the hash value unchanged.	 */	name->hash = full_name_hash(name->name, name->len);	if (dir->d_op && dir->d_op->d_hash)	{		if (dir->d_op->d_hash(dir, name) != 0)			goto out;	}	dentry = d_lookup(dir, name);	if (dentry)	{		if (dentry->d_inode)			ino = dentry->d_inode->i_ino;		dput(dentry);	}out:	return ino;}static void __init dcache_init(unsigned long mempages){	struct list_head *d;	unsigned long order;	unsigned int nr_hash;	int i;	/* 	 * A constructor could be added for stable state like the lists,	 * but it is probably not worth it because of the cache nature	 * of the dcache. 	 * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN	 * flag could be removed here, to hint to the allocator that	 * it should not try to get multiple page regions.  	 */	dentry_cache = kmem_cache_create("dentry_cache",					 sizeof(struct dentry),					 0,					 SLAB_HWCACHE_ALIGN,					 NULL, NULL);	if (!dentry_cache)		panic("Cannot create dentry cache");#if PAGE_SHIFT < 13	mempages >>= (13 - PAGE_SHIFT);#endif	mempages *= sizeof(struct list_head);	for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)		;	do {		unsigned long tmp;		nr_hash = (1UL << order) * PAGE_SIZE /			sizeof(struct list_head);		d_hash_mask = (nr_hash - 1);		tmp = nr_hash;		d_hash_shift = 0;		while ((tmp >>= 1UL) != 0UL)			d_hash_shift++;		dentry_hashtable = (struct list_head *)			__get_free_pages(GFP_ATOMIC, order);	} while (dentry_hashtable == NULL && --order >= 0);	printk("Dentry-cache hash table entries: %d (order: %ld, %ld bytes)\n",			nr_hash, order, (PAGE_SIZE << order));	if (!dentry_hashtable)		panic("Failed to allocate dcache hash table\n");	d = dentry_hashtable;	i = nr_hash;	do {		INIT_LIST_HEAD(d);		d++;		i--;	} while (i);}static void init_buffer_head(void * foo, kmem_cache_t * cachep, unsigned long flags){	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==	    SLAB_CTOR_CONSTRUCTOR)	{		struct buffer_head * bh = (struct buffer_head *) foo;		memset(bh, 0, sizeof(*bh));		init_waitqueue_head(&bh->b_wait);	}}/* SLAB cache for __getname() consumers */kmem_cache_t *names_cachep;/* SLAB cache for file structures */kmem_cache_t *filp_cachep;/* SLAB cache for dquot structures */kmem_cache_t *dquot_cachep;/* SLAB cache for buffer_head structures */kmem_cache_t *bh_cachep;EXPORT_SYMBOL(bh_cachep);extern void bdev_cache_init(void);extern void cdev_cache_init(void);void __init vfs_caches_init(unsigned long mempages){	bh_cachep = kmem_cache_create("buffer_head",			sizeof(struct buffer_head), 0,			SLAB_HWCACHE_ALIGN, init_buffer_head, NULL);	if(!bh_cachep)		panic("Cannot create buffer head SLAB cache");	names_cachep = kmem_cache_create("names_cache", 			PATH_MAX, 0, 			SLAB_HWCACHE_ALIGN, NULL, NULL);	if (!names_cachep)		panic("Cannot create names SLAB cache");	filp_cachep = kmem_cache_create("filp", 			sizeof(struct file), 0,			SLAB_HWCACHE_ALIGN, NULL, NULL);	if(!filp_cachep)		panic("Cannot create filp SLAB cache");#if defined (CONFIG_QUOTA)	dquot_cachep = kmem_cache_create("dquot", 			sizeof(struct dquot), sizeof(unsigned long) * 4,			SLAB_HWCACHE_ALIGN, NULL, NULL);	if (!dquot_cachep)		panic("Cannot create dquot SLAB cache");#endif	dcache_init(mempages);	inode_init(mempages);	mnt_init(mempages);	bdev_cache_init();	cdev_cache_init();}

⌨️ 快捷键说明

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