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

📄 nfs4proc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static __be32nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	       struct nfsd4_readlink *readlink){	readlink->rl_rqstp = rqstp;	readlink->rl_fhp = &cstate->current_fh;	return nfs_ok;}static __be32nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	     struct nfsd4_remove *remove){	__be32 status;	if (nfs4_in_grace())		return nfserr_grace;	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,			     remove->rm_name, remove->rm_namelen);	if (status == nfserr_symlink)		return nfserr_notdir;	if (!status) {		fh_unlock(&cstate->current_fh);		set_change_info(&remove->rm_cinfo, &cstate->current_fh);	}	return status;}static __be32nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	     struct nfsd4_rename *rename){	__be32 status = nfserr_nofilehandle;	if (!cstate->save_fh.fh_dentry)		return status;	if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags					& NFSEXP_NOSUBTREECHECK))		return nfserr_grace;	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,			     rename->rn_snamelen, &cstate->current_fh,			     rename->rn_tname, rename->rn_tnamelen);	/* the underlying filesystem returns different error's than required	 * by NFSv4. both save_fh and current_fh have been verified.. */	if (status == nfserr_isdir)		status = nfserr_exist;	else if ((status == nfserr_notdir) &&                  (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&                   S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))		status = nfserr_exist;	else if (status == nfserr_symlink)		status = nfserr_notdir;	if (!status) {		set_change_info(&rename->rn_sinfo, &cstate->current_fh);		set_change_info(&rename->rn_tinfo, &cstate->save_fh);	}	return status;}static __be32nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	      struct nfsd4_secinfo *secinfo){	struct svc_fh resfh;	struct svc_export *exp;	struct dentry *dentry;	__be32 err;	fh_init(&resfh, NFS4_FHSIZE);	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,				    secinfo->si_name, secinfo->si_namelen,				    &exp, &dentry);	if (err)		return err;	if (dentry->d_inode == NULL) {		exp_put(exp);		err = nfserr_noent;	} else		secinfo->si_exp = exp;	dput(dentry);	return err;}static __be32nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	      struct nfsd4_setattr *setattr){	__be32 status = nfs_ok;	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {		nfs4_lock_state();		status = nfs4_preprocess_stateid_op(&cstate->current_fh,			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);		nfs4_unlock_state();		if (status) {			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");			return status;		}	}	status = nfs_ok;	if (setattr->sa_acl != NULL)		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,					    setattr->sa_acl);	if (status)		return status;	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,				0, (time_t)0);	return status;}static __be32nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	    struct nfsd4_write *write){	stateid_t *stateid = &write->wr_stateid;	struct file *filp = NULL;	u32 *p;	__be32 status = nfs_ok;	/* no need to check permission - this will be done in nfsd_write() */	if (write->wr_offset >= OFFSET_MAX)		return nfserr_inval;	nfs4_lock_state();	status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,					CHECK_FH | WR_STATE, &filp);	if (filp)		get_file(filp);	nfs4_unlock_state();	if (status) {		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");		return status;	}	write->wr_bytes_written = write->wr_buflen;	write->wr_how_written = write->wr_stable_how;	p = (u32 *)write->wr_verifier.data;	*p++ = nfssvc_boot.tv_sec;	*p++ = nfssvc_boot.tv_usec;	status =  nfsd_write(rqstp, &cstate->current_fh, filp,			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,			     write->wr_buflen, &write->wr_how_written);	if (filp)		fput(filp);	if (status == nfserr_symlink)		status = nfserr_inval;	return status;}/* This routine never returns NFS_OK!  If there are no other errors, it * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the * attributes matched.  VERIFY is implemented by mapping NFSERR_SAME * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. */static __be32_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	     struct nfsd4_verify *verify){	__be32 *buf, *p;	int count;	__be32 status;	status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);	if (status)		return status;	if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)	    || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))		return nfserr_attrnotsupp;	if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)	    || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))		return nfserr_inval;	if (verify->ve_attrlen & 3)		return nfserr_inval;	/* count in words:	 *   bitmap_len(1) + bitmap(2) + attr_len(1) = 4	 */	count = 4 + (verify->ve_attrlen >> 2);	buf = kmalloc(count << 2, GFP_KERNEL);	if (!buf)		return nfserr_resource;	status = nfsd4_encode_fattr(&cstate->current_fh,				    cstate->current_fh.fh_export,				    cstate->current_fh.fh_dentry, buf,				    &count, verify->ve_bmval,				    rqstp);	/* this means that nfsd4_encode_fattr() ran out of space */	if (status == nfserr_resource && count == 0)		status = nfserr_not_same;	if (status)		goto out_kfree;	p = buf + 3;	status = nfserr_not_same;	if (ntohl(*p++) != verify->ve_attrlen)		goto out_kfree;	if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))		status = nfserr_same;out_kfree:	kfree(buf);	return status;}static __be32nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	      struct nfsd4_verify *verify){	__be32 status;	status = _nfsd4_verify(rqstp, cstate, verify);	return status == nfserr_not_same ? nfs_ok : status;}static __be32nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,	     struct nfsd4_verify *verify){	__be32 status;	status = _nfsd4_verify(rqstp, cstate, verify);	return status == nfserr_same ? nfs_ok : status;}/* * NULL call. */static __be32nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp){	return nfs_ok;}static inline void nfsd4_increment_op_stats(u32 opnum){	if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)		nfsdstats.nfs4_opcount[opnum]++;}static void cstate_free(struct nfsd4_compound_state *cstate){	if (cstate == NULL)		return;	fh_put(&cstate->current_fh);	fh_put(&cstate->save_fh);	BUG_ON(cstate->replay_owner);	kfree(cstate);}static struct nfsd4_compound_state *cstate_alloc(void){	struct nfsd4_compound_state *cstate;	cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);	if (cstate == NULL)		return NULL;	fh_init(&cstate->current_fh, NFS4_FHSIZE);	fh_init(&cstate->save_fh, NFS4_FHSIZE);	cstate->replay_owner = NULL;	return cstate;}typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,			      void *);struct nfsd4_operation {	nfsd4op_func op_func;	u32 op_flags;/* Most ops require a valid current filehandle; a few don't: */#define ALLOWED_WITHOUT_FH 1/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */#define ALLOWED_ON_ABSENT_FS 2};static struct nfsd4_operation nfsd4_ops[];/* * COMPOUND call. */static __be32nfsd4_proc_compound(struct svc_rqst *rqstp,		    struct nfsd4_compoundargs *args,		    struct nfsd4_compoundres *resp){	struct nfsd4_op	*op;	struct nfsd4_operation *opdesc;	struct nfsd4_compound_state *cstate = NULL;	int		slack_bytes;	__be32		status;	status = nfserr_resource;	cstate = cstate_alloc();	if (cstate == NULL)		goto out;	resp->xbuf = &rqstp->rq_res;	resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;	resp->tagp = resp->p;	/* reserve space for: taglen, tag, and opcnt */	resp->p += 2 + XDR_QUADLEN(args->taglen);	resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;	resp->taglen = args->taglen;	resp->tag = args->tag;	resp->opcnt = 0;	resp->rqstp = rqstp;	/*	 * According to RFC3010, this takes precedence over all other errors.	 */	status = nfserr_minor_vers_mismatch;	if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)		goto out;	status = nfs_ok;	while (!status && resp->opcnt < args->opcnt) {		op = &args->ops[resp->opcnt++];		dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);		/*		 * The XDR decode routines may have pre-set op->status;		 * for example, if there is a miscellaneous XDR error		 * it will be set to nfserr_bad_xdr.		 */		if (op->status)			goto encode_op;		/* We must be able to encode a successful response to		 * this operation, with enough room left over to encode a		 * failed response to the next operation.  If we don't		 * have enough room, fail with ERR_RESOURCE.		 */		slack_bytes = (char *)resp->end - (char *)resp->p;		if (slack_bytes < COMPOUND_SLACK_SPACE				+ COMPOUND_ERR_SLACK_SPACE) {			BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);			op->status = nfserr_resource;			goto encode_op;		}		opdesc = &nfsd4_ops[op->opnum];		if (!cstate->current_fh.fh_dentry) {			if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {				op->status = nfserr_nofilehandle;				goto encode_op;			}		} else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&			  !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {			op->status = nfserr_moved;			goto encode_op;		}		if (opdesc->op_func)			op->status = opdesc->op_func(rqstp, cstate, &op->u);		else			BUG_ON(op->status == nfs_ok);encode_op:		if (op->status == nfserr_replay_me) {			op->replay = &cstate->replay_owner->so_replay;			nfsd4_encode_replay(resp, op);			status = op->status = op->replay->rp_status;		} else {			nfsd4_encode_operation(resp, op);			status = op->status;		}		if (cstate->replay_owner) {			nfs4_put_stateowner(cstate->replay_owner);			cstate->replay_owner = NULL;		}		/* XXX Ugh, we need to get rid of this kind of special case: */		if (op->opnum == OP_READ && op->u.read.rd_filp)			fput(op->u.read.rd_filp);		nfsd4_increment_op_stats(op->opnum);	}out:	nfsd4_release_compoundargs(args);	cstate_free(cstate);	return status;}static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {	[OP_ACCESS] = {		.op_func = (nfsd4op_func)nfsd4_access,	},	[OP_CLOSE] = {		.op_func = (nfsd4op_func)nfsd4_close,	},	[OP_COMMIT] = {		.op_func = (nfsd4op_func)nfsd4_commit,	},	[OP_CREATE] = {		.op_func = (nfsd4op_func)nfsd4_create,	},	[OP_DELEGRETURN] = {		.op_func = (nfsd4op_func)nfsd4_delegreturn,	},	[OP_GETATTR] = {		.op_func = (nfsd4op_func)nfsd4_getattr,		.op_flags = ALLOWED_ON_ABSENT_FS,	},	[OP_GETFH] = {		.op_func = (nfsd4op_func)nfsd4_getfh,	},	[OP_LINK] = {		.op_func = (nfsd4op_func)nfsd4_link,	},	[OP_LOCK] = {		.op_func = (nfsd4op_func)nfsd4_lock,	},	[OP_LOCKT] = {		.op_func = (nfsd4op_func)nfsd4_lockt,	},	[OP_LOCKU] = {		.op_func = (nfsd4op_func)nfsd4_locku,	},	[OP_LOOKUP] = {		.op_func = (nfsd4op_func)nfsd4_lookup,	},	[OP_LOOKUPP] = {		.op_func = (nfsd4op_func)nfsd4_lookupp,	},	[OP_NVERIFY] = {		.op_func = (nfsd4op_func)nfsd4_nverify,	},	[OP_OPEN] = {		.op_func = (nfsd4op_func)nfsd4_open,	},	[OP_OPEN_CONFIRM] = {		.op_func = (nfsd4op_func)nfsd4_open_confirm,	},	[OP_OPEN_DOWNGRADE] = {		.op_func = (nfsd4op_func)nfsd4_open_downgrade,	},	[OP_PUTFH] = {		.op_func = (nfsd4op_func)nfsd4_putfh,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_PUTPUBFH] = {		/* unsupported; just for future reference: */		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_PUTROOTFH] = {		.op_func = (nfsd4op_func)nfsd4_putrootfh,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_READ] = {		.op_func = (nfsd4op_func)nfsd4_read,	},	[OP_READDIR] = {		.op_func = (nfsd4op_func)nfsd4_readdir,	},	[OP_READLINK] = {		.op_func = (nfsd4op_func)nfsd4_readlink,	},	[OP_REMOVE] = {		.op_func = (nfsd4op_func)nfsd4_remove,	},	[OP_RENAME] = {		.op_func = (nfsd4op_func)nfsd4_rename,	},	[OP_RENEW] = {		.op_func = (nfsd4op_func)nfsd4_renew,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_RESTOREFH] = {		.op_func = (nfsd4op_func)nfsd4_restorefh,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_SAVEFH] = {		.op_func = (nfsd4op_func)nfsd4_savefh,	},	[OP_SECINFO] = {		.op_func = (nfsd4op_func)nfsd4_secinfo,	},	[OP_SETATTR] = {		.op_func = (nfsd4op_func)nfsd4_setattr,	},	[OP_SETCLIENTID] = {		.op_func = (nfsd4op_func)nfsd4_setclientid,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_SETCLIENTID_CONFIRM] = {		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},	[OP_VERIFY] = {		.op_func = (nfsd4op_func)nfsd4_verify,	},	[OP_WRITE] = {		.op_func = (nfsd4op_func)nfsd4_write,	},	[OP_RELEASE_LOCKOWNER] = {		.op_func = (nfsd4op_func)nfsd4_release_lockowner,		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,	},};#define nfs4svc_decode_voidargs		NULL#define nfs4svc_release_void		NULL#define nfsd4_voidres			nfsd4_voidargs#define nfs4svc_release_compound	NULLstruct nfsd4_voidargs { int dummy; };#define PROC(name, argt, rest, relt, cache, respsize)	\ { (svc_procfunc) nfsd4_proc_##name,		\   (kxdrproc_t) nfs4svc_decode_##argt##args,	\   (kxdrproc_t) nfs4svc_encode_##rest##res,	\   (kxdrproc_t) nfs4svc_release_##relt,		\   sizeof(struct nfsd4_##argt##args),		\   sizeof(struct nfsd4_##rest##res),		\   0,						\   cache,					\   respsize,					\ }/* * TODO: At the present time, the NFSv4 server does not do XID caching * of requests.  Implementing XID caching would not be a serious problem, * although it would require a mild change in interfaces since one * doesn't know whether an NFSv4 request is idempotent until after the * XDR decode.  However, XID caching totally confuses pynfs (Peter * Astrand's regression testsuite for NFSv4 servers), which reuses * XID's liberally, so I've left it unimplemented until pynfs generates * better XID's. */static struct svc_procedure		nfsd_procedures4[2] = {  PROC(null,	 void,		void,		void,	  RC_NOCACHE, 1),  PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE/4)};struct svc_version	nfsd_version4 = {		.vs_vers	= 4,		.vs_nproc	= 2,		.vs_proc	= nfsd_procedures4,		.vs_dispatch	= nfsd_dispatch,		.vs_xdrsize	= NFS4_SVC_XDRSIZE,};/* * Local variables: *  c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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