lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.LNX.2.21.1801182000330.3@nippy.intranet>
Date:   Thu, 18 Jan 2018 20:35:03 +1100 (AEDT)
From:   Finn Thain <fthain@...egraphics.com.au>
To:     Arnd Bergmann <arnd@...db.de>
cc:     Adaptec OEM Raid Solutions <aacraid@...ptec.com>,
        "James E.J. Bottomley" <jejb@...ux.vnet.ibm.com>,
        "Martin K. Petersen" <martin.petersen@...cle.com>,
        Rasmus Villemoes <linux@...musvillemoes.dk>,
        Yang Hongyang <yanghy@...fujitsu.com>,
        Hannes Reinecke <hare@...e.de>,
        Mike Christie <michaelc@...wisc.edu>,
        Christoph Hellwig <hch@....de>, linux-scsi@...r.kernel.org,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH] [RESEND] scsi: ips: fix firmware timestamps for 32-bit

On Wed, 17 Jan 2018, Arnd Bergmann wrote:

> do_gettimeofday() is deprecated since it will stop working in 2038 on
> 32-bit platforms. The firmware interface here actually supports times
> until year 25500, so we should use longer timestamps.
> 

I think that reasoning is flawed. If the firmware supports large year 
values, then fine. The firmware interface is another story.

If you are simply trying to get rid of the old API, I think you should 
just say that.

> Using ktime_get_real_seconds() to get a 64-bit seconds value
> and time64_to_tm() to convert it into the right format also has
> the advantage of greatly simplifying the time management code.
> 
> Signed-off-by: Arnd Bergmann <arnd@...db.de>
> ---
> Submitted originally in November 2017. The aacraid@...ptec.com
> apparently bounced. Trying again now with a few people on Cc
> that previously reviewed patches to this driver.
> ---
>  drivers/scsi/ips.c | 78 +++++++++++-------------------------------------------
>  drivers/scsi/ips.h |  2 +-
>  2 files changed, 17 insertions(+), 63 deletions(-)
> 
> diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
> index 67621308eb9c..887843a465e1 100644
> --- a/drivers/scsi/ips.c
> +++ b/drivers/scsi/ips.c
> @@ -293,7 +293,7 @@ static void ips_freescb(ips_ha_t *, ips_scb_t *);
>  static void ips_setup_funclist(ips_ha_t *);
>  static void ips_statinit(ips_ha_t *);
>  static void ips_statinit_memio(ips_ha_t *);
> -static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
> +static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time64_t);
>  static void ips_ffdc_reset(ips_ha_t *, int);
>  static void ips_ffdc_time(ips_ha_t *);
>  static uint32_t ips_statupd_copperhead(ips_ha_t *);
> @@ -989,10 +989,7 @@ static int __ips_eh_reset(struct scsi_cmnd *SC)
>  
>  	/* FFDC */
>  	if (le32_to_cpu(ha->subsys->param[3]) & 0x300000) {
> -		struct timeval tv;
> -
> -		do_gettimeofday(&tv);
> -		ha->last_ffdc = tv.tv_sec;
> +		ha->last_ffdc = ktime_get_real_seconds();
>  		ha->reset_count++;
>  		ips_ffdc_reset(ha, IPS_INTR_IORL);
>  	}
> @@ -2396,7 +2393,6 @@ static int
>  ips_hainit(ips_ha_t * ha)
>  {
>  	int i;
> -	struct timeval tv;
>  
>  	METHOD_TRACE("ips_hainit", 1);
>  
> @@ -2411,8 +2407,7 @@ ips_hainit(ips_ha_t * ha)
>  
>  	/* Send FFDC */
>  	ha->reset_count = 1;
> -	do_gettimeofday(&tv);
> -	ha->last_ffdc = tv.tv_sec;
> +	ha->last_ffdc = ktime_get_real_seconds();
>  	ips_ffdc_reset(ha, IPS_INTR_IORL);
>  
>  	if (!ips_read_config(ha, IPS_INTR_IORL)) {
> @@ -2552,12 +2547,9 @@ ips_next(ips_ha_t * ha, int intr)
>  
>  	if ((ha->subsys->param[3] & 0x300000)
>  	    && (ha->scb_activelist.count == 0)) {
> -		struct timeval tv;
> -
> -		do_gettimeofday(&tv);
> -
> -		if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
> -			ha->last_ffdc = tv.tv_sec;
> +		time64_t now = ktime_get_real_seconds();
> +		if (now - ha->last_ffdc > IPS_SECS_8HOURS) {
> +			ha->last_ffdc = now;
>  			ips_ffdc_time(ha);
>  		}
>  	}
> @@ -5992,59 +5984,21 @@ ips_ffdc_time(ips_ha_t * ha)
>  /*                                                                          */
>  /****************************************************************************/
>  static void
> -ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time_t current_time)
> +ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time64_t current_time)

Does this conversion assume that current_time is always positive? I don't 
have a problem with that (the existing code seems to fail otherwise) but 
maybe it should be mentioned in the commit log.

>  {
> -	long days;
> -	long rem;
> -	int i;
> -	int year;
> -	int yleap;
> -	int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
> -	int month_lengths[12][2] = { {31, 31},
> -	{28, 29},
> -	{31, 31},
> -	{30, 30},
> -	{31, 31},
> -	{30, 30},
> -	{31, 31},
> -	{31, 31},
> -	{30, 30},
> -	{31, 31},
> -	{30, 30},
> -	{31, 31}
> -	};
> +	struct tm tm;
>  
>  	METHOD_TRACE("ips_fix_ffdc_time", 1);
>  
> -	days = current_time / IPS_SECS_DAY;
> -	rem = current_time % IPS_SECS_DAY;
> -
> -	scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
> -	rem = rem % IPS_SECS_HOUR;
> -	scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
> -	scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
> -
> -	year = IPS_EPOCH_YEAR;
> -	while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
> -		int newy;
> -
> -		newy = year + (days / IPS_DAYS_NORMAL_YEAR);
> -		if (days < 0)
> -			--newy;
> -		days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
> -		    IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
> -		    IPS_NUM_LEAP_YEARS_THROUGH(year - 1);

These IPS_ time macros are all unused after this patch except 
IPS_SECS_8HOURS so the definitions should probably be removed.

> -		year = newy;
> -	}
> -
> -	scb->cmd.ffdc.yearH = year / 100;
> -	scb->cmd.ffdc.yearL = year % 100;
> -
> -	for (i = 0; days >= month_lengths[i][yleap]; ++i)
> -		days -= month_lengths[i][yleap];
> +	time64_to_tm(current_time, 0, &tm);
>  
> -	scb->cmd.ffdc.month = i + 1;
> -	scb->cmd.ffdc.day = days + 1;
> +	scb->cmd.ffdc.hour   = tm.tm_hour;
> +	scb->cmd.ffdc.minute = tm.tm_min;
> +	scb->cmd.ffdc.second = tm.tm_sec;
> +	scb->cmd.ffdc.yearH  = tm.tm_year / 100 + 1900;

That looks wrong to me. If tm_year is in units of years not centuries, 
shouldn't that be,

	scb->cmd.ffdc.yearH  = tm.tm_year / 100 + 19;

-- 

> +	scb->cmd.ffdc.yearL  = tm.tm_year % 100;
> +	scb->cmd.ffdc.month  = tm.tm_mon + 1;
> +	scb->cmd.ffdc.day    = tm.tm_mday;
>  }
>  
>  /****************************************************************************
> diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
> index 366be3b2f9b4..b43a1ae75660 100644
> --- a/drivers/scsi/ips.h
> +++ b/drivers/scsi/ips.h
> @@ -1054,7 +1054,7 @@ typedef struct ips_ha {
>     uint8_t            active;
>     int                ioctl_reset;        /* IOCTL Requested Reset Flag */
>     uint16_t           reset_count;        /* number of resets           */
> -   time_t             last_ffdc;          /* last time we sent ffdc info*/
> +   time64_t           last_ffdc;          /* last time we sent ffdc info*/
>     uint8_t            slot_num;           /* PCI Slot Number            */
>     int                ioctl_len;          /* size of ioctl buffer       */
>     dma_addr_t         ioctl_busaddr;      /* dma address of ioctl buffer*/
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ