1 1.83 pgoyette /* $NetBSD: filecore_vfsops.c,v 1.83 2020/03/16 21:20:10 pgoyette Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 1994 The Regents of the University of California. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 8 1.1 jdolecek * modification, are permitted provided that the following conditions 9 1.1 jdolecek * are met: 10 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 11 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 12 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 14 1.1 jdolecek * documentation and/or other materials provided with the distribution. 15 1.6 agc * 3. Neither the name of the University nor the names of its contributors 16 1.6 agc * may be used to endorse or promote products derived from this software 17 1.6 agc * without specific prior written permission. 18 1.6 agc * 19 1.6 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.6 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.6 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.6 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.6 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.6 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.6 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.6 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.6 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.6 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.6 agc * SUCH DAMAGE. 30 1.6 agc * 31 1.6 agc * filecore_vfsops.c 1.1 1998/6/26 32 1.6 agc */ 33 1.6 agc 34 1.6 agc /*- 35 1.6 agc * Copyright (c) 1998 Andrew McMurry 36 1.6 agc * 37 1.6 agc * Redistribution and use in source and binary forms, with or without 38 1.6 agc * modification, are permitted provided that the following conditions 39 1.6 agc * are met: 40 1.6 agc * 1. Redistributions of source code must retain the above copyright 41 1.6 agc * notice, this list of conditions and the following disclaimer. 42 1.6 agc * 2. Redistributions in binary form must reproduce the above copyright 43 1.6 agc * notice, this list of conditions and the following disclaimer in the 44 1.6 agc * documentation and/or other materials provided with the distribution. 45 1.1 jdolecek * 3. All advertising materials mentioning features or use of this software 46 1.1 jdolecek * must display the following acknowledgement: 47 1.1 jdolecek * This product includes software developed by the University of 48 1.1 jdolecek * California, Berkeley and its contributors. 49 1.1 jdolecek * 4. Neither the name of the University nor the names of its contributors 50 1.1 jdolecek * may be used to endorse or promote products derived from this software 51 1.1 jdolecek * without specific prior written permission. 52 1.1 jdolecek * 53 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.1 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.1 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.1 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.1 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.1 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.1 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.1 jdolecek * SUCH DAMAGE. 64 1.1 jdolecek * 65 1.1 jdolecek * filecore_vfsops.c 1.1 1998/6/26 66 1.1 jdolecek */ 67 1.1 jdolecek 68 1.1 jdolecek #include <sys/cdefs.h> 69 1.83 pgoyette __KERNEL_RCSID(0, "$NetBSD: filecore_vfsops.c,v 1.83 2020/03/16 21:20:10 pgoyette Exp $"); 70 1.1 jdolecek 71 1.1 jdolecek #if defined(_KERNEL_OPT) 72 1.1 jdolecek #include "opt_compat_netbsd.h" 73 1.1 jdolecek #endif 74 1.1 jdolecek 75 1.1 jdolecek #include <sys/param.h> 76 1.1 jdolecek #include <sys/systm.h> 77 1.1 jdolecek #include <sys/namei.h> 78 1.1 jdolecek #include <sys/proc.h> 79 1.1 jdolecek #include <sys/vnode.h> 80 1.47 dholland #include <miscfs/genfs/genfs.h> 81 1.1 jdolecek #include <miscfs/specfs/specdev.h> 82 1.1 jdolecek #include <sys/mount.h> 83 1.1 jdolecek #include <sys/buf.h> 84 1.1 jdolecek #include <sys/file.h> 85 1.1 jdolecek #include <sys/device.h> 86 1.1 jdolecek #include <sys/errno.h> 87 1.1 jdolecek #include <sys/pool.h> 88 1.1 jdolecek #include <sys/conf.h> 89 1.8 bjh21 #include <sys/sysctl.h> 90 1.25 christos #include <sys/kauth.h> 91 1.53 rumble #include <sys/module.h> 92 1.1 jdolecek 93 1.1 jdolecek #include <fs/filecorefs/filecore.h> 94 1.1 jdolecek #include <fs/filecorefs/filecore_extern.h> 95 1.1 jdolecek #include <fs/filecorefs/filecore_node.h> 96 1.1 jdolecek #include <fs/filecorefs/filecore_mount.h> 97 1.2 thorpej 98 1.62 pooka MODULE(MODULE_CLASS_VFS, filecore, NULL); 99 1.53 rumble 100 1.1 jdolecek extern const struct vnodeopv_desc filecore_vnodeop_opv_desc; 101 1.1 jdolecek 102 1.1 jdolecek const struct vnodeopv_desc * const filecore_vnodeopv_descs[] = { 103 1.1 jdolecek &filecore_vnodeop_opv_desc, 104 1.1 jdolecek NULL, 105 1.1 jdolecek }; 106 1.1 jdolecek 107 1.1 jdolecek struct vfsops filecore_vfsops = { 108 1.75 hannken .vfs_name = MOUNT_FILECORE, 109 1.75 hannken .vfs_min_mount_data = sizeof (struct filecore_args), 110 1.75 hannken .vfs_mount = filecore_mount, 111 1.75 hannken .vfs_start = filecore_start, 112 1.75 hannken .vfs_unmount = filecore_unmount, 113 1.75 hannken .vfs_root = filecore_root, 114 1.75 hannken .vfs_quotactl = (void *)eopnotsupp, 115 1.75 hannken .vfs_statvfs = filecore_statvfs, 116 1.75 hannken .vfs_sync = filecore_sync, 117 1.75 hannken .vfs_vget = filecore_vget, 118 1.77 hannken .vfs_loadvnode = filecore_loadvnode, 119 1.75 hannken .vfs_fhtovp = filecore_fhtovp, 120 1.75 hannken .vfs_vptofh = filecore_vptofh, 121 1.75 hannken .vfs_init = filecore_init, 122 1.75 hannken .vfs_reinit = filecore_reinit, 123 1.75 hannken .vfs_done = filecore_done, 124 1.75 hannken .vfs_snapshot = (void *)eopnotsupp, 125 1.75 hannken .vfs_extattrctl = vfs_stdextattrctl, 126 1.79 hannken .vfs_suspendctl = genfs_suspendctl, 127 1.75 hannken .vfs_renamelock_enter = genfs_renamelock_enter, 128 1.75 hannken .vfs_renamelock_exit = genfs_renamelock_exit, 129 1.75 hannken .vfs_fsync = (void *)eopnotsupp, 130 1.75 hannken .vfs_opv_descs = filecore_vnodeopv_descs 131 1.1 jdolecek }; 132 1.1 jdolecek 133 1.83 pgoyette SYSCTL_SETUP(filecore_sysctl_setup, "filecore fs sysctl") 134 1.83 pgoyette { 135 1.83 pgoyette 136 1.83 pgoyette sysctl_createv(clog, 0, NULL, NULL, 137 1.83 pgoyette CTLFLAG_PERMANENT, 138 1.83 pgoyette CTLTYPE_NODE, "filecore", 139 1.83 pgoyette SYSCTL_DESCR("Acorn FILECORE file system"), 140 1.83 pgoyette NULL, 0, NULL, 0, 141 1.83 pgoyette CTL_VFS, 19, CTL_EOL); 142 1.83 pgoyette /* 143 1.83 pgoyette * XXX the "19" above could be dynamic, thereby eliminating 144 1.83 pgoyette * one more instance of the "number to vfs" mapping problem, 145 1.83 pgoyette * but "19" is the order as taken from sys/mount.h 146 1.83 pgoyette */ 147 1.83 pgoyette } 148 1.83 pgoyette 149 1.53 rumble static int 150 1.63 mlelstv filecore_modcmd(modcmd_t cmd, void *arg) 151 1.53 rumble { 152 1.55 rumble int error; 153 1.53 rumble 154 1.53 rumble switch (cmd) { 155 1.53 rumble case MODULE_CMD_INIT: 156 1.55 rumble error = vfs_attach(&filecore_vfsops); 157 1.55 rumble if (error != 0) 158 1.55 rumble break; 159 1.55 rumble break; 160 1.53 rumble case MODULE_CMD_FINI: 161 1.55 rumble error = vfs_detach(&filecore_vfsops); 162 1.55 rumble if (error != 0) 163 1.55 rumble break; 164 1.55 rumble break; 165 1.53 rumble default: 166 1.55 rumble error = ENOTTY; 167 1.55 rumble break; 168 1.53 rumble } 169 1.55 rumble 170 1.55 rumble return (error); 171 1.53 rumble } 172 1.53 rumble 173 1.1 jdolecek /* 174 1.1 jdolecek * Called by vfs_mountroot when iso is going to be mounted as root. 175 1.1 jdolecek * 176 1.1 jdolecek * Name is updated by mount(8) after booting. 177 1.1 jdolecek */ 178 1.1 jdolecek 179 1.56 dsl static int filecore_mountfs(struct vnode *devvp, struct mount *mp, 180 1.56 dsl struct lwp *l, struct filecore_args *argp); 181 1.1 jdolecek 182 1.1 jdolecek #if 0 183 1.1 jdolecek int 184 1.58 cegger filecore_mountroot(void) 185 1.1 jdolecek { 186 1.1 jdolecek struct mount *mp; 187 1.1 jdolecek extern struct vnode *rootvp; 188 1.1 jdolecek struct proc *p = curproc; /* XXX */ 189 1.1 jdolecek int error; 190 1.1 jdolecek struct filecore_args args; 191 1.1 jdolecek 192 1.23 thorpej if (device_class(root_device) != DV_DISK) 193 1.1 jdolecek return (ENODEV); 194 1.18 perry 195 1.1 jdolecek /* 196 1.1 jdolecek * Get vnodes for swapdev and rootdev. 197 1.1 jdolecek */ 198 1.1 jdolecek if (bdevvp(rootdev, &rootvp)) 199 1.1 jdolecek panic("filecore_mountroot: can't setup rootvp"); 200 1.1 jdolecek 201 1.1 jdolecek if ((error = vfs_rootmountalloc(MOUNT_FILECORE, "root_device", &mp)) != 0) 202 1.1 jdolecek return (error); 203 1.1 jdolecek 204 1.1 jdolecek args.flags = FILECOREMNT_ROOT; 205 1.1 jdolecek if ((error = filecore_mountfs(rootvp, mp, p, &args)) != 0) { 206 1.81 hannken vfs_unbusy(mp); 207 1.80 hannken vfs_rele(mp); 208 1.1 jdolecek return (error); 209 1.1 jdolecek } 210 1.72 christos mountlist_append(mp); 211 1.10 christos (void)filecore_statvfs(mp, &mp->mnt_stat, p); 212 1.81 hannken vfs_unbusy(mp); 213 1.1 jdolecek return (0); 214 1.1 jdolecek } 215 1.1 jdolecek #endif 216 1.1 jdolecek 217 1.1 jdolecek /* 218 1.1 jdolecek * VFS Operations. 219 1.1 jdolecek * 220 1.1 jdolecek * mount system call 221 1.1 jdolecek */ 222 1.1 jdolecek int 223 1.57 dsl filecore_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 224 1.1 jdolecek { 225 1.44 pooka struct lwp *l = curlwp; 226 1.1 jdolecek struct vnode *devvp; 227 1.36 dsl struct filecore_args *args = data; 228 1.1 jdolecek int error; 229 1.1 jdolecek struct filecore_mnt *fcmp = NULL; 230 1.18 perry 231 1.76 maxv if (args == NULL) 232 1.76 maxv return EINVAL; 233 1.36 dsl if (*data_len < sizeof *args) 234 1.36 dsl return EINVAL; 235 1.36 dsl 236 1.1 jdolecek if (mp->mnt_flag & MNT_GETARGS) { 237 1.1 jdolecek fcmp = VFSTOFILECORE(mp); 238 1.1 jdolecek if (fcmp == NULL) 239 1.1 jdolecek return EIO; 240 1.36 dsl args->flags = fcmp->fc_mntflags; 241 1.36 dsl args->uid = fcmp->fc_uid; 242 1.36 dsl args->gid = fcmp->fc_gid; 243 1.36 dsl args->fspec = NULL; 244 1.36 dsl *data_len = sizeof *args; 245 1.36 dsl return 0; 246 1.1 jdolecek } 247 1.18 perry 248 1.1 jdolecek if ((mp->mnt_flag & MNT_RDONLY) == 0) 249 1.1 jdolecek return (EROFS); 250 1.18 perry 251 1.36 dsl if ((mp->mnt_flag & MNT_UPDATE) && args->fspec == NULL) 252 1.21 jmmv return EINVAL; 253 1.21 jmmv 254 1.1 jdolecek /* 255 1.1 jdolecek * Not an update, or updating the name: look up the name 256 1.1 jdolecek * and verify that it refers to a sensible block device. 257 1.1 jdolecek */ 258 1.60 dholland error = namei_simple_user(args->fspec, 259 1.60 dholland NSM_FOLLOW_NOEMULROOT, &devvp); 260 1.60 dholland if (error != 0) 261 1.1 jdolecek return (error); 262 1.1 jdolecek 263 1.1 jdolecek if (devvp->v_type != VBLK) { 264 1.1 jdolecek vrele(devvp); 265 1.1 jdolecek return ENOTBLK; 266 1.1 jdolecek } 267 1.1 jdolecek if (bdevsw_lookup(devvp->v_rdev) == NULL) { 268 1.1 jdolecek vrele(devvp); 269 1.1 jdolecek return ENXIO; 270 1.1 jdolecek } 271 1.1 jdolecek /* 272 1.1 jdolecek * If mount by non-root, then verify that user has necessary 273 1.1 jdolecek * permissions on the device. 274 1.1 jdolecek */ 275 1.59 elad vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 276 1.69 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 277 1.69 elad KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(VREAD)); 278 1.64 hannken VOP_UNLOCK(devvp); 279 1.59 elad if (error) { 280 1.59 elad vrele(devvp); 281 1.59 elad return (error); 282 1.1 jdolecek } 283 1.1 jdolecek if ((mp->mnt_flag & MNT_UPDATE) == 0) 284 1.36 dsl error = filecore_mountfs(devvp, mp, l, args); 285 1.1 jdolecek else { 286 1.73 mlelstv fcmp = VFSTOFILECORE(mp); 287 1.1 jdolecek if (devvp != fcmp->fc_devvp) 288 1.1 jdolecek error = EINVAL; /* needs translation */ 289 1.1 jdolecek else 290 1.1 jdolecek vrele(devvp); 291 1.1 jdolecek } 292 1.1 jdolecek if (error) { 293 1.1 jdolecek vrele(devvp); 294 1.1 jdolecek return error; 295 1.1 jdolecek } 296 1.1 jdolecek fcmp = VFSTOFILECORE(mp); 297 1.36 dsl return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE, 298 1.37 pooka mp->mnt_op->vfs_name, mp, l); 299 1.1 jdolecek } 300 1.1 jdolecek 301 1.1 jdolecek /* 302 1.1 jdolecek * Common code for mount and mountroot 303 1.1 jdolecek */ 304 1.1 jdolecek static int 305 1.57 dsl filecore_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct filecore_args *argp) 306 1.1 jdolecek { 307 1.1 jdolecek struct filecore_mnt *fcmp = (struct filecore_mnt *)0; 308 1.1 jdolecek struct buf *bp = NULL; 309 1.1 jdolecek dev_t dev = devvp->v_rdev; 310 1.1 jdolecek int error = EINVAL; 311 1.1 jdolecek int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 312 1.1 jdolecek struct filecore_disc_record *fcdr; 313 1.1 jdolecek unsigned map; 314 1.1 jdolecek unsigned log2secsize; 315 1.18 perry 316 1.1 jdolecek if (!ronly) 317 1.1 jdolecek return EROFS; 318 1.18 perry 319 1.46 ad if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0) 320 1.1 jdolecek return (error); 321 1.1 jdolecek 322 1.68 hannken vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 323 1.44 pooka error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED); 324 1.68 hannken VOP_UNLOCK(devvp); 325 1.1 jdolecek if (error) 326 1.1 jdolecek return error; 327 1.18 perry 328 1.1 jdolecek /* Read the filecore boot block to check FS validity and to find the map */ 329 1.1 jdolecek error = bread(devvp, FILECORE_BOOTBLOCK_BLKN, 330 1.78 maxv FILECORE_BOOTBLOCK_SIZE, 0, &bp); 331 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 332 1.1 jdolecek printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp, 333 1.1 jdolecek FILECORE_BOOTBLOCK_BLKN, FILECORE_BOOTBLOCK_SIZE, 334 1.1 jdolecek bp, error); 335 1.1 jdolecek #endif 336 1.1 jdolecek if (error != 0) 337 1.1 jdolecek goto out; 338 1.28 christos 339 1.28 christos KASSERT(bp != NULL); 340 1.1 jdolecek if (filecore_bbchecksum(bp->b_data) != 0) { 341 1.1 jdolecek error = EINVAL; 342 1.1 jdolecek goto out; 343 1.1 jdolecek } 344 1.32 jnemeth fcdr = (struct filecore_disc_record *)((char *)(bp->b_data) + 345 1.32 jnemeth FILECORE_BB_DISCREC); 346 1.1 jdolecek map = ((((8 << fcdr->log2secsize) - fcdr->zone_spare) 347 1.1 jdolecek * (fcdr->nzones / 2) - 8 * FILECORE_DISCREC_SIZE) 348 1.1 jdolecek << fcdr->log2bpmb) >> fcdr->log2secsize; 349 1.1 jdolecek log2secsize = fcdr->log2secsize; 350 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 351 1.1 jdolecek printf("brelse(%p) vf1\n", bp); 352 1.1 jdolecek #endif 353 1.42 ad brelse(bp, BC_AGE); 354 1.1 jdolecek bp = NULL; 355 1.1 jdolecek 356 1.1 jdolecek /* Read the bootblock in the map */ 357 1.78 maxv error = bread(devvp, map, 1 << log2secsize, 0, &bp); 358 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 359 1.1 jdolecek printf("bread(%p, %x, %d, CRED, %p)=%d\n", devvp, 360 1.1 jdolecek map, 1 << log2secsize, bp, error); 361 1.1 jdolecek #endif 362 1.1 jdolecek if (error != 0) 363 1.1 jdolecek goto out; 364 1.32 jnemeth fcdr = (struct filecore_disc_record *)((char *)(bp->b_data) + 4); 365 1.65 rmind fcmp = kmem_zalloc(sizeof(*fcmp), KM_SLEEP); 366 1.1 jdolecek if (fcdr->log2bpmb > fcdr->log2secsize) 367 1.1 jdolecek fcmp->log2bsize = fcdr->log2bpmb; 368 1.1 jdolecek else fcmp->log2bsize = fcdr->log2secsize; 369 1.1 jdolecek fcmp->blksize = 1 << fcmp->log2bsize; 370 1.12 jrf memcpy(&fcmp->drec, fcdr, sizeof(*fcdr)); 371 1.1 jdolecek fcmp->map = map; 372 1.1 jdolecek fcmp->idspz = ((8 << fcdr->log2secsize) - fcdr->zone_spare) 373 1.1 jdolecek / (fcdr->idlen + 1); 374 1.1 jdolecek fcmp->mask = (1 << fcdr->idlen) - 1; 375 1.1 jdolecek if (fcdr->big_flag & 1) { 376 1.1 jdolecek fcmp->nblks = ((((u_int64_t)fcdr->disc_size_2) << 32) 377 1.1 jdolecek + fcdr->disc_size) / fcmp->blksize; 378 1.1 jdolecek } else { 379 1.1 jdolecek fcmp->nblks=fcdr->disc_size / fcmp->blksize; 380 1.1 jdolecek } 381 1.1 jdolecek 382 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 383 1.1 jdolecek printf("brelse(%p) vf2\n", bp); 384 1.1 jdolecek #endif 385 1.42 ad brelse(bp, BC_AGE); 386 1.1 jdolecek bp = NULL; 387 1.1 jdolecek 388 1.1 jdolecek mp->mnt_data = fcmp; 389 1.10 christos mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev; 390 1.10 christos mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FILECORE); 391 1.10 christos mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 392 1.16 jdolecek mp->mnt_stat.f_namemax = 10; 393 1.1 jdolecek mp->mnt_flag |= MNT_LOCAL; 394 1.1 jdolecek mp->mnt_dev_bshift = fcdr->log2secsize; 395 1.1 jdolecek mp->mnt_fs_bshift = fcmp->log2bsize; 396 1.1 jdolecek 397 1.1 jdolecek fcmp->fc_mountp = mp; 398 1.1 jdolecek fcmp->fc_dev = dev; 399 1.1 jdolecek fcmp->fc_devvp = devvp; 400 1.1 jdolecek fcmp->fc_mntflags = argp->flags; 401 1.1 jdolecek if (argp->flags & FILECOREMNT_USEUID) { 402 1.27 ad fcmp->fc_uid = kauth_cred_getuid(l->l_cred); 403 1.27 ad fcmp->fc_gid = kauth_cred_getgid(l->l_cred); 404 1.1 jdolecek } else { 405 1.1 jdolecek fcmp->fc_uid = argp->uid; 406 1.1 jdolecek fcmp->fc_gid = argp->gid; 407 1.1 jdolecek } 408 1.18 perry 409 1.1 jdolecek return 0; 410 1.1 jdolecek out: 411 1.1 jdolecek if (bp) { 412 1.1 jdolecek #ifdef FILECORE_DEBUG_BR 413 1.1 jdolecek printf("brelse(%p) vf3\n", bp); 414 1.1 jdolecek #endif 415 1.42 ad brelse(bp, 0); 416 1.1 jdolecek } 417 1.1 jdolecek vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 418 1.44 pooka (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 419 1.64 hannken VOP_UNLOCK(devvp); 420 1.1 jdolecek return error; 421 1.1 jdolecek } 422 1.1 jdolecek 423 1.1 jdolecek /* 424 1.1 jdolecek * Make a filesystem operational. 425 1.1 jdolecek * Nothing to do at the moment. 426 1.1 jdolecek */ 427 1.1 jdolecek /* ARGSUSED */ 428 1.1 jdolecek int 429 1.57 dsl filecore_start(struct mount *mp, int flags) 430 1.1 jdolecek { 431 1.1 jdolecek return 0; 432 1.1 jdolecek } 433 1.1 jdolecek 434 1.1 jdolecek /* 435 1.1 jdolecek * unmount system call 436 1.1 jdolecek */ 437 1.1 jdolecek int 438 1.57 dsl filecore_unmount(struct mount *mp, int mntflags) 439 1.1 jdolecek { 440 1.1 jdolecek struct filecore_mnt *fcmp; 441 1.1 jdolecek int error, flags = 0; 442 1.18 perry 443 1.1 jdolecek if (mntflags & MNT_FORCE) 444 1.1 jdolecek flags |= FORCECLOSE; 445 1.1 jdolecek if ((error = vflush(mp, NULLVP, flags)) != 0) 446 1.1 jdolecek return (error); 447 1.1 jdolecek 448 1.1 jdolecek fcmp = VFSTOFILECORE(mp); 449 1.1 jdolecek 450 1.1 jdolecek if (fcmp->fc_devvp->v_type != VBAD) 451 1.71 hannken spec_node_setmountedfs(fcmp->fc_devvp, NULL); 452 1.1 jdolecek vn_lock(fcmp->fc_devvp, LK_EXCLUSIVE | LK_RETRY); 453 1.44 pooka error = VOP_CLOSE(fcmp->fc_devvp, FREAD, NOCRED); 454 1.1 jdolecek vput(fcmp->fc_devvp); 455 1.65 rmind kmem_free(fcmp, sizeof(*fcmp)); 456 1.1 jdolecek mp->mnt_data = NULL; 457 1.1 jdolecek mp->mnt_flag &= ~MNT_LOCAL; 458 1.1 jdolecek return (error); 459 1.1 jdolecek } 460 1.1 jdolecek 461 1.1 jdolecek /* 462 1.1 jdolecek * Return root of a filesystem 463 1.1 jdolecek */ 464 1.1 jdolecek int 465 1.82 ad filecore_root(struct mount *mp, int lktype, struct vnode **vpp) 466 1.1 jdolecek { 467 1.1 jdolecek struct vnode *nvp; 468 1.1 jdolecek int error; 469 1.1 jdolecek 470 1.82 ad if ((error = VFS_VGET(mp, FILECORE_ROOTINO, lktype, &nvp)) != 0) 471 1.1 jdolecek return (error); 472 1.1 jdolecek *vpp = nvp; 473 1.1 jdolecek return (0); 474 1.1 jdolecek } 475 1.1 jdolecek 476 1.1 jdolecek /* 477 1.1 jdolecek * Get file system statistics. 478 1.1 jdolecek */ 479 1.1 jdolecek int 480 1.57 dsl filecore_statvfs(struct mount *mp, struct statvfs *sbp) 481 1.1 jdolecek { 482 1.1 jdolecek struct filecore_mnt *fcmp = VFSTOFILECORE(mp); 483 1.1 jdolecek 484 1.1 jdolecek sbp->f_bsize = fcmp->blksize; 485 1.10 christos sbp->f_frsize = sbp->f_bsize; /* XXX */ 486 1.1 jdolecek sbp->f_iosize = sbp->f_bsize; /* XXX */ 487 1.1 jdolecek sbp->f_blocks = fcmp->nblks; 488 1.1 jdolecek sbp->f_bfree = 0; /* total free blocks */ 489 1.1 jdolecek sbp->f_bavail = 0; /* blocks free for non superuser */ 490 1.10 christos sbp->f_bresvd = 0; /* reserved blocks */ 491 1.1 jdolecek sbp->f_files = 0; /* total files */ 492 1.10 christos sbp->f_ffree = 0; /* free file nodes for non superuser */ 493 1.10 christos sbp->f_favail = 0; /* free file nodes */ 494 1.10 christos sbp->f_fresvd = 0; /* reserved file nodes */ 495 1.10 christos copy_statvfs_info(sbp, mp); 496 1.1 jdolecek return 0; 497 1.1 jdolecek } 498 1.1 jdolecek 499 1.1 jdolecek /* ARGSUSED */ 500 1.1 jdolecek int 501 1.57 dsl filecore_sync(struct mount *mp, int waitfor, kauth_cred_t cred) 502 1.1 jdolecek { 503 1.1 jdolecek return (0); 504 1.1 jdolecek } 505 1.1 jdolecek 506 1.1 jdolecek /* 507 1.1 jdolecek * File handle to vnode 508 1.1 jdolecek * 509 1.1 jdolecek * Have to be really careful about stale file handles: 510 1.1 jdolecek * - check that the inode number is in range 511 1.1 jdolecek * - call iget() to get the locked inode 512 1.1 jdolecek * - check for an unallocated inode (i_mode == 0) 513 1.1 jdolecek * - check that the generation number matches 514 1.1 jdolecek */ 515 1.1 jdolecek 516 1.1 jdolecek struct ifid { 517 1.1 jdolecek ushort ifid_len; 518 1.1 jdolecek ushort ifid_pad; 519 1.1 jdolecek u_int32_t ifid_ino; 520 1.1 jdolecek }; 521 1.1 jdolecek 522 1.1 jdolecek /* ARGSUSED */ 523 1.1 jdolecek int 524 1.82 ad filecore_fhtovp(struct mount *mp, struct fid *fhp, int lktype, 525 1.82 ad struct vnode **vpp) 526 1.1 jdolecek { 527 1.26 martin struct ifid ifh; 528 1.1 jdolecek struct vnode *nvp; 529 1.1 jdolecek struct filecore_node *ip; 530 1.1 jdolecek int error; 531 1.18 perry 532 1.26 martin if (fhp->fid_len != sizeof(struct ifid)) 533 1.26 martin return EINVAL; 534 1.26 martin 535 1.26 martin memcpy(&ifh, fhp, sizeof(ifh)); 536 1.82 ad if ((error = VFS_VGET(mp, ifh.ifid_ino, lktype, &nvp)) != 0) { 537 1.1 jdolecek *vpp = NULLVP; 538 1.1 jdolecek return (error); 539 1.1 jdolecek } 540 1.1 jdolecek ip = VTOI(nvp); 541 1.1 jdolecek if (filecore_staleinode(ip)) { 542 1.1 jdolecek vput(nvp); 543 1.1 jdolecek *vpp = NULLVP; 544 1.1 jdolecek return (ESTALE); 545 1.1 jdolecek } 546 1.1 jdolecek *vpp = nvp; 547 1.1 jdolecek return (0); 548 1.1 jdolecek } 549 1.1 jdolecek 550 1.1 jdolecek /* This looks complicated. Look at other vgets as well as the iso9660 one. 551 1.1 jdolecek * 552 1.1 jdolecek * The filecore inode number is made up of 1 byte directory entry index and 553 1.1 jdolecek * 3 bytes of the internal disc address of the directory. On a read-only 554 1.1 jdolecek * filesystem this is unique. For a read-write version we may not be able to 555 1.1 jdolecek * do vget, see msdosfs. 556 1.1 jdolecek */ 557 1.1 jdolecek 558 1.1 jdolecek int 559 1.82 ad filecore_vget(struct mount *mp, ino_t ino, int lktype, struct vnode **vpp) 560 1.1 jdolecek { 561 1.1 jdolecek int error; 562 1.1 jdolecek 563 1.77 hannken error = vcache_get(mp, &ino, sizeof(ino), vpp); 564 1.77 hannken if (error) 565 1.77 hannken return error; 566 1.82 ad error = vn_lock(*vpp, lktype); 567 1.67 rmind if (error) { 568 1.77 hannken vrele(*vpp); 569 1.77 hannken *vpp = NULL; 570 1.77 hannken return error; 571 1.1 jdolecek } 572 1.77 hannken return 0; 573 1.1 jdolecek } 574 1.1 jdolecek 575 1.1 jdolecek /* 576 1.1 jdolecek * Vnode pointer to File handle 577 1.1 jdolecek */ 578 1.1 jdolecek /* ARGSUSED */ 579 1.1 jdolecek int 580 1.57 dsl filecore_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) 581 1.1 jdolecek { 582 1.1 jdolecek struct filecore_node *ip = VTOI(vp); 583 1.26 martin struct ifid ifh; 584 1.18 perry 585 1.26 martin if (*fh_size < sizeof(struct ifid)) { 586 1.26 martin *fh_size = sizeof(struct ifid); 587 1.26 martin return E2BIG; 588 1.26 martin } 589 1.26 martin memset(&ifh, 0, sizeof(ifh)); 590 1.26 martin ifh.ifid_len = sizeof(struct ifid); 591 1.26 martin ifh.ifid_ino = ip->i_number; 592 1.26 martin memcpy(fhp, &ifh, sizeof(ifh)); 593 1.1 jdolecek return 0; 594 1.1 jdolecek } 595