Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000768 [1003.1(2013)/Issue7+TC1] System Interfaces Editorial Enhancement Request 2013-10-11 13:24 2023-02-23 15:32
Reporter jlayton View Status public  
Assigned To
Priority normal Resolution Accepted As Marked  
Status Applied  
Name Jeff Layton
Organization Red Hat
User Reference
Section fcntl
Page Number 814-815
Line Number
Interp Status ---
Final Accepted Text see Note: 0006096
Summary 0000768: add "fd-private" POSIX locks to spec
Description At this year's Linux Storage and Filesystem summit, there was a lively discussion about what implementors of userland fileservers need. One of the things brought up was the problematic behavior of POSIX locks when a file is closed. The existing spec says:

"All locks associated with a file for a given process shall be removed when a
 file descriptor for that file is closed by that process or the process holding
 that file descriptor terminates."

The problem here is that userland programs may need to open more than one file
descriptor on a file, but they have to keep track of them and refrain from
closing *any* of them until they know that it's ok to release any locks held on
them. This behavior is surprising for most people when they first see it and it greatly complicates writing certain types of userland programs,
Desired Action I've posted an initial rough draft of a patchset here for Linux to address this by adding two new struct flock.l_type values -- F_RDLCKP and F_WRLCKP. In addition to adding this to Linux, I'd like to have it considered for adoption in the formal POSIX spec as well since I'm fairly sure this is an issue on other POSIX-y OS' as well.

The initial patch posting is here:

    http://marc.info/?l=linux-fsdevel&m=138149440915513&w=2 [^]

...and the semantics for the new lock types are layed out there. The basic idea is to have them behave exactly like any other F_RDLCK or F_WRLCK lock, but that these should only be released on close when the file descriptor against which they were opened is closed. Closing other file descriptors shouldn't affect them.

This changes how lock merging works a bit. The 'P' lock types can't be merged with 'non-P' types since they have different semantics when a fd is closed. Similarly, 'P' locks acquired on different file descriptors can't be merged either, since they need to be released separately on close.

At this point, the draft patchset is quite rough and I expect it'll need changes in response to review and comments. In the meantime, I'd like to also open the floor for other POSIX players to add feedback on this while I'm trying to finalize the interface.
Tags issue8
Attached Files

- Relationships
related to 0000824Closed 1003.1(2013)/Issue7+TC1 children should not inherit fcntl file locks from parent calling posix_spawn 
related to 0001318Applied 1003.1(2016/18)/Issue7+TC2 Define close-on-fork flag 
related to 0001671Applied Issue 8 drafts OFD-owned locks addition missed some changes 
related to 0001672Applied Issue 8 drafts Wording improvement to lockf() APPLICATION USAGE 

-  Notes
(0001879)
jilles (reporter)
2013-10-11 15:27

Another file locking API available on Linux and BSDs is flock(), originally from 4.2BSD. Although it only allows locking whole files (no byte-ranges), it has much better semantics: locks are tied to open file descriptions instead of processes. As a result, not only can processes open and close a file another time without affecting the lock, but a child process can inherit a lock from its parent and mutual exclusion works between threads in the same process if they each open the file themselves.

If fcntl(F_GETLK) returns a lock set with flock() (this is possible on FreeBSD but Linux man pages say it is not possible on Linux because fcntl() and flock() locks are independent), then the l_pid member cannot be a process ID because such a lock is not held by a process as such. FreeBSD sets it to -1 in that case.

The proposed F_RDLCKP and F_WRLCKP types seem to address the close issue only.

So I suggest standardizing flock() and/or a fcntl()-based locking mechanism with the same semantics as flock().
(0001880)
jlayton (reporter)
2013-10-11 15:45

The close() issue is the main one I'm trying to address.

Standardizing flock() wouldn't help much since it doesn't allow you to lock byte-ranges. I've no objection to standardizing that, but it's sort of orthogonal to the problem at hand.

Linux could be altered to return a flock() lock on F_GETLK, but it historically hasn't since flock and POSIX locks operate entirely independently. I don't think that would really buy us much. Do flock and fcntl locks conflict with one another on BSD as well?

The question of inheritance of a lock is more interesting however. It's not 100% clear to me what sort of semantics the people asking for this actually want in that respect, so I'll look into that.

I'm inclined to steer away from introducing an entirely new locking mechanism however, since I think we want these new lock types to conflict vs. "legacy" POSIX locks. IOW, programs written to use the older F_RDLCK/F_WRLCK types should continue to work in parallel with ones written for the new ones and provide the same exclusion guarantees. We could still do that with a new interface, but I worry that it'll be more confusing for developers.
(0001975)
jlayton (reporter)
2013-11-08 12:18

Ok, after looking at this, I think you're correct that emulating flock()'s semantics wrt to close and inheritance is the right thing to do. I've got a new draft patchset that does this.

It does mean that I'll need a new F_UNLCKP variant flag if we stick with the F_SETLK interface, but I think that's a reasonable addition anyway.
(0001985)
Don Cragun (manager)
2013-11-14 16:17

This was discussed during the November 14, 2013 conference call.

Although we agree that a new lock type might be a good idea, before we could consider anything, we would need actual changes to be added to the text to define the behavior of this feature. Furthermore, there would have to be an existing implementation that is shipping as part of a product. This bug will be kept open for a while as a placeholder for such a specification.
(0002062)
jlayton (reporter)
2013-12-10 19:59

Thanks for the consideration so far. I'm still pushing forward with proposed patches on the Linux mailing lists. Once I have the semantics a bit more settled, I'll see about writing up the actual changes to the text.
(0002069)
jlayton (reporter)
2013-12-12 12:05

First rough draft of update to the text in the spec. This is just covers the F_SETLK piece. We may need some updates to the F_GETLK piece. As a side note, documenting this makes it clear the that F_SETLK documentation is pretty complex. Would we be better served by doing this with new cmd values instead? i.e. F_GETLKP and F_SETLKP ? Then we could just reuse the existing definitions for F_RDLCK and F_WRLCK.

Thoughts?

--------------------------------------

...existing text:

F_SETLK
    Set or clear a file segment lock according to the lock description
pointed to by the third argument, arg, taken as a pointer to type struct
flock, defined in <fcntl.h>. F_SETLK can establish shared (or read)
locks (F_RDLCK) or exclusive (or write) locks (F_WRLCK), as well as to
remove either type of lock (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are
defined in <fcntl.h>. If a shared or exclusive lock cannot be set,
fcntl() shall return immediately with a return value of -1.

...new text:

F_SETLK

    Set or clear a file segment lock according to the lock description
pointed to by the third argument, arg, taken as a pointer to type struct
flock, defined in <fcntl.h>. F_SETLK can establish shared (or read)
locks (F_RDLCK and F_RDLCKP) or exclusive (or write) locks (F_WRLCK and
F_WRLCKP), as well as to remove either type of lock (F_UNLCK and
F_UNLCKP). F_RDLCK, F_WRLCK, F_UNLCK, F_RDLCKP, F_WRLCKP, and F_UNLCKP
are defined in <fcntl.h>. If a shared or exclusive lock cannot be set,
fcntl() shall return immediately with a return value of -1. Locks set
with F_RDLCK and F_WRLCK can only be unset with F_UNLCK, and locks set
with F_RDLCKP and F_WRLCKP can only be unset with F_UNLCKP.

---------------[part 2]---------------

...existing text:

All locks associated with a file for a given process shall be removed
when a file descriptor for that file is closed by that process or the
process holding that file descriptor terminates. Locks are not inherited
by a child process.

...new text:

All locks associated with a file for a given process that were set with
F_RDLCK or F_WRLCK shall be removed when a file descriptor for that file
is closed by that process or the process holding that file descriptor
terminates. Also those sorts of locks are not inherited by a child process.

Locks set with F_RDLCKP and F_WRLCKP are removed when the last reference
to the open file on which they were set is closed. These locks are
inherited by child processes.
(0002093)
jlayton (reporter)
2013-12-26 12:29

Now that I've looked at the complexity of adding the above text, I think it might be better to implement this with a new set of cmd values instead, a'la:

F_GETLKP
F_SETLKP
F_SETLKPW

I've made that change to the Linux implementation of this patchset and am testing it now. I'll plan to write up a documentation update once that's complete.
(0002163)
eblake (manager)
2014-02-27 16:20

During discussion of 0000824, the question was raised whether it might be useful to have read locks be inheritable across fork/posix_spawn, so that a child can be started with ownership of the same sections locked as the parent instead of having to re-grab the lock. This should be considered when adding new lock constructs (and the consideration may be that dropping all locks, including read locks, is still the best policy)
(0002168)
jlayton (reporter)
2014-02-27 18:44

With the current Linux implementation, I've taken the suggestion of jilles above and adopted BSD (flock()) lock semantics with respect to inheritance and on close(). Thus, file-private locks are associated with the open file so any entity that gets a reference to that open file won't need to reset locks.

The article here explains the semantics in more depth:

     https://lwn.net/Articles/586904/ [^]

...though this is still not yet merged into Linux kernel so the semantics are not yet set in stone.
(0002230)
jlayton (reporter)
2014-04-18 00:01

There is currently a discussion running on several Linux-related mailing lists about what we should call these new locks. The original name I game them was "file-private" locks but that's not as descriptive as it should be.

The current favorite is "file-description locks" since these follow the open file description, with a corresponding change of the macros to make them more visually distinct:

F_FD_GETLK
F_FD_SETLK
F_FD_SETLKW

...it would be nice to have some input on this front from the "powers that be" at the austingroup. A link to the discussion on LKML is here:

    https://lkml.org/lkml/2014/4/16/583 [^]

Please feel free to chime in on the discussion if you can. Unfortunately, the window to rename these is rather short. We only have around 6 weeks before v3.15 of the kernel ships with this feature, and I need to have this fixed well before then.
(0002508)
jlayton (reporter)
2014-12-18 20:57

Sorry for the long delay on this. I had a job change which ended up sidetracking my efforts here. A progress report:

The locks were renamed to "open file description" (OFD) locks, with the constants as:

    #define F_OFD_GETLK 36
    #define F_OFD_SETLK 37
    #define F_OFD_SETLKW 38

The code was merged into v3.15. Both Samba and NFS-Ganesha are looking to use this new facility to simplify their locking code, but both are currently works in progress.

When I did the (trivial) patch for glibc, I also added a section to its manual that describes the new locks and their semantics:

http://www.gnu.org/software/libc/manual/html_mono/libc.html#Open-File-Description-Locks [^]

I'm still interested in seeing this adopted into the POSIX standard.
(0002574)
olly (reporter)
2015-03-09 02:52
edited on: 2015-03-09 02:52

Xapian http://xapian.org/ [^] 1.2.20 was released on 2015-03-04 and will use F_OFD_SETLKW if available, which avoids having to fork a subprocess to hold the lock (which seems to be the sanest way to protect a lock obtained with F_SETLKW from being inadvertently released).

My feedback from having worked with the new API is that it perfectly addresses the issues we encountered with the current POSIX fcntl() locking. It would be really great to see this included in POSIX.

I also noticed this request for implementing it on FreeBSD:

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197696 [^]

(0002575)
mtk (reporter)
2015-03-09 08:08

Just by the bye, Jeff Layton and I produced man page text that describes OFD locks API. If it's useful, I'm sure we(*) could make it available under whatever license Austin needs. The text can be found here:
http://man7.org/linux/man-pages/man2/fcntl.2.html [^]

Thanks,

Michael

(*) Speaking for myself here, but I'm pretty sure Jeff would be agreeable also.
(0002576)
ned14 (reporter)
2015-03-09 18:32

@olly: It was me who added the feature request to FreeBSD. Proposed Boost.AFIO should gain portable byte range advisory file locking next release, and on POSIX it currently has to duplicate process-side an implementation of byte range locking to fuse locks from multiple threads into a single set of requests per process. I'd rather have that implementation go away on FreeBSD like it can on Linux, moreover then AFIO doesn't fail when combined with another library which also uses broken POSIX locks.

Regarding the proposal for standardisation, my sole big concern with it is that we really ought to also standardise on a method for asynchronously requesting a lock and being notified when that lock has been granted. Right now, you can only do polling and retry via F_ORD_SETLK or block up a whole dedicated thread using F_ORD_SETLKW. If one could have select() tell us when a lock has been removed for some file offset, that would be enormous.

As one way of doing this (note, I don't necessarily recommend this), right now as per POSIX regular file fds always return ready to read, ready to write and ready with error with select(). What could happen is that if the current file offset in a file descriptor is inside a range locked inside another fd somewhere, select() for reading could block if there were an exclusive lock on that range, and block for writing if there were a non-exclusive lock on that range. The pattern to more efficiently lock could then be:

1. Try F_OFD_SETLK, if success then proceed.

2. Set file offset in fd to start of range we wish to lock, and add to fds being waited upon with select().

3. When select returns ready on our fd, try F_OFD_SETLK again. If success then proceed, else loop to step 2.


As I mentioned, I wouldn't recommend this solution when something kqueues based is enormously superior as you can tell kqueues about entire byte ranges, and it can intelligently notify you when your specifically requested byte range has been granted to you without you needing to repeat F_OFD_SETLK and unnecessarily do many syscalls when none were needed. However POSIX doesn't standardise BSD kqueues, so I suppose the next best alternative is to extend the POSIX aio API with asynchronous byte range locking support. However, the POSIX aio API is not popular, and it seems overkill to require implementations merely needing notification of lock state changes to retool into POSIX aio just for that.

The AWG may be interested in how the NT kernel fairs with byte range locking (ref: NtLockFile() https://msdn.microsoft.com/en-us/library/windows/hardware/ff566474%28v=vs.85%29.aspx). [^] These are fully asynchronous, so you can queue up one or many ranges to lock and it'll signal a win32 event or the HANDLE when you've been awarded the lock. This allows lock wait composure into WaitForMultipleObjects which is the Win32 equivalent to select().

This NT kernel implementation is highly efficient relative to Linux and FreeBSD with O(1) to waiters complexity. See http://boostgsoc13.github.io/boost.afio/doc/html/afio/quickstart/atomic_logging.html [^] for some benchmarks. Part of that efficiency is an optimal API design. I really wish POSIX, or even any POSIX implementation, had something equivalent.

Niall
(0002577)
jlayton (reporter)
2015-03-10 20:00

Yes, I'd definitely be amenable to making the manpage text available for the POSIX spec. There's also a more comprehensive writeup in the glibc manual, and we might be able to make some of that text available as well (I'd have to check with them on that though).

As far as adding an async interface, for Linux we might want to add something to epoll for that. Not a bad idea!

As far as a standard async interface goes though, that's a much taller order. Given that we have a working sync implementation, I'd suggest that we consider that for standardization now and an async interface at a later date.
(0002589)
olly (reporter)
2015-03-17 22:43

Standardising the interface as implemented by Linux (and described above) separately seems the best plan - it's essentially how the fcntl locking API which has long existed really should have worked all along, and it should be easy to update existing code to use it, and also easy to fall back to the older API where the new one isn't yet supported (it certainly was for the Xapian code).

Blocking the standardisation of this while people work on an async locking API doesn't seem helpful - this has an existing working implementation which is already widely deployed, whereas there doesn't appear to even be a proposed design for an async interface yet.
(0002590)
ned14 (reporter)
2015-03-19 13:09

@jlayton: I did have a go at sketching out support for byte range lock notification to epoll + eventfd, but eventfd just doesn't transport enough information for it to work, so epoll would need API changes. A suitable enhancement of BSD kqueues is similarly stymied by insufficient fields to send which byte range lock was just granted, though one can encapsulate the struct flock into a following fake struct kevent. It still isn't great.

Can I therefore suggest a small change now which makes async support much easier later? If struct flock additionally had:

1. A intptr_t data
2. A void *udata

... then the caller of F_ORD_SETLK would have the means to set those members of struct kevent, and we thus solve the problem of lock identification for BSD because the lock requester could supply two unique numbers which make sense to itself. I'm thinking on Linux for epoll + eventfd that the intptr_t data value could specify an eventfd to notify and the udata value be returned by eventfd to indicate which lock request was granted. Not as nice as kqueues, but sufficient.

From the point of view of POSIX however, struct flock simply gains two new fields called data and udata. Nothing more is said about them (for now).

@olly: I wasn't advocating blocking fd-private locks awaiting a proper async locking API. I am advocating thinking fd-private locks through before standardisation without an async locking API. Adding two fields to struct flock to help out vendor proprietary async notification systems might be wise.
(0002592)
jlayton (reporter)
2015-03-19 18:50

Oh...my thinking was that you could just epoll() on the fd and look for an EPOLLLCK event or something, and then just reattempt getting the lock. That's obviously less cool than having the lock granted to you though.

As far as adding fields to struct flock, won't that cause horrible ABI problems? Think of all of those poor applications already built using struct flock that doesn't have the extra fields.

While I think an async interface is interesting and makes a lot of sense, I don't think we can overload struct flock with that info without causing horrible breakage in a lot of code.

Why not consider adding a new "struct flock_async" or something? a'la:

struct flock_async {
    struct flock fla_flock;
    intptr_t fla_data1;
    void *fla_data2;
};

...that would allow you to do basically what you want, but we wouldn't break the ABI for existing code. You could add that to FreeBSD in the near future, and then ask POSIX to consider adding your interface in the context of a separate request. My understanding is that they prefer to see this sort of thing in shipping code before standardizing it anyway.
(0002593)
ned14 (reporter)
2015-03-19 19:57

Throwing the idea of a new struct type right back at you, surely the struct flock taken by F_ORD_SETLK could be that exact new struct flock2?

If there is any time to break ABI, it's at the point of adding the new API. So, I propose that F_ORD_SETLK fnctl's don't take the existing struct flock, but a new struct flock_ord:

struct flock_ord {
       short l_type; /* lock operation type */
       short l_whence; /* lock base indicator */
       off_t l_start; /* starting offset from base */
       off_t l_len; /* lock length; l_len == 0 means
                until end of file */
       int l_sysid; /* system ID running process holding lock */
       pid_t l_pid; /* process ID of process holding lock */
       intptr_t data; /* requester supplied fd or data identifying lock */
       void *udata; /* requester supplied data identifying lock */
};

Does this seem reasonable?
(0002594)
jlayton (reporter)
2015-03-19 20:53

FWIW, the constants used in Linux currently have an F_OFD_ prefix, not F_ORD_

Also, looking at the struct above, l_sysid and l_pid don't really make much sense for an OFD lock. These locks are tied to the open file description, not a particular process.

They certainly could be a flock2 struct, but why would we add these to the current synchronous interface? What's the benefit of doing so? I don't think it's a good idea to add extra fields to the argument struct in the absence of a concrete proposal to add such an interface to POSIX.

If we ever did want to add an asynchronous interface, there's no reason that it would need to use the same argument struct as the synchronous one. It would be perfectly fine for the synchronous fcntl-based interface to use plain old struct flock (as the one shipping on Linux does today) and for the new async interface to use struct flock2 (or whatever).
(0002595)
ned14 (reporter)
2015-03-20 00:32

Sorry about the typo. I use my (email) laptop without my glasses, and F's and R's look very similar. Regarding the l_sysid and l_pid, they came from the FreeBSD man page. They are used with F_GETLK. You surprise me that they don't make much sense for an OFD lock as your own man page says l_pid is supplied. I certainly can see the use of using l_pid to decide if a process is a zombie, or to message or signal it somehow.

You raise the very good point that any async interface would necessarily use a different fcntl number, and therefore that different fcntl can take any kind of struct flock it likes. So I guess the existing proposal is fair enough and we can press ahead with standardisation for the proposal as is.

I would encourage you however to consider extending your Linux implementation using the scheme just outlined, though for Linux it's probably more appropriate to extend the Linux event file IO mechanism via additions to http://linux.die.net/include/linux/aio_abi.h [^] where usefully you get a free hand to schedule and cancel advisory locks asynchronously using any custom struct of your choice, so you're not constrained by eventfd et al. Not only would I find async notification of lock grants very useful in Boost.AFIO, but I suspect so would SQLite3, Samba, NFS and plenty others, anyone who does a lot of file locking. We all still have to write code which deals with the old semantics of course, but being able let the kernel fairly schedule file locks instead of first past the post makes enormous sense for electricity consumption and performance. And it would bring Linux to feature parity with Windows, always a good thing.

Anyway, thank you for your proposal. It's a huge win for everyone.
(0002596)
mtk (reporter)
2015-03-20 07:00

@ned14:
> Regarding the l_sysid and l_pid, they came from
> the FreeBSD man page. They are used with
> F_GETLK. You surprise me that they don't make
> much sense for an OFD lock as your own man page
> says l_pid is supplied.

l_pid can't be meaningful for OFD locks, because they are associated with an open file description, which can be shared by multiple process (fork(), PID passing across UNIX domain sockets). One can have the situation:

    <acquire lock>
    if (fork())
        exit();
    /* Child holds the lock */

At that point, the lock is still held, but the PID that created it has gone away.

Thanks

Michael
(0002602)
jlayton (reporter)
2015-03-24 01:32

I'd even go so far as to say that fcntl might be the wrong interface for handling locks asynchronously. But, I don't really know for sure. That's the problem, of course. No one has sat down to design a mechanism for handling locking asynchronously. That's a bit trickier than a simple, synchronous interface.

Also, Michael is correct about the l_pid field. Since it has no real meaning with an OFD lock, Linux always fills out that field with '-1' with an OFD lock.

FWIW, that behavior was actually copied from FreeBSD. On FreeBSD, flock and fcntl locks can conflict with one another, and if you do an F_GETLK request and a flock lock would conflict, the kernel also fills out the l_pid field with '-1'.
(0002603)
ned14 (reporter)
2015-03-25 16:33

@jlayton: Jeff would you be interested in collaborating with me on a white paper discussing API options for implementing asynchronous byte range file locks? A rough outline might be:

* How asynchronous byte range file locks are implemented on other platforms (Windows, QNX etc) and benchmarked performance thereof in various use case scenarios.

* How the Linux KAIO API could be extended (io_submit etc).

* How the POSIX AIO API could be extended (FreeBSD, OS X etc).

If you're interested, I don't mind producing a first draft. My next two weeks I am off from work writing conference papers anyway, and this white paper could form part of my CppCon proceedings.

The other question is whether there is any interest in standardising such a thing? I'm sure the vendors of database or package management or network filing system software would be extremely interested, especially in any guaranteed fair kernel implemented algorithm for locking multiple files concurrently, but this is a very niche topic.
(0002605)
jlayton (reporter)
2015-03-26 13:21

Sure, I'd be happy to review such a white paper. Probably best to carry on that discussion via email though -- jlayton@poochiereds.net. FWIW, I'm no longer at Red Hat.

I know that the Samba team have wished for an asynchronous file locking mechanism so I can speak to that particular use-case (or track down others who can better than I).
(0006096)
eblake (manager)
2022-12-15 17:14
edited on: 2022-12-15 17:22

On page 48 line 1558 section 3.138 File Lock, change:
A lock obtained on a file through the use of fcntl() or lockf().

to:
Any advisory lock, including a record lock (see [xref to Record Lock]), obtained on a file for the purpose of coordinating transactions among cooperating processes accessing the same file with the same lock type. See also [xref to OFD-Owned File Lock] and [xref to Process-Owned File Lock].

<small>Note: All file locks created by interfaces defined in this standard are record locks; however, implementations commonly also support a file lock extension interface named flock(), that creates non-record locks (that is, a file lock that can only be held on the whole file).</small>

<small>Note: Advisory locks do not prevent a process with sufficient access permissions from modifying the file without taking locks.</small>


After page 61 line 1905 section 3 Definitions, add:
3.NNN OFD-Owned File Lock

A record lock owned by an open file description. OFD-owned file locks are obtained through the use of fcntl() with F_OFD_SETLK or F_OFD_SETLKW. Whenever a file descriptor associated with the owning open file description is inherited these locks remain in effect. OFD-owned file locks are automatically released on the last close of the open file description. These locks are only shared among file descriptors associated with the same open file description. Thus, a multi-threaded process can use multiple open file descriptions (such as by open()) to create independent OFD-owned locks that can then be used to coordinate access patterns to the same file, while multiple file descriptors associated with the same file description (such as by dup()) share lock actions among all other descriptors associated with the same file description.


After page 68 line 2126 section 3 Definitions, add:
3.NNN Process-Owned File Lock

A record lock owned by a process. Process-owned file locks are obtained through the use of fcntl() with F_SETLK or F_SETLKW, or the use of lockf(). Process-owned file locks are not inherited by child processes, but are preserved across the exec*() family of functions. A process-owned file lock is released when the process exits, or when any file descriptor in the process referring to the same file is closed (even if via a different open file description). Locks are shared among all file descriptions referring to the same file in the process, making the use of process-owned file locks unsuitable for use for coordination of record access among multiple threads in a process.


(Note to the editor: also move 3.276 Process-To-Process Communication to after this new definition.)

After page 70 line 2165 section 3 Definitions, add:
3.NNN Record Lock

A file lock held on a record within a file. A record lock can be used to lock a whole file by specifying a special record with starting offset zero and length zero. (This special record extends to any future end-of-file, not just the current end-of-file.) This includes an OFD-owned file lock (see [xref to OFD-Owned File Lock]) or a process-owned file lock (see [xref to Process-Owned File Lock]). It is unspecified whether an implementation will detect and prevent deadlocks caused by two competing lock owners holding separate locks where each tries to obtain a lock that is blocked by the other's lock.


On page 229 line 7920 section <fcntl.h>, change:
F_GETLK Get record locking information.

F_SETLK Set record locking information.

F_SETLKW Set record locking information; wait if blocked.


to:
F_GETLK Get information about file locks.

F_SETLK Set a process-owned file lock.

F_SETLKW Set a process-owned file lock; wait if blocked.

F_OFD_GETLK Get information about file locks.

F_OFD_SETLK Set an OFD-owned file lock.

F_OFD_SETLKW Set an OFD-owned file lock; wait if blocked.


On page 231 line 8019 section <fcntl.h>, change l_pid text from:
Process ID of the process holding the lock; returned with F_GETLK.


to:
For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output.


On page 506 line 17959 section 2.9.5.2 Cancellation Points, change:
When the cmd argument is F_SETLKW.


to:
When the cmd argument is F_SETLKW or F_OFD_SETLKW.


On page 667 line 23031 section close(), change:
All outstanding record locks owned by the process on the file associated with the file descriptor shall be removed (that is, unlocked).


to:
All process-owned file locks that the calling process owns on the file associated with the file descriptor shall be unlocked.


On page 776 line 26503 section exec, change:
For any file descriptor that is closed for this reason, file locks are removed as a result of the close as described in close().


to:
For any file descriptor that is closed for this reason, process-owned file locks that the calling process owns on the file associated with the file descriptor shall be unlocked as a result of the close, as described in close().

    
On page 811 line 27663 section fcntl(), change:
F_GETLK
    
Get any lock which blocks the lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>. The information retrieved shall overwrite the information passed to fcntl() in the structure flock. If no lock is found that would prevent this lock from being created, then the structure shall be left unchanged except for the lock type which shall be set to F_UNLCK.


F_SETLK
    
Set or clear a file segment lock according to the lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive lock cannot be set, fcntl() shall return immediately with a return value of −1.


F_SETLKW
    
This command shall be equivalent to F_SETLK except that if a shared or exclusive lock is blocked by other locks, the thread shall wait until the request can be satisfied. If a signal that is to be caught is received while fcntl() is waiting for a region, fcntl() shall be interrupted. Upon return from the signal handler, fcntl() shall return −1 with errno set to [EINTR], and the lock operation shall not be done.


to:
F_GETLK
    
Get any file lock which blocks the process-owned file lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>. The information retrieved shall overwrite the information passed to fcntl() in the structure flock. If no lock is found that would prevent this lock from being created, then the structure shall be left unchanged except for the lock type in l_type which shall be set to F_UNLCK.


F_SETLK
    
Set or clear a process-owned file lock according to the lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive lock cannot be set, fcntl() shall return immediately with a return value of −1.


F_SETLKW
    
This command shall be equivalent to F_SETLK except that if a shared or exclusive lock is blocked by other locks, the thread shall wait until the request can be satisfied. If a signal that is to be caught is received while fcntl() is waiting for a region, fcntl() shall be interrupted. Upon return from the signal handler, fcntl() shall return −1 with errno set to [EINTR], and the lock operation shall not be done.


F_OFD_GETLK
    
Get any file lock which blocks the OFD-owned file lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>; the application shall ensure that the l_pid member of the structure pointed to by arg is set to 0 on input. The information retrieved shall overwrite the information passed to fcntl() in the structure flock. If no lock is found that would prevent this lock from being created, then the structure shall be left unchanged except for the lock type in l_type which shall be set to F_UNLCK.


F_OFD_SETLK
    
Set or clear an OFD-owned file lock according to the lock description pointed to by the third argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>; the application shall ensure that the l_pid member of the structure pointed to by arg is set to 0 on input. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive (or write) locks (F_WRLCK), as well as to remove either type of lock (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive lock cannot be set, fcntl() shall return immediately with a return value of −1.


F_OFD_SETLKW
    
This command shall be equivalent to F_OFD_SETLK except that if a shared or exclusive lock is blocked by other locks, the thread shall wait until the request can be satisfied. If a signal that is to be caught is received while fcntl() is waiting for a region, fcntl() shall be interrupted. Upon return from the signal handler, fcntl() shall return −1 with errno set to [EINTR], and the lock operation shall not be done.


At page 812 line 27696, change:
The l_pid field is only used with F_GETLK to return the process ID of the process holding a blocking lock. After a successful F_GETLK request, when a blocking lock is found, the values returned in the flock structure shall be as follows:

to:
On input, the l_pid field shall be ignored for F_GETLK, F_SETLK and F_SETLKW; the application shall ensure that it is set to zero for F_OFD_GETLK, F_OFD_SETLK and F_OFD_SETLKW. It is set by F_GETLK and F_OFD_GETLK when identifying a blocking lock. After a successful F_GETLK or F_OFD_GETLK request, when a blocking lock is found, the values returned in the flock structure shall be as follows:


At page 812 line 27704, change:
l_pid Process ID of the process that holds the blocking lock.

to:
l_pid Process ID of the process that holds the blocking lock if the blocking lock is a process-owned file lock, or (pid_t)-1 if the blocking lock is an OFD-owned file lock.


At page 812 line 22705, change:
If the command is F_SETLKW and the process must wait for another process to release a lock,

to:
If the command is F_SETLKW or F_OFD_SETLKW and the thread needs to wait for a blocking lock to be released,


At line 27714, change:
There shall be at most one type of lock set for each byte in the file. Before a successful return from an F_SETLK or an F_SETLKW request when the calling process has previously existing locks on bytes in the region specified by the request, the previous lock type for each byte in the specified region shall be replaced by the new lock type. As specified above under the descriptions of shared locks and exclusive locks, an F_SETLK or an F_SETLKW request (respectively) shall fail or block when another process has existing locks on bytes in the specified region and the type of any of those locks conflicts with the type specified in the request.

All locks associated with a file for a given process shall be removed when a file descriptor for that file is closed by that process or the process holding that file descriptor terminates. Locks are not inherited by a child process.

A potential for deadlock occurs if a process controlling a locked region is put to sleep by attempting to lock the locked region of another process. If the system detects that sleeping until a locked region is unlocked would cause a deadlock, fcntl() shall fail with an [EDEADLK] error.

to:
Each byte in the file can be locked either with one or more shared locks (F_RDLCK) or with one exclusive lock (F_WRLCK).

Before a successful return from an F_SETLK or an F_SETLKW request when the calling process has previously existing process-owned locks on bytes in the region specified by the request, the previous shared or exclusive lock for each byte in the specified region shall be replaced by the new shared or exclusive lock. An F_SETLK or an F_SETLKW request (respectively) shall fail or block when another process has existing process-owned locks, or any open file description (including the one associated with fildes) has existing OFD-owned locks, on bytes in the specified region and any of those locks conflicts with the requested lock.

Before a successful return from an F_OFD_SETLK or an F_OFD_SETLKW request when the open file description associated with fildes has previously existing OFD-owned locks on bytes in the region specified by the request, the previous shared or exclusive lock for each byte in the specified region shall be replaced by the new shared or exclusive lock. An F_OFD_SETLK or an F_OFD_SETLKW request (respectively) shall fail or block when another open file description has existing OFD-owned locks, or any process (including the calling process) has existing process-owned locks, on bytes in the specified region and any of those locks conflicts with the requested lock.

All process-owned locks associated with a file for a given process shall be removed when any file descriptor for that file is closed by that process (even if via a different open file description) or the process holding that file descriptor terminates. Process-owned locks shall not be inherited by a child process.

All OFD-owned locks associated with a given open file description shall be removed when all file descriptors associated with that open file description have been closed (either directly or as a side-effect of, for example, process termination or FD_CLOEXEC). OFD-owned locks shall be shared across all file descriptors that are associated with the owning open file description, regardless of which process holds the file descriptor.

A potential for deadlock occurs if a process or thread controlling a locked region is put to sleep by attempting to lock a region that has an existing conflicting lock. If the system detects that sleeping until a locked region is unlocked would cause a deadlock, fcntl() shall fail with an [EDEADLK] error. Deadlock detection may differ between process-owned locks and OFD-owned locks.

[XSI]The interaction between fcntl() and lockf() locks is unspecified.[/XSI]


On page 813 line 27729 section fcntl(), change:
when the process has an existing lock in which l_len is 0

to:
when the process (for F_SETLK and F_SETLKW) or open file description (for F_OFD_SETLK and F_OFD_SETLKW) has an existing lock in which l_len is 0


On page 813 line 27735 section fcntl(), change:
shall be unspecified: F_SETFL, F_GETLK, F_SETLK, and F_SETLKW.

to: 
is unspecified: F_SETFL, F_GETLK, F_SETLK, F_SETLKW, F_OFD_GETLK, F_OFD_SETLK, and F_OFD_SETLKW.


After page 813 line 27751 section fcntl(), add to RETURN VALUE:
F_OFD_GETLK Value other than -1.
F_OFD_SETLK Value other than -1.
F_OFD_SETLKW Value other than -1.


On page 813 line 27758 section fcntl(), change:
[EACCES] or [EAGAIN]
    
The cmd argument is F_SETLK; the type of lock (l_type) is a shared (F_RDLCK) or exclusive (F_WRLCK) lock and the segment of a file to be locked is already exclusive-locked by another process, or the type is an exclusive lock and some portion of the segment of a file to be locked is already shared-locked or exclusive-locked by another process.

to:
[EACCES] or [EAGAIN]
    
The cmd argument is F_SETLK, the type of lock (l_type) is a shared (F_RDLCK) or exclusive (F_WRLCK) lock, and the requested lock cannot be set because it is blocked by an existing lock on the file.

[EAGAIN]
    
The cmd argument is F_OFD_SETLK, the type of lock (l_type) is a shared (F_RDLCK) or exclusive (F_WRLCK) lock, and the requested lock cannot be set because it is blocked by an existing lock on the file.


On page 814 line 27763-27781 section fcntl() ERRORS, change:


  • All occurrences of "F_GETLK, F_SETLK, or F_SETLKW" to "F_GETLK, F_SETLK, F_SETLKW, F_OFD_GETLK, F_OFD_SETLK, or F_OFD_SETLKW"

  • All occurrences of "F_SETLK or F_SETLKW" to "F_SETLK, F_SETLKW, F_OFD_SETLK, or F_OFD_SETLKW"

  • All other occurrences of "F_SETLKW" to "F_SETLKW or F_OFD_SETLKW"



On page 814 line 27787 section fcntl() EDEADLK, change:
The cmd argument is F_SETLKW, the lock is blocked by a lock from another process, and putting the calling process to sleep to wait for that lock to become free would cause a deadlock.

to:
The cmd argument is F_SETLKW or F_OFD_SETLKW, the type of lock (l_type) is a shared (F_RDLCK) or exclusive (F_WRLCK) lock, the requested lock is blocked by an existing lock on the file, and the system determines that waiting for that lock to be released would cause a deadlock.


After page 816 line 27870 section fcntl(), add to APPLICATION USAGE:
Record-locking should not be used in combination with buffered standard I/O streams (see [xref to 2.5]). Instead, non-buffered I/O should be used. Unexpected results may occur in processes that do buffering in the user address space. The process may later read/write data which is/was locked. Functions that operate on standard I/O streams are the most common source of such buffering.


On page 886 line 30174 section fork(), change:
File locks set by the parent process shall not be inherited by the child process.

to:
Process-owned file locks set by the parent process shall not be inherited by the child process.


On page 1245 line 41729 section lockf(), change:
The lockf() function shall lock sections of a file with advisory-mode locks.

to:
The lockf() function shall lock sections of a file with advisory-mode process-owned locks.


On page 1245 line 41760 section lockf(), change:
File locks shall be released on first close by the locking process of any file descriptor for the file.

to:
Process-owned file locks shall be released on first close by the locking process of any file descriptor for the file.


On page 1449 line 48446,48457 section posix_spawn(), change:
... child process shall not inherit any file locks

to:
... child process shall not inherit any process-owned file locks


On page 2068 line 67057 section system(), change: 
that file locks are not inherited

to: 
that process-owned file locks are not inherited


On page 3669 line 127004 section D.2.3 Access to Data, change:
The file-locking mechanism provides for advisory locking

to:
The file-locking mechanisms provide for advisory locking



- Issue History
Date Modified Username Field Change
2013-10-11 13:24 jlayton New Issue
2013-10-11 13:24 jlayton Name => Jeff Layton
2013-10-11 13:24 jlayton Organization => Red Hat
2013-10-11 13:24 jlayton Section => fcntl
2013-10-11 13:24 jlayton Page Number => 814-815
2013-10-11 13:39 jlayton Issue Monitored: jlayton
2013-10-11 15:27 jilles Note Added: 0001879
2013-10-11 15:45 jlayton Note Added: 0001880
2013-11-08 12:18 jlayton Note Added: 0001975
2013-11-14 16:17 Don Cragun Note Added: 0001985
2013-11-27 17:44 grawity Issue Monitored: grawity
2013-12-04 11:06 Florian Weimer Issue Monitored: Florian Weimer
2013-12-10 19:59 jlayton Note Added: 0002062
2013-12-12 12:05 jlayton Note Added: 0002069
2013-12-26 12:29 jlayton Note Added: 0002093
2014-02-27 16:20 eblake Note Added: 0002163
2014-02-27 16:22 eblake Relationship added related to 0000824
2014-02-27 18:44 jlayton Note Added: 0002168
2014-04-18 00:01 jlayton Note Added: 0002230
2014-12-18 20:57 jlayton Note Added: 0002508
2015-03-09 02:52 olly Note Added: 0002574
2015-03-09 02:52 olly Note Edited: 0002574
2015-03-09 08:08 mtk Note Added: 0002575
2015-03-09 18:32 ned14 Note Added: 0002576
2015-03-10 20:00 jlayton Note Added: 0002577
2015-03-17 22:43 olly Note Added: 0002589
2015-03-19 13:09 ned14 Note Added: 0002590
2015-03-19 18:50 jlayton Note Added: 0002592
2015-03-19 19:57 ned14 Note Added: 0002593
2015-03-19 20:53 jlayton Note Added: 0002594
2015-03-20 00:32 ned14 Note Added: 0002595
2015-03-20 07:00 mtk Note Added: 0002596
2015-03-24 01:32 jlayton Note Added: 0002602
2015-03-25 16:33 ned14 Note Added: 0002603
2015-03-26 13:21 jlayton Note Added: 0002605
2022-12-15 17:14 eblake Note Added: 0006096
2022-12-15 17:19 eblake Note Edited: 0006096
2022-12-15 17:22 eblake Note Edited: 0006096
2022-12-15 17:28 eblake Interp Status => ---
2022-12-15 17:28 eblake Final Accepted Text => see Note: 0006096
2022-12-15 17:28 eblake Status New => Resolved
2022-12-15 17:28 eblake Resolution Open => Accepted As Marked
2022-12-15 17:29 shware_systems Tag Attached: issue8
2023-01-17 10:56 geoffclare Status Resolved => Applied
2023-02-23 15:32 eblake Relationship added related to 0001318
2023-04-18 08:56 geoffclare Relationship added related to 0001671
2023-04-18 09:12 geoffclare Relationship added related to 0001672


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker