umount.c revision 081901271249c8ffce8241a6035a9f13fb1c0aa9
160N/A * The contents of this file are subject to the terms of the 160N/A * Common Development and Distribution License, Version 1.0 only 160N/A * (the "License"). You may not use this file except in compliance 160N/A * See the License for the specific language governing permissions 160N/A * and limitations under the License. 160N/A * When distributing Covered Code, include this CDDL HEADER in each 160N/A * If applicable, add the following below this CDDL HEADER, with the 160N/A * fields enclosed by brackets "[]" replaced with your own identifying 160N/A * information: Portions Copyright [yyyy] [name of copyright owner] 160N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 160N/A * Use is subject to license terms. 160N/A/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 160N/A/* All Rights Reserved */ 160N/A#
pragma ident "%Z%%M% %I% %E% SMI" 160N/A * Currently, mounting cachefs's simultaneous uncovers various problems. 160N/A * For the short term, we serialize cachefs activity while we fix 160N/A * The basic mount struct that describes an mnttab entry. 160N/A * It is used both in an array and as a linked list elem. 160N/A * If the automatic flag (-a) is given and mount points are not specified 160N/A * on the command line, then do not attempt to umount these. These 160N/A * generally need to be kept mounted until system shutdown. static int mcompar(
const void *,
const void *);
/* copy '--' to specific */ * mnttab may be a symlink to a file in another file system. * This happens during install when / is mounted read-only * and /etc/mnttab is symlinked to a file in /tmp. * If this is the case, we need to follow the symlink to the * read-write file itself so that the subsequent mnttab.temp * open and rename will work. * call the realpath() here, so that if the user is * trying to umount an autofs directory, the directory * Read the whole mnttab into memory. "%s: warning: no entries found in %s\n"),
* if realpath fails, it can't be a mount point, so we'll * go straight to the code that treats the arg as a special. * if realpath succeeds, it could be a special or a mount point; * we'll start by assuming it's a mount point, and if it's not, * try to treat it as a special. * we'll have the appropriate record; if it fails * we'll assume the arg is a special of some sort * Since stackable mount is allowed (RFE 2001535), * we will un-mount the last entry in the MNTTAB that matches. * Perhaps there is a bogus mnttab entry that * assume it's a device (special) now * This is a device. Now we want to know if * it stackmounted on by something else. * The original fix for bug 1103850 has a * problem with lockfs (bug 1119731). This "%s: warning: %s not in mnttab\n"),
/* try to exec the dependent portion */ "%s: FSType %s exceeds %d characters\n"),
/* build the full pathname of the fstype dependent command. */ * create the new arg list, and end the list with a /* set the new argv[0] to the filename */ /* Try to exec the fstype dependent umount. */ * No fstype independent executable then. We'll go generic /* don't use -o with generic */ "%s: %s specific umount does not exist; -o suboption ignored\n"),
* Try to umount the mountpoint. * If that fails, try the corresponding special. * (This ordering is necessary for nfs umounts.) * (for remote resources: if the first umount returns EBUSY * don't call umount again - umount() with a resource name * will return a misleading error to the user gettext(
"%s: %s no such file or directory\n"),
"Usage:\n%s [-f] [-V] [-o specific_options] {special | mount-point}\n"),
"%s -a [-f] [-V] [-o specific_options] [mount_point ...]\n"),
myname);
gettext(
"%s: line in mnttab exceeds %d characters\n"),
gettext(
"%s: line in mnttab has too few entries\n"),
* Search the mlist linked list for the * first match of specp or mntp. The list is expected to be in reverse * If both are specified, then both have to match. * Returns the (mountent_t *) of the match, otherwise returns NULL. * Perform the parallel version of umount. Returns 0 if no errors occurred, * If no mount points are specified and none were found in mnttab, * This is the process scaling section. After running a series * of tests based on the number of simultaneous processes and * processors available, optimum performance was achieved near or * The parent needs to maintain 3 of its own fd's, plus 2 for * each child (the stdout and stderr pipes). maxfd = (
maxfd /
2) -
6;
/* 6 takes care of temporary */ /* periods of open fds */ maxrun =
4;
/* sanity check */ if (
count == 0)
/* not an error, just none found */ * Sort the entries based on their mount level only if lofs's are * If we do not detect a lofs by now, we never will. * Now link them up so that a given pid is easier to find when * we go to clean up after they are done. * Try to handle interrupts in a reasonable way. * Returns a mountent_t array based on mntlist. If mntlist is NULL, then * it returns all mnttab entries with a few exceptions. Sets the global * variable listlength to the number of entries in the array. * No mount list specified: take all mnttab mount points * except for a few cases. * A list of mount points was specified on the command line. * Build an array out of these. gettext(
"%s: warning: can't resolve %s\n"),
* Then we've reached the end without finding * what we are looking for, but we still have to * try to umount it: append it to mntarray. "%s: warning: %s not found in %s\n"),
* Returns the tail of a linked list of all mnttab entries. I.e, it's faster * to return the mnttab in reverse order. * Sets listlength to the number of entries in the list. * Returns NULL if none are found. * Main loop for the forked children: * Check to see if we cross a mount level: e.g., * /a/b/c -> /a/b. If so, we need to wait for all current * umounts to finish before umounting the rest. * Also, we unmount serially as long as there are lofs's * to mount to avoid improper umount ordering. * We can now go to parallel umounting. mp = *
ml;
/* possible first entry */ lofscnt--;
/* so we don't do this again */ if (
pid == 0) {
/* child */ * cleanup the existing children and exit with an error * Let the stragglers finish. * Waits for 1 child to die. * Returns -1 if no children are left to wait for. * Returns 0 if a child died without an error. * Returns 1 if a child died with an error. * Sets the global exitcode if an error occurred. ret =
1;
/* assume some kind of error */ * Find our child so we can process its std output, if any. * This search gets smaller and smaller as children are cleaned * Found: let's remove it from this list. * This should never happen. * Sort in descending order of "mount level". For example, /a/b/c is mcompar(
const void *a,
const void *b)
* The purpose of this routine is to form stdout and stderr * pipes for the children's output. The parent then reads and writes it * out it serially in order to ensure that the output is * Make a stdout and stderr pipe. This should never fail. * Don't block on an empty pipe. * Called by a child to attach its stdout and stderr to the write side of * Parent uses this to print any stdout or stderr output issued by * Let the stragglers finish.