|
@@ -181,6 +181,12 @@ void disk_part_iter_exit(struct disk_part_iter *piter)
|
|
|
}
|
|
|
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;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* disk_map_sector_rcu - map sector to partition
|
|
|
* @disk: gendisk of interest
|
|
@@ -199,16 +205,22 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit);
|
|
|
struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector)
|
|
|
{
|
|
|
struct disk_part_tbl *ptbl;
|
|
|
+ struct hd_struct *part;
|
|
|
int i;
|
|
|
|
|
|
ptbl = rcu_dereference(disk->part_tbl);
|
|
|
|
|
|
+ part = rcu_dereference(ptbl->last_lookup);
|
|
|
+ if (part && sector_in_part(part, sector))
|
|
|
+ return part;
|
|
|
+
|
|
|
for (i = 1; i < ptbl->len; i++) {
|
|
|
- struct hd_struct *part = rcu_dereference(ptbl->part[i]);
|
|
|
+ part = rcu_dereference(ptbl->part[i]);
|
|
|
|
|
|
- if (part && part->start_sect <= sector &&
|
|
|
- sector < part->start_sect + part->nr_sects)
|
|
|
+ if (part && sector_in_part(part, sector)) {
|
|
|
+ rcu_assign_pointer(ptbl->last_lookup, part);
|
|
|
return part;
|
|
|
+ }
|
|
|
}
|
|
|
return &disk->part0;
|
|
|
}
|
|
@@ -888,8 +900,11 @@ static void disk_replace_part_tbl(struct gendisk *disk,
|
|
|
struct disk_part_tbl *old_ptbl = disk->part_tbl;
|
|
|
|
|
|
rcu_assign_pointer(disk->part_tbl, new_ptbl);
|
|
|
- if (old_ptbl)
|
|
|
+
|
|
|
+ if (old_ptbl) {
|
|
|
+ rcu_assign_pointer(old_ptbl->last_lookup, NULL);
|
|
|
call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|