Re: [PATCH] debugfs: add support to properly set and display extended timestamps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2013-12-09 at 14:14 -0500, Theodore Ts'o wrote:
> In order to properly test the changes for extended timestamps, I
> extracted portions of David Turner's patches to e2fsprogs, so we could
> have a single commit which only adds the extended timestamps to e2fsprogs.
> 
> I moved things around a bit, to avoid the new header file
> lib/extract_epoch.h with only two lines.  I also added proper support
> to parse_time so that you can now have commands such as:
> 
> debugfs: set_inode_file /test ctime_lo 0x10203040
> debugfs: set_inode_file /test ctime_hi 3
> debugfs: set_inode_file /test ctime 205012143045
> debugfs: set_inode_file /test ctime @4386555179
> 
> David, let me know what you think.  

I have a few minor comments inline, but otherwise this patch looks
fine.  

> One thing which I'm still thinking
> about adding is support encoding and decoding for the older style
> encoding for pre-1970 dates, so we can properly test the e2fsck and
> kernel patches.  What I'm still thinking about is what's the best way
> to toggle between the legacy and new encoding for pre-1970 dates.

We can encode pre-1970 dates manually with 'set_inode_file /test
ctime_hi 3'.  I don't see a strong reason to have a special case to
decode these dates, because e2fsck is going to correct them anyway.

>    	  	      	     	     	      - Ted
> 
> commit 05c2f96e19b6a7b769369f11538a0f93adf747a5
> Author: Theodore Ts'o <tytso@xxxxxxx>
> Date:   Mon Dec 9 13:55:23 2013 -0500
> 
>     debugfs: add support to properly set and display extended timestamps
>     
>     This code is partially derived from patches from David Turner to allow
>     debugfs to properly support extended timestamps.
>     
>     Cc: David Turner <novalis@xxxxxxxxxxx>
>     Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx>
> 
> diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
> index 902ee66..7746629 100644
> --- a/debugfs/debugfs.c
> +++ b/debugfs/debugfs.c
> @@ -793,27 +793,37 @@ void internal_dump_inode(FILE *out, const char *prefix,
>  	if (is_large_inode && large_inode->i_extra_isize >= 24) {
>  		fprintf(out, "%s ctime: 0x%08x:%08x -- %s", prefix,
>  			inode->i_ctime, large_inode->i_ctime_extra,
> -			time_to_string(inode->i_ctime));
> +			inode_time_to_string(inode->i_ctime,
> +					     large_inode->i_ctime_extra));
>  		fprintf(out, "%s atime: 0x%08x:%08x -- %s", prefix,
>  			inode->i_atime, large_inode->i_atime_extra,
> -			time_to_string(inode->i_atime));
> +			inode_time_to_string(inode->i_atime,
> +					     large_inode->i_atime_extra));
>  		fprintf(out, "%s mtime: 0x%08x:%08x -- %s", prefix,
>  			inode->i_mtime, large_inode->i_mtime_extra,
> -			time_to_string(inode->i_mtime));
> +			inode_time_to_string(inode->i_mtime,
> +					     large_inode->i_mtime_extra));
>  		fprintf(out, "%scrtime: 0x%08x:%08x -- %s", prefix,
>  			large_inode->i_crtime, large_inode->i_crtime_extra,
> -			time_to_string(large_inode->i_crtime));
> +			inode_time_to_string(large_inode->i_crtime,
> +					     large_inode->i_crtime_extra));
> +		if (inode->i_dtime)
> +			fprintf(out, "%scrtime: 0x%08x:(%08x) -- %s", prefix,
> +				large_inode->i_dtime, large_inode->i_ctime_extra,
> +				inode_time_to_string(inode->i_dtime,
> +						     large_inode->i_ctime_extra));
>  	} else {
>  		fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime,
> -			time_to_string(inode->i_ctime));
> +			time_to_string((__s32) inode->i_ctime));
>  		fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime,
> -			time_to_string(inode->i_atime));
> +			time_to_string((__s32) inode->i_atime));
>  		fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime,
> -			time_to_string(inode->i_mtime));
> +			time_to_string((__s32) inode->i_mtime));
> +		if (inode->i_dtime)
> +			fprintf(out, "%sdtime: 0x%08x -- %s", prefix,
> +				inode->i_dtime,
> +				time_to_string((__s32) inode->i_dtime));
>  	}
> -	if (inode->i_dtime)
> -	  fprintf(out, "%sdtime: 0x%08x -- %s", prefix, inode->i_dtime,
> -		  time_to_string(inode->i_dtime));
>  	if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
>  		internal_dump_inode_extra(out, prefix, inode_num,
>  					  (struct ext2_inode_large *) inode);
> @@ -2149,7 +2159,7 @@ void do_set_current_time(int argc, char *argv[])
>  		return;
>  
>  	now = string_to_time(argv[1]);
> -	if (now == ((time_t) -1)) {
> +	if (now == -1) {
>  		com_err(argv[0], 0, "Couldn't parse argument as a time: %s\n",
>  			argv[1]);
>  		return;
> diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
> index 45175cf..32d32cc 100644
> --- a/debugfs/debugfs.h
> +++ b/debugfs/debugfs.h
> @@ -33,8 +33,9 @@ extern int check_fs_not_open(char *name);
>  extern int check_fs_read_write(char *name);
>  extern int check_fs_bitmaps(char *name);
>  extern ext2_ino_t string_to_inode(char *str);
> -extern char *time_to_string(__u32);
> -extern time_t string_to_time(const char *);
> +extern char *inode_time_to_string(__u32 xtime, __u32 xtime_extra);
> +extern char *time_to_string(__s64);
> +extern __s64 string_to_time(const char *);
>  extern unsigned long parse_ulong(const char *str, const char *cmd,
>  				 const char *descr, int *err);
>  extern unsigned long long parse_ulonglong(const char *str, const char *cmd,
> diff --git a/debugfs/lsdel.c b/debugfs/lsdel.c
> index bed0ce6..da2ad11 100644
> --- a/debugfs/lsdel.c
> +++ b/debugfs/lsdel.c
> @@ -166,7 +166,7 @@ void do_lsdel(int argc, char **argv)
>  			delarray[num_delarray].mode = inode.i_mode;
>  			delarray[num_delarray].uid = inode_uid(inode);
>  			delarray[num_delarray].size = EXT2_I_SIZE(&inode);
> -			delarray[num_delarray].dtime = inode.i_dtime;
> +			delarray[num_delarray].dtime = (__s32) inode.i_dtime;
>  			delarray[num_delarray].num_blocks = lsd.num_blocks;
>  			delarray[num_delarray].free_blocks = lsd.free_blocks;
>  			num_delarray++;
> diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
> index b09e2f8..1cffeca 100644
> --- a/debugfs/set_fields.c
> +++ b/debugfs/set_fields.c
> @@ -160,10 +160,14 @@ static struct field_set_info inode_fields[] = {
>  	{ "uid", &set_inode.i_uid, &set_inode.osd2.linux2.l_i_uid_high,
>  		2, parse_uint },
>  	{ "size", &set_inode.i_size, &set_inode.i_size_high, 4, parse_uint },
> -	{ "atime", &set_inode.i_atime, NULL, 4, parse_time },
> -	{ "ctime", &set_inode.i_ctime, NULL, 4, parse_time },
> -	{ "mtime", &set_inode.i_mtime, NULL, 4, parse_time },
> -	{ "dtime", &set_inode.i_dtime, NULL, 4, parse_time },
> +	{ "atime", &set_inode.i_atime, &set_inode.i_atime_extra,
> +		4, parse_time },
> +	{ "ctime", &set_inode.i_ctime, &set_inode.i_ctime_extra,
> +		4, parse_time },
> +	{ "mtime", &set_inode.i_mtime, &set_inode.i_mtime_extra,
> +		4, parse_time },
> +	{ "dtime", &set_inode.i_dtime, &set_inode.i_ctime_extra,
> +		4, parse_time },
>  	{ "gid", &set_inode.i_gid, &set_inode.osd2.linux2.l_i_gid_high,
>  		2, parse_uint },
>  	{ "links_count", &set_inode.i_links_count, NULL, 2, parse_uint },
> @@ -199,7 +203,8 @@ static struct field_set_info inode_fields[] = {
>  		4, parse_uint },
>  	{ "atime_extra", &set_inode.i_atime_extra, NULL,
>  		4, parse_uint },
> -	{ "crtime", &set_inode.i_crtime, NULL, 4, parse_uint },
> +	{ "crtime", &set_inode.i_crtime, &set_inode.i_crtime_extra,
> +		4, parse_time },
>  	{ "crtime_extra", &set_inode.i_crtime_extra, NULL,
>  		4, parse_uint },
>  	{ "bmap", NULL, NULL, 4, parse_bmap, FLAG_ARRAY },
> @@ -474,21 +479,31 @@ static errcode_t parse_string(struct field_set_info *info,
>  }
>  
>  static errcode_t parse_time(struct field_set_info *info,
> -			    char *field EXT2FS_ATTR((unused)), char *arg)
> +			    char *field, char *arg)
>  {
> -	time_t		t;
> -	__u32		*ptr32;
> +	__s64		t;
> +	__u32		t_low, t_high;
> +	__u32		*ptr_low, *ptr_high;
> +	int		suffix = check_suffix(field);

This variable is never used.

> +	if (check_suffix(field))
> +		return parse_uint(info, field, arg);
>  
> -	ptr32 = (__u32 *) info->ptr;
> +	ptr_low  = (__u32 *) info->ptr;
> +	ptr_high = (__u32 *) info->ptr2;
>  
>  	t = string_to_time(arg);
>  
> -	if (t == ((time_t) -1)) {
> +	if (t == -1) {

-1 looks like the wrong sentinel to me, because it is a perfectly valid
time (Dec 31, 1969 23:59:59 GMT).

>  		fprintf(stderr, "Couldn't parse '%s' for field %s.\n",
>  			arg, info->name);
>  		return EINVAL;
>  	}
> -	*ptr32 = t;
> +	t_low = (__u32) t;
> +	t_high = ((t - (__s32)t) >> 32) & EXT4_EPOCH_MASK;
> +	*ptr_low = t_low;
> +	if (ptr_high)
> +		*ptr_high = (*ptr_high & ~EXT4_EPOCH_MASK) | t_high;
>  	return 0;
>  }
>  
> diff --git a/debugfs/util.c b/debugfs/util.c
> index cf3a6c6..4a0abd8 100644
> --- a/debugfs/util.c
> +++ b/debugfs/util.c
> @@ -186,11 +186,19 @@ int check_fs_bitmaps(char *name)
>  	return 0;
>  }
>  
> +char *inode_time_to_string(__u32 xtime, __u32 xtime_extra)
> +{
> +	__s64 t = (__s32) xtime;
> +
> +	t += (__s64) (xtime_extra & EXT4_EPOCH_MASK) << 32;
> +	return time_to_string(t);
> +}
> +
>  /*
> - * This function takes a __u32 time value and converts it to a string,
> + * This function takes a __s64 time value and converts it to a string,
>   * using ctime

asctime, not ctime

>   */
> -char *time_to_string(__u32 cl)
> +char *time_to_string(__s64 cl)
>  {
>  	static int	do_gmt = -1;
>  	time_t		t = (time_t) cl;
> @@ -211,10 +219,10 @@ char *time_to_string(__u32 cl)
>   * Parse a string as a time.  Return ((time_t)-1) if the string
>   * doesn't appear to be a sane time.
>   */
> -extern time_t string_to_time(const char *arg)
> +extern __s64 string_to_time(const char *arg)
>  {
>  	struct	tm	ts;
> -	time_t		ret;
> +	__s64		ret;
>  	char *tmp;
>  
>  	if (strcmp(arg, "now") == 0) {
> @@ -222,9 +230,9 @@ extern time_t string_to_time(const char *arg)
>  	}
>  	if (arg[0] == '@') {
>  		/* interpret it as an integer */
> -		ret = strtoul(arg+1, &tmp, 0);
> +		ret = strtoll(arg+1, &tmp, 0);
>  		if (*tmp)
> -			return ((time_t) -1);
> +			return -1;
>  		return ret;
>  	}
>  	memset(&ts, 0, sizeof(ts));
> @@ -244,9 +252,9 @@ extern time_t string_to_time(const char *arg)
>  	ret = mktime(&ts);
>  	if (ts.tm_mday == 0 || ret == ((time_t) -1)) {
>  		/* Try it as an integer... */
> -		ret = strtoul(arg, &tmp, 0);
> +		ret = strtoll(arg, &tmp, 0);
>  		if (*tmp)
> -			return ((time_t) -1);
> +			return -1;
>  	}
>  	return ret;
>  }
> diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
> index fb3f7cc..fb10e7f 100644
> --- a/lib/ext2fs/ext2_fs.h
> +++ b/lib/ext2fs/ext2_fs.h
> @@ -809,6 +809,13 @@ struct ext2_dir_entry_2 {
>  					 ~EXT2_DIR_ROUND)
>  
>  /*
> + * Constants for ext4's extended time encoding
> + */
> +#define EXT4_EPOCH_BITS 2
> +#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
> +#define EXT4_NSEC_MASK  (~0UL << EXT4_EPOCH_BITS)

EXT4_NSEC_MASK is never used

> +/*
>   * This structure is used for multiple mount protection. It is written
>   * into the block number saved in the s_mmp_block field in the superblock.
>   * Programs that check MMP should assume that if SEQ_FSCK (or any unknown


--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux