示例#1
0
/*
 * attempt to fetch the status of an inode, coelescing multiple simultaneous
 * fetches
 */
static int afs_inode_fetch_status(struct inode *inode)
{
	struct afs_vnode *vnode;
	int ret;

	vnode = AFS_FS_I(inode);

	ret = afs_vnode_fetch_status(vnode);

	if (ret == 0)
		ret = afs_inode_map_status(vnode);

	return ret;

} /* end afs_inode_fetch_status() */
示例#2
0
文件: inode.c 项目: 020gzh/linux
/*
 * inode retrieval
 */
struct inode *afs_iget(struct super_block *sb, struct key *key,
		       struct afs_fid *fid, struct afs_file_status *status,
		       struct afs_callback *cb)
{
	struct afs_iget_data data = { .fid = *fid };
	struct afs_super_info *as;
	struct afs_vnode *vnode;
	struct inode *inode;
	int ret;

	_enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);

	as = sb->s_fs_info;
	data.volume = as->volume;

	inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set,
			     &data);
	if (!inode) {
		_leave(" = -ENOMEM");
		return ERR_PTR(-ENOMEM);
	}

	_debug("GOT INODE %p { vl=%x vn=%x, u=%x }",
	       inode, fid->vid, fid->vnode, fid->unique);

	vnode = AFS_FS_I(inode);

	/* deal with an existing inode */
	if (!(inode->i_state & I_NEW)) {
		_leave(" = %p", inode);
		return inode;
	}

	if (!status) {
		/* it's a remotely extant inode */
		set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
		ret = afs_vnode_fetch_status(vnode, NULL, key);
		if (ret < 0)
			goto bad_inode;
	} else {
		/* it's an inode we just created */
		memcpy(&vnode->status, status, sizeof(vnode->status));

		if (!cb) {
			/* it's a symlink we just created (the fileserver
			 * didn't give us a callback) */
			vnode->cb_version = 0;
			vnode->cb_expiry = 0;
			vnode->cb_type = 0;
			vnode->cb_expires = get_seconds();
		} else {
			vnode->cb_version = cb->version;
			vnode->cb_expiry = cb->expiry;
			vnode->cb_type = cb->type;
			vnode->cb_expires = vnode->cb_expiry + get_seconds();
		}
	}

	/* set up caching before mapping the status, as map-status reads the
	 * first page of symlinks to see if they're really mountpoints */
	inode->i_size = vnode->status.size;
#ifdef CONFIG_AFS_FSCACHE
	vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
					      &afs_vnode_cache_index_def,
					      vnode, true);
#endif

	ret = afs_inode_map_status(vnode, key);
	if (ret < 0)
		goto bad_inode;

	/* success */
	clear_bit(AFS_VNODE_UNSET, &vnode->flags);
	inode->i_flags |= S_NOATIME;
	unlock_new_inode(inode);
	_leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type);
	return inode;

	/* failure */
bad_inode:
#ifdef CONFIG_AFS_FSCACHE
	fscache_relinquish_cookie(vnode->cache, 0);
	vnode->cache = NULL;
#endif
	iget_failed(inode);
	_leave(" = %d [bad]", ret);
	return ERR_PTR(ret);
}