Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp804331pxb; Tue, 3 Nov 2020 13:01:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJyz17VS6rXzUUl/jd4cDJXgTn6FRHPBvY/tAysBcgUTiU7dfE3RynYaAryGnGVCKWAqGr61 X-Received: by 2002:aa7:d84a:: with SMTP id f10mr7794562eds.163.1604437288032; Tue, 03 Nov 2020 13:01:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604437288; cv=none; d=google.com; s=arc-20160816; b=Ghfse2eSb1broZ+iSDQRVIOkQj0CpF7O217rCgMvmFKEizXsVVyiT58mMbC5iDJUHx kIRtje1XAhNRmdkRG5iwU7YtTbUefDJLXXRlR1D5CS2I038Aw4U+18NStMhkYivGpx0G Rx8LH6/gAphqkeHtsgbS+VUUmIWqbT23D6XoCan1RM9WoEc8RbfoGxvsfgnWv3BV028/ /5TM7BClZLpj+oMBj7AZc2Qv+QNAXqyM8Hqawq6sFkQv3qYYUsZGFLaPyp8eHN7b2nkz WYmKPKQSrc03K11ZJnbqU2OoA/T2Y1REgps5q7fRLRdhRIchCSJ+5hhtD8UUuZHDowXq ivbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ImPKMKSY1I6nRk7wd+8uh1e/0bv8rvCNV3CONbJM/JY=; b=p+MWAM5fdFczq8wUwOiXADdirxXWxi/Q1Zue/mWtIuYr1qx5lI93G1ZmCojLjdh+sY mItnPf9fGAn9MRAKELe1Wpu+hEpT1XYTtDSWt57pI82ihTLMa/RysNg7MiVKa8pzLXce IWooTyQTo7L59jrCeB5ub+ogtL/mvFyrRyOPHTp2ePCSP5jsI9UDucZsv6VYqyJrPb+P NgwxHNw7kdpDuQk3q/LRAEpt1j+sjShsT0L8+zR7U7Sj1D2s5SN0gvU21lCTnUh5GpmT hx+Vq6a6DzgwdD1tHr+Qi7o/wK74v3+Y1/6ilpIZAG54oeoo7ltxZCTmtLN/JZZRLjzZ b0Qg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=JGou7ksd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k22si14668969edr.463.2020.11.03.13.01.04; Tue, 03 Nov 2020 13:01:28 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=JGou7ksd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733152AbgKCU7v (ORCPT + 99 others); Tue, 3 Nov 2020 15:59:51 -0500 Received: from mail.kernel.org ([198.145.29.99]:35182 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730777AbgKCU7t (ORCPT ); Tue, 3 Nov 2020 15:59:49 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A53A42053B; Tue, 3 Nov 2020 20:59:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604437188; bh=6kclw7NjpySyc7uw7GBrdqMgAv3hQb9hE1Q/lAP1phI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JGou7ksd8s1dx4jRmUmuUKk/I0e4Y3+fz3oKgWzXZkLp8rkGcRSQolNUTVUkkFN98 dhA7ujVBafQfzNDZ++qAuCf49bEOjkwdbKyMWeB6pi8VfR7jgIt38pn1UJa+6hDBvp SuuOt/hdia/AzkNIvYqX3TS6auPl5q3ANTarALQU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Sven Schnelle , Alexander Egorenkov , Vasily Gorbik Subject: [PATCH 5.4 157/214] s390/stp: add locking to sysfs functions Date: Tue, 3 Nov 2020 21:36:45 +0100 Message-Id: <20201103203305.506428725@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201103203249.448706377@linuxfoundation.org> References: <20201103203249.448706377@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sven Schnelle commit b3bd02495cb339124f13135d51940cf48d83e5cb upstream. The sysfs function might race with stp_work_fn. To prevent that, add the required locking. Another issue is that the sysfs functions are checking the stp_online flag, but this flag just holds the user setting whether STP is enabled. Add a flag to clock_sync_flag whether stp_info holds valid data and use that instead. Cc: stable@vger.kernel.org Signed-off-by: Sven Schnelle Reviewed-by: Alexander Egorenkov Signed-off-by: Vasily Gorbik Signed-off-by: Greg Kroah-Hartman --- arch/s390/kernel/time.c | 118 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 33 deletions(-) --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -354,8 +354,9 @@ static DEFINE_PER_CPU(atomic_t, clock_sy static DEFINE_MUTEX(clock_sync_mutex); static unsigned long clock_sync_flags; -#define CLOCK_SYNC_HAS_STP 0 -#define CLOCK_SYNC_STP 1 +#define CLOCK_SYNC_HAS_STP 0 +#define CLOCK_SYNC_STP 1 +#define CLOCK_SYNC_STPINFO_VALID 2 /* * The get_clock function for the physical clock. It will get the current @@ -592,6 +593,22 @@ void stp_queue_work(void) queue_work(time_sync_wq, &stp_work); } +static int __store_stpinfo(void) +{ + int rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi)); + + if (rc) + clear_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); + else + set_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); + return rc; +} + +static int stpinfo_valid(void) +{ + return stp_online && test_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); +} + static int stp_sync_clock(void *data) { struct clock_sync_data *sync = data; @@ -613,8 +630,7 @@ static int stp_sync_clock(void *data) if (rc == 0) { sync->clock_delta = clock_delta; clock_sync_global(clock_delta); - rc = chsc_sstpi(stp_page, &stp_info, - sizeof(struct stp_sstpi)); + rc = __store_stpinfo(); if (rc == 0 && stp_info.tmd != 2) rc = -EAGAIN; } @@ -659,7 +675,7 @@ static void stp_work_fn(struct work_stru if (rc) goto out_unlock; - rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi)); + rc = __store_stpinfo(); if (rc || stp_info.c == 0) goto out_unlock; @@ -696,10 +712,14 @@ static ssize_t stp_ctn_id_show(struct de struct device_attribute *attr, char *buf) { - if (!stp_online) - return -ENODATA; - return sprintf(buf, "%016llx\n", - *(unsigned long long *) stp_info.ctnid); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid()) + ret = sprintf(buf, "%016llx\n", + *(unsigned long long *) stp_info.ctnid); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); @@ -708,9 +728,13 @@ static ssize_t stp_ctn_type_show(struct struct device_attribute *attr, char *buf) { - if (!stp_online) - return -ENODATA; - return sprintf(buf, "%i\n", stp_info.ctn); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid()) + ret = sprintf(buf, "%i\n", stp_info.ctn); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); @@ -719,9 +743,13 @@ static ssize_t stp_dst_offset_show(struc struct device_attribute *attr, char *buf) { - if (!stp_online || !(stp_info.vbits & 0x2000)) - return -ENODATA; - return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid() && (stp_info.vbits & 0x2000)) + ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); @@ -730,9 +758,13 @@ static ssize_t stp_leap_seconds_show(str struct device_attribute *attr, char *buf) { - if (!stp_online || !(stp_info.vbits & 0x8000)) - return -ENODATA; - return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid() && (stp_info.vbits & 0x8000)) + ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); @@ -741,9 +773,13 @@ static ssize_t stp_stratum_show(struct d struct device_attribute *attr, char *buf) { - if (!stp_online) - return -ENODATA; - return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid()) + ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL); @@ -752,9 +788,13 @@ static ssize_t stp_time_offset_show(stru struct device_attribute *attr, char *buf) { - if (!stp_online || !(stp_info.vbits & 0x0800)) - return -ENODATA; - return sprintf(buf, "%i\n", (int) stp_info.tto); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid() && (stp_info.vbits & 0x0800)) + ret = sprintf(buf, "%i\n", (int) stp_info.tto); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL); @@ -763,9 +803,13 @@ static ssize_t stp_time_zone_offset_show struct device_attribute *attr, char *buf) { - if (!stp_online || !(stp_info.vbits & 0x4000)) - return -ENODATA; - return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid() && (stp_info.vbits & 0x4000)) + ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(time_zone_offset, 0400, @@ -775,9 +819,13 @@ static ssize_t stp_timing_mode_show(stru struct device_attribute *attr, char *buf) { - if (!stp_online) - return -ENODATA; - return sprintf(buf, "%i\n", stp_info.tmd); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid()) + ret = sprintf(buf, "%i\n", stp_info.tmd); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); @@ -786,9 +834,13 @@ static ssize_t stp_timing_state_show(str struct device_attribute *attr, char *buf) { - if (!stp_online) - return -ENODATA; - return sprintf(buf, "%i\n", stp_info.tst); + ssize_t ret = -ENODATA; + + mutex_lock(&stp_work_mutex); + if (stpinfo_valid()) + ret = sprintf(buf, "%i\n", stp_info.tst); + mutex_unlock(&stp_work_mutex); + return ret; } static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL);