summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael I. Bushnell <mib@gnu.org>1995-06-19 20:32:10 +0000
committerMichael I. Bushnell <mib@gnu.org>1995-06-19 20:32:10 +0000
commitc14f7dd31c3631260e54237b873d8ab7560443fb (patch)
tree73122d84cf27cd000341e60f389c8dd063fae435
parentf9df00feb36c4e7531a5156e6e9b8b6df8e816ca (diff)
(diskfs_S_dir_lookup): Use new translator startup interface.
-rw-r--r--libdiskfs/dir-lookup.c167
1 files changed, 38 insertions, 129 deletions
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index cc9ce52c..4c05c704 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -169,148 +169,57 @@ diskfs_S_dir_lookup (struct protid *dircred,
/* If this is translated, start the translator (if necessary)
and return. */
- /* The check for `np != dnp' simplifies this code a great
- deal. Such a translator should already have been started,
- so there's no lossage in doing it this way. */
- if ((!lastcomp || !(flags & O_NOTRANS))
- && np != dnp)
+ if (((flags & O_NOTRANS == 0) || !lastcomp)
+ && (np->istranslated
+ || fshelp_translated (&diskfs_root_node->transbox)))
{
- mach_port_t control;
- uid_t *uids = 0, *gids = 0;
- int nuids = 0, ngids = 0;
- file_t dirfile = MACH_PORT_NULL;
-
- /* Be very careful not to hold an inode lock while fetching
- a translator lock and vice versa. */
-
- mutex_unlock (&np->lock);
- mutex_unlock (&dnp->lock);
+ mach_port_t dirport;
+
+ /* Create an unauthenticated port for DNP, and then
+ unlock it. */
+ dirport = (ports_get_right
+ (diskfs_make_protid
+ (diskfs_make_peropen (dnp, 0, dircred->po->dotdotport),
+ 0, 0, 0, 0)));
+ mach_port_insert_right (mach_task_self (), dirport, dirport,
+ MACH_MSG_TYPE_MAKE_SEND);
+ if (np != dnp)
+ mutex_unlock (&dnp-lock);
+
+ error = fshelp_fetch_root (&np->transbox, &dircred->po->dotdotport,
+ dirport, dircred->uids, dircred->nuids,
+ dircred->gids, dircred->ngids,
+ lastcomp ? flags : 0,
+ retry, retryname, returned_port);
- repeat_trans:
- mutex_lock (&np->translator.lock);
- if (np->translator.control != MACH_PORT_NULL)
+ if (error != ENOENT)
{
- control = np->translator.control;
- mach_port_mod_refs (mach_task_self (), control,
- MACH_PORT_RIGHT_SEND, 1);
- mutex_unlock (&np->translator.lock);
-
- /* Now we have a copy of the translator port that isn't
- dependent on the translator lock itself. Relock
- the directory, make a port from it, and then call
- fsys_getroot. */
-
- if (dirfile == MACH_PORT_NULL)
- {
- mutex_lock (&dnp->lock);
- dirfile = (ports_get_right
- (diskfs_make_protid
- (diskfs_make_peropen (dnp, 0,
- dircred->po->dotdotport),
- 0, 0, 0, 0)));
- mach_port_insert_right (mach_task_self (), dirfile, dirfile,
- MACH_MSG_TYPE_MAKE_SEND);
- mutex_unlock (&dnp->lock);
- }
-
- if (!uids)
- {
- uids = dircred->uids;
- gids = dircred->gids;
- nuids = dircred->nuids;
- ngids = dircred->ngids;
- }
-
- error = fsys_getroot (control, dirfile, MACH_MSG_TYPE_COPY_SEND,
- uids, nuids, gids, ngids,
- lastcomp ? flags : 0,
- retry, retryname, returned_port);
-
- /* If we got MACH_SEND_INVALID_DEST or MIG_SERVER_DIED, then
- the server is dead. Zero out the old control port and try
- everything again. */
-
- if (error == MACH_SEND_INVALID_DEST || error == MIG_SERVER_DIED)
- {
- mutex_lock (&np->translator.lock);
-
- /* Only zero it if it hasn't changed. */
-
- if (np->translator.control == control)
- fshelp_translator_drop (&np->translator);
- mutex_unlock (&np->translator.lock);
-
- /* And we're done with this port. */
- mach_port_deallocate (mach_task_self (), control);
-
- goto repeat_trans;
- }
-
- /* Otherwise, we're done; return to the user. If there
- are more components after this name, be sure to append
- them to the user's retry path. */
- if (!error && !lastcomp)
+ diskfs_nrele (dnp);
+ diskfs_nput (np);
+ *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
+ if (!lastcomp && !error)
{
strcat (retryname, "/");
strcat (retryname, nextname);
}
- *returned_port_poly = MACH_MSG_TYPE_MOVE_SEND;
- diskfs_nrele (dnp);
- diskfs_nrele (np);
- mach_port_deallocate (mach_task_self (), dirfile);
return error;
}
- else
+
+ /* ENOENT means there was a hiccup, and the translator
+ vanished while NP was unlocked inside fshelp_fetch_root.
+ Reacquire the locks, and continue as normal. */
+ error = 0;
+ if (np != dnp)
{
- /* If we get here, then we have no active control port.
- Check to see if there is a passive translator, and if so
- repeat the translator check. */
- mutex_unlock (&np->translator.lock);
-
- mutex_lock (&np->lock);
- if (np->istranslated)
+ if (!strcmp (path, ".."))
+ mutex_lock (&dnp->lock);
+ else
{
- /* Start the translator. */
- if (dirfile == MACH_PORT_NULL)
- {
- /* This code is the same as above. */
- mutex_unlock (&np->lock);
- mutex_lock (&dnp->lock);
- dirfile = (ports_get_right
- (diskfs_make_protid
- (diskfs_make_peropen (dnp, 0,
- dircred->po
- ->dotdotport),
- 0, 0, 0, 0)));
- mach_port_insert_right (mach_task_self (), dirfile,
- dirfile,
- MACH_MSG_TYPE_MAKE_SEND);
- mutex_unlock (&dnp->lock);
- mutex_lock (&np->lock);
- }
- error = diskfs_start_translator (np, dirfile, dircred);
- if (error)
- {
- mach_port_deallocate (mach_task_self (), dirfile);
- diskfs_nrele (dnp);
- diskfs_nput (np);
- return error;
- }
- goto repeat_trans;
+ mutex_unlock (&np->lock);
+ mutex_lock (&dnp->lock);
+ mutex_lock (&np->lock);
}
}
-
- /* We're here if we tried the translator check, and it
- failed. Lock everything back, and make sure we do it
- in the right order. */
- if (strcmp (path, ".."))
- {
- mutex_unlock (&np->lock);
- mutex_lock (&dnp->lock);
- mutex_lock (&np->lock);
- }
- else
- mutex_lock (&dnp->lock);
}
if (S_ISLNK (np->dn_stat.st_mode)