On 2019/08/21 23:59, Darrick J. Wong wrote: > On Wed, Aug 21, 2019 at 04:03:08PM +0900, Damien Le Moal wrote: >> zonefs is a very simple file system exposing each zone of a zoned >> block device as a file. zonefs is in fact closer to a raw block device >> access interface than to a full feature POSIX file system. > > <skipping to the good part> > >> +/* >> + * Read super block information from the device. >> + */ >> +static int zonefs_read_super(struct super_block *sb) >> +{ >> + const void *zero_page = (const void *) __va(page_to_phys(ZERO_PAGE(0))); >> + struct zonefs_sb_info *sbi = ZONEFS_SB(sb); >> + struct zonefs_super *super; >> + struct bio bio; >> + struct bio_vec bio_vec; >> + struct page *page; >> + u32 crc, stored_crc; >> + int ret; >> + >> + page = alloc_page(GFP_KERNEL); >> + if (!page) >> + return -ENOMEM; >> + >> + bio_init(&bio, &bio_vec, 1); >> + bio.bi_iter.bi_sector = 0; >> + bio_set_dev(&bio, sb->s_bdev); >> + bio_set_op_attrs(&bio, REQ_OP_READ, 0); >> + bio_add_page(&bio, page, PAGE_SIZE, 0); >> + >> + ret = submit_bio_wait(&bio); >> + if (ret) >> + goto out; >> + >> + super = page_address(page); >> + >> + stored_crc = super->s_crc; >> + super->s_crc = 0; >> + crc = crc32_le(ZONEFS_MAGIC, (unsigned char *)super, >> + sizeof(struct zonefs_super)); >> + if (crc != stored_crc) { >> + zonefs_err(sb, "Invalid checksum (Expected 0x%08x, got 0x%08x)", >> + crc, stored_crc); >> + ret = -EIO; >> + goto out; >> + } >> + >> + ret = -EINVAL; >> + if (le32_to_cpu(super->s_magic) != ZONEFS_MAGIC) >> + goto out; >> + >> + sbi->s_features = le64_to_cpu(super->s_features); >> + if (sbi->s_features & ~((1ULL << ZONEFS_F_NUM) - 1)) { > > Most other filesystems would do: > > #define ZONEFS_F_ALL_FEATURES (ZONEFS_F_UID | ZONEFS_F_GID ...) > > and then this becomes: > > if (sbi->s_features & ~ZONEFS_F_ALL_FEATURES) OK. Will do that. >> + zonefs_err(sb, "Unknown features set\n"); > > Also it might help to print out the invalid s_features values so that > when you get help questions you can distinguish between a corrupted > superblock and a new fs on an old kernel. Good point. Will add that. > >> + goto out; >> + } >> + >> + >> + if (zonefs_has_feature(sbi, ZONEFS_F_UID)) { >> + sbi->s_uid = make_kuid(current_user_ns(), >> + le32_to_cpu(super->s_uid)); >> + if (!uid_valid(sbi->s_uid)) { >> + zonefs_err(sb, "Invalid UID feature\n"); >> + goto out; >> + } >> + } >> + if (zonefs_has_feature(sbi, ZONEFS_F_GID)) { >> + sbi->s_gid = make_kgid(current_user_ns(), >> + le32_to_cpu(super->s_gid)); >> + if (!gid_valid(sbi->s_gid)) { >> + zonefs_err(sb, "Invalid GID feature\n"); >> + goto out; >> + } >> + } >> + >> + if (zonefs_has_feature(sbi, ZONEFS_F_PERM)) >> + sbi->s_perm = le32_to_cpu(super->s_perm); >> + >> + if (memcmp(super->s_reserved, zero_page, sizeof(super->s_reserved))) { > > Er... memchr_inv? Ah. Yes. Good idea. That will avoid the need for using zero page. > > Otherwise looks reasonable enough. How do you test zonedfs? I created a small test suite that I put together with zonefs-tools in the github repo (see https://github.com/damien-lemoal/zonefs-tools). The tests run against real devices, DM devices (dm-linear chunks of a larger device) and null_blk devices with memory backing and zoned mode enabled (there is a script for running against this one automatically). This test suite is still small-ish but improving. For now, I have tests for checking number of files created and their attributes, truncate and unlink, and IO paths (read and write, sync and async) using dd and fio. I need to add some more test cases for mmap at least (tested "manually" for now). I will eventually need to go through xfstests to see what generic test cases can apply. Not many I guess given the limited features of zonefs. Will see. Best regards. -- Damien Le Moal Western Digital Research