static struct config_group *group_children_make_group(struct config_group *group, const char *name) { struct group_node *cfg; PRINTK_INFO("Creating configfs node for %s\n", name); cfg = kzalloc(sizeof(struct group_node), GFP_KERNEL); if (!cfg) { return ERR_PTR(-ENOMEM); } if (strcasecmp(name, GROUP_NAME_CR0) == 0) { config_group_init_type_name(&cfg->group, name, get_cr0_children_type()); } else if (strcasecmp(name, GROUP_NAME_CR4) == 0) { config_group_init_type_name(&cfg->group, name, get_cr4_children_type()); } else if (strcasecmp(name, GROUP_NAME_MSR) == 0) { config_group_init_type_name(&cfg->group, name, get_msr_children_type()); } else if (strcasecmp(name, GROUP_NAME_LOG) == 0) { config_group_init_type_name(&cfg->group, name, get_log_children_type()); } return &cfg->group; }
static struct config_group *target_fabric_make_wwn( struct config_group *group, const char *name) { struct target_fabric_configfs *tf = container_of(group, struct target_fabric_configfs, tf_group); struct se_wwn *wwn; if (!tf->tf_ops.fabric_make_wwn) { pr_err("tf->tf_ops.fabric_make_wwn is NULL\n"); return ERR_PTR(-ENOSYS); } wwn = tf->tf_ops.fabric_make_wwn(tf, group, name); if (!wwn || IS_ERR(wwn)) return ERR_PTR(-EINVAL); wwn->wwn_tf = tf; /* * Setup default groups from pre-allocated wwn->wwn_default_groups */ wwn->wwn_group.default_groups = wwn->wwn_default_groups; wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group; wwn->wwn_group.default_groups[1] = NULL; config_group_init_type_name(&wwn->wwn_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_cit); config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics", &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit); return &wwn->wwn_group; }
static struct config_group *target_fabric_make_lun( struct config_group *group, const char *name) { struct se_lun *lun; struct se_portal_group *se_tpg = container_of(group, struct se_portal_group, tpg_lun_group); struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct config_group *lun_cg = NULL, *port_stat_grp = NULL; unsigned long unpacked_lun; int errno; if (strstr(name, "lun_") != name) { pr_err("Unable to locate \'_\" in" " \"lun_$LUN_NUMBER\"\n"); return ERR_PTR(-EINVAL); } errno = kstrtoul(name + 4, 0, &unpacked_lun); if (errno) return ERR_PTR(errno); if (unpacked_lun > UINT_MAX) return ERR_PTR(-EINVAL); lun = core_get_lun_from_tpg(se_tpg, unpacked_lun); if (!lun) return ERR_PTR(-EINVAL); lun_cg = &lun->lun_group; lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lun_cg->default_groups) { pr_err("Unable to allocate lun_cg->default_groups\n"); return ERR_PTR(-ENOMEM); } config_group_init_type_name(&lun->lun_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); config_group_init_type_name(&lun->port_stat_grps.stat_group, "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit); lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group; lun_cg->default_groups[1] = NULL; port_stat_grp = &lun->port_stat_grps.stat_group; port_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 3, GFP_KERNEL); if (!port_stat_grp->default_groups) { pr_err("Unable to allocate port_stat_grp->default_groups\n"); errno = -ENOMEM; goto out; } target_stat_setup_port_default_groups(lun); return &lun->lun_group; out: if (lun_cg) kfree(lun_cg->default_groups); return ERR_PTR(errno); }
/* * Called from target_core_fabric_configfs.c:target_fabric_make_mappedlun() to setup * the target MappedLUN statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *lacl) { config_group_init_type_name(&lacl->ml_stat_grps.scsi_auth_intr_group, "scsi_auth_intr", &target_stat_scsi_auth_intr_cit); configfs_add_default_group(&lacl->ml_stat_grps.scsi_auth_intr_group, &lacl->ml_stat_grps.stat_group); config_group_init_type_name(&lacl->ml_stat_grps.scsi_att_intr_port_group, "scsi_att_intr_port", &target_stat_scsi_att_intr_port_cit); configfs_add_default_group(&lacl->ml_stat_grps.scsi_att_intr_port_group, &lacl->ml_stat_grps.stat_group); }
/* * Called from target_core_fabric_configfs.c:target_fabric_make_mappedlun() to setup * the target MappedLUN statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *lacl) { struct config_group *ml_stat_grp = &lacl->ml_stat_grps.stat_group; config_group_init_type_name(&lacl->ml_stat_grps.scsi_auth_intr_group, "scsi_auth_intr", &target_stat_scsi_auth_intr_cit); config_group_init_type_name(&lacl->ml_stat_grps.scsi_att_intr_port_group, "scsi_att_intr_port", &target_stat_scsi_att_intr_port_cit); ml_stat_grp->default_groups[0] = &lacl->ml_stat_grps.scsi_auth_intr_group; ml_stat_grp->default_groups[1] = &lacl->ml_stat_grps.scsi_att_intr_port_group; ml_stat_grp->default_groups[2] = NULL; }
int iio_sw_trigger_type_configfs_register(struct iio_sw_trigger_type *tt) { config_group_init_type_name(&tt->group, tt->name, &iio_trigger_type_group_type); return configfs_register_group(&iio_triggers_group, &tt->group); }
/** * dtbocfg_module_init() */ static int __init dtbocfg_module_init(void) { int retval = 0; pr_info("%s\n", __func__); config_group_init(&dtbocfg_root_subsys.su_group); config_group_init_type_name(&dtbocfg_overlay_group, "overlays", &dtbocfg_overlays_type); retval = configfs_register_subsystem(&dtbocfg_root_subsys); if (retval != 0) { pr_err( "%s: couldn't register subsys\n", __func__); goto register_subsystem_failed; } retval = configfs_register_group(&dtbocfg_root_subsys.su_group, &dtbocfg_overlay_group); if (retval != 0) { pr_err( "%s: couldn't register group\n", __func__); goto register_group_failed; } pr_info("%s: OK\n", __func__); return 0; register_group_failed: configfs_unregister_subsystem(&dtbocfg_root_subsys); register_subsystem_failed: return retval; }
/* * Called from target_core_fabric_configfs.c:target_fabric_make_lun() to setup * the target port statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_port_default_groups(struct se_lun *lun) { struct config_group *port_stat_grp = &lun->port_stat_grps.stat_group; config_group_init_type_name(&lun->port_stat_grps.scsi_port_group, "scsi_port", &target_stat_scsi_port_cit); config_group_init_type_name(&lun->port_stat_grps.scsi_tgt_port_group, "scsi_tgt_port", &target_stat_scsi_tgt_port_cit); config_group_init_type_name(&lun->port_stat_grps.scsi_transport_group, "scsi_transport", &target_stat_scsi_transport_cit); port_stat_grp->default_groups[0] = &lun->port_stat_grps.scsi_port_group; port_stat_grp->default_groups[1] = &lun->port_stat_grps.scsi_tgt_port_group; port_stat_grp->default_groups[2] = &lun->port_stat_grps.scsi_transport_group; port_stat_grp->default_groups[3] = NULL; }
static struct config_group *target_fabric_make_lun( struct config_group *group, const char *name) { struct se_lun *lun; struct se_portal_group *se_tpg = container_of(group, struct se_portal_group, tpg_lun_group); struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; unsigned long unpacked_lun; if (strstr(name, "lun_") != name) { printk(KERN_ERR "Unable to locate \'_\" in" " \"lun_$LUN_NUMBER\"\n"); return ERR_PTR(-EINVAL); } if (strict_strtoul(name + 4, 0, &unpacked_lun) || unpacked_lun > UINT_MAX) return ERR_PTR(-EINVAL); lun = core_get_lun_from_tpg(se_tpg, unpacked_lun); if (!(lun)) return ERR_PTR(-EINVAL); config_group_init_type_name(&lun->lun_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_port_cit); return &lun->lun_group; }
/* * Called from target_core_configfs.c:target_core_make_subdev() to setup * the target statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_dev_default_groups(struct se_device *dev) { struct config_group *dev_stat_grp = &dev->dev_stat_grps.stat_group; config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group, "scsi_dev", &target_stat_scsi_dev_cit); config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group, "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit); config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group, "scsi_lu", &target_stat_scsi_lu_cit); dev_stat_grp->default_groups[0] = &dev->dev_stat_grps.scsi_dev_group; dev_stat_grp->default_groups[1] = &dev->dev_stat_grps.scsi_tgt_dev_group; dev_stat_grp->default_groups[2] = &dev->dev_stat_grps.scsi_lu_group; dev_stat_grp->default_groups[3] = NULL; }
/* * Called from target_core_fabric_configfs.c:target_fabric_make_lun() to setup * the target port statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_port_default_groups(struct se_lun *lun) { config_group_init_type_name(&lun->port_stat_grps.scsi_port_group, "scsi_port", &target_stat_scsi_port_cit); configfs_add_default_group(&lun->port_stat_grps.scsi_port_group, &lun->port_stat_grps.stat_group); config_group_init_type_name(&lun->port_stat_grps.scsi_tgt_port_group, "scsi_tgt_port", &target_stat_scsi_tgt_port_cit); configfs_add_default_group(&lun->port_stat_grps.scsi_tgt_port_group, &lun->port_stat_grps.stat_group); config_group_init_type_name(&lun->port_stat_grps.scsi_transport_group, "scsi_transport", &target_stat_scsi_transport_cit); configfs_add_default_group(&lun->port_stat_grps.scsi_transport_group, &lun->port_stat_grps.stat_group); }
/* * Called from target_core_configfs.c:target_core_make_subdev() to setup * the target statistics groups + configfs CITs located in target_core_stat.c */ void target_stat_setup_dev_default_groups(struct se_device *dev) { config_group_init_type_name(&dev->dev_stat_grps.scsi_dev_group, "scsi_dev", &target_stat_scsi_dev_cit); configfs_add_default_group(&dev->dev_stat_grps.scsi_dev_group, &dev->dev_stat_grps.stat_group); config_group_init_type_name(&dev->dev_stat_grps.scsi_tgt_dev_group, "scsi_tgt_dev", &target_stat_scsi_tgt_dev_cit); configfs_add_default_group(&dev->dev_stat_grps.scsi_tgt_dev_group, &dev->dev_stat_grps.stat_group); config_group_init_type_name(&dev->dev_stat_grps.scsi_lu_group, "scsi_lu", &target_stat_scsi_lu_cit); configfs_add_default_group(&dev->dev_stat_grps.scsi_lu_group, &dev->dev_stat_grps.stat_group); }
static struct config_group *target_fabric_make_mappedlun( struct config_group *group, const char *name) { struct se_node_acl *se_nacl = container_of(group, struct se_node_acl, acl_group); struct se_portal_group *se_tpg = se_nacl->se_tpg; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct se_lun_acl *lacl; struct config_item *acl_ci; char *buf; unsigned long mapped_lun; int ret = 0; acl_ci = &group->cg_item; if (!(acl_ci)) { printk(KERN_ERR "Unable to locatel acl_ci\n"); return NULL; } buf = kzalloc(strlen(name) + 1, GFP_KERNEL); if (!(buf)) { printk(KERN_ERR "Unable to allocate memory for name buf\n"); return ERR_PTR(-ENOMEM); } snprintf(buf, strlen(name) + 1, "%s", name); /* * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID. */ if (strstr(buf, "lun_") != buf) { printk(KERN_ERR "Unable to locate \"lun_\" from buf: %s" " name: %s\n", buf, name); ret = -EINVAL; goto out; } /* * Determine the Mapped LUN value. This is what the SCSI Initiator * Port will actually see. */ if (strict_strtoul(buf + 4, 0, &mapped_lun) || mapped_lun > UINT_MAX) { ret = -EINVAL; goto out; } lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, config_item_name(acl_ci), &ret); if (!(lacl)) goto out; config_group_init_type_name(&lacl->se_lun_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); kfree(buf); return &lacl->se_lun_group; out: kfree(buf); return ERR_PTR(ret); }
static struct config_group *target_fabric_make_nodeacl( struct config_group *group, const char *name) { struct se_portal_group *se_tpg = container_of(group, struct se_portal_group, tpg_acl_group); struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct se_node_acl *se_nacl; struct config_group *nacl_cg; if (!tf->tf_ops.fabric_make_nodeacl) { pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n"); return ERR_PTR(-ENOSYS); } se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name); if (IS_ERR(se_nacl)) return ERR_CAST(se_nacl); nacl_cg = &se_nacl->acl_group; nacl_cg->default_groups = se_nacl->acl_default_groups; nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; nacl_cg->default_groups[1] = &se_nacl->acl_auth_group; nacl_cg->default_groups[2] = &se_nacl->acl_param_group; nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group; nacl_cg->default_groups[4] = NULL; config_group_init_type_name(&se_nacl->acl_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit); config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib", &TF_CIT_TMPL(tf)->tfc_tpg_nacl_attrib_cit); config_group_init_type_name(&se_nacl->acl_auth_group, "auth", &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit); config_group_init_type_name(&se_nacl->acl_param_group, "param", &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit); config_group_init_type_name(&se_nacl->acl_fabric_stat_group, "fabric_statistics", &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit); return &se_nacl->acl_group; }
static struct config_group *device_make_group(struct config_group *group, const char *name) { struct iio_dummy_instance *dummy = kzalloc(sizeof(struct iio_dummy_instance), GFP_KERNEL); config_item_set_name(&dummy->group.cg_item, name); config_group_init_type_name(&dummy->group, name, &iio_dummy_type); iio_dummy_probe(name); printk(KERN_ALERT "device make group called with name %s\n", name); return &dummy->group; }
static struct usb_function_instance *acm_alloc_instance(void) { struct f_serial_opts *opts; int ret; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = acm_free_instance; ret = gserial_alloc_line(&opts->port_num); if (ret) { kfree(opts); return ERR_PTR(ret); } config_group_init_type_name(&opts->func_inst.group, "", &acm_func_type); return &opts->func_inst; }
static struct config_group *target_fabric_make_tpg( struct config_group *group, const char *name) { struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group); struct target_fabric_configfs *tf = wwn->wwn_tf; struct se_portal_group *se_tpg; if (!tf->tf_ops.fabric_make_tpg) { pr_err("tf->tf_ops.fabric_make_tpg is NULL\n"); return ERR_PTR(-ENOSYS); } se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name); if (!se_tpg || IS_ERR(se_tpg)) return ERR_PTR(-EINVAL); /* * Setup default groups from pre-allocated se_tpg->tpg_default_groups */ se_tpg->tpg_group.default_groups = se_tpg->tpg_default_groups; se_tpg->tpg_group.default_groups[0] = &se_tpg->tpg_lun_group; se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group; se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group; se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group; se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_auth_group; se_tpg->tpg_group.default_groups[5] = &se_tpg->tpg_param_group; se_tpg->tpg_group.default_groups[6] = NULL; config_group_init_type_name(&se_tpg->tpg_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_base_cit); config_group_init_type_name(&se_tpg->tpg_lun_group, "lun", &TF_CIT_TMPL(tf)->tfc_tpg_lun_cit); config_group_init_type_name(&se_tpg->tpg_np_group, "np", &TF_CIT_TMPL(tf)->tfc_tpg_np_cit); config_group_init_type_name(&se_tpg->tpg_acl_group, "acls", &TF_CIT_TMPL(tf)->tfc_tpg_nacl_cit); config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib", &TF_CIT_TMPL(tf)->tfc_tpg_attrib_cit); config_group_init_type_name(&se_tpg->tpg_auth_group, "auth", &TF_CIT_TMPL(tf)->tfc_tpg_auth_cit); config_group_init_type_name(&se_tpg->tpg_param_group, "param", &TF_CIT_TMPL(tf)->tfc_tpg_param_cit); return &se_tpg->tpg_group; }
static struct config_group *target_fabric_make_wwn( struct config_group *group, const char *name) { struct target_fabric_configfs *tf = container_of(group, struct target_fabric_configfs, tf_group); struct se_wwn *wwn; if (!(tf->tf_ops.fabric_make_wwn)) { printk(KERN_ERR "tf->tf_ops.fabric_make_wwn is NULL\n"); return ERR_PTR(-ENOSYS); } wwn = tf->tf_ops.fabric_make_wwn(tf, group, name); if (!(wwn) || IS_ERR(wwn)) return ERR_PTR(-EINVAL); wwn->wwn_tf = tf; config_group_init_type_name(&wwn->wwn_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_cit); return &wwn->wwn_group; }
static struct usb_function_instance *gser_alloc_inst(void) { struct f_serial_opts *opts; int ret; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = gser_free_inst; /* Check if tty registration is handled here or not */ if (!nr_ports) { ret = gserial_alloc_line(&opts->port_num); if (ret) { kfree(opts); return ERR_PTR(ret); } } config_group_init_type_name(&opts->func_inst.group, "", &serial_func_type); return &opts->func_inst; }
static struct config_group *target_fabric_make_np( struct config_group *group, const char *name) { struct se_portal_group *se_tpg = container_of(group, struct se_portal_group, tpg_np_group); struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct se_tpg_np *se_tpg_np; if (!tf->tf_ops.fabric_make_np) { pr_err("tf->tf_ops.fabric_make_np is NULL\n"); return ERR_PTR(-ENOSYS); } se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name); if (!se_tpg_np || IS_ERR(se_tpg_np)) return ERR_PTR(-EINVAL); se_tpg_np->tpg_np_parent = se_tpg; config_group_init_type_name(&se_tpg_np->tpg_np_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_np_base_cit); return &se_tpg_np->tpg_np_group; }
int iio_device_type_configfs_register(struct config_group *dummy, const char *name) { config_group_init_type_name(dummy, name, &iio_device_type_group_type); return configfs_register_group(&iio_devices_group, dummy); }
static struct config_group *target_fabric_make_mappedlun( struct config_group *group, const char *name) { struct se_node_acl *se_nacl = container_of(group, struct se_node_acl, acl_group); struct se_portal_group *se_tpg = se_nacl->se_tpg; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct se_lun_acl *lacl; struct config_item *acl_ci; struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; char *buf; unsigned long mapped_lun; int ret = 0; acl_ci = &group->cg_item; if (!acl_ci) { pr_err("Unable to locatel acl_ci\n"); return NULL; } buf = kzalloc(strlen(name) + 1, GFP_KERNEL); if (!buf) { pr_err("Unable to allocate memory for name buf\n"); return ERR_PTR(-ENOMEM); } snprintf(buf, strlen(name) + 1, "%s", name); /* * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID. */ if (strstr(buf, "lun_") != buf) { pr_err("Unable to locate \"lun_\" from buf: %s" " name: %s\n", buf, name); ret = -EINVAL; goto out; } /* * Determine the Mapped LUN value. This is what the SCSI Initiator * Port will actually see. */ ret = kstrtoul(buf + 4, 0, &mapped_lun); if (ret) goto out; if (mapped_lun > UINT_MAX) { ret = -EINVAL; goto out; } if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG" "-1: %u for Target Portal Group: %u\n", mapped_lun, TRANSPORT_MAX_LUNS_PER_TPG-1, se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); ret = -EINVAL; goto out; } lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, mapped_lun, &ret); if (!lacl) { ret = -EINVAL; goto out; } lacl_cg = &lacl->se_lun_group; lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); if (!lacl_cg->default_groups) { pr_err("Unable to allocate lacl_cg->default_groups\n"); ret = -ENOMEM; goto out; } config_group_init_type_name(&lacl->se_lun_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit); config_group_init_type_name(&lacl->ml_stat_grps.stat_group, "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit); lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group; lacl_cg->default_groups[1] = NULL; ml_stat_grp = &lacl->ml_stat_grps.stat_group; ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3, GFP_KERNEL); if (!ml_stat_grp->default_groups) { pr_err("Unable to allocate ml_stat_grp->default_groups\n"); ret = -ENOMEM; goto out; } target_stat_setup_mappedlun_default_groups(lacl); kfree(buf); return &lacl->se_lun_group; out: if (lacl_cg) kfree(lacl_cg->default_groups); kfree(buf); return ERR_PTR(ret); }