📄 nfs4xdr.c
字号:
if (bmval0 & FATTR4_WORD0_SIZE) { if ((buflen -= 8) < 0) goto out_resource; WRITE64(stat.size); } if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(0); } if (bmval0 & FATTR4_WORD0_FSID) { if ((buflen -= 16) < 0) goto out_resource; if (exp->ex_fslocs.migrated) { WRITE64(NFS4_REFERRAL_FSID_MAJOR); WRITE64(NFS4_REFERRAL_FSID_MINOR); } else switch(fsid_source(fhp)) { case FSIDSOURCE_FSID: WRITE64((u64)exp->ex_fsid); WRITE64((u64)0); break; case FSIDSOURCE_DEV: WRITE32(0); WRITE32(MAJOR(stat.dev)); WRITE32(0); WRITE32(MINOR(stat.dev)); break; case FSIDSOURCE_UUID: WRITEMEM(exp->ex_uuid, 16); break; } } if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(0); } if (bmval0 & FATTR4_WORD0_LEASE_TIME) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(NFSD_LEASE_TIME); } if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(rdattr_err); } if (bmval0 & FATTR4_WORD0_ACL) { struct nfs4_ace *ace; if (acl == NULL) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(0); goto out_acl; } if ((buflen -= 4) < 0) goto out_resource; WRITE32(acl->naces); for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { if ((buflen -= 4*3) < 0) goto out_resource; WRITE32(ace->type); WRITE32(ace->flag); WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); status = nfsd4_encode_aclname(rqstp, ace->whotype, ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP, &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) goto out; } }out_acl: if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(aclsupport ? ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); } if (bmval0 & FATTR4_WORD0_CANSETTIME) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_FILEHANDLE) { buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; if (buflen < 0) goto out_resource; WRITE32(fhp->fh_handle.fh_size); WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); } if (bmval0 & FATTR4_WORD0_FILEID) { if ((buflen -= 8) < 0) goto out_resource; WRITE64(stat.ino); } if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { if ((buflen -= 8) < 0) goto out_resource; WRITE64((u64) statfs.f_ffree); } if (bmval0 & FATTR4_WORD0_FILES_FREE) { if ((buflen -= 8) < 0) goto out_resource; WRITE64((u64) statfs.f_ffree); } if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { if ((buflen -= 8) < 0) goto out_resource; WRITE64((u64) statfs.f_files); } if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) goto out; } if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { if ((buflen -= 8) < 0) goto out_resource; WRITE64(~(u64)0); } if (bmval0 & FATTR4_WORD0_MAXLINK) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(255); } if (bmval0 & FATTR4_WORD0_MAXNAME) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(statfs.f_namelen); } if (bmval0 & FATTR4_WORD0_MAXREAD) { if ((buflen -= 8) < 0) goto out_resource; WRITE64((u64) svc_max_payload(rqstp)); } if (bmval0 & FATTR4_WORD0_MAXWRITE) { if ((buflen -= 8) < 0) goto out_resource; WRITE64((u64) svc_max_payload(rqstp)); } if (bmval1 & FATTR4_WORD1_MODE) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(stat.mode & S_IALLUGO); } if (bmval1 & FATTR4_WORD1_NO_TRUNC) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(1); } if (bmval1 & FATTR4_WORD1_NUMLINKS) { if ((buflen -= 4) < 0) goto out_resource; WRITE32(stat.nlink); } if (bmval1 & FATTR4_WORD1_OWNER) { status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) goto out; } if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); if (status == nfserr_resource) goto out_resource; if (status) goto out; } if (bmval1 & FATTR4_WORD1_RAWDEV) { if ((buflen -= 8) < 0) goto out_resource; WRITE32((u32) MAJOR(stat.rdev)); WRITE32((u32) MINOR(stat.rdev)); } if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { if ((buflen -= 8) < 0) goto out_resource; dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; WRITE64(dummy64); } if (bmval1 & FATTR4_WORD1_SPACE_FREE) { if ((buflen -= 8) < 0) goto out_resource; dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; WRITE64(dummy64); } if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { if ((buflen -= 8) < 0) goto out_resource; dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; WRITE64(dummy64); } if (bmval1 & FATTR4_WORD1_SPACE_USED) { if ((buflen -= 8) < 0) goto out_resource; dummy64 = (u64)stat.blocks << 9; WRITE64(dummy64); } if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { if ((buflen -= 12) < 0) goto out_resource; WRITE32(0); WRITE32(stat.atime.tv_sec); WRITE32(stat.atime.tv_nsec); } if (bmval1 & FATTR4_WORD1_TIME_DELTA) { if ((buflen -= 12) < 0) goto out_resource; WRITE32(0); WRITE32(1); WRITE32(0); } if (bmval1 & FATTR4_WORD1_TIME_METADATA) { if ((buflen -= 12) < 0) goto out_resource; WRITE32(0); WRITE32(stat.ctime.tv_sec); WRITE32(stat.ctime.tv_nsec); } if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { if ((buflen -= 12) < 0) goto out_resource; WRITE32(0); WRITE32(stat.mtime.tv_sec); WRITE32(stat.mtime.tv_nsec); } if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { if ((buflen -= 8) < 0) goto out_resource; if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { err = vfs_getattr(exp->ex_mnt->mnt_parent, exp->ex_mnt->mnt_mountpoint, &stat); if (err) goto out_nfserr; } WRITE64(stat.ino); } *attrlenp = htonl((char *)p - (char *)attrlenp - 4); *countp = p - buffer; status = nfs_ok;out: kfree(acl); if (fhp == &tempfh) fh_put(&tempfh); return status;out_nfserr: status = nfserrno(err); goto out;out_resource: *countp = 0; status = nfserr_resource; goto out;out_serverfault: status = nfserr_serverfault; goto out;}static __be32nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, const char *name, int namlen, __be32 *p, int *buflen){ struct svc_export *exp = cd->rd_fhp->fh_export; struct dentry *dentry; __be32 nfserr; dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); if (IS_ERR(dentry)) return nfserrno(PTR_ERR(dentry)); exp_get(exp); if (d_mountpoint(dentry)) { int err; /* * Why the heck aren't we just using nfsd_lookup?? * Different "."/".." handling? Something else? * At least, add a comment here to explain.... */ err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); if (err) { nfserr = nfserrno(err); goto out_put; } nfserr = check_nfsd_access(exp, cd->rd_rqstp); if (nfserr) goto out_put; } nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, cd->rd_rqstp);out_put: dput(dentry); exp_put(exp); return nfserr;}static __be32 *nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr){ __be32 *attrlenp; if (buflen < 6) return NULL; *p++ = htonl(2); *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ *p++ = htonl(0); /* bmval1 */ attrlenp = p++; *p++ = nfserr; /* no htonl */ *attrlenp = htonl((char *)p - (char *)attrlenp - 4); return p;}static intnfsd4_encode_dirent(void *ccdv, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type){ struct readdir_cd *ccd = ccdv; struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); int buflen; __be32 *p = cd->buffer; __be32 nfserr = nfserr_toosmall; /* In nfsv4, "." and ".." never make it onto the wire.. */ if (name && isdotent(name, namlen)) { cd->common.err = nfs_ok; return 0; } if (cd->offset) xdr_encode_hyper(cd->offset, (u64) offset); buflen = cd->buflen - 4 - XDR_QUADLEN(namlen); if (buflen < 0) goto fail; *p++ = xdr_one; /* mark entry present */ cd->offset = p; /* remember pointer */ p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ p = xdr_encode_array(p, name, namlen); /* name length & name */ nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen); switch (nfserr) { case nfs_ok: p += buflen; break; case nfserr_resource: nfserr = nfserr_toosmall; goto fail; case nfserr_dropit: goto fail; default: /* * If the client requested the RDATTR_ERROR attribute, * we stuff the error code into this attribute * and continue. If this attribute was not requested, * then in accordance with the spec, we fail the * entire READDIR operation(!) */ if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) goto fail; p = nfsd4_encode_rdattr_error(p, buflen, nfserr); if (p == NULL) { nfserr = nfserr_toosmall; goto fail; } } cd->buflen -= (p - cd->buffer); cd->buffer = p; cd->common.err = nfs_ok; return 0;fail: cd->common.err = nfserr; return -EINVAL;}static voidnfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(8); WRITE32(access->ac_supported); WRITE32(access->ac_resp_access); ADJUST_ARGS(); }}static voidnfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close){ ENCODE_SEQID_OP_HEAD; if (!nfserr) { RESERVE_SPACE(sizeof(stateid_t)); WRITE32(close->cl_stateid.si_generation); WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t)); ADJUST_ARGS(); } ENCODE_SEQID_OP_TAIL(close->cl_stateowner);}static voidnfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(8); WRITEMEM(commit->co_verf.data, 8); ADJUST_ARGS(); }}static voidnfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create){ ENCODE_HEAD; if (!nfserr) { RESERVE_SPACE(32); WRITECINFO(create->cr_cinfo); WRITE32(2); WRITE32(create->cr_bmval[0]); WRITE32(create->cr_bmval[1]); ADJUST_ARGS(); }}static __be32nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr){ struct svc_fh *fhp = getattr->ga_fhp; int buflen; if (nfserr) return nfserr; buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, resp->p, &buflen, getattr->ga_bmval, resp->rqstp); if (!nfserr) resp->p += buflen; return nfserr;}static voidnfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp){ unsigned int len; ENCODE_HEAD; if (!nfserr) { len = fhp->fh_handle.fh_size; RESERVE_SPACE(len + 4); WRITE32(len); WRITEMEM(&fhp->fh_handle.fh_base, len); ADJUST_ARGS(); }}/** Including all fields other than the name, a LOCK4denied structure requires* 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.*/static voidnfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld){ ENCODE_HEAD; RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0)); WRITE64(ld->ld_start); WRITE64(ld->ld_length); WRITE32(ld->ld_type); if (ld->ld_sop) { WRITEMEM(&ld->ld_clientid, 8); WRITE32(ld->ld_sop->so_owner.len); WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len); kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -