Coffee文件系统多处地方出现flags,包括file_header->flagsfile_desc->flagsfile_desc->io_flagsfile->flags,含义不相同,本文整理这些flags

1. cfs_open的flags

Coffee打开文件cfs_open函数需要指定flagsflags可以取CFS_READCFS_WRITECFS_APPEND之一或者组合,宏定义如下:

//int cfs_open(const char *name, int flags)
#define CFS_READ     1
#define CFS_WRITE     2
#define CFS_APPEND     4

CFS_READCFS_WRITECFS_APPEND正好对应于COFFEE_FD_READCOFFEE_FD_WRITECOFFEE_FD_APPEND。纵观源代码,后3个都没用到,而是用前3个代替,看以下cfs_open函数语句就懂了:

//int cfs_open(const char *name, int flags)
fdp->flags |= flags;

2. file_desc->flags

file_desc->flags存储文件访问权限,系统定义了四个值:COFFEE_FD_READCOFFEE_FD_WRITECOFFEE_FD_APPEND,源代码如下:

#define COFFEE_FD_FREE         0x0
#define COFFEE_FD_READ         0x1
#define COFFEE_FD_WRITE     0x2
#define COFFEE_FD_APPEND     0x4

事实上,后3个都没用到,而是用CFS_READCFS_WRITECFS_APPEND代替。系统缓存file_desc组织成一个数组coffee_fd_set[COFFEE_FD_SET_SIZE],当coffee_fd_set[i]->flagsCOFFEE_FD_FREE,表示该FD可使用。

3. file->flags

fileflags只有两种取值:0COFFEE_FILE_MODIFIED,将物理文件缓存时(load_file函数,详情见博文《Coffee文件系统打开文件cfs_open》2.5节),如果物理文件元数据file_headerflagsM位为1的话(即物理文件被修改,日志存在),则file->flags设为COFFEE_FILE_MODIFIED,否则设为0。部分代码如下:

//load_file函数部分代码

file->flags = 0;
if(HDR_MODIFIED(*hdr))
{
  file->flags |= COFFEE_FILE_MODIFIED; //如果文件被修改(表示日志存在),#define COFFEE_FILE_MODIFIED 0x1
}

再看下面的代码就很清楚了,如果file->flagsCOFFEE_FILE_MODIFIED,返回真。

#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)

#define COFFEE_FILE_MODIFIED 0x1

4. file_desc->io_flags

4.1 COFFEE_IO_SEMANTICS

如果定义了COFFEE_IO_SEMANTICS,则在file_desc结构体会多一个成员变量io_flags,源码如下:

struct file_desc
{
  cfs_offset_t offset;
  struct file *file;
  uint8_t flags;
  #if COFFEE_IO_SEMANTICS
    uint8_t io_flags;
  #endif
};

配置了COFFEE_IO_SEMANTICS可以优化某些存储设备的文件访问(optimize file access on certain storage types),系统默认没有配置COFFEE_IO_SEMANTICS,源码如下:

4.2 file_desc->io_flags

系统定义了io_flags两个值,即CFS_COFFEE_IO_FLASH_AWARECFS_COFFEE_IO_FIRM_SIZE

(1)CFS_COFFEE_IO_FLASH_AWARE

/*Instruct Coffee that the access pattern to this file is adapted to flash I/O semantics by design, and Coffee should therefore not invoke its own micro logs when file modifications occur.This semantical I/O setting is useful when implementing flash storage algorithms on top of Coffee. */

#define CFS_COFFEE_IO_FLASH_AWARE 0x1

CFS_COFFEE_IO_FLASH_AWARE没看懂,需要阅读更多代码,后续补充。

(2)CFS_COFFEE_IO_FIRM_SIZE

/* A case when this is necessary is when the file has a firm size limit,and a safeguard is needed to protect against writes beyond this limit. */

#define CFS_COFFEE_IO_FIRM_SIZE 0x2

如果写入文件超过预留的大小,Coffee不会继续扩展文件。当文件有固定大小限制时,设置CFS_COFFEE_IO_FIRM_SIZE可以保护写超过。

file_descio_flags可以通过cfs_coffee_set_io_semantics()函数来设置,源码如下,其中flagCFS_COFFEE_IO_FLASH_AWARECFS_COFFEE_IO_FIRM_SIZE两者之一或全部。源码如下:

#if COFFEE_IO_SEMANTICS
  int cfs_coffee_set_io_semantics(int fd, unsigned flags)
  {
    if(!FD_VALID(fd))
    {
      return - 1;
    }

    coffee_fd_set[fd].io_flags |= flags;

    return 0;
  }
#endif

5. file_header->flags

file_headerflags反应了物理文件的状态,用了6位,分别是ALOMIV。但官方论文[1]与实际源码各位的位置不同,不过不影响分析,忠于源码就是了。file_headerflags两种版本示意图如下(visio源文件:Coffee的flags.vsd):

img

图1 file_header的flags两种版本

A(allocated)

如果该位被设置,表示文件正在使用。反之,当前页及所有保留页(直到下一个逻辑区的边界)是空闲的。

O(obsolete)

当文件被删除时,O标记保留页是无效的(obsolete)[2]。不是吧,这些页不用擦除就可以直接使用的,怎么说也应该标记成空闲free?

M(modified)

资料[1][2]居然没提这个标志,得根据源代码推测了:-( 在cfs-coffee.c的flags宏定义可得知,M表示文件已被修改,日志存在(Modified file, log exists)。

L(log)

L(log)标记文件已被修改,与微日志文件存在有关(and that a related log file exists)。不同于M,应该是指微日志的修改标志(待读源码确认)。

I(isolated)

I标记孤立的页,所有Coffee算法每次都会处理孤立的页面(Isolated pages are processed one at a time by all Coffee algorithms, and are treated the same way as obsolete files)

V(valid)

V(valid)标记文件头是完整的(helps by marking that the header data is complete),To discover garbled headers-typically caused by a system reboot during a header write operation。

注:这6个标志是有优先顺序的,依次是the valid flag(V)、the isolated flag(I), the obsolete flag(O),、the log flag(L)、the allocated flag(A)。(不晓得M该处于哪个位置)

为方便操作,Coffee将这些flags单独定义成宏,源代码如下(在cfs-coffee.c文件):

/* File header flags. */ 
#define HDR_FLAG_VALID         0x1 /* Completely written header. */ 
#define HDR_FLAG_ALLOCATED     0x2 /* Allocated file. */ 
#define HDR_FLAG_OBSOLETE     0x4 /* File marked for GC. */ 
#define HDR_FLAG_MODIFIED     0x8 /* Modified file, log exists. */ 
#define HDR_FLAG_LOG         0x10 /* Log file. */ 
#define HDR_FLAG_ISOLATED    0x20 /* Isolated page. */

Coffee定义了若干宏来判断文件的状态(依据file_header中的flags),如下:

/* File header macros. */ 
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))

#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)         //若V标志置1,则返回真 
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)    //若A标志置1,则返回真
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)    //若O标志置1,则返回真
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)    //若M标志置1,则返回真
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)        //若L标志置1,则返回真 
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)    //若I标志置1,则返回真 

#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) //若A标志置0,则返回真
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && !HDR_OBSOLETE(hdr) && !HDR_ISOLATED(hdr))//若A为1,O为0,I为0,则返回真

有个疑问,在Coffee格式化cfs_coffee_format中,将所有的逻辑区全部擦除,即file_header各成员变量填充为1,所以file_headerflags各位都是1。再结合上述宏定义,不免会发现矛盾之处。

参考资料:

[1] Tsiftes Nicolas,Dunkels Adam,He Zhitao.Enabling large-scale storage in sensor networks with the coffee file system[J].International Conference on Information Processing in Sensor Networks.2009,349-360

[2] Contiki源代码

本文系Spark & Shine原创,转载需注明出处本文最近一次修改时间 2022-03-22 22:34

results matching ""

    No results matching ""