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

📄 dir.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 link_adjust = 0;        int error;	ENTRY;	coda_vfs_stat.rename++;        CDEBUG(D_INODE, "old: %s, (%d length), new: %s"	       "(%d length). old:d_count: %d, new:d_count: %d\n", 	       old_name, old_length, new_name, new_length,	       atomic_read(&old_dentry->d_count), atomic_read(&new_dentry->d_count));        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) )                        	link_adjust = 1;                        coda_dir_changed(old_dir, -link_adjust);                        coda_dir_changed(new_dir,  link_adjust);			coda_flag_inode(new_dentry->d_inode, C_VATTR);		} else {			coda_flag_inode(old_dir, C_VATTR);			coda_flag_inode(new_dir, C_VATTR);                }	}	CDEBUG(D_INODE, "result %d\n", error); 	EXIT;	return error;}/* file operations for directories */int coda_readdir(struct file *file, void *dirent,  filldir_t filldir){        int result = 0;        struct file open_file;	struct dentry open_dentry;	struct inode *inode=file->f_dentry->d_inode, *container;        ENTRY;	coda_vfs_stat.readdir++;        if ( inode->i_mapping == &inode->i_data ) {                CDEBUG(D_FILE, "no container inode.\n");                return -EIO;        }	container = inode->i_mapping->host;	coda_prepare_fakefile(inode, file, container, &open_file, &open_dentry);        if ( S_ISREG(container->i_mode) ) {                /* Venus: we must read Venus dirents from the file */                result = coda_venus_readdir(&open_file, dirent, filldir);        } else {		/* potemkin case: we are handed a directory inode */                result = vfs_readdir(&open_file, filldir, dirent);        }	/* we only have to restore the file position (and f_version?) */	file->f_pos = open_file.f_pos;	file->f_version = open_file.f_version;        EXIT;	return result;}/* grab the ext2 inode of the container file */static int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind){        struct super_block *sbptr;        sbptr = get_super(dev);        if ( !sbptr ) {                printk("coda_inode_grab: coda_find_super returns NULL.\n");                return -ENXIO;        }                        *ind = NULL;        *ind = iget(sbptr, ino);        if ( *ind == NULL ) {		printk("coda_inode_grab: iget(dev: %d, ino: %ld) "		       "returns NULL.\n", dev, (long)ino);                return -ENOENT;        }	CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);        return 0;}/* ask venus to cache the file and return the inode of the container file,   put this inode pointer in the cnode for future read/writes */int coda_open(struct inode *i, struct file *f){        ino_t ino;	dev_t dev;        int error = 0;        struct inode *cont_inode = NULL, *old_container;        unsigned short flags = f->f_flags & (~O_EXCL);	unsigned short coda_flags = coda_flags_to_cflags(flags);	struct coda_cred *cred;        struct coda_inode_info *cii;	lock_kernel();        ENTRY;	coda_vfs_stat.open++;        CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 	       f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags);	error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &ino, &dev); 	if (error) {	        CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",		       dev, (long)ino, error);		unlock_kernel();		return error;	}        /* coda_upcall returns ino number of cached object, get inode */        CDEBUG(D_FILE, "cache file dev %d, ino %ld\n", dev, (long)ino);	error = coda_inode_grab(dev, ino, &cont_inode);		if ( error || !cont_inode ){		printk("coda_open: coda_inode_grab error %d.", error);		if (cont_inode) 			iput(cont_inode);		unlock_kernel();		return error;	}	CODA_ALLOC(cred, struct coda_cred *, sizeof(*cred));	coda_load_creds(cred);	f->private_data = cred;	if ( i->i_mapping != &i->i_data ) {		old_container = i->i_mapping->host;		i->i_mapping = &i->i_data;		iput(old_container);	}	i->i_mapping = cont_inode->i_mapping;        cii = ITOC(i);        cii->c_contcount++;	CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", 	       error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino);	CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", 	       cont_inode->i_ino, atomic_read(&cont_inode->i_count),               cont_inode->i_op);        EXIT;	unlock_kernel();        return 0;}int coda_release(struct inode *i, struct file *f){	struct inode *container = NULL;	int error = 0;        unsigned short flags = (f->f_flags) & (~O_EXCL);	unsigned short cflags = coda_flags_to_cflags(flags);	struct coda_cred *cred;        struct coda_inode_info *cii;	lock_kernel();        ENTRY;	coda_vfs_stat.release++;	cred = (struct coda_cred *)f->private_data;	if (i->i_mapping != &i->i_data)		container = i->i_mapping->host;        cii = ITOC(i);        CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d, cc %d) cache (ino %ld, ct %d)\n",		i->i_ino, atomic_read(&i->i_count), cii->c_contcount,                (container ? container->i_ino : 0),		(container ? atomic_read(&container->i_count) : -99));        if (--cii->c_contcount == 0 && container) {                i->i_mapping = &i->i_data;                iput(container);        }	error = venus_release(i->i_sb, coda_i2f(i), cflags, cred);	f->private_data = NULL;	if (cred)		CODA_FREE(cred, sizeof(*cred));        CDEBUG(D_FILE, "coda_release: result: %d\n", error);	unlock_kernel();        return error;}/* support routines *//* instantiate a fake file and dentry to pass to coda_venus_readdir */static void coda_prepare_fakefile(struct inode *i, struct file *coda_file, 				  struct inode *cont_inode,				  struct file *cont_file,				  struct dentry *cont_dentry){	cont_file->f_dentry = cont_dentry;	cont_file->f_dentry->d_inode = cont_inode;	cont_file->f_pos = coda_file->f_pos;	cont_file->f_version = coda_file->f_version;	cont_file->f_op = cont_inode->i_fop;	return ;}/*  * this structure is manipulated by filldir in vfs layer. * the count holds the remaining amount of space in the getdents buffer, * beyond the current_dir pointer. * * What structure is this comment referring to?? -JH *//* should be big enough to hold any single directory entry */#define DIR_BUFSIZE 2048static int coda_venus_readdir(struct file *filp, void *getdent, 			      filldir_t filldir){        int bufsize;	int offset = filp->f_pos; /* offset in the directory file */	int count = 0;	int pos = 0;      /* offset in the block we read */	int result = 0; /* either an error or # of entries returned */	int errfill;        char *buff = NULL;        struct venus_dirent *vdirent;        int string_offset = (int) (&((struct venus_dirent *)(0))->d_name);	int i;        ENTRY;                CODA_ALLOC(buff, char *, DIR_BUFSIZE);        if ( !buff ) {                 printk("coda_venus_readdir: out of memory.\n");                return -ENOMEM;        }        /* we use this routine to read the file into our buffer */        bufsize = kernel_read(filp, filp->f_pos, buff, DIR_BUFSIZE);        if ( bufsize < 0) {                printk("coda_venus_readdir: cannot read directory %d.\n",		       bufsize);                result = bufsize;                goto exit;        }        if ( bufsize == 0) {                result = 0;                goto exit;        }	        /* Parse and write into user space. Filldir tells us when done! */        CDEBUG(D_FILE, "buffsize: %d offset %d, count %d.\n", 	       bufsize, offset, count);	i = 0;	result = 0;         while ( pos + string_offset < bufsize && i < 1024) {                vdirent = (struct venus_dirent *) (buff + pos);                /* test if the name is fully in the buffer */                if ( pos + string_offset + (int) vdirent->d_namlen >= bufsize ){			if ( result == 0 )				printk("CODA: Invalid directory cfino: %ld\n", 				       filp->f_dentry->d_inode->i_ino);                        break;                }                /* now we are certain that we can read the entry from buff */                /* if we don't have a null entry, copy it */                if ( vdirent->d_fileno && vdirent->d_reclen ) {                        int namlen  = vdirent->d_namlen;                        off_t offs  = filp->f_pos;                         ino_t ino   = vdirent->d_fileno;                        char *name  = vdirent->d_name;			errfill = filldir(getdent,  name, namlen, 					  offs, ino, DT_UNKNOWN); CDEBUG(D_FILE, "entry %d: ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %*s, offset %d, result: %d, errfill: %d.\n", i,vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos,  string_offset, vdirent->d_namlen, vdirent->d_name, (u_int) offs, result, errfill);			/* errfill means no space for filling in this round */			if ( errfill < 0 ) {				result = 0;				break;			}                        /* adjust count */                        result++;                }                /* next one */                filp->f_pos += vdirent->d_reclen;		if ( filp->f_pos > filp->f_dentry->d_inode->i_size )			break; 		if ( !vdirent->d_reclen ) {			printk("CODA: Invalid directory, cfino: %ld\n", 			       filp->f_dentry->d_inode->i_ino);			result = -EINVAL;			break;		}                pos += (unsigned int) vdirent->d_reclen;		i++;        }        if ( i >= 1024 ) {               printk("Repeating too much in readdir %ld\n",                       filp->f_dentry->d_inode->i_ino);               result = -EINVAL;       }exit:        CODA_FREE(buff, DIR_BUFSIZE);        return result;}/* called when a cache lookup succeeds */static int coda_dentry_revalidate(struct dentry *de, int flags){	struct inode *inode = de->d_inode;	struct coda_inode_info *cii;	ENTRY;	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 */		CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",		       de->d_inode->i_ino, coda_f2s(&cii->c_fid));		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) {		CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", 		       dentry->d_parent->d_name.name, dentry->d_name.name,		       dentry->d_inode->i_ino);		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, *container;	struct coda_inode_info *cii = ITOC(inode);	ENTRY;	CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 	       dentry->d_name.len, dentry->d_name.name,	       dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);	lock_kernel();	if ( cii->c_flags == 0 )		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_inode;		/* 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_inode;				if ( cii->c_flags ) 			coda_flag_inode_children(inode, C_FLUSH);				cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);	}ok:	unlock_kernel();	return 0;return_bad_inode:	if ( inode->i_mapping != &inode->i_data ) {		container = inode->i_mapping->host;		inode->i_mapping = &inode->i_data;		iput(container);	}	make_bad_inode(inode);	unlock_kernel();	return -EIO;}

⌨️ 快捷键说明

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