diff --git a/kmod/src/bio.c b/kmod/src/bio.c index bb42b02a..916c5be7 100644 --- a/kmod/src/bio.c +++ b/kmod/src/bio.c @@ -197,6 +197,17 @@ int scoutfs_bio_read(struct super_block *sb, struct page **pages, return scoutfs_bio_wait_comp(sb, &comp); } +int scoutfs_bio_write(struct super_block *sb, struct page **pages, + u64 blkno, unsigned int nr_blocks) +{ + struct scoutfs_bio_completion comp; + + scoutfs_bio_init_comp(&comp); + scoutfs_bio_submit_comp(sb, WRITE, pages, blkno, nr_blocks, &comp); + + return scoutfs_bio_wait_comp(sb, &comp); +} + /* return pointer to the blk 4k block offset amongst the pages */ void *scoutfs_page_block_address(struct page **pages, unsigned int blk) { diff --git a/kmod/src/bio.h b/kmod/src/bio.h index d2e3390a..93439775 100644 --- a/kmod/src/bio.h +++ b/kmod/src/bio.h @@ -35,6 +35,8 @@ int scoutfs_bio_wait_comp(struct super_block *sb, int scoutfs_bio_read(struct super_block *sb, struct page **pages, u64 blkno, unsigned int nr_blocks); +int scoutfs_bio_write(struct super_block *sb, struct page **pages, + u64 blkno, unsigned int nr_blocks); void *scoutfs_page_block_address(struct page **pages, unsigned int blk); diff --git a/kmod/src/super.c b/kmod/src/super.c index 792d25ae..00b428a7 100644 --- a/kmod/src/super.c +++ b/kmod/src/super.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -110,26 +111,28 @@ void scoutfs_advance_dirty_super(struct super_block *sb) /* * The caller is responsible for setting the super header's blkno * and seq to something reasonable. + * + * XXX it'd be pretty easy to preallocate to avoid failure here. */ int scoutfs_write_dirty_super(struct super_block *sb) { struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); struct scoutfs_super_block *super; - struct scoutfs_block *bl; + struct page *page; int ret; - /* XXX prealloc? */ - bl = scoutfs_block_dirty(sb, le64_to_cpu(sbi->super.hdr.blkno)); - if (WARN_ON_ONCE(IS_ERR(bl))) - return PTR_ERR(bl); - super = scoutfs_block_data(bl); + page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!page) + return -ENOMEM; + super = page_address(page); memcpy(super, &sbi->super, sizeof(*super)); - scoutfs_block_zero(bl, sizeof(*super)); - scoutfs_block_set_crc(bl); - ret = scoutfs_block_write_sync(bl); - scoutfs_block_put(bl); + ret = scoutfs_bio_write(sb, &page, le64_to_cpu(super->hdr.blkno), 1); + WARN_ON_ONCE(ret); + + __free_page(page); + return ret; }