📄 nfs4xdr.c
字号:
} else { /* non - nfsv4 lock in conflict, no clientid nor owner */ WRITE64((u64)0); /* clientid */ WRITE32(0); /* length of owner name */ } ADJUST_ARGS();}static voidnfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock){ ENCODE_SEQID_OP_HEAD; if (!nfserr) { RESERVE_SPACE(4 + sizeof(stateid_t)); WRITE32(lock->lk_resp_stateid.si_generation); WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t)); ADJUST_ARGS(); } else if (nfserr == nfserr_denied) nfsd4_encode_lock_denied(resp, &lock->lk_denied); ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);}static voidnfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt){ if (nfserr == nfserr_denied) nfsd4_encode_lock_denied(resp, &lockt->lt_denied);}static voidnfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku){ ENCODE_SEQID_OP_HEAD; if (!nfserr) { RESERVE_SPACE(sizeof(stateid_t)); WRITE32(locku->lu_stateid.si_generation); WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t)); ADJUST_ARGS(); } ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);}static voidnfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(20); WRITECINFO(link->li_cinfo); ADJUST_ARGS(); }}static voidnfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open){ ENCODE_SEQID_OP_HEAD; if (nfserr) goto out; RESERVE_SPACE(36 + sizeof(stateid_t)); WRITE32(open->op_stateid.si_generation); WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t)); WRITECINFO(open->op_cinfo); WRITE32(open->op_rflags); WRITE32(2); WRITE32(open->op_bmval[0]); WRITE32(open->op_bmval[1]); WRITE32(open->op_delegate_type); ADJUST_ARGS(); switch (open->op_delegate_type) { case NFS4_OPEN_DELEGATE_NONE: break; case NFS4_OPEN_DELEGATE_READ: RESERVE_SPACE(20 + sizeof(stateid_t)); WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); WRITE32(open->op_recall); /* * TODO: ACE's in delegations */ WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); WRITE32(0); WRITE32(0); WRITE32(0); /* XXX: is NULL principal ok? */ ADJUST_ARGS(); break; case NFS4_OPEN_DELEGATE_WRITE: RESERVE_SPACE(32 + sizeof(stateid_t)); WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); WRITE32(0); /* * TODO: space_limit's in delegations */ WRITE32(NFS4_LIMIT_SIZE); WRITE32(~(u32)0); WRITE32(~(u32)0); /* * TODO: ACE's in delegations */ WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); WRITE32(0); WRITE32(0); WRITE32(0); /* XXX: is NULL principal ok? */ ADJUST_ARGS(); break; default: BUG(); } /* XXX save filehandle here */out: ENCODE_SEQID_OP_TAIL(open->op_stateowner);}static voidnfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc){ ENCODE_SEQID_OP_HEAD; if (!nfserr) { RESERVE_SPACE(sizeof(stateid_t)); WRITE32(oc->oc_resp_stateid.si_generation); WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t)); ADJUST_ARGS(); } ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);}static voidnfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od){ ENCODE_SEQID_OP_HEAD; if (!nfserr) { RESERVE_SPACE(sizeof(stateid_t)); WRITE32(od->od_stateid.si_generation); WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t)); ADJUST_ARGS(); } ENCODE_SEQID_OP_TAIL(od->od_stateowner);}static __be32nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read){ u32 eof; int v, pn; unsigned long maxcount; long len; ENCODE_HEAD; if (nfserr) return nfserr; if (resp->xbuf->page_len) return nfserr_resource; RESERVE_SPACE(8); /* eof flag and byte count */ maxcount = svc_max_payload(resp->rqstp); if (maxcount > read->rd_length) maxcount = read->rd_length; len = maxcount; v = 0; while (len > 0) { pn = resp->rqstp->rq_resused++; resp->rqstp->rq_vec[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); resp->rqstp->rq_vec[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; v++; len -= PAGE_SIZE; } read->rd_vlen = v; nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, &maxcount); if (nfserr == nfserr_symlink) nfserr = nfserr_inval; if (nfserr) return nfserr; eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size); WRITE32(eof); WRITE32(maxcount); ADJUST_ARGS(); resp->xbuf->head[0].iov_len = (char*)p - (char*)resp->xbuf->head[0].iov_base; resp->xbuf->page_len = maxcount; /* Use rest of head for padding and remaining ops: */ resp->xbuf->tail[0].iov_base = p; resp->xbuf->tail[0].iov_len = 0; if (maxcount&3) { RESERVE_SPACE(4); WRITE32(0); resp->xbuf->tail[0].iov_base += maxcount&3; resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); ADJUST_ARGS(); } return 0;}static __be32nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink){ int maxcount; char *page; ENCODE_HEAD; if (nfserr) return nfserr; if (resp->xbuf->page_len) return nfserr_resource; page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); maxcount = PAGE_SIZE; RESERVE_SPACE(4); /* * XXX: By default, the ->readlink() VFS op will truncate symlinks * if they would overflow the buffer. Is this kosher in NFSv4? If * not, one easy fix is: if ->readlink() precisely fills the buffer, * assume that truncation occurred, and return NFS4ERR_RESOURCE. */ nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); if (nfserr == nfserr_isdir) return nfserr_inval; if (nfserr) return nfserr; WRITE32(maxcount); ADJUST_ARGS(); resp->xbuf->head[0].iov_len = (char*)p - (char*)resp->xbuf->head[0].iov_base; resp->xbuf->page_len = maxcount; /* Use rest of head for padding and remaining ops: */ resp->xbuf->tail[0].iov_base = p; resp->xbuf->tail[0].iov_len = 0; if (maxcount&3) { RESERVE_SPACE(4); WRITE32(0); resp->xbuf->tail[0].iov_base += maxcount&3; resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); ADJUST_ARGS(); } return 0;}static __be32nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir){ int maxcount; loff_t offset; __be32 *page, *savep, *tailbase; ENCODE_HEAD; if (nfserr) return nfserr; if (resp->xbuf->page_len) return nfserr_resource; RESERVE_SPACE(8); /* verifier */ savep = p; /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ WRITE32(0); WRITE32(0); ADJUST_ARGS(); resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; tailbase = p; maxcount = PAGE_SIZE; if (maxcount > readdir->rd_maxcount) maxcount = readdir->rd_maxcount; /* * Convert from bytes to words, account for the two words already * written, make sure to leave two words at the end for the next * pointer and eof field. */ maxcount = (maxcount >> 2) - 4; if (maxcount < 0) { nfserr = nfserr_toosmall; goto err_no_verf; } page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); readdir->common.err = 0; readdir->buflen = maxcount; readdir->buffer = page; readdir->offset = NULL; offset = readdir->rd_cookie; nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, &offset, &readdir->common, nfsd4_encode_dirent); if (nfserr == nfs_ok && readdir->common.err == nfserr_toosmall && readdir->buffer == page) nfserr = nfserr_toosmall; if (nfserr == nfserr_symlink) nfserr = nfserr_notdir; if (nfserr) goto err_no_verf; if (readdir->offset) xdr_encode_hyper(readdir->offset, offset); p = readdir->buffer; *p++ = 0; /* no more entries */ *p++ = htonl(readdir->common.err == nfserr_eof); resp->xbuf->page_len = ((char*)p) - (char*)page_address( resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); /* Use rest of head for padding and remaining ops: */ resp->xbuf->tail[0].iov_base = tailbase; resp->xbuf->tail[0].iov_len = 0; resp->p = resp->xbuf->tail[0].iov_base; resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; return 0;err_no_verf: p = savep; ADJUST_ARGS(); return nfserr;}static voidnfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(20); WRITECINFO(remove->rm_cinfo); ADJUST_ARGS(); }}static voidnfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(40); WRITECINFO(rename->rn_sinfo); WRITECINFO(rename->rn_tinfo); ADJUST_ARGS(); }}static voidnfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_secinfo *secinfo){ int i = 0; struct svc_export *exp = secinfo->si_exp; u32 nflavs; struct exp_flavor_info *flavs; struct exp_flavor_info def_flavs[2]; ENCODE_HEAD; if (nfserr) goto out; if (exp->ex_nflavors) { flavs = exp->ex_flavors; nflavs = exp->ex_nflavors; } else { /* Handling of some defaults in absence of real secinfo: */ flavs = def_flavs; if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) { nflavs = 2; flavs[0].pseudoflavor = RPC_AUTH_UNIX; flavs[1].pseudoflavor = RPC_AUTH_NULL; } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) { nflavs = 1; flavs[0].pseudoflavor = svcauth_gss_flavor(exp->ex_client); } else { nflavs = 1; flavs[0].pseudoflavor = exp->ex_client->flavour->flavour; } } RESERVE_SPACE(4); WRITE32(nflavs); ADJUST_ARGS(); for (i = 0; i < nflavs; i++) { u32 flav = flavs[i].pseudoflavor; struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); if (gm) { RESERVE_SPACE(4); WRITE32(RPC_AUTH_GSS); ADJUST_ARGS(); RESERVE_SPACE(4 + gm->gm_oid.len); WRITE32(gm->gm_oid.len); WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); ADJUST_ARGS(); RESERVE_SPACE(4); WRITE32(0); /* qop */ ADJUST_ARGS(); RESERVE_SPACE(4); WRITE32(gss_pseudoflavor_to_service(gm, flav)); ADJUST_ARGS(); gss_mech_put(gm); } else { RESERVE_SPACE(4); WRITE32(flav); ADJUST_ARGS(); } }out: if (exp) exp_put(exp);}/* * The SETATTR encode routine is special -- it always encodes a bitmap, * regardless of the error status. */static voidnfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr){ ENCODE_HEAD; RESERVE_SPACE(12); if (nfserr) { WRITE32(2); WRITE32(0); WRITE32(0); } else { WRITE32(2); WRITE32(setattr->sa_bmval[0]); WRITE32(setattr->sa_bmval[1]); } ADJUST_ARGS();}static voidnfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(8 + sizeof(nfs4_verifier)); WRITEMEM(&scd->se_clientid, 8); WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); ADJUST_ARGS(); } else if (nfserr == nfserr_clid_inuse) { RESERVE_SPACE(8); WRITE32(0); WRITE32(0); ADJUST_ARGS(); }}static voidnfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(16); WRITE32(write->wr_bytes_written); WRITE32(write->wr_how_written); WRITEMEM(write->wr_verifier.data, 8); ADJUST_ARGS(); }}voidnfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op){ __be32 *statp; ENCODE_HEAD; RESERVE_SPACE(8); WRITE32(op->opnum); statp = p++; /* to be backfilled at the end */ ADJUST_ARGS(); switch (op->opnum) { case OP_ACCESS: nfsd4_encode_access(resp, op->status, &op->u.access); break; case OP_CLOSE: nfsd4_encode_close(resp, op->status, &op->u.close); break; case OP_COMMIT: nfsd4_encode_commit(resp, op->status, &op->u.commit); break; case OP_CREATE: nfsd4_encode_create(resp, op->status, &op->u.create); break; case OP_DELEGRETUR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -