futimens and utimensat vs birthtime (resurected)
Julian Elischer
julian at freebsd.org
Tue Nov 10 05:38:52 UTC 2015
On 11/10/15 3:09 AM, John Baldwin wrote:
> On Monday, November 09, 2015 11:16:18 AM Julian Elischer wrote:
>> On 8/15/15 5:22 AM, Kirk McKusick wrote:
>>>> From: John Baldwin <jhb at freebsd.org>
>>>> To: freebsd-current at freebsd.org
>>>> Subject: Re: futimens and utimensat vs birthtime
>>>> Date: Fri, 14 Aug 2015 10:39:41 -0700
>>>> Cc: "freebsd-fs at freebsd.org" <freebsd-fs at freebsd.org>,
>>>> "'Jilles Tjoelker'" <jilles at stack.nl>
>>>>
>>>> On Friday, August 14, 2015 10:46:10 PM Julian Elischer wrote:
>>>>> I would like to implement this call. but would like input as to it's
>>>>> nature.
>>>>> The code inside the system would already appear to support handling
>>>>> three elements, though it needs some scrutiny,
>>>>> so all that is needed is a system call with the ability to set the
>>>>> birthtime directly.
>>>>>
>>>>> Whether it should take the form of the existing calls but expecting
>>>>> three items is up for discussion.
>>>>> Maybe teh addition of a flags argument to specify which items are
>>>>> present and which to set.
>>>>>
>>>>> ideas?
>>>> I believe these should be new calls. Only utimensat() provides a flag
>>>> argument, but it is reserved for AT_* flags. I would be fine with
>>>> something like futimens3() and utimensat3() (where 3 means "three
>>>> timespecs"). Jilles implemented futimens() and utimensat(), so he
>>>> might have ideas as well. I would probably stick the birth time in
>>>> the third (final) timespec slot to make it easier to update new code
>>>> (you can use an #ifdef just around ts[2] without having to #ifdef the
>>>> entire block).
>>>>
>>> I concur with John's suggestion. Add a new system call with three
>>> argument set of times specifying birthtime as the last one. I
>>> proposed doing this when I added birthtime, but did not as the
>>> sentiment at the time was that it would gratuitously make FreeBSD
>>> written applications less portable if they used this new non-standard
>>> system call.
>> time has passed and I would like to get back to this:
>> There was some feedback last time. Taking that into account:
>>
>> One problem with the '3 arg' version is that we have to reinvent it
>> again if we get a 4th.
>> We could make something like the following:
>>
>> It has been suggested that a 4th entry might be "last archive time"
>> and that
>> "time created on this filesystem" and "file created first time (ever)"
>> might also
>> be separate in some systems. (as examples of why 3 might not be enough)
>>
>> the syscall name is also not decided.
>> one suggested form is:
>> $name (int fd, int32 flags/mask, const struct timespec *arrayptr[]);
>>
>> vs the current:
>> utimensat(int fd, const char *path, const struct timespec times[2],
>> int flag);
>>
>> where mask is:
>> ---
>> 0x01 disable_heuristic
>> 0x02 AT_SYMLINK_NOFOLLOW
>> 0x04-0x08 unused
>> -- times present---
>> 0x10 access time
>> 0x20 mod time
>> 0x40 birth time
>> 0x80 archive time
>> 0x100 conception time
>> 0x200-on reserverd for future times
>>
>> any bit not set in 0x010-on is not represented in the array.
>> no bits would be a nop (the price for orthogonality) and would
>> effectively be the same as a test for writeability.
>> "disable heuristic" would disable the forcing of birthtime back to mod
>> time or earlier (and any other 'logical fixes')
>> setting all 5 'time-present' bits would imply the array has 5 entries.
>>
>> anyone care to comment
> I think the mask is overly complex. utimensat() already has UTIME_OMIT.
> I think you should just have a new 'count' argument and use UTIME_OMIT
> when you wish to leave a timestamp alone:
>
> futimens3(int fd, const struct timespec *times, int ntimes);
> utimensat5(int fd, const char *path, const struct timespec *ntimes,
> int ntimes, int flag);
>
> ntimes defines how many valid timespecs are in the times[] array. If
> you pass in fewer entries than is required, any missing entries at the
> end are treated as if they were set to UTIME_OMIT (so not modified).
> The new versions would not set birthtime implicitly. For now I would
> simply define birthtime as times[2]. One curious idea is if you wanted
> to permit setting the change time (right now ctime is implicitly updated
> to "now" when you set the time). I think you probably don't want to
> allow that.
>
> The only other thing you might consider is adding constants for the
> array indices which might help with portability if other systems adopt
> this interface:
>
> #define TIMENS_ACCESS 0
> #define TIMENS_MODIFICATION 1
> #define TIMENS_BIRTH 2
> #define TIMENS_MAX TIMENS_BIRTH
>
> This would let you do things like in portable-ish code (if the
> interface itself is more widely adopted) where different systems can
> define the layout of the array while keeping the API portable.
>
> struct timespec times[TIMENS_MAX];
>
> for (i = 0; i < nitems(times); i++)
> times[i].tv_usec = UTIME_OMIT;
> #ifdef TIMENS_BIRTH
> timens[TIMENS_BIRTH] = foo;
> #endif
> futimens4(fd, times, nitems(times));
>
all makes sense, but one thing I would like to think about from the
old one is the ability to check for bad birthtime, unless over-ridden..
i.e. by default it keeps birthtime < modtime. I'm not sure whether
this is important to anybody.
More information about the freebsd-fs
mailing list