Closed adammoody closed 1 year ago
This PR changes unifyfs_fid_open
to be more like POSIX open
to that it's successful on existing files when only given O_CREAT
, while it fails with EEXIST
when given O_CREAT | O_EXCL
.
@MichaelBrim , the PR is failing on a test of the client API here:
I see our implementation only sets the O_CREAT
flag.
We could change this to O_CREAT | O_EXCL
. Another option might be to leave this as O_CREAT
but modify the test to expect success. What do you think?
We could change this to
O_CREAT | O_EXCL
. Another option might be to leave this asO_CREAT
but modify the test to expect success. What do you think?
The semantics of unifyfs_create()
match that of open(O_CREAT | O_EXCL)
, so my suggestion is to change the code in unifyfs_create()
to pass O_EXCL as well when calling unifyfs_fid_open()
.
@MichaelBrim , I added O_EXCL
. But now I think it's tripping a test on our "private file" semantic which is triggered with O_EXCL
:
We indicate that the exclusive bit was set in the open flags and pass that to unifyfs_fid_create
.
and then in unifyfs_fid_create
, we use that last parameter to mark the file as private (not shared).
So we currently have two meanings for O_EXCL
:
EEXIST
if file already exists on O_CREAT
I guess we'd need to either pick a different bit flag to indicate private files or I could revert back to handling the O_EXCL
logic up in the sysio/stdio wrappers. What do you think?
I'm a bit torn on this dilemma. I think it's useful to maintain the idea of a private (non-shared) file, although most of our usefulness to current applications comes from shared files. Using O_EXCL to mean private was always a hack, but I still can't find a better standard flag to substitute for it. If we want to maintain the private notion, the exclusive-create logic would need to live in the POSIX wrappers layer. We could funnel all open() or fopen() calls that should create files through posix_create()
and handle exclusive-create there.
@MichaelBrim , I've got this about halfway done now. As it stands unifyfs_fid_open
still does a lot of posix-like processing based on the flags it's given. Since it's pretty posix-specific, it may be better to move this up to the posix wrappers like you suggested. Maybe we could come up with a unifyfs_fid_open
that is free from any O_*
flags.
To avoid breaking things, I have unifyfs_api
call the old unifyfs_fid_open
implementation, which I renamed to unifyfs_fid_open2
. I also dropped the fid
and pos
params from that function since the API didn't use them.
Which O_*
flags do we want to expose to users in unifyfs_open()
?
The unifyfs_fid_open2
implementation currently processes O_DIRECTORY
, O_TRUNC
, and O_APPEND
. Do we want to keep those?
Should we throw an error if a user passes O_CREAT
and/or O_EXCL
in their call to unifyfs_open()
or just ignore them?
Since the library API assumes stateless file access,O_APPEND
has no useful meaning. O_TRUNC
is accomplished via an explicit UNIFYFS_IOREQ_OP_TRUNC
operation. We don't have directories in the library API yet, so O_DIRECTORY
isn't useful either.
I think my conclusion is the only O_XXX
flags we should allow in unifyfs_open()
are the read/write access ones. It does make sense to check for the other POSIX file-create related flags and throw an error if somebody passes those.
Also, we should define our own flag values for use in unifyfs_create()
for all the per-file behaviors we want. But that's a job for me independent of this PR.
@MichaelBrim , this is ready for another look when you have a chance. The main changes since you last looked at it are in the client API library.
I updated the API calls to use the new gfid_create
and fid_fetch
calls. I added a check so that unifyfs_open
only accepts O_RDONLY/WRONLY/RDWR
flags, and there's one test case added to check for O_TRUNC
as an example. I dropped the old unifyfs_fid_open()
call.
I think it's good to go. Let me know if you have suggestions.
Thanks, @MichaelBrim !
Description
This updates
unifyfs_fid_open()
to handleO_EXCL
andEEXIST
. Checks from posix wrappers are removed. It splitsunifyfs_fid_open()
into parts.unifyfs_gfid_create()
call is responsible for creating the gfid entry on the server. This does not modify the local fid cache at all.unifyfs_fid_fetch()
call retrieves file meta data for the corresponding gfid from the server. It allocates an entry in the fid cache, or if one already exists, it updates the existing cache entry.The client API library has been updated to call these new functions.
unifyfs_create()
callsunifyfs_gfid_create()
to create the gfid entry, and then it callsunifyfs_open()
.unifyfs_open()
callsunifyfs_fid_fetch()
to allocate an entry in the fid cache and populate it with data about the gfid from the server.A new
UNIFYFS_CLIENT_EXCL_PRIVATE
config option is added to toggle whetherO_EXCL
implies a private file. By default,O_EXCL
creates private files. One can create shared files usingO_EXCL
by settingUNIFYFS_CLIENT_EXCL_PRIVATE=0
.Motivation and Context
When passed the
O_CREAT
flag, anopen
call on an existing file should succeed as long asO_EXCL
is not also given. We return anEEXIST
error fromunifyfs_fid_open
when the file already exists. In ouropen
andcreat
wrappers, this is then handled as a special case where we do a second call tounifyfs_fid_open
after masking out theO_CREAT
flag.https://github.com/LLNL/UnifyFS/blob/ca3fa9e67efcb32eddc8380161f74fdc6595697d/client/src/unifyfs-sysio.c#L1200-L1209
However, that special case logic is missing from our
fopen
wrapper, which fails with an error when callingfopen(name, "w")
on an existing file. This means that the following case returns anEEXIST
error when it should succeed:This refactors
unifyfs_fid_open
to simplify checking when opening laminated files, truncating files, and allocating a new local fid structure when needed.How Has This Been Tested?
Types of changes
Checklist: