1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun================================ 4*4882a593SmuzhiyunOptimized MPEG Filesystem (OMFS) 5*4882a593Smuzhiyun================================ 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunOverview 8*4882a593Smuzhiyun======== 9*4882a593Smuzhiyun 10*4882a593SmuzhiyunOMFS is a filesystem created by SonicBlue for use in the ReplayTV DVR 11*4882a593Smuzhiyunand Rio Karma MP3 player. The filesystem is extent-based, utilizing 12*4882a593Smuzhiyunblock sizes from 2k to 8k, with hash-based directories. This 13*4882a593Smuzhiyunfilesystem driver may be used to read and write disks from these 14*4882a593Smuzhiyundevices. 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunNote, it is not recommended that this FS be used in place of a general 17*4882a593Smuzhiyunfilesystem for your own streaming media device. Native Linux filesystems 18*4882a593Smuzhiyunwill likely perform better. 19*4882a593Smuzhiyun 20*4882a593SmuzhiyunMore information is available at: 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun http://linux-karma.sf.net/ 23*4882a593Smuzhiyun 24*4882a593SmuzhiyunVarious utilities, including mkomfs and omfsck, are included with 25*4882a593Smuzhiyunomfsprogs, available at: 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun https://bobcopeland.com/karma/ 28*4882a593Smuzhiyun 29*4882a593SmuzhiyunInstructions are included in its README. 30*4882a593Smuzhiyun 31*4882a593SmuzhiyunOptions 32*4882a593Smuzhiyun======= 33*4882a593Smuzhiyun 34*4882a593SmuzhiyunOMFS supports the following mount-time options: 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun ============ ======================================== 37*4882a593Smuzhiyun uid=n make all files owned by specified user 38*4882a593Smuzhiyun gid=n make all files owned by specified group 39*4882a593Smuzhiyun umask=xxx set permission umask to xxx 40*4882a593Smuzhiyun fmask=xxx set umask to xxx for files 41*4882a593Smuzhiyun dmask=xxx set umask to xxx for directories 42*4882a593Smuzhiyun ============ ======================================== 43*4882a593Smuzhiyun 44*4882a593SmuzhiyunDisk format 45*4882a593Smuzhiyun=========== 46*4882a593Smuzhiyun 47*4882a593SmuzhiyunOMFS discriminates between "sysblocks" and normal data blocks. The sysblock 48*4882a593Smuzhiyungroup consists of super block information, file metadata, directory structures, 49*4882a593Smuzhiyunand extents. Each sysblock has a header containing CRCs of the entire 50*4882a593Smuzhiyunsysblock, and may be mirrored in successive blocks on the disk. A sysblock may 51*4882a593Smuzhiyunhave a smaller size than a data block, but since they are both addressed by the 52*4882a593Smuzhiyunsame 64-bit block number, any remaining space in the smaller sysblock is 53*4882a593Smuzhiyununused. 54*4882a593Smuzhiyun 55*4882a593SmuzhiyunSysblock header information:: 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun struct omfs_header { 58*4882a593Smuzhiyun __be64 h_self; /* FS block where this is located */ 59*4882a593Smuzhiyun __be32 h_body_size; /* size of useful data after header */ 60*4882a593Smuzhiyun __be16 h_crc; /* crc-ccitt of body_size bytes */ 61*4882a593Smuzhiyun char h_fill1[2]; 62*4882a593Smuzhiyun u8 h_version; /* version, always 1 */ 63*4882a593Smuzhiyun char h_type; /* OMFS_INODE_X */ 64*4882a593Smuzhiyun u8 h_magic; /* OMFS_IMAGIC */ 65*4882a593Smuzhiyun u8 h_check_xor; /* XOR of header bytes before this */ 66*4882a593Smuzhiyun __be32 h_fill2; 67*4882a593Smuzhiyun }; 68*4882a593Smuzhiyun 69*4882a593SmuzhiyunFiles and directories are both represented by omfs_inode:: 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun struct omfs_inode { 72*4882a593Smuzhiyun struct omfs_header i_head; /* header */ 73*4882a593Smuzhiyun __be64 i_parent; /* parent containing this inode */ 74*4882a593Smuzhiyun __be64 i_sibling; /* next inode in hash bucket */ 75*4882a593Smuzhiyun __be64 i_ctime; /* ctime, in milliseconds */ 76*4882a593Smuzhiyun char i_fill1[35]; 77*4882a593Smuzhiyun char i_type; /* OMFS_[DIR,FILE] */ 78*4882a593Smuzhiyun __be32 i_fill2; 79*4882a593Smuzhiyun char i_fill3[64]; 80*4882a593Smuzhiyun char i_name[OMFS_NAMELEN]; /* filename */ 81*4882a593Smuzhiyun __be64 i_size; /* size of file, in bytes */ 82*4882a593Smuzhiyun }; 83*4882a593Smuzhiyun 84*4882a593SmuzhiyunDirectories in OMFS are implemented as a large hash table. Filenames are 85*4882a593Smuzhiyunhashed then prepended into the bucket list beginning at OMFS_DIR_START. 86*4882a593SmuzhiyunLookup requires hashing the filename, then seeking across i_sibling pointers 87*4882a593Smuzhiyununtil a match is found on i_name. Empty buckets are represented by block 88*4882a593Smuzhiyunpointers with all-1s (~0). 89*4882a593Smuzhiyun 90*4882a593SmuzhiyunA file is an omfs_inode structure followed by an extent table beginning at 91*4882a593SmuzhiyunOMFS_EXTENT_START:: 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun struct omfs_extent_entry { 94*4882a593Smuzhiyun __be64 e_cluster; /* start location of a set of blocks */ 95*4882a593Smuzhiyun __be64 e_blocks; /* number of blocks after e_cluster */ 96*4882a593Smuzhiyun }; 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun struct omfs_extent { 99*4882a593Smuzhiyun __be64 e_next; /* next extent table location */ 100*4882a593Smuzhiyun __be32 e_extent_count; /* total # extents in this table */ 101*4882a593Smuzhiyun __be32 e_fill; 102*4882a593Smuzhiyun struct omfs_extent_entry e_entry; /* start of extent entries */ 103*4882a593Smuzhiyun }; 104*4882a593Smuzhiyun 105*4882a593SmuzhiyunEach extent holds the block offset followed by number of blocks allocated to 106*4882a593Smuzhiyunthe extent. The final extent in each table is a terminator with e_cluster 107*4882a593Smuzhiyunbeing ~0 and e_blocks being ones'-complement of the total number of blocks 108*4882a593Smuzhiyunin the table. 109*4882a593Smuzhiyun 110*4882a593SmuzhiyunIf this table overflows, a continuation inode is written and pointed to by 111*4882a593Smuzhiyune_next. These have a header but lack the rest of the inode structure. 112*4882a593Smuzhiyun 113