diff options
author | Michael I. Bushnell <mib@gnu.org> | 1995-12-18 18:47:56 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1995-12-18 18:47:56 +0000 |
commit | 4d54f71e1074c5778a58285b00419bea58fa8926 (patch) | |
tree | 84ff5dbbc1508022bd31bef194d7f3ff1e2237c0 | |
parent | 09b32a7289c917188156ce072c503344f83117cd (diff) |
Formerly dir-lookup.c.~4~
-rw-r--r-- | libnetfs/dir-lookup.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/libnetfs/dir-lookup.c b/libnetfs/dir-lookup.c index e0cecab2..0f66c92d 100644 --- a/libnetfs/dir-lookup.c +++ b/libnetfs/dir-lookup.c @@ -113,17 +113,12 @@ netfs_S_dir_lookup (struct protid *diruser, np = 0; - /* Attempt a lookup on the next pathname component. */ - error = netfs_attempt_lookup (diruser->credential, dnp, nextname, &np); - - /* Implement O_EXCL flag here */ - if (lastcomp && create && excl && (!error || error == EAGAIN)) - error = EEXIST; - - /* If we get an error, we're done */ - if (error == EAGAIN) + retry_lookup: + + if (dnp == netfs_root_node + && nextname[0] == '.' && nextname[1] == '.' && nextname[2] == '\0') { - /* This really means .. from root */ + /* Lookup of .. from root */ if (diruser->po->dotdotport != MACH_PORT_NULL) { *do_retry = FS_RETRY_REAUTH; @@ -132,28 +127,52 @@ netfs_S_dir_lookup (struct protid *diruser, if (!lastcomp) strcpy (retry_name, nextname); error = 0; + mutex_unlock (&dnp->lock); goto out; } else + /* We are global root */ { - /* We are the global root; .. from our root is - just our root again. */ error = 0; np = dnp; netfs_nref (np); } } - + else + /* Attempt a lookup on the next pathname component. */ + error = netfs_attempt_lookup (diruser->credential, dnp, nextname, &np); + + /* At this point, DNP is unlocked */ + + /* Implement O_EXCL flag here */ + if (lastcomp && create && excl && !error) + error = EEXIST; + /* Create the new node if necessary */ if (lastcomp && create && error == ENOENT) { mode &= ~(S_IFMT | S_ISPARE | S_ISVTX); mode |= S_IFREG; + mutex_lock (&dnp->lock); error = netfs_attempt_create_file (diruser->credential, dnp, filename, mode, &np); newnode = 1; + + /* If someone has already created the file (between our lookup + and this create) then we just got EEXIST. If we are + EXCL, that's fine; otherwise, we have to retry the lookup. */ + if (error == EEXIST && !excl) + { + mutex_lock (&dnp->lock); + goto retry_lookup; + } } + + /* All remaining errors get returned to the user */ + if (error) + goto out; +#if 0 /* If this is translated, start the translator (if necessary) and return. */ if ((((flags & O_NOTRANS) == 0) || !lastcomp) @@ -261,6 +280,7 @@ netfs_S_dir_lookup (struct protid *diruser, } } } +#endif netfs_validate_stat (np, diruser->credential); @@ -314,24 +334,22 @@ netfs_S_dir_lookup (struct protid *diruser, create = 0; } netfs_nput (np); + mutex_lock (&dnp->lock); np = 0; } else { - /* Normal nodes here */ + /* Normal nodes here for next filename component */ filename = nextname; - if (np == dnp) - netfs_nrele (dnp); - else - netfs_nput (dnp); + netfs_nrele (dnp); - if (!lastcomp) + if (lastcomp) + dnp = 0; + else { dnp = np; np = 0; } - else - dnp = 0; } } while (filename && *filename); @@ -363,14 +381,9 @@ netfs_S_dir_lookup (struct protid *diruser, out: if (np) - { - if (dnp == np) - netfs_nrele (np); - else - netfs_nput (np); - } + netfs_nput (np); if (dnp) - netfs_nput (dnp); + netfs_nrele (dnp); return error; } |