1*b4cb3fe0SToomas Soome /*- 2*b4cb3fe0SToomas Soome * Copyright 2021 Toomas Soome <tsoome@me.com> 3*b4cb3fe0SToomas Soome * 4*b4cb3fe0SToomas Soome * Redistribution and use in source and binary forms, with or without 5*b4cb3fe0SToomas Soome * modification, are permitted provided that the following conditions 6*b4cb3fe0SToomas Soome * are met: 7*b4cb3fe0SToomas Soome * 1. Redistributions of source code must retain the above copyright 8*b4cb3fe0SToomas Soome * notice, this list of conditions and the following disclaimer. 9*b4cb3fe0SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 10*b4cb3fe0SToomas Soome * notice, this list of conditions and the following disclaimer in the 11*b4cb3fe0SToomas Soome * documentation and/or other materials provided with the distribution. 12*b4cb3fe0SToomas Soome * 13*b4cb3fe0SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14*b4cb3fe0SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15*b4cb3fe0SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16*b4cb3fe0SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17*b4cb3fe0SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18*b4cb3fe0SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19*b4cb3fe0SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20*b4cb3fe0SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21*b4cb3fe0SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22*b4cb3fe0SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23*b4cb3fe0SToomas Soome * SUCH DAMAGE. 24*b4cb3fe0SToomas Soome */ 25*b4cb3fe0SToomas Soome 26*b4cb3fe0SToomas Soome #include <sys/cdefs.h> 27*b4cb3fe0SToomas Soome __FBSDID("$FreeBSD$"); 28*b4cb3fe0SToomas Soome 29*b4cb3fe0SToomas Soome #include <stand.h> 30*b4cb3fe0SToomas Soome #include <sys/queue.h> 31*b4cb3fe0SToomas Soome 32*b4cb3fe0SToomas Soome /* 33*b4cb3fe0SToomas Soome * While setting "currdev" environment variable, alse "mount" the 34*b4cb3fe0SToomas Soome * new root file system. This is done to hold disk device open 35*b4cb3fe0SToomas Soome * in between file accesses, and thus preserve block cache for 36*b4cb3fe0SToomas Soome * this device. Additionally, this allows us to optimize filesystem 37*b4cb3fe0SToomas Soome * access by sharing filesystem metadata (like superblock). 38*b4cb3fe0SToomas Soome */ 39*b4cb3fe0SToomas Soome 40*b4cb3fe0SToomas Soome typedef STAILQ_HEAD(mnt_info_list, mnt_info) mnt_info_list_t; 41*b4cb3fe0SToomas Soome 42*b4cb3fe0SToomas Soome typedef struct mnt_info { 43*b4cb3fe0SToomas Soome STAILQ_ENTRY(mnt_info) mnt_link; /* link in mount list */ 44*b4cb3fe0SToomas Soome const struct fs_ops *mnt_fs; 45*b4cb3fe0SToomas Soome char *mnt_dev; 46*b4cb3fe0SToomas Soome char *mnt_path; 47*b4cb3fe0SToomas Soome unsigned mnt_refcount; 48*b4cb3fe0SToomas Soome void *mnt_data; /* Private state */ 49*b4cb3fe0SToomas Soome } mnt_info_t; 50*b4cb3fe0SToomas Soome 51*b4cb3fe0SToomas Soome /* list of mounted filesystems. */ 52*b4cb3fe0SToomas Soome static mnt_info_list_t mnt_list = STAILQ_HEAD_INITIALIZER(mnt_list); 53*b4cb3fe0SToomas Soome 54*b4cb3fe0SToomas Soome static void 55*b4cb3fe0SToomas Soome free_mnt(mnt_info_t *mnt) 56*b4cb3fe0SToomas Soome { 57*b4cb3fe0SToomas Soome free(mnt->mnt_dev); 58*b4cb3fe0SToomas Soome free(mnt->mnt_path); 59*b4cb3fe0SToomas Soome free(mnt); 60*b4cb3fe0SToomas Soome } 61*b4cb3fe0SToomas Soome 62*b4cb3fe0SToomas Soome static int 63*b4cb3fe0SToomas Soome add_mnt_info(struct fs_ops *fs, const char *dev, const char *path, void *data) 64*b4cb3fe0SToomas Soome { 65*b4cb3fe0SToomas Soome mnt_info_t *mnt; 66*b4cb3fe0SToomas Soome 67*b4cb3fe0SToomas Soome mnt = malloc(sizeof(*mnt)); 68*b4cb3fe0SToomas Soome if (mnt == NULL) 69*b4cb3fe0SToomas Soome return (ENOMEM); 70*b4cb3fe0SToomas Soome 71*b4cb3fe0SToomas Soome mnt->mnt_fs = fs; 72*b4cb3fe0SToomas Soome mnt->mnt_dev = strdup(dev); 73*b4cb3fe0SToomas Soome mnt->mnt_path = strdup(path); 74*b4cb3fe0SToomas Soome mnt->mnt_data = data; 75*b4cb3fe0SToomas Soome mnt->mnt_refcount = 1; 76*b4cb3fe0SToomas Soome 77*b4cb3fe0SToomas Soome if (mnt->mnt_dev == NULL || mnt->mnt_path == NULL) { 78*b4cb3fe0SToomas Soome free_mnt(mnt); 79*b4cb3fe0SToomas Soome return (ENOMEM); 80*b4cb3fe0SToomas Soome } 81*b4cb3fe0SToomas Soome STAILQ_INSERT_TAIL(&mnt_list, mnt, mnt_link); 82*b4cb3fe0SToomas Soome return (0); 83*b4cb3fe0SToomas Soome } 84*b4cb3fe0SToomas Soome 85*b4cb3fe0SToomas Soome static void 86*b4cb3fe0SToomas Soome delete_mnt_info(mnt_info_t *mnt) 87*b4cb3fe0SToomas Soome { 88*b4cb3fe0SToomas Soome STAILQ_REMOVE(&mnt_list, mnt, mnt_info, mnt_link); 89*b4cb3fe0SToomas Soome free_mnt(mnt); 90*b4cb3fe0SToomas Soome } 91*b4cb3fe0SToomas Soome 92*b4cb3fe0SToomas Soome int 93*b4cb3fe0SToomas Soome mount(const char *dev, const char *path, int flags __unused, void *data) 94*b4cb3fe0SToomas Soome { 95*b4cb3fe0SToomas Soome mnt_info_t *mnt; 96*b4cb3fe0SToomas Soome int rc = -1; 97*b4cb3fe0SToomas Soome 98*b4cb3fe0SToomas Soome /* Is it already mounted? */ 99*b4cb3fe0SToomas Soome STAILQ_FOREACH(mnt, &mnt_list, mnt_link) { 100*b4cb3fe0SToomas Soome if (strcmp(dev, mnt->mnt_dev) == 0 && 101*b4cb3fe0SToomas Soome strcmp(path, mnt->mnt_path) == 0) { 102*b4cb3fe0SToomas Soome mnt->mnt_refcount++; 103*b4cb3fe0SToomas Soome return (0); 104*b4cb3fe0SToomas Soome } 105*b4cb3fe0SToomas Soome } 106*b4cb3fe0SToomas Soome 107*b4cb3fe0SToomas Soome for (int i = 0; file_system[i] != NULL; i++) { 108*b4cb3fe0SToomas Soome struct fs_ops *fs; 109*b4cb3fe0SToomas Soome 110*b4cb3fe0SToomas Soome fs = file_system[i]; 111*b4cb3fe0SToomas Soome if (fs->fo_mount == NULL) 112*b4cb3fe0SToomas Soome continue; 113*b4cb3fe0SToomas Soome 114*b4cb3fe0SToomas Soome if (fs->fo_mount(dev, path, &data) != 0) 115*b4cb3fe0SToomas Soome continue; 116*b4cb3fe0SToomas Soome 117*b4cb3fe0SToomas Soome rc = add_mnt_info(fs, dev, path, data); 118*b4cb3fe0SToomas Soome if (rc != 0 && mnt->mnt_fs->fo_unmount != NULL) { 119*b4cb3fe0SToomas Soome printf("failed to mount %s: %s\n", dev, 120*b4cb3fe0SToomas Soome strerror(rc)); 121*b4cb3fe0SToomas Soome (void)mnt->mnt_fs->fo_unmount(dev, data); 122*b4cb3fe0SToomas Soome } 123*b4cb3fe0SToomas Soome break; 124*b4cb3fe0SToomas Soome } 125*b4cb3fe0SToomas Soome 126*b4cb3fe0SToomas Soome 127*b4cb3fe0SToomas Soome /* 128*b4cb3fe0SToomas Soome * if rc is -1, it means we have no file system with fo_mount() 129*b4cb3fe0SToomas Soome * callback, or all fo_mount() calls failed. As long as we 130*b4cb3fe0SToomas Soome * have missing fo_mount() callbacks, we allow mount() to return 0. 131*b4cb3fe0SToomas Soome */ 132*b4cb3fe0SToomas Soome if (rc == -1) 133*b4cb3fe0SToomas Soome rc = 0; 134*b4cb3fe0SToomas Soome 135*b4cb3fe0SToomas Soome return (rc); 136*b4cb3fe0SToomas Soome } 137*b4cb3fe0SToomas Soome 138*b4cb3fe0SToomas Soome int 139*b4cb3fe0SToomas Soome unmount(const char *dev, int flags __unused) 140*b4cb3fe0SToomas Soome { 141*b4cb3fe0SToomas Soome mnt_info_t *mnt; 142*b4cb3fe0SToomas Soome int rv; 143*b4cb3fe0SToomas Soome 144*b4cb3fe0SToomas Soome rv = 0; 145*b4cb3fe0SToomas Soome STAILQ_FOREACH(mnt, &mnt_list, mnt_link) { 146*b4cb3fe0SToomas Soome if (strcmp(dev, mnt->mnt_dev) == 0) { 147*b4cb3fe0SToomas Soome if (mnt->mnt_refcount > 1) { 148*b4cb3fe0SToomas Soome mnt->mnt_refcount--; 149*b4cb3fe0SToomas Soome break; 150*b4cb3fe0SToomas Soome } 151*b4cb3fe0SToomas Soome 152*b4cb3fe0SToomas Soome if (mnt->mnt_fs->fo_unmount != NULL) 153*b4cb3fe0SToomas Soome rv = mnt->mnt_fs->fo_unmount(dev, 154*b4cb3fe0SToomas Soome mnt->mnt_data); 155*b4cb3fe0SToomas Soome delete_mnt_info(mnt); 156*b4cb3fe0SToomas Soome break; 157*b4cb3fe0SToomas Soome } 158*b4cb3fe0SToomas Soome } 159*b4cb3fe0SToomas Soome 160*b4cb3fe0SToomas Soome if (rv != 0) 161*b4cb3fe0SToomas Soome printf("failed to unmount %s: %d\n", dev, rv); 162*b4cb3fe0SToomas Soome return (0); 163*b4cb3fe0SToomas Soome } 164