From patchwork Fri Jun 22 21:40:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Christie X-Patchwork-Id: 10483079 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D75276023A for ; Fri, 22 Jun 2018 21:40:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C462828E5C for ; Fri, 22 Jun 2018 21:40:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B917429040; Fri, 22 Jun 2018 21:40:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 38AC828E5C for ; Fri, 22 Jun 2018 21:40:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932950AbeFVVke (ORCPT ); Fri, 22 Jun 2018 17:40:34 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:35984 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754575AbeFVVk2 (ORCPT ); Fri, 22 Jun 2018 17:40:28 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A6DBD81663FD; Fri, 22 Jun 2018 21:40:27 +0000 (UTC) Received: from rh2.redhat.com (ovpn-120-5.rdu2.redhat.com [10.10.120.5]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4F6E62026D6C; Fri, 22 Jun 2018 21:40:27 +0000 (UTC) From: Mike Christie To: martin.petersen@oracle.com, linux-scsi@vger.kernel.org, target-devel@vger.kernel.org, nab@linux-iscsi.org Cc: Mike Christie Subject: [PATCH 5/6] tcmu: add module wide block/reset_netlink support Date: Fri, 22 Jun 2018 16:40:22 -0500 Message-Id: <1529703623-9606-6-git-send-email-mchristi@redhat.com> In-Reply-To: <1529703623-9606-1-git-send-email-mchristi@redhat.com> References: <1529703623-9606-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 22 Jun 2018 21:40:27 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 22 Jun 2018 21:40:27 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'mchristi@redhat.com' RCPT:'' Sender: target-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: target-devel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch based on Xiubo's patches adds 2 tcmu attr to block and resetup the netlink interface. It's used during userspace daemon reinitialization after the daemon has crashed while there is outstanding nl requests. The daemon can block the nl interface, kill outstanding requests in the kernel and then reopen the netlink socket and unblock it to allow new requests. Signed-off-by: Mike Christie --- drivers/target/target_core_user.c | 100 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 2a2e9e4e..9555981 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -94,6 +94,7 @@ #define TCMU_GLOBAL_MAX_BLOCKS_DEF (512 * 1024) static u8 tcmu_kern_cmd_reply_supported; +static u8 tcmu_netlink_blocked; static struct device *tcmu_root_device; @@ -255,6 +256,92 @@ MODULE_PARM_DESC(global_max_data_area_mb, "Max MBs allowed to be allocated to all the tcmu device's " "data areas."); +static int tcmu_get_block_netlink(char *buffer, + const struct kernel_param *kp) +{ + return sprintf(buffer, "%s\n", tcmu_netlink_blocked ? + "blocked" : "unblocked"); +} + +static int tcmu_set_block_netlink(const char *str, + const struct kernel_param *kp) +{ + int ret; + u8 val; + + ret = kstrtou8(str, 0, &val); + if (ret < 0) + return ret; + + if (val > 1) { + pr_err("Invalid block netlink value %u\n", val); + return -EINVAL; + } + + tcmu_netlink_blocked = val; + return 0; +} + +static const struct kernel_param_ops tcmu_block_netlink_op = { + .set = tcmu_set_block_netlink, + .get = tcmu_get_block_netlink, +}; + +module_param_cb(block_netlink, &tcmu_block_netlink_op, NULL, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(block_netlink, "Block new netlink commands."); + +static int tcmu_fail_netlink_cmd(struct tcmu_nl_cmd *nl_cmd) +{ + struct tcmu_dev *udev = nl_cmd->udev; + + if (!tcmu_netlink_blocked) { + pr_err("Could not reset device's netlink interface. Netlink is not blocked.\n"); + return -EBUSY; + } + + if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { + pr_debug("Aborting nl cmd %d on %s\n", nl_cmd->cmd, udev->name); + nl_cmd->status = -EINTR; + list_del(&nl_cmd->nl_list); + complete(&nl_cmd->complete); + } + return 0; +} + +static int tcmu_set_reset_netlink(const char *str, + const struct kernel_param *kp) +{ + struct tcmu_nl_cmd *nl_cmd, *tmp_cmd; + int ret; + u8 val; + + ret = kstrtou8(str, 0, &val); + if (ret < 0) + return ret; + + if (val != 1) { + pr_err("Invalid reset netlink value %u\n", val); + return -EINVAL; + } + + mutex_lock(&tcmu_nl_cmd_mutex); + list_for_each_entry_safe(nl_cmd, tmp_cmd, &tcmu_nl_cmd_list, nl_list) { + ret = tcmu_fail_netlink_cmd(nl_cmd); + if (ret) + break; + } + mutex_unlock(&tcmu_nl_cmd_mutex); + + return ret; +} + +static const struct kernel_param_ops tcmu_reset_netlink_op = { + .set = tcmu_set_reset_netlink, +}; + +module_param_cb(reset_netlink, &tcmu_reset_netlink_op, NULL, S_IWUSR); +MODULE_PARM_DESC(reset_netlink, "Reset netlink commands."); + /* multicast group */ enum tcmu_multicast_groups { TCMU_MCGRP_CONFIG, @@ -303,8 +390,9 @@ static int tcmu_genl_cmd_done(struct genl_info *info, int completed_cmd) } list_del(&nl_cmd->nl_list); - pr_debug("%s genl cmd done got id %d curr %d done %d rc %d\n", - udev->name, dev_id, nl_cmd->cmd, completed_cmd, rc); + pr_debug("%s genl cmd done got id %d curr %d done %d rc %d stat %d\n", + udev->name, dev_id, nl_cmd->cmd, completed_cmd, rc, + nl_cmd->status); if (nl_cmd->cmd != completed_cmd) { pr_err("Mismatched commands on %s (Expecting reply for %d. Current %d).\n", @@ -1547,6 +1635,13 @@ static int tcmu_init_genl_cmd_reply(struct tcmu_dev *udev, int cmd) mutex_lock(&tcmu_nl_cmd_mutex); + if (tcmu_netlink_blocked) { + mutex_unlock(&tcmu_nl_cmd_mutex); + pr_warn("Failing nl cmd %d on %s. Interface is blocked.\n", cmd, + udev->name); + return -EAGAIN; + } + if (nl_cmd->cmd != TCMU_CMD_UNSPEC) { mutex_unlock(&tcmu_nl_cmd_mutex); pr_warn("netlink cmd %d already executing on %s\n", @@ -1583,7 +1678,6 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev) mutex_lock(&tcmu_nl_cmd_mutex); nl_cmd->cmd = TCMU_CMD_UNSPEC; ret = nl_cmd->status; - nl_cmd->status = 0; mutex_unlock(&tcmu_nl_cmd_mutex); return ret;