diff options
Diffstat (limited to 'fs/logfs/logfs.h')
| -rw-r--r-- | fs/logfs/logfs.h | 725 |
1 files changed, 725 insertions, 0 deletions
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h new file mode 100644 index 000000000000..b84b0eec6024 --- /dev/null +++ b/fs/logfs/logfs.h | |||
| @@ -0,0 +1,725 @@ | |||
| 1 | /* | ||
| 2 | * fs/logfs/logfs.h | ||
| 3 | * | ||
| 4 | * As should be obvious for Linux kernel code, license is GPLv2 | ||
| 5 | * | ||
| 6 | * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> | ||
| 7 | * | ||
| 8 | * Private header for logfs. | ||
| 9 | */ | ||
| 10 | #ifndef FS_LOGFS_LOGFS_H | ||
| 11 | #define FS_LOGFS_LOGFS_H | ||
| 12 | |||
| 13 | #undef __CHECK_ENDIAN__ | ||
| 14 | #define __CHECK_ENDIAN__ | ||
| 15 | |||
| 16 | #include <linux/btree.h> | ||
| 17 | #include <linux/crc32.h> | ||
| 18 | #include <linux/fs.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/mempool.h> | ||
| 21 | #include <linux/pagemap.h> | ||
| 22 | #include <linux/mtd/mtd.h> | ||
| 23 | #include "logfs_abi.h" | ||
| 24 | |||
| 25 | #define LOGFS_DEBUG_SUPER (0x0001) | ||
| 26 | #define LOGFS_DEBUG_SEGMENT (0x0002) | ||
| 27 | #define LOGFS_DEBUG_JOURNAL (0x0004) | ||
| 28 | #define LOGFS_DEBUG_DIR (0x0008) | ||
| 29 | #define LOGFS_DEBUG_FILE (0x0010) | ||
| 30 | #define LOGFS_DEBUG_INODE (0x0020) | ||
| 31 | #define LOGFS_DEBUG_READWRITE (0x0040) | ||
| 32 | #define LOGFS_DEBUG_GC (0x0080) | ||
| 33 | #define LOGFS_DEBUG_GC_NOISY (0x0100) | ||
| 34 | #define LOGFS_DEBUG_ALIASES (0x0200) | ||
| 35 | #define LOGFS_DEBUG_BLOCKMOVE (0x0400) | ||
| 36 | #define LOGFS_DEBUG_ALL (0xffffffff) | ||
| 37 | |||
| 38 | #define LOGFS_DEBUG (0x01) | ||
| 39 | /* | ||
| 40 | * To enable specific log messages, simply define LOGFS_DEBUG to match any | ||
| 41 | * or all of the above. | ||
| 42 | */ | ||
| 43 | #ifndef LOGFS_DEBUG | ||
| 44 | #define LOGFS_DEBUG (0) | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #define log_cond(cond, fmt, arg...) do { \ | ||
| 48 | if (cond) \ | ||
| 49 | printk(KERN_DEBUG fmt, ##arg); \ | ||
| 50 | } while (0) | ||
| 51 | |||
| 52 | #define log_super(fmt, arg...) \ | ||
| 53 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SUPER, fmt, ##arg) | ||
| 54 | #define log_segment(fmt, arg...) \ | ||
| 55 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SEGMENT, fmt, ##arg) | ||
| 56 | #define log_journal(fmt, arg...) \ | ||
| 57 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_JOURNAL, fmt, ##arg) | ||
| 58 | #define log_dir(fmt, arg...) \ | ||
| 59 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_DIR, fmt, ##arg) | ||
| 60 | #define log_file(fmt, arg...) \ | ||
| 61 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_FILE, fmt, ##arg) | ||
| 62 | #define log_inode(fmt, arg...) \ | ||
| 63 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_INODE, fmt, ##arg) | ||
| 64 | #define log_readwrite(fmt, arg...) \ | ||
| 65 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_READWRITE, fmt, ##arg) | ||
| 66 | #define log_gc(fmt, arg...) \ | ||
| 67 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC, fmt, ##arg) | ||
| 68 | #define log_gc_noisy(fmt, arg...) \ | ||
| 69 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC_NOISY, fmt, ##arg) | ||
| 70 | #define log_aliases(fmt, arg...) \ | ||
| 71 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_ALIASES, fmt, ##arg) | ||
| 72 | #define log_blockmove(fmt, arg...) \ | ||
| 73 | log_cond(LOGFS_DEBUG & LOGFS_DEBUG_BLOCKMOVE, fmt, ##arg) | ||
| 74 | |||
| 75 | #define PG_pre_locked PG_owner_priv_1 | ||
| 76 | #define PagePreLocked(page) test_bit(PG_pre_locked, &(page)->flags) | ||
| 77 | #define SetPagePreLocked(page) set_bit(PG_pre_locked, &(page)->flags) | ||
| 78 | #define ClearPagePreLocked(page) clear_bit(PG_pre_locked, &(page)->flags) | ||
| 79 | |||
| 80 | /* FIXME: This should really be somewhere in the 64bit area. */ | ||
| 81 | #define LOGFS_LINK_MAX (1<<30) | ||
| 82 | |||
| 83 | /* Read-only filesystem */ | ||
| 84 | #define LOGFS_SB_FLAG_RO 0x0001 | ||
| 85 | #define LOGFS_SB_FLAG_DIRTY 0x0002 | ||
| 86 | #define LOGFS_SB_FLAG_OBJ_ALIAS 0x0004 | ||
| 87 | #define LOGFS_SB_FLAG_SHUTDOWN 0x0008 | ||
| 88 | |||
| 89 | /* Write Control Flags */ | ||
| 90 | #define WF_LOCK 0x01 /* take write lock */ | ||
| 91 | #define WF_WRITE 0x02 /* write block */ | ||
| 92 | #define WF_DELETE 0x04 /* delete old block */ | ||
| 93 | |||
| 94 | typedef u8 __bitwise level_t; | ||
| 95 | typedef u8 __bitwise gc_level_t; | ||
| 96 | |||
| 97 | #define LEVEL(level) ((__force level_t)(level)) | ||
| 98 | #define GC_LEVEL(gc_level) ((__force gc_level_t)(gc_level)) | ||
| 99 | |||
| 100 | #define SUBLEVEL(level) ( (void)((level) == LEVEL(1)), \ | ||
| 101 | (__force level_t)((__force u8)(level) - 1) ) | ||
| 102 | |||
| 103 | /** | ||
| 104 | * struct logfs_area - area management information | ||
| 105 | * | ||
| 106 | * @a_sb: the superblock this area belongs to | ||
| 107 | * @a_is_open: 1 if the area is currently open, else 0 | ||
| 108 | * @a_segno: segment number of area | ||
| 109 | * @a_written_bytes: number of bytes already written back | ||
| 110 | * @a_used_bytes: number of used bytes | ||
| 111 | * @a_ops: area operations (either journal or ostore) | ||
| 112 | * @a_erase_count: erase count | ||
| 113 | * @a_level: GC level | ||
| 114 | */ | ||
| 115 | struct logfs_area { /* a segment open for writing */ | ||
| 116 | struct super_block *a_sb; | ||
| 117 | int a_is_open; | ||
| 118 | u32 a_segno; | ||
| 119 | u32 a_written_bytes; | ||
| 120 | u32 a_used_bytes; | ||
| 121 | const struct logfs_area_ops *a_ops; | ||
| 122 | u32 a_erase_count; | ||
| 123 | gc_level_t a_level; | ||
| 124 | }; | ||
| 125 | |||
| 126 | /** | ||
| 127 | * struct logfs_area_ops - area operations | ||
| 128 | * | ||
| 129 | * @get_free_segment: fill area->ofs with the offset of a free segment | ||
| 130 | * @get_erase_count: fill area->erase_count (needs area->ofs) | ||
| 131 | * @erase_segment: erase and setup segment | ||
| 132 | */ | ||
| 133 | struct logfs_area_ops { | ||
| 134 | void (*get_free_segment)(struct logfs_area *area); | ||
| 135 | void (*get_erase_count)(struct logfs_area *area); | ||
| 136 | int (*erase_segment)(struct logfs_area *area); | ||
| 137 | }; | ||
| 138 | |||
| 139 | /** | ||
| 140 | * struct logfs_device_ops - device access operations | ||
| 141 | * | ||
| 142 | * @readpage: read one page (mm page) | ||
| 143 | * @writeseg: write one segment. may be a partial segment | ||
| 144 | * @erase: erase one segment | ||
| 145 | * @read: read from the device | ||
| 146 | * @erase: erase part of the device | ||
| 147 | */ | ||
| 148 | struct logfs_device_ops { | ||
| 149 | struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); | ||
| 150 | struct page *(*find_last_sb)(struct super_block *sb, u64 *ofs); | ||
| 151 | int (*write_sb)(struct super_block *sb, struct page *page); | ||
| 152 | int (*readpage)(void *_sb, struct page *page); | ||
| 153 | void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); | ||
| 154 | int (*erase)(struct super_block *sb, loff_t ofs, size_t len, | ||
| 155 | int ensure_write); | ||
| 156 | void (*sync)(struct super_block *sb); | ||
| 157 | void (*put_device)(struct super_block *sb); | ||
| 158 | }; | ||
| 159 | |||
| 160 | /** | ||
| 161 | * struct candidate_list - list of similar candidates | ||
| 162 | */ | ||
| 163 | struct candidate_list { | ||
| 164 | struct rb_root rb_tree; | ||
| 165 | int count; | ||
| 166 | int maxcount; | ||
| 167 | int sort_by_ec; | ||
| 168 | }; | ||
| 169 | |||
| 170 | /** | ||
| 171 | * struct gc_candidate - "candidate" segment to be garbage collected next | ||
| 172 | * | ||
| 173 | * @list: list (either free of low) | ||
| 174 | * @segno: segment number | ||
| 175 | * @valid: number of valid bytes | ||
| 176 | * @erase_count: erase count of segment | ||
| 177 | * @dist: distance from tree root | ||
| 178 | * | ||
| 179 | * Candidates can be on two lists. The free list contains electees rather | ||
| 180 | * than candidates - segments that no longer contain any valid data. The | ||
| 181 | * low list contains candidates to be picked for GC. It should be kept | ||
| 182 | * short. It is not required to always pick a perfect candidate. In the | ||
| 183 | * worst case GC will have to move more data than absolutely necessary. | ||
| 184 | */ | ||
| 185 | struct gc_candidate { | ||
| 186 | struct rb_node rb_node; | ||
| 187 | struct candidate_list *list; | ||
| 188 | u32 segno; | ||
| 189 | u32 valid; | ||
| 190 | u32 erase_count; | ||
| 191 | u8 dist; | ||
| 192 | }; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * struct logfs_journal_entry - temporary structure used during journal scan | ||
| 196 | * | ||
| 197 | * @used: | ||
| 198 | * @version: normalized version | ||
| 199 | * @len: length | ||
| 200 | * @offset: offset | ||
| 201 | */ | ||
| 202 | struct logfs_journal_entry { | ||
| 203 | int used; | ||
| 204 | s16 version; | ||
| 205 | u16 len; | ||
| 206 | u16 datalen; | ||
| 207 | u64 offset; | ||
| 208 | }; | ||
| 209 | |||
| 210 | enum transaction_state { | ||
| 211 | CREATE_1 = 1, | ||
| 212 | CREATE_2, | ||
| 213 | UNLINK_1, | ||
| 214 | UNLINK_2, | ||
| 215 | CROSS_RENAME_1, | ||
| 216 | CROSS_RENAME_2, | ||
| 217 | TARGET_RENAME_1, | ||
| 218 | TARGET_RENAME_2, | ||
| 219 | TARGET_RENAME_3 | ||
| 220 | }; | ||
| 221 | |||
| 222 | /** | ||
| 223 | * struct logfs_transaction - essential fields to support atomic dirops | ||
| 224 | * | ||
| 225 | * @ino: target inode | ||
| 226 | * @dir: inode of directory containing dentry | ||
| 227 | * @pos: pos of dentry in directory | ||
| 228 | */ | ||
| 229 | struct logfs_transaction { | ||
| 230 | enum transaction_state state; | ||
| 231 | u64 ino; | ||
| 232 | u64 dir; | ||
| 233 | u64 pos; | ||
| 234 | }; | ||
| 235 | |||
| 236 | /** | ||
| 237 | * struct logfs_shadow - old block in the shadow of a not-yet-committed new one | ||
| 238 | * @old_ofs: offset of old block on medium | ||
| 239 | * @new_ofs: offset of new block on medium | ||
| 240 | * @ino: inode number | ||
| 241 | * @bix: block index | ||
| 242 | * @old_len: size of old block, including header | ||
| 243 | * @new_len: size of new block, including header | ||
| 244 | * @level: block level | ||
| 245 | */ | ||
| 246 | struct logfs_shadow { | ||
| 247 | u64 old_ofs; | ||
| 248 | u64 new_ofs; | ||
| 249 | u64 ino; | ||
| 250 | u64 bix; | ||
| 251 | int old_len; | ||
| 252 | int new_len; | ||
| 253 | gc_level_t gc_level; | ||
| 254 | }; | ||
| 255 | |||
| 256 | /** | ||
| 257 | * struct shadow_tree | ||
| 258 | * @new: shadows where old_ofs==0, indexed by new_ofs | ||
| 259 | * @old: shadows where old_ofs!=0, indexed by old_ofs | ||
| 260 | */ | ||
| 261 | struct shadow_tree { | ||
| 262 | struct btree_head64 new; | ||
| 263 | struct btree_head64 old; | ||
| 264 | }; | ||
| 265 | |||
| 266 | struct object_alias_item { | ||
| 267 | struct list_head list; | ||
| 268 | __be64 val; | ||
| 269 | int child_no; | ||
| 270 | }; | ||
| 271 | |||
| 272 | /** | ||
| 273 | * struct logfs_block - contains any block state | ||
| 274 | * @type: indirect block or inode | ||
| 275 | * @full: number of fully populated children | ||
| 276 | * @partial: number of partially populated children | ||
| 277 | * | ||
| 278 | * Most blocks are directly represented by page cache pages. But when a block | ||
| 279 | * becomes dirty, is part of a transaction, contains aliases or is otherwise | ||
| 280 | * special, a struct logfs_block is allocated to track the additional state. | ||
| 281 | * Inodes are very similar to indirect blocks, so they can also get one of | ||
| 282 | * these structures added when appropriate. | ||
| 283 | */ | ||
| 284 | #define BLOCK_INDIRECT 1 /* Indirect block */ | ||
| 285 | #define BLOCK_INODE 2 /* Inode */ | ||
| 286 | struct logfs_block_ops; | ||
| 287 | struct logfs_block { | ||
| 288 | struct list_head alias_list; | ||
| 289 | struct list_head item_list; | ||
| 290 | struct super_block *sb; | ||
| 291 | u64 ino; | ||
| 292 | u64 bix; | ||
| 293 | level_t level; | ||
| 294 | struct page *page; | ||
| 295 | struct inode *inode; | ||
| 296 | struct logfs_transaction *ta; | ||
| 297 | unsigned long alias_map[LOGFS_BLOCK_FACTOR / BITS_PER_LONG]; | ||
| 298 | struct logfs_block_ops *ops; | ||
| 299 | int full; | ||
| 300 | int partial; | ||
| 301 | int reserved_bytes; | ||
| 302 | }; | ||
| 303 | |||
| 304 | typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix, | ||
| 305 | level_t level, int child_no, __be64 val); | ||
| 306 | struct logfs_block_ops { | ||
| 307 | void (*write_block)(struct logfs_block *block); | ||
| 308 | gc_level_t (*block_level)(struct logfs_block *block); | ||
| 309 | void (*free_block)(struct super_block *sb, struct logfs_block*block); | ||
| 310 | int (*write_alias)(struct super_block *sb, | ||
| 311 | struct logfs_block *block, | ||
| 312 | write_alias_t *write_one_alias); | ||
| 313 | }; | ||
| 314 | |||
| 315 | struct logfs_super { | ||
| 316 | struct mtd_info *s_mtd; /* underlying device */ | ||
| 317 | struct block_device *s_bdev; /* underlying device */ | ||
| 318 | const struct logfs_device_ops *s_devops;/* device access */ | ||
| 319 | struct inode *s_master_inode; /* inode file */ | ||
| 320 | struct inode *s_segfile_inode; /* segment file */ | ||
| 321 | struct inode *s_mapping_inode; /* device mapping */ | ||
| 322 | atomic_t s_pending_writes; /* outstanting bios */ | ||
| 323 | long s_flags; | ||
| 324 | mempool_t *s_btree_pool; /* for btree nodes */ | ||
| 325 | mempool_t *s_alias_pool; /* aliases in segment.c */ | ||
| 326 | u64 s_feature_incompat; | ||
| 327 | u64 s_feature_ro_compat; | ||
| 328 | u64 s_feature_compat; | ||
| 329 | u64 s_feature_flags; | ||
| 330 | u64 s_sb_ofs[2]; | ||
| 331 | struct page *s_erase_page; /* for dev_bdev.c */ | ||
| 332 | /* alias.c fields */ | ||
| 333 | struct btree_head32 s_segment_alias; /* remapped segments */ | ||
| 334 | int s_no_object_aliases; | ||
| 335 | struct list_head s_object_alias; /* remapped objects */ | ||
| 336 | struct btree_head128 s_object_alias_tree; /* remapped objects */ | ||
| 337 | struct mutex s_object_alias_mutex; | ||
| 338 | /* dir.c fields */ | ||
| 339 | struct mutex s_dirop_mutex; /* for creat/unlink/rename */ | ||
| 340 | u64 s_victim_ino; /* used for atomic dir-ops */ | ||
| 341 | u64 s_rename_dir; /* source directory ino */ | ||
| 342 | u64 s_rename_pos; /* position of source dd */ | ||
| 343 | /* gc.c fields */ | ||
| 344 | long s_segsize; /* size of a segment */ | ||
| 345 | int s_segshift; /* log2 of segment size */ | ||
| 346 | long s_segmask; /* 1 << s_segshift - 1 */ | ||
| 347 | long s_no_segs; /* segments on device */ | ||
| 348 | long s_no_journal_segs; /* segments used for journal */ | ||
| 349 | long s_no_blocks; /* blocks per segment */ | ||
| 350 | long s_writesize; /* minimum write size */ | ||
| 351 | int s_writeshift; /* log2 of write size */ | ||
| 352 | u64 s_size; /* filesystem size */ | ||
| 353 | struct logfs_area *s_area[LOGFS_NO_AREAS]; /* open segment array */ | ||
| 354 | u64 s_gec; /* global erase count */ | ||
| 355 | u64 s_wl_gec_ostore; /* time of last wl event */ | ||
| 356 | u64 s_wl_gec_journal; /* time of last wl event */ | ||
| 357 | u64 s_sweeper; /* current sweeper pos */ | ||
| 358 | u8 s_ifile_levels; /* max level of ifile */ | ||
| 359 | u8 s_iblock_levels; /* max level of regular files */ | ||
| 360 | u8 s_data_levels; /* # of segments to leaf block*/ | ||
| 361 | u8 s_total_levels; /* sum of above three */ | ||
| 362 | struct btree_head32 s_cand_tree; /* all candidates */ | ||
| 363 | struct candidate_list s_free_list; /* 100% free segments */ | ||
| 364 | struct candidate_list s_reserve_list; /* Bad segment reserve */ | ||
| 365 | struct candidate_list s_low_list[LOGFS_NO_AREAS];/* good candidates */ | ||
| 366 | struct candidate_list s_ec_list; /* wear level candidates */ | ||
| 367 | struct btree_head32 s_reserved_segments;/* sb, journal, bad, etc. */ | ||
| 368 | /* inode.c fields */ | ||
| 369 | u64 s_last_ino; /* highest ino used */ | ||
| 370 | long s_inos_till_wrap; | ||
| 371 | u32 s_generation; /* i_generation for new files */ | ||
| 372 | struct list_head s_freeing_list; /* inodes being freed */ | ||
| 373 | /* journal.c fields */ | ||
| 374 | struct mutex s_journal_mutex; | ||
| 375 | void *s_je; /* journal entry to compress */ | ||
| 376 | void *s_compressed_je; /* block to write to journal */ | ||
| 377 | u32 s_journal_seg[LOGFS_JOURNAL_SEGS]; /* journal segments */ | ||
| 378 | u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ | ||
| 379 | u64 s_last_version; | ||
| 380 | struct logfs_area *s_journal_area; /* open journal segment */ | ||
| 381 | __be64 s_je_array[64]; | ||
| 382 | int s_no_je; | ||
| 383 | |||
| 384 | int s_sum_index; /* for the 12 summaries */ | ||
| 385 | struct shadow_tree s_shadow_tree; | ||
| 386 | int s_je_fill; /* index of current je */ | ||
| 387 | /* readwrite.c fields */ | ||
| 388 | struct mutex s_write_mutex; | ||
| 389 | int s_lock_count; | ||
| 390 | mempool_t *s_block_pool; /* struct logfs_block pool */ | ||
| 391 | mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ | ||
| 392 | /* | ||
| 393 | * Space accounting: | ||
| 394 | * - s_used_bytes specifies space used to store valid data objects. | ||
| 395 | * - s_dirty_used_bytes is space used to store non-committed data | ||
| 396 | * objects. Those objects have already been written themselves, | ||
| 397 | * but they don't become valid until all indirect blocks up to the | ||
| 398 | * journal have been written as well. | ||
| 399 | * - s_dirty_free_bytes is space used to store the old copy of a | ||
| 400 | * replaced object, as long as the replacement is non-committed. | ||
| 401 | * In other words, it is the amount of space freed when all dirty | ||
| 402 | * blocks are written back. | ||
| 403 | * - s_free_bytes is the amount of free space available for any | ||
| 404 | * purpose. | ||
| 405 | * - s_root_reserve is the amount of free space available only to | ||
| 406 | * the root user. Non-privileged users can no longer write once | ||
| 407 | * this watermark has been reached. | ||
| 408 | * - s_speed_reserve is space which remains unused to speed up | ||
| 409 | * garbage collection performance. | ||
| 410 | * - s_dirty_pages is the space reserved for currently dirty pages. | ||
| 411 | * It is a pessimistic estimate, so some/most will get freed on | ||
| 412 | * page writeback. | ||
| 413 | * | ||
| 414 | * s_used_bytes + s_free_bytes + s_speed_reserve = total usable size | ||
| 415 | */ | ||
| 416 | u64 s_free_bytes; | ||
| 417 | u64 s_used_bytes; | ||
| 418 | u64 s_dirty_free_bytes; | ||
| 419 | u64 s_dirty_used_bytes; | ||
| 420 | u64 s_root_reserve; | ||
| 421 | u64 s_speed_reserve; | ||
| 422 | u64 s_dirty_pages; | ||
| 423 | /* Bad block handling: | ||
| 424 | * - s_bad_seg_reserve is a number of segments usually kept | ||
| 425 | * free. When encountering bad blocks, the affected segment's data | ||
| 426 | * is _temporarily_ moved to a reserved segment. | ||
| 427 | * - s_bad_segments is the number of known bad segments. | ||
| 428 | */ | ||
| 429 | u32 s_bad_seg_reserve; | ||
| 430 | u32 s_bad_segments; | ||
| 431 | }; | ||
| 432 | |||
| 433 | /** | ||
| 434 | * struct logfs_inode - in-memory inode | ||
| 435 | * | ||
| 436 | * @vfs_inode: struct inode | ||
| 437 | * @li_data: data pointers | ||
| 438 | * @li_used_bytes: number of used bytes | ||
| 439 | * @li_freeing_list: used to track inodes currently being freed | ||
| 440 | * @li_flags: inode flags | ||
| 441 | * @li_refcount: number of internal (GC-induced) references | ||
| 442 | */ | ||
| 443 | struct logfs_inode { | ||
| 444 | struct inode vfs_inode; | ||
| 445 | u64 li_data[LOGFS_EMBEDDED_FIELDS]; | ||
| 446 | u64 li_used_bytes; | ||
| 447 | struct list_head li_freeing_list; | ||
| 448 | struct logfs_block *li_block; | ||
| 449 | u32 li_flags; | ||
| 450 | u8 li_height; | ||
| 451 | int li_refcount; | ||
| 452 | }; | ||
| 453 | |||
| 454 | #define journal_for_each(__i) for (__i = 0; __i < LOGFS_JOURNAL_SEGS; __i++) | ||
| 455 | #define for_each_area(__i) for (__i = 0; __i < LOGFS_NO_AREAS; __i++) | ||
| 456 | #define for_each_area_down(__i) for (__i = LOGFS_NO_AREAS - 1; __i >= 0; __i--) | ||
| 457 | |||
| 458 | /* compr.c */ | ||
| 459 | int logfs_compress(void *in, void *out, size_t inlen, size_t outlen); | ||
| 460 | int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen); | ||
| 461 | int __init logfs_compr_init(void); | ||
| 462 | void logfs_compr_exit(void); | ||
| 463 | |||
| 464 | /* dev_bdev.c */ | ||
| 465 | #ifdef CONFIG_BLOCK | ||
| 466 | int logfs_get_sb_bdev(struct file_system_type *type, int flags, | ||
| 467 | const char *devname, struct vfsmount *mnt); | ||
| 468 | #else | ||
| 469 | static inline int logfs_get_sb_bdev(struct file_system_type *type, int flags, | ||
| 470 | const char *devname, struct vfsmount *mnt) | ||
| 471 | { | ||
| 472 | return -ENODEV; | ||
| 473 | } | ||
| 474 | #endif | ||
| 475 | |||
| 476 | /* dev_mtd.c */ | ||
| 477 | #ifdef CONFIG_MTD | ||
| 478 | int logfs_get_sb_mtd(struct file_system_type *type, int flags, | ||
| 479 | int mtdnr, struct vfsmount *mnt); | ||
| 480 | #else | ||
| 481 | static inline int logfs_get_sb_mtd(struct file_system_type *type, int flags, | ||
| 482 | int mtdnr, struct vfsmount *mnt) | ||
| 483 | { | ||
| 484 | return -ENODEV; | ||
| 485 | } | ||
| 486 | #endif | ||
| 487 | |||
| 488 | /* dir.c */ | ||
| 489 | extern const struct inode_operations logfs_symlink_iops; | ||
| 490 | extern const struct inode_operations logfs_dir_iops; | ||
| 491 | extern const struct file_operations logfs_dir_fops; | ||
| 492 | int logfs_replay_journal(struct super_block *sb); | ||
| 493 | |||
| 494 | /* file.c */ | ||
| 495 | extern const struct inode_operations logfs_reg_iops; | ||
| 496 | extern const struct file_operations logfs_reg_fops; | ||
| 497 | extern const struct address_space_operations logfs_reg_aops; | ||
| 498 | int logfs_readpage(struct file *file, struct page *page); | ||
| 499 | int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 500 | unsigned long arg); | ||
| 501 | int logfs_fsync(struct file *file, struct dentry *dentry, int datasync); | ||
| 502 | |||
| 503 | /* gc.c */ | ||
| 504 | u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec); | ||
| 505 | void logfs_gc_pass(struct super_block *sb); | ||
| 506 | int logfs_check_areas(struct super_block *sb); | ||
| 507 | int logfs_init_gc(struct super_block *sb); | ||
| 508 | void logfs_cleanup_gc(struct super_block *sb); | ||
| 509 | |||
| 510 | /* inode.c */ | ||
| 511 | extern const struct super_operations logfs_super_operations; | ||
| 512 | struct inode *logfs_iget(struct super_block *sb, ino_t ino); | ||
| 513 | struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *cookie); | ||
| 514 | void logfs_safe_iput(struct inode *inode, int cookie); | ||
| 515 | struct inode *logfs_new_inode(struct inode *dir, int mode); | ||
| 516 | struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino); | ||
| 517 | struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino); | ||
| 518 | int logfs_init_inode_cache(void); | ||
| 519 | void logfs_destroy_inode_cache(void); | ||
| 520 | void destroy_meta_inode(struct inode *inode); | ||
| 521 | void logfs_set_blocks(struct inode *inode, u64 no); | ||
| 522 | /* these logically belong into inode.c but actually reside in readwrite.c */ | ||
| 523 | int logfs_read_inode(struct inode *inode); | ||
| 524 | int __logfs_write_inode(struct inode *inode, long flags); | ||
| 525 | void logfs_delete_inode(struct inode *inode); | ||
| 526 | void logfs_clear_inode(struct inode *inode); | ||
| 527 | |||
| 528 | /* journal.c */ | ||
| 529 | void logfs_write_anchor(struct super_block *sb); | ||
| 530 | int logfs_init_journal(struct super_block *sb); | ||
| 531 | void logfs_cleanup_journal(struct super_block *sb); | ||
| 532 | int write_alias_journal(struct super_block *sb, u64 ino, u64 bix, | ||
| 533 | level_t level, int child_no, __be64 val); | ||
| 534 | void do_logfs_journal_wl_pass(struct super_block *sb); | ||
| 535 | |||
| 536 | /* readwrite.c */ | ||
| 537 | pgoff_t logfs_pack_index(u64 bix, level_t level); | ||
| 538 | void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level); | ||
| 539 | int logfs_inode_write(struct inode *inode, const void *buf, size_t count, | ||
| 540 | loff_t bix, long flags, struct shadow_tree *shadow_tree); | ||
| 541 | int logfs_readpage_nolock(struct page *page); | ||
| 542 | int logfs_write_buf(struct inode *inode, struct page *page, long flags); | ||
| 543 | int logfs_delete(struct inode *inode, pgoff_t index, | ||
| 544 | struct shadow_tree *shadow_tree); | ||
| 545 | int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, | ||
| 546 | gc_level_t gc_level, long flags); | ||
| 547 | int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix, | ||
| 548 | gc_level_t gc_level); | ||
| 549 | int logfs_truncate(struct inode *inode, u64 size); | ||
| 550 | u64 logfs_seek_hole(struct inode *inode, u64 bix); | ||
| 551 | u64 logfs_seek_data(struct inode *inode, u64 bix); | ||
| 552 | int logfs_open_segfile(struct super_block *sb); | ||
| 553 | int logfs_init_rw(struct super_block *sb); | ||
| 554 | void logfs_cleanup_rw(struct super_block *sb); | ||
| 555 | void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta); | ||
| 556 | void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta); | ||
| 557 | void logfs_write_block(struct logfs_block *block, long flags); | ||
| 558 | int logfs_write_obj_aliases_pagecache(struct super_block *sb); | ||
| 559 | void logfs_get_segment_entry(struct super_block *sb, u32 segno, | ||
| 560 | struct logfs_segment_entry *se); | ||
| 561 | void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment); | ||
| 562 | void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec, | ||
| 563 | gc_level_t gc_level); | ||
| 564 | void logfs_set_segment_reserved(struct super_block *sb, u32 segno); | ||
| 565 | void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec); | ||
| 566 | struct logfs_block *__alloc_block(struct super_block *sb, | ||
| 567 | u64 ino, u64 bix, level_t level); | ||
| 568 | void __free_block(struct super_block *sb, struct logfs_block *block); | ||
| 569 | void btree_write_block(struct logfs_block *block); | ||
| 570 | void initialize_block_counters(struct page *page, struct logfs_block *block, | ||
| 571 | __be64 *array, int page_is_empty); | ||
| 572 | int logfs_exist_block(struct inode *inode, u64 bix); | ||
| 573 | int get_page_reserve(struct inode *inode, struct page *page); | ||
| 574 | extern struct logfs_block_ops indirect_block_ops; | ||
| 575 | |||
| 576 | /* segment.c */ | ||
| 577 | int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase); | ||
| 578 | int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf); | ||
| 579 | int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix, | ||
| 580 | level_t level); | ||
| 581 | int logfs_segment_write(struct inode *inode, struct page *page, | ||
| 582 | struct logfs_shadow *shadow); | ||
| 583 | int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow); | ||
| 584 | int logfs_load_object_aliases(struct super_block *sb, | ||
| 585 | struct logfs_obj_alias *oa, int count); | ||
| 586 | void move_page_to_btree(struct page *page); | ||
| 587 | int logfs_init_mapping(struct super_block *sb); | ||
| 588 | void logfs_sync_area(struct logfs_area *area); | ||
| 589 | void logfs_sync_segments(struct super_block *sb); | ||
| 590 | void freeseg(struct super_block *sb, u32 segno); | ||
| 591 | |||
| 592 | /* area handling */ | ||
| 593 | int logfs_init_areas(struct super_block *sb); | ||
| 594 | void logfs_cleanup_areas(struct super_block *sb); | ||
| 595 | int logfs_open_area(struct logfs_area *area, size_t bytes); | ||
| 596 | void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | ||
| 597 | int use_filler); | ||
| 598 | |||
| 599 | static inline void logfs_buf_write(struct logfs_area *area, u64 ofs, | ||
| 600 | void *buf, size_t len) | ||
| 601 | { | ||
| 602 | __logfs_buf_write(area, ofs, buf, len, 0); | ||
| 603 | } | ||
| 604 | |||
| 605 | static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs, | ||
| 606 | void *buf, size_t len) | ||
| 607 | { | ||
| 608 | __logfs_buf_write(area, ofs, buf, len, 1); | ||
| 609 | } | ||
| 610 | |||
| 611 | /* super.c */ | ||
| 612 | struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index); | ||
| 613 | void emergency_read_end(struct page *page); | ||
| 614 | void logfs_crash_dump(struct super_block *sb); | ||
| 615 | void *memchr_inv(const void *s, int c, size_t n); | ||
| 616 | int logfs_statfs(struct dentry *dentry, struct kstatfs *stats); | ||
| 617 | int logfs_get_sb_device(struct file_system_type *type, int flags, | ||
| 618 | struct mtd_info *mtd, struct block_device *bdev, | ||
| 619 | const struct logfs_device_ops *devops, struct vfsmount *mnt); | ||
| 620 | int logfs_check_ds(struct logfs_disk_super *ds); | ||
| 621 | int logfs_write_sb(struct super_block *sb); | ||
| 622 | |||
| 623 | static inline struct logfs_super *logfs_super(struct super_block *sb) | ||
| 624 | { | ||
| 625 | return sb->s_fs_info; | ||
| 626 | } | ||
| 627 | |||
| 628 | static inline struct logfs_inode *logfs_inode(struct inode *inode) | ||
| 629 | { | ||
| 630 | return container_of(inode, struct logfs_inode, vfs_inode); | ||
| 631 | } | ||
| 632 | |||
| 633 | static inline void logfs_set_ro(struct super_block *sb) | ||
| 634 | { | ||
| 635 | logfs_super(sb)->s_flags |= LOGFS_SB_FLAG_RO; | ||
| 636 | } | ||
| 637 | |||
| 638 | #define LOGFS_BUG(sb) do { \ | ||
| 639 | struct super_block *__sb = sb; \ | ||
| 640 | logfs_crash_dump(__sb); \ | ||
| 641 | logfs_super(__sb)->s_flags |= LOGFS_SB_FLAG_RO; \ | ||
| 642 | BUG(); \ | ||
| 643 | } while (0) | ||
| 644 | |||
| 645 | #define LOGFS_BUG_ON(condition, sb) \ | ||
| 646 | do { if (unlikely(condition)) LOGFS_BUG((sb)); } while (0) | ||
| 647 | |||
| 648 | static inline __be32 logfs_crc32(void *data, size_t len, size_t skip) | ||
| 649 | { | ||
| 650 | return cpu_to_be32(crc32(~0, data+skip, len-skip)); | ||
| 651 | } | ||
| 652 | |||
| 653 | static inline u8 logfs_type(struct inode *inode) | ||
| 654 | { | ||
| 655 | return (inode->i_mode >> 12) & 15; | ||
| 656 | } | ||
| 657 | |||
| 658 | static inline pgoff_t logfs_index(struct super_block *sb, u64 pos) | ||
| 659 | { | ||
| 660 | return pos >> sb->s_blocksize_bits; | ||
| 661 | } | ||
| 662 | |||
| 663 | static inline u64 dev_ofs(struct super_block *sb, u32 segno, u32 ofs) | ||
| 664 | { | ||
| 665 | return ((u64)segno << logfs_super(sb)->s_segshift) + ofs; | ||
| 666 | } | ||
| 667 | |||
| 668 | static inline u32 seg_no(struct super_block *sb, u64 ofs) | ||
| 669 | { | ||
| 670 | return ofs >> logfs_super(sb)->s_segshift; | ||
| 671 | } | ||
| 672 | |||
| 673 | static inline u32 seg_ofs(struct super_block *sb, u64 ofs) | ||
| 674 | { | ||
| 675 | return ofs & logfs_super(sb)->s_segmask; | ||
| 676 | } | ||
| 677 | |||
| 678 | static inline u64 seg_align(struct super_block *sb, u64 ofs) | ||
| 679 | { | ||
| 680 | return ofs & ~logfs_super(sb)->s_segmask; | ||
| 681 | } | ||
| 682 | |||
| 683 | static inline struct logfs_block *logfs_block(struct page *page) | ||
| 684 | { | ||
| 685 | return (void *)page->private; | ||
| 686 | } | ||
| 687 | |||
| 688 | static inline level_t shrink_level(gc_level_t __level) | ||
| 689 | { | ||
| 690 | u8 level = (__force u8)__level; | ||
| 691 | |||
| 692 | if (level >= LOGFS_MAX_LEVELS) | ||
| 693 | level -= LOGFS_MAX_LEVELS; | ||
| 694 | return (__force level_t)level; | ||
| 695 | } | ||
| 696 | |||
| 697 | static inline gc_level_t expand_level(u64 ino, level_t __level) | ||
| 698 | { | ||
| 699 | u8 level = (__force u8)__level; | ||
| 700 | |||
| 701 | if (ino == LOGFS_INO_MASTER) { | ||
| 702 | /* ifile has seperate areas */ | ||
| 703 | level += LOGFS_MAX_LEVELS; | ||
| 704 | } | ||
| 705 | return (__force gc_level_t)level; | ||
| 706 | } | ||
| 707 | |||
| 708 | static inline int logfs_block_shift(struct super_block *sb, level_t level) | ||
| 709 | { | ||
| 710 | level = shrink_level((__force gc_level_t)level); | ||
| 711 | return (__force int)level * (sb->s_blocksize_bits - 3); | ||
| 712 | } | ||
| 713 | |||
| 714 | static inline u64 logfs_block_mask(struct super_block *sb, level_t level) | ||
| 715 | { | ||
| 716 | return ~0ull << logfs_block_shift(sb, level); | ||
| 717 | } | ||
| 718 | |||
| 719 | static inline struct logfs_area *get_area(struct super_block *sb, | ||
| 720 | gc_level_t gc_level) | ||
| 721 | { | ||
| 722 | return logfs_super(sb)->s_area[(__force u8)gc_level]; | ||
| 723 | } | ||
| 724 | |||
| 725 | #endif | ||
