From: Ion Badulescu Date: Tue, 18 Jan 2005 03:01:24 +0000 (+0000) Subject: * NEWS: document the ability to restart old mount points X-Git-Tag: before-retrans-udp-tcp-split~5 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=80effa2e16240eae0fbcea712b8278923d19600f;p=am-utils-6.0.git * NEWS: document the ability to restart old mount points * amd/map.c (mount_auto_node): force the fileid of the root to be 1, so that it won't change between restarts; use the root filesystem's own methods instead of hard-coding the use of the default methods * conf/transp/transp_tli.c (create_nfs_service): better cleanup on error conditions. (bind_resv_port2): allow the caller to request a certain port. * conf/transp/transp_sockets.c (bind_resv_port): allow the caller to request a certain port. (create_nfs_service): better cleanup on error conditions. * amd/restart.c (restart_automounter_nodes): new function, takes care of restarting automounter NFS mount points (autofs will come later). (restart): skip all automounter mount points. * amd/nfs_subr.c (fh_to_mp3, mp_to_fh): new filehandle implementation: if the path to the node is shorter than sizeof(fh) chars (currently 32 chars for a NFSv2 fh), simply store it inside the fh. For longer paths, keep the old implementation. * amd/nfs_start.c (mount_automounter): reorder things so that restarting the toplvl filesystems occurs before anything else (so that we can grab all the ports we need before we accidentally use them for something else). * amd/mntfs.c (locate_mntfs): remove dead code; add special handling of restarted toplvl filesystems. * amd/mapc.c (root_keyiter): fix up a comment. * amd/map.c (path_to_exported_ap): new function, searches for and returns a node by the path to it. (get_root_nfs_fh): remove unnecessary fiddling with the root fh. * config.guess.long: support Red Hat Enterprise Linux --- diff --git a/ChangeLog b/ChangeLog index 5a0e385..3e449a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2005-01-17 Ion Badulescu + + * NEWS: document the ability to restart old mount points + + * amd/map.c (mount_auto_node): force the fileid of the + root to be 1, so that it won't change between restarts; use the + root filesystem's own methods instead of hard-coding the use of + the default methods + + * conf/transp/transp_tli.c (create_nfs_service): better cleanup on + error conditions. + (bind_resv_port2): allow the caller to request a certain port. + + * conf/transp/transp_sockets.c (bind_resv_port): allow the caller + to request a certain port. + (create_nfs_service): better cleanup on error conditions. + + * amd/restart.c (restart_automounter_nodes): new function, takes + care of restarting automounter NFS mount points (autofs will come + later). + (restart): skip all automounter mount points. + + * amd/nfs_subr.c (fh_to_mp3, mp_to_fh): new filehandle + implementation: if the path to the node is shorter than sizeof(fh) + chars (currently 32 chars for a NFSv2 fh), simply store it inside + the fh. For longer paths, keep the old implementation. + + * amd/nfs_start.c (mount_automounter): reorder things so that + restarting the toplvl filesystems occurs before anything else (so + that we can grab all the ports we need before we accidentally use + them for something else). + + * amd/mntfs.c (locate_mntfs): remove dead code; add special + handling of restarted toplvl filesystems. + + * amd/mapc.c (root_keyiter): fix up a comment. + + * amd/map.c (path_to_exported_ap): new function, searches for and + returns a node by the path to it. + (get_root_nfs_fh): remove unnecessary fiddling with the root fh. + + * config.guess.long: support Red Hat Enterprise Linux + 2005-01-17 Erez Zadok * libamu/util.c (rmdirs): prevent amd from logging 'Read-only diff --git a/NEWS b/NEWS index 3f26c82..b888d24 100644 --- a/NEWS +++ b/NEWS @@ -46,12 +46,15 @@ value, and you get ESTALE errors on your particular OS, then set this value back to 0 seconds. +- support restarting the automounter's own mount points (only over NFS, + for now). + - fully support WebNFS as per RFC 2054. It now tries v3/TCP first, falling back to v2/UDP if this doesn't work. The "webnfs" pseudo-mount options has been renamed (again) to "public" to match Solaris 2. - restructured the restarting of already-mounted filesystems, in the process - also fixing a problem with restarting nfsx components + also fixing a problem with restarting nfsx components. - support escaped slashes, needed for SMB mounts. Use '\\\/\\\/' in a string to get a double slash. diff --git a/amd/amd.c b/amd/amd.c index e88eaea..e50a47f 100644 --- a/amd/amd.c +++ b/amd/amd.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: amd.c,v 1.30 2005/01/14 01:14:00 ezk Exp $ + * $Id: amd.c,v 1.31 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -571,7 +571,6 @@ main(int argc, char *argv[]) if (gopt.flags & CFM_PROCESS_LOCK) { do_memory_locking(); } - sprintf(pid_fsname, "%s:(pid%ld)", am_get_hostname(), (long) am_mypid); do_mapc_reload = clocktime() + gopt.map_reload_interval; diff --git a/amd/amd.h b/amd/amd.h index 8ca31ef..653e6ad 100644 --- a/amd/amd.h +++ b/amd/amd.h @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: amd.h,v 1.55 2005/01/14 01:14:00 ezk Exp $ + * $Id: amd.h,v 1.56 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -485,6 +485,7 @@ struct am_node { * when transmitted. */ struct am_fh { + int fhh_type; /* old or new am_fh */ int fhh_pid; /* process id */ int fhh_id; /* map id */ u_int fhh_gen; /* generation number */ @@ -533,6 +534,7 @@ extern void am_unmounted(am_node *); extern am_node *get_exported_ap(int index); extern am_node *get_first_exported_ap(int *index); extern am_node *get_next_exported_ap(int *index); +extern am_node *path_to_exported_ap(char *path); extern am_node *exported_ap_alloc(void); extern am_node *find_mf(mntfs *); extern am_node *next_map(int *); @@ -594,6 +596,7 @@ extern void ops_showfstypes(char *outbuf); extern void rem_que(qelem *); extern void reschedule_timeout_mp(void); extern void restart(void); +extern void restart_automounter_nodes(void); extern int root_keyiter(key_fun *, opaque_t); extern void root_newmap(const char *, const char *, const char *, const cf_map_t *); extern void run_task(task_fun *, opaque_t, cb_fun *, opaque_t); diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c index e7d7935..f232d9d 100644 --- a/amd/amfs_generic.c +++ b/amd/amfs_generic.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: amfs_generic.c,v 1.27 2005/01/03 20:56:45 ezk Exp $ + * $Id: amfs_generic.c,v 1.28 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -727,21 +727,6 @@ amfs_bgmount(struct continuation *cp) if (mf->mf_fo && mf->mf_fo->opt_sublink) mp->am_link = strdup(mf->mf_fo->opt_sublink); - if (mf->mf_flags & MFF_MOUNTED) { - dlog("duplicate mount of \"%s\" ...", mf->mf_info); - /* - * Skip initial processing of the mountpoint if already mounted. - * This could happen if we have multiple sublinks into the same f/s. - */ - goto already_mounted; - } - - if (mf->mf_fo->fs_mtab) { - plog(XLOG_MAP, "Trying mount of %s on %s fstype %s mount_type %s", - mf->mf_fo->fs_mtab, mf->mf_mount, p->fs_type, - mp->am_flags & AMF_AUTOFS ? "autofs" : "non-autofs"); - } - /* * Will usually need to play around with the mount nodes * file attribute structure. This must be done here. @@ -758,6 +743,22 @@ amfs_bgmount(struct continuation *cp) else mk_fattr(&mp->am_fattr, NFLNK); + if (mf->mf_flags & MFF_MOUNTED) { + dlog("duplicate mount of \"%s\" ...", mf->mf_info); + /* + * Skip initial processing of the mountpoint if already mounted. + * This could happen if we have multiple sublinks into the same f/s, + * or if we are restarting an already-mounted filesystem. + */ + goto already_mounted; + } + + if (mf->mf_fo->fs_mtab) { + plog(XLOG_MAP, "Trying mount of %s on %s fstype %s mount_type %s", + mf->mf_fo->fs_mtab, mf->mf_mount, p->fs_type, + mp->am_flags & AMF_AUTOFS ? "autofs" : "non-autofs"); + } + if (p->fs_init && !(mf->mf_flags & MFF_RESTART)) this_error = p->fs_init(mf); diff --git a/amd/autil.c b/amd/autil.c index 414591e..4efd9b9 100644 --- a/amd/autil.c +++ b/amd/autil.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: autil.c,v 1.47 2005/01/14 01:14:00 ezk Exp $ + * $Id: autil.c,v 1.48 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -268,9 +268,8 @@ mf_mounted(mntfs *mf) /* * Do mounted callback */ - if (mf->mf_ops->mounted) { - (*mf->mf_ops->mounted) (mf); - } + if (mf->mf_ops->mounted) + mf->mf_ops->mounted(mf); free_opts(mf->mf_fo); XFREE(mf->mf_fo); diff --git a/amd/map.c b/amd/map.c index c0bbfdb..ed12803 100644 --- a/amd/map.c +++ b/amd/map.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: map.c,v 1.50 2005/01/03 20:56:45 ezk Exp $ + * $Id: map.c,v 1.51 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -143,6 +143,25 @@ get_exported_ap(int index) } +/* + * Get exported_ap by path + */ +am_node * +path_to_exported_ap(char *path) +{ + int index; + am_node *mp; + + mp = get_first_exported_ap(&index); + while (mp != NULL) { + if (STREQ(mp->am_path, path)) + break; + mp = get_next_exported_ap(&index); + } + return mp; +} + + /* * Resize exported_ap map */ @@ -529,14 +548,6 @@ get_root_nfs_fh(char *dir) am_node *mp = get_root_ap(dir); if (mp) { mp_to_fh(mp, &nfh); - /* - * Patch up PID to match main server... - */ - if (!foreground) { - long pid = getppid(); - ((struct am_fh *) &nfh)->fhh_pid = pid; - dlog("get_root_nfs_fh substitutes pid %ld", (long) pid); - } return &nfh; } @@ -595,18 +606,19 @@ mount_auto_node(char *dir, opaque_t arg) { int error = 0; am_node *mp = (am_node *) arg; - am_node *am; + am_node *new_mp; + + new_mp = mp->am_mnt->mf_ops->lookup_child(mp, dir, &error, VLOOK_CREATE); + if (new_mp && error < 0) { + /* + * We can't allow the fileid of the root node to change. + * Should be ok to force it to 1, always. + */ + new_mp->am_gen = new_mp->am_fattr.na_fileid = 1; + + new_mp = mp->am_mnt->mf_ops->mount_child(new_mp, &error); + } - /* - * this should be: - * mp->am_mnt->mf_opts->lookup_child(.....); - * - * as it is, it uses the generic methods regardless - * of the parent filesystem's type - */ - am = amfs_generic_lookup_child(mp, dir, &error, VLOOK_CREATE); - if (am && error < 0) - am = amfs_generic_mount_child(am, &error); if (error > 0) { errno = error; /* XXX */ plog(XLOG_ERROR, "Could not mount %s: %m", dir); diff --git a/amd/mapc.c b/amd/mapc.c index 3b5584c..be11735 100644 --- a/amd/mapc.c +++ b/amd/mapc.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: mapc.c,v 1.21 2005/01/03 20:56:45 ezk Exp $ + * $Id: mapc.c,v 1.22 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -1042,7 +1042,7 @@ mapc_keyiter(mnt_map *m, key_fun *fn, opaque_t arg) /* * Iterate on the root map and call (*fn)() on the key of all the nodes. - * Finally throw away the root map. + * Returns the number of entries in the root map. */ int root_keyiter(key_fun *fn, opaque_t arg) diff --git a/amd/mntfs.c b/amd/mntfs.c index 8d0b595..dfa9490 100644 --- a/amd/mntfs.c +++ b/amd/mntfs.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: mntfs.c,v 1.35 2005/01/03 20:56:45 ezk Exp $ + * $Id: mntfs.c,v 1.36 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -134,37 +134,31 @@ locate_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, ch */ if (mf->mf_ops != &amfs_error_ops) continue; - else - return dup_mntfs(mf); + return dup_mntfs(mf); } -#if 0 - if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) { + dlog("mf->mf_flags = %#x", mf->mf_flags); + mf->mf_fo = mo; + if ((mf->mf_flags & MFF_RESTART) && amd_state < Finishing) { /* * Restart a previously mounted filesystem. */ - mntfs *mf2 = alloc_mntfs(&amfs_inherit_ops, mo, mp, info, auto_opts, mopts, remopts); dlog("Restarting filesystem %s", mf->mf_mount); /* - * Remember who we are restarting + * If we are restarting an amd internal filesystem, + * we need to initialize it a bit. + * + * We know it's internal because it is marked as toplvl. */ - mf2->mf_private = (voidp) dup_mntfs(mf); - mf2->mf_prfree = free_mntfs; - return mf2; - } + if (mf->mf_ops == &amfs_toplvl_ops) { + mf->mf_ops = ops; + mf->mf_info = strealloc(mf->mf_info, info); + ops->mounted(mf); /* XXX: not right, but will do for now */ + } - mf->mf_fo = mo; -#else - mf->mf_fo = mo; - if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) { - /* - * Restart a previously mounted filesystem. - */ - dlog("Restarting filesystem %s", mf->mf_mount); return mf; } -#endif if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) { fserver *fs; diff --git a/amd/nfs_start.c b/amd/nfs_start.c index d4c3471..61fe39e 100644 --- a/amd/nfs_start.c +++ b/amd/nfs_start.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: nfs_start.c,v 1.22 2005/01/03 20:56:45 ezk Exp $ + * $Id: nfs_start.c,v 1.23 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -52,7 +52,7 @@ #endif /* not SELECT_MAXWAIT */ SVCXPRT *nfsxprt; -u_short nfs_port; +u_short nfs_port = 0; #ifndef HAVE_SIGACTION # define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP)) @@ -208,21 +208,19 @@ run_rpc(void) struct timeval tvv; int nsel; time_t now; -#ifdef HAVE_SVC_GETREQSET fd_set readfds; +#ifdef HAVE_SVC_GETREQSET memmove(&readfds, &svc_fdset, sizeof(svc_fdset)); - FD_SET(fwd_sock, &readfds); #else /* not HAVE_SVC_GETREQSET */ - fd_set readfds; FD_ZERO(&readfds); # ifdef HAVE_FD_SET_FDS_BITS readfds.fds_bits[0] = svc_fds; # else /* not HAVE_FD_SET_FDS_BITS */ readfds = svc_fds; # endif /* not HAVE_FD_SET_FDS_BITS */ - FD_SET(fwd_sock, &readfds); #endif /* not HAVE_SVC_GETREQSET */ + FD_SET(fwd_sock, &readfds); checkup(); @@ -337,12 +335,46 @@ mount_automounter(int ppid) int udp_soAMQ, tcp_soAMQ; struct netconfig *udp_amqncp, *tcp_amqncp; + /* + * This must be done first, because it attempts to bind + * to various UDP ports and we don't want anything else + * potentially taking over those ports before we get a chance + * to reserve them. + */ + if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS) + restart_automounter_nodes(); + + /* + * Start RPC forwarding + */ + if (fwd_init() != 0) + return 3; + + /* + * Construct the root automount node + */ + make_root_node(); + + /* + * Pick up the pieces from a previous run + * This is likely to (indirectly) need the rpc_fwd package + * so it *must* come after the call to fwd_init(). + */ + if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS) + restart(); + /* * Create the nfs service for amd + * If nfs_port is already initialized, it means we + * already created the service during restart_automounter_nodes(). */ - ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); - if (ret != 0) - return ret; + if (nfs_port == 0) { + ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2); + if (ret != 0) + return ret; + } + sprintf(pid_fsname, "%s:(pid%ld,port%u)", am_get_hostname(), (long) am_mypid, nfs_port); + /* security: if user sets -D amq, don't even create listening socket */ if (!amuDebug(D_AMQ)) { ret = create_amq_service(&udp_soAMQ, &udp_amqp, &udp_amqncp, &tcp_soAMQ, &tcp_amqp, &tcp_amqncp); @@ -364,25 +396,6 @@ mount_automounter(int ppid) } #endif /* HAVE_FS_AUTOFS */ - /* - * Start RPC forwarding - */ - if (fwd_init() != 0) - return 3; - - /* - * Construct the root automount node - */ - make_root_node(); - - /* - * Pick up the pieces from a previous run - * This is likely to (indirectly) need the rpc_fwd package - * so it *must* come after the call to fwd_init(). - */ - if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS) - restart(); - /* * Mount the top-level auto-mountpoints */ diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c index 37741ca..55b7dd0 100644 --- a/amd/nfs_subr.c +++ b/amd/nfs_subr.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: nfs_subr.c,v 1.21 2005/01/03 20:56:45 ezk Exp $ + * $Id: nfs_subr.c,v 1.22 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -612,19 +612,39 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) struct am_fh *fp = (struct am_fh *) fhp; am_node *ap = 0; - /* - * Check process id matches - * If it doesn't then it is probably - * from an old kernel cached filehandle - * which is now out of date. - */ - if (fp->fhh_pid != am_mypid) - goto drop; + if (fp->fhh_type != 0) { + /* New filehandle type */ + char *path = xmalloc(sizeof(*fhp) + 1); + memset(path, 0, sizeof(fhp) + 1); + strncpy(path, (char *) fhp, sizeof(*fhp)); + /* dlog("fh_to_mp3: new filehandle: %s", path); */ - /* - * Get hold of the supposed mount node - */ - ap = get_exported_ap(fp->fhh_id); + ap = path_to_exported_ap(path); + XFREE(path); + } else { + /* dlog("fh_to_mp3: old filehandle: %d", fp->fhh_id); */ + /* + * Check process id matches + * If it doesn't then it is probably + * from an old kernel cached filehandle + * which is now out of date. + */ + if (fp->fhh_pid != am_mypid) + goto drop; + + /* + * Get hold of the supposed mount node + */ + ap = get_exported_ap(fp->fhh_id); + /* + * Check the generation number in the node + * matches the one from the kernel. If not + * then the old node has been timed out and + * a new one allocated. + */ + if (ap->am_gen != fp->fhh_gen) + ap = 0; + } /* * If it doesn't exists then drop the request @@ -632,17 +652,6 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) if (!ap) goto drop; - /* - * Check the generation number in the node - * matches the one from the kernel. If not - * then the old node has been timed out and - * a new one allocated. - */ - if (ap->am_gen != fp->fhh_gen) { - ap = 0; - goto drop; - } - #if 0 /* * If the node is hung then locate a new node @@ -747,29 +756,38 @@ fh_to_mp(am_nfs_fh *fhp) void mp_to_fh(am_node *mp, am_nfs_fh *fhp) { - struct am_fh *fp = (struct am_fh *) fhp; + int pathlen; memset((char *) fhp, 0, sizeof(am_nfs_fh)); - /* - * Take the process id - */ - fp->fhh_pid = am_mypid; + pathlen = strlen(mp->am_path); + if (pathlen <= sizeof(*fhp)) { + /* dlog("mp_to_fh: new filehandle: %s", mp->am_path); */ + strncpy((char *) fhp, mp->am_path, pathlen); + } else { + struct am_fh *fp = (struct am_fh *) fhp; - /* - * ... the map number - */ - fp->fhh_id = mp->am_mapno; + /* + * Take the process id + */ + fp->fhh_pid = am_mypid; - /* - * ... and the generation number - */ - fp->fhh_gen = mp->am_gen; + /* + * ... the map number + */ + fp->fhh_id = mp->am_mapno; - /* - * ... to make a "unique" triple that will never - * be reallocated except across reboots (which doesn't matter) - * or if we are unlucky enough to be given the same - * pid as a previous amd (very unlikely). - */ + /* + * ... and the generation number + */ + fp->fhh_gen = mp->am_gen; + + /* + * ... to make a "unique" triple that will never + * be reallocated except across reboots (which doesn't matter) + * or if we are unlucky enough to be given the same + * pid as a previous amd (very unlikely). + */ + /* dlog("mp_to_fh: old filehandle: %d", fp->fhh_id); */ + } } diff --git a/amd/restart.c b/amd/restart.c index ad71d8b..e181171 100644 --- a/amd/restart.c +++ b/amd/restart.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: restart.c,v 1.11 2005/01/03 20:56:45 ezk Exp $ + * $Id: restart.c,v 1.12 2005/01/18 03:01:24 ib42 Exp $ * */ @@ -122,9 +122,7 @@ restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) * * Scan through the mount list finding all "interesting" mount points. * Next hack up partial data structures and add the mounted file - * system to the list of known filesystems. This will leave a - * dangling reference to that filesystems, so when the filesystem is - * finally inherited, an extra "free" must be done on it. + * system to the list of known filesystems. * * This module relies on internal details of other components. If * you change something else make *sure* restart() still works. @@ -147,6 +145,19 @@ restart(void) mntent_t *me = mlp->mnt; am_ops *fs_ops = 0; + if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { + /* + * NFS entry, or possibly an Amd entry... + * The mnt_fsname for daemon mount points is + * host:(pidXXX) + * or (seen on Solaris) + * host:daemon(pidXXX) + */ + char *colon = strchr(me->mnt_fsname, ':'); + if (colon && strstr(colon, "(pid")) + continue; + } + /* Search for the correct filesystem ops */ fs_ops = ops_search(me->mnt_type); @@ -157,6 +168,53 @@ restart(void) if (!fs_ops) fs_ops = &amfs_link_ops; + restart_fake_mntfs(me, fs_ops); + } + + /* + * Free the mount list + */ + free_mntlist(ml); +} + + +/* + * Handle an amd restart for amd's own mount points. + * + * Scan through the mount list finding all daemon mount points + * (determined by the presence of a pid inside the mount info). + * Next hack up partial data structures and add the mounted file + * system to the list of known filesystems. + * + * This module relies on internal details of other components. If + * you change something else make *sure* restart() still works. + */ +void +restart_automounter_nodes(void) +{ + /* + * Read the existing mount table + */ + mntlist *ml, *mlp; + + /* Reasonably sized list of restarted nfs ports */ + u_short old_ports[256]; + { + int i; + for (i = 0; i < 256; i++) + old_ports[i] = 0; + } + + /* + * For each entry, find nfs, ufs or auto mounts + * and create a partial am_node to represent it. + */ + for (mlp = ml = read_mtab("restart", mnttab_file_name); + mlp; + mlp = mlp->mnext) { + mntent_t *me = mlp->mnt; + am_ops *fs_ops = 0; + if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* * NFS entry, or possibly an Amd entry... @@ -166,14 +224,71 @@ restart(void) * host:daemon(pidXXX) */ char *colon = strchr(me->mnt_fsname, ':'); - if (colon && strstr(colon, "(pid")) { + long pid; + u_short port; + int err = 1; + plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir); - fs_ops = &amfs_link_ops; + + /* Is the old automounter still alive? */ + if (sscanf(colon, "%*[^(](pid%ld%*[,)]", &pid) != 1) { + plog(XLOG_WARNING, "Can't parse pid in %s", me->mnt_fsname); + goto give_up; + } + if (kill(pid, 0) != -1 || errno != ESRCH) { + plog(XLOG_WARNING, "Automounter (pid: %ld) still alive", pid); + goto give_up; + } + + /* + * Do we have a map for this mount point? + * Who cares, we'll restart anyway -- getting ESTALE + * is way better than hanging. + */ + + /* Can we restart it? Only if it tells us what port it was using... */ + if (sscanf(colon, "%*[^,],port%hu)", &port) != 1) { + plog(XLOG_WARNING, "No port specified for %s", me->mnt_fsname); + goto give_up; + } + + /* Maybe we already own that port... */ + if (port != nfs_port) { + int i; + for (i = 0; i < 256; i++) { + if (old_ports[i] == port || + old_ports[i] == 0) + break; + } + if (i == 256) { + plog(XLOG_WARNING, "Too many open ports (256)"); + goto give_up; + } + + if (old_ports[i] == 0) { + int soNFS; + SVCXPRT *nfsxprt; + if (create_nfs_service(&soNFS, &port, &nfsxprt, nfs_program_2) != 0) { + plog(XLOG_WARNING, "Can't bind to port %u", port); + goto give_up; + } + old_ports[i] = nfs_port = port; + } + } + err = 0; + + give_up: + if (err) { + plog(XLOG_WARNING, "Can't restart %s, leaving it alone", me->mnt_dir); + fs_ops = &amfs_link_ops; + } else { + fs_ops = &amfs_toplvl_ops; + } + + restart_fake_mntfs(me, fs_ops); } } - - restart_fake_mntfs(me, fs_ops); } /* diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c index c7eb9fd..ab260b4 100644 --- a/conf/transp/transp_sockets.c +++ b/conf/transp/transp_sockets.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: transp_sockets.c,v 1.30 2005/01/14 03:29:45 ezk Exp $ + * $Id: transp_sockets.c,v 1.31 2005/01/18 03:01:24 ib42 Exp $ * * Socket specific utilities. * -Erez Zadok @@ -129,16 +129,21 @@ bind_resv_port(int so, u_short *pp) memset((voidp) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; - port = IPPORT_RESERVED; - - do { - --port; - sin.sin_port = htons(port); + if (pp && *pp > 0) { + sin.sin_port = htons(*pp); rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); - } while (rc < 0 && (int) port > IPPORT_RESERVED / 2); + } else { + port = IPPORT_RESERVED; - if (pp && rc == 0) - *pp = port; + do { + --port; + sin.sin_port = htons(port); + rc = bind(so, (struct sockaddr *) &sin, sizeof(sin)); + } while (rc < 0 && (int) port > IPPORT_RESERVED / 2); + + if (pp && rc == 0) + *pp = port; + } return rc; } @@ -249,21 +254,28 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* *soNFSp = socket(AF_INET, SOCK_DGRAM, 0); - if (*soNFSp < 0 || bind_resv_port(*soNFSp, NULL) < 0) { + if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) { plog(XLOG_FATAL, "Can't create privileged nfs port (socket)"); + if (*soNFSp >= 0) + close(*soNFSp); return 1; } if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) { plog(XLOG_FATAL, "cannot create rpc/udp service"); + close(*soNFSp); return 2; } if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) { plog(XLOG_FATAL, "Can't create privileged nfs port"); + svc_destroy(*nfs_xprtp); + close(*soNFSp); return 1; } if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) { plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", (u_long) NFS_PROGRAM, (u_long) NFS_VERSION); + svc_destroy(*nfs_xprtp); + close(*soNFSp); return 3; } diff --git a/conf/transp/transp_tli.c b/conf/transp/transp_tli.c index 4488f95..7e0851e 100644 --- a/conf/transp/transp_tli.c +++ b/conf/transp/transp_tli.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * - * $Id: transp_tli.c,v 1.25 2005/01/14 03:29:45 ezk Exp $ + * $Id: transp_tli.c,v 1.26 2005/01/18 03:01:24 ib42 Exp $ * * TLI specific utilities. * -Erez Zadok @@ -154,7 +154,7 @@ bind_resv_port(int td, u_short *pp) * How to bind to reserved ports. * (port-only) version. */ -int +static int bind_resv_port2(u_short *pp) { int td, rc = -1, port; @@ -216,24 +216,31 @@ bind_resv_port2(u_short *pp) treq->qlen = 0; treq->addr.len = treq->addr.maxlen; errno = EADDRINUSE; - port = IPPORT_RESERVED; - do { - --port; - sin->sin_port = htons(port); + if (pp && *pp > 0) { + sin->sin_port = htons(*pp); rc = t_bind(td, treq, tret); - if (rc < 0) { - plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]); - } else { - if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0) - break; - else - t_unbind(td); - } - } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2); + } else { + port = IPPORT_RESERVED; + + do { + --port; + sin->sin_port = htons(port); + rc = t_bind(td, treq, tret); + if (rc < 0) { + plog(XLOG_ERROR, "t_bind for port %d: %s", port, t_errlist[t_errno]); + } else { + if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0) + break; + else + t_unbind(td); + } + } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2); + + if (pp && rc == 0) + *pp = port; + } - if (pp && rc == 0) - *pp = port; t_free((char *) tret, T_BIND); t_free((char *) treq, T_BIND); return rc; @@ -436,10 +443,12 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (* *soNFSp = (*nfs_xprtp)->xp_fd; if (*soNFSp < 0 || bindnfs_port(*soNFSp, nfs_portp) < 0) { plog(XLOG_ERROR, "Can't create privileged nfs port (TLI)"); + svc_destroy(*nfs_xprtp); return 1; } if (svc_reg(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, NULL) != 1) { plog(XLOG_ERROR, "could not register amd NFS service"); + svc_destroy(*nfs_xprtp); return 1; } diff --git a/config.guess.long b/config.guess.long index 0327550..1c4614b 100755 --- a/config.guess.long +++ b/config.guess.long @@ -31,8 +31,9 @@ case "${GCONFIG}" in GCONFIG=`echo ${GCONFIG} | sed -e 's/i.86/i386/' -e 's/linux-gnu/linux/'` if test -f /etc/redhat-release ; then long=`getver /etc/redhat-release` - # determine if it's Red Hat or Fedora - if grep -qi fedora /etc/redhat-release ; then + if grep -q 'Red Hat Enterprise Linux' /etc/redhat-release; then + echo ${GCONFIG}-rhel${long} + elif grep -q 'Fedora Core' /etc/redhat-release; then echo ${GCONFIG}-fc${long} else echo ${GCONFIG}-rh${long}