diff options
Diffstat (limited to 'drivers/target/target_core_configfs.c')
-rw-r--r-- | drivers/target/target_core_configfs.c | 117 |
1 files changed, 102 insertions, 15 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index caf8dc18ee0a..a5f44a6e6e1d 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -3,8 +3,8 @@ | |||
3 | * | 3 | * |
4 | * This file contains ConfigFS logic for the Generic Target Engine project. | 4 | * This file contains ConfigFS logic for the Generic Target Engine project. |
5 | * | 5 | * |
6 | * Copyright (c) 2008-2010 Rising Tide Systems | 6 | * Copyright (c) 2008-2011 Rising Tide Systems |
7 | * Copyright (c) 2008-2010 Linux-iSCSI.org | 7 | * Copyright (c) 2008-2011 Linux-iSCSI.org |
8 | * | 8 | * |
9 | * Nicholas A. Bellinger <nab@kernel.org> | 9 | * Nicholas A. Bellinger <nab@kernel.org> |
10 | * | 10 | * |
@@ -50,6 +50,7 @@ | |||
50 | #include "target_core_hba.h" | 50 | #include "target_core_hba.h" |
51 | #include "target_core_pr.h" | 51 | #include "target_core_pr.h" |
52 | #include "target_core_rd.h" | 52 | #include "target_core_rd.h" |
53 | #include "target_core_stat.h" | ||
53 | 54 | ||
54 | static struct list_head g_tf_list; | 55 | static struct list_head g_tf_list; |
55 | static struct mutex g_tf_lock; | 56 | static struct mutex g_tf_lock; |
@@ -1451,8 +1452,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1451 | size_t count) | 1452 | size_t count) |
1452 | { | 1453 | { |
1453 | struct se_device *dev; | 1454 | struct se_device *dev; |
1454 | unsigned char *i_fabric, *t_fabric, *i_port = NULL, *t_port = NULL; | 1455 | unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; |
1455 | unsigned char *isid = NULL; | 1456 | unsigned char *t_fabric = NULL, *t_port = NULL; |
1456 | char *orig, *ptr, *arg_p, *opts; | 1457 | char *orig, *ptr, *arg_p, *opts; |
1457 | substring_t args[MAX_OPT_ARGS]; | 1458 | substring_t args[MAX_OPT_ARGS]; |
1458 | unsigned long long tmp_ll; | 1459 | unsigned long long tmp_ll; |
@@ -1488,9 +1489,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1488 | switch (token) { | 1489 | switch (token) { |
1489 | case Opt_initiator_fabric: | 1490 | case Opt_initiator_fabric: |
1490 | i_fabric = match_strdup(&args[0]); | 1491 | i_fabric = match_strdup(&args[0]); |
1492 | if (!i_fabric) { | ||
1493 | ret = -ENOMEM; | ||
1494 | goto out; | ||
1495 | } | ||
1491 | break; | 1496 | break; |
1492 | case Opt_initiator_node: | 1497 | case Opt_initiator_node: |
1493 | i_port = match_strdup(&args[0]); | 1498 | i_port = match_strdup(&args[0]); |
1499 | if (!i_port) { | ||
1500 | ret = -ENOMEM; | ||
1501 | goto out; | ||
1502 | } | ||
1494 | if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { | 1503 | if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { |
1495 | printk(KERN_ERR "APTPL metadata initiator_node=" | 1504 | printk(KERN_ERR "APTPL metadata initiator_node=" |
1496 | " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", | 1505 | " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", |
@@ -1501,6 +1510,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1501 | break; | 1510 | break; |
1502 | case Opt_initiator_sid: | 1511 | case Opt_initiator_sid: |
1503 | isid = match_strdup(&args[0]); | 1512 | isid = match_strdup(&args[0]); |
1513 | if (!isid) { | ||
1514 | ret = -ENOMEM; | ||
1515 | goto out; | ||
1516 | } | ||
1504 | if (strlen(isid) > PR_REG_ISID_LEN) { | 1517 | if (strlen(isid) > PR_REG_ISID_LEN) { |
1505 | printk(KERN_ERR "APTPL metadata initiator_isid" | 1518 | printk(KERN_ERR "APTPL metadata initiator_isid" |
1506 | "= exceeds PR_REG_ISID_LEN: %d\n", | 1519 | "= exceeds PR_REG_ISID_LEN: %d\n", |
@@ -1511,6 +1524,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1511 | break; | 1524 | break; |
1512 | case Opt_sa_res_key: | 1525 | case Opt_sa_res_key: |
1513 | arg_p = match_strdup(&args[0]); | 1526 | arg_p = match_strdup(&args[0]); |
1527 | if (!arg_p) { | ||
1528 | ret = -ENOMEM; | ||
1529 | goto out; | ||
1530 | } | ||
1514 | ret = strict_strtoull(arg_p, 0, &tmp_ll); | 1531 | ret = strict_strtoull(arg_p, 0, &tmp_ll); |
1515 | if (ret < 0) { | 1532 | if (ret < 0) { |
1516 | printk(KERN_ERR "strict_strtoull() failed for" | 1533 | printk(KERN_ERR "strict_strtoull() failed for" |
@@ -1547,9 +1564,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1547 | */ | 1564 | */ |
1548 | case Opt_target_fabric: | 1565 | case Opt_target_fabric: |
1549 | t_fabric = match_strdup(&args[0]); | 1566 | t_fabric = match_strdup(&args[0]); |
1567 | if (!t_fabric) { | ||
1568 | ret = -ENOMEM; | ||
1569 | goto out; | ||
1570 | } | ||
1550 | break; | 1571 | break; |
1551 | case Opt_target_node: | 1572 | case Opt_target_node: |
1552 | t_port = match_strdup(&args[0]); | 1573 | t_port = match_strdup(&args[0]); |
1574 | if (!t_port) { | ||
1575 | ret = -ENOMEM; | ||
1576 | goto out; | ||
1577 | } | ||
1553 | if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { | 1578 | if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { |
1554 | printk(KERN_ERR "APTPL metadata target_node=" | 1579 | printk(KERN_ERR "APTPL metadata target_node=" |
1555 | " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", | 1580 | " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", |
@@ -1592,6 +1617,11 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1592 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, | 1617 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, |
1593 | res_holder, all_tg_pt, type); | 1618 | res_holder, all_tg_pt, type); |
1594 | out: | 1619 | out: |
1620 | kfree(i_fabric); | ||
1621 | kfree(i_port); | ||
1622 | kfree(isid); | ||
1623 | kfree(t_fabric); | ||
1624 | kfree(t_port); | ||
1595 | kfree(orig); | 1625 | kfree(orig); |
1596 | return (ret == 0) ? count : ret; | 1626 | return (ret == 0) ? count : ret; |
1597 | } | 1627 | } |
@@ -1798,7 +1828,9 @@ static ssize_t target_core_store_dev_enable( | |||
1798 | return -EINVAL; | 1828 | return -EINVAL; |
1799 | 1829 | ||
1800 | dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); | 1830 | dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); |
1801 | if (!(dev) || IS_ERR(dev)) | 1831 | if (IS_ERR(dev)) |
1832 | return PTR_ERR(dev); | ||
1833 | else if (!dev) | ||
1802 | return -EINVAL; | 1834 | return -EINVAL; |
1803 | 1835 | ||
1804 | se_dev->se_dev_ptr = dev; | 1836 | se_dev->se_dev_ptr = dev; |
@@ -2678,6 +2710,34 @@ static struct config_item_type target_core_alua_cit = { | |||
2678 | 2710 | ||
2679 | /* End functions for struct config_item_type target_core_alua_cit */ | 2711 | /* End functions for struct config_item_type target_core_alua_cit */ |
2680 | 2712 | ||
2713 | /* Start functions for struct config_item_type target_core_stat_cit */ | ||
2714 | |||
2715 | static struct config_group *target_core_stat_mkdir( | ||
2716 | struct config_group *group, | ||
2717 | const char *name) | ||
2718 | { | ||
2719 | return ERR_PTR(-ENOSYS); | ||
2720 | } | ||
2721 | |||
2722 | static void target_core_stat_rmdir( | ||
2723 | struct config_group *group, | ||
2724 | struct config_item *item) | ||
2725 | { | ||
2726 | return; | ||
2727 | } | ||
2728 | |||
2729 | static struct configfs_group_operations target_core_stat_group_ops = { | ||
2730 | .make_group = &target_core_stat_mkdir, | ||
2731 | .drop_item = &target_core_stat_rmdir, | ||
2732 | }; | ||
2733 | |||
2734 | static struct config_item_type target_core_stat_cit = { | ||
2735 | .ct_group_ops = &target_core_stat_group_ops, | ||
2736 | .ct_owner = THIS_MODULE, | ||
2737 | }; | ||
2738 | |||
2739 | /* End functions for struct config_item_type target_core_stat_cit */ | ||
2740 | |||
2681 | /* Start functions for struct config_item_type target_core_hba_cit */ | 2741 | /* Start functions for struct config_item_type target_core_hba_cit */ |
2682 | 2742 | ||
2683 | static struct config_group *target_core_make_subdev( | 2743 | static struct config_group *target_core_make_subdev( |
@@ -2690,10 +2750,12 @@ static struct config_group *target_core_make_subdev( | |||
2690 | struct config_item *hba_ci = &group->cg_item; | 2750 | struct config_item *hba_ci = &group->cg_item; |
2691 | struct se_hba *hba = item_to_hba(hba_ci); | 2751 | struct se_hba *hba = item_to_hba(hba_ci); |
2692 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; | 2752 | struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; |
2753 | struct config_group *dev_stat_grp = NULL; | ||
2754 | int errno = -ENOMEM, ret; | ||
2693 | 2755 | ||
2694 | if (mutex_lock_interruptible(&hba->hba_access_mutex)) | 2756 | ret = mutex_lock_interruptible(&hba->hba_access_mutex); |
2695 | return NULL; | 2757 | if (ret) |
2696 | 2758 | return ERR_PTR(ret); | |
2697 | /* | 2759 | /* |
2698 | * Locate the struct se_subsystem_api from parent's struct se_hba. | 2760 | * Locate the struct se_subsystem_api from parent's struct se_hba. |
2699 | */ | 2761 | */ |
@@ -2723,7 +2785,7 @@ static struct config_group *target_core_make_subdev( | |||
2723 | se_dev->se_dev_hba = hba; | 2785 | se_dev->se_dev_hba = hba; |
2724 | dev_cg = &se_dev->se_dev_group; | 2786 | dev_cg = &se_dev->se_dev_group; |
2725 | 2787 | ||
2726 | dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 6, | 2788 | dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, |
2727 | GFP_KERNEL); | 2789 | GFP_KERNEL); |
2728 | if (!(dev_cg->default_groups)) | 2790 | if (!(dev_cg->default_groups)) |
2729 | goto out; | 2791 | goto out; |
@@ -2755,13 +2817,17 @@ static struct config_group *target_core_make_subdev( | |||
2755 | &target_core_dev_wwn_cit); | 2817 | &target_core_dev_wwn_cit); |
2756 | config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, | 2818 | config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, |
2757 | "alua", &target_core_alua_tg_pt_gps_cit); | 2819 | "alua", &target_core_alua_tg_pt_gps_cit); |
2820 | config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, | ||
2821 | "statistics", &target_core_stat_cit); | ||
2822 | |||
2758 | dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; | 2823 | dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; |
2759 | dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; | 2824 | dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; |
2760 | dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; | 2825 | dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; |
2761 | dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; | 2826 | dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; |
2762 | dev_cg->default_groups[4] = NULL; | 2827 | dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; |
2828 | dev_cg->default_groups[5] = NULL; | ||
2763 | /* | 2829 | /* |
2764 | * Add core/$HBA/$DEV/alua/tg_pt_gps/default_tg_pt_gp | 2830 | * Add core/$HBA/$DEV/alua/default_tg_pt_gp |
2765 | */ | 2831 | */ |
2766 | tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); | 2832 | tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); |
2767 | if (!(tg_pt_gp)) | 2833 | if (!(tg_pt_gp)) |
@@ -2781,6 +2847,17 @@ static struct config_group *target_core_make_subdev( | |||
2781 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; | 2847 | tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; |
2782 | tg_pt_gp_cg->default_groups[1] = NULL; | 2848 | tg_pt_gp_cg->default_groups[1] = NULL; |
2783 | T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; | 2849 | T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; |
2850 | /* | ||
2851 | * Add core/$HBA/$DEV/statistics/ default groups | ||
2852 | */ | ||
2853 | dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; | ||
2854 | dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, | ||
2855 | GFP_KERNEL); | ||
2856 | if (!dev_stat_grp->default_groups) { | ||
2857 | printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n"); | ||
2858 | goto out; | ||
2859 | } | ||
2860 | target_stat_setup_dev_default_groups(se_dev); | ||
2784 | 2861 | ||
2785 | printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" | 2862 | printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" |
2786 | " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); | 2863 | " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); |
@@ -2792,6 +2869,8 @@ out: | |||
2792 | core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); | 2869 | core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); |
2793 | T10_ALUA(se_dev)->default_tg_pt_gp = NULL; | 2870 | T10_ALUA(se_dev)->default_tg_pt_gp = NULL; |
2794 | } | 2871 | } |
2872 | if (dev_stat_grp) | ||
2873 | kfree(dev_stat_grp->default_groups); | ||
2795 | if (tg_pt_gp_cg) | 2874 | if (tg_pt_gp_cg) |
2796 | kfree(tg_pt_gp_cg->default_groups); | 2875 | kfree(tg_pt_gp_cg->default_groups); |
2797 | if (dev_cg) | 2876 | if (dev_cg) |
@@ -2801,7 +2880,7 @@ out: | |||
2801 | kfree(se_dev); | 2880 | kfree(se_dev); |
2802 | unlock: | 2881 | unlock: |
2803 | mutex_unlock(&hba->hba_access_mutex); | 2882 | mutex_unlock(&hba->hba_access_mutex); |
2804 | return NULL; | 2883 | return ERR_PTR(errno); |
2805 | } | 2884 | } |
2806 | 2885 | ||
2807 | static void target_core_drop_subdev( | 2886 | static void target_core_drop_subdev( |
@@ -2813,7 +2892,7 @@ static void target_core_drop_subdev( | |||
2813 | struct se_hba *hba; | 2892 | struct se_hba *hba; |
2814 | struct se_subsystem_api *t; | 2893 | struct se_subsystem_api *t; |
2815 | struct config_item *df_item; | 2894 | struct config_item *df_item; |
2816 | struct config_group *dev_cg, *tg_pt_gp_cg; | 2895 | struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; |
2817 | int i; | 2896 | int i; |
2818 | 2897 | ||
2819 | hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); | 2898 | hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); |
@@ -2825,6 +2904,14 @@ static void target_core_drop_subdev( | |||
2825 | list_del(&se_dev->g_se_dev_list); | 2904 | list_del(&se_dev->g_se_dev_list); |
2826 | spin_unlock(&se_global->g_device_lock); | 2905 | spin_unlock(&se_global->g_device_lock); |
2827 | 2906 | ||
2907 | dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; | ||
2908 | for (i = 0; dev_stat_grp->default_groups[i]; i++) { | ||
2909 | df_item = &dev_stat_grp->default_groups[i]->cg_item; | ||
2910 | dev_stat_grp->default_groups[i] = NULL; | ||
2911 | config_item_put(df_item); | ||
2912 | } | ||
2913 | kfree(dev_stat_grp->default_groups); | ||
2914 | |||
2828 | tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; | 2915 | tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; |
2829 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { | 2916 | for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { |
2830 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; | 2917 | df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; |
@@ -3044,7 +3131,7 @@ static struct config_item_type target_core_cit = { | |||
3044 | 3131 | ||
3045 | /* Stop functions for struct config_item_type target_core_hba_cit */ | 3132 | /* Stop functions for struct config_item_type target_core_hba_cit */ |
3046 | 3133 | ||
3047 | static int target_core_init_configfs(void) | 3134 | static int __init target_core_init_configfs(void) |
3048 | { | 3135 | { |
3049 | struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL; | 3136 | struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL; |
3050 | struct config_group *lu_gp_cg = NULL; | 3137 | struct config_group *lu_gp_cg = NULL; |
@@ -3176,7 +3263,7 @@ out_global: | |||
3176 | return -1; | 3263 | return -1; |
3177 | } | 3264 | } |
3178 | 3265 | ||
3179 | static void target_core_exit_configfs(void) | 3266 | static void __exit target_core_exit_configfs(void) |
3180 | { | 3267 | { |
3181 | struct configfs_subsystem *subsys; | 3268 | struct configfs_subsystem *subsys; |
3182 | struct config_group *hba_cg, *alua_cg, *lu_gp_cg; | 3269 | struct config_group *hba_cg, *alua_cg, *lu_gp_cg; |