Blame view

block/partition-generic.c 17.4 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
94ea4158f   Al Viro   separate partitio...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  /*
   *  Code extracted from drivers/block/genhd.c
   *  Copyright (C) 1991-1998  Linus Torvalds
   *  Re-organised Feb 1998 Russell King
   *
   *  We now have independent partition support from the
   *  block drivers, which allows all the partition code to
   *  be grouped in one location, and it to be mostly self
   *  contained.
   */
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/fs.h>
  #include <linux/slab.h>
  #include <linux/kmod.h>
  #include <linux/ctype.h>
  #include <linux/genhd.h>
  #include <linux/blktrace_api.h>
  
  #include "partitions/check.h"
  
  #ifdef CONFIG_BLK_DEV_MD
  extern void md_autodetect_dev(dev_t dev);
  #endif
   
  /*
   * disk_name() is used by partition check code and the genhd driver.
   * It formats the devicename of the indicated disk into
   * the supplied buffer (of size at least 32), and returns
   * a pointer to that same buffer (for convenience).
   */
  
  char *disk_name(struct gendisk *hd, int partno, char *buf)
  {
  	if (!partno)
  		snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
  	else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
  		snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno);
  	else
  		snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno);
  
  	return buf;
  }
  
  const char *bdevname(struct block_device *bdev, char *buf)
  {
  	return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf);
  }
  
  EXPORT_SYMBOL(bdevname);
9c0fb1e31   Jiufei Xue   block: display th...
53
54
55
56
57
  const char *bio_devname(struct bio *bio, char *buf)
  {
  	return disk_name(bio->bi_disk, bio->bi_partno, buf);
  }
  EXPORT_SYMBOL(bio_devname);
94ea4158f   Al Viro   separate partitio...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  /*
   * There's very little reason to use this, you should really
   * have a struct block_device just about everywhere and use
   * bdevname() instead.
   */
  const char *__bdevname(dev_t dev, char *buffer)
  {
  	scnprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)",
  				MAJOR(dev), MINOR(dev));
  	return buffer;
  }
  
  EXPORT_SYMBOL(__bdevname);
  
  static ssize_t part_partition_show(struct device *dev,
  				   struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  
  	return sprintf(buf, "%d
  ", p->partno);
  }
  
  static ssize_t part_start_show(struct device *dev,
  			       struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  
  	return sprintf(buf, "%llu
  ",(unsigned long long)p->start_sect);
  }
  
  ssize_t part_size_show(struct device *dev,
  		       struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
c83f6bf98   Vivek Goyal   block: add partit...
94
95
  	return sprintf(buf, "%llu
  ",(unsigned long long)part_nr_sects_read(p));
94ea4158f   Al Viro   separate partitio...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  }
  
  static ssize_t part_ro_show(struct device *dev,
  			    struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  	return sprintf(buf, "%d
  ", p->policy ? 1 : 0);
  }
  
  static ssize_t part_alignment_offset_show(struct device *dev,
  					  struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  	return sprintf(buf, "%llu
  ", (unsigned long long)p->alignment_offset);
  }
  
  static ssize_t part_discard_alignment_show(struct device *dev,
  					   struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  	return sprintf(buf, "%u
  ", p->discard_alignment);
  }
  
  ssize_t part_stat_show(struct device *dev,
  		       struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
f5c156c4c   Shaohua Li   block: fix a cras...
126
  	struct request_queue *q = part_to_disk(p)->queue;
e016b7820   Mikulas Patocka   block: return jus...
127
  	unsigned int inflight;
94ea4158f   Al Viro   separate partitio...
128

e016b7820   Mikulas Patocka   block: return jus...
129
  	inflight = part_in_flight(q, p);
94ea4158f   Al Viro   separate partitio...
130
131
132
  	return sprintf(buf,
  		"%8lu %8lu %8llu %8u "
  		"%8lu %8lu %8llu %8u "
bdca3c87f   Michael Callahan   block: Track DISC...
133
134
  		"%8u %8u %8u "
  		"%8lu %8lu %8llu %8u"
94ea4158f   Al Viro   separate partitio...
135
136
  		"
  ",
dbae2c551   Michael Callahan   block: Define and...
137
138
139
  		part_stat_read(p, ios[STAT_READ]),
  		part_stat_read(p, merges[STAT_READ]),
  		(unsigned long long)part_stat_read(p, sectors[STAT_READ]),
b57e99b4b   Omar Sandoval   block: use nanose...
140
  		(unsigned int)part_stat_read_msecs(p, STAT_READ),
dbae2c551   Michael Callahan   block: Define and...
141
142
143
  		part_stat_read(p, ios[STAT_WRITE]),
  		part_stat_read(p, merges[STAT_WRITE]),
  		(unsigned long long)part_stat_read(p, sectors[STAT_WRITE]),
b57e99b4b   Omar Sandoval   block: use nanose...
144
  		(unsigned int)part_stat_read_msecs(p, STAT_WRITE),
e016b7820   Mikulas Patocka   block: return jus...
145
  		inflight,
94ea4158f   Al Viro   separate partitio...
146
  		jiffies_to_msecs(part_stat_read(p, io_ticks)),
bdca3c87f   Michael Callahan   block: Track DISC...
147
148
149
150
  		jiffies_to_msecs(part_stat_read(p, time_in_queue)),
  		part_stat_read(p, ios[STAT_DISCARD]),
  		part_stat_read(p, merges[STAT_DISCARD]),
  		(unsigned long long)part_stat_read(p, sectors[STAT_DISCARD]),
b57e99b4b   Omar Sandoval   block: use nanose...
151
  		(unsigned int)part_stat_read_msecs(p, STAT_DISCARD));
94ea4158f   Al Viro   separate partitio...
152
  }
bf0ddaba6   Omar Sandoval   blk-mq: fix sysfs...
153
154
  ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
  			   char *buf)
94ea4158f   Al Viro   separate partitio...
155
156
  {
  	struct hd_struct *p = dev_to_part(dev);
bf0ddaba6   Omar Sandoval   blk-mq: fix sysfs...
157
158
  	struct request_queue *q = part_to_disk(p)->queue;
  	unsigned int inflight[2];
94ea4158f   Al Viro   separate partitio...
159

bf0ddaba6   Omar Sandoval   blk-mq: fix sysfs...
160
161
162
  	part_in_flight_rw(q, p, inflight);
  	return sprintf(buf, "%8u %8u
  ", inflight[0], inflight[1]);
94ea4158f   Al Viro   separate partitio...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  }
  
  #ifdef CONFIG_FAIL_MAKE_REQUEST
  ssize_t part_fail_show(struct device *dev,
  		       struct device_attribute *attr, char *buf)
  {
  	struct hd_struct *p = dev_to_part(dev);
  
  	return sprintf(buf, "%d
  ", p->make_it_fail);
  }
  
  ssize_t part_fail_store(struct device *dev,
  			struct device_attribute *attr,
  			const char *buf, size_t count)
  {
  	struct hd_struct *p = dev_to_part(dev);
  	int i;
  
  	if (count > 0 && sscanf(buf, "%d", &i) > 0)
  		p->make_it_fail = (i == 0) ? 0 : 1;
  
  	return count;
  }
  #endif
5657a819a   Joe Perches   block drivers/blo...
188
189
190
191
192
193
194
195
  static DEVICE_ATTR(partition, 0444, part_partition_show, NULL);
  static DEVICE_ATTR(start, 0444, part_start_show, NULL);
  static DEVICE_ATTR(size, 0444, part_size_show, NULL);
  static DEVICE_ATTR(ro, 0444, part_ro_show, NULL);
  static DEVICE_ATTR(alignment_offset, 0444, part_alignment_offset_show, NULL);
  static DEVICE_ATTR(discard_alignment, 0444, part_discard_alignment_show, NULL);
  static DEVICE_ATTR(stat, 0444, part_stat_show, NULL);
  static DEVICE_ATTR(inflight, 0444, part_inflight_show, NULL);
94ea4158f   Al Viro   separate partitio...
196
197
  #ifdef CONFIG_FAIL_MAKE_REQUEST
  static struct device_attribute dev_attr_fail =
5657a819a   Joe Perches   block drivers/blo...
198
  	__ATTR(make-it-fail, 0644, part_fail_show, part_fail_store);
94ea4158f   Al Viro   separate partitio...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
  #endif
  
  static struct attribute *part_attrs[] = {
  	&dev_attr_partition.attr,
  	&dev_attr_start.attr,
  	&dev_attr_size.attr,
  	&dev_attr_ro.attr,
  	&dev_attr_alignment_offset.attr,
  	&dev_attr_discard_alignment.attr,
  	&dev_attr_stat.attr,
  	&dev_attr_inflight.attr,
  #ifdef CONFIG_FAIL_MAKE_REQUEST
  	&dev_attr_fail.attr,
  #endif
  	NULL
  };
  
  static struct attribute_group part_attr_group = {
  	.attrs = part_attrs,
  };
  
  static const struct attribute_group *part_attr_groups[] = {
  	&part_attr_group,
  #ifdef CONFIG_BLK_DEV_IO_TRACE
  	&blk_trace_attr_group,
  #endif
  	NULL
  };
  
  static void part_release(struct device *dev)
  {
  	struct hd_struct *p = dev_to_part(dev);
2da78092d   Keith Busch   block: Fix dev_t ...
231
  	blk_free_devt(dev->devt);
b54e5ed8f   Ming Lei   block: partition:...
232
  	hd_free_part(p);
94ea4158f   Al Viro   separate partitio...
233
234
  	kfree(p);
  }
0d9c51a6e   San Mehat   block: partition:...
235
236
237
238
239
240
241
242
243
  static int part_uevent(struct device *dev, struct kobj_uevent_env *env)
  {
  	struct hd_struct *part = dev_to_part(dev);
  
  	add_uevent_var(env, "PARTN=%u", part->partno);
  	if (part->info && part->info->volname[0])
  		add_uevent_var(env, "PARTNAME=%s", part->info->volname);
  	return 0;
  }
94ea4158f   Al Viro   separate partitio...
244
245
246
247
  struct device_type part_type = {
  	.name		= "partition",
  	.groups		= part_attr_groups,
  	.release	= part_release,
0d9c51a6e   San Mehat   block: partition:...
248
  	.uevent		= part_uevent,
94ea4158f   Al Viro   separate partitio...
249
  };
94a2c3a32   Yufen Yu   block: use rcu_wo...
250
  static void delete_partition_work_fn(struct work_struct *work)
94ea4158f   Al Viro   separate partitio...
251
  {
94a2c3a32   Yufen Yu   block: use rcu_wo...
252
253
  	struct hd_struct *part = container_of(to_rcu_work(work), struct hd_struct,
  					rcu_work);
94ea4158f   Al Viro   separate partitio...
254
255
256
257
258
259
  
  	part->start_sect = 0;
  	part->nr_sects = 0;
  	part_stat_set_all(part, 0);
  	put_device(part_to_dev(part));
  }
6c71013ec   Ming Lei   block: partition:...
260
  void __delete_partition(struct percpu_ref *ref)
94ea4158f   Al Viro   separate partitio...
261
  {
6c71013ec   Ming Lei   block: partition:...
262
  	struct hd_struct *part = container_of(ref, struct hd_struct, ref);
94a2c3a32   Yufen Yu   block: use rcu_wo...
263
264
  	INIT_RCU_WORK(&part->rcu_work, delete_partition_work_fn);
  	queue_rcu_work(system_wq, &part->rcu_work);
94ea4158f   Al Viro   separate partitio...
265
  }
6d2cf6f2b   Bart Van Assche   genhd: Annotate a...
266
267
268
269
  /*
   * Must be called either with bd_mutex held, before a disk can be opened or
   * after all disk users are gone.
   */
94ea4158f   Al Viro   separate partitio...
270
271
  void delete_partition(struct gendisk *disk, int partno)
  {
6d2cf6f2b   Bart Van Assche   genhd: Annotate a...
272
273
  	struct disk_part_tbl *ptbl =
  		rcu_dereference_protected(disk->part_tbl, 1);
94ea4158f   Al Viro   separate partitio...
274
275
276
277
  	struct hd_struct *part;
  
  	if (partno >= ptbl->len)
  		return;
6d2cf6f2b   Bart Van Assche   genhd: Annotate a...
278
  	part = rcu_dereference_protected(ptbl->part[partno], 1);
94ea4158f   Al Viro   separate partitio...
279
280
  	if (!part)
  		return;
94ea4158f   Al Viro   separate partitio...
281
282
283
284
  	rcu_assign_pointer(ptbl->part[partno], NULL);
  	rcu_assign_pointer(ptbl->last_lookup, NULL);
  	kobject_put(part->holder_dir);
  	device_del(part_to_dev(part));
6fcc44d1d   Yufen Yu   block: fix use-af...
285
286
287
288
289
290
291
  	/*
  	 * Remove gendisk pointer from idr so that it cannot be looked up
  	 * while RCU period before freeing gendisk is running to prevent
  	 * use-after-free issues. Note that the device number stays
  	 * "in-use" until we really free the gendisk.
  	 */
  	blk_invalidate_devt(part_devt(part));
6c71013ec   Ming Lei   block: partition:...
292
  	hd_struct_kill(part);
94ea4158f   Al Viro   separate partitio...
293
294
295
296
297
298
299
  }
  
  static ssize_t whole_disk_show(struct device *dev,
  			       struct device_attribute *attr, char *buf)
  {
  	return 0;
  }
5657a819a   Joe Perches   block drivers/blo...
300
  static DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
94ea4158f   Al Viro   separate partitio...
301

6d2cf6f2b   Bart Van Assche   genhd: Annotate a...
302
303
304
305
  /*
   * Must be called either with bd_mutex held, before a disk can be opened or
   * after all disk users are gone.
   */
94ea4158f   Al Viro   separate partitio...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  struct hd_struct *add_partition(struct gendisk *disk, int partno,
  				sector_t start, sector_t len, int flags,
  				struct partition_meta_info *info)
  {
  	struct hd_struct *p;
  	dev_t devt = MKDEV(0, 0);
  	struct device *ddev = disk_to_dev(disk);
  	struct device *pdev;
  	struct disk_part_tbl *ptbl;
  	const char *dname;
  	int err;
  
  	err = disk_expand_part_tbl(disk, partno);
  	if (err)
  		return ERR_PTR(err);
6d2cf6f2b   Bart Van Assche   genhd: Annotate a...
321
  	ptbl = rcu_dereference_protected(disk->part_tbl, 1);
94ea4158f   Al Viro   separate partitio...
322
323
324
325
326
327
328
329
330
331
332
333
  
  	if (ptbl->part[partno])
  		return ERR_PTR(-EBUSY);
  
  	p = kzalloc(sizeof(*p), GFP_KERNEL);
  	if (!p)
  		return ERR_PTR(-EBUSY);
  
  	if (!init_part_stats(p)) {
  		err = -ENOMEM;
  		goto out_free;
  	}
c83f6bf98   Vivek Goyal   block: add partit...
334
335
  
  	seqcount_init(&p->nr_sects_seq);
94ea4158f   Al Viro   separate partitio...
336
337
338
339
340
341
342
343
344
345
346
347
348
  	pdev = part_to_dev(p);
  
  	p->start_sect = start;
  	p->alignment_offset =
  		queue_limit_alignment_offset(&disk->queue->limits, start);
  	p->discard_alignment =
  		queue_limit_discard_alignment(&disk->queue->limits, start);
  	p->nr_sects = len;
  	p->partno = partno;
  	p->policy = get_disk_ro(disk);
  
  	if (info) {
  		struct partition_meta_info *pinfo = alloc_part_info(disk);
7bd897cfc   Dan Carpenter   block: fix an err...
349
350
  		if (!pinfo) {
  			err = -ENOMEM;
94ea4158f   Al Viro   separate partitio...
351
  			goto out_free_stats;
7bd897cfc   Dan Carpenter   block: fix an err...
352
  		}
94ea4158f   Al Viro   separate partitio...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  		memcpy(pinfo, info, sizeof(*info));
  		p->info = pinfo;
  	}
  
  	dname = dev_name(ddev);
  	if (isdigit(dname[strlen(dname) - 1]))
  		dev_set_name(pdev, "%sp%d", dname, partno);
  	else
  		dev_set_name(pdev, "%s%d", dname, partno);
  
  	device_initialize(pdev);
  	pdev->class = &block_class;
  	pdev->type = &part_type;
  	pdev->parent = ddev;
  
  	err = blk_alloc_devt(p, &devt);
  	if (err)
  		goto out_free_info;
  	pdev->devt = devt;
  
  	/* delay uevent until 'holders' subdir is created */
  	dev_set_uevent_suppress(pdev, 1);
  	err = device_add(pdev);
  	if (err)
  		goto out_put;
  
  	err = -ENOMEM;
  	p->holder_dir = kobject_create_and_add("holders", &pdev->kobj);
  	if (!p->holder_dir)
  		goto out_del;
  
  	dev_set_uevent_suppress(pdev, 0);
  	if (flags & ADDPART_FLAG_WHOLEDISK) {
  		err = device_create_file(pdev, &dev_attr_whole_disk);
  		if (err)
  			goto out_del;
  	}
b30a337ca   Ming Lei   block: partition:...
390
391
392
393
394
395
  	err = hd_ref_init(p);
  	if (err) {
  		if (flags & ADDPART_FLAG_WHOLEDISK)
  			goto out_remove_file;
  		goto out_del;
  	}
94ea4158f   Al Viro   separate partitio...
396
397
398
399
400
401
  	/* everything is up and running, commence */
  	rcu_assign_pointer(ptbl->part[partno], p);
  
  	/* suppress uevent if the disk suppresses it */
  	if (!dev_get_uevent_suppress(ddev))
  		kobject_uevent(&pdev->kobj, KOBJ_ADD);
b30a337ca   Ming Lei   block: partition:...
402
  	return p;
94ea4158f   Al Viro   separate partitio...
403
404
405
406
407
408
409
410
  
  out_free_info:
  	free_part_info(p);
  out_free_stats:
  	free_part_stats(p);
  out_free:
  	kfree(p);
  	return ERR_PTR(err);
b30a337ca   Ming Lei   block: partition:...
411
412
  out_remove_file:
  	device_remove_file(pdev, &dev_attr_whole_disk);
94ea4158f   Al Viro   separate partitio...
413
414
415
416
417
  out_del:
  	kobject_put(p->holder_dir);
  	device_del(pdev);
  out_put:
  	put_device(pdev);
94ea4158f   Al Viro   separate partitio...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  	return ERR_PTR(err);
  }
  
  static bool disk_unlock_native_capacity(struct gendisk *disk)
  {
  	const struct block_device_operations *bdops = disk->fops;
  
  	if (bdops->unlock_native_capacity &&
  	    !(disk->flags & GENHD_FL_NATIVE_CAPACITY)) {
  		printk(KERN_CONT "enabling native capacity
  ");
  		bdops->unlock_native_capacity(disk);
  		disk->flags |= GENHD_FL_NATIVE_CAPACITY;
  		return true;
  	} else {
  		printk(KERN_CONT "truncated
  ");
  		return false;
  	}
  }
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
438
  static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
94ea4158f   Al Viro   separate partitio...
439
  {
94ea4158f   Al Viro   separate partitio...
440
441
  	struct disk_part_iter piter;
  	struct hd_struct *part;
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
442
  	int res;
94ea4158f   Al Viro   separate partitio...
443

77032ca66   Eric Sandeen   Return EBUSY from...
444
  	if (bdev->bd_part_count || bdev->bd_super)
94ea4158f   Al Viro   separate partitio...
445
446
447
448
449
450
451
452
453
  		return -EBUSY;
  	res = invalidate_partition(disk, 0);
  	if (res)
  		return res;
  
  	disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
  	while ((part = disk_part_iter_next(&piter)))
  		delete_partition(disk, part->partno);
  	disk_part_iter_exit(&piter);
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
454
455
  	return 0;
  }
b02d8aaea   Damien Le Moal   block: Check part...
456
457
458
459
  static bool part_zone_aligned(struct gendisk *disk,
  			      struct block_device *bdev,
  			      sector_t from, sector_t size)
  {
f99e86485   Damien Le Moal   block: Rename blk...
460
  	unsigned int zone_sectors = bdev_zone_sectors(bdev);
b02d8aaea   Damien Le Moal   block: Check part...
461
462
463
464
465
466
467
468
469
470
471
  
  	/*
  	 * If this function is called, then the disk is a zoned block device
  	 * (host-aware or host-managed). This can be detected even if the
  	 * zoned block device support is disabled (CONFIG_BLK_DEV_ZONED not
  	 * set). In this case, however, only host-aware devices will be seen
  	 * as a block device is not created for host-managed devices. Without
  	 * zoned block device support, host-aware drives can still be used as
  	 * regular block devices (no zone operation) and their zone size will
  	 * be reported as 0. Allow this case.
  	 */
f99e86485   Damien Le Moal   block: Rename blk...
472
  	if (!zone_sectors)
b02d8aaea   Damien Le Moal   block: Check part...
473
474
475
476
477
478
479
480
  		return true;
  
  	/*
  	 * Check partition start and size alignement. If the drive has a
  	 * smaller last runt zone, ignore it and allow the partition to
  	 * use it. Check the zone size too: it should be a power of 2 number
  	 * of sectors.
  	 */
f99e86485   Damien Le Moal   block: Rename blk...
481
  	if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) {
b02d8aaea   Damien Le Moal   block: Check part...
482
  		u32 rem;
f99e86485   Damien Le Moal   block: Rename blk...
483
  		div_u64_rem(from, zone_sectors, &rem);
b02d8aaea   Damien Le Moal   block: Check part...
484
485
486
  		if (rem)
  			return false;
  		if ((from + size) < get_capacity(disk)) {
f99e86485   Damien Le Moal   block: Rename blk...
487
  			div_u64_rem(size, zone_sectors, &rem);
b02d8aaea   Damien Le Moal   block: Check part...
488
489
490
491
492
  			if (rem)
  				return false;
  		}
  
  	} else {
f99e86485   Damien Le Moal   block: Rename blk...
493
  		if (from & (zone_sectors - 1))
b02d8aaea   Damien Le Moal   block: Check part...
494
495
  			return false;
  		if ((from + size) < get_capacity(disk) &&
f99e86485   Damien Le Moal   block: Rename blk...
496
  		    (size & (zone_sectors - 1)))
b02d8aaea   Damien Le Moal   block: Check part...
497
498
499
500
501
502
  			return false;
  
  	}
  
  	return true;
  }
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
503
504
505
506
507
508
509
  int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
  {
  	struct parsed_partitions *state = NULL;
  	struct hd_struct *part;
  	int p, highest, res;
  rescan:
  	if (state && !IS_ERR(state)) {
ac2e5327a   Ming Lei   block/partitions:...
510
  		free_partitions(state);
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
511
512
513
514
515
516
  		state = NULL;
  	}
  
  	res = drop_partitions(disk, bdev);
  	if (res)
  		return res;
94ea4158f   Al Viro   separate partitio...
517
518
  	if (disk->fops->revalidate_disk)
  		disk->fops->revalidate_disk(disk);
5afb78356   Christoph Hellwig   block: don't prin...
519
  	check_disk_size_change(disk, bdev, true);
94ea4158f   Al Viro   separate partitio...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  	bdev->bd_invalidated = 0;
  	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
  		return 0;
  	if (IS_ERR(state)) {
  		/*
  		 * I/O error reading the partition table.  If any
  		 * partition code tried to read beyond EOD, retry
  		 * after unlocking native capacity.
  		 */
  		if (PTR_ERR(state) == -ENOSPC) {
  			printk(KERN_WARNING "%s: partition table beyond EOD, ",
  			       disk->disk_name);
  			if (disk_unlock_native_capacity(disk))
  				goto rescan;
  		}
  		return -EIO;
  	}
  	/*
  	 * If any partition code tried to read beyond EOD, try
  	 * unlocking native capacity even if partition table is
  	 * successfully read as we could be missing some partitions.
  	 */
  	if (state->access_beyond_eod) {
  		printk(KERN_WARNING
  		       "%s: partition table partially beyond EOD, ",
  		       disk->disk_name);
  		if (disk_unlock_native_capacity(disk))
  			goto rescan;
  	}
  
  	/* tell userspace that the media / partition table may have changed */
  	kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
  
  	/* Detect the highest partition number and preallocate
  	 * disk->part_tbl.  This is an optimization and not strictly
  	 * necessary.
  	 */
  	for (p = 1, highest = 0; p < state->limit; p++)
  		if (state->parts[p].size)
  			highest = p;
  
  	disk_expand_part_tbl(disk, highest);
  
  	/* add partitions */
  	for (p = 1; p < state->limit; p++) {
  		sector_t size, from;
94ea4158f   Al Viro   separate partitio...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  
  		size = state->parts[p].size;
  		if (!size)
  			continue;
  
  		from = state->parts[p].from;
  		if (from >= get_capacity(disk)) {
  			printk(KERN_WARNING
  			       "%s: p%d start %llu is beyond EOD, ",
  			       disk->disk_name, p, (unsigned long long) from);
  			if (disk_unlock_native_capacity(disk))
  				goto rescan;
  			continue;
  		}
  
  		if (from + size > get_capacity(disk)) {
  			printk(KERN_WARNING
  			       "%s: p%d size %llu extends beyond EOD, ",
  			       disk->disk_name, p, (unsigned long long) size);
  
  			if (disk_unlock_native_capacity(disk)) {
  				/* free state and restart */
  				goto rescan;
  			} else {
  				/*
  				 * we can not ignore partitions of broken tables
  				 * created by for example camera firmware, but
  				 * we limit them to the end of the disk to avoid
  				 * creating invalid block devices
  				 */
  				size = get_capacity(disk) - from;
  			}
  		}
b02d8aaea   Damien Le Moal   block: Check part...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
  		/*
  		 * On a zoned block device, partitions should be aligned on the
  		 * device zone size (i.e. zone boundary crossing not allowed).
  		 * Otherwise, resetting the write pointer of the last zone of
  		 * one partition may impact the following partition.
  		 */
  		if (bdev_is_zoned(bdev) &&
  		    !part_zone_aligned(disk, bdev, from, size)) {
  			printk(KERN_WARNING
  			       "%s: p%d start %llu+%llu is not zone aligned
  ",
  			       disk->disk_name, p, (unsigned long long) from,
  			       (unsigned long long) size);
  			continue;
  		}
94ea4158f   Al Viro   separate partitio...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  		part = add_partition(disk, p, from, size,
  				     state->parts[p].flags,
  				     &state->parts[p].info);
  		if (IS_ERR(part)) {
  			printk(KERN_ERR " %s: p%d could not be added: %ld
  ",
  			       disk->disk_name, p, -PTR_ERR(part));
  			continue;
  		}
  #ifdef CONFIG_BLK_DEV_MD
  		if (state->parts[p].flags & ADDPART_FLAG_RAID)
  			md_autodetect_dev(part_to_dev(part)->devt);
  #endif
  	}
ac2e5327a   Ming Lei   block/partitions:...
628
  	free_partitions(state);
94ea4158f   Al Viro   separate partitio...
629
630
  	return 0;
  }
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
631
632
633
634
635
636
637
638
639
640
641
642
  int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
  {
  	int res;
  
  	if (!bdev->bd_invalidated)
  		return 0;
  
  	res = drop_partitions(disk, bdev);
  	if (res)
  		return res;
  
  	set_capacity(disk, 0);
5afb78356   Christoph Hellwig   block: don't prin...
643
  	check_disk_size_change(disk, bdev, false);
fe316bf2d   Jun'ichi Nomura   block: Fix NULL p...
644
645
646
647
648
649
  	bdev->bd_invalidated = 0;
  	/* tell userspace that the media / partition table may have changed */
  	kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
  
  	return 0;
  }
d1a5f2b4d   Dan Williams   block: use DAX fo...
650
651
  unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
  {
a41fe02b6   Dan Williams   Revert "block: us...
652
  	struct address_space *mapping = bdev->bd_inode->i_mapping;
94ea4158f   Al Viro   separate partitio...
653
  	struct page *page;
a41fe02b6   Dan Williams   Revert "block: us...
654
  	page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_SHIFT-9)), NULL);
94ea4158f   Al Viro   separate partitio...
655
656
657
658
  	if (!IS_ERR(page)) {
  		if (PageError(page))
  			goto fail;
  		p->v = page;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
659
  		return (unsigned char *)page_address(page) +  ((n & ((1 << (PAGE_SHIFT - 9)) - 1)) << 9);
94ea4158f   Al Viro   separate partitio...
660
  fail:
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
661
  		put_page(page);
94ea4158f   Al Viro   separate partitio...
662
663
664
665
666
667
  	}
  	p->v = NULL;
  	return NULL;
  }
  
  EXPORT_SYMBOL(read_dev_sector);