Beispiel #1
0
/*
 * finish off updating the recorded status of a file
 * - starts callback expiry timer
 * - adds to server's callback list
 */
void afs_vnode_finalise_status_update(afs_vnode_t *vnode, afs_server_t *server, int ret)
{
	afs_server_t *oldserver = NULL;

	_enter("%p,%p,%d",vnode,server,ret);

	spin_lock(&vnode->lock);

	vnode->flags &= ~AFS_VNODE_CHANGED;

	if (ret==0) {
		/* adjust the callback timeout appropriately */
		afs_kafstimod_add_timer(&vnode->cb_timeout,vnode->cb_expiry*HZ);

		spin_lock(&afs_cb_hash_lock);
		list_del(&vnode->cb_hash_link);
		list_add_tail(&vnode->cb_hash_link,&afs_cb_hash(server,&vnode->fid));
		spin_unlock(&afs_cb_hash_lock);

		/* swap ref to old callback server with that for new callback server */
		oldserver = xchg(&vnode->cb_server,server);
		if (oldserver!=server) {
			if (oldserver) {
				spin_lock(&oldserver->cb_lock);
				list_del_init(&vnode->cb_link);
				spin_unlock(&oldserver->cb_lock);
			}

			afs_get_server(server);
			spin_lock(&server->cb_lock);
			list_add_tail(&vnode->cb_link,&server->cb_promises);
			spin_unlock(&server->cb_lock);
		}
		else {
			/* same server */
			oldserver = NULL;
		}
	}
	else if (ret==-ENOENT) {
		/* the file was deleted - clear the callback timeout */
		oldserver = xchg(&vnode->cb_server,NULL);
		afs_kafstimod_del_timer(&vnode->cb_timeout);

		_debug("got NOENT from server - marking file deleted");
		vnode->flags |= AFS_VNODE_DELETED;
	}

	vnode->update_cnt--;

	spin_unlock(&vnode->lock);

	wake_up_all(&vnode->update_waitq);

	afs_put_server(oldserver);

	_leave("");

} /* end afs_vnode_finalise_status_update() */
Beispiel #2
0
/*
 * insert a vnode into the backing server's vnode tree
 */
static void afs_install_vnode(struct afs_vnode *vnode,
			      struct afs_server *server)
{
	struct afs_server *old_server = vnode->server;
	struct afs_vnode *xvnode;
	struct rb_node *parent, **p;

	_enter("%p,%p", vnode, server);

	if (old_server) {
		spin_lock(&old_server->fs_lock);
		rb_erase(&vnode->server_rb, &old_server->fs_vnodes);
		spin_unlock(&old_server->fs_lock);
	}

	afs_get_server(server);
	vnode->server = server;
	afs_put_server(old_server);

	/* insert into the server's vnode tree in FID order */
	spin_lock(&server->fs_lock);

	parent = NULL;
	p = &server->fs_vnodes.rb_node;
	while (*p) {
		parent = *p;
		xvnode = rb_entry(parent, struct afs_vnode, server_rb);
		if (vnode->fid.vid < xvnode->fid.vid)
			p = &(*p)->rb_left;
		else if (vnode->fid.vid > xvnode->fid.vid)
			p = &(*p)->rb_right;
		else if (vnode->fid.vnode < xvnode->fid.vnode)
			p = &(*p)->rb_left;
		else if (vnode->fid.vnode > xvnode->fid.vnode)
			p = &(*p)->rb_right;
		else if (vnode->fid.unique < xvnode->fid.unique)
			p = &(*p)->rb_left;
		else if (vnode->fid.unique > xvnode->fid.unique)
			p = &(*p)->rb_right;
		else
			BUG(); /* can't happen unless afs_iget() malfunctions */
	}

	rb_link_node(&vnode->server_rb, parent, p);
	rb_insert_color(&vnode->server_rb, &server->fs_vnodes);

	spin_unlock(&server->fs_lock);
	_leave("");
}
Beispiel #3
0
/*
 * pick a server to use to try accessing this volume
 * - returns with an elevated usage count on the server chosen
 */
struct afs_server *afs_volume_pick_fileserver(struct afs_vnode *vnode)
{
	struct afs_volume *volume = vnode->volume;
	struct afs_server *server;
	int ret, state, loop;

	_enter("%s", volume->vlocation->vldb.name);

	/* stick with the server we're already using if we can */
	if (vnode->server && vnode->server->fs_state == 0) {
		afs_get_server(vnode->server);
		_leave(" = %p [current]", vnode->server);
		return vnode->server;
	}

	down_read(&volume->server_sem);

	/* handle the no-server case */
	if (volume->nservers == 0) {
		ret = volume->rjservers ? -ENOMEDIUM : -ESTALE;
		up_read(&volume->server_sem);
		_leave(" = %d [no servers]", ret);
		return ERR_PTR(ret);
	}

	/* basically, just search the list for the first live server and use
	 * that */
	ret = 0;
	for (loop = 0; loop < volume->nservers; loop++) {
		server = volume->servers[loop];
		state = server->fs_state;

		_debug("consider %d [%d]", loop, state);

		switch (state) {
			/* found an apparently healthy server */
		case 0:
			afs_get_server(server);
			up_read(&volume->server_sem);
			_leave(" = %p (picked %08x)",
			       server, ntohl(server->addr.s_addr));
			return server;

		case -ENETUNREACH:
			if (ret == 0)
				ret = state;
			break;

		case -EHOSTUNREACH:
			if (ret == 0 ||
			    ret == -ENETUNREACH)
				ret = state;
			break;

		case -ECONNREFUSED:
			if (ret == 0 ||
			    ret == -ENETUNREACH ||
			    ret == -EHOSTUNREACH)
				ret = state;
			break;

		default:
		case -EREMOTEIO:
			if (ret == 0 ||
			    ret == -ENETUNREACH ||
			    ret == -EHOSTUNREACH ||
			    ret == -ECONNREFUSED)
				ret = state;
			break;
		}
	}

	/* no available servers
	 * - TODO: handle the no active servers case better
	 */
	up_read(&volume->server_sem);
	_leave(" = %d", ret);
	return ERR_PTR(ret);
}