138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 Erez Zadok 338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1989 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174294Sobrien * File: am-utils/fsinfo/fsi_analyze.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien/* 4138494Sobrien * Analyze filesystem declarations 4238494Sobrien * 4338494Sobrien * Note: most of this is magic! 4438494Sobrien */ 4538494Sobrien 4638494Sobrien#ifdef HAVE_CONFIG_H 4738494Sobrien# include <config.h> 4838494Sobrien#endif /* HAVE_CONFIG_H */ 4938494Sobrien#include <am_defs.h> 5038494Sobrien#include <fsi_data.h> 5138494Sobrien#include <fsinfo.h> 5238494Sobrien 5338494Sobrienchar *disk_fs_strings[] = 5438494Sobrien{ 55310490Scy "fstype", "opts", "dumpset", "passno", "freq", "mount", "log", NULL, 5638494Sobrien}; 5738494Sobrien 5838494Sobrienchar *mount_strings[] = 5938494Sobrien{ 60310490Scy "volname", "exportfs", NULL, 6138494Sobrien}; 6238494Sobrien 6338494Sobrienchar *fsmount_strings[] = 6438494Sobrien{ 65310490Scy "as", "volname", "fstype", "opts", "from", NULL, 6638494Sobrien}; 6738494Sobrien 6838494Sobrienchar *host_strings[] = 6938494Sobrien{ 70310490Scy "host", "netif", "config", "arch", "cluster", "os", NULL, 7138494Sobrien}; 7238494Sobrien 7338494Sobrienchar *ether_if_strings[] = 7438494Sobrien{ 75310490Scy "inaddr", "netmask", "hwaddr", NULL, 7638494Sobrien}; 7738494Sobrien 7838494Sobrien 7938494Sobrien/* 8038494Sobrien * Strip off the trailing part of a domain 8138494Sobrien * to produce a short-form domain relative 8238494Sobrien * to the local host domain. 8338494Sobrien * Note that this has no effect if the domain 8438494Sobrien * names do not have the same number of 8538494Sobrien * components. If that restriction proves 8638494Sobrien * to be a problem then the loop needs recoding 8738494Sobrien * to skip from right to left and do partial 8838494Sobrien * matches along the way -- ie more expensive. 8938494Sobrien */ 9038494Sobrienvoid 9138494Sobriendomain_strip(char *otherdom, char *localdom) 9238494Sobrien{ 9338494Sobrien char *p1, *p2; 9438494Sobrien 9538494Sobrien if ((p1 = strchr(otherdom, '.')) && 9638494Sobrien (p2 = strchr(localdom, '.')) && 9738494Sobrien STREQ(p1 + 1, p2 + 1)) 9838494Sobrien *p1 = '\0'; 9938494Sobrien} 10038494Sobrien 10138494Sobrien 10238494Sobrien/* 10338494Sobrien * Take a little-endian domain name and 10438494Sobrien * transform into a big-endian Un*x pathname. 10538494Sobrien * For example: kiska.doc.ic -> ic/doc/kiska 10638494Sobrien */ 10738494Sobrienstatic char * 10838494Sobriencompute_hostpath(char *hn) 10938494Sobrien{ 110174294Sobrien char *p = xmalloc(MAXPATHLEN); 11138494Sobrien char *d; 11238494Sobrien char path[MAXPATHLEN]; 11338494Sobrien 114174294Sobrien xstrlcpy(p, hn, MAXPATHLEN); 11538494Sobrien domain_strip(p, hostname); 11638494Sobrien path[0] = '\0'; 11738494Sobrien 11838494Sobrien do { 11938494Sobrien d = strrchr(p, '.'); 12038494Sobrien if (d) { 121310490Scy *d = '\0'; 122174294Sobrien xstrlcat(path, d + 1, sizeof(path)); 123174294Sobrien xstrlcat(path, "/", sizeof(path)); 12438494Sobrien } else { 125174294Sobrien xstrlcat(path, p, sizeof(path)); 12638494Sobrien } 12738494Sobrien } while (d); 12838494Sobrien 129119679Smbr fsi_log("hostpath of '%s' is '%s'", hn, path); 13038494Sobrien 131174294Sobrien xstrlcpy(p, path, MAXPATHLEN); 13238494Sobrien return p; 13338494Sobrien} 13438494Sobrien 13538494Sobrien 13638494Sobrienstatic dict_ent * 13738494Sobrienfind_volname(char *nn) 13838494Sobrien{ 13938494Sobrien dict_ent *de; 140310490Scy char *p = xstrdup(nn); 14138494Sobrien char *q; 14238494Sobrien 14338494Sobrien do { 144119679Smbr fsi_log("Searching for volname %s", p); 14538494Sobrien de = dict_locate(dict_of_volnames, p); 14638494Sobrien q = strrchr(p, '/'); 14738494Sobrien if (q) 14838494Sobrien *q = '\0'; 14938494Sobrien } while (!de && q); 15038494Sobrien 15138494Sobrien XFREE(p); 15238494Sobrien return de; 15338494Sobrien} 15438494Sobrien 15538494Sobrien 15638494Sobrienstatic void 15738494Sobrienshow_required(ioloc *l, int mask, char *info, char *hostname, char *strings[]) 15838494Sobrien{ 15938494Sobrien int i; 160119679Smbr fsi_log("mask left for %s:%s is %#x", hostname, info, mask); 16138494Sobrien 16238494Sobrien for (i = 0; strings[i]; i++) 16338494Sobrien if (ISSET(mask, i)) 16438494Sobrien lerror(l, "%s:%s needs field \"%s\"", hostname, info, strings[i]); 16538494Sobrien} 16638494Sobrien 16738494Sobrien 16838494Sobrien/* 16938494Sobrien * Check and fill in "exportfs" details. 17038494Sobrien * Make sure the m_exported field references 17138494Sobrien * the most local node with an "exportfs" entry. 17238494Sobrien */ 17338494Sobrienstatic int 17438494Sobriencheck_exportfs(qelem *q, fsi_mount *e) 17538494Sobrien{ 17638494Sobrien fsi_mount *mp; 17738494Sobrien int errors = 0; 17838494Sobrien 17938494Sobrien ITER(mp, fsi_mount, q) { 18038494Sobrien if (ISSET(mp->m_mask, DM_EXPORTFS)) { 18138494Sobrien if (e) 18238494Sobrien lwarning(mp->m_ioloc, "%s has duplicate exportfs data", mp->m_name); 18338494Sobrien mp->m_exported = mp; 18438494Sobrien if (!ISSET(mp->m_mask, DM_VOLNAME)) 185310490Scy set_mount(mp, DM_VOLNAME, xstrdup(mp->m_name)); 18638494Sobrien } else { 18738494Sobrien mp->m_exported = e; 18838494Sobrien } 18938494Sobrien 19038494Sobrien /* 19138494Sobrien * Recursively descend the mount tree 19238494Sobrien */ 19338494Sobrien if (mp->m_mount) 19438494Sobrien errors += check_exportfs(mp->m_mount, mp->m_exported); 19538494Sobrien 19638494Sobrien /* 19738494Sobrien * If a volume name has been specified, but this node and none 19838494Sobrien * of its parents has been exported, report an error. 19938494Sobrien */ 20038494Sobrien if (ISSET(mp->m_mask, DM_VOLNAME) && !mp->m_exported) { 20138494Sobrien lerror(mp->m_ioloc, "%s has a volname but no exportfs data", mp->m_name); 20238494Sobrien errors++; 20338494Sobrien } 20438494Sobrien } 20538494Sobrien 20638494Sobrien return errors; 20738494Sobrien} 20838494Sobrien 20938494Sobrien 21038494Sobrienstatic int 21138494Sobrienanalyze_dkmount_tree(qelem *q, fsi_mount *parent, disk_fs *dk) 21238494Sobrien{ 21338494Sobrien fsi_mount *mp; 21438494Sobrien int errors = 0; 21538494Sobrien 21638494Sobrien ITER(mp, fsi_mount, q) { 217119679Smbr fsi_log("Mount %s:", mp->m_name); 21838494Sobrien if (parent) { 21938494Sobrien char n[MAXPATHLEN]; 220174294Sobrien xsnprintf(n, sizeof(n), "%s/%s", parent->m_name, mp->m_name); 22138494Sobrien if (*mp->m_name == '/') 22238494Sobrien lerror(mp->m_ioloc, "sub-directory %s of %s starts with '/'", mp->m_name, parent->m_name); 22338494Sobrien else if (STREQ(mp->m_name, "default")) 22438494Sobrien lwarning(mp->m_ioloc, "sub-directory of %s is named \"default\"", parent->m_name); 225119679Smbr fsi_log("Changing name %s to %s", mp->m_name, n); 22638494Sobrien XFREE(mp->m_name); 227310490Scy mp->m_name = xstrdup(n); 22838494Sobrien } 22938494Sobrien 23038494Sobrien mp->m_name_len = strlen(mp->m_name); 23138494Sobrien mp->m_parent = parent; 23238494Sobrien mp->m_dk = dk; 23338494Sobrien if (mp->m_mount) 23438494Sobrien analyze_dkmount_tree(mp->m_mount, mp, dk); 23538494Sobrien } 23638494Sobrien 23738494Sobrien return errors; 23838494Sobrien} 23938494Sobrien 24038494Sobrien 24138494Sobrien/* 24238494Sobrien * The mount tree is a singleton list 24338494Sobrien * containing the top-level mount 24438494Sobrien * point for a disk. 24538494Sobrien */ 24638494Sobrienstatic int 24738494Sobrienanalyze_dkmounts(disk_fs *dk, qelem *q) 24838494Sobrien{ 24938494Sobrien int errors = 0; 250310490Scy fsi_mount *mp, *mp2 = NULL; 25138494Sobrien int i = 0; 25238494Sobrien 25338494Sobrien /* 25438494Sobrien * First scan the list of subdirs to make 25538494Sobrien * sure there is only one - and remember it 25638494Sobrien */ 25738494Sobrien if (q) { 25838494Sobrien ITER(mp, fsi_mount, q) { 25938494Sobrien mp2 = mp; 26038494Sobrien i++; 26138494Sobrien } 26238494Sobrien } 26338494Sobrien 26438494Sobrien /* 26538494Sobrien * Check... 26638494Sobrien */ 26738494Sobrien if (i < 1) { 26838494Sobrien lerror(dk->d_ioloc, "%s:%s has no mount point", dk->d_host->h_hostname, dk->d_dev); 26938494Sobrien return 1; 27038494Sobrien } 27138494Sobrien 27238494Sobrien if (i > 1) { 27338494Sobrien lerror(dk->d_ioloc, "%s:%s has more than one mount point", dk->d_host->h_hostname, dk->d_dev); 27438494Sobrien errors++; 27538494Sobrien } 27638494Sobrien 27738494Sobrien /* 27838494Sobrien * Now see if a default mount point is required 27938494Sobrien */ 280174294Sobrien if (mp2 && STREQ(mp2->m_name, "default")) { 28138494Sobrien if (ISSET(mp2->m_mask, DM_VOLNAME)) { 28238494Sobrien char nbuf[1024]; 283174294Sobrien compute_automount_point(nbuf, sizeof(nbuf), dk->d_host, mp2->m_volname); 28438494Sobrien XFREE(mp2->m_name); 285310490Scy mp2->m_name = xstrdup(nbuf); 286119679Smbr fsi_log("%s:%s has default mount on %s", dk->d_host->h_hostname, dk->d_dev, mp2->m_name); 28738494Sobrien } else { 28838494Sobrien lerror(dk->d_ioloc, "no volname given for %s:%s", dk->d_host->h_hostname, dk->d_dev); 28938494Sobrien errors++; 29038494Sobrien } 29138494Sobrien } 29238494Sobrien 29338494Sobrien /* 29438494Sobrien * Fill in the disk mount point 29538494Sobrien */ 29638494Sobrien if (!errors && mp2 && mp2->m_name) 297310490Scy dk->d_mountpt = xstrdup(mp2->m_name); 29838494Sobrien else 299310490Scy dk->d_mountpt = xstrdup("error"); 30038494Sobrien 30138494Sobrien /* 30238494Sobrien * Analyze the mount tree 30338494Sobrien */ 304310490Scy errors += analyze_dkmount_tree(q, NULL, dk); 30538494Sobrien 30638494Sobrien /* 30738494Sobrien * Analyze the export tree 30838494Sobrien */ 309310490Scy errors += check_exportfs(q, NULL); 31038494Sobrien 31138494Sobrien return errors; 31238494Sobrien} 31338494Sobrien 31438494Sobrien 31538494Sobrienstatic void 31638494Sobrienfixup_required_disk_info(disk_fs *dp) 31738494Sobrien{ 31838494Sobrien /* 31938494Sobrien * "fstype" 32038494Sobrien */ 32138494Sobrien if (ISSET(dp->d_mask, DF_FSTYPE)) { 32238494Sobrien if (STREQ(dp->d_fstype, "swap")) { 32338494Sobrien 32438494Sobrien /* 32538494Sobrien * Fixup for a swap device 32638494Sobrien */ 32738494Sobrien if (!ISSET(dp->d_mask, DF_PASSNO)) { 32838494Sobrien dp->d_passno = 0; 32938494Sobrien BITSET(dp->d_mask, DF_PASSNO); 33038494Sobrien } else if (dp->d_freq != 0) { 33138494Sobrien lwarning(dp->d_ioloc, 33238494Sobrien "Pass number for %s:%s is non-zero", 33338494Sobrien dp->d_host->h_hostname, dp->d_dev); 33438494Sobrien } 33538494Sobrien 33638494Sobrien /* 33738494Sobrien * "freq" 33838494Sobrien */ 33938494Sobrien if (!ISSET(dp->d_mask, DF_FREQ)) { 34038494Sobrien dp->d_freq = 0; 34138494Sobrien BITSET(dp->d_mask, DF_FREQ); 34238494Sobrien } else if (dp->d_freq != 0) { 34338494Sobrien lwarning(dp->d_ioloc, 34438494Sobrien "dump frequency for %s:%s is non-zero", 34538494Sobrien dp->d_host->h_hostname, dp->d_dev); 34638494Sobrien } 34738494Sobrien 34838494Sobrien /* 34938494Sobrien * "opts" 35038494Sobrien */ 35138494Sobrien if (!ISSET(dp->d_mask, DF_OPTS)) 352310490Scy set_disk_fs(dp, DF_OPTS, xstrdup("swap")); 35338494Sobrien 35438494Sobrien /* 35538494Sobrien * "mount" 35638494Sobrien */ 35738494Sobrien if (!ISSET(dp->d_mask, DF_MOUNT)) { 35838494Sobrien qelem *q = new_que(); 35938494Sobrien fsi_mount *m = new_mount(); 36038494Sobrien 361310490Scy m->m_name = xstrdup("swap"); 36238494Sobrien m->m_mount = new_que(); 36338494Sobrien ins_que(&m->m_q, q->q_back); 36438494Sobrien dp->d_mount = q; 36538494Sobrien BITSET(dp->d_mask, DF_MOUNT); 36638494Sobrien } else { 36738494Sobrien lerror(dp->d_ioloc, "%s: mount field specified for swap partition", dp->d_host->h_hostname); 36838494Sobrien } 36938494Sobrien } else if (STREQ(dp->d_fstype, "export")) { 37038494Sobrien 37138494Sobrien /* 37238494Sobrien * "passno" 37338494Sobrien */ 37438494Sobrien if (!ISSET(dp->d_mask, DF_PASSNO)) { 37538494Sobrien dp->d_passno = 0; 37638494Sobrien BITSET(dp->d_mask, DF_PASSNO); 37738494Sobrien } else if (dp->d_passno != 0) { 37838494Sobrien lwarning(dp->d_ioloc, 37938494Sobrien "pass number for %s:%s is non-zero", 38038494Sobrien dp->d_host->h_hostname, dp->d_dev); 38138494Sobrien } 38238494Sobrien 38338494Sobrien /* 38438494Sobrien * "freq" 38538494Sobrien */ 38638494Sobrien if (!ISSET(dp->d_mask, DF_FREQ)) { 38738494Sobrien dp->d_freq = 0; 38838494Sobrien BITSET(dp->d_mask, DF_FREQ); 38938494Sobrien } else if (dp->d_freq != 0) { 39038494Sobrien lwarning(dp->d_ioloc, 39138494Sobrien "dump frequency for %s:%s is non-zero", 39238494Sobrien dp->d_host->h_hostname, dp->d_dev); 39338494Sobrien } 39438494Sobrien 39538494Sobrien /* 39638494Sobrien * "opts" 39738494Sobrien */ 39838494Sobrien if (!ISSET(dp->d_mask, DF_OPTS)) 399310490Scy set_disk_fs(dp, DF_OPTS, xstrdup("rw,defaults")); 40038494Sobrien 40138494Sobrien } 40238494Sobrien } 40338494Sobrien} 40438494Sobrien 40538494Sobrien 40638494Sobrienstatic void 40738494Sobrienfixup_required_mount_info(fsmount *fp, dict_ent *de) 40838494Sobrien{ 40938494Sobrien if (!ISSET(fp->f_mask, FM_FROM)) { 41038494Sobrien if (de->de_count != 1) { 41138494Sobrien lerror(fp->f_ioloc, "ambiguous mount: %s is a replicated filesystem", fp->f_volname); 41238494Sobrien } else { 41338494Sobrien dict_data *dd; 414310490Scy fsi_mount *mp = NULL; 41538494Sobrien dd = AM_FIRST(dict_data, &de->de_q); 41638494Sobrien mp = (fsi_mount *) dd->dd_data; 41738494Sobrien if (!mp) 41838494Sobrien abort(); 41938494Sobrien fp->f_ref = mp; 42038494Sobrien set_fsmount(fp, FM_FROM, mp->m_dk->d_host->h_hostname); 421119679Smbr fsi_log("set: %s comes from %s", fp->f_volname, fp->f_from); 42238494Sobrien } 42338494Sobrien } 42438494Sobrien 42538494Sobrien if (!ISSET(fp->f_mask, FM_FSTYPE)) { 426310490Scy set_fsmount(fp, FM_FSTYPE, xstrdup("nfs")); 427119679Smbr fsi_log("set: fstype is %s", fp->f_fstype); 42838494Sobrien } 42938494Sobrien 43038494Sobrien if (!ISSET(fp->f_mask, FM_OPTS)) { 431310490Scy set_fsmount(fp, FM_OPTS, xstrdup("rw,nosuid,grpid,defaults")); 432119679Smbr fsi_log("set: opts are %s", fp->f_opts); 43338494Sobrien } 43438494Sobrien 43538494Sobrien if (!ISSET(fp->f_mask, FM_LOCALNAME)) { 43638494Sobrien if (fp->f_ref) { 437310490Scy set_fsmount(fp, FM_LOCALNAME, xstrdup(fp->f_volname)); 438119679Smbr fsi_log("set: localname is %s", fp->f_localname); 43938494Sobrien } else { 44038494Sobrien lerror(fp->f_ioloc, "cannot determine localname since volname %s is not uniquely defined", fp->f_volname); 44138494Sobrien } 44238494Sobrien } 44338494Sobrien} 44438494Sobrien 44538494Sobrien 44638494Sobrien/* 44738494Sobrien * For each disk on a host 44838494Sobrien * analyze the mount information 44938494Sobrien * and fill in any derivable 45038494Sobrien * details. 45138494Sobrien */ 45238494Sobrienstatic void 45338494Sobrienanalyze_drives(host *hp) 45438494Sobrien{ 45538494Sobrien qelem *q = hp->h_disk_fs; 45638494Sobrien disk_fs *dp; 45738494Sobrien 45838494Sobrien ITER(dp, disk_fs, q) { 45938494Sobrien int req; 460119679Smbr fsi_log("Disk %s:", dp->d_dev); 46138494Sobrien dp->d_host = hp; 46238494Sobrien fixup_required_disk_info(dp); 46338494Sobrien req = ~dp->d_mask & DF_REQUIRED; 46438494Sobrien if (req) 46538494Sobrien show_required(dp->d_ioloc, req, dp->d_dev, hp->h_hostname, disk_fs_strings); 46638494Sobrien analyze_dkmounts(dp, dp->d_mount); 46738494Sobrien } 46838494Sobrien} 46938494Sobrien 47038494Sobrien 47138494Sobrien/* 47238494Sobrien * Check that all static mounts make sense and 47338494Sobrien * that the source volumes exist. 47438494Sobrien */ 47538494Sobrienstatic void 47638494Sobrienanalyze_mounts(host *hp) 47738494Sobrien{ 47838494Sobrien qelem *q = hp->h_mount; 47938494Sobrien fsmount *fp; 48038494Sobrien int netbootp = 0; 48138494Sobrien 48238494Sobrien ITER(fp, fsmount, q) { 48338494Sobrien char *p; 484310490Scy char *nn = xstrdup(fp->f_volname); 48538494Sobrien int req; 48638494Sobrien dict_ent *de = (dict_ent *) NULL; 48738494Sobrien int found = 0; 48838494Sobrien int matched = 0; 48938494Sobrien 49038494Sobrien if (ISSET(fp->f_mask, FM_DIRECT)) { 49138494Sobrien found = 1; 49238494Sobrien matched = 1; 49338494Sobrien } else 49438494Sobrien do { 495310490Scy p = NULL; 49638494Sobrien de = find_volname(nn); 497119679Smbr fsi_log("Mount: %s (trying %s)", fp->f_volname, nn); 49838494Sobrien 49938494Sobrien if (de) { 50038494Sobrien found = 1; 50138494Sobrien 50238494Sobrien /* 50338494Sobrien * Check that the from field is really exporting 50438494Sobrien * the filesystem requested. 50538494Sobrien * LBL: If fake mount, then don't care about 50638494Sobrien * consistency check. 50738494Sobrien */ 50838494Sobrien if (ISSET(fp->f_mask, FM_FROM) && !ISSET(fp->f_mask, FM_DIRECT)) { 50938494Sobrien dict_data *dd; 510310490Scy fsi_mount *mp2 = NULL; 51138494Sobrien 51238494Sobrien ITER(dd, dict_data, &de->de_q) { 51338494Sobrien fsi_mount *mp = (fsi_mount *) dd->dd_data; 51438494Sobrien 515174294Sobrien if (fp->f_from && 516174294Sobrien STREQ(mp->m_dk->d_host->h_hostname, fp->f_from)) { 51738494Sobrien mp2 = mp; 51838494Sobrien break; 51938494Sobrien } 52038494Sobrien } 52138494Sobrien 52238494Sobrien if (mp2) { 52338494Sobrien fp->f_ref = mp2; 52438494Sobrien matched = 1; 52538494Sobrien break; 52638494Sobrien } 52738494Sobrien } else { 52838494Sobrien matched = 1; 52938494Sobrien break; 53038494Sobrien } 53138494Sobrien } 53238494Sobrien p = strrchr(nn, '/'); 53338494Sobrien if (p) 534310490Scy *p = '\0'; 53538494Sobrien } while (de && p); 53638494Sobrien XFREE(nn); 53738494Sobrien 53838494Sobrien if (!found) { 53938494Sobrien lerror(fp->f_ioloc, "volname %s unknown", fp->f_volname); 54038494Sobrien } else if (matched) { 54138494Sobrien 542174294Sobrien if (de) 543174294Sobrien fixup_required_mount_info(fp, de); 54438494Sobrien req = ~fp->f_mask & FM_REQUIRED; 54538494Sobrien if (req) { 54638494Sobrien show_required(fp->f_ioloc, req, fp->f_volname, hp->h_hostname, 54738494Sobrien fsmount_strings); 54838494Sobrien } else if (STREQ(fp->f_localname, "/")) { 54938494Sobrien hp->h_netroot = fp; 55038494Sobrien netbootp |= FM_NETROOT; 55138494Sobrien } else if (STREQ(fp->f_localname, "swap")) { 55238494Sobrien hp->h_netswap = fp; 55338494Sobrien netbootp |= FM_NETSWAP; 55438494Sobrien } 55538494Sobrien 55638494Sobrien } else { 55738494Sobrien lerror(fp->f_ioloc, "volname %s not exported from %s", fp->f_volname, 55838494Sobrien fp->f_from ? fp->f_from : "anywhere"); 55938494Sobrien } 56038494Sobrien } 56138494Sobrien 56238494Sobrien if (netbootp && (netbootp != FM_NETBOOT)) 56338494Sobrien lerror(hp->h_ioloc, "network booting requires both root and swap areas"); 56438494Sobrien} 56538494Sobrien 56638494Sobrien 56738494Sobrienvoid 56838494Sobrienanalyze_hosts(qelem *q) 56938494Sobrien{ 57038494Sobrien host *hp; 57138494Sobrien 57238494Sobrien show_area_being_processed("analyze hosts", 5); 57338494Sobrien 57438494Sobrien /* 57538494Sobrien * Check all drives 57638494Sobrien */ 57738494Sobrien ITER(hp, host, q) { 578119679Smbr fsi_log("disks on host %s", hp->h_hostname); 57938494Sobrien show_new("ana-host"); 58038494Sobrien hp->h_hostpath = compute_hostpath(hp->h_hostname); 58138494Sobrien 58238494Sobrien if (hp->h_disk_fs) 58338494Sobrien analyze_drives(hp); 58438494Sobrien 58538494Sobrien } 58638494Sobrien 58738494Sobrien show_area_being_processed("analyze mounts", 5); 58838494Sobrien 58938494Sobrien /* 59038494Sobrien * Check static mounts 59138494Sobrien */ 59238494Sobrien ITER(hp, host, q) { 593119679Smbr fsi_log("mounts on host %s", hp->h_hostname); 59438494Sobrien show_new("ana-mount"); 59538494Sobrien if (hp->h_mount) 59638494Sobrien analyze_mounts(hp); 59738494Sobrien 59838494Sobrien } 59938494Sobrien} 60038494Sobrien 60138494Sobrien 60238494Sobrien/* 60338494Sobrien * Check an automount request 60438494Sobrien */ 60538494Sobrienstatic void 60638494Sobrienanalyze_automount(automount *ap) 60738494Sobrien{ 60838494Sobrien dict_ent *de = find_volname(ap->a_volname); 60938494Sobrien 61038494Sobrien if (de) { 61138494Sobrien ap->a_mounted = de; 61238494Sobrien } else { 61338494Sobrien if (STREQ(ap->a_volname, ap->a_name)) 61438494Sobrien lerror(ap->a_ioloc, "unknown volname %s automounted", ap->a_volname); 61538494Sobrien else 61638494Sobrien lerror(ap->a_ioloc, "unknown volname %s automounted on %s", ap->a_volname, ap->a_name); 61738494Sobrien } 61838494Sobrien} 61938494Sobrien 62038494Sobrien 62138494Sobrienstatic void 62238494Sobrienanalyze_automount_tree(qelem *q, char *pref, int lvl) 62338494Sobrien{ 62438494Sobrien automount *ap; 62538494Sobrien 62638494Sobrien ITER(ap, automount, q) { 62738494Sobrien char nname[1024]; 62838494Sobrien 62938494Sobrien if (lvl > 0 || ap->a_mount) 63038494Sobrien if (ap->a_name[1] && strchr(ap->a_name + 1, '/')) 63138494Sobrien lerror(ap->a_ioloc, "not allowed '/' in a directory name"); 632174294Sobrien xsnprintf(nname, sizeof(nname), "%s/%s", pref, ap->a_name); 63338494Sobrien XFREE(ap->a_name); 634310490Scy ap->a_name = xstrdup(nname[1] == '/' ? nname + 1 : nname); 635119679Smbr fsi_log("automount point %s:", ap->a_name); 63638494Sobrien show_new("ana-automount"); 63738494Sobrien 63838494Sobrien if (ap->a_mount) { 63938494Sobrien analyze_automount_tree(ap->a_mount, ap->a_name, lvl + 1); 64038494Sobrien } else if (ap->a_hardwiredfs) { 641119679Smbr fsi_log("\thardwired from %s to %s", ap->a_volname, ap->a_hardwiredfs); 64238494Sobrien } else if (ap->a_volname) { 643119679Smbr fsi_log("\tautomount from %s", ap->a_volname); 64438494Sobrien analyze_automount(ap); 64538494Sobrien } else if (ap->a_symlink) { 646119679Smbr fsi_log("\tsymlink to %s", ap->a_symlink); 64738494Sobrien } else { 648310490Scy ap->a_volname = xstrdup(ap->a_name); 649119679Smbr fsi_log("\timplicit automount from %s", ap->a_volname); 65038494Sobrien analyze_automount(ap); 65138494Sobrien } 65238494Sobrien } 65338494Sobrien} 65438494Sobrien 65538494Sobrien 65638494Sobrienvoid 65738494Sobrienanalyze_automounts(qelem *q) 65838494Sobrien{ 65938494Sobrien auto_tree *tp; 66038494Sobrien 66138494Sobrien show_area_being_processed("analyze automount", 5); 66238494Sobrien 66338494Sobrien /* 66438494Sobrien * q is a list of automounts 66538494Sobrien */ 66638494Sobrien ITER(tp, auto_tree, q) 66738494Sobrien analyze_automount_tree(tp->t_mount, "", 0); 66838494Sobrien} 669