dir.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 667 行 · 第 1/2 页

C
667
字号
	int ret;	_enter("{%lu},%u,,", dir->i_ino, *fpos);	if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {		_leave(" = -ESTALE");		return -ESTALE;	}	/* round the file position up to the next entry boundary */	*fpos += sizeof(union afs_dirent) - 1;	*fpos &= ~(sizeof(union afs_dirent) - 1);	/* walk through the blocks in sequence */	ret = 0;	while (*fpos < dir->i_size) {		blkoff = *fpos & ~(sizeof(union afs_dir_block) - 1);		/* fetch the appropriate page from the directory */		page = afs_dir_get_page(dir, blkoff / PAGE_SIZE);		if (IS_ERR(page)) {			ret = PTR_ERR(page);			break;		}		limit = blkoff & ~(PAGE_SIZE - 1);		dbuf = page_address(page);		/* deal with the individual blocks stashed on this page */		do {			dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /					       sizeof(union afs_dir_block)];			ret = afs_dir_iterate_block(fpos, dblock, blkoff,						    cookie, filldir);			if (ret != 1) {				afs_dir_put_page(page);				goto out;			}			blkoff += sizeof(union afs_dir_block);		} while (*fpos < dir->i_size && blkoff < limit);		afs_dir_put_page(page);		ret = 0;	} out:	_leave(" = %d", ret);	return ret;} /* end afs_dir_iterate() *//*****************************************************************************//* * read an AFS directory */static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir){	unsigned fpos;	int ret;	_enter("{%Ld,{%lu}}", file->f_pos, file->f_dentry->d_inode->i_ino);	fpos = file->f_pos;	ret = afs_dir_iterate(file->f_dentry->d_inode, &fpos, cookie, filldir);	file->f_pos = fpos;	_leave(" = %d", ret);	return ret;} /* end afs_dir_readdir() *//*****************************************************************************//* * search the directory for a name * - if afs_dir_iterate_block() spots this function, it'll pass the FID *   uniquifier through dtype */static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,				  loff_t fpos, ino_t ino, unsigned dtype){	struct afs_dir_lookup_cookie *cookie = _cookie;	_enter("{%s,%Zu},%s,%u,,%lu,%u",	       cookie->name, cookie->nlen, name, nlen, ino, dtype);	if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {		_leave(" = 0 [no]");		return 0;	}	cookie->fid.vnode = ino;	cookie->fid.unique = dtype;	cookie->found = 1;	_leave(" = -1 [found]");	return -1;} /* end afs_dir_lookup_filldir() *//*****************************************************************************//* * look up an entry in a directory */static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,				     struct nameidata *nd){	struct afs_dir_lookup_cookie cookie;	struct afs_super_info *as;	struct afs_vnode *vnode;	struct inode *inode;	unsigned fpos;	int ret;	_enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name);	/* insanity checks first */	BUG_ON(sizeof(union afs_dir_block) != 2048);	BUG_ON(sizeof(union afs_dirent) != 32);	if (dentry->d_name.len > 255) {		_leave(" = -ENAMETOOLONG");		return ERR_PTR(-ENAMETOOLONG);	}	vnode = AFS_FS_I(dir);	if (vnode->flags & AFS_VNODE_DELETED) {		_leave(" = -ESTALE");		return ERR_PTR(-ESTALE);	}	as = dir->i_sb->s_fs_info;	/* search the directory */	cookie.name	= dentry->d_name.name;	cookie.nlen	= dentry->d_name.len;	cookie.fid.vid	= as->volume->vid;	cookie.found	= 0;	fpos = 0;	ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir);	if (ret < 0) {		_leave(" = %d", ret);		return ERR_PTR(ret);	}	ret = -ENOENT;	if (!cookie.found) {		_leave(" = %d", ret);		return ERR_PTR(ret);	}	/* instantiate the dentry */	ret = afs_iget(dir->i_sb, &cookie.fid, &inode);	if (ret < 0) {		_leave(" = %d", ret);		return ERR_PTR(ret);	}	dentry->d_op = &afs_fs_dentry_operations;	dentry->d_fsdata = (void *) (unsigned long) vnode->status.version;	d_add(dentry, inode);	_leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }",	       cookie.fid.vnode,	       cookie.fid.unique,	       dentry->d_inode->i_ino,	       dentry->d_inode->i_version);	return NULL;} /* end afs_dir_lookup() *//*****************************************************************************//* * check that a dentry lookup hit has found a valid entry * - NOTE! the hit can be a negative hit too, so we can't assume we have an *   inode * (derived from nfs_lookup_revalidate) */static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd){	struct afs_dir_lookup_cookie cookie;	struct dentry *parent;	struct inode *inode, *dir;	unsigned fpos;	int ret;	_enter("{sb=%p n=%s},", dentry->d_sb, dentry->d_name.name);	/* lock down the parent dentry so we can peer at it */	parent = dget_parent(dentry->d_parent);	dir = parent->d_inode;	inode = dentry->d_inode;	/* handle a negative dentry */	if (!inode)		goto out_bad;	/* handle a bad inode */	if (is_bad_inode(inode)) {		printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",		       dentry->d_parent->d_name.name, dentry->d_name.name);		goto out_bad;	}	/* force a full look up if the parent directory changed since last the	 * server was consulted	 * - otherwise this inode must still exist, even if the inode details	 *   themselves have changed	 */	if (AFS_FS_I(dir)->flags & AFS_VNODE_CHANGED)		afs_vnode_fetch_status(AFS_FS_I(dir));	if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {		_debug("%s: parent dir deleted", dentry->d_name.name);		goto out_bad;	}	if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED) {		_debug("%s: file already deleted", dentry->d_name.name);		goto out_bad;	}	if ((unsigned long) dentry->d_fsdata !=	    (unsigned long) AFS_FS_I(dir)->status.version) {		_debug("%s: parent changed %lu -> %u",		       dentry->d_name.name,		       (unsigned long) dentry->d_fsdata,		       (unsigned) AFS_FS_I(dir)->status.version);		/* search the directory for this vnode */		cookie.name	= dentry->d_name.name;		cookie.nlen	= dentry->d_name.len;		cookie.fid.vid	= AFS_FS_I(inode)->volume->vid;		cookie.found	= 0;		fpos = 0;		ret = afs_dir_iterate(dir, &fpos, &cookie,				      afs_dir_lookup_filldir);		if (ret < 0) {			_debug("failed to iterate dir %s: %d",			       parent->d_name.name, ret);			goto out_bad;		}		if (!cookie.found) {			_debug("%s: dirent not found", dentry->d_name.name);			goto not_found;		}		/* if the vnode ID has changed, then the dirent points to a		 * different file */		if (cookie.fid.vnode != AFS_FS_I(inode)->fid.vnode) {			_debug("%s: dirent changed", dentry->d_name.name);			goto not_found;		}		/* if the vnode ID uniqifier has changed, then the file has		 * been deleted */		if (cookie.fid.unique != AFS_FS_I(inode)->fid.unique) {			_debug("%s: file deleted (uq %u -> %u I:%lu)",			       dentry->d_name.name,			       cookie.fid.unique,			       AFS_FS_I(inode)->fid.unique,			       inode->i_version);			spin_lock(&AFS_FS_I(inode)->lock);			AFS_FS_I(inode)->flags |= AFS_VNODE_DELETED;			spin_unlock(&AFS_FS_I(inode)->lock);			invalidate_remote_inode(inode);			goto out_bad;		}		dentry->d_fsdata =			(void *) (unsigned long) AFS_FS_I(dir)->status.version;	} out_valid:	dput(parent);	_leave(" = 1 [valid]");	return 1;	/* the dirent, if it exists, now points to a different vnode */ not_found:	spin_lock(&dentry->d_lock);	dentry->d_flags |= DCACHE_NFSFS_RENAMED;	spin_unlock(&dentry->d_lock); out_bad:	if (inode) {		/* don't unhash if we have submounts */		if (have_submounts(dentry))			goto out_valid;	}	shrink_dcache_parent(dentry);	_debug("dropping dentry %s/%s",	       dentry->d_parent->d_name.name, dentry->d_name.name);	d_drop(dentry);	dput(parent);	_leave(" = 0 [bad]");	return 0;} /* end afs_d_revalidate() *//*****************************************************************************//* * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't * sleep) * - called from dput() when d_count is going to 0. * - return 1 to request dentry be unhashed, 0 otherwise */static int afs_d_delete(struct dentry *dentry){	_enter("%s", dentry->d_name.name);	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)		goto zap;	if (dentry->d_inode) {		if (AFS_FS_I(dentry->d_inode)->flags & AFS_VNODE_DELETED)			goto zap;	}	_leave(" = 0 [keep]");	return 0; zap:	_leave(" = 1 [zap]");	return 1;} /* end afs_d_delete() */

⌨️ 快捷键说明

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