📄 nfs3proc.c
字号:
/* * linux/fs/nfsd/nfs3proc.c * * Process version 3 NFS requests. * * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de> */#include <linux/linkage.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/locks.h>#include <linux/fs.h>#include <linux/ext2_fs.h>#include <linux/stat.h>#include <linux/fcntl.h>#include <linux/net.h>#include <linux/in.h>#include <linux/version.h>#include <linux/unistd.h>#include <linux/slab.h>#include <linux/major.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr3.h>#include <linux/nfs3.h>#define NFSDDBG_FACILITY NFSDDBG_PROC#define RETURN_STATUS(st) { resp->status = (st); return (st); }static int nfs3_ftypes[] = { 0, /* NF3NON */ S_IFREG, /* NF3REG */ S_IFDIR, /* NF3DIR */ S_IFBLK, /* NF3BLK */ S_IFCHR, /* NF3CHR */ S_IFLNK, /* NF3LNK */ S_IFSOCK, /* NF3SOCK */ S_IFIFO, /* NF3FIFO */};/* * Reserve room in the send buffer */static voidsvcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr){ *ptr = buf->buf + nr; *len = buf->buflen - buf->len - nr;}/* * NULL call. */static intnfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp){ return nfs_ok;}/* * Get a file's attributes */static intnfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd3_attrstat *resp){ int nfserr; dprintk("nfsd: GETATTR(3) %s\n", SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); RETURN_STATUS(nfserr);}/* * Set a file's attributes */static intnfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp, struct nfsd3_attrstat *resp){ int nfserr; dprintk("nfsd: SETATTR(3) %s\n", SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, argp->check_guard, argp->guardtime); RETURN_STATUS(nfserr);}/* * Look up a path name component */static intnfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, struct nfsd3_diropres *resp){ int nfserr; dprintk("nfsd: LOOKUP(3) %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); fh_copy(&resp->dirfh, &argp->fh); fh_init(&resp->fh, NFS3_FHSIZE); nfserr = nfsd_lookup(rqstp, &resp->dirfh, argp->name, argp->len, &resp->fh); RETURN_STATUS(nfserr);}/* * Check file access */static intnfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, struct nfsd3_accessres *resp){ int nfserr; dprintk("nfsd: ACCESS(3) %s 0x%x\n", SVCFH_fmt(&argp->fh), argp->access); fh_copy(&resp->fh, &argp->fh); resp->access = argp->access; nfserr = nfsd_access(rqstp, &resp->fh, &resp->access); RETURN_STATUS(nfserr);}/* * Read a symlink. */static intnfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd3_readlinkres *resp){ u32 *path; int dummy, nfserr; dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh)); /* Reserve room for status, post_op_attr, and path length */ svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 1 + NFS3_POST_OP_ATTR_WORDS + 1); /* Read the symlink. */ fh_copy(&resp->fh, &argp->fh); resp->len = NFS3_MAXPATHLEN; nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len); RETURN_STATUS(nfserr);}/* * Read a portion of a file. */static intnfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, struct nfsd3_readres *resp){ u32 * buffer; int nfserr, avail; dprintk("nfsd: READ(3) %s %lu bytes at %lu\n", SVCFH_fmt(&argp->fh), (unsigned long) argp->count, (unsigned long) argp->offset); /* Obtain buffer pointer for payload. * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof) * + 1 (xdr opaque byte count) = 26 */ svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &avail, 1 + NFS3_POST_OP_ATTR_WORDS + 3); resp->count = argp->count; if ((avail << 2) < resp->count) resp->count = avail << 2; fh_copy(&resp->fh, &argp->fh); nfserr = nfsd_read(rqstp, &resp->fh, argp->offset, (char *) buffer, &resp->count); if (nfserr == 0) { struct inode *inode = resp->fh.fh_dentry->d_inode; resp->eof = (argp->offset + resp->count) >= inode->i_size; } RETURN_STATUS(nfserr);}/* * Write data to a file */static intnfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, struct nfsd3_writeres *resp){ int nfserr; dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n", SVCFH_fmt(&argp->fh), argp->len, (unsigned long) argp->offset, argp->stable? " stable" : ""); fh_copy(&resp->fh, &argp->fh); resp->committed = argp->stable; nfserr = nfsd_write(rqstp, &resp->fh, argp->offset, argp->data, argp->len, &resp->committed); resp->count = argp->count; RETURN_STATUS(nfserr);}/* * With NFSv3, CREATE processing is a lot easier than with NFSv2. * At least in theory; we'll see how it fares in practice when the * first reports about SunOS compatibility problems start to pour in... */static intnfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, struct nfsd3_diropres *resp){ svc_fh *dirfhp, *newfhp = NULL; struct iattr *attr; u32 nfserr; dprintk("nfsd: CREATE(3) %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); dirfhp = fh_copy(&resp->dirfh, &argp->fh); newfhp = fh_init(&resp->fh, NFS3_FHSIZE); attr = &argp->attrs; /* Get the directory inode */ nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE); if (nfserr) RETURN_STATUS(nfserr); /* Unfudge the mode bits */ attr->ia_mode &= ~S_IFMT; if (!(attr->ia_valid & ATTR_MODE)) { attr->ia_valid |= ATTR_MODE; attr->ia_mode = S_IFREG; } else { attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG; } /* Now create the file and set attributes */ nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, attr, newfhp, argp->createmode, argp->verf); RETURN_STATUS(nfserr);}/* * Make directory. This operation is not idempotent. */static intnfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, struct nfsd3_diropres *resp){ int nfserr; dprintk("nfsd: MKDIR(3) %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); argp->attrs.ia_valid &= ~ATTR_SIZE; fh_copy(&resp->dirfh, &argp->fh); fh_init(&resp->fh, NFS3_FHSIZE); nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, &argp->attrs, S_IFDIR, 0, &resp->fh); RETURN_STATUS(nfserr);}static intnfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, struct nfsd3_diropres *resp){ int nfserr; dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n", SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, argp->tlen, argp->tname); fh_copy(&resp->dirfh, &argp->ffh); fh_init(&resp->fh, NFS3_FHSIZE); nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen, argp->tname, argp->tlen, &resp->fh, &argp->attrs); RETURN_STATUS(nfserr);}/* * Make socket/fifo/device. */static intnfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, struct nfsd3_diropres *resp){ int nfserr, type; dev_t rdev = 0; dprintk("nfsd: MKNOD(3) %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); fh_copy(&resp->dirfh, &argp->fh); fh_init(&resp->fh, NFS3_FHSIZE); if (argp->ftype == 0 || argp->ftype >= NF3BAD) RETURN_STATUS(nfserr_inval); if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) { if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV) || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV) || argp->minor > 0xFF) RETURN_STATUS(nfserr_inval); rdev = ((argp->major) << 8) | (argp->minor);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -