From owner-freebsd-fs@freebsd.org Tue Nov 10 05:38:52 2015 Return-Path: Delivered-To: freebsd-fs@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 76050A2BA46 for ; Tue, 10 Nov 2015 05:38:52 +0000 (UTC) (envelope-from julian@freebsd.org) Received: from vps1.elischer.org (vps1.elischer.org [204.109.63.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 453C711E7; Tue, 10 Nov 2015 05:38:51 +0000 (UTC) (envelope-from julian@freebsd.org) Received: from Julian-MBP3.local (ppp121-45-229-78.lns20.per1.internode.on.net [121.45.229.78]) (authenticated bits=0) by vps1.elischer.org (8.15.2/8.15.2) with ESMTPSA id tAA5cdj2085734 (version=TLSv1.2 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Mon, 9 Nov 2015 21:38:43 -0800 (PST) (envelope-from julian@freebsd.org) Subject: Re: futimens and utimensat vs birthtime (resurected) To: John Baldwin References: <201508142122.t7ELMPjR002452@chez.mckusick.com> <56401002.8020909@freebsd.org> <10503657.4i3LlcO4Z3@ralph.baldwin.cx> Cc: Kirk McKusick , "freebsd-fs@freebsd.org" , "'Jilles Tjoelker'" From: Julian Elischer Message-ID: <564182D9.8000701@freebsd.org> Date: Tue, 10 Nov 2015 13:38:33 +0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <10503657.4i3LlcO4Z3@ralph.baldwin.cx> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Nov 2015 05:38:52 -0000 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 >>>> To: freebsd-current@freebsd.org >>>> Subject: Re: futimens and utimensat vs birthtime >>>> Date: Fri, 14 Aug 2015 10:39:41 -0700 >>>> Cc: "freebsd-fs@freebsd.org" , >>>> "'Jilles Tjoelker'" >>>> >>>> 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.