On 11/09/2012 05:35 AM, [email protected] wrote:
> +/* Target attributes */
> +
> +iscsi_flash_tgt_rw_attr(ip, ipaddress, ISCSI_FLASH_TGT_IP_ADDR);
> +iscsi_flash_tgt_rw_attr(port, port, ISCSI_FLASH_TGT_PORT);
> +iscsi_flash_tgt_rw_attr(opt_auto_send_tgt_disable, opt_auto_send_tgt_disable,
> +                     ISCSI_FLASH_TGT_OPT_AUTO_SND_TGT_DISABLE);
> +iscsi_flash_tgt_rw_attr(opt_discovery_sess, opt_discovery_session,
> +                     ISCSI_FLASH_TGT_OPT_DISCOVERY_SESS);
> +iscsi_flash_tgt_rw_attr(opt_entry_enable, opt_entry_enable,
> +                     ISCSI_FLASH_TGT_OPT_ENTRY_ENABLE);
> +iscsi_flash_tgt_rw_attr(iscsiopt_enable_hdr_digest,
> +                     iscsiopt_enable_hdr_digest,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_HDR_DIGEST);
> +iscsi_flash_tgt_rw_attr(iscsiopt_enable_data_digest,
> +                     iscsiopt_enable_data_digest,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_DATA_DIGEST);
> +iscsi_flash_tgt_rw_attr(iscsiopt_enable_immediate_data,
> +                     iscsiopt_enable_immediate_data,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_IMMEDIATE_DATA);
> +iscsi_flash_tgt_rw_attr(iscsiopt_enable_initial_r2t,
> +                     iscsiopt_enable_initial_r2t,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_INITIAL_R2T);
> +iscsi_flash_tgt_rw_attr(iscsiopt_data_seq_in_order, 
> iscsiopt_data_seq_in_order,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_DATA_SEQ_IN_ORDER);
> +iscsi_flash_tgt_rw_attr(iscsiopt_data_pdu_in_order, 
> iscsiopt_data_pdu_in_order,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_DATA_PDU_IN_ORDER);
> +iscsi_flash_tgt_rw_attr(iscsiopt_chap_auth_enable, iscsiopt_chap_auth_enable,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_CHAP_AUTH_ENABLE);
> +iscsi_flash_tgt_rw_attr(iscsiopt_snack_req_enable, iscsiopt_snack_req_enable,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_SNACK_REQ_ENABLE);
> +iscsi_flash_tgt_rw_attr(iscsiopt_discovery_logout_enable,
> +                     iscsiopt_discovery_logout_enable,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_LOGOUT_ENABLE);
> +iscsi_flash_tgt_rw_attr(iscsiopt_bi_chap_challenge_enable,
> +                     iscsiopt_bi_chap_challenge_enable,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_BI_CHAP_CHALLENGE_ENABLE);
> +iscsi_flash_tgt_rw_attr(iscsiopt_discovery_auth_opt,
> +                     iscsiopt_discovery_auth_opt,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_AUTH_OPT);



What are the options for this?



> +iscsi_flash_tgt_rw_attr(tcpopt_nagle_disable, tcpopt_nagle_disable,
> +                     ISCSI_FLASH_TGT_TCPOPT_NAGLE_DISABLE);
> +iscsi_flash_tgt_rw_attr(tcpopt_timer_scale, tcpopt_timer_scale,
> +                     ISCSI_FLASH_TGT_TCPOPT_TIMER_SCALE);
> +iscsi_flash_tgt_rw_attr(tcpopt_timestamp_enable, tcpopt_timestamp_enable,
> +                     ISCSI_FLASH_TGT_TCPOPT_TIMESTAMP_ENABLE);
> +iscsi_flash_tgt_rw_attr(ipopt_frag_disable, ipopt_frag_disable,
> +                     ISCSI_FLASH_TGT_IPOPT_FRAG_DISABLE);
> +iscsi_flash_tgt_rw_attr(max_recv_ds_len, max_recv_data_segment_length,
> +                     ISCSI_FLASH_TGT_MAX_RECV_DS_LEN);
> +iscsi_flash_tgt_rw_attr(max_xmit_ds_len, max_xmit_data_segment_length,
> +                     ISCSI_FLASH_TGT_MAX_XMIT_DS_LEN);
> +iscsi_flash_tgt_rw_attr(first_burst_len, first_burst_length,
> +                     ISCSI_FLASH_TGT_FIRST_BURST_LEN);
> +iscsi_flash_tgt_rw_attr(def_time2wait, default_time2wait,
> +                     ISCSI_FLASH_TGT_DEF_TIME2WAIT);
> +iscsi_flash_tgt_rw_attr(def_time2retain, default_time2retain,
> +                     ISCSI_FLASH_TGT_DEF_TIME2RETAIN);
> +iscsi_flash_tgt_rw_attr(max_outstanding_r2t, max_outstanding_r2t,
> +                     ISCSI_FLASH_TGT_MAX_OUTSTANDING_R2T);
> +iscsi_flash_tgt_rw_attr(noop_out_interval, noop_out_interval,
> +                     ISCSI_FLASH_TGT_NOOP_OUT_INTERVAL);
> +iscsi_flash_tgt_rw_attr(isid, isid, ISCSI_FLASH_TGT_ISID);
> +iscsi_flash_tgt_rw_attr(tsid, tsid, ISCSI_FLASH_TGT_TSID);
> +iscsi_flash_tgt_rw_attr(max_burst_len, max_burst_length,
> +                     ISCSI_FLASH_TGT_MAX_BURST_LEN);
> +iscsi_flash_tgt_rw_attr(fw_cmd_timeout, firmware_cmd_timeout,
> +                     ISCSI_FLASH_TGT_FW_CMD_TIMEOUT);
> +iscsi_flash_tgt_rw_attr(iscsi_alias, iscsi_alias,
> +                     ISCSI_FLASH_TGT_ISCSI_ALIAS);
> +iscsi_flash_tgt_rw_attr(address, target_address, ISCSI_FLASH_TGT_ADDRESS);
> +iscsi_flash_tgt_rw_attr(name, name, ISCSI_FLASH_TGT_NAME);
> +iscsi_flash_tgt_rw_attr(tpgt, tpgt, ISCSI_FLASH_TGT_TPGT);
> +iscsi_flash_tgt_rw_attr(chap_tbl_idx, chap_tbl_idx,
> +                     ISCSI_FLASH_TGT_CHAP_TBL_IDX);


I am not sure how this will work for other drivers. I am also not
entirely sure how it is supposed to work for your driver. Would the app
do a ISCSI_UEVENT_GET_CHAP NL event, then use those values to set here?


For qla4xxx can you have 2 table entries with the same values? If not,
then can we just have the interface expose strings like user, password,
username_in, and password_in? For qla4xxx you could then match those
values with a matching table entry and convert to a index. The other
drivers would just use the strings.


Also for CHAP, should any user be able to see the chap values or should
only root?



> +iscsi_flash_tgt_rw_attr(is_persistent, is_persistent,
> +                     ISCSI_FLASH_TGT_IS_PERSISTENT);
> +iscsi_flash_tgt_rw_attr(is_dirty, is_dirty, ISCSI_FLASH_TGT_IS_DIRTY);


What does this do?


> +iscsi_flash_tgt_rw_attr(login, login, ISCSI_FLASH_TGT_LOGIN);
> +iscsi_flash_tgt_rw_attr(logout, logout, ISCSI_FLASH_TGT_LOGOUT);
> +iscsi_flash_tgt_rw_attr(apply, apply, ISCSI_FLASH_TGT_APPLY);
> +
> +
> +static struct attribute *target_attrs[] = {
> +     &iscsi_flash_tgt_ip.attr,
> +     &iscsi_flash_tgt_port.attr,
> +     &iscsi_flash_tgt_name.attr,
> +     &iscsi_flash_tgt_opt_auto_send_tgt_disable.attr,
> +     &iscsi_flash_tgt_opt_discovery_sess.attr,
> +     &iscsi_flash_tgt_opt_entry_enable.attr,
> +     &iscsi_flash_tgt_iscsiopt_enable_hdr_digest.attr,
> +     &iscsi_flash_tgt_iscsiopt_enable_data_digest.attr,
> +     &iscsi_flash_tgt_iscsiopt_enable_immediate_data.attr,
> +     &iscsi_flash_tgt_iscsiopt_enable_initial_r2t.attr,
> +     &iscsi_flash_tgt_iscsiopt_data_seq_in_order.attr,
> +     &iscsi_flash_tgt_iscsiopt_data_pdu_in_order.attr,
> +     &iscsi_flash_tgt_iscsiopt_chap_auth_enable.attr,
> +     &iscsi_flash_tgt_iscsiopt_snack_req_enable.attr,
> +     &iscsi_flash_tgt_iscsiopt_discovery_logout_enable.attr,
> +     &iscsi_flash_tgt_iscsiopt_bi_chap_challenge_enable.attr,
> +     &iscsi_flash_tgt_iscsiopt_discovery_auth_opt.attr,
> +     &iscsi_flash_tgt_tcpopt_nagle_disable.attr,
> +     &iscsi_flash_tgt_tcpopt_timer_scale.attr,
> +     &iscsi_flash_tgt_tcpopt_timestamp_enable.attr,
> +     &iscsi_flash_tgt_ipopt_frag_disable.attr,
> +     &iscsi_flash_tgt_max_recv_ds_len.attr,
> +     &iscsi_flash_tgt_max_xmit_ds_len.attr,
> +     &iscsi_flash_tgt_first_burst_len.attr,
> +     &iscsi_flash_tgt_def_time2wait.attr,
> +     &iscsi_flash_tgt_def_time2retain.attr,
> +     &iscsi_flash_tgt_max_outstanding_r2t.attr,
> +     &iscsi_flash_tgt_noop_out_interval.attr,
> +     &iscsi_flash_tgt_isid.attr,
> +     &iscsi_flash_tgt_tsid.attr,
> +     &iscsi_flash_tgt_max_burst_len.attr,
> +     &iscsi_flash_tgt_fw_cmd_timeout.attr,
> +     &iscsi_flash_tgt_iscsi_alias.attr,
> +     &iscsi_flash_tgt_address.attr,
> +     &iscsi_flash_tgt_tpgt.attr,
> +     &iscsi_flash_tgt_chap_tbl_idx.attr,
> +     &iscsi_flash_tgt_is_persistent.attr,
> +     &iscsi_flash_tgt_is_dirty.attr,
> +     &iscsi_flash_tgt_login.attr,
> +     &iscsi_flash_tgt_logout.attr,
> +     &iscsi_flash_tgt_apply.attr,
> +     NULL,
> +};
> +
> +static umode_t iscsi_flash_tgt_attr_is_visible(struct kobject *kobj,
> +                                          struct attribute *attr, int i)
> +{
> +     struct iscsi_flash_tgt_kobj *tgt_kobj =
> +                     container_of(kobj, struct iscsi_flash_tgt_kobj, kobj);
> +
> +     if (attr == &iscsi_flash_tgt_ip.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_IP_ADDR);
> +     else if (attr == &iscsi_flash_tgt_port.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_PORT);
> +     else if (attr ==  &iscsi_flash_tgt_name.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_NAME);
> +     else if (attr == &iscsi_flash_tgt_opt_auto_send_tgt_disable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_OPT_AUTO_SND_TGT_DISABLE);
> +     else if (attr == &iscsi_flash_tgt_opt_discovery_sess.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                     ISCSI_FLASH_TGT_OPT_DISCOVERY_SESS);
> +     else if (attr == &iscsi_flash_tgt_opt_entry_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_OPT_ENTRY_ENABLE);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_enable_hdr_digest.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_HDR_DIGEST);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_enable_data_digest.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_DATA_DIGEST);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_enable_immediate_data.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_IMMEDIATE_DATA);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_enable_initial_r2t.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_ENABLE_INITIAL_R2T);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_data_seq_in_order.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_DATA_SEQ_IN_ORDER);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_data_pdu_in_order.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_DATA_PDU_IN_ORDER);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_chap_auth_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_CHAP_AUTH_ENABLE);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_snack_req_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_SNACK_REQ_ENABLE);
> +     else if (attr ==
> +              &iscsi_flash_tgt_iscsiopt_discovery_logout_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_LOGOUT_ENABLE);
> +     else if (attr ==
> +              &iscsi_flash_tgt_iscsiopt_bi_chap_challenge_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                     ISCSI_FLASH_TGT_ISCSIOPT_BI_CHAP_CHALLENGE_ENABLE);
> +     else if (attr == &iscsi_flash_tgt_iscsiopt_discovery_auth_opt.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_ISCSIOPT_DISCOVERY_AUTH_OPT);
> +     else if (attr == &iscsi_flash_tgt_tcpopt_nagle_disable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                     ISCSI_FLASH_TGT_TCPOPT_NAGLE_DISABLE);
> +     else if (attr == &iscsi_flash_tgt_tcpopt_timer_scale.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                     ISCSI_FLASH_TGT_TCPOPT_TIMER_SCALE);
> +     else if (attr == &iscsi_flash_tgt_tcpopt_timestamp_enable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                             ISCSI_FLASH_TGT_TCPOPT_TIMESTAMP_ENABLE);
> +     else if (attr == &iscsi_flash_tgt_ipopt_frag_disable.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_IPOPT_FRAG_DISABLE);
> +     else if (attr == &iscsi_flash_tgt_max_recv_ds_len.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_MAX_RECV_DS_LEN);
> +     else if (attr == &iscsi_flash_tgt_max_xmit_ds_len.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_MAX_XMIT_DS_LEN);
> +     else if (attr == &iscsi_flash_tgt_first_burst_len.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_FIRST_BURST_LEN);
> +     else if (attr == &iscsi_flash_tgt_def_time2wait.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_DEF_TIME2WAIT);
> +     else if (attr == &iscsi_flash_tgt_def_time2retain.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_DEF_TIME2RETAIN);
> +     else if (attr == &iscsi_flash_tgt_max_outstanding_r2t.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                     ISCSI_FLASH_TGT_MAX_OUTSTANDING_R2T);
> +     else if (attr == &iscsi_flash_tgt_noop_out_interval.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_NOOP_OUT_INTERVAL);
> +     else if (attr == &iscsi_flash_tgt_isid.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_ISID);
> +     else if (attr == &iscsi_flash_tgt_tsid.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_TSID);
> +     else if (attr == &iscsi_flash_tgt_max_burst_len.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_MAX_BURST_LEN);
> +     else if (attr ==  &iscsi_flash_tgt_fw_cmd_timeout.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_FW_CMD_TIMEOUT);
> +     else if (attr ==  &iscsi_flash_tgt_iscsi_alias.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_ISCSI_ALIAS);
> +     else if (attr ==  &iscsi_flash_tgt_address.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_ADDRESS);
> +     else if (attr ==  &iscsi_flash_tgt_tpgt.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_TPGT);
> +     else if (attr == &iscsi_flash_tgt_chap_tbl_idx.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_CHAP_TBL_IDX);
> +     else if (attr == &iscsi_flash_tgt_is_persistent.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_IS_PERSISTENT);
> +     else if (attr == &iscsi_flash_tgt_is_dirty.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_IS_DIRTY);
> +     else if (attr == &iscsi_flash_tgt_login.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_LOGIN);
> +     else if (attr == &iscsi_flash_tgt_logout.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_LOGOUT);
> +     else if (attr == &iscsi_flash_tgt_apply.attr)
> +             return tgt_kobj->is_visible(tgt_kobj->data,
> +                                         ISCSI_FLASH_TGT_APPLY);
> +     return 0;
> +}
> +
> +static struct attribute_group iscsi_flash_tgt_attr_group = {
> +     .attrs = target_attrs,
> +     .is_visible = iscsi_flash_tgt_attr_is_visible,
> +};
> +
> +static struct iscsi_flash_tgt_kobj *
> +__iscsi_flash_tgt_kobj_create(struct iscsi_host_kobj *host_kobj,
> +                           struct attribute_group *attr_group,
> +                           const char *name, int index, void *data,
> +                           ssize_t (*show) (void *data, int type, char *buf),
> +                           ssize_t (*store) (void *data, int type,
> +                                             const char *buf, size_t size),
> +                           umode_t (*is_visible) (void *data, int type),
> +                           void (*release) (void *data))
> +{
> +     struct iscsi_flash_tgt_kobj *tgt_kobj = NULL;
> +
> +     tgt_kobj = kzalloc(sizeof(*tgt_kobj), GFP_KERNEL);
> +     if (!tgt_kobj)
> +             goto exit_kobj_create;
> +
> +     INIT_LIST_HEAD(&tgt_kobj->list);
> +     if (kobject_init_and_add(&tgt_kobj->kobj, &iscsi_flash_tgt_ktype,
> +                              &host_kobj->kobj, name, index)) {
> +             kfree(tgt_kobj);
> +             tgt_kobj = NULL;
> +             goto exit_kobj_create;
> +     }
> +     tgt_kobj->data = data;
> +     tgt_kobj->show = show;
> +     tgt_kobj->store = store;
> +     tgt_kobj->is_visible = is_visible;
> +     tgt_kobj->release = release;
> +
> +     if (sysfs_create_group(&tgt_kobj->kobj, attr_group)) {
> +             tgt_kobj->release = NULL;
> +             kobject_put(&tgt_kobj->kobj);
> +             kfree(tgt_kobj);
> +             tgt_kobj = NULL;
> +             goto exit_kobj_create;
> +     }
> +     tgt_kobj->attr_group = attr_group;
> +
> +     kobject_uevent(&tgt_kobj->kobj, KOBJ_ADD);
> +     list_add_tail(&tgt_kobj->list, &host_kobj->tgt_list);
> +
> +exit_kobj_create:
> +     return tgt_kobj;


You should follow the normal kernel goto error unwinding style:


        return tgt_kobj;

exit_put_kobj:
        tgt_kobj->release = NULL;
        kobject_put(&tgt_kobj->kobj);
exit_free_tgt_kobj:
        kfree(tgt_kobj);
        return NULL;
}






> +}
> +
> +/**
> + * iscsi_flash_tgt_kobj_create() - create flash target sysfs dir
> + * @host_kobj: kobject of host
> + * @index: the target id
> + * @data: driver specific data for target
> + * @show: attr show function
> + * @is_visible: attr visibility function
> + * @release: release function
> + */
> +struct iscsi_flash_tgt_kobj *
> +iscsi_flash_tgt_kobj_create(struct iscsi_host_kobj *host_kobj, int index,
> +                         void *data,
> +                         ssize_t (*show) (void *data, int type, char *buf),
> +                         ssize_t (*store) (void *data, int type,
> +                                           const char *buf, size_t size),
> +                         umode_t (*is_visible) (void *data, int type),
> +                         void (*release) (void *data))
> +{
> +     return __iscsi_flash_tgt_kobj_create(host_kobj,
> +                                          &iscsi_flash_tgt_attr_group,
> +                                          "tgt%d", index, data, show, store,
> +                                          is_visible, release);
> +}
> +EXPORT_SYMBOL_GPL(iscsi_flash_tgt_kobj_create);
> +
> +static void iscsi_flash_tgt_kobj_delete(struct iscsi_flash_tgt_kobj 
> *tgt_kobj)
> +{
> +     list_del(&tgt_kobj->list);
> +     sysfs_remove_group(&tgt_kobj->kobj, tgt_kobj->attr_group);
> +     kobject_put(&tgt_kobj->kobj);
> +}
> +
> +static ssize_t iscsi_flash_new_tgt_store(struct iscsi_host_kobj *host_kobj,
> +                                      struct iscsi_host_attribute *attr,
> +                                      const char *buf, size_t len)
> +{
> +     if (!host_kobj->add)
> +             return -EIO;
> +
> +     return host_kobj->add(host_kobj->data, buf, len);
> +}
> +
> +/**
> + * iscsi_flash_find_tgt_kobj_by_index() - find tgt kobj in the list
> + * @tgt_kobj_list: head of the list to search
> + * @tgt_kobj: pointer to the kobj to iterate
> + * @index: index of the target to search
> + *
> + * Returns:
> + * On success: 1
> + * On failure: 0
> + *
> + * This will find the tgt kobj in the given list with the help of index
> + */
> +int iscsi_flash_find_tgt_kobj_by_index(struct list_head *tgt_kobj_list,
> +                                    struct iscsi_flash_tgt_kobj **tgt_kobj,
> +                                    int index)
> +{
> +     char *get_name = NULL;
> +     int found = 0;
> +
> +     get_name = kasprintf(GFP_KERNEL, "tgt%d", index);
> +     if (!get_name)
> +             return found;
> +



Is there something like this already in the core kobject code? It seems
like we need locking and/or refcounting.



> +     list_for_each_entry((*tgt_kobj), tgt_kobj_list, list) {
> +             if ((*tgt_kobj)->kobj.name &&
> +                 !strcmp((*tgt_kobj)->kobj.name, get_name)) {
> +                     found = 1;
> +                     break;
> +             }
> +     }
> +
> +     kfree(get_name);
> +     return found;
> +}
> +EXPORT_SYMBOL_GPL(iscsi_flash_find_tgt_kobj_by_index);
> +
> +static ssize_t iscsi_flash_del_tgt_store(struct iscsi_host_kobj *host_kobj,
> +                                      struct iscsi_host_attribute *attr,
> +                                      const char *buf, size_t len)
> +{
> +     int index;
> +     struct iscsi_flash_tgt_kobj *tgt_kobj = NULL;
> +     int found = 0;
> +     int ret = len;
> +
> +     if (kstrtoint(buf, 10, &index)) {
> +             ret = -EINVAL;
> +             goto exit_del_tgt_store;
> +     }
> +
> +     found = iscsi_flash_find_tgt_kobj_by_index(&host_kobj->tgt_list,
> +                                                &tgt_kobj, index);
> +     if (!found) {
> +             ret = -EINVAL;
> +             goto exit_del_tgt_store;
> +     }
> +
> +     if (!host_kobj->del) {
> +             ret = -EIO;
> +             goto exit_del_tgt_store;
> +     }
> +
> +     host_kobj->del(tgt_kobj->data);
> +     iscsi_flash_tgt_kobj_delete(tgt_kobj);
> +
> +exit_del_tgt_store:
> +     return ret;
> +}
> +
> +static void iscsi_host_kobj_release(struct kobject *kobj)
> +{
> +     struct iscsi_host_kobj *host_kobj =
> +                     container_of(kobj, struct iscsi_host_kobj, kobj);
> +
> +     kfree(host_kobj);
> +}
> +
> +static ssize_t iscsi_host_attr_store(struct kobject *kobj,
> +                                  struct attribute *attr,
> +                                  const char *buf, size_t size)
> +{
> +     struct iscsi_host_kobj *host_kobj =
> +                     container_of(kobj, struct iscsi_host_kobj, kobj);
> +     struct iscsi_host_attribute *host_tgt_attr =
> +                     container_of(attr, struct iscsi_host_attribute, attr);
> +
> +     if (!host_tgt_attr->store)
> +             return -EIO;
> +
> +     return host_tgt_attr->store(host_kobj, host_tgt_attr, buf, size);
> +}
> +
> +static const struct sysfs_ops iscsi_host_attr_ops = {
> +     .show = NULL,
> +     .store = iscsi_host_attr_store,
> +};
> +
> +static struct kobj_type iscsi_host_ktype = {
> +     .release = iscsi_host_kobj_release,
> +     .sysfs_ops = &iscsi_host_attr_ops,
> +};
> +
> +#define iscsi_host_rw_attr(fnname, sysfs_name, _mode, _show, _store, _type)  
> \
> +static struct iscsi_host_attribute iscsi_host_flash_tgt_##fnname = {         
> \
> +     .attr = { .name = __stringify(sysfs_name), .mode = _mode },          \
> +     .store = _store,                                                     \
> +     .type = _type,                                                       \
> +}
> +
> +/* Host attributes */
> +iscsi_host_rw_attr(new, new, 0200, NULL, iscsi_flash_new_tgt_store,
> +                HOST_FLASH_TGT_NEW);
> +iscsi_host_rw_attr(del, delete, 0200, NULL, iscsi_flash_del_tgt_store,
> +                HOST_FLASH_TGT_DEL);
> +
> +static struct attribute *host_attrs[] = {
> +     &iscsi_host_flash_tgt_del.attr,
> +     &iscsi_host_flash_tgt_new.attr,
> +     NULL,
> +};
> +
> +static struct attribute_group iscsi_host_attr_group = {
> +     .attrs = host_attrs,
> +};
> +
> +/**
> + * __iscsi_host_kobj_create() - creates host kobject
> + * @set_name: name of the kobject to create
> + * @data: pointer to host specific data
> + * @add: function to add new target for this host
> + *
> + * This creates the host kobject for the given name
> + */
> +static struct iscsi_host_kobj *
> +__iscsi_host_kobj_create(const char *set_name, void *data,
> +                      ssize_t (*add) (void *data, const char *buf,
> +                                     size_t len),
> +                      void (*del) (void *data))
> +{
> +     struct iscsi_host_kobj *host_kobj = NULL;
> +
> +     host_kobj = kzalloc(sizeof(*host_kobj), GFP_KERNEL);
> +     if (!host_kobj)
> +             return NULL;
> +
> +     if (kobject_init_and_add(&host_kobj->kobj, &iscsi_host_ktype,
> +                              iscsi_offload_kobj, "%s", set_name))
> +             goto error;
> +
> +     host_kobj->data = data;
> +     host_kobj->add = add;
> +     host_kobj->del = del;
> +
> +     if (sysfs_create_group(&host_kobj->kobj,
> +                            &iscsi_host_attr_group)) {
> +             kobject_put(&host_kobj->kobj);
> +             goto error;
> +     }
> +
> +     kobject_uevent(&host_kobj->kobj, KOBJ_ADD);
> +     INIT_LIST_HEAD(&host_kobj->tgt_list);
> +
> +     return host_kobj;
> +
> +error:
> +     kfree(host_kobj);
> +     return NULL;
> +}
> +
> +/**
> + * iscsi_host_kobj_create() - creates kobject for a scsi host
> + * @hostno: host number of scsi host
> + * @data: pointer to host specific data
> + * @add: function to add target for this host
> + *
> + * This will create host kobject for the given hostno.
> + */
> +struct iscsi_host_kobj *
> +iscsi_host_kobj_create(unsigned int hostno, void *data,
> +                    ssize_t (*add) (void *data, const char *buf, size_t len),
> +                    void (*del) (void *data))
> +{
> +     struct iscsi_host_kobj *host_kobj;
> +     char *set_name;
> +
> +     set_name = kasprintf(GFP_KERNEL, "host%u", hostno);
> +     if (!set_name)
> +             return NULL;
> +
> +     host_kobj = __iscsi_host_kobj_create(set_name, data, add, del);
> +     kfree(set_name);
> +     return host_kobj;
> +}
> +EXPORT_SYMBOL_GPL(iscsi_host_kobj_create);
> +
> +/**
> + * iscsi_host_kobj_delete() - destroy host kobject and tgt kobjects under it
> + * @host_kobj: host kobject
> + *
> + * This will remove the host kobject and all target kobjects and attrs under 
> it.
> + */
> +void iscsi_host_kobj_delete(struct iscsi_host_kobj *host_kobj)
> +{
> +     struct iscsi_flash_tgt_kobj *tgt_kobj = NULL, *tmp_kobj;
> +
> +     if (!host_kobj)
> +             return;
> +
> +     sysfs_remove_group(&host_kobj->kobj, &iscsi_host_attr_group);
> +
> +     list_for_each_entry_safe(tgt_kobj, tmp_kobj,
> +                              &host_kobj->tgt_list, list)
> +             iscsi_flash_tgt_kobj_delete(tgt_kobj);
> +
> +     kobject_put(&host_kobj->kobj);
> +}
> +EXPORT_SYMBOL_GPL(iscsi_host_kobj_delete);
> +
> +/**
> + * iscsi_offload_kobj_create() - creates kobject for iscsi_offload
> + * @name: name of kobject to create
> + */
> +static struct kobject *iscsi_offload_kobj_create(const char *name)
> +{
> +     struct kobject *fw_iscsi_offload = NULL;
> +
> +     fw_iscsi_offload = kobject_create_and_add(name, firmware_kobj);
> +     if (!fw_iscsi_offload)
> +             return NULL;
> +
> +     return fw_iscsi_offload;
> +}
> +
> +/**
> + * iscsi_offload_kobj_remove() - removes iscsi_offload kobject
> + */
> +static void iscsi_offload_kobj_remove(struct kobject *kobj)
> +{
> +     if (kobj) {
> +             kobject_del(kobj);
> +             kobject_put(kobj);
> +     }
> +}
> +
> +static int __init iscsi_offload_module_init(void)
> +{
> +     iscsi_offload_kobj = iscsi_offload_kobj_create(ISCSI_OFFLOAD_NAME);
> +     if (!iscsi_offload_kobj) {
> +             pr_err("%s: Unable to create sysfs interface\n",
> +                    ISCSI_OFFLOAD_NAME);
> +             return -EIO;
> +     }
> +     return 0;
> +}
> +
> +static void __exit iscsi_offload_module_exit(void)
> +{
> +     iscsi_offload_kobj_remove(iscsi_offload_kobj);
> +}
> +

Not sure about the name. It looks like a generic way to create a session
in the kernel that just happens to be used by a offload driver. It also
looks like it might be initiator specific, we would want to avoid
confusion with any future target mode interface.

-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

Reply via email to