Device helper cleanups
David Sterba
maintainercover Device helper cleanups
David Sterba (4):
btrfs: merge alloc_device helpers
btrfs: refactor find_device helper
btrfs: split write_dev_supers to two functions
btrfs: use named constant for bdev blocksize
fs/btrfs/check-integrity.c | 6 +- fs/btrfs/disk-io.c | 136 +++++++++++++++++++++++++-------------------- fs/btrfs/disk-io.h | 8 +++ fs/btrfs/volumes.c | 61 +++++++++----------- 4 files changed, 115 insertions(+), 96 deletions(-)
Signature · 1 line
2.13.0
David Sterba
maintainerPATCH 1/4 btrfs: merge alloc_device helpers
There are two helpers called in chain from one location, we can merge the functionaliy.
Originally, alloc_fs_devices could fill the device uuid randomly if we we didn't give the uuid buffer. This happens for seed devices but the fsid is generated in btrfs_prepare_sprout, so we can remove it.
--- fs/btrfs/volumes.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-)
fs/btrfs/volumes.c +11 -25
@@ -152,7 +152,15 @@ struct list_head *btrfs_get_fs_uuids(void)return &fs_uuids; } -static struct btrfs_fs_devices *__alloc_fs_devices (void ) +/* +* alloc_fs_devices - allocate struct btrfs_fs_devices +* @fsid: if not NULL, copy the uuid to fs_devices::fsid +* +* Return a pointer to a new struct btrfs_fs_devices on success, or ERR_PTR(). +* The returned struct is not linked onto any lists and can be destroyed with +* kfree() right away. +*/ +static struct btrfs_fs_devices *alloc_fs_devices (const u8 *fsid) {struct btrfs_fs_devices *fs_devs;
@@ -166,31 +174,8 @@ static struct btrfs_fs_devices *__alloc_fs_devices(void)INIT_LIST_HEAD (&fs_devs->resized_devices);INIT_LIST_HEAD (&fs_devs->alloc_list);INIT_LIST_HEAD (&fs_devs->list); - -return fs_devs; -} - -/** -* alloc_fs_devices - allocate struct btrfs_fs_devices -* @fsid: a pointer to UUID for this FS. If NULL a new UUID is -* generated. -* -* Return: a pointer to a new &struct btrfs_fs_devices on success; -* ERR_PTR() on error. Returned struct is not linked onto any lists and -* can be destroyed with kfree() right away. -*/ -static struct btrfs_fs_devices *alloc_fs_devices (const u8 *fsid) -{ -struct btrfs_fs_devices *fs_devs; - - fs_devs =__alloc_fs_devices (); -if (IS_ERR (fs_devs)) -return fs_devs; -if (fsid)memcpy (fs_devs->fsid, fsid,BTRFS_FSID_SIZE ); -else -generate_random_uuid (fs_devs->fsid);return fs_devs; }
@@ -2202,7 +2187,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info)if (!fs_devices->seeding)return -EINVAL ; - seed_devices =__alloc_fs_devices (); + seed_devices =alloc_fs_devices (NULL );if (IS_ERR (seed_devices))return PTR_ERR (seed_devices);
@@ -6568,6 +6553,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,int ret;BUG_ON (!mutex_is_locked (&uuid_mutex)); +ASSERT (fsid); fs_devices = fs_info->fs_devices->seed;while (fs_devices) {
Signature · 1 line
2.13.0
David Sterba
maintainerPATCH 2/4 btrfs: refactor find_device helper
In reply to David SterbaPolish the helper:
* drop underscores, no special meaning here
* pass fs_devices, as this is what the API implements
* drop noinline, no apparent reason for such simple helper
* constify uuid
* add comment
--- fs/btrfs/volumes.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
fs/btrfs/volumes.c +13 -6
@@ -254,9 +254,17 @@ static struct btrfs_device *__alloc_device(void)return dev; } -static noinline struct btrfs_device *__find_device(struct list_head *head, -u64 devid,u8 *uuid) +/* +* Find a device specified by @devid or @uuid in the list of @fs_devices, or +* return NULL. +* +* If devid and uuid are both specified, the match must be exact, otherwise +* only devid is used. +*/ +static struct btrfs_device *find_device (struct btrfs_fs_devices *fs_devices, +u64 devid,const u8 *uuid) { +struct list_head *head = &fs_devices->devices;struct btrfs_device *dev;list_for_each_entry (dev, head, dev_list) {
@@ -621,8 +629,8 @@ static noinline int device_list_add(const char *path, device =NULL ; }else { - device =__find_device (&fs_devices->devices, devid, - disk_super->dev_item.uuid); + device =find_device (fs_devices, devid, + disk_super->dev_item.uuid); }if (!device) {
@@ -6280,8 +6288,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,while (cur_devices) {if (!fsid || !memcmp (cur_devices->fsid, fsid,BTRFS_UUID_SIZE )) { - device =__find_device (&cur_devices->devices, - devid, uuid); + device =find_device (cur_devices, devid, uuid);if (device)return device; }
Signature · 1 line
2.13.0
David Sterba
maintainerPATCH 3/4 btrfs: split write_dev_supers to two functions
In reply to David SterbaThere are two independent parts, one that writes the superblocks and another that waits for completion. No functional changes, but cleanups, reformatting and comment updates.
--- fs/btrfs/disk-io.c | 129 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 56 deletions(-)
fs/btrfs/disk-io.c +73 -56
@@ -3378,19 +3378,17 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) }/* -* this should be called twice, once with wait == 0 and -* once with wait == 1. When wait == 0 is done, all the buffer heads -* we write are pinned. +* Write superblock @sb to the @device. Do not wait for completion, all the +* buffer heads we write are pinned. * -* They are released when wait == 1 is done. -* max_mirrors must be the same for both runs, and it indicates how -* many supers on this one device should be written. +* Write @max_mirrors copies of the superblock, where 0 means default that fit +* the expected device size at commit time. Note that max_mirrors must be +* same for write and wait phases. * -* max_mirrors == 0 means to write them all. +* Return number of errors when buffer head is not found or submission fails. */ static int write_dev_supers (struct btrfs_device *device, -struct btrfs_super_block *sb, -int wait,int max_mirrors) +struct btrfs_super_block *sb,int max_mirrors) {struct buffer_head *bh;int i;
@@ -3408,57 +3406,33 @@ static int write_dev_supers(struct btrfs_device *device, device->commit_total_bytes)break ; -if (wait) { - bh =__find_get_block (device->bdev, bytenr /4096 , -BTRFS_SUPER_INFO_SIZE ); -if (!bh) { - errors++; -continue ; - } -wait_on_buffer (bh); -if (!buffer_uptodate (bh)) - errors++; +btrfs_set_super_bytenr (sb, bytenr); -/* drop our reference */ -brelse (bh); + crc = ~(u32 )0 ; + crc =btrfs_csum_data ((const char *)sb +BTRFS_CSUM_SIZE , crc, +BTRFS_SUPER_INFO_SIZE -BTRFS_CSUM_SIZE ); +btrfs_csum_final (crc, sb->csum); -/* drop the reference from the wait == 0 run */ -brelse (bh); +/* One reference for us, and we leave it for the caller */ + bh =__getblk (device->bdev, bytenr /4096 , +BTRFS_SUPER_INFO_SIZE ); +if (!bh) { +btrfs_err (device->fs_info, +"couldn't get super buffer head for bytenr %llu" , + bytenr); + errors++;continue ; - }else { -btrfs_set_super_bytenr (sb, bytenr); - - crc = ~(u32 )0 ; - crc =btrfs_csum_data ((const char *)sb + -BTRFS_CSUM_SIZE , crc, -BTRFS_SUPER_INFO_SIZE - -BTRFS_CSUM_SIZE ); -btrfs_csum_final (crc, sb->csum); - -/* -* one reference for us, and we leave it for the -* caller -*/ - bh =__getblk (device->bdev, bytenr /4096 , -BTRFS_SUPER_INFO_SIZE ); -if (!bh) { -btrfs_err (device->fs_info, -"couldn't get super buffer head for bytenr %llu" , - bytenr); - errors++; -continue ; - } + } -memcpy (bh->b_data, sb,BTRFS_SUPER_INFO_SIZE ); +memcpy (bh->b_data, sb,BTRFS_SUPER_INFO_SIZE ); -/* one reference for submit_bh */ -get_bh (bh); +/* one reference for submit_bh */ +get_bh (bh); -set_buffer_uptodate (bh); -lock_buffer (bh); - bh->b_end_io = btrfs_end_buffer_write_sync; - bh->b_private = device; - } +set_buffer_uptodate (bh); +lock_buffer (bh); + bh->b_end_io = btrfs_end_buffer_write_sync; + bh->b_private = device;/* * we fua the first super. The others we allow
@@ -3477,6 +3451,49 @@ static int write_dev_supers(struct btrfs_device *device, }/* +* Wait for write completion of superblocks done by write_dev_supers, +* @max_mirrors same for write and wait phases. +* +* Return number of errors when buffer head is not found or not marked up to +* date. +*/ +static int wait_dev_supers (struct btrfs_device *device,int max_mirrors) +{ +struct buffer_head *bh; +int i; +int errors =0 ; +u64 bytenr; + +if (max_mirrors ==0 ) + max_mirrors =BTRFS_SUPER_MIRROR_MAX ; + +for (i =0 ; i < max_mirrors; i++) { + bytenr =btrfs_sb_offset (i); +if (bytenr +BTRFS_SUPER_INFO_SIZE >= + device->commit_total_bytes) +break ; + + bh =__find_get_block (device->bdev, bytenr /4096 , +BTRFS_SUPER_INFO_SIZE ); +if (!bh) { + errors++; +continue ; + } +wait_on_buffer (bh); +if (!buffer_uptodate (bh)) + errors++; + +/* drop our reference */ +brelse (bh); + +/* drop the reference from the writing run */ +brelse (bh); + } + +return errors < i ?0 :-1 ; +} + +/* * endio for the write_dev_flush, this will wake anyone waiting * for the barrier when it is done */
@@ -3737,7 +3754,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors) flags =btrfs_super_flags (sb);btrfs_set_super_flags (sb, flags |BTRFS_HEADER_FLAG_WRITTEN ); - ret =write_dev_supers (dev, sb,0 , max_mirrors); + ret =write_dev_supers (dev, sb, max_mirrors);if (ret) total_errors++; }
@@ -3760,7 +3777,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)if (!dev->in_fs_metadata || !dev->writeable)continue ; - ret =write_dev_supers (dev, sb,1 , max_mirrors); + ret =wait_dev_supers (dev, max_mirrors);if (ret) total_errors++; }
Signature · 1 line
2.13.0
David Sterba
maintainerPATCH 4/4 btrfs: use named constant for bdev blocksize
In reply to David SterbaSuperblock is read and written using buffer heads, we need to set the bdev blocksize. The magic constant has been hardcoded in several places, so replace it with a named constant.
--- fs/btrfs/check-integrity.c | 6 +++--- fs/btrfs/disk-io.c | 11 ++++++----- fs/btrfs/disk-io.h | 8 ++++++++ fs/btrfs/volumes.c | 6 +++--- 4 files changed, 20 insertions(+), 11 deletions(-)
fs/btrfs/check-integrity.c +3 -3
@@ -795,12 +795,12 @@ static int btrfsic_process_superblock_dev_mirror( dev_bytenr =btrfs_sb_offset (superblock_mirror_num);if (dev_bytenr +BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes)return -1 ; - bh =__bread (superblock_bdev, dev_bytenr /4096 , + bh =__bread (superblock_bdev, dev_bytenr /BTRFS_BDEV_BLOCKSIZE ,BTRFS_SUPER_INFO_SIZE );if (NULL == bh)return -1 ; super_tmp = (struct btrfs_super_block *) - (bh->b_data + (dev_bytenr &4095 )); + (bh->b_data + (dev_bytenr & (BTRFS_BDEV_BLOCKSIZE -1 ))); if (btrfs_super_bytenr(super_tmp) != dev_bytenr || btrfs_super_magic(super_tmp) != BTRFS_MAGIC ||
@@ -2758,7 +2758,7 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh) (op == REQ_OP_WRITE) && bh->b_size > 0) {u64 dev_bytenr; - dev_bytenr =4096 * bh->b_blocknr; + dev_bytenr =BTRFS_BDEV_BLOCKSIZE * bh->b_blocknr;if (dev_state->state->print_mask &BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH ) pr_info("submit_bh(op=0x%x,0x%x, blocknr=%llu (bytenr %llu), size=%zu, data=%p, bdev=%p)\n",
fs/btrfs/disk-io.c +6 -5
@@ -2694,8 +2694,8 @@ int open_ctree(struct super_block *sb,btrfs_init_balance (fs_info);btrfs_init_async_reclaim_work (&fs_info->async_reclaim_work); - sb->s_blocksize =4096 ; - sb->s_blocksize_bits =blksize_bits (4096 ); + sb->s_blocksize =BTRFS_BDEV_BLOCKSIZE ; + sb->s_blocksize_bits =blksize_bits (BTRFS_BDEV_BLOCKSIZE );btrfs_init_btree_inode (fs_info);
@@ -3321,7 +3321,7 @@ int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num,if (bytenr +BTRFS_SUPER_INFO_SIZE >=i_size_read (bdev->bd_inode))return -EINVAL ; - bh =__bread (bdev, bytenr /4096 ,BTRFS_SUPER_INFO_SIZE ); + bh =__bread (bdev, bytenr /BTRFS_BDEV_BLOCKSIZE ,BTRFS_SUPER_INFO_SIZE );/* * If we fail to read from the underlying devices, as of now * the best option we have is to mark it EIO.
@@ -3414,7 +3414,7 @@ static int write_dev_supers(struct btrfs_device *device,btrfs_csum_final (crc, sb->csum);/* One reference for us, and we leave it for the caller */ - bh =__getblk (device->bdev, bytenr /4096 , + bh =__getblk (device->bdev, bytenr /BTRFS_BDEV_BLOCKSIZE ,BTRFS_SUPER_INFO_SIZE );if (!bh) { btrfs_err(device->fs_info,
@@ -3473,7 +3473,8 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors) device->commit_total_bytes)break ; - bh =__find_get_block (device->bdev, bytenr /4096 , + bh =__find_get_block (device->bdev, + bytenr /BTRFS_BDEV_BLOCKSIZE ,BTRFS_SUPER_INFO_SIZE );if (!bh) { errors++;
fs/btrfs/disk-io.h +8 -0
@@ -25,6 +25,14 @@#define BTRFS_SUPER_MIRROR_MAX 3#define BTRFS_SUPER_MIRROR_SHIFT 12 +/* +* Fixed blocksize for all devices, applies to specific ways of reading +* metadata like superblock. Must meet the set_blocksize requirements. +* +* Do not change. +*/ +#define BTRFS_BDEV_BLOCKSIZE (4096) +enum btrfs_wq_endio_type {BTRFS_WQ_ENDIO_DATA =0 ,BTRFS_WQ_ENDIO_METADATA =1 ,
fs/btrfs/volumes.c +3 -3
@@ -303,7 +303,7 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,if (flush)filemap_write_and_wait ((*bdev)->bd_inode->i_mapping); - ret =set_blocksize (*bdev,4096 ); + ret =set_blocksize (*bdev,BTRFS_BDEV_BLOCKSIZE );if (ret) {blkdev_put (*bdev, flags); goto error;
@@ -2400,7 +2400,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path device->is_tgtdev_for_dev_replace =0 ; device->mode =FMODE_EXCL ; device->dev_stats_valid =1 ; -set_blocksize (device->bdev,4096 ); +set_blocksize (device->bdev,BTRFS_BDEV_BLOCKSIZE );if (seeding_dev) { sb->s_flags &= ~MS_RDONLY ;
@@ -2605,7 +2605,7 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, device->is_tgtdev_for_dev_replace =1 ; device->mode =FMODE_EXCL ; device->dev_stats_valid =1 ; -set_blocksize (device->bdev,4096 ); +set_blocksize (device->bdev,BTRFS_BDEV_BLOCKSIZE ); device->fs_devices = fs_info->fs_devices;list_add (&device->dev_list, &fs_info->fs_devices->devices); fs_info->fs_devices->num_devices++;
Signature · 1 line
2.13.0