Logoaddress Study of cwfs table of contents 1.0.0 What is cwfs 2.0.0 cwfs console 2.1.0 Overview 2.2.0 backup of fsworm 3.0.0 Structure of fsworm 3.1.0 Block 3.2.0 dump stack 3.3.0 Super Block 3.4.0 Directory Entry Block 3.5.0 Indirect Block 3.6.0 File Block 3.7.0 Fsworm Root 3.8.0 Dump order 3.9.0 qid 4.0.0 Structure of fscache 4.1.0 Config Block 4.2.0 Tcache Block 4.3.0 Mapping 4.3.1 bucket 4.3.2 cache entry 4.3.3 age 4.3.4 state 4.4.0 free block and dirty block 4.5.0 msize and csize 4.6.0 Map from Worm to Cache 4.7.0 msize determination algorithm 4.8.0 Fscache Root 5.0.0 Recovery 5.1.0 recovery 5.2.0 Review on recovery 5.3.0 What is lost by Recovery 6.0.0 Other Configurations 6.1.0 pseudo-RAID 1 6.2.0 fake WORM 6.2.1 Creating fake WORM 6.3.0 Tvirgo 7.0.0 Misc. 7.1.0 What did I do that day? 7.2.0 atime 7.2.1 Plan 9 7.2.2 Linux 7.2.3 OSX 8.0.0 cwstudy 8.1.0 usage References 2012/10/20 2013/03/14 renewal Updated on March 20, 2013 Updated 2013/04/02 Updated 2013/04/10 2013/04/24 Update For the summer vacation in 2012, I was trying 9front's cwfs. cwfs consists of fscache and fsworm, but we decided to look it up from fsworm. The reason why you are more interested in fsworm is that information such as file history is placed in fsworm and recovery when fscache crashes is done based on fsworm. Of course, any device eventually will die. Backup is necessary for fsworm. It may be possible to put cwfs itself in RAID, but it's too overkill for me. Add another HDD and want to have a copy of fsworm there. So, how can we copy it in a short time? I wanted to elucidate this problem. The cwfs attached to 9front is cwfs64x. Therefore, we will explain it based on cwfs64x. Note: This article is just my memo so far. Of course, it may contain errors. I would be pleased if you let me know if you find an error. What is cwfs This section is incomplete. I will write it in my spare time. Figure 1. layer Sean Quinlan (Ph.D) Ken Thompson (Ken's fs) Plan 9 2nd edition (1995) Geoff Collyer (2007/03/27 mail) 9front (2011) Past History WORM (write once read many) It will not disappear (can not be erased) dump Comparison with Mac / OSX time machine pdumpfs Previously we had one assigned for the server. memory: Memory in the dedicated file server disk: disk cache WORM: Optical disc Currently it runs under Plan 9 user program cwfs Advantages of being a user program: It is easy to check the mechanism. memory: memory in cwfs daemon disk: fscache partition of file server WORM: File server fsworm partition cwfs (or cwfs32) cwfs64 cwfs64x cwfs console Overview The size of my partition on cwfs is as follows. term% ls - l / dev / sdC 0 / fs * - rw - r ---- - S 0 arisawa arisawa 22848146432 Sep 13 09: 50 / dev / sdC 0 / fscache - rw - r ----- S 0 arisawa arisawa 114240734208 Sep 13 09: 50 / dev / sdC 0 / fsworm term% The cwfs console uses commands con -C /srv/cwfs.cmd You will be able to use with. Note: Create one new window cat /srv/cwfs.cmd Run it from another window echo statw >> /srv/cwfs.cmd May be executed. Distribution seems to assume this method. Running statw on the cwfs console will output usage statistics for fsworm. Next, an example of the output is shown. > statw cwstats main filesys main maddr = 3 msize = 10313 caddr = 1035 csize = 1392255 sbaddr = 1755217 craddr = 1755389 1755389 roaddr = 1755392 1755392 fsize = 1755394 1755394 0 + 25% slast = 1754642 snext = 1755393 wmax = 1755392 0 + 25% wsize = 6972701 1 + 0% 8600 none 230005 dirty 0 dump 1153555 read 95 write 0 dump1 cache 17% full > Figure 2. Example of statw output from the cwfs console. The prompt " > " is not issued in the official distribution version. I am trying to go out with a modified version by the author. The numbers on the right of the equal sign ( maddr to wsize ) (the first and second columns) represent the size. The information of the number in the first column is obtained from Tcache block (block address 2) of Tcache . The second column is obtained from fsworm Note 1 . These units are block except for msize . Only msize is a bucket number. Note 1: This part is incorrect. The second row is also obtained from fscache. The cache of the last super block of fsworm is included in fscache and this is displayed. fsize for fsize , the information in the second column matches the information obtained from the last super block. fsize is the value at the time of executing the statw command, which is consistent with fsize obtained from the Tcache block of Tcache . (2013/04/24) Notice that fsworm does not include information on fsworm's partition size. It may be replaced by a larger partition when fsworm is full, so in that case it would be designed to just copy the contents of the full partition to the new partition . Both fscache and fsworm are managed in block units. In the case of cwfs64x, 1 block is 16 KB. Hereinafter, block is represented by an address. ba[0] means the first block, and ba[1] means the second block. wsize 6972701 /dev/sdC0/fsworm the size of /dev/sdC0/fsworm the number of blocks. 6972701 * 16 * 1024 == 114240733184 This is 1024 less than the actual size of /dev/sdC0/fsworm , but since it is being used as a unit, an unusable area has occurred. It should be noted that there is no concept of format in fsworm. Because it is Write Once, after formatting it can not write data! 3 It is written to fsworm in order from the top block. snext (next super block) indicates the next block to be written. When you dump, a block called super block is written first, followed by the body of the data. Super block serves as a boundary for every dump and plays a fundamental role in fsworm. sbaddr (super block address) is the address of the super block written last. Also, slast is the address of the preceding super block. Note 2: The block managed by cwfs is different from the block as the unit of reading / writing managed by the driver. Note 3: WORM in its original meaning will not be used recently. The significance of the existence of an optical disk as a backup medium has disappeared, substituting WORM for a hard task is low cost and easy to use. The following explanation also assumes the use of a hard disk. Backup of fsworm Revised 2013/03/06 Although fsworm is very robust (in its mechanism), it still has the risk of data loss due to hardware crashes. To do the backup you have a copy of fsworm (eg fsworm-bak). For each dump, you might think that you can copy only the newly created block in fsworm, but the story is not that easy. This is because unwritten blocks exist under the last dumped super block. In my observation there are two kinds of them. (a) reserved blockNote 1 (b) free block . (a) is a block of fsworm that is used in fscache, but has not yet completed dump. (b) is a block of fsworm that fscache can use in the future. Note 1: "reserved block" is a term that I am using arbitrarily. This term does not exist in the literature. Structure of fsworm Block Both fscache and fsworm are managed in units of block. In the case of cwfs64x, 1 block is 16 KB. Hereinafter, block is represented by an address. ba[0] means the first block and ba[1] means the second block. Together, the first two blocks are special. The address of block is specified by 8 B data. In the program, the data type is indicated by Off . In the case of fscache, ba[0] contains config information. ba[1] seems not to be used. In the case of fsworm, there is no indication that the first 2 blocks are used. Each block has Tag . However, not all the blocks are formatted. The size of Tag is 12 B in the case of cwfs 64 x, and it is placed at the end of the block. Its structure is as follows. struct Tag { short pad; / * make tag end at a long boundary * / short tag; Off path; }; The value of pad is 0. tag indicates the type of block. path way of thinking about the value of path is different for each tag . The area excluding Tag 12B is a data area (hereinafter referred to as Data) from 16 KB and has a structure for each type of block. To summarize block = Data + Tag . Note 1: Recent HD has large capacity. Formatting all the blocks takes a huge amount of time. In addition, the WORM device can not write if formatted! dump stack 2013/02/28 When dump is repeated, dumped data is stacked on fsworm. Data will never be overwritten. The situation is shown in Fig. 3 (left). Figure 3. dump Hereinafter, the block of block address n is represented by ba[n] . ba[0] and ba[1] are not used. When cwfs is executed, first three blocks ba [2]: super block ba [3]: cfs root block ba [4]: ​​dump root block Is made. It does not contain information on files included in fscache. Note: The words "cfs root block" or "dump root block" do not appear in formal documents or program code. "Cfs root address" and "dump root address" appear. Blocks are stacked for each dump. We call the block that is stacked with one dump simply as dump. One dump always includes three blocks, "super block", "cfs root block", "dump root block". Figure 3 (right) shows the internal structure of dump. In the block between super block and cfs root block, the content of fscache is saved (only the difference updated from the previous dump). The block between the cfs root block and the dump root block contains information on the dumped date. The required number of blocks depends on the number of dumps. Super Block The most basic thing to capture the structure of fsworm is super block. The tag of super block is Tsuper (= 1). When we read the code of cwfs, the path the Tag of super block is QPSUPER (= 2). One super block is created when you dump fscache. First, super block is written to fsworm, then the body of the data is written block by block (right in Figure 3). The structure of super block struct Superb { Fbuf fbuf; Super 1; }; have. Fbuf has an array of addresses of free blocks inside. I will postpone commentary on free block. Super1 is important. struct Super 1 { Off fstart; Off fsize; Off tfree; Off qidgen; / * generator for unique ids * / / * * Stuff for WWC device * / Off cwraddr; / * cfs root addr * / Off roraddr; / * dump root addr * / Off last; / * last super block addr * / Off next; / * next super block addr * / }; Figure 4. Structure of Super1 As can be seen, each super block has the address ( next ) of the next super block. And the first super block starts with ba[2] . Therefore, if you follow the super block from ba[2] order, you will know the address to be dumped next. Next, an example of the output result is shown. (This tool will be introduced later) super blocks: 2 Five 69908 85793 104695 222009 ... 1751346 1754278 1754381 1754569 1754642 1755217 1755393 The last 1755393 is the super block address to be made next. The contents of Super1 ba[1755217] are (for example) as follows. super1 fstart: 2 super1 fsize: 1755394 super1 tfree: 92 super1 qidgen: 6d76e super1 cwraddr: 1755389 super1 roraddr: 1755392 super1 last: 1754642 super1 next: 1755393 Some of these information is also obtained from the cwfs console. sbaddr 1755217 : current super block (last written super block) snext 1755393 : The next dump schedule address (that is, the super block address to be created next) slast 1754642 : super block address one before the sbaddr Directory Entry Block Updated 2013/03/02 Next is the directory entry block. Tag.tag of this block is Tdir . Also, Tag.path matches the Tag.path of the parent directory. The directory entry block contains one or more of the following directory entries (Dentry) (up to 62 in the case of cwfs64x). struct Dentry { char name [NAMELEN]; Userid uid; Userid gid; ushort mode; #define DALLOC 0x8000 #define DDIR 0x4000 #define DAPND 0x2000 #define DLOCK 0x1000 #define DTMP 0x0800 #define DREAD 0x4 #define DWRITE 0x2 #define DEXEC 0x1 Userid muid; Qid 9 p 1 qid; Off size; Off dblock [NDBLOCK]; Off iblocks [NIBLOCK]; long atime; long mtime; }; Figure 5. Directory entry Since the names of files and directories are included here, the size of NAMELEN-1 depends on the allowable name length ( NAMELEN-1 ). The dump root block is one of directory entry blocks. In the case of my system at home, you can see the dumped date as follows. term% ls / n / dump / n / dump / 2012/0801 / n / dump / 2012/0802 / n / dump / 2012/0804 / n / dump / 2012/0813 .... / n / dump / 2013/0121 / n / dump / 2013/0127 / n / dump / 2013/0128 / n / dump / 2013/0205 .... The first line is generated for the first time on dump (August 1, 2012). ls - l / n / dump / 2012/0801 You can access the files on this day as follows. maia% ls - l / n / dump / 2012/0801 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801/386 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801/68000 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801/68020 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / acme d-rwxrwxr-x M 495 adm adm 0 Jul 31 2012 / n / dump / 2012/0801 / adm .... d-rwxrwxr-x M 495 sys sys 0 Jan 18 2012 / n / dump / 2012/0801 / mnt d-rwxrwxr-x M 495 sys sys 0 Jan 18 2012 / n / dump / 2012/0801 / n d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / power d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / power64 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / rc d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / sparc d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / sparc 64 d-rwxrwxr-x M 495 sys sys 0 Jul 31 2012 / n / dump / 2012/0801 / sys dr-xr-xr-x M 495 sys sys 0 Jan 18 2012 / n / dump / 2012/0801 / tmp d-rwxrwxr-x M 495 sys sys 0 Aug 1 2012 / n / dump / 2012/0801 / usr maia% Figure 6. ls / n / dump The dumped date information ( YYYY/MMDD ) is between dump root address and cfs root address. (Figure 3) In this case, blocks are connected as shown in the next figure 7. Figure 7. Connection of directory entry block A rectangle represents one block. In this figure, none is a directory entry block. Since the number of dumps is still small, the date information of 2013 can be made in time with one directory entry block, but multiple blocks will be required within the time. In Plan 9, as you can see from the Dentry structure in Figure 5, the name of directory and the information such as mode live in the same block. On UNIX, on the other hand, information such as mode is placed in the inode and is a block different from the list of names (Fig. 8). The origin of this difference seems to be that in UNIX, in order to support hard link, it is necessary to have the link counter in another block (specifically, inode) different from the name. Figure 8. In the conceptual diagram of unix inode, we write contents as contents of file or other directory. Qid9p1 's Qid9p1 structure struct Qid 9 p 1 { Off path; / * was long * / ulong version; / * should be Off * / }; However, this path is set to 1 in the first bit when mode is a directory (that is, when mode&DDIR != 0 ). (I'm not sure about the reason why I designed this way.) The official qid, ie the command ls - ql The qid displayed is the one with the first bit of this qid.path , that is, qid.path&~DDIR . In the case of cwfs 64 x, one Dentry is 260 B. Therefore, one block can hold up to 62 Dentry . name contains the file name and directory name. NAMELEN is 144 in the case of cwfs NAMELEN x. Since the name ends with '\0' , the maximum length of the name is 143 characters. In addition to the name, basic information for directories and files is included in this. Dentry mode&DDIR == 0 represents a file ( mode&DDIR == 0 ), the block dblock[NDBLOCK] the file contents can be traced based on direct block ( dblock[NDBLOCK] ) and indirect block ( iblocks[NIBLOCK] ). The block containing the file contents is tagged with Tfile . Dentry mode&DDIR != 0 is a directory ( mode&DDIR != 0 ), the mode&DDIR != 0 in which the directory contents (the information of the files and directories contained therein) is placed is set to direct block ( dblock[NDBLOCK] ) and indirect block ( iblocks[NIBLOCK] ). The block containing the directory contents is tagged with Tdir . In the case of NDBLOCK the value of NDBLOCK is 6 and the value of NIBLOCK is 4. Data is directly written to 6 direct blocks. Because 16 * 1024 - 12 B data can be written in one direct block, 6 direct blocks can be written with a total of 6 * (16 * 1024 - 12) B data. In the case of a directory, up to 372 (= 62 * 6) Dentry can be handled. Indirect Block For the block indicated by iblocks[0] included in the iblocks[0] structure of the directory entry block, (16 * 1024 - 12) / 8 = 2046 Block addresses. Here, 8 is the size of one block address. ) These block addresses indicate the location of the data (ie direct block). Therefore 2046 * (16 * 1024 - 12) = 33497112 B Can be written. Let's say that such block information is the primary indirect block. iblocks[1] , a secondary indirect block is written. In other words, the block addresses are written in this block, but these addresses are the primary indirect block addresses (not the data location). Therefore 2046 * 2046 * (16 * 1024 - 12) = 68535091152 B Can be written. Likewise, iblocks[2] has 2046 * 2046 * 2046 * (16 * 1024 - 12) = 140222796496992 B And iblocks[3] has 2046 * 2046 * 2046 * 2046 * (16 * 1024 - 12) = 286895841632845632 B . The tag of indirect block iblocks [0] Tind 1 iblocks [1] Tind 2 iblocks [2] Tind 3 iblocks [3] Tind 4 . Also, any of these Tag.paths matches the qid of the parent directory. File Block The block containing the contents of the file is tagged with Tfile . Tag.path of this block matches the qid of the directory to which this file belongs. One file block has a maximum 16 * 1024 - 12 B File data can be saved. The contents of the file are managed in block unit. Will all blocks be rewritten when the contents of the file is updated? According to my experiment, it is not. If you add data to the end of a file larger than one block, only the last block is updated. Other blocks are used as they are. However, this experiment (a) The append attribute is specified in the file (b) writing at the end of the file by seeking at the end of the experiment under either condition. If I open a large file larger than 16 KB with a text editor and add data to the end, I think that it can be completely rewritten. (I have not done an experiment though ...) Characteristics of cwfs in which only rewritten blocks are newly generated is particularly important in servers. On my server, the log file of web server is 1.7 GB. 1757143424 Oct 18 17: 13 http It will not go on to keep copying files of this size every day1. Note 1: On Mac / OSX's Time Machine or Linux pdumpfs, if the file has been updated, a new copy of it will be made. If we try to realize the function of TimeMachine with only hard links, copy will be inevitable specification. Since the server carries a large log file which is updated day by day, it should not be suitable for server use at all. In the case of database files, even cwfs should be removed from daily dump. It is safer to log transactions. Fsworm Root 2013/03/09 All information on fsworm can be traced from the dump root block at the top of the dump stack. You can find out this address from roaddr of cwfs console. Figures 6 and 7 are the first part of the path seen from here. Actually roaddr is a root block managed by fscache, but it matches dump root block of fsworm. Dump order The dump is done based on the current fscache. First, super block is written to fsworm. Following this, the information at the end of the directory tree is written in order. Thus, in fsworm, for example / 2012/0925 / .... Is created, the last / before 2012 , before 0925 before that ... qid From the user, you can see the qid of the file or directory by adding q option to ls command. For example maia% ls - ql (000000000009 baa2 6 00) - rw - rw - r - M 326 web web 33597 Mar 8 15: 01 bucket.png (000000000009 baa 3 300) - rw - rw - r - M 326 web web 13693 Mar 8 15: 02 bucket.svg (0000000000089b8c 2 00) - rw - rw - r - M 326 arisawa web 782 Sep 28 10: 11 console.txt (0000000000089b8d 2 00) - rw - rw - r - M 326 arisawa web 2401 Oct 15 21:21 cwfs.svg ... maia% As shown in FIG. The part of hexadecimal notation in the head () is qid, and the next digit is qid version. According to the manual qid is unique within the file system. If it is unique, the qid must be managed. It seems that qidgen in super block is there for that (Figure 4). You can tell by experimenting but qid does not change by changing file name. Version changes when content changes. So, when creating an editor, you can use it to know whether or not you have changed by something else at the time of saving, but time stamp is easier, so I used qid so far There is nothing. (The qid of unix seems to be different) Except in fsworm and fscache, qid and its version are included in the directory entry (Figure 5), and you can see that the block concerning the contents is the same qid. That is, it seems to be used to confirm the affiliation of block. Structure of fscache ba [0] config ba [1] - ba [2] Tcache ba [maddr] map ... ba [caddr] cache ... Config Block 2013/03/05 As far as cwfs64x is concerned, the following data was written in the text format from the beginning in my config block ( ba[0] ). (This content can also be seen with the printconf command of cwfs console) service cwfs filsys main c (/ dev / sdC 0 / fscache) (/ dev / sdC 0 / fsworm) filsys dump o filsys other (/ dev / sdC 0 / other) noauth newcache blocksize 16384 daddrbits 64 indirblks 4 dirblks 6 namelen 144 noauth means allowing access to cwfs without authentication. noauth should be noted that noauth is a special setting only allowed at the experimental level in a secure environment. What I use at university is the February version of this year, which is not noauth . (2013/04/10) In addition, this block is tagged as follows. pad: 0000 tag: 10 (Tconfig) path: 0 The source code has the following structured data. struct Conf { ulong nmach; / * processors * / ulong nuid; / * distinct uids * / ulong nserve; / * server processes * / ulong nfile; / * number of fid - system wide * / ulong nwpath; / * number of active paths, derived from nfile * / ulong gidspace; / * space for gid names - derived from nuid * / ulong nlgmsg; / * number of large message buffers * / ulong nsmmsg; / * number of small message buffers * / Off recovcw; / * recover addresses * / Off recovro; Off firstsb; Off recovsb; ulong configfirst; / * configure before starting normal operation * / char * confdev; char * devmap; / * name of config-> file device mapping file * / uchar nodump; / * no periodic dumps * / uchar dumpreread; / * read and compare in dump copy * / uchar newcache; }; Data in this is given (in the source code) for each type of cwfs during the initialization process. Tcache Block Tcache block manages basic information about cwfs. You can see this in the cwfs console. struct Cache { Off maddr; / * cache map addr * / Off msize; / * cache map size in buckets * / Off caddr; / * cache addr * / Off csize; / * cache size * / Off fsize; / * current size of worm * / Off wsize; / * max size of the worm * / Off wmax; / * highwater write * / Off sbaddr; / * super block addr * / Off cwraddr; / * cw root addr * / Off roraddr; / * dump root addr * / Timet toytime; / * somewhere convienent * / Timet time; }; Each block of fscache is cached in memory. Every ten seconds the cache of memory is written to fscache (if there is an update). Mapping Updated 2013/03/08 Each block of fsworm is mapped to the cache block of the cache area of ​​FIG. Let cba be the cache block address of cba , cba caddr <= cba で表す。 以下の操作は新しい window の中で行うのが無難である。 fscons> users default fscons> newuser arisawa fscons> allow term% mount -c /srv/cwfs /n/cwfs term% mkdir /n/cwfs/adm term% cp /adm/users /n/cwfs/adm fscons> users 注意: newuser arisawaは、筆者のシステムの system owner はglendaではなくarisawaだから必要になったのであり、 glendaのままであれば不要である。 このあとは、筆者のcpdirを使うのが早い。 cpdir -mvug /root /n/cwfs adm 386 acme cfg cron lib mail rc sys /rootの下にあるfd 、 mnt 、 n 、 tmp 、 usrは個別に確認した方が無難である。 特に、 /root/n/の下にはcwfsが見えているはずである。 Tvirgo fakeworm の場合に��� cwfs console の statw で表示されるwsizeから、 Tvirgo block が始まる。 Tvirgo block は fsworm の block 0 からwsizeま での使用状況を bitmap で表している。書き込まれた block には bit 1 が立てられ、まだ書き込まれていない block の bit は 0 である。fsworm の先頭 2 block は書き込まれていないので、bitmap の最初の 2 bit は 0 である。 fakeworm は fsworm の末尾に bitmap が入り込むので、その分、 wsizeは小さくなる。 Misc. What did I do that day? 2013/03/18 「あの日は何をしていたのだろう?」と僕が考える場合には、ファイルの修正などの話であり、飲みに行ったとかの話ではない。 あの日に変更されたファイルを全て列挙するには、UNIX では find コマンドを使うと思う。膨大なファイルの中から、変更されたファイルを探し出す作業は(ファイルの量にもよるが)多くの時間を要し数秒では終わらない。ちなみに僕の MacBook では僕の$HOMEの探索だけでも30秒程要している。(結構たくさんのファイルを持っているせいもある) bash$ touch a.txt bash$ time find $HOME -newer a.txt -print find: /Users/arisawa/.emacs.d/auto-save-list: Permission denied /Users/arisawa/Library/Application Support/Google/Chrome/Default/Cookies ... ... find: /Users/arisawa/src/rminnich-vx32-17a064eed9c2/src/9vx/osx/9vx.app: Permission denied real 0m28.372s user 0m0.783s sys 0m18.783s bash$ ここで紹介するのは僕の作った lr コマンドであり、find の -newer オプションに相当するオプションが存在する。これを使って昨日に変更されたファイルをサーバーの全てのファイルの中から見つけるには次のようにする。 term% cpu -h ar ar% 9fs dump mounting as arisawa mounting as arisawa ar% ls /n/dump/2013|tail -2 /n/dump/2013/0317 /n/dump/2013/0318 ar% mtime /n/dump/2013/0317 1363498134 /n/dump/2013/0317 ar% time lr -lt 1363498134 /n/dump/2013/0318 ... ... --rw-rw-rw- web arisawa 5819730 2013/03/18 12:54:03 /n/dump/2013/0318/usr/cpa/www/log/dict d-rwxrwxrwx arisawa arisawa 0 2013/03/17 21:51:56 /n/dump/2013/0318/usr/cpa/www/users ... ... 0.01u 0.18s 1.91r lr -lt 1363498134 /n/dump/2013/0318 ar% この日には33個のファイルの変更があった。多くは log ファイルである。変更されたファイルの中には web の cgi に拠るものもある。システムの全てのファイルを探しているのだが2秒弱で探索が完了している。僕は膨大なファイルをサーバー上に持っているにも係わらずで ある! なぜこんなに高速に変更を調べられるのか? 探索にatimeが利用されているからである。 atimeとは access time の意味である。マニュアルを見てもそれ以上に詳しい説明はない。(Plan9 のマニュアルには read time と書いてあるが、write に対してもatimeが更新される) 注: lr は http://plan9.aichi-u.ac.jp/netlib/cmd/lr/ に置かれている。 atime 2013/06/06 実際の動作を見ていると、Plan9 と UNIX(MacOSX や Linux) で振る舞いが異なる。 Plan9 の場合には、ファイルサーバがファイルを探し出すために辿ったルートに存在する全てのディレクトリのatimeが更新されている。膨大な directory tree の中で、指定された日に実際にファイルサーバが辿った道は極く極く僅かである。従ってatimeを見ていれば、必要な探索のルートを大幅に減らす事が可能である。 UNIX では違う。ファイルサーバがファイルを探し出すために辿ったルートに存在するディレクトリのatimeは更新されていない。変更が実際に発生したディレクトリやファイルのatimeだけが更新されている。従って、 atimeを頼りに、更新を効率的に探し出す事はできない。 以下に、Plan9 と UNIX の atime の違いを具体例で示す。 Plan9 # Plan9 term% date; touch $home/doc/x;ls -dlu /usr $home/doc Wed Jun 5 07:58:17 JST 2013 d-rwxrwxr-x M 20 sys sys 0 Jun 5 07:58 /usr d-rwxrwxr-x M 20 arisawa arisawa 0 Jun 5 07:58 /usr/arisawa/doc term% Linux # UNIX (Linux) hebe$ date; touch $HOME/doc/x; ls -dlu /home $HOME/doc Wed Jun 5 07:56:41 JST 2013 drwxr-xr-x 3 root root 4096 Jun 4 09:49 /home drwxr-xr-x 9 arisawa arisawa 4096 Jun 5 07:46 /home/arisawa/doc hebe$ OSX # UNIX (OSX) -bash$ date; touch $HOME/doc/x; ls -dlu /Users $HOME/doc Wed Jun 5 08:08:27 JST 2013 drwxr-xr-x 6 root admin 204 May 31 07:51 /Users drwxr-xr-x 3 arisawa staff 102 Jun 5 08:03 /Users/arisawa/doc -bash$ cwstudy This section is incomplete. usage cwstudy block_address cwstudy -C block_address cwstudy path cwstudy super 文献 [1] Sean Quinlan “A Cached WORM File System” Softw., Pract. Exper., vol. 21 (1991), pp. 1289-1299 http://plan9.bell-labs.com/who/seanq/cw.pdf [2] Ken Thompson, Geoff Collyer “The 64-bit Standalone Plan 9 File Server” http://plan9.bell-labs.com/sys/doc/fs/fs.pdf