📄 nfs4xdr.c
字号:
decode_getattr_maxsz)#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ encode_getacl_maxsz)#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ decode_getacl_maxsz)#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ encode_setacl_maxsz)#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ decode_setacl_maxsz)#define NFS4_enc_fs_locations_sz \ (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ encode_lookup_maxsz + \ encode_fs_locations_maxsz)#define NFS4_dec_fs_locations_sz \ (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ decode_lookup_maxsz + \ decode_fs_locations_maxsz)static struct { unsigned int mode; unsigned int nfs2type;} nfs_type2fmt[] = { { 0, NFNON }, { S_IFREG, NFREG }, { S_IFDIR, NFDIR }, { S_IFBLK, NFBLK }, { S_IFCHR, NFCHR }, { S_IFLNK, NFLNK }, { S_IFSOCK, NFSOCK }, { S_IFIFO, NFFIFO }, { 0, NFNON }, { 0, NFNON },};struct compound_hdr { int32_t status; uint32_t nops; uint32_t taglen; char * tag;};/* * START OF "GENERIC" ENCODE ROUTINES. * These may look a little ugly since they are imported from a "generic" * set of XDR encode/decode routines which are intended to be shared by * all of our NFSv4 implementations (OpenBSD, MacOS X...). * * If the pain of reading these is too great, it should be a straightforward * task to translate them into Linux-specific versions which are more * consistent with the style used in NFSv2/v3... */#define WRITE32(n) *p++ = htonl(n)#define WRITE64(n) do { \ *p++ = htonl((uint32_t)((n) >> 32)); \ *p++ = htonl((uint32_t)(n)); \} while (0)#define WRITEMEM(ptr,nbytes) do { \ p = xdr_encode_opaque_fixed(p, ptr, nbytes); \} while (0)#define RESERVE_SPACE(nbytes) do { \ p = xdr_reserve_space(xdr, nbytes); \ BUG_ON(!p); \} while (0)static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str){ __be32 *p; p = xdr_reserve_space(xdr, 4 + len); BUG_ON(p == NULL); xdr_encode_opaque(p, str, len);}static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr){ __be32 *p; dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag); BUG_ON(hdr->taglen > NFS4_MAXTAGLEN); RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2)); WRITE32(hdr->taglen); WRITEMEM(hdr->tag, hdr->taglen); WRITE32(NFS4_MINOR_VERSION); WRITE32(hdr->nops); return 0;}static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf){ __be32 *p; p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE); BUG_ON(p == NULL); xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);}static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server){ char owner_name[IDMAP_NAMESZ]; char owner_group[IDMAP_NAMESZ]; int owner_namelen = 0; int owner_grouplen = 0; __be32 *p; __be32 *q; int len; uint32_t bmval0 = 0; uint32_t bmval1 = 0; int status; /* * We reserve enough space to write the entire attribute buffer at once. * In the worst-case, this would be * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) * = 36 bytes, plus any contribution from variable-length fields * such as owner/group. */ len = 16; /* Sigh */ if (iap->ia_valid & ATTR_SIZE) len += 8; if (iap->ia_valid & ATTR_MODE) len += 4; if (iap->ia_valid & ATTR_UID) { owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); if (owner_namelen < 0) { dprintk("nfs: couldn't resolve uid %d to string\n", iap->ia_uid); /* XXX */ strcpy(owner_name, "nobody"); owner_namelen = sizeof("nobody") - 1; /* goto out; */ } len += 4 + (XDR_QUADLEN(owner_namelen) << 2); } if (iap->ia_valid & ATTR_GID) { owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); if (owner_grouplen < 0) { dprintk("nfs: couldn't resolve gid %d to string\n", iap->ia_gid); strcpy(owner_group, "nobody"); owner_grouplen = sizeof("nobody") - 1; /* goto out; */ } len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); } if (iap->ia_valid & ATTR_ATIME_SET) len += 16; else if (iap->ia_valid & ATTR_ATIME) len += 4; if (iap->ia_valid & ATTR_MTIME_SET) len += 16; else if (iap->ia_valid & ATTR_MTIME) len += 4; RESERVE_SPACE(len); /* * We write the bitmap length now, but leave the bitmap and the attribute * buffer length to be backfilled at the end of this routine. */ WRITE32(2); q = p; p += 3; if (iap->ia_valid & ATTR_SIZE) { bmval0 |= FATTR4_WORD0_SIZE; WRITE64(iap->ia_size); } if (iap->ia_valid & ATTR_MODE) { bmval1 |= FATTR4_WORD1_MODE; WRITE32(iap->ia_mode & S_IALLUGO); } if (iap->ia_valid & ATTR_UID) { bmval1 |= FATTR4_WORD1_OWNER; WRITE32(owner_namelen); WRITEMEM(owner_name, owner_namelen); } if (iap->ia_valid & ATTR_GID) { bmval1 |= FATTR4_WORD1_OWNER_GROUP; WRITE32(owner_grouplen); WRITEMEM(owner_group, owner_grouplen); } if (iap->ia_valid & ATTR_ATIME_SET) { bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; WRITE32(NFS4_SET_TO_CLIENT_TIME); WRITE32(0); WRITE32(iap->ia_mtime.tv_sec); WRITE32(iap->ia_mtime.tv_nsec); } else if (iap->ia_valid & ATTR_ATIME) { bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; WRITE32(NFS4_SET_TO_SERVER_TIME); } if (iap->ia_valid & ATTR_MTIME_SET) { bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; WRITE32(NFS4_SET_TO_CLIENT_TIME); WRITE32(0); WRITE32(iap->ia_mtime.tv_sec); WRITE32(iap->ia_mtime.tv_nsec); } else if (iap->ia_valid & ATTR_MTIME) { bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; WRITE32(NFS4_SET_TO_SERVER_TIME); } /* * Now we backfill the bitmap and the attribute buffer length. */ if (len != ((char *)p - (char *)q) + 4) { printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n", len, ((char *)p - (char *)q) + 4); BUG(); } len = (char *)p - (char *)q - 12; *q++ = htonl(bmval0); *q++ = htonl(bmval1); *q++ = htonl(len); status = 0;/* out: */ return status;}static int encode_access(struct xdr_stream *xdr, u32 access){ __be32 *p; RESERVE_SPACE(8); WRITE32(OP_ACCESS); WRITE32(access); return 0;}static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg){ __be32 *p; RESERVE_SPACE(8+NFS4_STATEID_SIZE); WRITE32(OP_CLOSE); WRITE32(arg->seqid->sequence->counter); WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); return 0;}static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args){ __be32 *p; RESERVE_SPACE(16); WRITE32(OP_COMMIT); WRITE64(args->offset); WRITE32(args->count); return 0;}static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create){ __be32 *p; RESERVE_SPACE(8); WRITE32(OP_CREATE); WRITE32(create->ftype); switch (create->ftype) { case NF4LNK: RESERVE_SPACE(4); WRITE32(create->u.symlink.len); xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); break; case NF4BLK: case NF4CHR: RESERVE_SPACE(8); WRITE32(create->u.device.specdata1); WRITE32(create->u.device.specdata2); break; default: break; } RESERVE_SPACE(4 + create->name->len); WRITE32(create->name->len); WRITEMEM(create->name->name, create->name->len); return encode_attrs(xdr, create->attrs, create->server);}static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap){ __be32 *p; RESERVE_SPACE(12); WRITE32(OP_GETATTR); WRITE32(1); WRITE32(bitmap); return 0;}static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1){ __be32 *p; RESERVE_SPACE(16); WRITE32(OP_GETATTR); WRITE32(2); WRITE32(bm0); WRITE32(bm1); return 0;}static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask){ return encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], bitmask[1] & nfs4_fattr_bitmap[1]);}static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask){ return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], bitmask[1] & nfs4_fsinfo_bitmap[1]);}static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask){ return encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0], bitmask[1] & nfs4_fs_locations_bitmap[1]);}static int encode_getfh(struct xdr_stream *xdr){ __be32 *p; RESERVE_SPACE(4); WRITE32(OP_GETFH); return 0;}static int encode_link(struct xdr_stream *xdr, const struct qstr *name){ __be32 *p; RESERVE_SPACE(8 + name->len); WRITE32(OP_LINK); WRITE32(name->len); WRITEMEM(name->name, name->len); return 0;}static inline int nfs4_lock_type(struct file_lock *fl, int block){ if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) return block ? NFS4_READW_LT : NFS4_READ_LT; return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;}static inline uint64_t nfs4_lock_length(struct file_lock *fl){ if (fl->fl_end == OFFSET_MAX) return ~(uint64_t)0; return fl->fl_end - fl->fl_start + 1;}/* * opcode,type,reclaim,offset,length,new_lock_owner = 32 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 */static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args){ __be32 *p; RESERVE_SPACE(32); WRITE32(OP_LOCK); WRITE32(nfs4_lock_type(args->fl, args->block)); WRITE32(args->reclaim); WRITE64(args->fl->fl_start); WRITE64(nfs4_lock_length(args->fl)); WRITE32(args->new_lock_owner); if (args->new_lock_owner){ RESERVE_SPACE(4+NFS4_STATEID_SIZE+32); WRITE32(args->open_seqid->sequence->counter); WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE); WRITE32(args->lock_seqid->sequence->counter); WRITE64(args->lock_owner.clientid); WRITE32(16); WRITEMEM("lock id:", 8); WRITE64(args->lock_owner.id); } else { RESERVE_SPACE(NFS4_STATEID_SIZE+4); WRITEMEM(args->lock_stateid->data, NFS4_STATEID_SIZE); WRITE32(args->lock_seqid->sequence->counter); } return 0;}static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args){ __be32 *p; RESERVE_SPACE(52); WRITE32(OP_LOCKT); WRITE32(nfs4_lock_type(args->fl, 0)); WRITE64(args->fl->fl_start); WRITE64(nfs4_lock_length(args->fl)); WRITE64(args->lock_owner.clientid); WRITE32(16); WRITEMEM("lock id:", 8); WRITE64(args->lock_owner.id); return 0;}static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args){ __be32 *p; RESERVE_SPACE(12+NFS4_STATEID_SIZE+16); WRITE32(OP_LOCKU); WRITE32(nfs4_lock_type(args->fl, 0)); WRITE32(args->seqid->sequence->counter); WRITEMEM(args->stateid->data, NFS4_STATEID_SIZE); WRITE64(args->fl->fl_start); WRITE64(nfs4_lock_length(args->fl)); return 0;}static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name){ int len = name->len; __be32 *p; RESERVE_SPACE(8 + len); WRITE32(OP_LOOKUP); WRITE32(len); WRITEMEM(name->name, len); return 0;}static void encode_share_access(struct xdr_stream *xdr, int open_flags){ __be32 *p; RESERVE_SPACE(8); switch (open_flags & (FMODE_READ|FMODE_WRITE)) { case FMODE_READ: WRITE32(NFS4_SHARE_ACCESS_READ); break; case FMODE_WRITE: WRITE32(NFS4_SHARE_ACCESS_WRITE); break; case FMODE_READ|FMODE_WRITE: WRITE32(NFS4_SHARE_ACCESS_BOTH); break; default: BUG(); } WRITE32(0); /* for linux, share_deny = 0 always */}static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg){ __be32 *p; /* * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4, * owner 4 = 32 */ RESERVE_SPACE(8); WRITE32(OP_OPEN); WRITE32(arg->seqid->sequence->counter); encode_share_access(xdr, arg->open_flags); RESERVE_SPACE(28); WRITE64(arg->clientid); WRITE32(16); WRITEMEM("open id:", 8); WRITE64(arg->id);}static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg){ __be32 *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -