aboutsummaryrefslogtreecommitdiffstats
path: root/fs/partitions
diff options
context:
space:
mode:
Diffstat (limited to 'fs/partitions')
-rw-r--r--fs/partitions/check.c315
1 files changed, 105 insertions, 210 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9184215f3ef3..97f3f5f064ee 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -195,96 +195,45 @@ check_partition(struct gendisk *hd, struct block_device *bdev)
195 return ERR_PTR(res); 195 return ERR_PTR(res);
196} 196}
197 197
198/* 198static ssize_t part_start_show(struct device *dev,
199 * sysfs bindings for partitions 199 struct device_attribute *attr, char *buf)
200 */
201
202struct part_attribute {
203 struct attribute attr;
204 ssize_t (*show)(struct hd_struct *,char *);
205 ssize_t (*store)(struct hd_struct *,const char *, size_t);
206};
207
208static ssize_t
209part_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
210{ 200{
211 struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); 201 struct hd_struct *p = dev_to_part(dev);
212 struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
213 ssize_t ret = 0;
214 if (part_attr->show)
215 ret = part_attr->show(p, page);
216 return ret;
217}
218static ssize_t
219part_attr_store(struct kobject * kobj, struct attribute * attr,
220 const char *page, size_t count)
221{
222 struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
223 struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
224 ssize_t ret = 0;
225 202
226 if (part_attr->store) 203 return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect);
227 ret = part_attr->store(p, page, count);
228 return ret;
229} 204}
230 205
231static struct sysfs_ops part_sysfs_ops = { 206static ssize_t part_size_show(struct device *dev,
232 .show = part_attr_show, 207 struct device_attribute *attr, char *buf)
233 .store = part_attr_store,
234};
235
236static ssize_t part_uevent_store(struct hd_struct * p,
237 const char *page, size_t count)
238{ 208{
239 kobject_uevent(&p->kobj, KOBJ_ADD); 209 struct hd_struct *p = dev_to_part(dev);
240 return count; 210 return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
241} 211}
242static ssize_t part_dev_read(struct hd_struct * p, char *page) 212
243{ 213static ssize_t part_stat_show(struct device *dev,
244 struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj); 214 struct device_attribute *attr, char *buf)
245 dev_t dev = MKDEV(disk->major, disk->first_minor + p->partno);
246 return print_dev_t(page, dev);
247}
248static ssize_t part_start_read(struct hd_struct * p, char *page)
249{
250 return sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
251}
252static ssize_t part_size_read(struct hd_struct * p, char *page)
253{
254 return sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
255}
256static ssize_t part_stat_read(struct hd_struct * p, char *page)
257{ 215{
258 return sprintf(page, "%8u %8llu %8u %8llu\n", 216 struct hd_struct *p = dev_to_part(dev);
217
218 return sprintf(buf, "%8u %8llu %8u %8llu\n",
259 p->ios[0], (unsigned long long)p->sectors[0], 219 p->ios[0], (unsigned long long)p->sectors[0],
260 p->ios[1], (unsigned long long)p->sectors[1]); 220 p->ios[1], (unsigned long long)p->sectors[1]);
261} 221}
262static struct part_attribute part_attr_uevent = {
263 .attr = {.name = "uevent", .mode = S_IWUSR },
264 .store = part_uevent_store
265};
266static struct part_attribute part_attr_dev = {
267 .attr = {.name = "dev", .mode = S_IRUGO },
268 .show = part_dev_read
269};
270static struct part_attribute part_attr_start = {
271 .attr = {.name = "start", .mode = S_IRUGO },
272 .show = part_start_read
273};
274static struct part_attribute part_attr_size = {
275 .attr = {.name = "size", .mode = S_IRUGO },
276 .show = part_size_read
277};
278static struct part_attribute part_attr_stat = {
279 .attr = {.name = "stat", .mode = S_IRUGO },
280 .show = part_stat_read
281};
282 222
283#ifdef CONFIG_FAIL_MAKE_REQUEST 223#ifdef CONFIG_FAIL_MAKE_REQUEST
224static ssize_t part_fail_show(struct device *dev,
225 struct device_attribute *attr, char *buf)
226{
227 struct hd_struct *p = dev_to_part(dev);
284 228
285static ssize_t part_fail_store(struct hd_struct * p, 229 return sprintf(buf, "%d\n", p->make_it_fail);
230}
231
232static ssize_t part_fail_store(struct device *dev,
233 struct device_attribute *attr,
286 const char *buf, size_t count) 234 const char *buf, size_t count)
287{ 235{
236 struct hd_struct *p = dev_to_part(dev);
288 int i; 237 int i;
289 238
290 if (count > 0 && sscanf(buf, "%d", &i) > 0) 239 if (count > 0 && sscanf(buf, "%d", &i) > 0)
@@ -292,49 +241,52 @@ static ssize_t part_fail_store(struct hd_struct * p,
292 241
293 return count; 242 return count;
294} 243}
295static ssize_t part_fail_read(struct hd_struct * p, char *page) 244#endif
296{
297 return sprintf(page, "%d\n", p->make_it_fail);
298}
299static struct part_attribute part_attr_fail = {
300 .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR },
301 .store = part_fail_store,
302 .show = part_fail_read
303};
304 245
246static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
247static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
248static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
249#ifdef CONFIG_FAIL_MAKE_REQUEST
250static struct device_attribute dev_attr_fail =
251 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
305#endif 252#endif
306 253
307static struct attribute * default_attrs[] = { 254static struct attribute *part_attrs[] = {
308 &part_attr_uevent.attr, 255 &dev_attr_start.attr,
309 &part_attr_dev.attr, 256 &dev_attr_size.attr,
310 &part_attr_start.attr, 257 &dev_attr_stat.attr,
311 &part_attr_size.attr,
312 &part_attr_stat.attr,
313#ifdef CONFIG_FAIL_MAKE_REQUEST 258#ifdef CONFIG_FAIL_MAKE_REQUEST
314 &part_attr_fail.attr, 259 &dev_attr_fail.attr,
315#endif 260#endif
316 NULL, 261 NULL
317}; 262};
318 263
319extern struct kset *block_kset; 264static struct attribute_group part_attr_group = {
265 .attrs = part_attrs,
266};
320 267
321static void part_release(struct kobject *kobj) 268static struct attribute_group *part_attr_groups[] = {
269 &part_attr_group,
270 NULL
271};
272
273static void part_release(struct device *dev)
322{ 274{
323 struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); 275 struct hd_struct *p = dev_to_part(dev);
324 kfree(p); 276 kfree(p);
325} 277}
326 278
327struct kobj_type ktype_part = { 279struct device_type part_type = {
280 .name = "partition",
281 .groups = part_attr_groups,
328 .release = part_release, 282 .release = part_release,
329 .default_attrs = default_attrs,
330 .sysfs_ops = &part_sysfs_ops,
331}; 283};
332 284
333static inline void partition_sysfs_add_subdir(struct hd_struct *p) 285static inline void partition_sysfs_add_subdir(struct hd_struct *p)
334{ 286{
335 struct kobject *k; 287 struct kobject *k;
336 288
337 k = kobject_get(&p->kobj); 289 k = kobject_get(&p->dev.kobj);
338 p->holder_dir = kobject_create_and_add("holders", k); 290 p->holder_dir = kobject_create_and_add("holders", k);
339 kobject_put(k); 291 kobject_put(k);
340} 292}
@@ -343,7 +295,7 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
343{ 295{
344 struct kobject *k; 296 struct kobject *k;
345 297
346 k = kobject_get(&disk->kobj); 298 k = kobject_get(&disk->dev.kobj);
347 disk->holder_dir = kobject_create_and_add("holders", k); 299 disk->holder_dir = kobject_create_and_add("holders", k);
348 disk->slave_dir = kobject_create_and_add("slaves", k); 300 disk->slave_dir = kobject_create_and_add("slaves", k);
349 kobject_put(k); 301 kobject_put(k);
@@ -352,6 +304,7 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
352void delete_partition(struct gendisk *disk, int part) 304void delete_partition(struct gendisk *disk, int part)
353{ 305{
354 struct hd_struct *p = disk->part[part-1]; 306 struct hd_struct *p = disk->part[part-1];
307
355 if (!p) 308 if (!p)
356 return; 309 return;
357 if (!p->nr_sects) 310 if (!p->nr_sects)
@@ -361,113 +314,55 @@ void delete_partition(struct gendisk *disk, int part)
361 p->nr_sects = 0; 314 p->nr_sects = 0;
362 p->ios[0] = p->ios[1] = 0; 315 p->ios[0] = p->ios[1] = 0;
363 p->sectors[0] = p->sectors[1] = 0; 316 p->sectors[0] = p->sectors[1] = 0;
364 sysfs_remove_link(&p->kobj, "subsystem");
365 kobject_unregister(p->holder_dir); 317 kobject_unregister(p->holder_dir);
366 kobject_uevent(&p->kobj, KOBJ_REMOVE); 318 device_del(&p->dev);
367 kobject_del(&p->kobj); 319 put_device(&p->dev);
368 kobject_put(&p->kobj);
369} 320}
370 321
371void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) 322void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags)
372{ 323{
373 struct hd_struct *p; 324 struct hd_struct *p;
325 int err;
374 326
375 p = kzalloc(sizeof(*p), GFP_KERNEL); 327 p = kzalloc(sizeof(*p), GFP_KERNEL);
376 if (!p) 328 if (!p)
377 return; 329 return;
378 330
379 p->start_sect = start; 331 p->start_sect = start;
380 p->nr_sects = len; 332 p->nr_sects = len;
381 p->partno = part; 333 p->partno = part;
382 p->policy = disk->policy; 334 p->policy = disk->policy;
383 335
384 if (isdigit(disk->kobj.k_name[strlen(disk->kobj.k_name)-1])) 336 if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1]))
385 kobject_set_name(&p->kobj, "%sp%d", 337 snprintf(p->dev.bus_id, BUS_ID_SIZE,
386 kobject_name(&disk->kobj), part); 338 "%sp%d", disk->dev.bus_id, part);
387 else 339 else
388 kobject_set_name(&p->kobj, "%s%d", 340 snprintf(p->dev.bus_id, BUS_ID_SIZE,
389 kobject_name(&disk->kobj),part); 341 "%s%d", disk->dev.bus_id, part);
390 p->kobj.parent = &disk->kobj; 342
391 p->kobj.ktype = &ktype_part; 343 device_initialize(&p->dev);
392 kobject_init(&p->kobj); 344 p->dev.devt = MKDEV(disk->major, disk->first_minor + part);
393 kobject_add(&p->kobj); 345 p->dev.class = &block_class;
394 if (!disk->part_uevent_suppress) 346 p->dev.type = &part_type;
395 kobject_uevent(&p->kobj, KOBJ_ADD); 347 p->dev.parent = &disk->dev;
396 sysfs_create_link(&p->kobj, &block_kset->kobj, "subsystem"); 348 disk->part[part-1] = p;
349
350 /* delay uevent until 'holders' subdir is created */
351 p->dev.uevent_suppress = 1;
352 device_add(&p->dev);
353 partition_sysfs_add_subdir(p);
354 p->dev.uevent_suppress = 0;
397 if (flags & ADDPART_FLAG_WHOLEDISK) { 355 if (flags & ADDPART_FLAG_WHOLEDISK) {
398 static struct attribute addpartattr = { 356 static struct attribute addpartattr = {
399 .name = "whole_disk", 357 .name = "whole_disk",
400 .mode = S_IRUSR | S_IRGRP | S_IROTH, 358 .mode = S_IRUSR | S_IRGRP | S_IROTH,
401 }; 359 };
402 360 err = sysfs_create_file(&p->dev.kobj, &addpartattr);
403 sysfs_create_file(&p->kobj, &addpartattr);
404 } 361 }
405 partition_sysfs_add_subdir(p);
406 disk->part[part-1] = p;
407}
408 362
409static char *make_block_name(struct gendisk *disk) 363 /* suppress uevent if the disk supresses it */
410{ 364 if (!disk->dev.uevent_suppress)
411 char *name; 365 kobject_uevent(&p->dev.kobj, KOBJ_ADD);
412 static char *block_str = "block:";
413 int size;
414 char *s;
415
416 size = strlen(block_str) + strlen(disk->disk_name) + 1;
417 name = kmalloc(size, GFP_KERNEL);
418 if (!name)
419 return NULL;
420 strcpy(name, block_str);
421 strcat(name, disk->disk_name);
422 /* ewww... some of these buggers have / in name... */
423 s = strchr(name, '/');
424 if (s)
425 *s = '!';
426 return name;
427}
428
429static int disk_sysfs_symlinks(struct gendisk *disk)
430{
431 struct device *target = get_device(disk->driverfs_dev);
432 int err;
433 char *disk_name = NULL;
434
435 if (target) {
436 disk_name = make_block_name(disk);
437 if (!disk_name) {
438 err = -ENOMEM;
439 goto err_out;
440 }
441
442 err = sysfs_create_link(&disk->kobj, &target->kobj, "device");
443 if (err)
444 goto err_out_disk_name;
445
446 err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name);
447 if (err)
448 goto err_out_dev_link;
449 }
450
451 err = sysfs_create_link(&disk->kobj, &block_kset->kobj,
452 "subsystem");
453 if (err)
454 goto err_out_disk_name_lnk;
455
456 kfree(disk_name);
457
458 return 0;
459
460err_out_disk_name_lnk:
461 if (target) {
462 sysfs_remove_link(&target->kobj, disk_name);
463err_out_dev_link:
464 sysfs_remove_link(&disk->kobj, "device");
465err_out_disk_name:
466 kfree(disk_name);
467err_out:
468 put_device(target);
469 }
470 return err;
471} 366}
472 367
473/* Not exported, helper to add_disk(). */ 368/* Not exported, helper to add_disk(). */
@@ -479,19 +374,29 @@ void register_disk(struct gendisk *disk)
479 struct hd_struct *p; 374 struct hd_struct *p;
480 int err; 375 int err;
481 376
482 kobject_set_name(&disk->kobj, "%s", disk->disk_name); 377 disk->dev.parent = disk->driverfs_dev;
483 /* ewww... some of these buggers have / in name... */ 378 disk->dev.devt = MKDEV(disk->major, disk->first_minor);
484 s = strchr(disk->kobj.k_name, '/'); 379
380 strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN);
381 /* ewww... some of these buggers have / in the name... */
382 s = strchr(disk->dev.bus_id, '/');
485 if (s) 383 if (s)
486 *s = '!'; 384 *s = '!';
487 if ((err = kobject_add(&disk->kobj))) 385
386 /* delay uevents, until we scanned partition table */
387 disk->dev.uevent_suppress = 1;
388
389 if (device_add(&disk->dev))
488 return; 390 return;
489 err = disk_sysfs_symlinks(disk); 391#ifndef CONFIG_SYSFS_DEPRECATED
392 err = sysfs_create_link(block_depr, &disk->dev.kobj,
393 kobject_name(&disk->dev.kobj));
490 if (err) { 394 if (err) {
491 kobject_del(&disk->kobj); 395 device_del(&disk->dev);
492 return; 396 return;
493 } 397 }
494 disk_sysfs_add_subdirs(disk); 398#endif
399 disk_sysfs_add_subdirs(disk);
495 400
496 /* No minors to use for partitions */ 401 /* No minors to use for partitions */
497 if (disk->minors == 1) 402 if (disk->minors == 1)
@@ -505,25 +410,23 @@ void register_disk(struct gendisk *disk)
505 if (!bdev) 410 if (!bdev)
506 goto exit; 411 goto exit;
507 412
508 /* scan partition table, but suppress uevents */
509 bdev->bd_invalidated = 1; 413 bdev->bd_invalidated = 1;
510 disk->part_uevent_suppress = 1;
511 err = blkdev_get(bdev, FMODE_READ, 0); 414 err = blkdev_get(bdev, FMODE_READ, 0);
512 disk->part_uevent_suppress = 0;
513 if (err < 0) 415 if (err < 0)
514 goto exit; 416 goto exit;
515 blkdev_put(bdev); 417 blkdev_put(bdev);
516 418
517exit: 419exit:
518 /* announce disk after possible partitions are already created */ 420 /* announce disk after possible partitions are created */
519 kobject_uevent(&disk->kobj, KOBJ_ADD); 421 disk->dev.uevent_suppress = 0;
422 kobject_uevent(&disk->dev.kobj, KOBJ_ADD);
520 423
521 /* announce possible partitions */ 424 /* announce possible partitions */
522 for (i = 1; i < disk->minors; i++) { 425 for (i = 1; i < disk->minors; i++) {
523 p = disk->part[i-1]; 426 p = disk->part[i-1];
524 if (!p || !p->nr_sects) 427 if (!p || !p->nr_sects)
525 continue; 428 continue;
526 kobject_uevent(&p->kobj, KOBJ_ADD); 429 kobject_uevent(&p->dev.kobj, KOBJ_ADD);
527 } 430 }
528} 431}
529 432
@@ -602,19 +505,11 @@ void del_gendisk(struct gendisk *disk)
602 disk_stat_set_all(disk, 0); 505 disk_stat_set_all(disk, 0);
603 disk->stamp = 0; 506 disk->stamp = 0;
604 507
605 kobject_uevent(&disk->kobj, KOBJ_REMOVE);
606 kobject_unregister(disk->holder_dir); 508 kobject_unregister(disk->holder_dir);
607 kobject_unregister(disk->slave_dir); 509 kobject_unregister(disk->slave_dir);
608 if (disk->driverfs_dev) { 510 disk->driverfs_dev = NULL;
609 char *disk_name = make_block_name(disk); 511#ifndef CONFIG_SYSFS_DEPRECATED
610 sysfs_remove_link(&disk->kobj, "device"); 512 sysfs_remove_link(block_depr, disk->dev.bus_id);
611 if (disk_name) { 513#endif
612 sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name); 514 device_del(&disk->dev);
613 kfree(disk_name);
614 }
615 put_device(disk->driverfs_dev);
616 disk->driverfs_dev = NULL;
617 }
618 sysfs_remove_link(&disk->kobj, "subsystem");
619 kobject_del(&disk->kobj);
620} 515}