OPEN(一)
来源:互联网 发布:辐射4 ini优化 编辑:程序博客网 时间:2024/06/05 17:31
1.OPEN请求报文和应答报文中的数据
OPEN操作比较复杂,涉及到很多种特殊情况。按照RFC3530的规定,OPEN请求报文中需要包含下列数据:
struct OPEN4args { seqid4 seqid; // 这是一个序号,保证请求能够序列化. uint32_t share_access; // 这是用户请求的访问权限 uint32_t share_deny; // 一定不能有这些权限,Linux中固定设置为0. open_owner4 owner; // clientid + 这次OPEN操作的名称. openflag4 openhow; // 有两个取值:OPEN4_NOCREATE和OPEN4_CREATE open_claim4 claim; // 有四个取值:CLAIM_NULL、CLAIM_PREVIOUS、CLAIM_DELEGATE_CUR、CLAIM_DELEGATE_PREV};
owner包含两个字段:clientid和这次操作的名称, 服务器端可以根据clientid和OPEN操作的名称查找是否已经保存了这次操作的信息。seqid是OPEN操作的序号,保证多个OPEN操作序列化执行。share_access是用户打开文件时请求的访问权限,share_deny是为Windows share reservation设置的字段,Linux系统中这个字段固定为0。openhow表示如果文件不存在是否创建一个新文件。claim表示OPEN类型,按照按照claim值不同,OPEN操作分为四种类型。这篇文>章中,我们只讲解最常见的一种情况:打开服务器端存在的一个文件。这种请求中claim的类型是CLAIM_NULL。这种情况下,open_claim4中还包含了文件的名>称,这是我们要打开的文件。
按照RFC3530的规定,OPEN操作应答报文包含下列内容
struct OPEN4resok { stateid4 stateid; /* Stateid for open */ change_info4 cinfo; /* Directory Change Info */ uint32_t rflags; /* Result flags */ bitmap4 attrset; /* attributes on create */ open_delegation4 delegation; /* Info on any open delegation */};stateid固定长度为16字节,代表了这个打开的文件,后续发起READ、WRITE操作时需要将这个stateid包含在请求报文中,服务器根据stateid查找对应的>文件。cinfo包含了父目录的属性信息。rflags是一些标志位,目前定义了两个标志位:
const OPEN4_RESULT_CONFIRM = 0x00000002; // 应答报文中的stateid不能马上使用,需要发起OPEN_CONFIRM请求。
const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004; // 服务器支持POSIX文件锁
如果OPEN请求报文中openhow字段的值为NFS4_CREATE,则服务器端可以创建一个新的文件,应答消息中的attrset就包含了新创建文件的属性信息。应答消息最后一个字段是delegation的信息,RFC3530定义了三种取值:
OPEN_DELEGATE_NONE // 没有使用delegation
OPEN_DELEGATE_READ // 读操作使用的delegation
OPEN_DELEGATE_WRITE // 写操作使用的delegation
OPEN_DELEGATE_READ表示读操作中使用的delegation。如果文件以只读方式打开,则可以申请这种delegation。一个客户端的多个用户或者不同的客户端可以共享同一个OPEN_DELEGATE_READ,因为多个用户同时执行读操作不会造成冲突。当另外一个用户试图向文件中写入数据时服务器会回收OPEN_DELEGATE_READ。OPEN_DELEGATE_WRITE表示写操作中使用的delegation,OPEN_DELEGATE_WRITE只能被一个用户独占。当另一个用户向文件写入数据时服务器会回收OPEN_DELEGATE_WRITE。具体实现中,Linux没有实现OPEN_DELEGATE_WRITE。
2.客户端程序
客户端设置OPEN请求报文中数据的函数是nfs4_opendata_alloc(),这个函数的代码如下:
参数dentry:这是要打开的文件在客户端的目录项结构
参数sp:这表示客户端的一个用户,就是这个用户要打开文件
参数fmode:这是文件的打开权限,读权限还是写权限
参数flags:这是打开文件时指定的一些标志位,如O_CREAT表示如何文件不存在就创建一个新文件
参数attrs:这是为新创建的文件设置的属性信息,如访问权限。
参数gfp_mask:这是分配内存时使用的标志位
static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,struct nfs4_state_owner *sp, fmode_t fmode, int flags,const struct iattr *attrs,gfp_t gfp_mask){struct dentry *parent = dget_parent(dentry);// 获取父目录的目录项结构struct inode *dir = parent->d_inode;// 这是父目录的索引节点struct nfs_server *server = NFS_SERVER(dir);// 文件系统结构struct nfs4_opendata *p;p = kzalloc(sizeof(*p), gfp_mask);// 分配内存if (p == NULL)goto err;// 分配内存失败// 这时分配了一个nfs_seqid结构,暂时没有链接到nfs_seqid_counter中p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid, gfp_mask);if (p->o_arg.seqid == NULL)// seqid分配失败.goto err_free;nfs_sb_active(dentry->d_sb);p->dentry = dget(dentry);// 这是要打开文件的目录项结构p->dir = parent;// 设置父目录的索引节点p->owner = sp;// nfs4_state_owner结构atomic_inc(&sp->so_count);// 增加这个结构的引用计数p->o_arg.fh = NFS_FH(dir);// 父目录的文件句柄p->o_arg.open_flags = flags;// 打开目标文件时设置的标志信息,如O_CREATp->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);// 文件的访问模式p->o_arg.clientid = server->nfs_client->cl_clientid;// 这表示一个NFS客户端// nfs_seqid_counter的创建时间p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);// 这是客户端为nfs4_state_owner结构设置的编号p->o_arg.id.uniquifier = sp->so_seqid.owner_id;p->o_arg.name = &dentry->d_name;// 目标文件的名称p->o_arg.server = server;// nfs_server结构p->o_arg.bitmask = server->attr_bitmask;// NFS服务器端文件系统支持的属性信息p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];// 需要查找的基本属性信息p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;// 正常打开文件.// 这是为OPEN4_CREATE设置的信息if (attrs != NULL && attrs->ia_valid != 0) {__be32 verf[2];p->o_arg.u.attrs = &p->attrs;memcpy(&p->attrs, attrs, sizeof(p->attrs));verf[0] = jiffies;// 当前时间verf[1] = current->pid;// 进程的pidmemcpy(p->o_arg.u.verifier.data, verf,sizeof(p->o_arg.u.verifier.data));}p->c_arg.fh = &p->o_res.fh;p->c_arg.stateid = &p->o_res.stateid;p->c_arg.seqid = p->o_arg.seqid;nfs4_init_opendata_res(p);kref_init(&p->kref);return p;err_free:kfree(p);err:dput(parent);return NULL;}
函数encode_open()根据nfs4_opendata_alloc()设置的信息封装OPEN请求报文。
static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr){ encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr); // OPEN请求编号 encode_openhdr(xdr, arg); encode_opentype(xdr, arg); // openhow,取值为OPEN4_CREATE或者OPEN4_NOCREATE switch (arg->claim) { // claim 通常情况下取值是NFS4_OPEN_CLAIM_NULL case NFS4_OPEN_CLAIM_NULL: encode_claim_null(xdr, arg->name); break; case NFS4_OPEN_CLAIM_PREVIOUS: encode_claim_previous(xdr, arg->u.delegation_type); break; case NFS4_OPEN_CLAIM_DELEGATE_CUR: encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation); break; default: BUG(); }}
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 */ // 这是seqid encode_nfs4_seqid(xdr, arg->seqid); // arg->seqid->sequence->counter seqid // share_accessed 文件访问权限 只读 0x00000001 只写 0x00000002 读写 0x00000003 // share_deny = 0 always encode_share_access(xdr, arg->fmode); // 编码share_access和share_deny p = reserve_space(xdr, 36); p = xdr_encode_hyper(p, arg->clientid); // 编码clientid 8字节 *p++ = cpu_to_be32(24); // owner 长度固定为24字节 p = xdr_encode_opaque_fixed(p, "open id:", 8); // 8字节 *p++ = cpu_to_be32(arg->server->s_dev); // 4字节 // 设备号 *p++ = cpu_to_be32(arg->id.uniquifier); // nfs4_state_owner结构的编号 4字节 xdr_encode_hyper(p, arg->id.create_time); // nfs4_state_owner结构的创建时间 8字节}对照RFC3530的规定,请求报文中的owner字段由clientid和这次请求操作的名称两部分构成,名称字段长度固定为24字节,包含了字符串"open id:"(8字节)、NFS文件系统所在设备的设备号(4字节)、用户信息数据结构的编号(4字节)、用户信息结构的创建时间(8字节)。
- OPEN(一)
- Open vSwitch学习(一)
- Open Flash Chart 使用方法(一)
- OpenGL(Open Graphics Library) 一
- open-iscsi源码分析-iscsid(一)
- open-iscsi源码分析-iscsid(一)
- Open MPI之旅(一)
- Open GL es 学习(一)
- Open CV 学习记录(一)
- OPEN AS2环境搭建(一)
- Delphi Open Tools Api实例研究(一)
- Delphi Open Tools Api实例研究(一)
- Delphi Open Tools Api实例研究(一)
- Delphi Open Tools Api实例研究(一)
- JavaScript之关于window.open()应用(一)
- WebBrowser弹出窗口之(一) -- window.open( )
- 文件篇(一、fopen和open有什么区别? )
- OPen GL 学习 (一)2D纹理使用
- ThinkPHP中RBAC数据库详解
- android/linux 经典开发环境下载链接:Ubuntu+VMWare
- android中dip、dp、px、sp和屏幕密度
- ZOJ 2208 To and Fro
- 20130204ubuntu下安装,python-gevent
- OPEN(一)
- OceanBase中并发request处理的思考
- Ubuntu Server安装桌面GUI
- Linux&UNIX 上卸载 GoldenGate 的方法
- 怎么获取web-inf/upload/a.txt 文件?
- 在虚拟机上安装 Oracle 11g RAC 过程中遇 SCAN Name 配置错误的处理办法
- MVC中 ViewData、ViewBag、TempData的区别与联系
- Android--AudioManager控制音量
- Oracle 11.2.0.3 RAC环境 ORA-29280 错误解决办法