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

📄 proc.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/nfs/proc.c * *  Copyright (C) 1992, 1993, 1994  Rick Sladkey * *  OS-independent nfs remote procedure call functions * *  Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers *  so at last we can have decent(ish) throughput off a  *  Sun server. * *  Coding optimized and cleaned up by Florian La Roche. *  Note: Error returns are optimized for NFS_OK, which isn't translated via *  nfs_stat_to_errno(), but happens to be already the right return code. * *  FixMe: We ought to define a sensible small max size for *  things like getattr that are tiny packets and use the *  old get_free_page stuff with it. * *  Also, the code currently doesn't check the size of the packet, when *  it decodes the packet. * *  Feel free to fix it and mail me the diffs if it worries you. *//* * Defining NFS_PROC_DEBUG causes a lookup of a file named * "xyzzy" to toggle debugging.  Just cd to an NFS-mounted * filesystem and type 'ls xyzzy' to turn on debugging. */#if 0#define NFS_PROC_DEBUG#endif#include <linux/param.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/malloc.h>#include <linux/nfs_fs.h>#include <linux/utsname.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/in.h>#include <linux/pagemap.h>#include <asm/segment.h>#ifdef NFS_PROC_DEBUGstatic int proc_debug = 0;#define PRINTK(format, args...) \	do {						\		if (proc_debug)				\			printk(format , ## args);	\	} while (0)#else /* !NFS_PROC_DEBUG */#define PRINTK(format, args...) do ; while (0)#endif /* !NFS_PROC_DEBUG *//* Mapping from NFS error code to "errno" error code. */#define errno_NFSERR_IO EIOstatic int *nfs_rpc_header(int *p, int procedure, int ruid);static int *nfs_rpc_verify(int *p);static int nfs_stat_to_errno(int stat);/* * Our memory allocation and release functions. */ #define NFS_SLACK_SPACE		1024	/* Total overkill */ /* !!! Be careful, this constant is now also used in sock.c...   We should easily convert to not using it anymore for most cases... */static inline int *nfs_rpc_alloc(int size){	int *i;	while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_NFS))) {		schedule();	}	return i;}static inline void nfs_rpc_free(int *p){	kfree((void *)p);}/* * Here are a bunch of xdr encode/decode functions that convert * between machine dependent and xdr data formats. */#define QUADLEN(len) (((len) + 3) >> 2)static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle){	*((struct nfs_fh *) p) = *fhandle;	return p + QUADLEN(sizeof(*fhandle));}static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle){	*fhandle = *((struct nfs_fh *) p);	return p + QUADLEN(sizeof(*fhandle));}static inline int *xdr_encode_string(int *p, const char *string){	int len = strlen(string);	int quadlen = QUADLEN(len);	p[quadlen] = 0;	*p++ = htonl(len);	memcpy(p, string, len);	return p + quadlen;}static inline int *xdr_decode_string(int *p, char *string, unsigned int maxlen){	unsigned int len = ntohl(*p++);	if (len > maxlen)		return NULL;	memcpy(string, p, len);	string[len] = '\0';	return p + QUADLEN(len);}static inline int *xdr_decode_string2(int *p, char **string, unsigned int *len,			unsigned int maxlen){	*len = ntohl(*p++);	if (*len > maxlen)		return NULL;	*string = (char *) p;	return p + QUADLEN(*len);}static inline int *xdr_encode_data(int *p, const char *data, int len){	int quadlen = QUADLEN(len);		p[quadlen] = 0;	*p++ = htonl(len);	memcpy_fromfs(p, data, len);	return p + quadlen;}static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen){	unsigned len = *lenp = ntohl(*p++);	if (len > maxlen)		return NULL;	memcpy(data, p, len);	return p + QUADLEN(len);}static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr){	fattr->type = (enum nfs_ftype) ntohl(*p++);	fattr->mode = ntohl(*p++);	fattr->nlink = ntohl(*p++);	fattr->uid = ntohl(*p++);	fattr->gid = ntohl(*p++);	fattr->size = ntohl(*p++);	fattr->blocksize = ntohl(*p++);	fattr->rdev = ntohl(*p++);	fattr->blocks = ntohl(*p++);	fattr->fsid = ntohl(*p++);	fattr->fileid = ntohl(*p++);	fattr->atime.seconds = ntohl(*p++);	fattr->atime.useconds = ntohl(*p++);	fattr->mtime.seconds = ntohl(*p++);	fattr->mtime.useconds = ntohl(*p++);	fattr->ctime.seconds = ntohl(*p++);	fattr->ctime.useconds = ntohl(*p++);	return p;}static int *xdr_encode_sattr(int *p, struct nfs_sattr *sattr){	*p++ = htonl(sattr->mode);	*p++ = htonl(sattr->uid);	*p++ = htonl(sattr->gid);	*p++ = htonl(sattr->size);	*p++ = htonl(sattr->atime.seconds);	*p++ = htonl(sattr->atime.useconds);	*p++ = htonl(sattr->mtime.seconds);	*p++ = htonl(sattr->mtime.useconds);	return p;}static int *xdr_decode_entry(int *p, struct nfs_entry *entry){	entry->fileid = ntohl(*p++);	if (!(p = xdr_decode_string(p, entry->name, NFS_MAXNAMLEN)))		return NULL;	entry->cookie = ntohl(*p++);	entry->eof = 0;	return p;}static int *xdr_decode_fsinfo(int *p, struct nfs_fsinfo *res){	res->tsize = ntohl(*p++);	res->bsize = ntohl(*p++);	res->blocks = ntohl(*p++);	res->bfree = ntohl(*p++);	res->bavail = ntohl(*p++);	return p;}/* * One function for each procedure in the NFS protocol. */int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,		     struct nfs_fattr *fattr){	int *p, *p0;	int status;	int ruid = 0;	PRINTK("NFS call  getattr\n");	if (!(p0 = nfs_rpc_alloc(server->rsize)))		return -EIO;retry:	p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);	p = xdr_encode_fhandle(p, fhandle);	if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {		nfs_rpc_free(p0);		return status;	}	if (!(p = nfs_rpc_verify(p0)))		status = -errno_NFSERR_IO;	else if ((status = ntohl(*p++)) == NFS_OK) {		p = xdr_decode_fattr(p, fattr);		PRINTK("NFS reply getattr\n");		/* status = 0; */	}	else {		if (!ruid && current->fsuid == 0 && current->uid != 0) {			ruid = 1;			goto retry;		}		PRINTK("NFS reply getattr failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	nfs_rpc_free(p0);	return status;}int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,		     struct nfs_sattr *sattr, struct nfs_fattr *fattr){	int *p, *p0;	int status;	int ruid = 0;	PRINTK("NFS call  setattr\n");	if (!(p0 = nfs_rpc_alloc(server->wsize)))		return -EIO;retry:	p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);	p = xdr_encode_fhandle(p, fhandle);	p = xdr_encode_sattr(p, sattr);	if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {		nfs_rpc_free(p0);		return status;	}	if (!(p = nfs_rpc_verify(p0)))		status = -errno_NFSERR_IO;	else if ((status = ntohl(*p++)) == NFS_OK) {		p = xdr_decode_fattr(p, fattr);		PRINTK("NFS reply setattr\n");		/* status = 0; */	}	else {		if (!ruid && current->fsuid == 0 && current->uid != 0) {			ruid = 1;			goto retry;		}		PRINTK("NFS reply setattr failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	nfs_rpc_free(p0);	return status;}int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,		    struct nfs_fh *fhandle, struct nfs_fattr *fattr){	int *p, *p0;	int status;	int ruid = 0;	PRINTK("NFS call  lookup %s\n", name);#ifdef NFS_PROC_DEBUG	if (!strcmp(name, "xyzzy"))		proc_debug = 1 - proc_debug;#endif	if (!(p0 = nfs_rpc_alloc(server->rsize)))		return -EIO;retry:	p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);	p = xdr_encode_fhandle(p, dir);	p = xdr_encode_string(p, name);	if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {		nfs_rpc_free(p0);		return status;	}	if (!(p = nfs_rpc_verify(p0)))		status = -errno_NFSERR_IO;	else if ((status = ntohl(*p++)) == NFS_OK) {		p = xdr_decode_fhandle(p, fhandle);		p = xdr_decode_fattr(p, fattr);		PRINTK("NFS reply lookup\n");		/* status = 0; */	}	else {		if (!ruid && current->fsuid == 0 && current->uid != 0) {			ruid = 1;			goto retry;		}		PRINTK("NFS reply lookup failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	nfs_rpc_free(p0);	return status;}int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,		int **p0, char **string, unsigned int *len, unsigned int maxlen){	int *p;	int status, ruid = 0;	PRINTK("NFS call  readlink\n");	if (!(*p0 = nfs_rpc_alloc(server->rsize)))		return -EIO;retry:	p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid);	p = xdr_encode_fhandle(p, fhandle);	if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0)		return status;	if (!(p = nfs_rpc_verify(*p0)))		status = -errno_NFSERR_IO;	else if ((status = ntohl(*p++)) == NFS_OK) {		if (!(p = xdr_decode_string2(p, string, len, maxlen))) {			printk("nfs_proc_readlink: giant pathname\n");			status = -errno_NFSERR_IO;		}		else	/* status = 0, */			PRINTK("NFS reply readlink\n");	}	else {		if (!ruid && current->fsuid == 0 && current->uid != 0) {			ruid = 1;			goto retry;		}		PRINTK("NFS reply readlink failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	return status;}int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,	  int offset, int count, char *data, struct nfs_fattr *fattr){	int *p, *p0;	int status;	int ruid = 0;	int len;	PRINTK("NFS call  read %d @ %d\n", count, offset);	if (!(p0 = nfs_rpc_alloc(server->rsize)))		return -EIO;retry:	p = nfs_rpc_header(p0, NFSPROC_READ, ruid);	p = xdr_encode_fhandle(p, fhandle);	*p++ = htonl(offset);	*p++ = htonl(count);	*p++ = htonl(count); /* traditional, could be any value */	if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {		nfs_rpc_free(p0);		return status;	}	if (!(p = nfs_rpc_verify(p0)))		status = -errno_NFSERR_IO;	else if ((status = ntohl(*p++)) == NFS_OK) {		p = xdr_decode_fattr(p, fattr);		if (!(p = xdr_decode_data(p, data, &len, count))) {			printk("nfs_proc_read: giant data size\n"); 			status = -errno_NFSERR_IO;		}		else {			status = len;			PRINTK("NFS reply read %d\n", len);		}	}	else {		if (!ruid && current->fsuid == 0 && current->uid != 0) {			ruid = 1;			goto retry;		}		PRINTK("NFS reply read failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	nfs_rpc_free(p0);	return status;}intnfs_proc_read_request(struct rpc_ioreq *req, struct nfs_server *server,			struct nfs_fh *fh, unsigned long offset,			unsigned long count, __u32 *buf){	__u32	*p, *p0;	int	len;	PRINTK("NFS reqst read %ld @ %ld\n", count, offset);	if (!(p0 = nfs_rpc_alloc(NFS_SLACK_SPACE)))		return -EIO;	p = nfs_rpc_header(p0, NFSPROC_READ, 0);	p = xdr_encode_fhandle(p, fh);	*p++ = htonl(offset);	*p++ = htonl(count);	*p++ = htonl(count); /* traditional, could be any value */	req->rq_svec[0].iov_base = p0;	req->rq_svec[0].iov_len  = (p - p0) << 2;	req->rq_slen = (p - p0) << 2;	req->rq_snr = 1;	len = (6 + 1 + 17 + 1);		/* standard READ reply header */	req->rq_rvec[0].iov_base = p0;	req->rq_rvec[0].iov_len  = len << 2;	req->rq_rvec[1].iov_base = buf;	req->rq_rvec[1].iov_len  = count;	req->rq_rvec[2].iov_base = p0 + len;		/* spill buffer */	req->rq_rvec[2].iov_len  = (NFS_SLACK_SPACE - len) << 2;	req->rq_rlen = count + NFS_SLACK_SPACE;	req->rq_rnr = 3;	req->rq_addr = &server->toaddr;	req->rq_alen = sizeof(server->toaddr);	return rpc_transmit(server->rsock, req);}intnfs_proc_read_reply(struct rpc_ioreq *req, struct nfs_fattr *fattr){	int		status;	__u32		*p0, *p;	int		count;	p0 = (__u32 *) req->rq_rvec[0].iov_base;	if (!(p = nfs_rpc_verify(p0))) {		/* Tell the upper layers to retry */		status = -EAGAIN;		/* status = -errno_NFSERR_IO; */	} else if ((status = ntohl(*p++)) == NFS_OK) {		p = xdr_decode_fattr(p, fattr);		count = ntohl(*p++);		if (p != req->rq_rvec[2].iov_base) {			/* unexpected RPC reply header size. punt.			 * fixme: move iovec contents to align data			 * on page boundary and adjust RPC header size			 * guess. */			status = -errno_NFSERR_IO;			PRINTK("NFS reply read odd header size %d\n",					(p - p0) << 2);		} else {			status = count;			PRINTK("NFS reply read %d\n", count);		}	}	else {		PRINTK("NFS reply read failed = %d\n", status);		status = -nfs_stat_to_errno(status);	}	nfs_rpc_free(p0);	return status;}int nfs_proc_write(struct inode * inode, int offset,		   int count, const char *data, struct nfs_fattr *fattr){	int *p, *p0;	int status;	int ruid = 0;	void * kdata;	/* address of kernel copy */	struct nfs_server * server = NFS_SERVER(inode);	struct nfs_fh *fhandle = NFS_FH(inode);	PRINTK("NFS call  write %d @ %d\n", count, offset);	if (!(p0 = nfs_rpc_alloc(server->wsize)))		return -EIO;retry:	p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);	p = xdr_encode_fhandle(p, fhandle);	*p++ = htonl(offset); /* traditional, could be any value */	*p++ = htonl(offset);	*p++ = htonl(count); /* traditional, could be any value */	kdata = (void *) (p+1);	/* start of data in RPC buffer */	p = xdr_encode_data(p, data, count);	if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {		nfs_rpc_free(p0);		return status;	}

⌨️ 快捷键说明

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