Print this page
6198 Let's EOL cachefs


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.

  25  */
  26 
  27 
  28 /*
  29  * System includes
  30  */
  31 
  32 #include <stdio.h>
  33 #include <limits.h>
  34 #include <errno.h>
  35 #include <stdlib.h>
  36 #include <unistd.h>
  37 #include <libgen.h>
  38 #include <string.h>
  39 #include <wait.h>
  40 #include <signal.h>
  41 #include <malloc.h>
  42 #include <sys/types.h>
  43 #include <sys/mount.h>
  44 #include <sys/stat.h>


  88 
  89 /* returned by already_mounted() */
  90 #define MNT_NOT         0
  91 #define MNT_EXACT       1
  92 #define MNT_AVAIL       2
  93 
  94 /* used with is_remote_src() */
  95 #define NOT_REMOTE      0
  96 #define REAL_REMOTE     1
  97 #define SELF_SERVE      2
  98 
  99 /*
 100  * Due to /etc/mnttab files containing entries for multiple nfs hosts
 101  * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
 102  * man page of 257 needs to be expanded. See bugid 4076513.
 103  * 1024 chars is defined in the mnttab.h header as the max size of an entry.
 104  */
 105 
 106 #define HOST_NM_LN      MNT_LINE_MAX
 107 
 108 /* These cachefs definitions should be in mntent.h. Maybe some day. */
 109 #define MNTTYPE_CFS             "cachefs"
 110 #define MNTOPT_BACKFSTYPE       "backfstype"
 111 #define MNTTYPE_AUTO            "autofs"
 112 
 113 /*
 114  * Utilities for getting filesystem information from the mount table.
 115  *
 116  * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
 117  * popen() on the "/etc/mount" command.  However, we need to get more
 118  * information about mounted filesystems, so we use the C interfaces to
 119  * the mount table, which also happens to be much faster than running
 120  * another process.  Since several of the pkg commands need access to the
 121  * the code has been placed here, to be included in the libinst library.
 122  */
 123 
 124 #define ALLOC_CHUNK     30
 125 
 126 /*
 127  * fs_tab_ent_comp -    compare fstable entries first by length in reverse
 128  *                      order, then alphabetically.
 129  */
 130 static int
 131 fs_tab_ent_comp(const void *e1, const void *e2)
 132 {


 210 
 211         (void) close(fd);
 212         (void) unlink(testfile);
 213 
 214         return (retval);
 215 }
 216 
 217 /* This returns the hostname portion of a remote path. */
 218 char *
 219 get_server_host(uint32_t n)
 220 {
 221         static char hostname[HOST_NM_LN], *host_end;
 222 
 223         if (fs_tab_used == 0) {
 224                 return ("unknown source");
 225         }
 226 
 227         if (n < fs_tab_used) {
 228                 (void) strcpy(hostname, fs_tab[n]->remote_name);
 229                 if ((host_end = strchr(hostname, ':')) == NULL) {
 230                         if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
 231                                 return ("automounter");
 232                         else
 233                                 return (fs_tab[n]->fstype);
 234                 } else {
 235                         *host_end = '\0';
 236                         return (hostname);
 237                 }
 238         }
 239 
 240         return ("unknown source");
 241 }
 242 
 243 /*
 244  * This pulls the path out of a hostpath which may be of the form host:path
 245  * where path is an absolute path. NOTE: If path turns out to be relative,
 246  * this returns NULL.
 247  */
 248 static char *
 249 path_part(char *hostpath)
 250 {


 697  * into fs_tab[].
 698  */
 699 static int
 700 construct_mt(struct mnttab *mt)
 701 {
 702         struct  fstable *nfte;
 703 
 704         /*
 705          * Initialize fstable structure and make the standard entries.
 706          */
 707         if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
 708                 return (1);
 709 
 710         /*
 711          * See if this is served from another host.
 712          * Testing the type is cheap; finding the hostname is not.
 713          * At this point, we're using the REAL mnttab; since we're not
 714          * allowed to mount ourself with "NFS", "NFS" must be remote.
 715          * The automount will translate "nfs:self" to a lofs mount.
 716          */
 717         if (strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0 ||
 718             strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
 719             is_remote_src(mt->mnt_special) == REAL_REMOTE)
 720                 nfte->remote = 1;
 721         else
 722                 nfte->remote = 0;
 723 
 724         /* It's mounted now (by definition), so we don't have to remap it. */
 725         nfte->srvr_map = 0;
 726         nfte->mounted = 1;
 727 
 728         nfte->remote_name = strdup(mt->mnt_special);
 729 
 730         /*
 731          * This checks the mount commands which establish the most
 732          * basic level of access. Later further tests may be
 733          * necessary to fully qualify this. We set this bit
 734          * preliminarily because we have access to the mount data
 735          * now.
 736          */
 737         nfte->writeable = 0; /* Assume read-only. */


 946                                     strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
 947                                     0)
 948                                         continue;       /* not interesting */
 949 
 950                                 /*
 951                                  * Construct client_mountp by prepending the
 952                                  * install_root to the 'mount point' name.
 953                                  */
 954                                 if (strcmp(vfs->vfs_mountp, "/") == 0) {
 955                                         (void) strcpy(client_mountp,
 956                                             install_root);
 957                                 } else {
 958                                         (void) snprintf(client_mountp,
 959                                             sizeof (client_mountp), "%s%s",
 960                                             install_root, vfs->vfs_mountp);
 961                                 }
 962 
 963                                 /*
 964                                  * We also skip the entry if the vfs_special
 965                                  * path and the client_path are the same.
 966                                  * There's no need to mount it, it's just a
 967                                  * cachefs optimization that mounts a
 968                                  * directory over itself from this server.
 969                                  */
 970                                 if ((is_remote == SELF_SERVE) &&
 971                                     strcmp(path_part(vfs->vfs_special),
 972                                     client_mountp) == 0)
 973                                         continue;
 974 
 975                                 /* Determine if this is already mounted. */
 976                                 link_name = strdup(path_part(vfs->vfs_special));
 977                                 mnt_stat = already_mounted(vfs,
 978                                     (is_remote != REAL_REMOTE), client_mountp,
 979                                     link_name);
 980 
 981                                 if (mnt_stat == MNT_EXACT) {
 982                                         mod_existing(vfs, match_mount,
 983                                             is_remote);
 984                                 } else {        /* MNT_NOT */
 985                                         if (construct_vfs(vfs, client_mountp,
 986                                             link_name, is_remote, mnt_stat)) {
 987                                                 return (1);
 988                                         }




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  26  */
  27 
  28 
  29 /*
  30  * System includes
  31  */
  32 
  33 #include <stdio.h>
  34 #include <limits.h>
  35 #include <errno.h>
  36 #include <stdlib.h>
  37 #include <unistd.h>
  38 #include <libgen.h>
  39 #include <string.h>
  40 #include <wait.h>
  41 #include <signal.h>
  42 #include <malloc.h>
  43 #include <sys/types.h>
  44 #include <sys/mount.h>
  45 #include <sys/stat.h>


  89 
  90 /* returned by already_mounted() */
  91 #define MNT_NOT         0
  92 #define MNT_EXACT       1
  93 #define MNT_AVAIL       2
  94 
  95 /* used with is_remote_src() */
  96 #define NOT_REMOTE      0
  97 #define REAL_REMOTE     1
  98 #define SELF_SERVE      2
  99 
 100 /*
 101  * Due to /etc/mnttab files containing entries for multiple nfs hosts
 102  * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
 103  * man page of 257 needs to be expanded. See bugid 4076513.
 104  * 1024 chars is defined in the mnttab.h header as the max size of an entry.
 105  */
 106 
 107 #define HOST_NM_LN      MNT_LINE_MAX
 108 





 109 /*
 110  * Utilities for getting filesystem information from the mount table.
 111  *
 112  * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
 113  * popen() on the "/etc/mount" command.  However, we need to get more
 114  * information about mounted filesystems, so we use the C interfaces to
 115  * the mount table, which also happens to be much faster than running
 116  * another process.  Since several of the pkg commands need access to the
 117  * the code has been placed here, to be included in the libinst library.
 118  */
 119 
 120 #define ALLOC_CHUNK     30
 121 
 122 /*
 123  * fs_tab_ent_comp -    compare fstable entries first by length in reverse
 124  *                      order, then alphabetically.
 125  */
 126 static int
 127 fs_tab_ent_comp(const void *e1, const void *e2)
 128 {


 206 
 207         (void) close(fd);
 208         (void) unlink(testfile);
 209 
 210         return (retval);
 211 }
 212 
 213 /* This returns the hostname portion of a remote path. */
 214 char *
 215 get_server_host(uint32_t n)
 216 {
 217         static char hostname[HOST_NM_LN], *host_end;
 218 
 219         if (fs_tab_used == 0) {
 220                 return ("unknown source");
 221         }
 222 
 223         if (n < fs_tab_used) {
 224                 (void) strcpy(hostname, fs_tab[n]->remote_name);
 225                 if ((host_end = strchr(hostname, ':')) == NULL) {
 226                         if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTOFS)) == NULL)
 227                                 return ("automounter");
 228                         else
 229                                 return (fs_tab[n]->fstype);
 230                 } else {
 231                         *host_end = '\0';
 232                         return (hostname);
 233                 }
 234         }
 235 
 236         return ("unknown source");
 237 }
 238 
 239 /*
 240  * This pulls the path out of a hostpath which may be of the form host:path
 241  * where path is an absolute path. NOTE: If path turns out to be relative,
 242  * this returns NULL.
 243  */
 244 static char *
 245 path_part(char *hostpath)
 246 {


 693  * into fs_tab[].
 694  */
 695 static int
 696 construct_mt(struct mnttab *mt)
 697 {
 698         struct  fstable *nfte;
 699 
 700         /*
 701          * Initialize fstable structure and make the standard entries.
 702          */
 703         if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
 704                 return (1);
 705 
 706         /*
 707          * See if this is served from another host.
 708          * Testing the type is cheap; finding the hostname is not.
 709          * At this point, we're using the REAL mnttab; since we're not
 710          * allowed to mount ourself with "NFS", "NFS" must be remote.
 711          * The automount will translate "nfs:self" to a lofs mount.
 712          */
 713         if (strcmp(mt->mnt_fstype, MNTTYPE_AUTOFS) == 0 ||
 714             strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
 715             is_remote_src(mt->mnt_special) == REAL_REMOTE)
 716                 nfte->remote = 1;
 717         else
 718                 nfte->remote = 0;
 719 
 720         /* It's mounted now (by definition), so we don't have to remap it. */
 721         nfte->srvr_map = 0;
 722         nfte->mounted = 1;
 723 
 724         nfte->remote_name = strdup(mt->mnt_special);
 725 
 726         /*
 727          * This checks the mount commands which establish the most
 728          * basic level of access. Later further tests may be
 729          * necessary to fully qualify this. We set this bit
 730          * preliminarily because we have access to the mount data
 731          * now.
 732          */
 733         nfte->writeable = 0; /* Assume read-only. */


 942                                     strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
 943                                     0)
 944                                         continue;       /* not interesting */
 945 
 946                                 /*
 947                                  * Construct client_mountp by prepending the
 948                                  * install_root to the 'mount point' name.
 949                                  */
 950                                 if (strcmp(vfs->vfs_mountp, "/") == 0) {
 951                                         (void) strcpy(client_mountp,
 952                                             install_root);
 953                                 } else {
 954                                         (void) snprintf(client_mountp,
 955                                             sizeof (client_mountp), "%s%s",
 956                                             install_root, vfs->vfs_mountp);
 957                                 }
 958 
 959                                 /*
 960                                  * We also skip the entry if the vfs_special
 961                                  * path and the client_path are the same.



 962                                  */
 963                                 if ((is_remote == SELF_SERVE) &&
 964                                     strcmp(path_part(vfs->vfs_special),
 965                                     client_mountp) == 0)
 966                                         continue;
 967 
 968                                 /* Determine if this is already mounted. */
 969                                 link_name = strdup(path_part(vfs->vfs_special));
 970                                 mnt_stat = already_mounted(vfs,
 971                                     (is_remote != REAL_REMOTE), client_mountp,
 972                                     link_name);
 973 
 974                                 if (mnt_stat == MNT_EXACT) {
 975                                         mod_existing(vfs, match_mount,
 976                                             is_remote);
 977                                 } else {        /* MNT_NOT */
 978                                         if (construct_vfs(vfs, client_mountp,
 979                                             link_name, is_remote, mnt_stat)) {
 980                                                 return (1);
 981                                         }