示例#1
0
/*
 * `Async' versions of the above service routines. They aren't really,
 * because we send the callback before the reply proper. I hope this
 * doesn't break any clients.
 */
static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp,
		__be32 (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res  *))
{
	struct nlm_host	*host;
	struct nlm_rqst	*call;
	__be32 stat;

	host = nlmsvc_lookup_host(rqstp,
				  argp->lock.caller,
				  argp->lock.len);
	if (host == NULL)
		return rpc_system_err;

	call = nlm_alloc_call(host);
	if (call == NULL)
		return rpc_system_err;

	stat = func(rqstp, argp, &call->a_res);
	if (stat != 0) {
		nlm_release_call(call);
		return stat;
	}

	call->a_flags = RPC_TASK_ASYNC;
	if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0)
		return rpc_system_err;
	return rpc_success;
}
示例#2
0
/*
 * Create a block and initialize it.
 *
 * Note: we explicitly set the cookie of the grant reply to that of
 * the blocked lock request. The spec explicitly mentions that the client
 * should _not_ rely on the callback containing the same cookie as the
 * request, but (as I found out later) that's because some implementations
 * do just this. Never mind the standards comittees, they support our
 * logging industries.
 */
static inline struct nlm_block *
nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
				struct nlm_lock *lock, struct nlm_cookie *cookie)
{
	struct nlm_block	*block;
	struct nlm_host		*host;
	struct nlm_rqst		*call;

	/* Create host handle for callback */
	host = nlmclnt_lookup_host(&rqstp->rq_addr,
				rqstp->rq_prot, rqstp->rq_vers);
	if (host == NULL)
		return NULL;

	/* Allocate memory for block, and initialize arguments */
	if (!(block = (struct nlm_block *) kmalloc(sizeof(*block), GFP_KERNEL)))
		goto failed;
	memset(block, 0, sizeof(*block));
	locks_init_lock(&block->b_call.a_args.lock.fl);
	locks_init_lock(&block->b_call.a_res.lock.fl);

	block->b_host = nlmsvc_lookup_host(rqstp);
	if (block->b_host == NULL) {
		goto failed_free;
	}

	if (!nlmclnt_setgrantargs(&block->b_call, lock))
		goto failed_free;

	/* Set notifier function for VFS, and init args */
	block->b_call.a_args.lock.fl.fl_notify = nlmsvc_notify_blocked;
	block->b_call.a_args.cookie = *cookie;	/* see above */

	dprintk("lockd: created block %p...\n", block);

	/* Create and initialize the block */
	block->b_daemon = rqstp->rq_server;
	block->b_file   = file;

	/* Add to file's list of blocks */
	block->b_fnext  = file->f_blocks;
	file->f_blocks  = block;

	/* Set up RPC arguments for callback */
	call = &block->b_call;
	call->a_host    = host;
	call->a_flags   = RPC_TASK_ASYNC;

	return block;

failed_free:
	kfree(block);
failed:
	nlm_release_host(host);
	return NULL;
}
示例#3
0
/*
 * Obtain client and file from arguments
 */
static u32
nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	u32			error = 0;

	/* nfsd callbacks must have been installed for this procedure */
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	/* Obtain handle for client host */
	if (rqstp->rq_client == NULL) {
		printk(KERN_NOTICE
			"lockd: unauthenticated request from (%08x:%d)\n",
			ntohl(rqstp->rq_addr.sin_addr.s_addr),
			ntohs(rqstp->rq_addr.sin_port));
		return nlm_lck_denied_nolocks;
	}

	/* Obtain host handle */
	if (!(host = nlmsvc_lookup_host(rqstp))
	 || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	/* Obtain file pointer. Not used by FREE_ALL call. */
	if (filp != NULL) {
		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
			goto no_locks;
		*filp = file;

		/* Set up the missing parts of the file_lock structure */
		lock->fl.fl_file  = &file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
	}

	return 0;

no_locks:
	if (host)
		nlm_release_host(host);
 	if (error)
		return error;	
	return nlm_lck_denied_nolocks;
}
示例#4
0
/*
 * Obtain client and file from arguments
 */
static __be32
nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	__be32			error = 0;

	/* nfsd callbacks must have been installed for this procedure */
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	/* Obtain host handle */
	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
	 || (argp->monitor && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	/* Obtain file pointer. Not used by FREE_ALL call. */
	if (filp != NULL) {
		if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
			goto no_locks;
		*filp = file;

		/* Set up the missing parts of the file_lock structure */
		lock->fl.fl_file  = file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
		lock->fl.fl_lmops = &nlmsvc_lock_operations;
	}

	return 0;

no_locks:
	if (host)
		nlm_release_host(host);
 	if (error)
		return error;	
	return nlm_lck_denied_nolocks;
}
示例#5
0
static __be32
nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
			struct nlm_host **hostp, struct nlm_file **filp)
{
	struct nlm_host		*host = NULL;
	struct nlm_file		*file = NULL;
	struct nlm_lock		*lock = &argp->lock;
	__be32			error = 0;

	
	if (!nlmsvc_ops)
		return nlm_lck_denied_nolocks;

	
	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
	 || (argp->monitor && nsm_monitor(host) < 0))
		goto no_locks;
	*hostp = host;

	
	if (filp != NULL) {
		error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
		if (error != 0)
			goto no_locks;
		*filp = file;

		
		lock->fl.fl_file  = file->f_file;
		lock->fl.fl_owner = (fl_owner_t) host;
		lock->fl.fl_lmops = &nlmsvc_lock_operations;
	}

	return 0;

no_locks:
	nlmsvc_release_host(host);
	if (error)
		return error;
	return nlm_lck_denied_nolocks;
}