mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
block: add partition resize function to blkpg ioctl
Add a new operation code (BLKPG_RESIZE_PARTITION) to the BLKPG ioctl that allows altering the size of an existing partition, even if it is currently in use. This patch converts hd_struct->nr_sects into sequence counter because One might extend a partition while IO is happening to it and update of nr_sects can be non-atomic on 32bit machines with 64bit sector_t. This can lead to issues like reading inconsistent size of a partition. Sequence counter have been used so that readers don't have to take bdev mutex lock as we call sector_in_part() very frequently. Now all the access to hd_struct->nr_sects should happen using sequence counter read/update helper functions part_nr_sects_read/part_nr_sects_write. There is one exception though, set_capacity()/get_capacity(). I think theoritically race should exist there too but this patch does not modify set_capacity()/get_capacity() due to sheer number of call sites and I am afraid that change might break something. I have left that as a TODO item. We can handle it later if need be. This patch does not introduce any new races as such w.r.t set_capacity()/get_capacity(). v2: Add CONFIG_LBDAF test to UP preempt case as suggested by Phillip. Signed-off-by: Vivek Goyal <[email protected]> Signed-off-by: Phillip Susi <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
This commit is contained in:
parent
4638a83e86
commit
c83f6bf98d
5 changed files with 132 additions and 9 deletions
|
|
@ -154,7 +154,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
|
|||
part = rcu_dereference(ptbl->part[piter->idx]);
|
||||
if (!part)
|
||||
continue;
|
||||
if (!part->nr_sects &&
|
||||
if (!part_nr_sects_read(part) &&
|
||||
!(piter->flags & DISK_PITER_INCL_EMPTY) &&
|
||||
!(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
|
||||
piter->idx == 0))
|
||||
|
|
@ -191,7 +191,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit);
|
|||
static inline int sector_in_part(struct hd_struct *part, sector_t sector)
|
||||
{
|
||||
return part->start_sect <= sector &&
|
||||
sector < part->start_sect + part->nr_sects;
|
||||
sector < part->start_sect + part_nr_sects_read(part);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -769,8 +769,8 @@ void __init printk_all_partitions(void)
|
|||
|
||||
printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
|
||||
bdevt_str(part_devt(part), devt_buf),
|
||||
(unsigned long long)part->nr_sects >> 1,
|
||||
disk_name(disk, part->partno, name_buf),
|
||||
(unsigned long long)part_nr_sects_read(part) >> 1
|
||||
, disk_name(disk, part->partno, name_buf),
|
||||
uuid_buf);
|
||||
if (is_part0) {
|
||||
if (disk->driverfs_dev != NULL &&
|
||||
|
|
@ -862,7 +862,7 @@ static int show_partition(struct seq_file *seqf, void *v)
|
|||
while ((part = disk_part_iter_next(&piter)))
|
||||
seq_printf(seqf, "%4d %7d %10llu %s\n",
|
||||
MAJOR(part_devt(part)), MINOR(part_devt(part)),
|
||||
(unsigned long long)part->nr_sects >> 1,
|
||||
(unsigned long long)part_nr_sects_read(part) >> 1,
|
||||
disk_name(sgp, part->partno, buf));
|
||||
disk_part_iter_exit(&piter);
|
||||
|
||||
|
|
@ -1268,6 +1268,16 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
|
|||
}
|
||||
disk->part_tbl->part[0] = &disk->part0;
|
||||
|
||||
/*
|
||||
* set_capacity() and get_capacity() currently don't use
|
||||
* seqcounter to read/update the part0->nr_sects. Still init
|
||||
* the counter as we can read the sectors in IO submission
|
||||
* patch using seqence counters.
|
||||
*
|
||||
* TODO: Ideally set_capacity() and get_capacity() should be
|
||||
* converted to make use of bd_mutex and sequence counters.
|
||||
*/
|
||||
seqcount_init(&disk->part0.nr_sects_seq);
|
||||
hd_ref_init(&disk->part0);
|
||||
|
||||
disk->minors = minors;
|
||||
|
|
|
|||
Loading…
Reference in a new issue