Skip to contentSkip to conversation

ext4: add EXT4_IOC_GETCRTIME ioctl

PATCH Applied Li Zefan 3 participants 6 messages Aug 6, 2008 – Aug 18, 2008 ext4 file system

lore
Share & tools
lore

Li Zefan

author
#0 lore raw

PATCH 1/3 ext4: add EXT4_IOC_GETCRTIME ioctl

Add EXT4_IOC_GETCRTIME ioctl, and then we can use it in e2fsprogs.

---
 fs/ext4/ext4.h  |    1 +
 fs/ext4/ioctl.c |    3 +++
 2 files changed, 4 insertions(+), 0 deletions(-)
fs/ext4/ext4.h +1 -0
index 303e41c..a487f2f 100644
@@ -295,6 +295,7 @@ struct ext4_new_group_data {
 #define EXT4_IOC_GROUP_ADD		_IOW('f', 8,struct ext4_new_group_input)
 #define	EXT4_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
 #define	EXT4_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
+#define	EXT4_IOC_GETCRTIME		_IOR('f', 9, struct timespec)
 #ifdef CONFIG_JBD2_DEBUG
 #define EXT4_IOC_WAIT_FOR_READONLY	_IOR('f', 99, long)
 #endif
fs/ext4/ioctl.c +3 -0
index 7a6c2f1..6204b5d 100644
@@ -269,6 +269,9 @@ setversion_out:
 	case EXT4_IOC_MIGRATE:
 		return ext4_ext_migrate(inode, filp, cmd, arg);
 
+	case EXT4_IOC_GETCRTIME:
+		return put_user(ei->i_crtime, (struct timespec __user *)arg);
+
 	default:
 		return -ENOTTY;
 	}
Signature · 1 line
1.5.4.rc3
maintainer
#1 lore raw

fs/ext4/ioctl.c setversion_out: · line 274

Quoted 3 lines · Li Zefan
fs/ext4/ioctl.c +3 -0
+	case EXT4_IOC_GETCRTIME:
+		return put_user(ei->i_crtime, (struct timespec __user *)arg);
+

I'm worried about writing a struct timespec directly to user space, because the kernel's idea of what is struct timespec might not be the same as the userspace's understanding of struct timespec --- specifically, because of the question of the width of time_t might be different in the kernel and in userspace on different architectures.

I think we would be better off explicitly defining a structure, or just returning the seconds and nanoseconds in explicit primitive types.

Regards,

- Ted

author
#2 lore raw

(sorry for the so dealyed reply, I was offline last week.)

Quoted 8 lines · Theodore Tso

fs/ext4/ioctl.c setversion_out: · line 274

Quoted 3 lines · Li Zefan
fs/ext4/ioctl.c +3 -0
+	case EXT4_IOC_GETCRTIME:
+		return put_user(ei->i_crtime, (struct timespec __user *)arg);
+

I'm worried about writing a struct timespec directly to user space, because the kernel's idea of what is struct timespec might not be the same as the userspace's understanding of struct timespec ---

We have system call nanosleep(), which copies a struct timespec directly from user space.

Quoted 3 lines

specifically, because of the question of the width of time_t might be different in the kernel and in userspace on different architectures.

But timeval.tv_sec is also of type time_t. Also sys_time() writes a time_t directry to user space.

I should not use put_user() though...

+ return copy_to_user((struct timespec __user *)arg,
+ &ei->i_crtime, sizeof(ei->i_crtime));

Quoted 4 lines

I think we would be better off explicitly defining a structure, or just returning the seconds and nanoseconds in explicit primitive types.

maintainer
#3 lore raw
Quoted 7 lines · Li Zefan
Quoted 4 lines

I'm worried about writing a struct timespec directly to user space, because the kernel's idea of what is struct timespec might not be the same as the userspace's understanding of struct timespec ---

We have system call nanosleep(), which copies a struct timespec directly from user space.

The difference is that for system calls, we have a glue layer (glibc) whose duties include translating between the kernel data structures and the userpsace data structures --- and for various architectures there are ***no*** guarantees that the interfaces shipped by glibc in /usr/include match up with the data structures used by the kernel in /usr/src/linux/include/linux.

When you use an ioctl, you bypass the glibc translation layer, so life can get iffy here. And given that struct timespec contains time_t, which *can* differ from architecture to architecure in in terms of being either 32 bits or 64 bits, and what is in the kernel might be different from what is in the user space /usr/include, I get doubly nervous.

Quoted 3 lines
Quoted 3 lines

I think we would be better off explicitly defining a structure, or just returning the seconds and nanoseconds in explicit primitive types.

That's the quick and dirty fast answer, yes. The long-term (but one which involves much more work) is to define a new struct kernel<->glibc stat interface (we already have 5 or so :-) to extend it include st_crtime, and then try to get glibc to use the magic of ELF symbol versioning so there is a new struct stat as defined in /usr/include, and a new stat(2) call defined in glibc, which returns the new struct stat which include st_crtime. This also means we have to define proper semantics for what happens if a filesystem doesn't support st_crtime.

- Ted

#4 lore raw
Quoted 9 lines · Theodore Ts'o

That's the quick and dirty fast answer, yes. The long-term (but one which involves much more work) is to define a new struct kernel<->glibc stat interface (we already have 5 or so :-) to extend it include st_crtime, and then try to get glibc to use the magic of ELF symbol versioning so there is a new struct stat as defined in /usr/include, and a new stat(2) call defined in glibc, which returns the new struct stat which include st_crtime. This also means we have to define proper semantics for what happens if a filesystem doesn't support st_crtime.

In the meantime, I'd think it preferable to use a virtual-xattr to get this information from the kernel instead of an ioctl. That way a shell script can extract it with getfattr, and it is no harder to do from a C program using getxattr().

I'd propose something like "system.creation_time" for the xattr name, but I'll leave it up to people who care to propose better names.

Cheers, Andreas
--
Andreas Dilger
Sr. Staff Engineer, Lustre Group
Sun Microsystems of Canada, Inc.

author
#5 lore raw
In reply to Theodore Tso
Quoted 14 lines · Theodore Tso
Quoted 5 lines · Li Zefan
Quoted 3 lines

I'm worried about writing a struct timespec directly to user space, because the kernel's idea of what is struct timespec might not be the same as the userspace's understanding of struct timespec ---

We have system call nanosleep(), which copies a struct timespec directly from user space.

The difference is that for system calls, we have a glue layer (glibc) whose duties include translating between the kernel data structures and the userpsace data structures --- and for various architectures there are ***no*** guarantees that the interfaces shipped by glibc in /usr/include match up with the data structures used by the kernel in /usr/src/linux/include/linux.

Quoted 7 lines

When you use an ioctl, you bypass the glibc translation layer, so life can get iffy here. And given that struct timespec contains time_t, which *can* differ from architecture to architecure in in terms of being either 32 bits or 64 bits, and what is in the kernel might be different from what is in the user space /usr/include, I get doubly nervous.

I got the point, thanks. :)

Quoted 4 lines
Quoted 3 lines
Quoted 3 lines

I think we would be better off explicitly defining a structure, or just returning the seconds and nanoseconds in explicit primitive types.

Quoted 10 lines

That's the quick and dirty fast answer, yes. The long-term (but one which involves much more work) is to define a new struct kernel<->glibc stat interface (we already have 5 or so :-) to extend it include st_crtime, and then try to get glibc to use the magic of ELF symbol versioning so there is a new struct stat as defined in /usr/include, and a new stat(2) call defined in glibc, which returns the new struct stat which include st_crtime. This also means we have to define proper semantics for what happens if a filesystem doesn't support st_crtime.

Yes, my first thought was if stat can report crtime.

So, for now I think we can use timespec_to_ns() to convert the time to a s64 value and return it to the userspace.