From dc0ba7ebf3109b2bbdd73c5f0a411ba6129c2daf Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 9 Oct 2007 15:33:05 +0000 Subject: [PATCH] netmount, localmount, halt.sh and net scripts now check OS specific flags to see if a mount is network mounted (linux = fstab, *bsd = "local" in mount options) or not, #192772. --- ChangeLog | 3 ++ init.d/halt.sh | 4 +- init.d/localmount | 6 ++- init.d/netmount | 40 +++++++++---------- sh/rc-functions.sh | 5 +++ sh/rc-mount.sh | 4 +- src/mountinfo.c | 95 ++++++++++++++++++++++++++++++++++++---------- 7 files changed, 111 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 710e125e..d18d0935 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ 09 Oct 2007; Roy Marples : + netmount, localmount, halt.sh and net scripts now check OS specific flags + to see if a mount is network mounted (linux = fstab, *bsd = "local" in + mount options) or not, #192772. txqueuelen_eth0= now works, #190538. 03 Oct 2007; Roy Marples : diff --git a/init.d/halt.sh b/init.d/halt.sh index f02c1336..f94f4d28 100755 --- a/init.d/halt.sh +++ b/init.d/halt.sh @@ -72,7 +72,9 @@ if [ "${RC_UNAME}" = "Linux" ] ; then fs="${fs}${fs:+|}${x}" done [ -n "${fs}" ] && fs="^(${fs})$" - do_unmount "mount -n -o remount,ro" "^(/dev|/dev/.*|/proc|/proc/.*|/sys|/sys/.*)$" "" "" "${fs}" + do_unmount "mount -n -o remount,ro" \ + --skip-point-regex "^(/dev|/dev/.*|/proc|/proc/.*|/sys|/sys/.*)$" \ + ${fs:+--skip-fstype-regex} ${fs} --nonetdev eoutdent eend $? unmounted=$? diff --git a/init.d/localmount b/init.d/localmount index 4b820267..001338c3 100755 --- a/init.d/localmount +++ b/init.d/localmount @@ -203,7 +203,8 @@ stop() { # Umount loopback devices einfo "Unmounting loopback devices" eindent - do_unmount "umount -d" "${no_umounts}" "^/dev/loop" + do_unmount "umount -d" --skip-point-regex "${no_umounts}" \ + --node-regex "^/dev/loop" eoutdent # Now everything else, except network filesystems as the @@ -215,7 +216,8 @@ stop() { fs="${fs}${fs:+|}${x}" done [ -n "${fs}" ] && fs="^(${fs})$" - do_unmount "umount" "${no_umounts}" "" "" "${fs}" + do_unmount "umount" --skip-point-regex "${no_umounts}" \ + ${fs:+--skip-fstype-regex} ${fs} --nonetdev eoutdent return 0 diff --git a/init.d/netmount b/init.d/netmount index 7ead6d9e..e4885a7c 100755 --- a/init.d/netmount +++ b/init.d/netmount @@ -21,7 +21,7 @@ depend() { # Only have portmap as a dependency if there is a nfs mount in fstab that # is set to mount at boot local pmap="" - if need_portmap ; then + if need_portmap; then [ -x /etc/init.d/rpcbind ] \ && pmap="rpcbind" \ || pmap="portmap" @@ -37,7 +37,7 @@ start() { [ -x /etc/init.d/rpcbind ] && pmap="rpcbind" local x= fs= - for x in ${RC_NET_FS_LIST} ; do + for x in ${RC_NET_FS_LIST}; do case "${x}" in nfs|nfs4) # If the nfsmount script took care of the nfs filesystems, @@ -47,7 +47,7 @@ start() { # Only try to mount NFS filesystems if portmap was started. # This is to fix "hang" problems for new users who do not # add portmap to the default runlevel. - if need_portmap && ! service_started "${pmap}" ; then + if need_portmap && ! service_started "${pmap}"; then continue fi ;; @@ -63,28 +63,28 @@ start() { stop() { local x= fs= + + ebegin "Unmounting network filesystems" + . "${RC_LIBDIR}/sh/rc-mount.sh" + for x in ${RC_NET_FS_LIST} ; do fs="${fs}${fs:+,}${x}" done - - ebegin "Unmounting network filesystems" - umount -at ${fs} - local retval=$? - eend ${retval} "Failed to simply unmount filesystems" - - if [ ${retval} -ne 0 ] ; then - . "${RC_LIBDIR}/sh/rc-mount.sh" - eindent - fs= - for x in ${RC_NET_FS_LIST} ; do - fs="${fs:+|}${x}" - done - do_unmount "umount" "" "" "^(${fs})$" - retval=$? - eoutdent + if [ -n "${fs}" ]; then + umount -at ${fs} || eerror "Failed to simply unmount filesystems" fi - return ${retval} + eindent + fs= + for x in ${RC_NET_FS_LIST}; do + fs="${fs}${fs:+|}${x}" + done + [ -n "${fs}" ] && fs="^(${fs})$" + do_unmount "umount" ${fs:+--fstype-regex} ${fs} --netdev + retval=$? + + eoutdent + eend ${retval} "Failed to unmount network filesystems" } # vim: set ts=4 : diff --git a/sh/rc-functions.sh b/sh/rc-functions.sh index 0e149432..c3f60dd7 100755 --- a/sh/rc-functions.sh +++ b/sh/rc-functions.sh @@ -26,6 +26,11 @@ stop_addon() { is_net_fs() { [ -z "$1" ] && return 1 + # Check OS specific flags to see if we're local or net mounted + mountinfo --quiet --netdev "$1" && return 0 + mountinfo --quiet --nonetdev "$1" && return 1 + + # Fall back on fs types local t=$(mountinfo --fstype "$1") for x in ${RC_NET_FS_LIST}; do [ "${x}" = "${t}" ] && return 0 diff --git a/sh/rc-mount.sh b/sh/rc-mount.sh index 94de3b65..08839c3e 100644 --- a/sh/rc-mount.sh +++ b/sh/rc-mount.sh @@ -12,8 +12,8 @@ do_unmount() { f_kill="-" fi - mountinfo ${2:+--skip-point-regex} $2 ${3:+--node-regex} $3 ${4:+--fstype-regex} $4 ${5:+--skip-fstype-regex} $5 | \ - while read mnt; do + shift + mountinfo "$@" | while read mnt; do case "${cmd}" in umount*) # If we're using the mount (probably /usr) then don't unmount us diff --git a/src/mountinfo.c b/src/mountinfo.c index 58a70b3e..d8cbc066 100644 --- a/src/mountinfo.c +++ b/src/mountinfo.c @@ -15,6 +15,8 @@ #include #include #include +#elif defined (__linux__) +#include #endif #include @@ -38,6 +40,12 @@ typedef enum { mount_options } mount_type; +typedef enum { + net_ignore, + net_yes, + net_no +} net_opts; + struct args { regex_t *node_regex; regex_t *skip_node_regex; @@ -47,10 +55,12 @@ struct args { regex_t *skip_options_regex; char **mounts; mount_type mount_type; + net_opts netdev; }; static int process_mount (char ***list, struct args *args, - char *from, char *to, char *fstype, char *options) + char *from, char *to, char *fstype, char *options, + int netdev) { char *p; @@ -62,26 +72,34 @@ static int process_mount (char ***list, struct args *args, return (-1); #endif - if (args->node_regex && - regexec (args->node_regex, from, 0, NULL, 0) != 0) - return (1); - if (args->skip_node_regex && - regexec (args->skip_node_regex, from, 0, NULL, 0) == 0) - return (1); + if (args->netdev == net_yes && netdev != -1) { + if (netdev != 0) + return (1); + } else if (args->netdev == net_no && netdev != -1) { + if (netdev != 1) + return (1); + } else { + if (args->node_regex && + regexec (args->node_regex, from, 0, NULL, 0) != 0) + return (1); + if (args->skip_node_regex && + regexec (args->skip_node_regex, from, 0, NULL, 0) == 0) + return (1); - if (args->fstype_regex && - regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0) - return (-1); - if (args->skip_fstype_regex && - regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) - return (-1); + if (args->fstype_regex && + regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0) + return (-1); + if (args->skip_fstype_regex && + regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) + return (-1); - if (args->options_regex && - regexec (args->options_regex, options, 0, NULL, 0) != 0) - return (-1); - if (args->skip_options_regex && - regexec (args->skip_options_regex, options, 0, NULL, 0) == 0) - return (-1); + if (args->options_regex && + regexec (args->options_regex, options, 0, NULL, 0) != 0) + return (-1); + if (args->skip_options_regex && + regexec (args->skip_options_regex, options, 0, NULL, 0) == 0) + return (-1); + } if (args->mounts) { bool found = false; @@ -169,9 +187,12 @@ static char **find_mounts (struct args *args) eerrorx ("getmntinfo: %s", strerror (errno)); for (i = 0; i < nmnts; i++) { + int netdev = 0; flags = mnts[i].f_flags & MNT_VISFLAGMASK; for (o = optnames; flags && o->o_opt; o++) { if (flags & o->o_opt) { + if (o->o_opt == MNT_LOCAL) + netdev = 1; if (! options) options = xstrdup (o->o_name); else { @@ -188,7 +209,8 @@ static char **find_mounts (struct args *args) mnts[i].f_mntfromname, mnts[i].f_mntonname, mnts[i].f_fstypename, - options); + options, + netdev); free (options); options = NULL; @@ -198,6 +220,20 @@ static char **find_mounts (struct args *args) } #elif defined (__linux__) +static struct mntent *getmntfile (const char *file) +{ + struct mntent *ent = NULL; + FILE *fp; + + fp = setmntent ("/etc/fstab", "r"); + while ((ent = getmntent (fp))) + if (strcmp (file, ent->mnt_dir) == 0) + break; + endmntent (fp); + + return (ent); +} + static char **find_mounts (struct args *args) { FILE *fp; @@ -208,18 +244,26 @@ static char **find_mounts (struct args *args) char *fst; char *opts; char **list = NULL; + struct mntent *ent; + int netdev; if ((fp = fopen ("/proc/mounts", "r")) == NULL) eerrorx ("getmntinfo: %s", strerror (errno)); while (fgets (buffer, sizeof (buffer), fp)) { + netdev = -1; p = buffer; from = strsep (&p, " "); to = strsep (&p, " "); fst = strsep (&p, " "); opts = strsep (&p, " "); - process_mount (&list, args, from, to, fst, opts); + if ((ent = getmntfile (to))) { + if (strstr (ent->mnt_opts, "_netdev")) + netdev = 0; + } + + process_mount (&list, args, from, to, fst, opts, netdev); } fclose (fp); @@ -260,6 +304,8 @@ static struct option longopts[] = { { "options", 0, NULL, 'i'}, { "fstype", 0, NULL, 's'}, { "node", 0, NULL, 't'}, + { "netdev", 0, NULL, 'e'}, + { "nonetdev", 0, NULL, 'E'}, longopts_COMMON { NULL, 0, NULL, 0} }; @@ -298,11 +344,18 @@ int mountinfo (int argc, char **argv) memset (&args, 0, sizeof (struct args)); args.mount_type = mount_to; + args.netdev = net_ignore; while ((opt = getopt_long (argc, argv, getoptstring, longopts, (int *) 0)) != -1) { switch (opt) { + case 'e': + args.netdev = net_yes; + break; + case 'E': + args.netdev = net_no; + break; case 'f': DO_REG (args.fstype_regex); break;