Re: [PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-08 Thread Andreas Dilger
On Nov 7, 2013, at 4:26 PM, David Turner  wrote:
> On Fri, 2013-11-08 at 00:14 +0100, Jan Kara wrote:
>> Still unnecessary type cast here (but that's a cosmetic issue).
> ...
>> Otherwise the patch looks good. You can add:
>> Reviewed-by: Jan Kara 
> 
> Thanks.  A version with this correction and the reviewed-by follows.

Thanks for working on this.  It was (seriously) in my list of things to
get done, but I figured I still had a few years to work on it...

My (unfinished) version of this patch had a nice comment at ext4_encode_time()
that explained the encoding that is being used very clearly:

/*
 * We need is an encoding that preserves the times for extra epoch "00":
 *
 * extra  msb of adjust for signed
 * epoch  32-bit 32-bit tv_sec to
 * bits   timedecoded 64-bit tv_sec  64-bit tv_sec  valid time range
 * 0 01-0x8000..-0x0001  0x0 1901-12-13..1969-12-31
 * 0 000x0..0x07fff  0x0 1970-01-01..2038-01-19
 * 0 110x08000..0x0  0x1 2038-01-19..2106-02-07
 * 0 100x1..0x17fff  0x1 2106-02-07..2174-02-25
 * 1 010x18000..0x1  0x2 2174-02-25..2242-03-16
 * 1 000x2..0x27fff  0x2 2242-03-16..2310-04-04
 * 1 110x28000..0x2  0x3 2310-04-04..2378-04-22
 * 1 100x3..0x37fff  0x3 2378-04-22..2446-05-10
 */

It seems that your version of the patch seems to use a different encoding.  Not
that this is a problem, per-se, since my patch wasn’t in use anywhere, but it
would be nice to have a similarly clear explanation of what the mapping is so
that it can be clearly understood.

My ext4_{encode,decode}_extra_time() used add/subtract instead of mask/OR ops,
which changed the on-disk format for times beyond 2038, but those were already
broken, and presumably not in use by anyone yet.  However, it seemed to me this
was easier to produce the correct results.  Have you tested your patch with
a variety of timestamps to verify its correctness?  It looks to me like you
have mapped the 1901-1969 range onto 0x3 for the epoch bits, instead of the
(IMHO) natural 0x0 bits. The critical time ranges are listed above.

Cheers, Andreas

> --
> In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
> the {a,c,m}time fields, deferring the year 2038 problem to the year
> 2446.  The representation (which this patch does not alter) is a bit
> hackish, in that the most-significant bit is no longer (alone)
> sufficient to indicate the sign.  That's because we're representing an
> asymmetric range, with seven times as many positive values as
> negative.
> 
> When decoding these extended fields, for times whose bottom 32 bits
> would represent a negative number, sign extension causes the 64-bit
> extended timestamp to be negative as well, which is not what's
> intended.  This patch corrects that issue, so that the only negative
> {a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
> timestamps).
> 
> Signed-off-by: David Turner 
> Reported-by: Mark Harris 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
> Reviewed-by: Jan Kara 
> ---
> fs/ext4/ext4.h | 13 +
> 1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index af815ea..3c2d0b3 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -722,10 +722,15 @@ static inline __le32 ext4_encode_extra_time(struct 
> timespec *time)
> 
> static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
> {
> -   if (sizeof(time->tv_sec) > 4)
> -time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
> -<< 32;
> -   time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 
> EXT4_EPOCH_BITS;
> + if (sizeof(time->tv_sec) > 4) {
> + u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
> + if (time->tv_sec > 0 || extra_bits != EXT4_EPOCH_MASK) {
> + time->tv_sec &= 0x;
> + time->tv_sec |= extra_bits << 32;
> + }
> + }
> + time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >>
> + EXT4_EPOCH_BITS;
> }
> 
> #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)\
> -- 
> 1.8.1.2
> 
> 
> 


Cheers, Andreas





--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-08 Thread Andreas Dilger
On Nov 7, 2013, at 4:26 PM, David Turner nova...@novalis.org wrote:
 On Fri, 2013-11-08 at 00:14 +0100, Jan Kara wrote:
 Still unnecessary type cast here (but that's a cosmetic issue).
 ...
 Otherwise the patch looks good. You can add:
 Reviewed-by: Jan Kara j...@suse.cz
 
 Thanks.  A version with this correction and the reviewed-by follows.

Thanks for working on this.  It was (seriously) in my list of things to
get done, but I figured I still had a few years to work on it...

My (unfinished) version of this patch had a nice comment at ext4_encode_time()
that explained the encoding that is being used very clearly:

/*
 * We need is an encoding that preserves the times for extra epoch 00:
 *
 * extra  msb of adjust for signed
 * epoch  32-bit 32-bit tv_sec to
 * bits   timedecoded 64-bit tv_sec  64-bit tv_sec  valid time range
 * 0 01-0x8000..-0x0001  0x0 1901-12-13..1969-12-31
 * 0 000x0..0x07fff  0x0 1970-01-01..2038-01-19
 * 0 110x08000..0x0  0x1 2038-01-19..2106-02-07
 * 0 100x1..0x17fff  0x1 2106-02-07..2174-02-25
 * 1 010x18000..0x1  0x2 2174-02-25..2242-03-16
 * 1 000x2..0x27fff  0x2 2242-03-16..2310-04-04
 * 1 110x28000..0x2  0x3 2310-04-04..2378-04-22
 * 1 100x3..0x37fff  0x3 2378-04-22..2446-05-10
 */

It seems that your version of the patch seems to use a different encoding.  Not
that this is a problem, per-se, since my patch wasn’t in use anywhere, but it
would be nice to have a similarly clear explanation of what the mapping is so
that it can be clearly understood.

My ext4_{encode,decode}_extra_time() used add/subtract instead of mask/OR ops,
which changed the on-disk format for times beyond 2038, but those were already
broken, and presumably not in use by anyone yet.  However, it seemed to me this
was easier to produce the correct results.  Have you tested your patch with
a variety of timestamps to verify its correctness?  It looks to me like you
have mapped the 1901-1969 range onto 0x3 for the epoch bits, instead of the
(IMHO) natural 0x0 bits. The critical time ranges are listed above.

Cheers, Andreas

 --
 In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
 the {a,c,m}time fields, deferring the year 2038 problem to the year
 2446.  The representation (which this patch does not alter) is a bit
 hackish, in that the most-significant bit is no longer (alone)
 sufficient to indicate the sign.  That's because we're representing an
 asymmetric range, with seven times as many positive values as
 negative.
 
 When decoding these extended fields, for times whose bottom 32 bits
 would represent a negative number, sign extension causes the 64-bit
 extended timestamp to be negative as well, which is not what's
 intended.  This patch corrects that issue, so that the only negative
 {a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
 timestamps).
 
 Signed-off-by: David Turner nova...@novalis.org
 Reported-by: Mark Harris mh8...@yahoo.com
 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
 Reviewed-by: Jan Kara j...@suse.cz
 ---
 fs/ext4/ext4.h | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)
 
 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
 index af815ea..3c2d0b3 100644
 --- a/fs/ext4/ext4.h
 +++ b/fs/ext4/ext4.h
 @@ -722,10 +722,15 @@ static inline __le32 ext4_encode_extra_time(struct 
 timespec *time)
 
 static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
 {
 -   if (sizeof(time-tv_sec)  4)
 -time-tv_sec |= (__u64)(le32_to_cpu(extra)  EXT4_EPOCH_MASK)
 - 32;
 -   time-tv_nsec = (le32_to_cpu(extra)  EXT4_NSEC_MASK)  
 EXT4_EPOCH_BITS;
 + if (sizeof(time-tv_sec)  4) {
 + u64 extra_bits = le32_to_cpu(extra)  EXT4_EPOCH_MASK;
 + if (time-tv_sec  0 || extra_bits != EXT4_EPOCH_MASK) {
 + time-tv_sec = 0x;
 + time-tv_sec |= extra_bits  32;
 + }
 + }
 + time-tv_nsec = (le32_to_cpu(extra)  EXT4_NSEC_MASK) 
 + EXT4_EPOCH_BITS;
 }
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)\
 -- 
 1.8.1.2
 
 
 


Cheers, Andreas





--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-07 Thread Theodore Ts'o
On Thu, Nov 07, 2013 at 06:26:47PM -0500, David Turner wrote:
> In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
> the {a,c,m}time fields, deferring the year 2038 problem to the year
> 2446.  The representation (which this patch does not alter) is a bit
> hackish, in that the most-significant bit is no longer (alone)
> sufficient to indicate the sign.  That's because we're representing an
> asymmetric range, with seven times as many positive values as
> negative.
> 
> When decoding these extended fields, for times whose bottom 32 bits
> would represent a negative number, sign extension causes the 64-bit
> extended timestamp to be negative as well, which is not what's
> intended.  This patch corrects that issue, so that the only negative
> {a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
> timestamps).
> 
> Signed-off-by: David Turner 
> Reported-by: Mark Harris 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
> Reviewed-by: Jan Kara 

Thanks, applied.

- Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-07 Thread David Turner
On Fri, 2013-11-08 at 00:14 +0100, Jan Kara wrote:
> Still unnecessary type cast here (but that's a cosmetic issue).
...
> Otherwise the patch looks good. You can add:
> Reviewed-by: Jan Kara 

Thanks.  A version with this correction and the reviewed-by follows.

--
In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
the {a,c,m}time fields, deferring the year 2038 problem to the year
2446.  The representation (which this patch does not alter) is a bit
hackish, in that the most-significant bit is no longer (alone)
sufficient to indicate the sign.  That's because we're representing an
asymmetric range, with seven times as many positive values as
negative.

When decoding these extended fields, for times whose bottom 32 bits
would represent a negative number, sign extension causes the 64-bit
extended timestamp to be negative as well, which is not what's
intended.  This patch corrects that issue, so that the only negative
{a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
timestamps).

Signed-off-by: David Turner 
Reported-by: Mark Harris 
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
Reviewed-by: Jan Kara 
---
 fs/ext4/ext4.h | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index af815ea..3c2d0b3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -722,10 +722,15 @@ static inline __le32 ext4_encode_extra_time(struct 
timespec *time)
 
 static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
 {
-   if (sizeof(time->tv_sec) > 4)
-  time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
-  << 32;
-   time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 
EXT4_EPOCH_BITS;
+   if (sizeof(time->tv_sec) > 4) {
+   u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
+   if (time->tv_sec > 0 || extra_bits != EXT4_EPOCH_MASK) {
+   time->tv_sec &= 0x;
+   time->tv_sec |= extra_bits << 32;
+   }
+   }
+   time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >>
+   EXT4_EPOCH_BITS;
 }
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
-- 
1.8.1.2



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-07 Thread David Turner
On Fri, 2013-11-08 at 00:14 +0100, Jan Kara wrote:
 Still unnecessary type cast here (but that's a cosmetic issue).
...
 Otherwise the patch looks good. You can add:
 Reviewed-by: Jan Kara j...@suse.cz

Thanks.  A version with this correction and the reviewed-by follows.

--
In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
the {a,c,m}time fields, deferring the year 2038 problem to the year
2446.  The representation (which this patch does not alter) is a bit
hackish, in that the most-significant bit is no longer (alone)
sufficient to indicate the sign.  That's because we're representing an
asymmetric range, with seven times as many positive values as
negative.

When decoding these extended fields, for times whose bottom 32 bits
would represent a negative number, sign extension causes the 64-bit
extended timestamp to be negative as well, which is not what's
intended.  This patch corrects that issue, so that the only negative
{a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
timestamps).

Signed-off-by: David Turner nova...@novalis.org
Reported-by: Mark Harris mh8...@yahoo.com
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
Reviewed-by: Jan Kara j...@suse.cz
---
 fs/ext4/ext4.h | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index af815ea..3c2d0b3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -722,10 +722,15 @@ static inline __le32 ext4_encode_extra_time(struct 
timespec *time)
 
 static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
 {
-   if (sizeof(time-tv_sec)  4)
-  time-tv_sec |= (__u64)(le32_to_cpu(extra)  EXT4_EPOCH_MASK)
-   32;
-   time-tv_nsec = (le32_to_cpu(extra)  EXT4_NSEC_MASK)  
EXT4_EPOCH_BITS;
+   if (sizeof(time-tv_sec)  4) {
+   u64 extra_bits = le32_to_cpu(extra)  EXT4_EPOCH_MASK;
+   if (time-tv_sec  0 || extra_bits != EXT4_EPOCH_MASK) {
+   time-tv_sec = 0x;
+   time-tv_sec |= extra_bits  32;
+   }
+   }
+   time-tv_nsec = (le32_to_cpu(extra)  EXT4_NSEC_MASK) 
+   EXT4_EPOCH_BITS;
 }
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
-- 
1.8.1.2



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3] ext4: Fix reading of extended tv_sec (bug 23732)

2013-11-07 Thread Theodore Ts'o
On Thu, Nov 07, 2013 at 06:26:47PM -0500, David Turner wrote:
 In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
 the {a,c,m}time fields, deferring the year 2038 problem to the year
 2446.  The representation (which this patch does not alter) is a bit
 hackish, in that the most-significant bit is no longer (alone)
 sufficient to indicate the sign.  That's because we're representing an
 asymmetric range, with seven times as many positive values as
 negative.
 
 When decoding these extended fields, for times whose bottom 32 bits
 would represent a negative number, sign extension causes the 64-bit
 extended timestamp to be negative as well, which is not what's
 intended.  This patch corrects that issue, so that the only negative
 {a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
 timestamps).
 
 Signed-off-by: David Turner nova...@novalis.org
 Reported-by: Mark Harris mh8...@yahoo.com
 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
 Reviewed-by: Jan Kara j...@suse.cz

Thanks, applied.

- Ted
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/