/* * Encode access() argument */ static int nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args) { p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(args->access); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode SETATTR arguments */ static int nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode directory ops argument * LOOKUP, REMOVE, RMDIR */ static int nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode REMOVE argument */ static int nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name.name, args->name.len); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode MKDIR arguments */ static int nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode SYMLINK arguments */ static int nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); p = xdr_encode_array(p, args->topath, args->tolen); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle, int cookie, int count, struct nfs_entry *entry) { int *p, *p0; int status; int ruid = 0; int i; int size; int eof; PRINTK("NFS call readdir %d @ %d\n", count, cookie); size = server->rsize; if (!(p0 = nfs_rpc_alloc(server->rsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid); p = xdr_encode_fhandle(p, fhandle); *p++ = htonl(cookie); *p++ = htonl(size); 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) { for (i = 0; i < count && *p++; i++) { if (!(p = xdr_decode_entry(p, entry++))) break; } if (!p) { printk("nfs_proc_readdir: giant filename\n"); status = -errno_NFSERR_IO; } else { eof = (i == count && !*p++ && *p++) || (i < count && *p++); if (eof && i) entry[-1].eof = 1; PRINTK("NFS reply readdir %d %s\n", i, eof ? "eof" : ""); status = i; } } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readdir failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
/* * Encode SETATTR arguments */ static int nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_sattr(p, args->sattr); *p++ = htonl(args->guard); if (args->guard) p = xdr_encode_time3(p, &args->guardtime); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode SYMLINK arguments */ static int nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); p = xdr_encode_sattr(p, args->sattr); *p++ = htonl(args->pathlen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* Copy the page */ xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); return 0; }
int nfs_proc_rename(struct nfs_server *server, struct nfs_fh *old_dir, const char *old_name, struct nfs_fh *new_dir, const char *new_name) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call rename %s -> %s\n", old_name, new_name); if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid); p = xdr_encode_fhandle(p, old_dir); p = xdr_encode_string(p, old_name); p = xdr_encode_fhandle(p, new_dir); p = xdr_encode_string(p, new_name); 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) { PRINTK("NFS reply rename\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply rename failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
/* * Encode READLINK args */ static int nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_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 + NFS_readlinkres_sz) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); return 0; }
/* * Encode MKNOD arguments */ static int nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); *p++ = htonl(args->type); p = xdr_encode_sattr(p, args->sattr); if (args->type == NF3CHR || args->type == NF3BLK) { *p++ = htonl(MAJOR(args->rdev)); *p++ = htonl(MINOR(args->rdev)); } req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode CREATE arguments */ static int nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_array(p, args->name, args->len); *p++ = htonl(args->createmode); if (args->createmode == NFS3_CREATE_EXCLUSIVE) { *p++ = args->verifier[0]; *p++ = args->verifier[1]; } else p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; }
/* * Encode arguments to readdir call */ static int nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) { struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; unsigned int replen; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_hyper(p, args->cookie); *p++ = args->verf[0]; *p++ = args->verf[1]; if (args->plus) { /* readdirplus: need dircount + buffer size. * We just make sure we make dircount big enough */ *p++ = htonl(count >> 3); }
/* * Write arguments. Splice the buffer to be written into the iovec. */ static int nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) { struct xdr_buf *sndbuf = &req->rq_snd_buf; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_hyper(p, args->offset); *p++ = htonl(count); *p++ = htonl(args->stable); *p++ = htonl(count); sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); /* Copy the page array */ xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); return 0; }
/* * Encode arguments to readdir call */ static int nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) { struct rpc_auth *auth = req->rq_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; }
int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr, int fs) { 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, fs))) { 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; }
/* * Write arguments. Splice the buffer to be written into the iovec. */ static int nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) { unsigned int nr; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(args->offset); *p++ = htonl(args->offset); *p++ = htonl(count); *p++ = htonl(count); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* Get the number of buffers in the send iovec */ nr = args->nriov; if (nr+2 > MAX_IOVEC) { printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs " "(nr %d max %d)\n", nr, MAX_IOVEC); return -EINVAL; } /* Copy the iovec */ memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec)); #ifdef NFS_PAD_WRITES /* * Some old servers require that the message length * be a multiple of 4, so we pad it here if needed. */ if (count & 3) { struct iovec *iov = req->rq_svec + nr + 1; int pad = 4 - (count & 3); iov->iov_base = (void *) "\0\0\0"; iov->iov_len = pad; count += pad; nr++; } #endif req->rq_slen += count; req->rq_snr += nr; return 0; }
/* * Arguments to a READ call. Since we read data directly into the page * cache, we also set up the reply iovec here so that iov[1] points * exactly to the page we want to fetch. */ static int nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; unsigned int replen; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_hyper(p, args->offset); *p++ = htonl(count); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* Inline the page array */ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, count); return 0; }
/* not parallel */ int nfs_proc_read_np(struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr) { int *p; int len = 0; int status; int ruid = 0; struct generic_server *server = fhandle->server; int *p0; DPRINTF(CLUHELP_LEVEL,("NFS call read %d @ %d\n", count, offset)); if (!(p0 = overhead_rpc_alloc(server->rsize))) return -EIO; 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 */ DPRINTF(CLUHELP_LEVEL,("ORIGNAL\n")); /* print_rpc2(p0,128); */ if ((status = generic_rpc_call(server, p0, p)) < 0) { overhead_rpc_free(p0); return status; } if (!(p = generic_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); if (!(p = xdr_decode_data(p, data, &len, count))) { DPRINTF(CLUHELP_LEVEL,("nfs_proc_read: giant data size\n")); status = NFSERR_IO; } else DPRINTF(CLUHELP_LEVEL,("NFS reply read %d\n", len)); } overhead_rpc_free(p0); return (status == NFS_OK) ? len : nfs_stat_to_errno(status); }
static int nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) { struct xdr_buf *sndbuf = &req->rq_snd_buf; u32 offset = (u32)args->offset; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(offset); *p++ = htonl(offset); *p++ = htonl(count); *p++ = htonl(count); sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); /* Copy the page array */ xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); sndbuf->flags |= XDRBUF_WRITE; return 0; }
/* * Encode READLINK args */ static int nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args) { struct rpc_task *task = req->rq_task; struct rpc_auth *auth = task->tk_auth; int buflen, replen; p = xdr_encode_fhandle(p, args->fh); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2; buflen = req->rq_rvec[0].iov_len; req->rq_rvec[0].iov_len = replen; req->rq_rvec[1].iov_base = args->buffer; req->rq_rvec[1].iov_len = args->bufsiz; req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; req->rq_rvec[2].iov_len = buflen - replen; req->rq_rlen = buflen + args->bufsiz; req->rq_rnr += 2; return 0; }
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; }
/* * Arguments to a READ call. Since we read data directly into the page * cache, we also set up the reply iovec here so that iov[1] points * exactly to the page we want to fetch. */ static int nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_cred->cr_auth; unsigned int replen; u32 offset = (u32)args->offset; u32 count = args->count; p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(offset); *p++ = htonl(count); *p++ = htonl(count); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* Inline the page array */ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, count); req->rq_rcv_buf.flags |= XDRBUF_READ; return 0; }
int nfs_proc_write(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; 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 */ p = xdr_encode_data(p, data, count); 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 write\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply write failed = %d\n", status); status = -nfs_stat_to_errno(status); } nfs_rpc_free(p0); return status; }
int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir, const char *name, struct nfs_sattr *sattr, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call mkdir %s\n", name); if (!(p0 = nfs_rpc_alloc(server->wsize))) return -EIO; retry: p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid); p = xdr_encode_fhandle(p, dir); p = xdr_encode_string(p, name); 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_fhandle(p, fhandle); p = xdr_decode_fattr(p, fattr); PRINTK("NFS reply mkdir\n"); /* status = 0; */ } else { if (!ruid && current->fsuid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply mkdir 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, char *res) { int *p, *p0; int status; int ruid = 0; PRINTK("NFS call readlink\n"); if (!(p0 = nfs_rpc_alloc())) 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)) < 0) { nfs_rpc_free(p0); return status; } if (!(p = nfs_rpc_verify(p0))) status = NFSERR_IO; else if ((status = ntohl(*p++)) == NFS_OK) { if (!(p = xdr_decode_string(p, res, NFS_MAXPATHLEN))) { printk("nfs_proc_readlink: giant pathname\n"); status = NFSERR_IO; } else PRINTK("NFS reply readlink %s\n", res); } else { if (!ruid && current->euid == 0 && current->uid != 0) { ruid = 1; goto retry; } PRINTK("NFS reply readlink failed = %d\n", status); } nfs_rpc_free(p0); return -nfs_stat_to_errno(status); }
int nfs_proc_read_p(struct nfs_fh *fhandle, int offset, int count, char *data, struct nfs_fattr *fattr) { int *p; int len = 0; int status; int ruid = 0; struct generic_server *server = fhandle->server; struct p_rpc *prpc; struct p_rpc_rec *rw; int i; int rsize; /* to be used with new prpc */ int remaining_count = count; int total_length = 0; char *tmp_data; char *tmp_data0; DPRINTF(CLUHELP_LEVEL,("NFS call read %d @ %d\n", count, offset)); rsize = server->rsize; //rsize = 1366; if ((offset < NFSMAXOFFSET) && ((offset % 4096) != 0)) { kprintf("warning non page aligned read: %d:%d\n",offset,count); } if (!(prpc = p_overhead_rpc_alloc(rsize, count))) return -EIO; for (i = 0; i < prpc->n ; i++) { rw = &prpc->rw[i]; rw->start = nfs_rpc_header(rw->ptr, NFSPROC_READ, ruid); rw->start = xdr_encode_fhandle(rw->start, fhandle); *rw->start++ = htonl(offset + i*rsize); /* offset */ *rw->start++ = htonl((remaining_count >= rsize) ? rsize : remaining_count); /* count */ rw->count = (remaining_count >= rsize) ? rsize : remaining_count; remaining_count -= rsize; *rw->start++ = htonl(rsize); /* traditional, could be any value */ rw->end = rw->start; rw->r.n = 0; rw->xid = rw->ptr[0]; rw->done = 0; /* print_rpc2(prpc->rw[i].ptr,128); */ } /* pr_p_rpc(prpc); */ if ((status = p_generic_rpc_call(server,prpc)) < 0) { p_overhead_rpc_free(prpc); return status; } DPRINTF(CLUHELP_LEVEL,("P_GENERIC_RPC_CALL: %d\n",status)); tmp_data = tmp_data0 = data; for (i = 0; i < prpc->n ; i++) { rw = &prpc->rw[i]; if (!(p = generic_rpc_verify(rw->ptr))) { status = NFSERR_IO; break; } else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); if (!(p = xdr_decode_data(p, tmp_data, &len, rw->count))) { DPRINTF(CLUHELP_LEVEL,("nfs_proc_read: giant data size\n")); status = NFSERR_IO; break; } else { DPRINTF(CLUHELP_LEVEL,("NFS reply read xid: %d, length: %d count %d\n", rw->xid,len,rw->count)); tmp_data += len; total_length += len; } } } DPRINTF(CLUHELP_LEVEL,("status: %d\n",status)); p_overhead_rpc_free(prpc); return (status == NFS_OK) ? total_length : nfs_stat_to_errno(status); }
int nfs_proc_writev(struct nfs_fh *fhandle, int offset, int count, struct ae_recv *r, struct nfs_fattr *fattr) { int *p; int status; int ruid = 0; struct generic_server *server = fhandle->server; char *tmp_data; int i; int wsize; /* to be used with new prpc */ int remaining_count = count; struct p_rpc *prpc; struct p_rpc_rec *rw; DPRINTF(CLUHELP_LEVEL,("NFS call write %p %d @ %d\n", r, count, offset)); wsize = server->wsize; if (!(prpc = p_overhead_rpc_alloc(wsize, count))) return -EIO; demand(count <= wsize, we only handle up to 8K for now); tmp_data = NULL; // data; for (i = 0; i < prpc->n ; i++) { static char overflow[4]; rw = &prpc->rw[i]; rw->start = nfs_rpc_header(rw->ptr, NFSPROC_WRITE, ruid); rw->start = xdr_encode_fhandle(rw->start, fhandle); *rw->start++ = htonl(offset + i*wsize); /* offset */ *rw->start++ = htonl(offset + i*wsize); /* offset */ rw->count = (remaining_count >= wsize) ? wsize : remaining_count; *rw->start++ = htonl(rw->count); /* count */ *rw->start++ = htonl(rw->count); /* data len */ rw->end = rw->start; rw->r.n = 1; rw->r = *r; if ((rw->count % 4) != 0) { rw->r.r[r->n].data = overflow; rw->r.r[r->n].sz = 4 - (rw->count % 4); rw->r.n++; } pr_ae_recv(&rw->r); tmp_data += rw->count; remaining_count -= rw->count; rw->xid = rw->ptr[0]; rw->done = 0; /* print_rpc2(prpc->rw[i].ptr,128); */ } /* pr_p_rpc(prpc); */ lprintf("p_generic_rpc_call start\n"); if ((status = p_generic_rpc_call(server,prpc)) < 0) { p_overhead_rpc_free(prpc); return status; } lprintf("p_generic_rpc_call done\n"); DPRINTF(CLUHELP_LEVEL,("P_GENERIC_RPC_CALL: %d\n",status)); for (i = 0; i < prpc->n ; i++) { rw = &prpc->rw[i]; if (!(p = generic_rpc_verify(rw->ptr))) { status = NFSERR_IO; break; } else if ((status = ntohl(*p++)) == NFS_OK) { p = xdr_decode_fattr(p, fattr); DPRINTF(CLUHELP_LEVEL,("NFS reply write xid: %d, count %d\n", rw->xid,rw->count)); } } DPRINTF(CLUHELP_LEVEL,("status: %d\n",status)); p_overhead_rpc_free(prpc); return nfs_stat_to_errno(status); }