Coffee文件系统多处地方出现flags
,包括file_header->flags
、file_desc->flags
、file_desc->io_flags
、file->flags
,含义不相同,本文整理这些flags
。
1. cfs_open的flags
Coffee打开文件cfs_open
函数需要指定flags
,flags
可以取CFS_READ
、CFS_WRITE
、CFS_APPEND
之一或者组合,宏定义如下:
//int cfs_open(const char *name, int flags)
#define CFS_READ 1
#define CFS_WRITE 2
#define CFS_APPEND 4
CFS_READ
、CFS_WRITE
、CFS_APPEND
正好对应于COFFEE_FD_READ
、COFFEE_FD_WRITE
、COFFEE_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_READ
、COFFEE_FD_WRITE
、COFFEE_FD_APPEND
,源代码如下:
#define COFFEE_FD_FREE 0x0
#define COFFEE_FD_READ 0x1
#define COFFEE_FD_WRITE 0x2
#define COFFEE_FD_APPEND 0x4
事实上,后3个都没用到,而是用CFS_READ
、CFS_WRITE
、CFS_APPEND
代替。系统缓存file_desc
组织成一个数组coffee_fd_set[COFFEE_FD_SET_SIZE]
,当coffee_fd_set[i]->flags
为COFFEE_FD_FREE
,表示该FD可使用。
3. file->flags
file
的flags
只有两种取值:0
和COFFEE_FILE_MODIFIED
,将物理文件缓存时(load_file
函数,详情见博文《Coffee文件系统打开文件cfs_open》2.5节),如果物理文件元数据file_header
的flags
的M
位为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->flags
为COFFEE_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_AWARE
和CFS_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_desc
的io_flags
可以通过cfs_coffee_set_io_semantics()
函数来设置,源码如下,其中flag
是CFS_COFFEE_IO_FLASH_AWARE
和CFS_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_header
的flags
反应了物理文件的状态,用了6位,分别是ALOMIV
。但官方论文[1]与实际源码各位的位置不同,不过不影响分析,忠于源码就是了。file_header
的flags
两种版本示意图如下(visio源文件:Coffee的flags.vsd):
图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_header
的flags
各位都是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源代码