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

📄 nfs2xdr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	p = xdr_encode_fhandle(p, args->fromfh);	p = xdr_encode_array(p, args->fromname, args->fromlen);	*p++ = htonl(args->pathlen);	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);	xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);	/*	 * xdr_encode_pages may have added a few bytes to ensure the	 * pathname ends on a 4-byte boundary.  Start encoding the	 * attributes after the pad bytes.	 */	pad = sndbuf->tail->iov_len;	if (pad > 0)		p++;	p = xdr_encode_sattr(p, args->sattr);	sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;	return 0;}/* * Encode arguments to readdir call */static intnfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args){	struct rpc_task	*task = req->rq_task;	struct rpc_auth	*auth = task->tk_msg.rpc_cred->cr_auth;	unsigned int replen;	u32 count = args->count;	p = xdr_encode_fhandle(p, args->fh);	*p++ = htonl(args->cookie);	*p++ = htonl(count); /* see above */	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);	/* Inline the page array */	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);	return 0;}/* * Decode the result of a readdir call. * We're not really decoding anymore, we just leave the buffer untouched * and only check that it is syntactically correct. * The real decoding happens in nfs_decode_entry below, called directly * from nfs_readdir for each entry. */static intnfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy){	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;	struct kvec *iov = rcvbuf->head;	struct page **page;	int hdrlen, recvd;	int status, nr;	unsigned int len, pglen;	__be32 *end, *entry, *kaddr;	if ((status = ntohl(*p++)))		return -nfs_stat_to_errno(status);	hdrlen = (u8 *) p - (u8 *) iov->iov_base;	if (iov->iov_len < hdrlen) {		dprintk("NFS: READDIR reply header overflowed:"				"length %d > %Zu\n", hdrlen, iov->iov_len);		return -errno_NFSERR_IO;	} else if (iov->iov_len != hdrlen) {		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);	}	pglen = rcvbuf->page_len;	recvd = rcvbuf->len - hdrlen;	if (pglen > recvd)		pglen = recvd;	page = rcvbuf->pages;	kaddr = p = kmap_atomic(*page, KM_USER0);	end = (__be32 *)((char *)p + pglen);	entry = p;	for (nr = 0; *p++; nr++) {		if (p + 2 > end)			goto short_pkt;		p++; /* fileid */		len = ntohl(*p++);		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */		if (len > NFS2_MAXNAMLEN) {			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",						len);			goto err_unmap;		}		if (p + 2 > end)			goto short_pkt;		entry = p;	}	if (!nr && (entry[0] != 0 || entry[1] == 0))		goto short_pkt; out:	kunmap_atomic(kaddr, KM_USER0);	return nr; short_pkt:	entry[0] = entry[1] = 0;	/* truncate listing ? */	if (!nr) {		dprintk("NFS: readdir reply truncated!\n");		entry[1] = 1;	}	goto out;err_unmap:	nr = -errno_NFSERR_IO;	goto out;}__be32 *nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus){	if (!*p++) {		if (!*p)			return ERR_PTR(-EAGAIN);		entry->eof = 1;		return ERR_PTR(-EBADCOOKIE);	}	entry->ino	  = ntohl(*p++);	entry->len	  = ntohl(*p++);	entry->name	  = (const char *) p;	p		 += XDR_QUADLEN(entry->len);	entry->prev_cookie	  = entry->cookie;	entry->cookie	  = ntohl(*p++);	entry->eof	  = !p[0] && p[1];	return p;}/* * NFS XDR decode functions *//* * Decode simple status reply */static intnfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy){	int	status;	if ((status = ntohl(*p++)) != 0)		status = -nfs_stat_to_errno(status);	return status;}/* * Decode attrstat reply * GETATTR, SETATTR, WRITE */static intnfs_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 diropres reply * LOOKUP, CREATE, MKDIR */static intnfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res){	int	status;	if ((status = ntohl(*p++)))		return -nfs_stat_to_errno(status);	p = xdr_decode_fhandle(p, res->fh);	xdr_decode_fattr(p, res->fattr);	return 0;}/* * Encode READLINK args */static intnfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_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 + NFS_readlinkres_sz) << 2;	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);	return 0;}/* * Decode READLINK reply */static intnfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy){	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;	struct kvec *iov = rcvbuf->head;	int hdrlen, len, recvd;	char	*kaddr;	int	status;	if ((status = ntohl(*p++)))		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 WRITE reply */static intnfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res){	res->verf->committed = NFS_FILE_SYNC;	return nfs_xdr_attrstat(req, p, res->fattr);}/* * Decode STATFS reply */static intnfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res){	int	status;	if ((status = ntohl(*p++)))		return -nfs_stat_to_errno(status);	res->tsize  = ntohl(*p++);	res->bsize  = ntohl(*p++);	res->blocks = ntohl(*p++);	res->bfree  = ntohl(*p++);	res->bavail = ntohl(*p++);	return 0;}/* * We need to translate between nfs status return values and * the local errno values which may not be the same. */static struct {	int stat;	int errno;} nfs_errtbl[] = {	{ NFS_OK,		0		},	{ NFSERR_PERM,		EPERM		},	{ NFSERR_NOENT,		ENOENT		},	{ NFSERR_IO,		errno_NFSERR_IO	},	{ NFSERR_NXIO,		ENXIO		},/*	{ NFSERR_EAGAIN,	EAGAIN		}, */	{ NFSERR_ACCES,		EACCES		},	{ NFSERR_EXIST,		EEXIST		},	{ NFSERR_XDEV,		EXDEV		},	{ NFSERR_NODEV,		ENODEV		},	{ NFSERR_NOTDIR,	ENOTDIR		},	{ NFSERR_ISDIR,		EISDIR		},	{ NFSERR_INVAL,		EINVAL		},	{ NFSERR_FBIG,		EFBIG		},	{ NFSERR_NOSPC,		ENOSPC		},	{ NFSERR_ROFS,		EROFS		},	{ NFSERR_MLINK,		EMLINK		},	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},	{ NFSERR_DQUOT,		EDQUOT		},	{ NFSERR_STALE,		ESTALE		},	{ NFSERR_REMOTE,	EREMOTE		},#ifdef EWFLUSH	{ NFSERR_WFLUSH,	EWFLUSH		},#endif	{ NFSERR_BADHANDLE,	EBADHANDLE	},	{ NFSERR_NOT_SYNC,	ENOTSYNC	},	{ NFSERR_BAD_COOKIE,	EBADCOOKIE	},	{ NFSERR_NOTSUPP,	ENOTSUPP	},	{ NFSERR_TOOSMALL,	ETOOSMALL	},	{ NFSERR_SERVERFAULT,	ESERVERFAULT	},	{ NFSERR_BADTYPE,	EBADTYPE	},	{ NFSERR_JUKEBOX,	EJUKEBOX	},	{ -1,			EIO		}};/* * Convert an NFS error code to a local one. * This one is used jointly by NFSv2 and NFSv3. */intnfs_stat_to_errno(int stat){	int i;	for (i = 0; nfs_errtbl[i].stat != -1; i++) {		if (nfs_errtbl[i].stat == stat)			return nfs_errtbl[i].errno;	}	dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);	return nfs_errtbl[i].errno;}#define PROC(proc, argtype, restype, timer)				\[NFSPROC_##proc] = {							\	.p_proc	    =  NFSPROC_##proc,					\	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\	.p_arglen   =  NFS_##argtype##_sz,				\	.p_replen   =  NFS_##restype##_sz,				\	.p_timer    =  timer,						\	.p_statidx  =  NFSPROC_##proc,					\	.p_name     =  #proc,						\	}struct rpc_procinfo	nfs_procedures[] = {    PROC(GETATTR,	fhandle,	attrstat, 1),    PROC(SETATTR,	sattrargs,	attrstat, 0),    PROC(LOOKUP,	diropargs,	diropres, 2),    PROC(READLINK,	readlinkargs,	readlinkres, 3),    PROC(READ,		readargs,	readres, 3),    PROC(WRITE,		writeargs,	writeres, 4),    PROC(CREATE,	createargs,	diropres, 0),    PROC(REMOVE,	removeargs,	stat, 0),    PROC(RENAME,	renameargs,	stat, 0),    PROC(LINK,		linkargs,	stat, 0),    PROC(SYMLINK,	symlinkargs,	stat, 0),    PROC(MKDIR,		createargs,	diropres, 0),    PROC(RMDIR,		diropargs,	stat, 0),    PROC(READDIR,	readdirargs,	readdirres, 3),    PROC(STATFS,	fhandle,	statfsres, 0),};struct rpc_version		nfs_version2 = {	.number			= 2,	.nrprocs		= ARRAY_SIZE(nfs_procedures),	.procs			= nfs_procedures};

⌨️ 快捷键说明

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