Chinaunix

标题: 系统调用close如何更新文件的属性和数据 [打印本页]

作者: panweiping    时间: 2010-08-04 20:42
标题: 系统调用close如何更新文件的属性和数据
我们经常说close(fd)系统调用执行完毕后,文件的数据都会写到硬盘上。
但是通过分析2.4.0的sys_close()代码(fs/open.c),发现两个问题:
1、inode对应的ext2_inode没有同步写回磁盘;
2、文件的脏的缓冲区即inode->i_dirty_buffers中的缓冲区没有同步写回磁盘。

sys_close()的调用流程:
-->filp_close()
       -->fput()
              (如果--file->f_count == 0)
              -->dput()
                     (如果--dentry->d_count==0)并且(list_empty(&dentry->d_hash为真)
                     -->dentry_iput()  
                            -->iput()
                                   (可能是,我不太确定)
                                   -->clear_inode()
                                          -->invalidate_inode_buffers()
下面的就不写了。其中invalidate_inode_buffers()只是将inode->i_dirty_buffers指向的链表中的每一项从该链表中删除,并没有将脏的缓冲区立即写到硬盘上。

是不是我遗漏了什么?要不然两个问题如何解释?
作者: bigrat023    时间: 2010-08-05 09:48
1145 int filp_close(struct file *filp, fl_owner_t id)
  1146 {
  1147     int retval = 0;
  1148
  1149     if (!file_count(filp)) {
  1150         printk(KERN_ERR "VFS: Close: file count is 0\n");
  1151         return 0;
  1152     }
  1153
  1154     if (filp->f_op && filp->f_op->flush)
  1155         retval = filp->f_op->flush(filp, id);
  1156
  1157     dnotify_flush(filp, id);
  1158     locks_remove_posix(filp, id);
  1159     fput(filp);
  1160     return retval;
  1161 }

第1155行调用flush,不就是把数据同步到硬盘吗?
作者: panweiping    时间: 2010-08-06 09:33
fs/ext2/file.c

59 /*
60  * We have mostly NULL's here: the current defaults are ok for
61  * the ext2 filesystem.
62  */
63 const struct file_operations ext2_file_operations = {
64     .llseek     = generic_file_llseek,
65     .read       = do_sync_read,
66     .write      = do_sync_write,
67     .aio_read   = generic_file_aio_read,
68     .aio_write  = generic_file_aio_write,
69     .unlocked_ioctl = ext2_ioctl,
70 #ifdef CONFIG_COMPAT
71     .compat_ioctl   = ext2_compat_ioctl,
72 #endif
73     .mmap       = generic_file_mmap,
74     .open       = dquot_file_open,
75     .release    = ext2_release_file,
76     .fsync      = ext2_fsync,
77     .splice_read    = generic_file_splice_read,
78     .splice_write   = generic_file_splice_write,
79 };

由此看filp->f_op->flush==NULL。
作者: cambyzju    时间: 2010-08-06 15:31
应该write back模式,是不保证写入磁盘的

否则,fsync等是不是就没意义了
man close
A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a filesystem to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2). (It will depend on the disk hardware at this point.)

回复 1# panweiping
作者: panweiping    时间: 2010-08-09 22:08
我觉得楼上的解释是正确的。
首先"close(fd)系统调用执行完毕后,文件的数据都会写到硬盘上"这种说法是不准确的。
因为我们一般是在程序里close(fd),然后用cat查看文件,其实此时cat得到的数据未必是磁盘上的,也可能是缓冲区中的。

顺便分析了以下2.4.0的sys_fsync()代码。
sys_fsync
   -->filemap_fdatasync
          -->ext2_writepage
                 -->__block_write_full_page
                       -->submit_bh
  -->ext2_sync_file
         -->fsync_inode_buffers
                -->ll_rw_block
                -->o_sync_inode_buffers
         -->ext2_sync_inode
                -->ext2_update_inode

这样,刷新缓冲区和更新inode都完成了。

谢谢cambyzju




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2