Commit 11c3b79218390a139f2d474ee1e983a672d5839a
Committed by
Mark Fasheh
1 parent
6d8344baee
Exists in
master
and in
4 other branches
configfs: Allow ->make_item() and ->make_group() to return detailed errors.
The configfs operations ->make_item() and ->make_group() currently return a new item/group. A return of NULL signifies an error. Because of this, -ENOMEM is the only return code bubbled up the stack. Multiple folks have requested the ability to return specific error codes when these operations fail. This patch adds that ability by changing the ->make_item/group() ops to return an int. Also updated are the in-kernel users of configfs. Signed-off-by: Joel Becker <joel.becker@oracle.com>
Showing 8 changed files with 94 additions and 64 deletions Side-by-side Diff
Documentation/filesystems/configfs/configfs.txt
... | ... | @@ -233,10 +233,12 @@ |
233 | 233 | config_item_type. |
234 | 234 | |
235 | 235 | struct configfs_group_operations { |
236 | - struct config_item *(*make_item)(struct config_group *group, | |
237 | - const char *name); | |
238 | - struct config_group *(*make_group)(struct config_group *group, | |
239 | - const char *name); | |
236 | + int (*make_item)(struct config_group *group, | |
237 | + const char *name, | |
238 | + struct config_item **new_item); | |
239 | + int (*make_group)(struct config_group *group, | |
240 | + const char *name, | |
241 | + struct config_group **new_group); | |
240 | 242 | int (*commit_item)(struct config_item *item); |
241 | 243 | void (*disconnect_notify)(struct config_group *group, |
242 | 244 | struct config_item *item); |
Documentation/filesystems/configfs/configfs_example.c
... | ... | @@ -273,13 +273,13 @@ |
273 | 273 | return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; |
274 | 274 | } |
275 | 275 | |
276 | -static struct config_item *simple_children_make_item(struct config_group *group, const char *name) | |
276 | +static int simple_children_make_item(struct config_group *group, const char *name, struct config_item **new_item) | |
277 | 277 | { |
278 | 278 | struct simple_child *simple_child; |
279 | 279 | |
280 | 280 | simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); |
281 | 281 | if (!simple_child) |
282 | - return NULL; | |
282 | + return -ENOMEM; | |
283 | 283 | |
284 | 284 | |
285 | 285 | config_item_init_type_name(&simple_child->item, name, |
... | ... | @@ -287,7 +287,8 @@ |
287 | 287 | |
288 | 288 | simple_child->storeme = 0; |
289 | 289 | |
290 | - return &simple_child->item; | |
290 | + *new_item = &simple_child->item; | |
291 | + return 0; | |
291 | 292 | } |
292 | 293 | |
293 | 294 | static struct configfs_attribute simple_children_attr_description = { |
294 | 295 | |
295 | 296 | |
... | ... | @@ -359,20 +360,21 @@ |
359 | 360 | * children of its own. |
360 | 361 | */ |
361 | 362 | |
362 | -static struct config_group *group_children_make_group(struct config_group *group, const char *name) | |
363 | +static int group_children_make_group(struct config_group *group, const char *name, struct config_group **new_group) | |
363 | 364 | { |
364 | 365 | struct simple_children *simple_children; |
365 | 366 | |
366 | 367 | simple_children = kzalloc(sizeof(struct simple_children), |
367 | 368 | GFP_KERNEL); |
368 | 369 | if (!simple_children) |
369 | - return NULL; | |
370 | + return -ENOMEM; | |
370 | 371 | |
371 | 372 | |
372 | 373 | config_group_init_type_name(&simple_children->group, name, |
373 | 374 | &simple_children_type); |
374 | 375 | |
375 | - return &simple_children->group; | |
376 | + *new_group = &simple_children->group; | |
377 | + return 0; | |
376 | 378 | } |
377 | 379 | |
378 | 380 | static struct configfs_attribute group_children_attr_description = { |
drivers/net/netconsole.c
... | ... | @@ -585,8 +585,9 @@ |
585 | 585 | * Group operations and type for netconsole_subsys. |
586 | 586 | */ |
587 | 587 | |
588 | -static struct config_item *make_netconsole_target(struct config_group *group, | |
589 | - const char *name) | |
588 | +static int make_netconsole_target(struct config_group *group, | |
589 | + const char *name, | |
590 | + struct config_item **new_item) | |
590 | 591 | { |
591 | 592 | unsigned long flags; |
592 | 593 | struct netconsole_target *nt; |
... | ... | @@ -598,7 +599,7 @@ |
598 | 599 | nt = kzalloc(sizeof(*nt), GFP_KERNEL); |
599 | 600 | if (!nt) { |
600 | 601 | printk(KERN_ERR "netconsole: failed to allocate memory\n"); |
601 | - return NULL; | |
602 | + return -ENOMEM; | |
602 | 603 | } |
603 | 604 | |
604 | 605 | nt->np.name = "netconsole"; |
... | ... | @@ -615,7 +616,8 @@ |
615 | 616 | list_add(&nt->list, &target_list); |
616 | 617 | spin_unlock_irqrestore(&target_list_lock, flags); |
617 | 618 | |
618 | - return &nt->item; | |
619 | + *new_item = &nt->item; | |
620 | + return 0; | |
619 | 621 | } |
620 | 622 | |
621 | 623 | static void drop_netconsole_target(struct config_group *group, |
fs/configfs/dir.c
... | ... | @@ -1073,25 +1073,24 @@ |
1073 | 1073 | group = NULL; |
1074 | 1074 | item = NULL; |
1075 | 1075 | if (type->ct_group_ops->make_group) { |
1076 | - group = type->ct_group_ops->make_group(to_config_group(parent_item), name); | |
1077 | - if (group) { | |
1076 | + ret = type->ct_group_ops->make_group(to_config_group(parent_item), name, &group); | |
1077 | + if (!ret) { | |
1078 | 1078 | link_group(to_config_group(parent_item), group); |
1079 | 1079 | item = &group->cg_item; |
1080 | 1080 | } |
1081 | 1081 | } else { |
1082 | - item = type->ct_group_ops->make_item(to_config_group(parent_item), name); | |
1083 | - if (item) | |
1082 | + ret = type->ct_group_ops->make_item(to_config_group(parent_item), name, &item); | |
1083 | + if (!ret) | |
1084 | 1084 | link_obj(parent_item, item); |
1085 | 1085 | } |
1086 | 1086 | mutex_unlock(&subsys->su_mutex); |
1087 | 1087 | |
1088 | 1088 | kfree(name); |
1089 | - if (!item) { | |
1089 | + if (ret) { | |
1090 | 1090 | /* |
1091 | - * If item == NULL, then link_obj() was never called. | |
1091 | + * If ret != 0, then link_obj() was never called. | |
1092 | 1092 | * There are no extra references to clean up. |
1093 | 1093 | */ |
1094 | - ret = -ENOMEM; | |
1095 | 1094 | goto out_put; |
1096 | 1095 | } |
1097 | 1096 |
fs/dlm/config.c
... | ... | @@ -41,16 +41,20 @@ |
41 | 41 | struct nodes; |
42 | 42 | struct node; |
43 | 43 | |
44 | -static struct config_group *make_cluster(struct config_group *, const char *); | |
44 | +static int make_cluster(struct config_group *, const char *, | |
45 | + struct config_group **); | |
45 | 46 | static void drop_cluster(struct config_group *, struct config_item *); |
46 | 47 | static void release_cluster(struct config_item *); |
47 | -static struct config_group *make_space(struct config_group *, const char *); | |
48 | +static int make_space(struct config_group *, const char *, | |
49 | + struct config_group **); | |
48 | 50 | static void drop_space(struct config_group *, struct config_item *); |
49 | 51 | static void release_space(struct config_item *); |
50 | -static struct config_item *make_comm(struct config_group *, const char *); | |
52 | +static int make_comm(struct config_group *, const char *, | |
53 | + struct config_item **); | |
51 | 54 | static void drop_comm(struct config_group *, struct config_item *); |
52 | 55 | static void release_comm(struct config_item *); |
53 | -static struct config_item *make_node(struct config_group *, const char *); | |
56 | +static int make_node(struct config_group *, const char *, | |
57 | + struct config_item **); | |
54 | 58 | static void drop_node(struct config_group *, struct config_item *); |
55 | 59 | static void release_node(struct config_item *); |
56 | 60 | |
... | ... | @@ -392,8 +396,8 @@ |
392 | 396 | return i ? container_of(i, struct node, item) : NULL; |
393 | 397 | } |
394 | 398 | |
395 | -static struct config_group *make_cluster(struct config_group *g, | |
396 | - const char *name) | |
399 | +static int make_cluster(struct config_group *g, const char *name, | |
400 | + struct config_group **new_g) | |
397 | 401 | { |
398 | 402 | struct cluster *cl = NULL; |
399 | 403 | struct spaces *sps = NULL; |
400 | 404 | |
... | ... | @@ -431,14 +435,15 @@ |
431 | 435 | |
432 | 436 | space_list = &sps->ss_group; |
433 | 437 | comm_list = &cms->cs_group; |
434 | - return &cl->group; | |
438 | + *new_g = &cl->group; | |
439 | + return 0; | |
435 | 440 | |
436 | 441 | fail: |
437 | 442 | kfree(cl); |
438 | 443 | kfree(gps); |
439 | 444 | kfree(sps); |
440 | 445 | kfree(cms); |
441 | - return NULL; | |
446 | + return -ENOMEM; | |
442 | 447 | } |
443 | 448 | |
444 | 449 | static void drop_cluster(struct config_group *g, struct config_item *i) |
... | ... | @@ -466,7 +471,8 @@ |
466 | 471 | kfree(cl); |
467 | 472 | } |
468 | 473 | |
469 | -static struct config_group *make_space(struct config_group *g, const char *name) | |
474 | +static int make_space(struct config_group *g, const char *name, | |
475 | + struct config_group **new_g) | |
470 | 476 | { |
471 | 477 | struct space *sp = NULL; |
472 | 478 | struct nodes *nds = NULL; |
473 | 479 | |
... | ... | @@ -489,13 +495,14 @@ |
489 | 495 | INIT_LIST_HEAD(&sp->members); |
490 | 496 | mutex_init(&sp->members_lock); |
491 | 497 | sp->members_count = 0; |
492 | - return &sp->group; | |
498 | + *new_g = &sp->group; | |
499 | + return 0; | |
493 | 500 | |
494 | 501 | fail: |
495 | 502 | kfree(sp); |
496 | 503 | kfree(gps); |
497 | 504 | kfree(nds); |
498 | - return NULL; | |
505 | + return -ENOMEM; | |
499 | 506 | } |
500 | 507 | |
501 | 508 | static void drop_space(struct config_group *g, struct config_item *i) |
502 | 509 | |
503 | 510 | |
... | ... | @@ -522,19 +529,21 @@ |
522 | 529 | kfree(sp); |
523 | 530 | } |
524 | 531 | |
525 | -static struct config_item *make_comm(struct config_group *g, const char *name) | |
532 | +static int make_comm(struct config_group *g, const char *name, | |
533 | + struct config_item **new_i) | |
526 | 534 | { |
527 | 535 | struct comm *cm; |
528 | 536 | |
529 | 537 | cm = kzalloc(sizeof(struct comm), GFP_KERNEL); |
530 | 538 | if (!cm) |
531 | - return NULL; | |
539 | + return -ENOMEM; | |
532 | 540 | |
533 | 541 | config_item_init_type_name(&cm->item, name, &comm_type); |
534 | 542 | cm->nodeid = -1; |
535 | 543 | cm->local = 0; |
536 | 544 | cm->addr_count = 0; |
537 | - return &cm->item; | |
545 | + *new_i = &cm->item; | |
546 | + return 0; | |
538 | 547 | } |
539 | 548 | |
540 | 549 | static void drop_comm(struct config_group *g, struct config_item *i) |
541 | 550 | |
... | ... | @@ -554,14 +563,15 @@ |
554 | 563 | kfree(cm); |
555 | 564 | } |
556 | 565 | |
557 | -static struct config_item *make_node(struct config_group *g, const char *name) | |
566 | +static int make_node(struct config_group *g, const char *name, | |
567 | + struct config_item **new_i) | |
558 | 568 | { |
559 | 569 | struct space *sp = to_space(g->cg_item.ci_parent); |
560 | 570 | struct node *nd; |
561 | 571 | |
562 | 572 | nd = kzalloc(sizeof(struct node), GFP_KERNEL); |
563 | 573 | if (!nd) |
564 | - return NULL; | |
574 | + return -ENOMEM; | |
565 | 575 | |
566 | 576 | config_item_init_type_name(&nd->item, name, &node_type); |
567 | 577 | nd->nodeid = -1; |
... | ... | @@ -573,7 +583,8 @@ |
573 | 583 | sp->members_count++; |
574 | 584 | mutex_unlock(&sp->members_lock); |
575 | 585 | |
576 | - return &nd->item; | |
586 | + *new_i = &nd->item; | |
587 | + return 0; | |
577 | 588 | } |
578 | 589 | |
579 | 590 | static void drop_node(struct config_group *g, struct config_item *i) |
fs/ocfs2/cluster/heartbeat.c
... | ... | @@ -1489,25 +1489,28 @@ |
1489 | 1489 | : NULL; |
1490 | 1490 | } |
1491 | 1491 | |
1492 | -static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group, | |
1493 | - const char *name) | |
1492 | +static int o2hb_heartbeat_group_make_item(struct config_group *group, | |
1493 | + const char *name, | |
1494 | + struct config_item **new_item) | |
1494 | 1495 | { |
1495 | 1496 | struct o2hb_region *reg = NULL; |
1496 | - struct config_item *ret = NULL; | |
1497 | + int ret = 0; | |
1497 | 1498 | |
1498 | 1499 | reg = kzalloc(sizeof(struct o2hb_region), GFP_KERNEL); |
1499 | - if (reg == NULL) | |
1500 | - goto out; /* ENOMEM */ | |
1500 | + if (reg == NULL) { | |
1501 | + ret = -ENOMEM; | |
1502 | + goto out; | |
1503 | + } | |
1501 | 1504 | |
1502 | 1505 | config_item_init_type_name(®->hr_item, name, &o2hb_region_type); |
1503 | 1506 | |
1504 | - ret = ®->hr_item; | |
1507 | + *new_item = ®->hr_item; | |
1505 | 1508 | |
1506 | 1509 | spin_lock(&o2hb_live_lock); |
1507 | 1510 | list_add_tail(®->hr_all_item, &o2hb_all_regions); |
1508 | 1511 | spin_unlock(&o2hb_live_lock); |
1509 | 1512 | out: |
1510 | - if (ret == NULL) | |
1513 | + if (ret) | |
1511 | 1514 | kfree(reg); |
1512 | 1515 | |
1513 | 1516 | return ret; |
fs/ocfs2/cluster/nodemanager.c
... | ... | @@ -644,27 +644,32 @@ |
644 | 644 | return ret; |
645 | 645 | } |
646 | 646 | |
647 | -static struct config_item *o2nm_node_group_make_item(struct config_group *group, | |
648 | - const char *name) | |
647 | +static int o2nm_node_group_make_item(struct config_group *group, | |
648 | + const char *name, | |
649 | + struct config_item **new_item) | |
649 | 650 | { |
650 | 651 | struct o2nm_node *node = NULL; |
651 | - struct config_item *ret = NULL; | |
652 | + int ret = 0; | |
652 | 653 | |
653 | - if (strlen(name) > O2NM_MAX_NAME_LEN) | |
654 | - goto out; /* ENAMETOOLONG */ | |
654 | + if (strlen(name) > O2NM_MAX_NAME_LEN) { | |
655 | + ret = -ENAMETOOLONG; | |
656 | + goto out; | |
657 | + } | |
655 | 658 | |
656 | 659 | node = kzalloc(sizeof(struct o2nm_node), GFP_KERNEL); |
657 | - if (node == NULL) | |
658 | - goto out; /* ENOMEM */ | |
660 | + if (node == NULL) { | |
661 | + ret = -ENOMEM; | |
662 | + goto out; | |
663 | + } | |
659 | 664 | |
660 | 665 | strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ |
661 | 666 | config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); |
662 | 667 | spin_lock_init(&node->nd_lock); |
663 | 668 | |
664 | - ret = &node->nd_item; | |
669 | + *new_item = &node->nd_item; | |
665 | 670 | |
666 | 671 | out: |
667 | - if (ret == NULL) | |
672 | + if (ret) | |
668 | 673 | kfree(node); |
669 | 674 | |
670 | 675 | return ret; |
671 | 676 | |
672 | 677 | |
673 | 678 | |
674 | 679 | |
675 | 680 | |
... | ... | @@ -751,25 +756,31 @@ |
751 | 756 | } |
752 | 757 | #endif |
753 | 758 | |
754 | -static struct config_group *o2nm_cluster_group_make_group(struct config_group *group, | |
755 | - const char *name) | |
759 | +static int o2nm_cluster_group_make_group(struct config_group *group, | |
760 | + const char *name, | |
761 | + struct config_group **new_group) | |
756 | 762 | { |
757 | 763 | struct o2nm_cluster *cluster = NULL; |
758 | 764 | struct o2nm_node_group *ns = NULL; |
759 | - struct config_group *o2hb_group = NULL, *ret = NULL; | |
765 | + struct config_group *o2hb_group = NULL; | |
760 | 766 | void *defs = NULL; |
767 | + int ret = 0; | |
761 | 768 | |
762 | 769 | /* this runs under the parent dir's i_mutex; there can be only |
763 | 770 | * one caller in here at a time */ |
764 | - if (o2nm_single_cluster) | |
765 | - goto out; /* ENOSPC */ | |
771 | + if (o2nm_single_cluster) { | |
772 | + ret = -ENOSPC; | |
773 | + goto out; | |
774 | + } | |
766 | 775 | |
767 | 776 | cluster = kzalloc(sizeof(struct o2nm_cluster), GFP_KERNEL); |
768 | 777 | ns = kzalloc(sizeof(struct o2nm_node_group), GFP_KERNEL); |
769 | 778 | defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL); |
770 | 779 | o2hb_group = o2hb_alloc_hb_set(); |
771 | - if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) | |
780 | + if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL) { | |
781 | + ret = -ENOMEM; | |
772 | 782 | goto out; |
783 | + } | |
773 | 784 | |
774 | 785 | config_group_init_type_name(&cluster->cl_group, name, |
775 | 786 | &o2nm_cluster_type); |
776 | 787 | |
... | ... | @@ -786,11 +797,11 @@ |
786 | 797 | cluster->cl_idle_timeout_ms = O2NET_IDLE_TIMEOUT_MS_DEFAULT; |
787 | 798 | cluster->cl_keepalive_delay_ms = O2NET_KEEPALIVE_DELAY_MS_DEFAULT; |
788 | 799 | |
789 | - ret = &cluster->cl_group; | |
800 | + *new_group = &cluster->cl_group; | |
790 | 801 | o2nm_single_cluster = cluster; |
791 | 802 | |
792 | 803 | out: |
793 | - if (ret == NULL) { | |
804 | + if (ret) { | |
794 | 805 | kfree(cluster); |
795 | 806 | kfree(ns); |
796 | 807 | o2hb_free_hb_set(o2hb_group); |
include/linux/configfs.h
... | ... | @@ -165,8 +165,8 @@ |
165 | 165 | }; |
166 | 166 | |
167 | 167 | struct configfs_group_operations { |
168 | - struct config_item *(*make_item)(struct config_group *group, const char *name); | |
169 | - struct config_group *(*make_group)(struct config_group *group, const char *name); | |
168 | + int (*make_item)(struct config_group *group, const char *name, struct config_item **new_item); | |
169 | + int (*make_group)(struct config_group *group, const char *name, struct config_group **new_group); | |
170 | 170 | int (*commit_item)(struct config_item *item); |
171 | 171 | void (*disconnect_notify)(struct config_group *group, struct config_item *item); |
172 | 172 | void (*drop_item)(struct config_group *group, struct config_item *item); |