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

📄 nfs3xdr.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	pglen = rcvbuf->page_len;	recvd = rcvbuf->len - hdrlen;	if (pglen > recvd)		pglen = recvd;	page = rcvbuf->pages;	kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);	end = (u32 *)((char *)p + pglen);	entry = p;	for (nr = 0; *p++; nr++) {		if (p + 3 > end)			goto short_pkt;		p += 2;				/* inode # */		len = ntohl(*p++);		/* string length */		p += XDR_QUADLEN(len) + 2;	/* name + cookie */		if (len > NFS3_MAXNAMLEN) {			printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",						len);			goto err_unmap;		}		if (res->plus) {			/* post_op_attr */			if (p + 2 > end)				goto short_pkt;			if (*p++) {				p += 21;				if (p + 1 > end)					goto short_pkt;			}			/* post_op_fh3 */			if (*p++) {				if (p + 1 > end)					goto short_pkt;				len = ntohl(*p++);				if (len > NFS3_FHSIZE) {					printk(KERN_WARNING "NFS: giant filehandle in "						"readdir (len %x)!\n", len);					goto err_unmap;				}				p += XDR_QUADLEN(len);			}		}		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) {		printk(KERN_NOTICE "NFS: readdir reply truncated!\n");		entry[1] = 1;	}	goto out;err_unmap:	nr = -errno_NFSERR_IO;	goto out;}u32 *nfs3_decode_dirent(u32 *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, u32 *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;}/* * NFS XDR decode functions *//* * Decode attrstat reply. */static intnfs3_xdr_attrstat(struct rpc_rqst *req, u32 *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, u32 *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;}/* * Decode LOOKUP reply */static intnfs3_xdr_lookupres(struct rpc_rqst *req, u32 *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, u32 *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, u32 *p, struct nfs3_readlinkargs *args){	struct rpc_auth *auth = req->rq_task->tk_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, u32 *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(KERN_WARNING "nfs: server returned giant symlink!\n");		return -ENAMETOOLONG;	}	hdrlen = (u8 *) p - (u8 *) iov->iov_base;	if (iov->iov_len < hdrlen) {		printk(KERN_WARNING "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) {		printk(KERN_WARNING "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, u32 *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) {		printk(KERN_WARNING "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) {		printk(KERN_WARNING "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) {		printk(KERN_WARNING "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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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;}#ifndef MAX# define MAX(a, b)	(((a) > (b))? (a) : (b))#endif#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_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,	\	.p_timer     = timer						\	}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,		diropargs,	wccstat, 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		= sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),	.procs			= nfs3_procedures};

⌨️ 快捷键说明

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