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

📄 nfs4state.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
		spin_unlock(&inode->i_lock);		if (new)			nfs4_free_open_state(new);	}out:	return state;}/* * Beware! Caller must be holding exactly one * reference to clp->cl_sem and owner->so_sema! */void nfs4_put_open_state(struct nfs4_state *state){	struct inode *inode = state->inode;	struct nfs4_state_owner *owner = state->owner;	if (!atomic_dec_and_lock(&state->count, &inode->i_lock))		return;	if (!list_empty(&state->inode_states))		list_del(&state->inode_states);	spin_unlock(&inode->i_lock);	list_del(&state->open_states);	BUG_ON (state->state != 0);	nfs4_free_open_state(state);	nfs4_put_state_owner(owner);}/* * Beware! Caller must be holding no references to clp->cl_sem! * of owner->so_sema! */void nfs4_close_state(struct nfs4_state *state, mode_t mode){	struct inode *inode = state->inode;	struct nfs4_state_owner *owner = state->owner;	struct nfs4_client *clp = owner->so_client;	int newstate;	int status = 0;	atomic_inc(&owner->so_count);	down_read(&clp->cl_sem);	down(&owner->so_sema);	/* Protect against nfs4_find_state() */	spin_lock(&inode->i_lock);	if (mode & FMODE_READ)		state->nreaders--;	if (mode & FMODE_WRITE)		state->nwriters--;	if (state->nwriters == 0 && state->nreaders == 0)		list_del_init(&state->inode_states);	spin_unlock(&inode->i_lock);	newstate = 0;	if (state->state != 0) {		if (state->nreaders)			newstate |= FMODE_READ;		if (state->nwriters)			newstate |= FMODE_WRITE;		if (state->state == newstate)			goto out;		if (newstate != 0)			status = nfs4_do_downgrade(inode, state, newstate);		else			status = nfs4_do_close(inode, state);	}out:	nfs4_put_open_state(state);	up(&owner->so_sema);	nfs4_put_state_owner(owner);	up_read(&clp->cl_sem);}/* * Search the state->lock_states for an existing lock_owner * that is compatible with current->files */static struct nfs4_lock_state *__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner){	struct nfs4_lock_state *pos;	list_for_each_entry(pos, &state->lock_states, ls_locks) {		if (pos->ls_owner != fl_owner)			continue;		atomic_inc(&pos->ls_count);		return pos;	}	return NULL;}struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner){	struct nfs4_lock_state *lsp;	read_lock(&state->state_lock);	lsp = __nfs4_find_lock_state(state, fl_owner);	read_unlock(&state->state_lock);	return lsp;}/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * * The caller must be holding state->lock_sema */static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner){	struct nfs4_lock_state *lsp;	struct nfs4_client *clp = state->owner->so_client;	lsp = kmalloc(sizeof(*lsp), GFP_KERNEL);	if (lsp == NULL)		return NULL;	lsp->ls_flags = 0;	lsp->ls_seqid = 0;	/* arbitrary */	lsp->ls_id = -1; 	memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));	atomic_set(&lsp->ls_count, 1);	lsp->ls_owner = fl_owner;	INIT_LIST_HEAD(&lsp->ls_locks);	spin_lock(&clp->cl_lock);	lsp->ls_id = nfs4_alloc_lockowner_id(clp);	spin_unlock(&clp->cl_lock);	return lsp;}/* * Return a compatible lock_state. If no initialized lock_state structure * exists, return an uninitialized one. * * The caller must be holding state->lock_sema and clp->cl_sem */struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner){	struct nfs4_lock_state * lsp;		lsp = nfs4_find_lock_state(state, owner);	if (lsp == NULL)		lsp = nfs4_alloc_lock_state(state, owner);	return lsp;}/* * Byte-range lock aware utility to initialize the stateid of read/write * requests. */voidnfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner){	if (test_bit(LK_STATE_IN_USE, &state->flags)) {		struct nfs4_lock_state *lsp;		lsp = nfs4_find_lock_state(state, fl_owner);		if (lsp) {			memcpy(dst, &lsp->ls_stateid, sizeof(*dst));			nfs4_put_lock_state(lsp);			return;		}	}	memcpy(dst, &state->stateid, sizeof(*dst));}/** Called with state->lock_sema and clp->cl_sem held.*/void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp){	if (status == NFS_OK || seqid_mutating_err(-status))		lsp->ls_seqid++;}/* * Check to see if the request lock (type FL_UNLK) effects the fl lock.** fl and request must have the same posix owner** return: * 0 -> fl not effected by request* 1 -> fl consumed by request*/static intnfs4_check_unlock(struct file_lock *fl, struct file_lock *request){	if (fl->fl_start >= request->fl_start && fl->fl_end <= request->fl_end)		return 1;	return 0;}/* * Post an initialized lock_state on the state->lock_states list. */void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp){	if (!list_empty(&lsp->ls_locks))		return;	atomic_inc(&lsp->ls_count);	write_lock(&state->state_lock);	list_add(&lsp->ls_locks, &state->lock_states);	set_bit(LK_STATE_IN_USE, &state->flags);	write_unlock(&state->state_lock);}/*  * to decide to 'reap' lock state: * 1) search i_flock for file_locks with fl.lock_state = to ls. * 2) determine if unlock will consume found lock.  * 	if so, reap * * 	else, don't reap. * */voidnfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp){	struct inode *inode = state->inode;	struct file_lock *fl;	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {		if (!(fl->fl_flags & FL_POSIX))			continue;		if (fl->fl_owner != lsp->ls_owner)			continue;		/* Exit if we find at least one lock which is not consumed */		if (nfs4_check_unlock(fl,request) == 0)			return;	}	write_lock(&state->state_lock);	list_del_init(&lsp->ls_locks);	if (list_empty(&state->lock_states))		clear_bit(LK_STATE_IN_USE, &state->flags);	write_unlock(&state->state_lock);	nfs4_put_lock_state(lsp);}/* * Release reference to lock_state, and free it if we see that * it is no longer in use */voidnfs4_put_lock_state(struct nfs4_lock_state *lsp){	if (!atomic_dec_and_test(&lsp->ls_count))		return;	BUG_ON (!list_empty(&lsp->ls_locks));	kfree(lsp);}/** Called with sp->so_sema and clp->cl_sem held.** Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or* failed with a seqid incrementing error -* see comments nfs_fs.h:seqid_mutating_error()*/void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp){	if (status == NFS_OK || seqid_mutating_err(-status))		sp->so_seqid++;	/* If the server returns BAD_SEQID, unhash state_owner here */	if (status == -NFS4ERR_BAD_SEQID)		nfs4_unhash_state_owner(sp);}static int reclaimer(void *);struct reclaimer_args {	struct nfs4_client *clp;	struct completion complete;};/* * State recovery routine */voidnfs4_recover_state(void *data){	struct nfs4_client *clp = (struct nfs4_client *)data;	struct reclaimer_args args = {		.clp = clp,	};	might_sleep();	init_completion(&args.complete);	if (kernel_thread(reclaimer, &args, CLONE_KERNEL) < 0)		goto out_failed_clear;	wait_for_completion(&args.complete);	return;out_failed_clear:	set_bit(NFS4CLNT_OK, &clp->cl_state);	wake_up_all(&clp->cl_waitq);	rpc_wake_up(&clp->cl_rpcwaitq);}/* * Schedule a state recovery attempt */voidnfs4_schedule_state_recovery(struct nfs4_client *clp){	if (!clp)		return;	if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state))		schedule_work(&clp->cl_recoverd);}static int nfs4_reclaim_locks(struct nfs4_state *state){	struct inode *inode = state->inode;	struct file_lock *fl;	int status = 0;	for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {		if (!(fl->fl_flags & FL_POSIX))			continue;		if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)			continue;		status = nfs4_lock_reclaim(state, fl);		if (status >= 0)			continue;		switch (status) {			default:				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",						__FUNCTION__, status);			case -NFS4ERR_EXPIRED:			case -NFS4ERR_NO_GRACE:			case -NFS4ERR_RECLAIM_BAD:			case -NFS4ERR_RECLAIM_CONFLICT:				/* kill_proc(fl->fl_owner, SIGLOST, 1); */				break;			case -NFS4ERR_STALE_CLIENTID:				goto out_err;		}	}	return 0;out_err:	return status;}static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp){	struct nfs4_state *state;	struct nfs4_lock_state *lock;	int status = 0;	list_for_each_entry(state, &sp->so_states, open_states) {		if (state->state == 0)			continue;		status = nfs4_open_reclaim(sp, state);		list_for_each_entry(lock, &state->lock_states, ls_locks)			lock->ls_flags &= ~NFS_LOCK_INITIALIZED;		if (status >= 0) {			status = nfs4_reclaim_locks(state);			if (status < 0)				goto out_err;			list_for_each_entry(lock, &state->lock_states, ls_locks) {				if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))					printk("%s: Lock reclaim failed!\n",							__FUNCTION__);			}			continue;		}		switch (status) {			default:				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",						__FUNCTION__, status);			case -NFS4ERR_EXPIRED:			case -NFS4ERR_NO_GRACE:			case -NFS4ERR_RECLAIM_BAD:			case -NFS4ERR_RECLAIM_CONFLICT:				/*				 * Open state on this file cannot be recovered				 * All we can do is revert to using the zero stateid.				 */				memset(state->stateid.data, 0,					sizeof(state->stateid.data));				/* Mark the file as being 'closed' */				state->state = 0;				break;			case -NFS4ERR_STALE_CLIENTID:				goto out_err;		}	}	return 0;out_err:	return status;}static int reclaimer(void *ptr){	struct reclaimer_args *args = (struct reclaimer_args *)ptr;	struct nfs4_client *clp = args->clp;	struct nfs4_state_owner *sp;	int status = 0;	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));	allow_signal(SIGKILL);	atomic_inc(&clp->cl_count);	complete(&args->complete);	/* Ensure exclusive access to NFSv4 state */	lock_kernel();	down_write(&clp->cl_sem);	/* Are there any NFS mounts out there? */	if (list_empty(&clp->cl_superblocks))		goto out;restart_loop:	status = nfs4_proc_renew(clp);	if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)		goto out;	status = nfs4_init_client(clp);	if (status)		goto out_error;	/* Mark all delagations for reclaim */	nfs_delegation_mark_reclaim(clp);	/* Note: list is protected by exclusive lock on cl->cl_sem */	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {		status = nfs4_reclaim_open_state(sp);		if (status < 0) {			if (status == -NFS4ERR_STALE_CLIENTID)				goto restart_loop;			goto out_error;		}	}	nfs_delegation_reap_unclaimed(clp);out:	set_bit(NFS4CLNT_OK, &clp->cl_state);	up_write(&clp->cl_sem);	unlock_kernel();	wake_up_all(&clp->cl_waitq);	rpc_wake_up(&clp->cl_rpcwaitq);	if (status == -NFS4ERR_CB_PATH_DOWN)		nfs_handle_cb_pathdown(clp);	nfs4_put_client(clp);	return 0;out_error:	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",				NIPQUAD(clp->cl_addr.s_addr), -status);	goto out;}/* * Local variables: *  c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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