From: Stefan Richter <stefanr@s5r6.in-berlin.de>
To: Chris Boot <bootc@bootc.net>
Cc: linux1394-devel@lists.sourceforge.net,
target-devel@vger.kernel.org, linux-kernel@vger.kernel.org,
agrover@redhat.com, clemens@ladisch.de, nab@linux-iscsi.org
Subject: Re: [PATCH v2 08/11] firewire-sbp-target: Add sbp_login.{c,h}
Date: Wed, 15 Feb 2012 22:00:52 +0100 [thread overview]
Message-ID: <20120215220052.040e680a@stein> (raw)
In-Reply-To: <1329317248-94128-9-git-send-email-bootc@bootc.net>
On Feb 15 Chris Boot wrote:
> This file contains the implementation of the login, reconnect and logout
> management ORBs in SBP-2.
>
> Signed-off-by: Chris Boot <bootc@bootc.net>
> Cc: Andy Grover <agrover@redhat.com>
> Cc: Clemens Ladisch <clemens@ladisch.de>
> Cc: Nicholas A. Bellinger <nab@linux-iscsi.org>
> Cc: Stefan Richter <stefanr@s5r6.in-berlin.de>
> ---
> drivers/target/sbp/sbp_login.c | 665 ++++++++++++++++++++++++++++++++++++++++
> drivers/target/sbp/sbp_login.h | 14 +
> 2 files changed, 679 insertions(+), 0 deletions(-)
> create mode 100644 drivers/target/sbp/sbp_login.c
> create mode 100644 drivers/target/sbp/sbp_login.h
>
> diff --git a/drivers/target/sbp/sbp_login.c b/drivers/target/sbp/sbp_login.c
> new file mode 100644
> index 0000000..74b5eaf
> --- /dev/null
> +++ b/drivers/target/sbp/sbp_login.c
> @@ -0,0 +1,665 @@
> +/*
> + * SBP2 target driver (SCSI over IEEE1394 in target mode)
> + *
> + * Copyright (C) 2011 Chris Boot <bootc@bootc.net>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software Foundation,
> + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#define KMSG_COMPONENT "sbp_target"
> +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
> +
> +#include <linux/kref.h>
> +#include <linux/firewire.h>
> +#include <linux/firewire-constants.h>
> +#include <linux/slab.h>
> +
> +#include <target/target_core_base.h>
> +#include <target/target_core_fabric.h>
> +
> +#include "sbp_base.h"
> +#include "sbp_management_agent.h"
> +#include "sbp_login.h"
> +#include "sbp_target_agent.h"
> +
> +#define SESSION_MAINTENANCE_INTERVAL HZ
> +
> +static atomic_t login_id = ATOMIC_INIT(0);
> +
> +static void session_maintenance_work(struct work_struct *work);
> +
> +static int read_peer_guid(u64 *guid, const struct sbp_management_request *req)
> +{
> + int ret;
> + __be32 high, low;
> +
> + ret = fw_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST,
> + req->node_addr, req->generation, req->speed,
> + (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + 3 * 4,
> + &high, sizeof(high));
> + if (ret != RCODE_COMPLETE)
> + return ret;
> +
> + ret = fw_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST,
> + req->node_addr, req->generation, req->speed,
> + (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + 4 * 4,
> + &low, sizeof(low));
> + if (ret != RCODE_COMPLETE)
> + return ret;
> +
> + *guid = (u64)be32_to_cpu(high) << 32 | be32_to_cpu(low);
> +
> + return RCODE_COMPLETE;
> +}
> +
> +static struct sbp_session *sbp_session_find_by_guid(
> + struct sbp_tpg *tpg, u64 guid)
> +{
> + struct se_session *se_sess;
> +
> + spin_lock(&tpg->se_tpg.session_lock);
> + list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
> + struct sbp_session *sess = se_sess->fabric_sess_ptr;
> + if (sess->guid == guid) {
> + spin_unlock(&tpg->se_tpg.session_lock);
> + return sess;
> + }
> + }
> + spin_unlock(&tpg->se_tpg.session_lock);
> +
> + return NULL;
> +}
Another form to write this would be
static struct sbp_session *sbp_session_find_by_guid(
struct sbp_tpg *tpg, u64 guid)
{
struct se_session *se_sess;
struct sbp_session *s, *session = NULL;
spin_lock(&tpg->se_tpg.session_lock);
list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
s = se_sess->fabric_sess_ptr;
if (s->guid == guid) {
session = s;
break;
}
}
spin_unlock(&tpg->se_tpg.session_lock);
return session;
}
But since your function is very small, the dual unlock-and-exit paths are
not a problem for readability.
As an aside, here is a variation of the theme, though weirdly looking if
one never came across it before:
static struct sbp_session *sbp_session_find_by_guid(
struct sbp_tpg *tpg, u64 guid)
{
struct se_session *s;
spin_lock(&tpg->se_tpg.session_lock);
list_for_each_entry(s, &tpg->se_tpg.tpg_sess_list, sess_list)
if (s->fabric_sess_ptr->guid == guid)
break;
spin_unlock(&tpg->se_tpg.session_lock);
if (&s->sess_list != &tpg->se_tpg.tpg_sess_list)
return s->fabric_sess_ptr;
else
return NULL;
}
[...]
> +static struct sbp_login_descriptor *sbp_login_find_by_id(
> + struct sbp_tpg *tpg, int login_id)
> +{
> + struct se_session *se_sess;
> +
> + spin_lock(&tpg->se_tpg.session_lock);
> + list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) {
> + struct sbp_session *sess = se_sess->fabric_sess_ptr;
> + struct sbp_login_descriptor *login;
> +
> + spin_lock(&sess->login_list_lock);
> + list_for_each_entry(login, &sess->login_list, link) {
> + if (login->login_id == login_id) {
> + spin_unlock(&sess->login_list_lock);
> + spin_unlock(&tpg->se_tpg.session_lock);
> + return login;
> + }
> + }
> + spin_unlock(&sess->login_list_lock);
> + }
> + spin_unlock(&tpg->se_tpg.session_lock);
> +
> + return NULL;
> +}
This function on the other hand might indeed benefit from a style
involving a single unlock-and-exit path.
[...]
> +static void sbp_session_release(struct sbp_session *sess, bool cancel_work)
> +{
> + spin_lock(&sess->login_list_lock);
> + if (!list_empty(&sess->login_list)) {
> + spin_unlock(&sess->login_list_lock);
> + return;
> + }
> + spin_unlock(&sess->login_list_lock);
> +
> + transport_deregister_session_configfs(sess->se_sess);
> + transport_deregister_session(sess->se_sess);
> +
> + if (sess->card)
> + fw_card_put(sess->card);
> +
> + if (cancel_work)
> + cancel_delayed_work_sync(&sess->maint_work);
> +
> + kfree(sess);
> +}
What prevents that an entry is added to sess->login_list right after
you tested for it being empty?
If there is something external which prevents this, then you don't
need to take the lock just for this test.
If there is no such external measure of serialization, then the
spinlock-protected section is too small.
By the way, the use of spin_lock()/spin_unlock() is quite atypical.
This API restricts you
- not to call a possibly sleeping function within the lock-
protected section,
- not to take the lock in tasklet context or IRQ context.
So this locking API is quite rarely used: Anywhere where a mutex
/could/ be used, but none of the locked sections ever need to sleep.
This is a rather narrow use case.
Maybe you know all this but I thought I mention it anyway.
> +static void session_check_for_reset(struct sbp_session *sess)
> +{
> + bool card_valid = false;
> +
> + if (sess->card) {
> + spin_lock_irq(&sess->card->lock);
> + card_valid = (sess->card->local_node != NULL);
> + spin_unlock_irq(&sess->card->lock);
> +
> + if (!card_valid) {
> + fw_card_put(sess->card);
> + sess->card = NULL;
> + }
> + }
> +
> + if (!card_valid || (sess->generation != sess->card->generation)) {
> + pr_info("Waiting for reconnect from node: %016llx\n",
> + sess->guid);
> +
> + sess->node_id = -1;
> + sess->reconnect_expires = get_jiffies_64() +
> + ((sess->reconnect_hold + 1) * HZ);
> + }
> +}
[Note to self: When more awake, carefully review this peeking into
fw_card internals, the generation accesses, and the card refcounting.]
> +static void session_reconnect_expired(struct sbp_session *sess)
> +{
> + struct sbp_login_descriptor *login, *temp;
> +
> + pr_info("Reconnect timer expired for node: %016llx\n", sess->guid);
> +
> + spin_lock(&sess->login_list_lock);
> + list_for_each_entry_safe(login, temp, &sess->login_list, link) {
> + spin_unlock(&sess->login_list_lock);
> + sbp_login_release(login, false);
> + spin_lock(&sess->login_list_lock);
> + }
> + spin_unlock(&sess->login_list_lock);
> +
> + /* sbp_login_release() calls sbp_session_release() */
> +}
This is wrong. Either something external protects the
session_reconnect_expired() executing context from concurrent
manipulations of sess->login_list. Then you don't need to
take the lock here in the first place.
Or there is no such external serialization measure. Then you
must not drop the list lock in the loop body.
In the latter case, an easy fix would be to move the expired
logins to a local temporary list while holding the lock, then
release each item from the temporary list without holding the
lock.
--
Stefan Richter
-=====-===-- --=- -====
http://arcgraph.de/sr/
next prev parent reply other threads:[~2012-02-15 21:01 UTC|newest]
Thread overview: 100+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-17 14:51 FireWire/SBP2 Target mode Chris Boot
2011-08-17 18:57 ` Stefan Richter
2011-08-18 16:19 ` Clemens Ladisch
2012-02-01 19:50 ` Andy Grover
2012-02-01 21:41 ` Stefan Richter
2012-02-02 9:22 ` Boaz Harrosh
2012-02-02 10:09 ` Clemens Ladisch
2012-02-06 13:13 ` Chris Boot
2012-02-06 14:43 ` Clemens Ladisch
2012-02-06 14:51 ` Chris Boot
2012-02-06 20:26 ` Stefan Richter
2012-02-06 22:28 ` Chris Boot
2012-02-06 23:00 ` Julian Calaby
2012-02-06 23:09 ` Chris Boot
2012-02-07 7:38 ` Chris Boot
2012-02-07 10:06 ` Julian Calaby
2012-02-07 19:17 ` Stefan Richter
2012-02-07 19:53 ` Chris Boot
2012-02-11 19:43 ` [RFC][PATCH 00/13] firewire-sbp-target: FireWire SBP-2 SCSI target Chris Boot
2012-02-11 19:44 ` [PATCH 01/13] firewire: Add function to get speed from opaque struct fw_request Chris Boot
2012-02-11 19:44 ` [PATCH 02/13] firewire: Add EXPORT_SYMBOL_GPL(fw_card_release) Chris Boot
2012-02-11 19:44 ` [PATCH 03/13] firewire-sbp-target: Add Kconfig, Makefile and TODO Chris Boot
2012-02-13 12:50 ` Nicholas A. Bellinger
2012-02-11 19:44 ` [PATCH 04/13] firewire-sbp-target: Add sbp_base.h header Chris Boot
2012-02-11 19:44 ` [PATCH 05/13] firewire-sbp-target: Add sbp_configfs.c Chris Boot
2012-02-11 19:44 ` [PATCH 06/13] firewire-sbp-target: Add sbp_fabric.{c,h} Chris Boot
2012-02-13 13:06 ` Nicholas A. Bellinger
[not found] ` <337FFBD7-6B4A-41CA-BB57-6038C935B5BF@bootc.net>
2012-02-13 19:53 ` Stefan Richter
2012-02-13 22:41 ` Nicholas A. Bellinger
2012-02-11 19:44 ` [PATCH 07/13] firewire-sbp-target: Add sbp_proto.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 08/13] firewire-sbp-target: add sbp_management_agent.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 09/13] firewire-sbp-target: Add sbp_login.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 10/13] firewire-sbp-target: Add sbp_target_agent.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 11/13] firewire-sbp-target: Add sbp_scsi_cmnd.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 12/13] firewire-sbp-target: Add sbp_util.{c,h} Chris Boot
2012-02-11 19:44 ` [PATCH 13/13] firewire-sbp-target: Add to target Kconfig and Makefile Chris Boot
2012-02-12 14:12 ` [RFC][PATCH 00/13] firewire-sbp-target: FireWire SBP-2 SCSI target Stefan Richter
2012-02-12 15:13 ` Chris Boot
2012-02-12 16:16 ` Stefan Richter
2012-02-15 14:47 ` [PATCH v2 00/11] " Chris Boot
2012-02-15 14:47 ` [PATCH v2 01/11] firewire: Add function to get speed from opaque struct fw_request Chris Boot
2012-02-15 19:09 ` Stefan Richter
2012-02-15 19:10 ` Chris Boot
2012-02-15 22:01 ` Stefan Richter
2012-02-16 9:12 ` Chris Boot
2012-02-15 14:47 ` [PATCH v2 02/11] firewire: Move fw_card kref functions into linux/firewire.h Chris Boot
2012-02-15 19:10 ` Stefan Richter
2012-02-16 9:18 ` Chris Boot
2012-02-15 14:47 ` [PATCH v2 03/11] firewire-sbp-target: Add Kconfig, Makefile and TODO Chris Boot
2012-02-15 14:47 ` [PATCH v2 04/11] firewire-sbp-target: Add sbp_base.h header Chris Boot
2012-02-15 19:15 ` Stefan Richter
2012-02-16 9:55 ` Chris Boot
2012-02-15 14:47 ` [PATCH v2 05/11] firewire-sbp-target: Add sbp_configfs.c Chris Boot
2012-02-15 19:21 ` Stefan Richter
2012-02-16 9:57 ` Chris Boot
2012-02-16 13:48 ` Stefan Richter
2012-02-15 14:47 ` [PATCH v2 06/11] firewire-sbp-target: Add sbp_fabric.{c,h} Chris Boot
2012-02-15 14:47 ` [PATCH v2 07/11] firewire-sbp-target: add sbp_management_agent.{c,h} Chris Boot
2012-02-15 19:48 ` Stefan Richter
2012-02-16 10:28 ` Chris Boot
2012-02-16 14:12 ` Stefan Richter
2012-02-15 14:47 ` [PATCH v2 08/11] firewire-sbp-target: Add sbp_login.{c,h} Chris Boot
2012-02-15 21:00 ` Stefan Richter [this message]
2012-02-16 11:21 ` Chris Boot
2012-03-03 17:37 ` Stefan Richter
2012-03-15 17:48 ` Paul E. McKenney
2012-02-15 14:47 ` [PATCH v2 09/11] firewire-sbp-target: Add sbp_target_agent.{c,h} Chris Boot
2012-02-15 21:27 ` Stefan Richter
2012-02-16 11:25 ` Chris Boot
2012-02-18 14:59 ` Stefan Richter
2012-02-18 15:05 ` Chris Boot
2012-02-15 14:47 ` [PATCH v2 10/11] firewire-sbp-target: Add sbp_scsi_cmnd.{c,h} Chris Boot
2012-02-15 14:47 ` [PATCH v2 11/11] firewire-sbp-target: Add to target Kconfig and Makefile Chris Boot
2012-04-11 14:20 ` [PATCH v3 00/11] firewire-sbp-target: FireWire SBP-2 SCSI target Chris Boot
2012-04-11 14:20 ` [PATCH 01/11] firewire: Add function to get speed from opaque struct fw_request Chris Boot
2012-04-11 14:20 ` [PATCH 02/11] firewire: Move fw_card kref functions into linux/firewire.h Chris Boot
2012-04-11 14:20 ` [PATCH 03/11] firewire-sbp-target: Add Kconfig, Makefile and TODO Chris Boot
2012-04-11 14:20 ` [PATCH 04/11] firewire-sbp-target: Add sbp_base.h header Chris Boot
2012-04-11 14:20 ` [PATCH 05/11] firewire-sbp-target: Add sbp_configfs.c Chris Boot
2012-04-11 14:20 ` [PATCH 06/11] firewire-sbp-target: Add sbp_fabric.{c,h} Chris Boot
2012-04-11 14:20 ` [PATCH 07/11] firewire-sbp-target: Add sbp_management_agent.{c,h} Chris Boot
2012-04-11 14:20 ` [PATCH 08/11] firewire-sbp-target: Add sbp_login.{c,h} Chris Boot
2012-04-14 10:17 ` Stefan Richter
2012-04-11 14:20 ` [PATCH 09/11] firewire-sbp-target: Add sbp_target_agent.{c,h} Chris Boot
2012-04-14 10:49 ` Stefan Richter
2012-04-14 11:33 ` Stefan Richter
2012-04-11 14:20 ` [PATCH 10/11] firewire-sbp-target: Add sbp_scsi_cmnd.{c,h} Chris Boot
2012-04-11 14:20 ` [PATCH 11/11] firewire-sbp-target: Add to target Kconfig and Makefile Chris Boot
2012-04-12 21:02 ` [PATCH v3 00/11] firewire-sbp-target: FireWire SBP-2 SCSI target Andy Grover
2012-04-13 3:03 ` Nicholas A. Bellinger
2012-04-13 13:16 ` Chris Boot
2012-04-14 1:23 ` Nicholas A. Bellinger
2012-04-14 9:12 ` [PATCH 0/2] sbp-target: cleanup after merge into single file Chris Boot
2012-04-14 9:12 ` [PATCH 1/2] sbp-target: minor cleanups after merging " Chris Boot
2012-04-14 9:12 ` [PATCH 2/2] sbp-target: update TODO file Chris Boot
2012-04-14 21:44 ` [PATCH 0/2] sbp-target: cleanup after merge into single file Nicholas A. Bellinger
2012-04-14 23:11 ` Stefan Richter
2012-04-15 1:22 ` Nicholas A. Bellinger
2012-04-17 10:48 ` [PATCH v3 00/11] firewire-sbp-target: FireWire SBP-2 SCSI target Chris Boot
2012-04-18 7:17 ` Nicholas A. Bellinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120215220052.040e680a@stein \
--to=stefanr@s5r6.in-berlin.de \
--cc=agrover@redhat.com \
--cc=bootc@bootc.net \
--cc=clemens@ladisch.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux1394-devel@lists.sourceforge.net \
--cc=nab@linux-iscsi.org \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox