1 1.27 andvar /* $NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /* 4 1.1 reinoud * Copyright (c) 2008, 2009 Reinoud Zandijk 5 1.1 reinoud * All rights reserved. 6 1.1 reinoud * 7 1.1 reinoud * Redistribution and use in source and binary forms, with or without 8 1.1 reinoud * modification, are permitted provided that the following conditions 9 1.1 reinoud * are met: 10 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 11 1.1 reinoud * notice, this list of conditions and the following disclaimer. 12 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 14 1.1 reinoud * documentation and/or other materials provided with the distribution. 15 1.1 reinoud * 16 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 reinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 reinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 reinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 reinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 reinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 reinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 reinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 reinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 reinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 reinoud * 27 1.1 reinoud */ 28 1.1 reinoud 29 1.1 reinoud #include <sys/cdefs.h> 30 1.1 reinoud #ifndef lint 31 1.27 andvar __KERNEL_RCSID(0, "$NetBSD: nilfs_vfsops.c,v 1.27 2021/09/16 22:19:11 andvar Exp $"); 32 1.1 reinoud #endif /* not lint */ 33 1.1 reinoud 34 1.1 reinoud 35 1.1 reinoud #if defined(_KERNEL_OPT) 36 1.1 reinoud #include "opt_compat_netbsd.h" 37 1.1 reinoud #endif 38 1.1 reinoud 39 1.1 reinoud #include <sys/param.h> 40 1.1 reinoud #include <sys/systm.h> 41 1.1 reinoud #include <sys/sysctl.h> 42 1.1 reinoud #include <sys/namei.h> 43 1.1 reinoud #include <sys/proc.h> 44 1.1 reinoud #include <sys/kernel.h> 45 1.1 reinoud #include <sys/vnode.h> 46 1.1 reinoud #include <miscfs/genfs/genfs.h> 47 1.1 reinoud #include <miscfs/specfs/specdev.h> 48 1.1 reinoud #include <sys/mount.h> 49 1.1 reinoud #include <sys/buf.h> 50 1.1 reinoud #include <sys/file.h> 51 1.1 reinoud #include <sys/device.h> 52 1.1 reinoud #include <sys/disklabel.h> 53 1.1 reinoud #include <sys/ioctl.h> 54 1.1 reinoud #include <sys/malloc.h> 55 1.1 reinoud #include <sys/dirent.h> 56 1.1 reinoud #include <sys/stat.h> 57 1.1 reinoud #include <sys/conf.h> 58 1.1 reinoud #include <sys/kauth.h> 59 1.1 reinoud #include <sys/module.h> 60 1.1 reinoud 61 1.1 reinoud #include <fs/nilfs/nilfs_mount.h> 62 1.1 reinoud #include <sys/dirhash.h> 63 1.1 reinoud 64 1.1 reinoud 65 1.1 reinoud #include "nilfs.h" 66 1.1 reinoud #include "nilfs_subr.h" 67 1.1 reinoud #include "nilfs_bswap.h" 68 1.1 reinoud 69 1.1 reinoud MODULE(MODULE_CLASS_VFS, nilfs, NULL); 70 1.1 reinoud 71 1.1 reinoud #define VTOI(vnode) ((struct nilfs_node *) vnode->v_data) 72 1.1 reinoud 73 1.1 reinoud /* verbose levels of the nilfs filingsystem */ 74 1.1 reinoud int nilfs_verbose = NILFS_DEBUGGING; 75 1.1 reinoud 76 1.1 reinoud /* malloc regions */ 77 1.1 reinoud MALLOC_JUSTDEFINE(M_NILFSMNT, "NILFS mount", "NILFS mount structures"); 78 1.1 reinoud MALLOC_JUSTDEFINE(M_NILFSTEMP, "NILFS temp", "NILFS scrap space"); 79 1.1 reinoud struct pool nilfs_node_pool; 80 1.1 reinoud 81 1.1 reinoud /* globals */ 82 1.1 reinoud struct _nilfs_devices nilfs_devices; 83 1.1 reinoud 84 1.1 reinoud /* supported functions predefined */ 85 1.1 reinoud VFS_PROTOS(nilfs); 86 1.1 reinoud 87 1.1 reinoud 88 1.1 reinoud /* --------------------------------------------------------------------- */ 89 1.1 reinoud 90 1.18 hannken /* 91 1.18 hannken * Genfs interfacing 92 1.18 hannken * 93 1.18 hannken * static const struct genfs_ops nilfs_genfsops = { 94 1.18 hannken * .gop_size = genfs_size, 95 1.18 hannken * size of transfers 96 1.18 hannken * .gop_alloc = nilfs_gop_alloc, 97 1.18 hannken * allocate len bytes at offset 98 1.18 hannken * .gop_write = genfs_gop_write, 99 1.18 hannken * putpages interface code 100 1.18 hannken * .gop_markupdate = nilfs_gop_markupdate, 101 1.18 hannken * set update/modify flags etc. 102 1.18 hannken * } 103 1.18 hannken */ 104 1.18 hannken 105 1.18 hannken /* 106 1.18 hannken * Callback from genfs to allocate len bytes at offset off; only called when 107 1.18 hannken * filling up gaps in the allocation. 108 1.18 hannken */ 109 1.18 hannken static int 110 1.18 hannken nilfs_gop_alloc(struct vnode *vp, off_t off, 111 1.18 hannken off_t len, int flags, kauth_cred_t cred) 112 1.18 hannken { 113 1.18 hannken DPRINTF(NOTIMPL, ("nilfs_gop_alloc not implemented\n")); 114 1.18 hannken DPRINTF(ALLOC, ("nilfs_gop_alloc called for %"PRIu64" bytes\n", len)); 115 1.18 hannken 116 1.18 hannken return 0; 117 1.18 hannken } 118 1.18 hannken 119 1.18 hannken 120 1.18 hannken /* 121 1.18 hannken * callback from genfs to update our flags 122 1.18 hannken */ 123 1.18 hannken static void 124 1.18 hannken nilfs_gop_markupdate(struct vnode *vp, int flags) 125 1.18 hannken { 126 1.18 hannken struct nilfs_node *nilfs_node = VTOI(vp); 127 1.18 hannken u_long mask = 0; 128 1.18 hannken 129 1.18 hannken if ((flags & GOP_UPDATE_ACCESSED) != 0) { 130 1.18 hannken mask = IN_ACCESS; 131 1.18 hannken } 132 1.18 hannken if ((flags & GOP_UPDATE_MODIFIED) != 0) { 133 1.18 hannken if (vp->v_type == VREG) { 134 1.18 hannken mask |= IN_CHANGE | IN_UPDATE; 135 1.18 hannken } else { 136 1.18 hannken mask |= IN_MODIFY; 137 1.18 hannken } 138 1.18 hannken } 139 1.18 hannken if (mask) { 140 1.18 hannken nilfs_node->i_flags |= mask; 141 1.18 hannken } 142 1.18 hannken } 143 1.18 hannken 144 1.18 hannken 145 1.18 hannken static const struct genfs_ops nilfs_genfsops = { 146 1.18 hannken .gop_size = genfs_size, 147 1.18 hannken .gop_alloc = nilfs_gop_alloc, 148 1.18 hannken .gop_write = genfs_gop_write_rwmap, 149 1.18 hannken .gop_markupdate = nilfs_gop_markupdate, 150 1.24 chs .gop_putrange = genfs_gop_putrange, 151 1.18 hannken }; 152 1.18 hannken 153 1.18 hannken /* --------------------------------------------------------------------- */ 154 1.18 hannken 155 1.1 reinoud /* predefine vnode-op list descriptor */ 156 1.1 reinoud extern const struct vnodeopv_desc nilfs_vnodeop_opv_desc; 157 1.1 reinoud 158 1.1 reinoud const struct vnodeopv_desc * const nilfs_vnodeopv_descs[] = { 159 1.1 reinoud &nilfs_vnodeop_opv_desc, 160 1.1 reinoud NULL, 161 1.1 reinoud }; 162 1.1 reinoud 163 1.1 reinoud 164 1.1 reinoud /* vfsops descriptor linked in as anchor point for the filingsystem */ 165 1.1 reinoud struct vfsops nilfs_vfsops = { 166 1.15 hannken .vfs_name = MOUNT_NILFS, 167 1.15 hannken .vfs_min_mount_data = sizeof (struct nilfs_args), 168 1.15 hannken .vfs_mount = nilfs_mount, 169 1.15 hannken .vfs_start = nilfs_start, 170 1.15 hannken .vfs_unmount = nilfs_unmount, 171 1.15 hannken .vfs_root = nilfs_root, 172 1.15 hannken .vfs_quotactl = (void *)eopnotsupp, 173 1.15 hannken .vfs_statvfs = nilfs_statvfs, 174 1.15 hannken .vfs_sync = nilfs_sync, 175 1.15 hannken .vfs_vget = nilfs_vget, 176 1.18 hannken .vfs_loadvnode = nilfs_loadvnode, 177 1.15 hannken .vfs_fhtovp = nilfs_fhtovp, 178 1.15 hannken .vfs_vptofh = nilfs_vptofh, 179 1.15 hannken .vfs_init = nilfs_init, 180 1.15 hannken .vfs_reinit = nilfs_reinit, 181 1.15 hannken .vfs_done = nilfs_done, 182 1.15 hannken .vfs_mountroot = nilfs_mountroot, 183 1.15 hannken .vfs_snapshot = nilfs_snapshot, 184 1.15 hannken .vfs_extattrctl = vfs_stdextattrctl, 185 1.23 hannken .vfs_suspendctl = genfs_suspendctl, 186 1.15 hannken .vfs_renamelock_enter = genfs_renamelock_enter, 187 1.15 hannken .vfs_renamelock_exit = genfs_renamelock_exit, 188 1.15 hannken .vfs_fsync = (void *)eopnotsupp, 189 1.15 hannken .vfs_opv_descs = nilfs_vnodeopv_descs 190 1.1 reinoud }; 191 1.1 reinoud 192 1.1 reinoud /* --------------------------------------------------------------------- */ 193 1.1 reinoud 194 1.1 reinoud /* file system starts here */ 195 1.1 reinoud void 196 1.1 reinoud nilfs_init(void) 197 1.1 reinoud { 198 1.1 reinoud size_t size; 199 1.1 reinoud 200 1.1 reinoud /* setup memory types */ 201 1.1 reinoud malloc_type_attach(M_NILFSMNT); 202 1.1 reinoud malloc_type_attach(M_NILFSTEMP); 203 1.1 reinoud 204 1.1 reinoud /* init device lists */ 205 1.1 reinoud SLIST_INIT(&nilfs_devices); 206 1.1 reinoud 207 1.1 reinoud /* init node pools */ 208 1.1 reinoud size = sizeof(struct nilfs_node); 209 1.1 reinoud pool_init(&nilfs_node_pool, size, 0, 0, 0, 210 1.1 reinoud "nilfs_node_pool", NULL, IPL_NONE); 211 1.1 reinoud } 212 1.1 reinoud 213 1.1 reinoud 214 1.1 reinoud void 215 1.1 reinoud nilfs_reinit(void) 216 1.1 reinoud { 217 1.1 reinoud /* nothing to do */ 218 1.1 reinoud } 219 1.1 reinoud 220 1.1 reinoud 221 1.1 reinoud void 222 1.1 reinoud nilfs_done(void) 223 1.1 reinoud { 224 1.1 reinoud /* remove pools */ 225 1.1 reinoud pool_destroy(&nilfs_node_pool); 226 1.1 reinoud 227 1.1 reinoud malloc_type_detach(M_NILFSMNT); 228 1.1 reinoud malloc_type_detach(M_NILFSTEMP); 229 1.1 reinoud } 230 1.1 reinoud 231 1.1 reinoud /* 232 1.1 reinoud * If running a DEBUG kernel, provide an easy way to set the debug flags when 233 1.1 reinoud * running into a problem. 234 1.1 reinoud */ 235 1.1 reinoud #define NILFS_VERBOSE_SYSCTLOPT 1 236 1.1 reinoud 237 1.26 pgoyette SYSCTL_SETUP(nilfs_sysctl_setup, "nilfs sysctl") 238 1.26 pgoyette { 239 1.26 pgoyette const struct sysctlnode *node; 240 1.26 pgoyette 241 1.26 pgoyette /* 242 1.26 pgoyette * XXX the "30" below could be dynamic, thereby eliminating one 243 1.26 pgoyette * more instance of the "number to vfs" mapping problem, but 244 1.26 pgoyette * "30" is the order as taken from sys/mount.h 245 1.26 pgoyette */ 246 1.26 pgoyette sysctl_createv(clog, 0, NULL, &node, 247 1.26 pgoyette CTLFLAG_PERMANENT, 248 1.26 pgoyette CTLTYPE_NODE, "nilfs", 249 1.26 pgoyette SYSCTL_DESCR("NTT's NILFSv2"), 250 1.26 pgoyette NULL, 0, NULL, 0, 251 1.26 pgoyette CTL_VFS, 30, CTL_EOL); 252 1.26 pgoyette #ifdef DEBUG 253 1.26 pgoyette sysctl_createv(clog, 0, NULL, &node, 254 1.26 pgoyette CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 255 1.26 pgoyette CTLTYPE_INT, "verbose", 256 1.26 pgoyette SYSCTL_DESCR("Bitmask for filesystem debugging"), 257 1.26 pgoyette NULL, 0, &nilfs_verbose, 0, 258 1.26 pgoyette CTL_VFS, 30, NILFS_VERBOSE_SYSCTLOPT, CTL_EOL); 259 1.26 pgoyette #endif 260 1.26 pgoyette } 261 1.26 pgoyette 262 1.1 reinoud static int 263 1.1 reinoud nilfs_modcmd(modcmd_t cmd, void *arg) 264 1.1 reinoud { 265 1.1 reinoud int error; 266 1.1 reinoud 267 1.1 reinoud switch (cmd) { 268 1.1 reinoud case MODULE_CMD_INIT: 269 1.1 reinoud error = vfs_attach(&nilfs_vfsops); 270 1.1 reinoud if (error != 0) 271 1.1 reinoud break; 272 1.1 reinoud break; 273 1.1 reinoud case MODULE_CMD_FINI: 274 1.1 reinoud error = vfs_detach(&nilfs_vfsops); 275 1.1 reinoud if (error != 0) 276 1.1 reinoud break; 277 1.1 reinoud break; 278 1.1 reinoud default: 279 1.1 reinoud error = ENOTTY; 280 1.1 reinoud break; 281 1.1 reinoud } 282 1.1 reinoud 283 1.1 reinoud return (error); 284 1.1 reinoud } 285 1.1 reinoud 286 1.1 reinoud /* --------------------------------------------------------------------- */ 287 1.1 reinoud 288 1.1 reinoud int 289 1.1 reinoud nilfs_mountroot(void) 290 1.1 reinoud { 291 1.1 reinoud return EOPNOTSUPP; 292 1.1 reinoud } 293 1.1 reinoud 294 1.1 reinoud /* --------------------------------------------------------------------- */ 295 1.1 reinoud 296 1.1 reinoud /* system nodes */ 297 1.1 reinoud static int 298 1.1 reinoud nilfs_create_system_nodes(struct nilfs_device *nilfsdev) 299 1.1 reinoud { 300 1.1 reinoud int error; 301 1.1 reinoud 302 1.1 reinoud error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_DAT_INO, 303 1.1 reinoud &nilfsdev->super_root.sr_dat, &nilfsdev->dat_node); 304 1.1 reinoud if (error) 305 1.1 reinoud goto errorout; 306 1.1 reinoud 307 1.1 reinoud error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_CPFILE_INO, 308 1.1 reinoud &nilfsdev->super_root.sr_cpfile, &nilfsdev->cp_node); 309 1.1 reinoud if (error) 310 1.1 reinoud goto errorout; 311 1.1 reinoud 312 1.1 reinoud error = nilfs_get_node_raw(nilfsdev, NULL, NILFS_SUFILE_INO, 313 1.1 reinoud &nilfsdev->super_root.sr_sufile, &nilfsdev->su_node); 314 1.1 reinoud if (error) 315 1.1 reinoud goto errorout; 316 1.1 reinoud 317 1.1 reinoud return 0; 318 1.1 reinoud errorout: 319 1.1 reinoud nilfs_dispose_node(&nilfsdev->dat_node); 320 1.1 reinoud nilfs_dispose_node(&nilfsdev->cp_node); 321 1.1 reinoud nilfs_dispose_node(&nilfsdev->su_node); 322 1.1 reinoud 323 1.1 reinoud return error; 324 1.1 reinoud } 325 1.1 reinoud 326 1.1 reinoud 327 1.1 reinoud static void 328 1.1 reinoud nilfs_release_system_nodes(struct nilfs_device *nilfsdev) 329 1.1 reinoud { 330 1.1 reinoud if (!nilfsdev) 331 1.1 reinoud return; 332 1.1 reinoud if (nilfsdev->refcnt > 0) 333 1.1 reinoud return; 334 1.1 reinoud 335 1.1 reinoud nilfs_dispose_node(&nilfsdev->dat_node); 336 1.1 reinoud nilfs_dispose_node(&nilfsdev->cp_node); 337 1.1 reinoud nilfs_dispose_node(&nilfsdev->su_node); 338 1.1 reinoud } 339 1.1 reinoud 340 1.1 reinoud 341 1.1 reinoud /* --------------------------------------------------------------------- */ 342 1.1 reinoud 343 1.1 reinoud static int 344 1.1 reinoud nilfs_check_superblock_crc(struct nilfs_super_block *super) 345 1.1 reinoud { 346 1.1 reinoud uint32_t super_crc, comp_crc; 347 1.1 reinoud 348 1.1 reinoud /* check super block magic */ 349 1.1 reinoud if (nilfs_rw16(super->s_magic) != NILFS_SUPER_MAGIC) 350 1.1 reinoud return 0; 351 1.1 reinoud 352 1.1 reinoud /* preserve crc */ 353 1.1 reinoud super_crc = nilfs_rw32(super->s_sum); 354 1.1 reinoud 355 1.1 reinoud /* calculate */ 356 1.1 reinoud super->s_sum = 0; 357 1.1 reinoud comp_crc = crc32_le(nilfs_rw32(super->s_crc_seed), 358 1.1 reinoud (uint8_t *) super, nilfs_rw16(super->s_bytes)); 359 1.1 reinoud 360 1.1 reinoud /* restore */ 361 1.1 reinoud super->s_sum = nilfs_rw32(super_crc); 362 1.1 reinoud 363 1.1 reinoud /* check CRC */ 364 1.1 reinoud return (super_crc == comp_crc); 365 1.1 reinoud } 366 1.1 reinoud 367 1.1 reinoud 368 1.1 reinoud 369 1.1 reinoud static int 370 1.1 reinoud nilfs_read_superblock(struct nilfs_device *nilfsdev) 371 1.1 reinoud { 372 1.1 reinoud struct nilfs_super_block *super, tmp_super; 373 1.1 reinoud struct buf *bp; 374 1.1 reinoud uint64_t sb1off, sb2off; 375 1.2 reinoud uint64_t last_cno1, last_cno2; 376 1.1 reinoud uint64_t dev_blk; 377 1.1 reinoud int dev_bsize, dev_blks; 378 1.1 reinoud int sb1ok, sb2ok, swp; 379 1.1 reinoud int error; 380 1.1 reinoud 381 1.1 reinoud sb1off = NILFS_SB_OFFSET_BYTES; 382 1.1 reinoud sb2off = NILFS_SB2_OFFSET_BYTES(nilfsdev->devsize); 383 1.1 reinoud 384 1.1 reinoud dev_bsize = 1 << nilfsdev->devvp->v_mount->mnt_fs_bshift; 385 1.1 reinoud 386 1.1 reinoud /* read our superblock regardless of backing device blocksize */ 387 1.1 reinoud dev_blk = 0; 388 1.1 reinoud dev_blks = (sb1off + dev_bsize -1)/dev_bsize; 389 1.21 maxv error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp); 390 1.1 reinoud if (error) { 391 1.1 reinoud return error; 392 1.1 reinoud } 393 1.1 reinoud 394 1.1 reinoud /* copy read-in super block at the offset */ 395 1.1 reinoud super = &nilfsdev->super; 396 1.1 reinoud memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES, 397 1.1 reinoud sizeof(struct nilfs_super_block)); 398 1.1 reinoud brelse(bp, BC_AGE); 399 1.1 reinoud 400 1.1 reinoud /* read our 2nd superblock regardless of backing device blocksize */ 401 1.1 reinoud dev_blk = sb2off / dev_bsize; 402 1.1 reinoud dev_blks = 2; /* assumption max one dev_bsize */ 403 1.21 maxv error = bread(nilfsdev->devvp, dev_blk, dev_blks * dev_bsize, 0, &bp); 404 1.1 reinoud if (error) { 405 1.1 reinoud return error; 406 1.1 reinoud } 407 1.1 reinoud 408 1.1 reinoud /* copy read-in superblock2 at the offset */ 409 1.1 reinoud super = &nilfsdev->super2; 410 1.1 reinoud memcpy(super, (uint8_t *) bp->b_data + NILFS_SB_OFFSET_BYTES, 411 1.1 reinoud sizeof(struct nilfs_super_block)); 412 1.1 reinoud brelse(bp, BC_AGE); 413 1.1 reinoud 414 1.1 reinoud sb1ok = nilfs_check_superblock_crc(&nilfsdev->super); 415 1.1 reinoud sb2ok = nilfs_check_superblock_crc(&nilfsdev->super2); 416 1.1 reinoud 417 1.2 reinoud last_cno1 = nilfs_rw64(nilfsdev->super.s_last_cno); 418 1.2 reinoud last_cno2 = nilfs_rw64(nilfsdev->super2.s_last_cno); 419 1.2 reinoud swp = sb2ok && (last_cno2 > last_cno1); 420 1.1 reinoud 421 1.1 reinoud if (swp) { 422 1.1 reinoud printf("nilfs warning: broken superblock, using spare\n"); 423 1.1 reinoud tmp_super = nilfsdev->super2; 424 1.1 reinoud nilfsdev->super2 = nilfsdev->super; /* why preserve? */ 425 1.1 reinoud nilfsdev->super = tmp_super; 426 1.1 reinoud } 427 1.1 reinoud 428 1.1 reinoud if (!sb1ok && !sb2ok) { 429 1.1 reinoud printf("nilfs: no valid superblocks found\n"); 430 1.1 reinoud return EINVAL; 431 1.1 reinoud } 432 1.1 reinoud 433 1.1 reinoud return 0; 434 1.1 reinoud } 435 1.1 reinoud 436 1.1 reinoud 437 1.1 reinoud /* XXX NOTHING from the system nodes should need to be written here */ 438 1.1 reinoud static void 439 1.1 reinoud nilfs_unmount_base(struct nilfs_device *nilfsdev) 440 1.1 reinoud { 441 1.13 mrg int error __diagused; 442 1.1 reinoud 443 1.1 reinoud if (!nilfsdev) 444 1.1 reinoud return; 445 1.1 reinoud 446 1.1 reinoud /* remove all our information */ 447 1.1 reinoud error = vinvalbuf(nilfsdev->devvp, 0, FSCRED, curlwp, 0, 0); 448 1.1 reinoud KASSERT(error == 0); 449 1.1 reinoud 450 1.1 reinoud /* release the device's system nodes */ 451 1.1 reinoud nilfs_release_system_nodes(nilfsdev); 452 1.1 reinoud 453 1.1 reinoud /* TODO writeout super_block? */ 454 1.1 reinoud } 455 1.1 reinoud 456 1.1 reinoud 457 1.1 reinoud static int 458 1.1 reinoud nilfs_mount_base(struct nilfs_device *nilfsdev, 459 1.1 reinoud struct mount *mp, struct nilfs_args *args) 460 1.1 reinoud { 461 1.1 reinoud struct lwp *l = curlwp; 462 1.1 reinoud uint64_t last_pseg, last_cno, last_seq; 463 1.1 reinoud uint32_t log_blocksize; 464 1.1 reinoud int error; 465 1.1 reinoud 466 1.1 reinoud /* flush out any old buffers remaining from a previous use. */ 467 1.1 reinoud if ((error = vinvalbuf(nilfsdev->devvp, V_SAVE, l->l_cred, l, 0, 0))) 468 1.1 reinoud return error; 469 1.1 reinoud 470 1.1 reinoud /* read in our superblock */ 471 1.1 reinoud error = nilfs_read_superblock(nilfsdev); 472 1.1 reinoud if (error) { 473 1.1 reinoud printf("nilfs_mount: can't read in super block : %d\n", error); 474 1.1 reinoud return error; 475 1.1 reinoud } 476 1.1 reinoud 477 1.1 reinoud /* get our blocksize */ 478 1.1 reinoud log_blocksize = nilfs_rw32(nilfsdev->super.s_log_block_size); 479 1.1 reinoud nilfsdev->blocksize = (uint64_t) 1 << (log_blocksize + 10); 480 1.1 reinoud /* TODO check superblock's blocksize limits */ 481 1.1 reinoud 482 1.1 reinoud /* calculate dat structure parameters */ 483 1.1 reinoud nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->dat_mdt, 484 1.1 reinoud nilfs_rw16(nilfsdev->super.s_dat_entry_size)); 485 1.1 reinoud nilfs_calc_mdt_consts(nilfsdev, &nilfsdev->ifile_mdt, 486 1.1 reinoud nilfs_rw16(nilfsdev->super.s_inode_size)); 487 1.1 reinoud 488 1.1 reinoud DPRINTF(VOLUMES, ("nilfs_mount: accepted super block\n")); 489 1.1 reinoud 490 1.1 reinoud /* search for the super root and roll forward when needed */ 491 1.1 reinoud nilfs_search_super_root(nilfsdev); 492 1.1 reinoud 493 1.1 reinoud nilfsdev->mount_state = nilfs_rw16(nilfsdev->super.s_state); 494 1.1 reinoud if (nilfsdev->mount_state != NILFS_VALID_FS) { 495 1.1 reinoud printf("FS is seriously damaged, needs repairing\n"); 496 1.1 reinoud printf("aborting mount\n"); 497 1.1 reinoud return EINVAL; 498 1.1 reinoud } 499 1.1 reinoud 500 1.1 reinoud /* 501 1.1 reinoud * FS should be ok now. The superblock and the last segsum could be 502 1.1 reinoud * updated from the repair so extract running values again. 503 1.1 reinoud */ 504 1.1 reinoud last_pseg = nilfs_rw64(nilfsdev->super.s_last_pseg); /*blknr */ 505 1.1 reinoud last_cno = nilfs_rw64(nilfsdev->super.s_last_cno); 506 1.1 reinoud last_seq = nilfs_rw64(nilfsdev->super.s_last_seq); 507 1.1 reinoud 508 1.1 reinoud nilfsdev->last_seg_seq = last_seq; 509 1.1 reinoud nilfsdev->last_seg_num = nilfs_get_segnum_of_block(nilfsdev, last_pseg); 510 1.1 reinoud nilfsdev->next_seg_num = nilfs_get_segnum_of_block(nilfsdev, 511 1.1 reinoud nilfs_rw64(nilfsdev->last_segsum.ss_next)); 512 1.1 reinoud nilfsdev->last_cno = last_cno; 513 1.1 reinoud 514 1.1 reinoud DPRINTF(VOLUMES, ("nilfs_mount: accepted super root\n")); 515 1.1 reinoud 516 1.1 reinoud /* create system vnodes for DAT, CP and SEGSUM */ 517 1.1 reinoud error = nilfs_create_system_nodes(nilfsdev); 518 1.1 reinoud if (error) 519 1.1 reinoud nilfs_unmount_base(nilfsdev); 520 1.1 reinoud return error; 521 1.1 reinoud } 522 1.1 reinoud 523 1.1 reinoud 524 1.1 reinoud static void 525 1.1 reinoud nilfs_unmount_device(struct nilfs_device *nilfsdev) 526 1.1 reinoud { 527 1.1 reinoud int error; 528 1.1 reinoud 529 1.1 reinoud /* is there anything? */ 530 1.1 reinoud if (nilfsdev == NULL) 531 1.1 reinoud return; 532 1.1 reinoud 533 1.1 reinoud /* remove the device only if we're the last reference */ 534 1.1 reinoud nilfsdev->refcnt--; 535 1.1 reinoud if (nilfsdev->refcnt >= 1) 536 1.1 reinoud return; 537 1.1 reinoud 538 1.1 reinoud /* unmount our base */ 539 1.1 reinoud nilfs_unmount_base(nilfsdev); 540 1.1 reinoud 541 1.1 reinoud /* remove from our device list */ 542 1.1 reinoud SLIST_REMOVE(&nilfs_devices, nilfsdev, nilfs_device, next_device); 543 1.1 reinoud 544 1.1 reinoud /* close device */ 545 1.1 reinoud DPRINTF(VOLUMES, ("closing device\n")); 546 1.1 reinoud 547 1.1 reinoud /* remove our mount reference before closing device */ 548 1.11 hannken spec_node_setmountedfs(nilfsdev->devvp, NULL); 549 1.1 reinoud 550 1.1 reinoud /* devvp is still locked by us */ 551 1.1 reinoud vn_lock(nilfsdev->devvp, LK_EXCLUSIVE | LK_RETRY); 552 1.1 reinoud error = VOP_CLOSE(nilfsdev->devvp, FREAD | FWRITE, NOCRED); 553 1.1 reinoud if (error) 554 1.1 reinoud printf("Error during closure of device! error %d, " 555 1.1 reinoud "device might stay locked\n", error); 556 1.1 reinoud DPRINTF(VOLUMES, ("device close ok\n")); 557 1.1 reinoud 558 1.1 reinoud /* clear our mount reference and release device node */ 559 1.1 reinoud vput(nilfsdev->devvp); 560 1.1 reinoud 561 1.1 reinoud /* free our device info */ 562 1.17 hannken cv_destroy(&nilfsdev->sync_cv); 563 1.1 reinoud free(nilfsdev, M_NILFSMNT); 564 1.1 reinoud } 565 1.1 reinoud 566 1.1 reinoud 567 1.1 reinoud static int 568 1.1 reinoud nilfs_check_mounts(struct nilfs_device *nilfsdev, struct mount *mp, 569 1.1 reinoud struct nilfs_args *args) 570 1.1 reinoud { 571 1.1 reinoud struct nilfs_mount *ump; 572 1.1 reinoud uint64_t last_cno; 573 1.1 reinoud 574 1.1 reinoud /* no double-mounting of the same checkpoint */ 575 1.1 reinoud STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) { 576 1.1 reinoud if (ump->mount_args.cpno == args->cpno) 577 1.1 reinoud return EBUSY; 578 1.1 reinoud } 579 1.1 reinoud 580 1.1 reinoud /* allow readonly mounts without questioning here */ 581 1.1 reinoud if (mp->mnt_flag & MNT_RDONLY) 582 1.1 reinoud return 0; 583 1.1 reinoud 584 1.1 reinoud /* readwrite mount you want */ 585 1.1 reinoud STAILQ_FOREACH(ump, &nilfsdev->mounts, next_mount) { 586 1.1 reinoud /* only one RW mount on this device! */ 587 1.1 reinoud if ((ump->vfs_mountp->mnt_flag & MNT_RDONLY)==0) 588 1.1 reinoud return EROFS; 589 1.1 reinoud /* RDONLY on last mountpoint is device busy */ 590 1.1 reinoud last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno); 591 1.1 reinoud if (ump->mount_args.cpno == last_cno) 592 1.1 reinoud return EBUSY; 593 1.1 reinoud } 594 1.1 reinoud 595 1.1 reinoud /* OK for now */ 596 1.1 reinoud return 0; 597 1.1 reinoud } 598 1.1 reinoud 599 1.1 reinoud 600 1.1 reinoud static int 601 1.1 reinoud nilfs_mount_device(struct vnode *devvp, struct mount *mp, struct nilfs_args *args, 602 1.1 reinoud struct nilfs_device **nilfsdev_p) 603 1.1 reinoud { 604 1.7 christos uint64_t psize; 605 1.7 christos unsigned secsize; 606 1.1 reinoud struct nilfs_device *nilfsdev; 607 1.1 reinoud struct lwp *l = curlwp; 608 1.1 reinoud int openflags, accessmode, error; 609 1.1 reinoud 610 1.1 reinoud DPRINTF(VOLUMES, ("Mounting NILFS device\n")); 611 1.1 reinoud 612 1.1 reinoud /* lookup device in our nilfs_mountpoints */ 613 1.1 reinoud *nilfsdev_p = NULL; 614 1.1 reinoud SLIST_FOREACH(nilfsdev, &nilfs_devices, next_device) 615 1.1 reinoud if (nilfsdev->devvp == devvp) 616 1.1 reinoud break; 617 1.1 reinoud 618 1.1 reinoud if (nilfsdev) { 619 1.1 reinoud DPRINTF(VOLUMES, ("device already mounted\n")); 620 1.1 reinoud error = nilfs_check_mounts(nilfsdev, mp, args); 621 1.1 reinoud if (error) 622 1.1 reinoud return error; 623 1.1 reinoud nilfsdev->refcnt++; 624 1.1 reinoud *nilfsdev_p = nilfsdev; 625 1.1 reinoud return 0; 626 1.1 reinoud } 627 1.1 reinoud 628 1.1 reinoud DPRINTF(VOLUMES, ("no previous mounts on this device, mounting device\n")); 629 1.1 reinoud 630 1.1 reinoud /* check if its a block device specified */ 631 1.1 reinoud if (devvp->v_type != VBLK) { 632 1.1 reinoud vrele(devvp); 633 1.1 reinoud return ENOTBLK; 634 1.1 reinoud } 635 1.1 reinoud if (bdevsw_lookup(devvp->v_rdev) == NULL) { 636 1.1 reinoud vrele(devvp); 637 1.22 msaitoh return ENXIO; 638 1.1 reinoud } 639 1.1 reinoud 640 1.1 reinoud /* 641 1.1 reinoud * If mount by non-root, then verify that user has necessary 642 1.1 reinoud * permissions on the device. 643 1.1 reinoud */ 644 1.1 reinoud accessmode = VREAD; 645 1.1 reinoud if ((mp->mnt_flag & MNT_RDONLY) == 0) 646 1.1 reinoud accessmode |= VWRITE; 647 1.1 reinoud vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 648 1.9 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 649 1.9 elad KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode)); 650 1.3 hannken VOP_UNLOCK(devvp); 651 1.1 reinoud if (error) { 652 1.1 reinoud vrele(devvp); 653 1.1 reinoud return error; 654 1.1 reinoud } 655 1.1 reinoud 656 1.1 reinoud /* 657 1.1 reinoud * Open device read-write; TODO how about upgrading later when needed? 658 1.1 reinoud */ 659 1.1 reinoud openflags = FREAD | FWRITE; 660 1.8 hannken vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 661 1.1 reinoud error = VOP_OPEN(devvp, openflags, FSCRED); 662 1.8 hannken VOP_UNLOCK(devvp); 663 1.1 reinoud if (error) { 664 1.1 reinoud vrele(devvp); 665 1.1 reinoud return error; 666 1.1 reinoud } 667 1.1 reinoud 668 1.1 reinoud /* opened ok, try mounting */ 669 1.7 christos nilfsdev = malloc(sizeof(*nilfsdev), M_NILFSMNT, M_WAITOK | M_ZERO); 670 1.1 reinoud 671 1.1 reinoud /* initialise */ 672 1.1 reinoud nilfsdev->refcnt = 1; 673 1.1 reinoud nilfsdev->devvp = devvp; 674 1.1 reinoud nilfsdev->uncomitted_bl = 0; 675 1.5 pgoyette cv_init(&nilfsdev->sync_cv, "nilfssyn"); 676 1.1 reinoud STAILQ_INIT(&nilfsdev->mounts); 677 1.1 reinoud 678 1.6 dholland /* register nilfs_device in list */ 679 1.6 dholland SLIST_INSERT_HEAD(&nilfs_devices, nilfsdev, next_device); 680 1.6 dholland 681 1.1 reinoud /* get our device's size */ 682 1.7 christos error = getdisksize(devvp, &psize, &secsize); 683 1.1 reinoud if (error) { 684 1.1 reinoud /* remove all our information */ 685 1.1 reinoud nilfs_unmount_device(nilfsdev); 686 1.1 reinoud return EINVAL; 687 1.1 reinoud } 688 1.7 christos 689 1.7 christos nilfsdev->devsize = psize * secsize; 690 1.1 reinoud 691 1.1 reinoud /* connect to the head for most recent files XXX really pass mp and args? */ 692 1.1 reinoud error = nilfs_mount_base(nilfsdev, mp, args); 693 1.1 reinoud if (error) { 694 1.1 reinoud /* remove all our information */ 695 1.1 reinoud nilfs_unmount_device(nilfsdev); 696 1.1 reinoud return EINVAL; 697 1.1 reinoud } 698 1.1 reinoud 699 1.1 reinoud *nilfsdev_p = nilfsdev; 700 1.1 reinoud DPRINTF(VOLUMES, ("NILFS device mounted ok\n")); 701 1.1 reinoud 702 1.1 reinoud return 0; 703 1.1 reinoud } 704 1.1 reinoud 705 1.1 reinoud 706 1.1 reinoud static int 707 1.1 reinoud nilfs_mount_checkpoint(struct nilfs_mount *ump) 708 1.1 reinoud { 709 1.1 reinoud struct nilfs_cpfile_header *cphdr; 710 1.1 reinoud struct nilfs_checkpoint *cp; 711 1.1 reinoud struct nilfs_inode ifile_inode; 712 1.1 reinoud struct nilfs_node *cp_node; 713 1.1 reinoud struct buf *bp; 714 1.1 reinoud uint64_t ncp, nsn, fcpno, blocknr, last_cno; 715 1.1 reinoud uint32_t off, dlen; 716 1.1 reinoud int cp_per_block, error; 717 1.1 reinoud 718 1.1 reinoud DPRINTF(VOLUMES, ("mount_nilfs: trying to mount checkpoint number " 719 1.1 reinoud "%"PRIu64"\n", ump->mount_args.cpno)); 720 1.1 reinoud 721 1.1 reinoud cp_node = ump->nilfsdev->cp_node; 722 1.1 reinoud 723 1.1 reinoud /* get cpfile header from 1st block of cp file */ 724 1.21 maxv error = nilfs_bread(cp_node, 0, 0, &bp); 725 1.1 reinoud if (error) 726 1.1 reinoud return error; 727 1.1 reinoud cphdr = (struct nilfs_cpfile_header *) bp->b_data; 728 1.1 reinoud ncp = nilfs_rw64(cphdr->ch_ncheckpoints); 729 1.1 reinoud nsn = nilfs_rw64(cphdr->ch_nsnapshots); 730 1.1 reinoud 731 1.1 reinoud brelse(bp, BC_AGE); 732 1.1 reinoud 733 1.1 reinoud DPRINTF(VOLUMES, ("mount_nilfs: checkpoint header read in\n")); 734 1.1 reinoud DPRINTF(VOLUMES, ("\tNumber of checkpoints %"PRIu64"\n", ncp)); 735 1.1 reinoud DPRINTF(VOLUMES, ("\tNumber of snapshots %"PRIu64"\n", nsn)); 736 1.12 christos #ifndef NILFS_DEBUG 737 1.12 christos __USE(ncp); 738 1.12 christos __USE(nsn); 739 1.12 christos #endif 740 1.1 reinoud 741 1.1 reinoud /* read in our specified checkpoint */ 742 1.1 reinoud dlen = nilfs_rw16(ump->nilfsdev->super.s_checkpoint_size); 743 1.1 reinoud cp_per_block = ump->nilfsdev->blocksize / dlen; 744 1.1 reinoud 745 1.1 reinoud fcpno = ump->mount_args.cpno + NILFS_CPFILE_FIRST_CHECKPOINT_OFFSET -1; 746 1.1 reinoud blocknr = fcpno / cp_per_block; 747 1.1 reinoud off = (fcpno % cp_per_block) * dlen; 748 1.1 reinoud 749 1.21 maxv error = nilfs_bread(cp_node, blocknr, 0, &bp); 750 1.1 reinoud if (error) { 751 1.1 reinoud printf("mount_nilfs: couldn't read cp block %"PRIu64"\n", 752 1.1 reinoud fcpno); 753 1.1 reinoud return EINVAL; 754 1.1 reinoud } 755 1.1 reinoud 756 1.1 reinoud /* needs to be a valid checkpoint */ 757 1.1 reinoud cp = (struct nilfs_checkpoint *) ((uint8_t *) bp->b_data + off); 758 1.1 reinoud if (cp->cp_flags & NILFS_CHECKPOINT_INVALID) { 759 1.1 reinoud printf("mount_nilfs: checkpoint marked invalid\n"); 760 1.1 reinoud brelse(bp, BC_AGE); 761 1.1 reinoud return EINVAL; 762 1.1 reinoud } 763 1.1 reinoud 764 1.1 reinoud /* is this really the checkpoint we want? */ 765 1.1 reinoud if (nilfs_rw64(cp->cp_cno) != ump->mount_args.cpno) { 766 1.1 reinoud printf("mount_nilfs: checkpoint file corrupt? " 767 1.1 reinoud "expected cpno %"PRIu64", found cpno %"PRIu64"\n", 768 1.1 reinoud ump->mount_args.cpno, nilfs_rw64(cp->cp_cno)); 769 1.1 reinoud brelse(bp, BC_AGE); 770 1.1 reinoud return EINVAL; 771 1.1 reinoud } 772 1.1 reinoud 773 1.1 reinoud /* check if its a snapshot ! */ 774 1.1 reinoud last_cno = nilfs_rw64(ump->nilfsdev->super.s_last_cno); 775 1.1 reinoud if (ump->mount_args.cpno != last_cno) { 776 1.1 reinoud /* only allow snapshots if not mounting on the last cp */ 777 1.1 reinoud if ((cp->cp_flags & NILFS_CHECKPOINT_SNAPSHOT) == 0) { 778 1.1 reinoud printf( "mount_nilfs: checkpoint %"PRIu64" is not a " 779 1.1 reinoud "snapshot\n", ump->mount_args.cpno); 780 1.1 reinoud brelse(bp, BC_AGE); 781 1.1 reinoud return EINVAL; 782 1.1 reinoud } 783 1.1 reinoud } 784 1.1 reinoud 785 1.1 reinoud ifile_inode = cp->cp_ifile_inode; 786 1.1 reinoud brelse(bp, BC_AGE); 787 1.1 reinoud 788 1.1 reinoud /* get ifile inode */ 789 1.1 reinoud error = nilfs_get_node_raw(ump->nilfsdev, NULL, NILFS_IFILE_INO, 790 1.1 reinoud &ifile_inode, &ump->ifile_node); 791 1.1 reinoud if (error) { 792 1.1 reinoud printf("mount_nilfs: can't read ifile node\n"); 793 1.1 reinoud return EINVAL; 794 1.1 reinoud } 795 1.1 reinoud 796 1.1 reinoud /* get root node? */ 797 1.1 reinoud 798 1.1 reinoud return 0; 799 1.1 reinoud } 800 1.1 reinoud 801 1.1 reinoud 802 1.1 reinoud static int 803 1.1 reinoud nilfs_stop_writing(struct nilfs_mount *ump) 804 1.1 reinoud { 805 1.1 reinoud /* readonly mounts won't write */ 806 1.1 reinoud if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) 807 1.1 reinoud return 0; 808 1.1 reinoud 809 1.1 reinoud DPRINTF(CALL, ("nilfs_stop_writing called for RW mount\n")); 810 1.1 reinoud 811 1.1 reinoud /* TODO writeout super_block? */ 812 1.1 reinoud /* XXX no support for writing yet anyway */ 813 1.1 reinoud return 0; 814 1.1 reinoud } 815 1.1 reinoud 816 1.1 reinoud 817 1.1 reinoud /* --------------------------------------------------------------------- */ 818 1.1 reinoud 819 1.1 reinoud 820 1.1 reinoud 821 1.1 reinoud #define MPFREE(a, lst) \ 822 1.1 reinoud if ((a)) free((a), lst); 823 1.1 reinoud static void 824 1.1 reinoud free_nilfs_mountinfo(struct mount *mp) 825 1.1 reinoud { 826 1.1 reinoud struct nilfs_mount *ump = VFSTONILFS(mp); 827 1.1 reinoud 828 1.1 reinoud if (ump == NULL) 829 1.1 reinoud return; 830 1.1 reinoud 831 1.1 reinoud MPFREE(ump, M_NILFSMNT); 832 1.1 reinoud } 833 1.1 reinoud #undef MPFREE 834 1.1 reinoud 835 1.1 reinoud int 836 1.1 reinoud nilfs_mount(struct mount *mp, const char *path, 837 1.1 reinoud void *data, size_t *data_len) 838 1.1 reinoud { 839 1.1 reinoud struct nilfs_args *args = data; 840 1.1 reinoud struct nilfs_device *nilfsdev; 841 1.1 reinoud struct nilfs_mount *ump; 842 1.1 reinoud struct vnode *devvp; 843 1.18 hannken int error; 844 1.1 reinoud 845 1.1 reinoud DPRINTF(VFSCALL, ("nilfs_mount called\n")); 846 1.1 reinoud 847 1.16 maxv if (args == NULL) 848 1.16 maxv return EINVAL; 849 1.1 reinoud if (*data_len < sizeof *args) 850 1.1 reinoud return EINVAL; 851 1.1 reinoud 852 1.1 reinoud if (mp->mnt_flag & MNT_GETARGS) { 853 1.1 reinoud /* request for the mount arguments */ 854 1.1 reinoud ump = VFSTONILFS(mp); 855 1.1 reinoud if (ump == NULL) 856 1.1 reinoud return EINVAL; 857 1.1 reinoud *args = ump->mount_args; 858 1.1 reinoud *data_len = sizeof *args; 859 1.1 reinoud return 0; 860 1.1 reinoud } 861 1.1 reinoud 862 1.1 reinoud /* check/translate struct version */ 863 1.1 reinoud if (args->version != 1) { 864 1.1 reinoud printf("mount_nilfs: unrecognized argument structure version\n"); 865 1.1 reinoud return EINVAL; 866 1.1 reinoud } 867 1.1 reinoud /* TODO sanity checking other mount arguments */ 868 1.1 reinoud 869 1.1 reinoud /* handle request for updating mount parameters */ 870 1.1 reinoud if (mp->mnt_flag & MNT_UPDATE) { 871 1.1 reinoud /* TODO can't update my mountpoint yet */ 872 1.1 reinoud return EOPNOTSUPP; 873 1.1 reinoud } 874 1.1 reinoud 875 1.1 reinoud /* lookup name to get its vnode */ 876 1.1 reinoud error = namei_simple_user(args->fspec, NSM_FOLLOW_NOEMULROOT, &devvp); 877 1.1 reinoud if (error) 878 1.1 reinoud return error; 879 1.1 reinoud 880 1.1 reinoud #ifdef DEBUG 881 1.1 reinoud if (nilfs_verbose & NILFS_DEBUG_VOLUMES) 882 1.1 reinoud vprint("NILFS mount, trying to mount \n", devvp); 883 1.1 reinoud #endif 884 1.1 reinoud 885 1.1 reinoud error = nilfs_mount_device(devvp, mp, args, &nilfsdev); 886 1.20 maxv if (error) 887 1.1 reinoud return error; 888 1.1 reinoud 889 1.1 reinoud /* 890 1.1 reinoud * Create a nilfs_mount on the specified checkpoint. Note that only 891 1.1 reinoud * ONE RW mount point can exist and it needs to have the highest 892 1.1 reinoud * checkpoint nr. If mounting RW and its not on the last checkpoint we 893 1.1 reinoud * need to invalidate all checkpoints that follow!!! This is an 894 1.1 reinoud * advanced option. 895 1.1 reinoud */ 896 1.1 reinoud 897 1.1 reinoud /* setup basic mountpoint structure */ 898 1.1 reinoud mp->mnt_data = NULL; 899 1.1 reinoud mp->mnt_stat.f_fsidx.__fsid_val[0] = (uint32_t) devvp->v_rdev; 900 1.1 reinoud mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_NILFS); 901 1.1 reinoud mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 902 1.1 reinoud mp->mnt_stat.f_namemax = NILFS_NAME_LEN; 903 1.1 reinoud mp->mnt_flag |= MNT_LOCAL; 904 1.1 reinoud 905 1.1 reinoud /* XXX can't enable MPSAFE yet since genfs barfs on bad CV */ 906 1.1 reinoud // mp->mnt_iflag |= IMNT_MPSAFE; 907 1.1 reinoud 908 1.1 reinoud /* set our dev and fs units */ 909 1.1 reinoud mp->mnt_dev_bshift = nilfs_rw32(nilfsdev->super.s_log_block_size) + 10; 910 1.1 reinoud mp->mnt_fs_bshift = mp->mnt_dev_bshift; 911 1.1 reinoud 912 1.1 reinoud /* allocate nilfs part of mount structure; malloc always succeeds */ 913 1.1 reinoud ump = malloc(sizeof(struct nilfs_mount), M_NILFSMNT, M_WAITOK | M_ZERO); 914 1.1 reinoud 915 1.1 reinoud /* set up linkage */ 916 1.1 reinoud mp->mnt_data = ump; 917 1.1 reinoud ump->vfs_mountp = mp; 918 1.1 reinoud ump->nilfsdev = nilfsdev; 919 1.1 reinoud 920 1.1 reinoud #if 0 921 1.1 reinoud #ifndef NILFS_READWRITE 922 1.1 reinoud /* force read-only for now */ 923 1.1 reinoud if ((mp->mnt_flag & MNT_RDONLY) == 0) { 924 1.1 reinoud printf( "Enable kernel/module option NILFS_READWRITE for " 925 1.1 reinoud "writing, downgrading access to read-only\n"); 926 1.1 reinoud mp->mnt_flag |= MNT_RDONLY; 927 1.1 reinoud } 928 1.1 reinoud #endif 929 1.1 reinoud #endif 930 1.1 reinoud 931 1.1 reinoud /* DONT register our nilfs mountpoint on our vfs mountpoint */ 932 1.11 hannken spec_node_setmountedfs(devvp, NULL); 933 1.1 reinoud #if 0 934 1.11 hannken if (spec_node_getmountedfs(devvp) == NULL) 935 1.11 hannken spec_node_setmountedfs(devvp, mp); 936 1.1 reinoud if ((mp->mnt_flag & MNT_RDONLY) == 0) 937 1.11 hannken spec_node_setmountedfs(devvp, mp); 938 1.1 reinoud #endif 939 1.1 reinoud 940 1.1 reinoud /* add our mountpoint */ 941 1.1 reinoud STAILQ_INSERT_TAIL(&nilfsdev->mounts, ump, next_mount); 942 1.1 reinoud 943 1.1 reinoud /* get our selected checkpoint */ 944 1.1 reinoud if (args->cpno == 0) 945 1.1 reinoud args->cpno = nilfsdev->last_cno; 946 1.1 reinoud args->cpno = MIN(args->cpno, nilfsdev->last_cno); 947 1.1 reinoud 948 1.1 reinoud /* setting up other parameters */ 949 1.1 reinoud ump->mount_args = *args; 950 1.1 reinoud error = nilfs_mount_checkpoint(ump); 951 1.1 reinoud if (error) { 952 1.1 reinoud nilfs_unmount(mp, MNT_FORCE); 953 1.1 reinoud return error; 954 1.1 reinoud } 955 1.1 reinoud 956 1.1 reinoud /* set VFS info */ 957 1.1 reinoud error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE, 958 1.1 reinoud mp->mnt_op->vfs_name, mp, curlwp); 959 1.1 reinoud if (error) { 960 1.1 reinoud nilfs_unmount(mp, MNT_FORCE); 961 1.1 reinoud return error; 962 1.1 reinoud } 963 1.1 reinoud 964 1.1 reinoud /* successfully mounted */ 965 1.27 andvar DPRINTF(VOLUMES, ("nilfs_mount() successful\n")); 966 1.1 reinoud 967 1.1 reinoud return 0; 968 1.1 reinoud } 969 1.1 reinoud 970 1.1 reinoud /* --------------------------------------------------------------------- */ 971 1.1 reinoud 972 1.1 reinoud 973 1.1 reinoud /* remove our mountpoint and if its the last reference, remove our device */ 974 1.1 reinoud int 975 1.1 reinoud nilfs_unmount(struct mount *mp, int mntflags) 976 1.1 reinoud { 977 1.1 reinoud struct nilfs_device *nilfsdev; 978 1.1 reinoud struct nilfs_mount *ump; 979 1.1 reinoud int error, flags; 980 1.1 reinoud 981 1.1 reinoud DPRINTF(VFSCALL, ("nilfs_umount called\n")); 982 1.1 reinoud 983 1.1 reinoud ump = VFSTONILFS(mp); 984 1.1 reinoud if (!ump) 985 1.1 reinoud panic("NILFS unmount: empty ump\n"); 986 1.1 reinoud nilfsdev = ump->nilfsdev; 987 1.1 reinoud 988 1.1 reinoud /* 989 1.17 hannken * Flush all nodes associated to this mountpoint. 990 1.1 reinoud */ 991 1.1 reinoud flags = (mntflags & MNT_FORCE) ? FORCECLOSE : 0; 992 1.17 hannken if ((error = vflush(mp, NULLVP, flags)) != 0) 993 1.1 reinoud return error; 994 1.1 reinoud 995 1.1 reinoud /* if we're the write mount, we ought to close the writing session */ 996 1.1 reinoud error = nilfs_stop_writing(ump); 997 1.1 reinoud if (error) 998 1.1 reinoud return error; 999 1.1 reinoud 1000 1.1 reinoud nilfs_dispose_node(&ump->ifile_node); 1001 1.1 reinoud 1002 1.1 reinoud /* remove our mount point */ 1003 1.1 reinoud STAILQ_REMOVE(&nilfsdev->mounts, ump, nilfs_mount, next_mount); 1004 1.1 reinoud free_nilfs_mountinfo(mp); 1005 1.1 reinoud 1006 1.1 reinoud /* free ump struct references */ 1007 1.1 reinoud mp->mnt_data = NULL; 1008 1.1 reinoud mp->mnt_flag &= ~MNT_LOCAL; 1009 1.1 reinoud 1010 1.1 reinoud /* unmount the device itself when we're the last one */ 1011 1.1 reinoud nilfs_unmount_device(nilfsdev); 1012 1.1 reinoud 1013 1.1 reinoud DPRINTF(VOLUMES, ("Fin unmount\n")); 1014 1.1 reinoud return error; 1015 1.1 reinoud } 1016 1.1 reinoud 1017 1.1 reinoud /* --------------------------------------------------------------------- */ 1018 1.1 reinoud 1019 1.1 reinoud int 1020 1.1 reinoud nilfs_start(struct mount *mp, int flags) 1021 1.1 reinoud { 1022 1.1 reinoud /* do we have to do something here? */ 1023 1.1 reinoud return 0; 1024 1.1 reinoud } 1025 1.1 reinoud 1026 1.1 reinoud /* --------------------------------------------------------------------- */ 1027 1.1 reinoud 1028 1.1 reinoud int 1029 1.25 ad nilfs_root(struct mount *mp, int lktype, struct vnode **vpp) 1030 1.1 reinoud { 1031 1.18 hannken uint64_t ino = NILFS_ROOT_INO; 1032 1.1 reinoud int error; 1033 1.1 reinoud 1034 1.1 reinoud DPRINTF(NODE, ("nilfs_root called\n")); 1035 1.1 reinoud 1036 1.18 hannken error = vcache_get(mp, &ino, sizeof(ino), vpp); 1037 1.17 hannken if (error == 0) { 1038 1.25 ad error = vn_lock(*vpp, lktype); 1039 1.17 hannken if (error) { 1040 1.17 hannken vrele(*vpp); 1041 1.17 hannken *vpp = NULL; 1042 1.17 hannken return error; 1043 1.17 hannken } 1044 1.1 reinoud } 1045 1.17 hannken KASSERT(error != 0 || ((*vpp)->v_vflag & VV_ROOT)); 1046 1.1 reinoud 1047 1.1 reinoud DPRINTF(NODE, ("nilfs_root finished\n")); 1048 1.1 reinoud return error; 1049 1.1 reinoud } 1050 1.1 reinoud 1051 1.1 reinoud /* --------------------------------------------------------------------- */ 1052 1.1 reinoud 1053 1.1 reinoud int 1054 1.1 reinoud nilfs_statvfs(struct mount *mp, struct statvfs *sbp) 1055 1.1 reinoud { 1056 1.1 reinoud struct nilfs_mount *ump = VFSTONILFS(mp); 1057 1.1 reinoud uint32_t blocksize; 1058 1.1 reinoud 1059 1.1 reinoud DPRINTF(VFSCALL, ("nilfs_statvfs called\n")); 1060 1.1 reinoud 1061 1.1 reinoud blocksize = ump->nilfsdev->blocksize; 1062 1.1 reinoud sbp->f_flag = mp->mnt_flag; 1063 1.1 reinoud sbp->f_bsize = blocksize; 1064 1.1 reinoud sbp->f_frsize = blocksize; 1065 1.1 reinoud sbp->f_iosize = blocksize; 1066 1.1 reinoud 1067 1.1 reinoud copy_statvfs_info(sbp, mp); 1068 1.1 reinoud return 0; 1069 1.1 reinoud } 1070 1.1 reinoud 1071 1.1 reinoud /* --------------------------------------------------------------------- */ 1072 1.1 reinoud 1073 1.1 reinoud int 1074 1.1 reinoud nilfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) 1075 1.1 reinoud { 1076 1.1 reinoud // struct nilfs_mount *ump = VFSTONILFS(mp); 1077 1.1 reinoud 1078 1.1 reinoud DPRINTF(VFSCALL, ("nilfs_sync called\n")); 1079 1.1 reinoud /* if called when mounted readonly, just ignore */ 1080 1.1 reinoud if (mp->mnt_flag & MNT_RDONLY) 1081 1.1 reinoud return 0; 1082 1.1 reinoud 1083 1.1 reinoud DPRINTF(VFSCALL, ("end of nilfs_sync()\n")); 1084 1.1 reinoud 1085 1.1 reinoud return 0; 1086 1.1 reinoud } 1087 1.1 reinoud 1088 1.1 reinoud /* --------------------------------------------------------------------- */ 1089 1.1 reinoud 1090 1.1 reinoud /* 1091 1.1 reinoud * Get vnode for the file system type specific file id ino for the fs. Its 1092 1.1 reinoud * used for reference to files by unique ID and for NFSv3. 1093 1.1 reinoud * (optional) TODO lookup why some sources state NFSv3 1094 1.1 reinoud */ 1095 1.1 reinoud int 1096 1.25 ad nilfs_vget(struct mount *mp, ino_t ino, int lktype, 1097 1.1 reinoud struct vnode **vpp) 1098 1.1 reinoud { 1099 1.1 reinoud DPRINTF(NOTIMPL, ("nilfs_vget called\n")); 1100 1.1 reinoud return EOPNOTSUPP; 1101 1.1 reinoud } 1102 1.1 reinoud 1103 1.1 reinoud /* --------------------------------------------------------------------- */ 1104 1.1 reinoud 1105 1.1 reinoud /* 1106 1.18 hannken * Read an inode from disk and initialize this vnode / inode pair. 1107 1.18 hannken * Caller assures no other thread will try to load this inode. 1108 1.18 hannken */ 1109 1.18 hannken int 1110 1.18 hannken nilfs_loadvnode(struct mount *mp, struct vnode *vp, 1111 1.18 hannken const void *key, size_t key_len, const void **new_key) 1112 1.18 hannken { 1113 1.18 hannken uint64_t ino; 1114 1.18 hannken struct nilfs_device *nilfsdev; 1115 1.18 hannken struct nilfs_inode inode, *entry; 1116 1.18 hannken struct nilfs_node *node; 1117 1.18 hannken struct nilfs_mount *ump; 1118 1.18 hannken struct buf *bp; 1119 1.18 hannken uint64_t ivblocknr; 1120 1.18 hannken uint32_t entry_in_block; 1121 1.18 hannken int error; 1122 1.18 hannken extern int (**nilfs_vnodeop_p)(void *); 1123 1.18 hannken 1124 1.18 hannken KASSERT(key_len == sizeof(ino)); 1125 1.18 hannken memcpy(&ino, key, key_len); 1126 1.18 hannken 1127 1.18 hannken ump = VFSTONILFS(mp); 1128 1.18 hannken 1129 1.18 hannken /* create new inode; XXX check could be handier */ 1130 1.18 hannken if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) { 1131 1.18 hannken printf("nilfs_get_node: system ino %"PRIu64" not in mount " 1132 1.18 hannken "point!\n", ino); 1133 1.18 hannken return ENOENT; 1134 1.18 hannken } 1135 1.18 hannken 1136 1.18 hannken /* lookup inode in the ifile */ 1137 1.18 hannken DPRINTF(NODE, ("lookup ino %"PRIu64"\n", ino)); 1138 1.18 hannken 1139 1.18 hannken /* lookup inode structure in mountpoints ifile */ 1140 1.18 hannken nilfsdev = ump->nilfsdev; 1141 1.18 hannken nilfs_mdt_trans(&nilfsdev->ifile_mdt, ino, &ivblocknr, &entry_in_block); 1142 1.18 hannken 1143 1.21 maxv error = nilfs_bread(ump->ifile_node, ivblocknr, 0, &bp); 1144 1.18 hannken if (error) 1145 1.18 hannken return ENOENT; 1146 1.18 hannken 1147 1.18 hannken /* get inode entry */ 1148 1.18 hannken entry = (struct nilfs_inode *) bp->b_data + entry_in_block; 1149 1.18 hannken inode = *entry; 1150 1.18 hannken brelse(bp, BC_AGE); 1151 1.18 hannken 1152 1.18 hannken /* get node */ 1153 1.18 hannken error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, &node); 1154 1.18 hannken if (error) 1155 1.18 hannken return error; 1156 1.18 hannken 1157 1.18 hannken vp->v_type = IFTOVT(inode.i_mode); 1158 1.18 hannken switch (vp->v_type) { 1159 1.18 hannken case VREG: 1160 1.18 hannken case VDIR: 1161 1.18 hannken case VLNK: 1162 1.18 hannken break; 1163 1.18 hannken /* other types not yet supported. */ 1164 1.18 hannken default: 1165 1.18 hannken vp->v_type = VNON; 1166 1.18 hannken nilfs_dispose_node(&node); 1167 1.18 hannken return ENXIO; 1168 1.18 hannken } 1169 1.18 hannken 1170 1.18 hannken vp->v_tag = VT_NILFS; 1171 1.18 hannken vp->v_op = nilfs_vnodeop_p; 1172 1.18 hannken vp->v_data = node; 1173 1.18 hannken node->vnode = vp; 1174 1.18 hannken 1175 1.18 hannken /* initialise genfs */ 1176 1.18 hannken genfs_node_init(vp, &nilfs_genfsops); 1177 1.18 hannken 1178 1.18 hannken /* check if we're fetching the root */ 1179 1.18 hannken if (ino == NILFS_ROOT_INO) 1180 1.18 hannken vp->v_vflag |= VV_ROOT; 1181 1.18 hannken 1182 1.18 hannken uvm_vnp_setsize(vp, nilfs_rw64(inode.i_size)); 1183 1.18 hannken *new_key = &node->ino; 1184 1.18 hannken 1185 1.18 hannken return 0; 1186 1.18 hannken 1187 1.18 hannken } 1188 1.18 hannken 1189 1.18 hannken /* --------------------------------------------------------------------- */ 1190 1.18 hannken 1191 1.18 hannken /* 1192 1.1 reinoud * Lookup vnode for file handle specified 1193 1.1 reinoud */ 1194 1.1 reinoud int 1195 1.25 ad nilfs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, 1196 1.1 reinoud struct vnode **vpp) 1197 1.1 reinoud { 1198 1.1 reinoud DPRINTF(NOTIMPL, ("nilfs_fhtovp called\n")); 1199 1.1 reinoud return EOPNOTSUPP; 1200 1.1 reinoud } 1201 1.1 reinoud 1202 1.1 reinoud /* --------------------------------------------------------------------- */ 1203 1.1 reinoud 1204 1.1 reinoud /* 1205 1.1 reinoud * Create an unique file handle. Its structure is opaque and won't be used by 1206 1.1 reinoud * other subsystems. It should uniquely identify the file in the filingsystem 1207 1.1 reinoud * and enough information to know if a file has been removed and/or resources 1208 1.1 reinoud * have been recycled. 1209 1.1 reinoud */ 1210 1.1 reinoud int 1211 1.1 reinoud nilfs_vptofh(struct vnode *vp, struct fid *fid, 1212 1.1 reinoud size_t *fh_size) 1213 1.1 reinoud { 1214 1.1 reinoud DPRINTF(NOTIMPL, ("nilfs_vptofh called\n")); 1215 1.1 reinoud return EOPNOTSUPP; 1216 1.1 reinoud } 1217 1.1 reinoud 1218 1.1 reinoud /* --------------------------------------------------------------------- */ 1219 1.1 reinoud 1220 1.1 reinoud /* 1221 1.1 reinoud * Create a file system snapshot at the specified timestamp. 1222 1.1 reinoud */ 1223 1.1 reinoud int 1224 1.1 reinoud nilfs_snapshot(struct mount *mp, struct vnode *vp, 1225 1.1 reinoud struct timespec *tm) 1226 1.1 reinoud { 1227 1.1 reinoud DPRINTF(NOTIMPL, ("nilfs_snapshot called\n")); 1228 1.1 reinoud return EOPNOTSUPP; 1229 1.1 reinoud } 1230 1.1 reinoud 1231 1.1 reinoud /* --------------------------------------------------------------------- */ 1232