static int journal_erase_segment(struct logfs_area *area) { struct super_block *sb = area->a_sb; union { struct logfs_segment_header sh; unsigned char c[ALIGN(sizeof(struct logfs_segment_header), 16)]; } u; u64 ofs; int err; err = logfs_erase_segment(sb, area->a_segno, 1); if (err) return err; memset(&u, 0, sizeof(u)); u.sh.pad = 0; u.sh.type = SEG_JOURNAL; u.sh.level = 0; u.sh.segno = cpu_to_be32(area->a_segno); u.sh.ec = cpu_to_be32(area->a_erase_count); u.sh.gec = cpu_to_be64(logfs_super(sb)->s_gec); u.sh.crc = logfs_crc32(&u.sh, sizeof(u.sh), 4); ofs = dev_ofs(sb, area->a_segno, 0); area->a_used_bytes = sizeof(u); logfs_buf_write(area, ofs, &u, sizeof(u)); return 0; }
static int journal_erase_segment(struct logfs_area *area) { struct super_block *sb = area->a_sb; struct logfs_segment_header sh; u64 ofs; int err; err = logfs_erase_segment(sb, area->a_segno, 1); if (err) return err; sh.pad = 0; sh.type = SEG_JOURNAL; sh.level = 0; sh.segno = cpu_to_be32(area->a_segno); sh.ec = cpu_to_be32(area->a_erase_count); sh.gec = cpu_to_be64(logfs_super(sb)->s_gec); sh.crc = logfs_crc32(&sh, sizeof(sh), 4); /* This causes a bug in segment.c. Not yet. */ //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0); ofs = dev_ofs(sb, area->a_segno, 0); area->a_used_bytes = ALIGN(sizeof(sh), 16); logfs_buf_write(area, ofs, &sh, sizeof(sh)); return 0; }
static int read_area(struct super_block *sb, struct logfs_je_area *a) { struct logfs_super *super = logfs_super(sb); struct logfs_area *area = super->s_area[a->gc_level]; u64 ofs; u32 writemask = ~(super->s_writesize - 1); if (a->gc_level >= LOGFS_NO_AREAS) return -EIO; if (a->vim != VIM_DEFAULT) return -EIO; /* TODO: close area and continue */ area->a_used_bytes = be32_to_cpu(a->used_bytes); area->a_written_bytes = area->a_used_bytes & writemask; area->a_segno = be32_to_cpu(a->segno); if (area->a_segno) area->a_is_open = 1; ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); if (super->s_writesize > 1) logfs_buf_recover(area, ofs, a + 1, super->s_writesize); else logfs_buf_recover(area, ofs, NULL, 0); return 0; }
static s64 logfs_get_free_bytes(struct logfs_area *area, size_t bytes) { s32 ofs; logfs_open_area(area, bytes); ofs = area->a_used_bytes; area->a_used_bytes += bytes; BUG_ON(area->a_used_bytes >= logfs_super(area->a_sb)->s_segsize); return dev_ofs(area->a_sb, area->a_segno, ofs); }
static int logfs_read_segment(struct super_block *sb, u32 segno) { struct logfs_super *super = logfs_super(sb); struct logfs_journal_header *jh = super->s_compressed_je; u64 ofs, seg_ofs = dev_ofs(sb, segno, 0); u32 h_ofs, last_ofs = 0; u16 len, datalen, last_len = 0; int i, err; for (h_ofs = 0; h_ofs < super->s_segsize; h_ofs += sizeof(*jh)) { ofs = seg_ofs + h_ofs; err = __read_je_header(sb, ofs, jh); if (err) continue; if (jh->h_type != cpu_to_be16(JE_COMMIT)) continue; err = __read_je_payload(sb, ofs, jh); if (err) continue; len = be16_to_cpu(jh->h_len); datalen = be16_to_cpu(jh->h_datalen); if ((datalen > sizeof(super->s_je_array)) || (datalen % sizeof(__be64))) continue; last_ofs = h_ofs; last_len = datalen; h_ofs += ALIGN(len, sizeof(*jh)) - sizeof(*jh); } if (last_ofs == 0) return -ENOENT; ofs = seg_ofs + last_ofs; log_journal("Read commit from %llx\n", ofs); err = __read_je(sb, ofs, jh); BUG_ON(err); if (err) return err; unpack(jh, super->s_je_array); super->s_no_je = last_len / sizeof(__be64); for (i = 0; i < super->s_no_je; i++) { err = read_je(sb, be64_to_cpu(super->s_je_array[i])); if (err) return err; } super->s_journal_area->a_segno = segno; return 0; }
static u64 read_gec(struct super_block *sb, u32 segno) { struct logfs_segment_header sh; __be32 crc; int err; if (!segno) return 0; err = wbuf_read(sb, dev_ofs(sb, segno, 0), sizeof(sh), &sh); if (err) return 0; crc = logfs_crc32(&sh, sizeof(sh), 4); if (crc != sh.crc) { WARN_ON(sh.gec != cpu_to_be64(0xffffffffffffffffull)); return 0; } return be64_to_cpu(sh.gec); }
static void write_wbuf(struct super_block *sb, struct logfs_area *area, void *wbuf) { struct logfs_super *super = logfs_super(sb); struct address_space *mapping = super->s_mapping_inode->i_mapping; u64 ofs; pgoff_t index; int page_ofs; struct page *page; ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes & ~(super->s_writesize - 1)); index = ofs >> PAGE_SHIFT; page_ofs = ofs & (PAGE_SIZE - 1); page = find_lock_page(mapping, index); BUG_ON(!page); memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize); unlock_page(page); }
static s64 logfs_get_free_bytes(struct logfs_area *area, size_t *bytes, int must_pad) { u32 writesize = logfs_super(area->a_sb)->s_writesize; s32 ofs; int ret; ret = logfs_open_area(area, *bytes); if (ret) return -EAGAIN; ofs = area->a_used_bytes; area->a_used_bytes += *bytes; if (must_pad) { area->a_used_bytes = ALIGN(area->a_used_bytes, writesize); *bytes = area->a_used_bytes - ofs; } return dev_ofs(area->a_sb, area->a_segno, ofs); }