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

📄 dir.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	const char *name = de->d_name.name;	int len = de->d_name.len;	lock_kernel();	error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);	if ( error ) {		unlock_kernel();		return error;	}	coda_dir_update_mtime(dir);	drop_nlink(de->d_inode);	unlock_kernel();	return 0;}int coda_rmdir(struct inode *dir, struct dentry *de){	const char *name = de->d_name.name;	int len = de->d_name.len;	int error;	lock_kernel();	error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);	if (!error) {		/* VFS may delete the child */		if (de->d_inode)		    de->d_inode->i_nlink = 0;		/* fix the link count of the parent */		coda_dir_drop_nlink(dir);		coda_dir_update_mtime(dir);	}	unlock_kernel();	return error;}/* rename */static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,		       struct inode *new_dir, struct dentry *new_dentry){	const char *old_name = old_dentry->d_name.name;	const char *new_name = new_dentry->d_name.name;	int old_length = old_dentry->d_name.len;	int new_length = new_dentry->d_name.len;	int error;	lock_kernel();	error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),			     coda_i2f(new_dir), old_length, new_length,			     (const char *) old_name, (const char *)new_name);	if ( !error ) {		if ( new_dentry->d_inode ) {			if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {				coda_dir_drop_nlink(old_dir);				coda_dir_inc_nlink(new_dir);			}			coda_dir_update_mtime(old_dir);			coda_dir_update_mtime(new_dir);			coda_flag_inode(new_dentry->d_inode, C_VATTR);		} else {			coda_flag_inode(old_dir, C_VATTR);			coda_flag_inode(new_dir, C_VATTR);		}	}	unlock_kernel();	return error;}/* file operations for directories */int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir){	struct coda_file_info *cfi;	struct file *host_file;	int ret;	cfi = CODA_FTOC(coda_file);	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);	host_file = cfi->cfi_container;	if (!host_file->f_op)		return -ENOTDIR;	if (host_file->f_op->readdir)	{		/* potemkin case: we were handed a directory inode.		 * We can't use vfs_readdir because we have to keep the file		 * position in sync between the coda_file and the host_file.		 * and as such we need grab the inode mutex. */		struct inode *host_inode = host_file->f_path.dentry->d_inode;		mutex_lock(&host_inode->i_mutex);		host_file->f_pos = coda_file->f_pos;		ret = -ENOENT;		if (!IS_DEADDIR(host_inode)) {			ret = host_file->f_op->readdir(host_file, buf, filldir);			file_accessed(host_file);		}		coda_file->f_pos = host_file->f_pos;		mutex_unlock(&host_inode->i_mutex);	}	else /* Venus: we must read Venus dirents from a file */		ret = coda_venus_readdir(coda_file, buf, filldir);	return ret;}static inline unsigned int CDT2DT(unsigned char cdt){	unsigned int dt;	switch(cdt) {	case CDT_UNKNOWN: dt = DT_UNKNOWN; break;	case CDT_FIFO:	  dt = DT_FIFO;    break;	case CDT_CHR:	  dt = DT_CHR;     break;	case CDT_DIR:	  dt = DT_DIR;     break;	case CDT_BLK:	  dt = DT_BLK;     break;	case CDT_REG:	  dt = DT_REG;     break;	case CDT_LNK:	  dt = DT_LNK;     break;	case CDT_SOCK:	  dt = DT_SOCK;    break;	case CDT_WHT:	  dt = DT_WHT;     break;	default:	  dt = DT_UNKNOWN; break;	}	return dt;}/* support routines */static int coda_venus_readdir(struct file *coda_file, void *buf,			      filldir_t filldir){	int result = 0; /* # of entries returned */	struct coda_file_info *cfi;	struct coda_inode_info *cii;	struct file *host_file;	struct dentry *de;	struct venus_dirent *vdir;	unsigned long vdir_size =	    (unsigned long)(&((struct venus_dirent *)0)->d_name);	unsigned int type;	struct qstr name;	ino_t ino;	int ret;	cfi = CODA_FTOC(coda_file);	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);	host_file = cfi->cfi_container;	de = coda_file->f_path.dentry;	cii = ITOC(de->d_inode);	vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);	if (!vdir) return -ENOMEM;	if (coda_file->f_pos == 0) {		ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);		if (ret < 0)			goto out;		result++;		coda_file->f_pos++;	}	if (coda_file->f_pos == 1) {		ret = filldir(buf, "..", 2, 1, de->d_parent->d_inode->i_ino, DT_DIR);		if (ret < 0)			goto out;		result++;		coda_file->f_pos++;	}	while (1) {		/* read entries from the directory file */		ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,				  sizeof(*vdir));		if (ret < 0) {			printk(KERN_ERR "coda readdir: read dir %s failed %d\n",			       coda_f2s(&cii->c_fid), ret);			break;		}		if (ret == 0) break; /* end of directory file reached */		/* catch truncated reads */		if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {			printk(KERN_ERR "coda readdir: short read on %s\n",			       coda_f2s(&cii->c_fid));			ret = -EBADF;			break;		}		/* validate whether the directory file actually makes sense */		if (vdir->d_reclen < vdir_size + vdir->d_namlen) {			printk(KERN_ERR "coda readdir: invalid dir %s\n",			       coda_f2s(&cii->c_fid));			ret = -EBADF;			break;		}		name.len = vdir->d_namlen;		name.name = vdir->d_name;		/* Make sure we skip '.' and '..', we already got those */		if (name.name[0] == '.' && (name.len == 1 ||		    (vdir->d_name[1] == '.' && name.len == 2)))			vdir->d_fileno = name.len = 0;		/* skip null entries */		if (vdir->d_fileno && name.len) {			/* try to look up this entry in the dcache, that way			 * userspace doesn't have to worry about breaking			 * getcwd by having mismatched inode numbers for			 * internal volume mountpoints. */			ino = find_inode_number(de, &name);			if (!ino) ino = vdir->d_fileno;			type = CDT2DT(vdir->d_type);			ret = filldir(buf, name.name, name.len,				      coda_file->f_pos, ino, type);			/* failure means no space for filling in this round */			if (ret < 0) break;			result++;		}		/* we'll always have progress because d_reclen is unsigned and		 * we've already established it is non-zero. */		coda_file->f_pos += vdir->d_reclen;	}out:	kfree(vdir);	return result ? result : ret;}/* called when a cache lookup succeeds */static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd){	struct inode *inode = de->d_inode;	struct coda_inode_info *cii;	if (!inode)		return 1;	lock_kernel();	if (coda_isroot(inode))		goto out;	if (is_bad_inode(inode))		goto bad;	cii = ITOC(de->d_inode);	if (!(cii->c_flags & (C_PURGE | C_FLUSH)))		goto out;	shrink_dcache_parent(de);	/* propagate for a flush */	if (cii->c_flags & C_FLUSH) 		coda_flag_inode_children(inode, C_FLUSH);	if (atomic_read(&de->d_count) > 1)		/* pretend it's valid, but don't change the flags */		goto out;	/* clear the flags. */	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);bad:	unlock_kernel();	return 0;out:	unlock_kernel();	return 1;}/* * This is the callback from dput() when d_count is going to 0. * We use this to unhash dentries with bad inodes. */static int coda_dentry_delete(struct dentry * dentry){	int flags;	if (!dentry->d_inode) 		return 0;	flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;	if (is_bad_inode(dentry->d_inode) || flags) {		return 1;	}	return 0;}/* * This is called when we want to check if the inode has * changed on the server.  Coda makes this easy since the * cache manager Venus issues a downcall to the kernel when this  * happens  */int coda_revalidate_inode(struct dentry *dentry){	struct coda_vattr attr;	int error = 0;	int old_mode;	ino_t old_ino;	struct inode *inode = dentry->d_inode;	struct coda_inode_info *cii = ITOC(inode);	lock_kernel();	if ( !cii->c_flags )		goto ok;	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);		if ( error )			goto return_bad;		/* this inode may be lost if:		   - it's ino changed 		   - type changes must be permitted for repair and		   missing mount points.		*/		old_mode = inode->i_mode;		old_ino = inode->i_ino;		coda_vattr_to_iattr(inode, &attr);		if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {			printk("Coda: inode %ld, fid %s changed type!\n",			       inode->i_ino, coda_f2s(&(cii->c_fid)));		}		/* the following can happen when a local fid is replaced 		   with a global one, here we lose and declare the inode bad */		if (inode->i_ino != old_ino)			goto return_bad;				coda_flag_inode_children(inode, C_FLUSH);		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);	}ok:	unlock_kernel();	return 0;return_bad:	unlock_kernel();	return -EIO;}

⌨️ 快捷键说明

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