关闭文件

这篇博客详细介绍了NFS文件系统中与关闭文件相关的两个请求:CLOSE和OPEN_DOWNGRADE。CLOSE用于释放OPEN请求时申请的stateid,而OPEN_DOWNGRADE则表示用户释放部分访问权限。文中通过具体场景分析了何时发起CLOSE和OPEN_DOWNGRADE请求,并探讨了客户端和服务器端的代码实现,包括权限检查、状态更新和访问权限的调整等操作流程。
摘要由CSDN通过智能技术生成

1.CLOSE和OPEN_DOWNGRADE

    客户端用户执行完读写操作之后就需要关闭文件了,一般情况下客户端用户调用close(2)关闭文件。NFS文件系统中有两个请求与关闭文件相关:CLOSE和OPEN_DOWNGRADE。

CLOSE:这个请求的作用是释放OPEN请求中申请的stateid。客户端在OPEN操作中向服务器申请了stateid,stateid表示了客户端用户请求的对文件的访问权限。当执行CLOSE请求后,客户端用户就放弃了这种访问权限,就不能继续使用这个stateid读写文件了。如果想再次访问文件,必须再次执行OPEN操作申请访问权限。

OPEN_DOWNGRADE:表示用户释放了部分访问权限,比如用户申请了读权限和写权限,可以通过OPEN_DOWNGRADE放弃部分访问权限。


下面先以几个具体例子说明什么情况下会发起CLOSE请求,什么情况下会发起OPEN_DOWNGRADE请求。

情况1:

fd1 = open(file1, O_RDONLY);
close(fd1);
这是最简单的情况,当执行close(fd1)时会向服务器发起CLOSE请求。

情况2:

fd1 = open(file1, O_RDONLY);
fd2 = open(file1, O_RDWR);
close(fd2);
close(fd1);
执行close(fd2)时会向服务器发起OPEN_DOWNGRADE请求,放弃写权限。执行close(fd1)时会向服务器发起CLOSE请求。

情况3:

fd1 = open(file1, O_RDONLY);
fd2 = open(file1, O_RDWR);
close(fd1);
close(fd2);
执行close(fd1)时不会向服务器发起任何请求,因为fd2仍然需要读写权限,执行close(fd2)时会向服务器发起CLOSE请求。

情况4:

fd1 = open(file1, O_RDONLY);
fd2 = open(file1, O_RDONLY);
close(fd1);
close(fd2);

执行close(fd1)时不会向服务器发起任何请求,因为fd2仍然需要读权限,执行close(fd2)时会向服务器发起CLOSE请求。

总结:如果执行open(2)后用户的访问权限不变,则不会向服务器发起任何请求。如果执行open(2)后用户的访问权限变小了,但是仍有访问权限,则执行open(2)时向服务器发起OPEN_DOWNGRADE请求。如果执行open(2)后用户没有任何访问权限了,则执行open(2)时向服务器发起CLOSE请求。

情况5:

如果用户通过delegation访问文件,则关闭文件时不会执行任何请求。

user1:
fd1 = open(file1, O_RDONLY);
sleep(100);
close(fd1);

user2:
fd2 = open(file1, O_RDONLY);
close(fd2);

在这个例子中,user1先以只读权限打开了文件file1(假设服务器分配了delegation),然后等待了100秒。在user1等待的过程中user2也执行了open()操作,然后马上执行了close()。执行close(fd2)不会发起任何请求,执行close(fd1)时会向服务器发起CLOSE请求。

2.客户端代码

当用户执行close(2)时,客户端会执行到函数__nfs4_close(),这个函数代码如下:

参数state:这是OPEN操作中创建的nfs4_state结构,包含了申请的stateid.
参数fmode:这是关闭的访问权限。
参数gfp_mask:分配内存的标志位
参数wait:同步操作还是异步操作

static void __nfs4_close(struct nfs4_state *state,
                fmode_t fmode, gfp_t gfp_mask, int wait)
{
	// 找到nfs4_state_owner结构,这里包含了用户信息.
        struct nfs4_state_owner *owner = state->owner;
        int call_close = 0;
        fmode_t newstate;

        atomic_inc(&owner->so_count);           // 先增加引用计数,处理完毕后再减少引用计数.
        /* Protect against nfs4_find_state() */
        spin_lock(&owner->so_lock);             // 加锁
        // 先减少相应访问权限的计数.
        switch (fmode & (FMODE_READ | FMODE_WRITE)) {
                case FMODE_READ:        // 我们释放的是读权限
                        state->n_rdonly--;
                        break;
                case FMODE_WRITE:       // 我们释放的是写权限
                        state->n_wronly--;
                        break;
                case FMODE_READ|FMODE_WRITE:    // 我们释放的是读写权限
                        state->n_rdwr--;
        }

	// newstate表示剩余的访问权限
        newstate = FMODE_READ|FMODE_WRITE;
        // 读写权限的计数为0了,说明没有以O_RDWR权限打开文件的进程了
        if (state->n_rdwr == 0) {
                if (state->n_rdonly == 0) {     // 以O_RDONLY权限打开文件的进程数量也为0了
                        newstate &= ~FMODE_READ;	// 表示可以释放读权限了
                        call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
                        call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
                }
                if (state->n_wronly == 0) {     // 以O_WRONLY权限打开文件的进程数量为0了
                        newstate &= ~FMODE_WRITE;	// 表示可以释放写权限了
                        call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
                        call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
                }
                if (newstate == 0)
                        clear_bit(NFS_DELEGATED_STATE, &state->flags);
        }
	// 设置nfs4_state结构中现在的访问权限.
        nfs4_state_set_mode_locked(state, newstate);
        spin_unlock(&owner->so_lock);   // 解锁

        // 访问权限没有变化,不需要向服务器发起CLOSE或者OPEN_DOWNGRADE请求
        if (!call_close) {
                nfs4_put_open_state(state);     // 只需减少state引用计数就可以了,当计数减到0时释放内存.
                nfs4_put_state_owner(owner);    // 减少owner引用计数
        } else {
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值