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

📄 nfs3xdr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
__be32 *nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus){	struct nfs_entry old = *entry;	if (!*p++) {		if (!*p)			return ERR_PTR(-EAGAIN);		entry->eof = 1;		return ERR_PTR(-EBADCOOKIE);	}	p = xdr_decode_hyper(p, &entry->ino);	entry->len  = ntohl(*p++);	entry->name = (const char *) p;	p += XDR_QUADLEN(entry->len);	entry->prev_cookie = entry->cookie;	p = xdr_decode_hyper(p, &entry->cookie);	if (plus) {		entry->fattr->valid = 0;		p = xdr_decode_post_op_attr(p, entry->fattr);		/* In fact, a post_op_fh3: */		if (*p++) {			p = xdr_decode_fhandle(p, entry->fh);			/* Ugh -- server reply was truncated */			if (p == NULL) {				dprintk("NFS: FH truncated\n");				*entry = old;				return ERR_PTR(-EAGAIN);			}		} else			memset((u8*)(entry->fh), 0, sizeof(*entry->fh));	}	entry->eof = !p[0] && p[1];	return p;}/* * Encode COMMIT arguments */static intnfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args){	p = xdr_encode_fhandle(p, args->fh);	p = xdr_encode_hyper(p, args->offset);	*p++ = htonl(args->count);	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);	return 0;}#ifdef CONFIG_NFS_V3_ACL/* * Encode GETACL arguments */static intnfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,		    struct nfs3_getaclargs *args){	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;	unsigned int replen;	p = xdr_encode_fhandle(p, args->fh);	*p++ = htonl(args->mask);	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);	if (args->mask & (NFS_ACL | NFS_DFACL)) {		/* Inline the page array */		replen = (RPC_REPHDRSIZE + auth->au_rslack +			  ACL3_getaclres_sz) << 2;		xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,				 NFSACL_MAXPAGES << PAGE_SHIFT);	}	return 0;}/* * Encode SETACL arguments */static intnfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,                   struct nfs3_setaclargs *args){	struct xdr_buf *buf = &req->rq_snd_buf;	unsigned int base, len_in_head, len = nfsacl_size(		(args->mask & NFS_ACL)   ? args->acl_access  : NULL,		(args->mask & NFS_DFACL) ? args->acl_default : NULL);	int count, err;	p = xdr_encode_fhandle(p, NFS_FH(args->inode));	*p++ = htonl(args->mask);	base = (char *)p - (char *)buf->head->iov_base;	/* put as much of the acls into head as possible. */	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);	len -= len_in_head;	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));	for (count = 0; (count << PAGE_SHIFT) < len; count++) {		args->pages[count] = alloc_page(GFP_KERNEL);		if (!args->pages[count]) {			while (count)				__free_page(args->pages[--count]);			return -ENOMEM;		}	}	xdr_encode_pages(buf, args->pages, 0, len);	err = nfsacl_encode(buf, base, args->inode,			    (args->mask & NFS_ACL) ?			    args->acl_access : NULL, 1, 0);	if (err > 0)		err = nfsacl_encode(buf, base + err, args->inode,				    (args->mask & NFS_DFACL) ?				    args->acl_default : NULL, 1,				    NFS_ACL_DEFAULT);	return (err > 0) ? 0 : err;}#endif  /* CONFIG_NFS_V3_ACL *//* * NFS XDR decode functions *//* * Decode attrstat reply. */static intnfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr){	int	status;	if ((status = ntohl(*p++)))		return -nfs_stat_to_errno(status);	xdr_decode_fattr(p, fattr);	return 0;}/* * Decode status+wcc_data reply * SATTR, REMOVE, RMDIR */static intnfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr){	int	status;	if ((status = ntohl(*p++)))		status = -nfs_stat_to_errno(status);	xdr_decode_wcc_data(p, fattr);	return status;}static intnfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res){	return nfs3_xdr_wccstat(req, p, &res->dir_attr);}/* * Decode LOOKUP reply */static intnfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res){	int	status;	if ((status = ntohl(*p++))) {		status = -nfs_stat_to_errno(status);	} else {		if (!(p = xdr_decode_fhandle(p, res->fh)))			return -errno_NFSERR_IO;		p = xdr_decode_post_op_attr(p, res->fattr);	}	xdr_decode_post_op_attr(p, res->dir_attr);	return status;}/* * Decode ACCESS reply */static intnfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res){	int	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, res->fattr);	if (status)		return -nfs_stat_to_errno(status);	res->access = ntohl(*p++);	return 0;}static intnfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args){	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;	unsigned int replen;	p = xdr_encode_fhandle(p, args->fh);	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);	/* Inline the page array */	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);	return 0;}/* * Decode READLINK reply */static intnfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr){	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;	struct kvec *iov = rcvbuf->head;	int hdrlen, len, recvd;	char	*kaddr;	int	status;	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	/* Convert length of symlink */	len = ntohl(*p++);	if (len >= rcvbuf->page_len || len <= 0) {		dprintk("nfs: server returned giant symlink!\n");		return -ENAMETOOLONG;	}	hdrlen = (u8 *) p - (u8 *) iov->iov_base;	if (iov->iov_len < hdrlen) {		dprintk("NFS: READLINK reply header overflowed:"				"length %d > %Zu\n", hdrlen, iov->iov_len);		return -errno_NFSERR_IO;	} else if (iov->iov_len != hdrlen) {		dprintk("NFS: READLINK header is short. "			"iovec will be shifted.\n");		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);	}	recvd = req->rq_rcv_buf.len - hdrlen;	if (recvd < len) {		dprintk("NFS: server cheating in readlink reply: "				"count %u > recvd %u\n", len, recvd);		return -EIO;	}	/* NULL terminate the string we got */	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);	kaddr[len+rcvbuf->page_base] = '\0';	kunmap_atomic(kaddr, KM_USER0);	return 0;}/* * Decode READ reply */static intnfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res){	struct kvec *iov = req->rq_rcv_buf.head;	int	status, count, ocount, recvd, hdrlen;	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	/* Decode reply could and EOF flag. NFSv3 is somewhat redundant	 * in that it puts the count both in the res struct and in the	 * opaque data count. */	count    = ntohl(*p++);	res->eof = ntohl(*p++);	ocount   = ntohl(*p++);	if (ocount != count) {		dprintk("NFS: READ count doesn't match RPC opaque count.\n");		return -errno_NFSERR_IO;	}	hdrlen = (u8 *) p - (u8 *) iov->iov_base;	if (iov->iov_len < hdrlen) {		dprintk("NFS: READ reply header overflowed:"				"length %d > %Zu\n", hdrlen, iov->iov_len);       		return -errno_NFSERR_IO;	} else if (iov->iov_len != hdrlen) {		dprintk("NFS: READ header is short. iovec will be shifted.\n");		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);	}	recvd = req->rq_rcv_buf.len - hdrlen;	if (count > recvd) {		dprintk("NFS: server cheating in read reply: "			"count %d > recvd %d\n", count, recvd);		count = recvd;		res->eof = 0;	}	if (count < res->count)		res->count = count;	return count;}/* * Decode WRITE response */static intnfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res){	int	status;	status = ntohl(*p++);	p = xdr_decode_wcc_data(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	res->count = ntohl(*p++);	res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);	res->verf->verifier[0] = *p++;	res->verf->verifier[1] = *p++;	return res->count;}/* * Decode a CREATE response */static intnfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res){	int	status;	status = ntohl(*p++);	if (status == 0) {		if (*p++) {			if (!(p = xdr_decode_fhandle(p, res->fh)))				return -errno_NFSERR_IO;			p = xdr_decode_post_op_attr(p, res->fattr);		} else {			memset(res->fh, 0, sizeof(*res->fh));			/* Do decode post_op_attr but set it to NULL */			p = xdr_decode_post_op_attr(p, res->fattr);			res->fattr->valid = 0;		}	} else {		status = -nfs_stat_to_errno(status);	}	p = xdr_decode_wcc_data(p, res->dir_attr);	return status;}/* * Decode RENAME reply */static intnfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res){	int	status;	if ((status = ntohl(*p++)) != 0)		status = -nfs_stat_to_errno(status);	p = xdr_decode_wcc_data(p, res->fromattr);	p = xdr_decode_wcc_data(p, res->toattr);	return status;}/* * Decode LINK reply */static intnfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res){	int	status;	if ((status = ntohl(*p++)) != 0)		status = -nfs_stat_to_errno(status);	p = xdr_decode_post_op_attr(p, res->fattr);	p = xdr_decode_wcc_data(p, res->dir_attr);	return status;}/* * Decode FSSTAT reply */static intnfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res){	int		status;	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	p = xdr_decode_hyper(p, &res->tbytes);	p = xdr_decode_hyper(p, &res->fbytes);	p = xdr_decode_hyper(p, &res->abytes);	p = xdr_decode_hyper(p, &res->tfiles);	p = xdr_decode_hyper(p, &res->ffiles);	p = xdr_decode_hyper(p, &res->afiles);	/* ignore invarsec */	return 0;}/* * Decode FSINFO reply */static intnfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res){	int		status;	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	res->rtmax  = ntohl(*p++);	res->rtpref = ntohl(*p++);	res->rtmult = ntohl(*p++);	res->wtmax  = ntohl(*p++);	res->wtpref = ntohl(*p++);	res->wtmult = ntohl(*p++);	res->dtpref = ntohl(*p++);	p = xdr_decode_hyper(p, &res->maxfilesize);	/* ignore time_delta and properties */	res->lease_time = 0;	return 0;}/* * Decode PATHCONF reply */static intnfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res){	int		status;	status = ntohl(*p++);	p = xdr_decode_post_op_attr(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	res->max_link = ntohl(*p++);	res->max_namelen = ntohl(*p++);	/* ignore remaining fields */	return 0;}/* * Decode COMMIT reply */static intnfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res){	int		status;	status = ntohl(*p++);	p = xdr_decode_wcc_data(p, res->fattr);	if (status != 0)		return -nfs_stat_to_errno(status);	res->verf->verifier[0] = *p++;	res->verf->verifier[1] = *p++;	return 0;}#ifdef CONFIG_NFS_V3_ACL/* * Decode GETACL reply */static intnfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,		   struct nfs3_getaclres *res){	struct xdr_buf *buf = &req->rq_rcv_buf;	int status = ntohl(*p++);	struct posix_acl **acl;	unsigned int *aclcnt;	int err, base;	if (status != 0)		return -nfs_stat_to_errno(status);	p = xdr_decode_post_op_attr(p, res->fattr);	res->mask = ntohl(*p++);	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))		return -EINVAL;	base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;	acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;	aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;	err = nfsacl_decode(buf, base, aclcnt, acl);	acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;	aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;	if (err > 0)		err = nfsacl_decode(buf, base + err, aclcnt, acl);	return (err > 0) ? 0 : err;}/* * Decode setacl reply. */static intnfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr){	int status = ntohl(*p++);	if (status)		return -nfs_stat_to_errno(status);	xdr_decode_post_op_attr(p, fattr);	return 0;}#endif  /* CONFIG_NFS_V3_ACL */#define PROC(proc, argtype, restype, timer)				\[NFS3PROC_##proc] = {							\	.p_proc      = NFS3PROC_##proc,					\	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\	.p_arglen    = NFS3_##argtype##_sz,				\	.p_replen    = NFS3_##restype##_sz,				\	.p_timer     = timer,						\	.p_statidx   = NFS3PROC_##proc,					\	.p_name      = #proc,						\	}struct rpc_procinfo	nfs3_procedures[] = {  PROC(GETATTR,		fhandle,	attrstat, 1),  PROC(SETATTR, 	sattrargs,	wccstat, 0),  PROC(LOOKUP,		diropargs,	lookupres, 2),  PROC(ACCESS,		accessargs,	accessres, 1),  PROC(READLINK,	readlinkargs,	readlinkres, 3),  PROC(READ,		readargs,	readres, 3),  PROC(WRITE,		writeargs,	writeres, 4),  PROC(CREATE,		createargs,	createres, 0),  PROC(MKDIR,		mkdirargs,	createres, 0),  PROC(SYMLINK,		symlinkargs,	createres, 0),  PROC(MKNOD,		mknodargs,	createres, 0),  PROC(REMOVE,		removeargs,	removeres, 0),  PROC(RMDIR,		diropargs,	wccstat, 0),  PROC(RENAME,		renameargs,	renameres, 0),  PROC(LINK,		linkargs,	linkres, 0),  PROC(READDIR,		readdirargs,	readdirres, 3),  PROC(READDIRPLUS,	readdirargs,	readdirres, 3),  PROC(FSSTAT,		fhandle,	fsstatres, 0),  PROC(FSINFO,  	fhandle,	fsinfores, 0),  PROC(PATHCONF,	fhandle,	pathconfres, 0),  PROC(COMMIT,		commitargs,	commitres, 5),};struct rpc_version		nfs_version3 = {	.number			= 3,	.nrprocs		= ARRAY_SIZE(nfs3_procedures),	.procs			= nfs3_procedures};#ifdef CONFIG_NFS_V3_ACLstatic struct rpc_procinfo	nfs3_acl_procedures[] = {	[ACLPROC3_GETACL] = {		.p_proc = ACLPROC3_GETACL,		.p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,		.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,		.p_arglen = ACL3_getaclargs_sz,		.p_replen = ACL3_getaclres_sz,		.p_timer = 1,		.p_name = "GETACL",	},	[ACLPROC3_SETACL] = {		.p_proc = ACLPROC3_SETACL,		.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,		.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,		.p_arglen = ACL3_setaclargs_sz,		.p_replen = ACL3_setaclres_sz,		.p_timer = 0,		.p_name = "SETACL",	},};struct rpc_version		nfsacl_version3 = {	.number			= 3,	.nrprocs		= sizeof(nfs3_acl_procedures)/				  sizeof(nfs3_acl_procedures[0]),	.procs			= nfs3_acl_procedures,};#endif  /* CONFIG_NFS_V3_ACL */

⌨️ 快捷键说明

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