1 /* $NetBSD: lfs_vnops.c,v 1.355 2026/09/08 22:30:44 perseant Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant (at) hhhh.org>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 1986, 1989, 1991, 1993, 1995 33 * The Regents of the University of California. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)lfs_vnops.c 8.13 (Berkeley) 6/10/95 60 */ 61 62 /* from NetBSD: ufs_vnops.c,v 1.232 2016/05/19 18:32:03 riastradh Exp */ 63 /*- 64 * Copyright (c) 2008 The NetBSD Foundation, Inc. 65 * All rights reserved. 66 * 67 * This code is derived from software contributed to The NetBSD Foundation 68 * by Wasabi Systems, Inc. 69 * 70 * Redistribution and use in source and binary forms, with or without 71 * modification, are permitted provided that the following conditions 72 * are met: 73 * 1. Redistributions of source code must retain the above copyright 74 * notice, this list of conditions and the following disclaimer. 75 * 2. Redistributions in binary form must reproduce the above copyright 76 * notice, this list of conditions and the following disclaimer in the 77 * documentation and/or other materials provided with the distribution. 78 * 79 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 80 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 81 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 82 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 83 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 84 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 85 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 86 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 87 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 88 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 89 * POSSIBILITY OF SUCH DAMAGE. 90 */ 91 /* 92 * Copyright (c) 1982, 1986, 1989, 1993, 1995 93 * The Regents of the University of California. All rights reserved. 94 * (c) UNIX System Laboratories, Inc. 95 * All or some portions of this file are derived from material licensed 96 * to the University of California by American Telephone and Telegraph 97 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 98 * the permission of UNIX System Laboratories, Inc. 99 * 100 * Redistribution and use in source and binary forms, with or without 101 * modification, are permitted provided that the following conditions 102 * are met: 103 * 1. Redistributions of source code must retain the above copyright 104 * notice, this list of conditions and the following disclaimer. 105 * 2. Redistributions in binary form must reproduce the above copyright 106 * notice, this list of conditions and the following disclaimer in the 107 * documentation and/or other materials provided with the distribution. 108 * 3. Neither the name of the University nor the names of its contributors 109 * may be used to endorse or promote products derived from this software 110 * without specific prior written permission. 111 * 112 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 113 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 114 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 115 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 116 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 117 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 118 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 119 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 120 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 121 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 122 * SUCH DAMAGE. 123 * 124 * @(#)ufs_vnops.c 8.28 (Berkeley) 7/31/95 125 */ 126 127 #include <sys/cdefs.h> 128 __KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.355 2026/09/08 22:30:44 perseant Exp $"); 129 130 #ifdef _KERNEL_OPT 131 #include "opt_compat_netbsd.h" 132 #include "opt_uvm_page_trkown.h" 133 #endif 134 135 #include <sys/param.h> 136 #include <sys/systm.h> 137 #include <sys/namei.h> 138 #include <sys/resourcevar.h> 139 #include <sys/kernel.h> 140 #include <sys/file.h> 141 #include <sys/stat.h> 142 #include <sys/buf.h> 143 #include <sys/proc.h> 144 #include <sys/mount.h> 145 #include <sys/vnode.h> 146 #include <sys/pool.h> 147 #include <sys/signalvar.h> 148 #include <sys/kauth.h> 149 #include <sys/syslog.h> 150 151 #include <miscfs/fifofs/fifo.h> 152 #include <miscfs/genfs/genfs.h> 153 #include <miscfs/specfs/specdev.h> 154 155 #include <ufs/lfs/ulfs_inode.h> 156 #include <ufs/lfs/ulfsmount.h> 157 #include <ufs/lfs/ulfs_bswap.h> 158 #include <ufs/lfs/ulfs_extern.h> 159 160 #include <uvm/uvm_extern.h> 161 162 #include <ufs/lfs/lfs.h> 163 #include <ufs/lfs/lfs_accessors.h> 164 #include <ufs/lfs/lfs_kernel.h> 165 #include <ufs/lfs/lfs_extern.h> 166 167 extern kcondvar_t lfs_writerd_cv; 168 int lfs_ignore_lazy_sync = 1; 169 170 static int lfs_openextattr(void *v); 171 static int lfs_closeextattr(void *v); 172 static int lfs_getextattr(void *v); 173 static int lfs_setextattr(void *v); 174 static int lfs_listextattr(void *v); 175 static int lfs_deleteextattr(void *v); 176 177 static int lfs_makeinode(struct vattr *vap, struct vnode *, 178 const struct ulfs_lookup_results *, 179 struct vnode **, struct componentname *); 180 static int lfs_filestats(struct lfs *, ino_t, struct lfs_filestats *); 181 182 /* Global vfs data structures for lfs. */ 183 int (**lfs_vnodeop_p)(void *); 184 const struct vnodeopv_entry_desc lfs_vnodeop_entries[] = { 185 { &vop_default_desc, vn_default_error }, 186 { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ 187 { &vop_lookup_desc, ulfs_lookup }, /* lookup */ 188 { &vop_create_desc, lfs_create }, /* create */ 189 { &vop_whiteout_desc, ulfs_whiteout }, /* whiteout */ 190 { &vop_mknod_desc, lfs_mknod }, /* mknod */ 191 { &vop_open_desc, ulfs_open }, /* open */ 192 { &vop_close_desc, lfs_close }, /* close */ 193 { &vop_access_desc, ulfs_access }, /* access */ 194 { &vop_accessx_desc, genfs_accessx }, /* accessx */ 195 { &vop_getattr_desc, lfs_getattr }, /* getattr */ 196 { &vop_setattr_desc, lfs_setattr }, /* setattr */ 197 { &vop_read_desc, lfs_read }, /* read */ 198 { &vop_write_desc, lfs_write }, /* write */ 199 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 200 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 201 { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ 202 { &vop_fcntl_desc, lfs_fcntl }, /* fcntl */ 203 { &vop_poll_desc, genfs_poll }, /* poll */ 204 { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */ 205 { &vop_revoke_desc, genfs_revoke }, /* revoke */ 206 { &vop_mmap_desc, lfs_mmap }, /* mmap */ 207 { &vop_fsync_desc, lfs_fsync }, /* fsync */ 208 { &vop_seek_desc, genfs_seek }, /* seek */ 209 { &vop_remove_desc, lfs_remove }, /* remove */ 210 { &vop_link_desc, lfs_link }, /* link */ 211 { &vop_rename_desc, lfs_rename }, /* rename */ 212 { &vop_mkdir_desc, lfs_mkdir }, /* mkdir */ 213 { &vop_rmdir_desc, lfs_rmdir }, /* rmdir */ 214 { &vop_symlink_desc, lfs_symlink }, /* symlink */ 215 { &vop_readdir_desc, ulfs_readdir }, /* readdir */ 216 { &vop_readlink_desc, ulfs_readlink }, /* readlink */ 217 { &vop_abortop_desc, genfs_abortop }, /* abortop */ 218 { &vop_inactive_desc, lfs_inactive }, /* inactive */ 219 { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */ 220 { &vop_lock_desc, genfs_lock }, /* lock */ 221 { &vop_unlock_desc, genfs_unlock }, /* unlock */ 222 { &vop_bmap_desc, ulfs_bmap }, /* bmap */ 223 { &vop_strategy_desc, lfs_strategy }, /* strategy */ 224 { &vop_print_desc, ulfs_print }, /* print */ 225 { &vop_islocked_desc, genfs_islocked }, /* islocked */ 226 { &vop_pathconf_desc, ulfs_pathconf }, /* pathconf */ 227 { &vop_advlock_desc, ulfs_advlock }, /* advlock */ 228 { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 229 { &vop_getpages_desc, lfs_getpages }, /* getpages */ 230 { &vop_putpages_desc, lfs_putpages }, /* putpages */ 231 { &vop_openextattr_desc, lfs_openextattr }, /* openextattr */ 232 { &vop_closeextattr_desc, lfs_closeextattr }, /* closeextattr */ 233 { &vop_getextattr_desc, lfs_getextattr }, /* getextattr */ 234 { &vop_setextattr_desc, lfs_setextattr }, /* setextattr */ 235 { &vop_listextattr_desc, lfs_listextattr }, /* listextattr */ 236 { &vop_deleteextattr_desc, lfs_deleteextattr }, /* deleteextattr */ 237 { NULL, NULL } 238 }; 239 const struct vnodeopv_desc lfs_vnodeop_opv_desc = 240 { &lfs_vnodeop_p, lfs_vnodeop_entries }; 241 242 int (**lfs_specop_p)(void *); 243 const struct vnodeopv_entry_desc lfs_specop_entries[] = { 244 { &vop_default_desc, vn_default_error }, 245 GENFS_SPECOP_ENTRIES, 246 { &vop_close_desc, lfsspec_close }, /* close */ 247 { &vop_access_desc, ulfs_access }, /* access */ 248 { &vop_accessx_desc, genfs_accessx }, /* accessx */ 249 { &vop_getattr_desc, lfs_getattr }, /* getattr */ 250 { &vop_setattr_desc, lfs_setattr }, /* setattr */ 251 { &vop_read_desc, ulfsspec_read }, /* read */ 252 { &vop_write_desc, ulfsspec_write }, /* write */ 253 { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 254 { &vop_fsync_desc, spec_fsync }, /* fsync */ 255 { &vop_inactive_desc, lfs_inactive }, /* inactive */ 256 { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */ 257 { &vop_lock_desc, genfs_lock }, /* lock */ 258 { &vop_unlock_desc, genfs_unlock }, /* unlock */ 259 { &vop_print_desc, ulfs_print }, /* print */ 260 { &vop_islocked_desc, genfs_islocked }, /* islocked */ 261 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 262 { &vop_openextattr_desc, lfs_openextattr }, /* openextattr */ 263 { &vop_closeextattr_desc, lfs_closeextattr }, /* closeextattr */ 264 { &vop_getextattr_desc, lfs_getextattr }, /* getextattr */ 265 { &vop_setextattr_desc, lfs_setextattr }, /* setextattr */ 266 { &vop_listextattr_desc, lfs_listextattr }, /* listextattr */ 267 { &vop_deleteextattr_desc, lfs_deleteextattr }, /* deleteextattr */ 268 { NULL, NULL } 269 }; 270 const struct vnodeopv_desc lfs_specop_opv_desc = 271 { &lfs_specop_p, lfs_specop_entries }; 272 273 int (**lfs_fifoop_p)(void *); 274 const struct vnodeopv_entry_desc lfs_fifoop_entries[] = { 275 { &vop_default_desc, vn_default_error }, 276 GENFS_FIFOOP_ENTRIES, 277 { &vop_close_desc, lfsfifo_close }, /* close */ 278 { &vop_access_desc, ulfs_access }, /* access */ 279 { &vop_accessx_desc, genfs_accessx }, /* accessx */ 280 { &vop_getattr_desc, lfs_getattr }, /* getattr */ 281 { &vop_setattr_desc, lfs_setattr }, /* setattr */ 282 { &vop_read_desc, ulfsfifo_read }, /* read */ 283 { &vop_write_desc, ulfsfifo_write }, /* write */ 284 { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 285 { &vop_fsync_desc, vn_fifo_bypass }, /* fsync */ 286 { &vop_inactive_desc, lfs_inactive }, /* inactive */ 287 { &vop_reclaim_desc, lfs_reclaim }, /* reclaim */ 288 { &vop_lock_desc, genfs_lock }, /* lock */ 289 { &vop_unlock_desc, genfs_unlock }, /* unlock */ 290 { &vop_strategy_desc, vn_fifo_bypass }, /* strategy */ 291 { &vop_print_desc, ulfs_print }, /* print */ 292 { &vop_islocked_desc, genfs_islocked }, /* islocked */ 293 { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */ 294 { &vop_openextattr_desc, lfs_openextattr }, /* openextattr */ 295 { &vop_closeextattr_desc, lfs_closeextattr }, /* closeextattr */ 296 { &vop_getextattr_desc, lfs_getextattr }, /* getextattr */ 297 { &vop_setextattr_desc, lfs_setextattr }, /* setextattr */ 298 { &vop_listextattr_desc, lfs_listextattr }, /* listextattr */ 299 { &vop_deleteextattr_desc, lfs_deleteextattr }, /* deleteextattr */ 300 { NULL, NULL } 301 }; 302 const struct vnodeopv_desc lfs_fifoop_opv_desc = 303 { &lfs_fifoop_p, lfs_fifoop_entries }; 304 305 #include <ufs/lfs/ulfs_readwrite.c> 306 307 /* 308 * Allocate a new inode. 309 */ 310 static int 311 lfs_makeinode(struct vattr *vap, struct vnode *dvp, 312 const struct ulfs_lookup_results *ulr, 313 struct vnode **vpp, struct componentname *cnp) 314 { 315 struct inode *ip; 316 struct vnode *tvp; 317 int error; 318 319 error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, &tvp); 320 if (error) 321 return error; 322 error = vn_lock(tvp, LK_EXCLUSIVE); 323 if (error) { 324 vrele(tvp); 325 return error; 326 } 327 MARK_VNODE(tvp); 328 *vpp = tvp; 329 ip = VTOI(tvp); 330 ip->i_state |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 331 ip->i_nlink = 1; 332 DIP_ASSIGN(ip, nlink, 1); 333 334 /* Authorize setting SGID if needed. */ 335 if (ip->i_mode & ISGID) { 336 error = kauth_authorize_vnode(cnp->cn_cred, 337 KAUTH_VNODE_WRITE_SECURITY, 338 tvp, NULL, genfs_can_chmod(tvp, cnp->cn_cred, ip->i_uid, 339 ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode))); 340 if (error) { 341 ip->i_mode &= ~ISGID; 342 DIP_ASSIGN(ip, mode, ip->i_mode); 343 } 344 } 345 346 if (cnp->cn_flags & ISWHITEOUT) { 347 ip->i_flags |= UF_OPAQUE; 348 DIP_ASSIGN(ip, flags, ip->i_flags); 349 } 350 351 /* 352 * Make sure inode goes to disk before directory entry. 353 */ 354 if ((error = lfs_update(tvp, NULL, NULL, UPDATE_DIROP)) != 0) 355 goto bad; 356 error = ulfs_direnter(dvp, ulr, tvp, 357 cnp, ip->i_number, LFS_IFTODT(ip->i_mode), NULL); 358 if (error) 359 goto bad; 360 *vpp = tvp; 361 cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); 362 KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE); 363 return (0); 364 365 bad: 366 /* 367 * Write error occurred trying to update the inode 368 * or the directory so must deallocate the inode. 369 */ 370 ip->i_nlink = 0; 371 DIP_ASSIGN(ip, nlink, 0); 372 ip->i_state |= IN_CHANGE; 373 /* If IN_ADIROP, account for it */ 374 UNMARK_VNODE(tvp); 375 vput(tvp); 376 return (error); 377 } 378 379 /* 380 * Synch an open file. 381 */ 382 /* ARGSUSED */ 383 int 384 lfs_fsync(void *v) 385 { 386 struct vop_fsync_args /* { 387 struct vnode *a_vp; 388 kauth_cred_t a_cred; 389 int a_flags; 390 off_t offlo; 391 off_t offhi; 392 } */ *ap = v; 393 struct vnode *vp = ap->a_vp; 394 int wait; 395 struct inode *ip = VTOI(vp); 396 struct lfs *fs = ip->i_lfs; 397 int error = 0; 398 399 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 400 401 /* If we're mounted read-only, don't try to sync. */ 402 if (fs->lfs_ronly) 403 goto out; 404 405 /* If a removed vnode is being cleaned, no need to sync here. */ 406 if ((ap->a_flags & FSYNC_RECLAIM) != 0 && ip->i_mode == 0) 407 goto out; 408 409 /* 410 * Trickle sync simply adds this vnode to the pager list, as if 411 * the pagedaemon had requested a pageout. 412 */ 413 if (ap->a_flags & FSYNC_LAZY) { 414 if (lfs_ignore_lazy_sync == 0) { 415 mutex_enter(&lfs_lock); 416 if (!(ip->i_state & IN_PAGING)) { 417 ip->i_state |= IN_PAGING; 418 TAILQ_INSERT_TAIL(&fs->lfs_pchainhd, ip, 419 i_lfs_pchain); 420 } 421 cv_broadcast(&lfs_writerd_cv); 422 mutex_exit(&lfs_lock); 423 } 424 goto out; 425 } 426 427 KASSERT(!(ap->a_flags & FSYNC_RECLAIM && ip->i_state & IN_CLEANING)); 428 429 wait = (ap->a_flags & FSYNC_WAIT); 430 do { 431 rw_enter(vp->v_uobj.vmobjlock, RW_WRITER); 432 error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo), 433 round_page(ap->a_offhi), 434 PGO_CLEANIT | (wait ? PGO_SYNCIO : 0)); 435 if (error == EAGAIN) { 436 mutex_enter(&lfs_lock); 437 mtsleep(&fs->lfs_availsleep, PCATCH | PUSER, 438 "lfs_fsync", hz / 100 + 1, &lfs_lock); 439 mutex_exit(&lfs_lock); 440 } 441 } while (error == EAGAIN); 442 if (error) 443 goto out; 444 445 if ((ap->a_flags & FSYNC_DATAONLY) == 0 446 && (ip->i_flags & IN_MODIFIED)) 447 error = lfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); 448 449 if (error == 0 && ap->a_flags & FSYNC_CACHE) { 450 int l = 0; 451 error = VOP_IOCTL(ip->i_devvp, DIOCCACHESYNC, &l, FWRITE, 452 curlwp->l_cred); 453 } 454 if (wait && !VPISEMPTY(vp)) 455 LFS_SET_UINO(ip, IN_MODIFIED); 456 457 out: 458 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 459 return error; 460 } 461 462 /* 463 * Take IN_ADIROP off, then call ulfs_inactive. 464 */ 465 int 466 lfs_inactive(void *v) 467 { 468 struct vop_inactive_v2_args /* { 469 struct vnode *a_vp; 470 bool *a_recycle; 471 } */ *ap = v; 472 struct inode *ip; 473 474 ip = VTOI(ap->a_vp); 475 KASSERT(VOP_ISLOCKED(ap->a_vp) == LK_EXCLUSIVE); 476 KASSERT(!(ip->i_state & IN_CLEANING)); 477 478 UNMARK_VNODE(ap->a_vp); 479 480 /* 481 * The Ifile is only ever inactivated on unmount. 482 * Streamline this process by not giving it more dirty blocks. 483 */ 484 if (ip->i_number == LFS_IFILE_INUM) { 485 mutex_enter(&lfs_lock); 486 LFS_CLR_UINO(ip, IN_ALLMOD); 487 mutex_exit(&lfs_lock); 488 return 0; 489 } 490 491 #ifdef DEBUG 492 /* 493 * This might happen on unmount. 494 * XXX If it happens at any other time, it should be a panic. 495 */ 496 if (ap->a_vp->v_uflag & VU_DIROP) { 497 printf("lfs_inactive: inactivating VU_DIROP? ino = %llu\n", 498 (unsigned long long) ip->i_number); 499 } 500 #endif /* DIAGNOSTIC */ 501 502 return ulfs_inactive(v); 503 } 504 505 int 506 lfs_set_dirop(struct vnode *dvp, struct vnode *vp) 507 { 508 struct lfs *fs; 509 int error; 510 511 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 512 KASSERT(vp == NULL || VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 513 514 fs = VTOI(dvp)->i_lfs; 515 516 ASSERT_NO_SEGLOCK(fs); 517 /* 518 * LFS_NRESERVE calculates direct and indirect blocks as well 519 * as an inode block; an overestimate in most cases. 520 */ 521 if ((error = lfs_reserve(fs, dvp, vp, LFS_NRESERVE(fs))) != 0) 522 return (error); 523 524 restart: 525 mutex_enter(&lfs_lock); 526 if (fs->lfs_dirops == 0) { 527 mutex_exit(&lfs_lock); 528 lfs_check(dvp, LFS_UNUSED_LBN, 0); 529 mutex_enter(&lfs_lock); 530 } 531 while (fs->lfs_writer) { 532 error = cv_wait_sig(&fs->lfs_diropscv, &lfs_lock); 533 if (error == EINTR) { 534 mutex_exit(&lfs_lock); 535 goto unreserve; 536 } 537 } 538 if (lfs_dirvcount > LFS_MAX_DIROP && fs->lfs_dirops == 0) { 539 cv_broadcast(&lfs_writerd_cv); 540 mutex_exit(&lfs_lock); 541 preempt(); 542 goto restart; 543 } 544 545 if (lfs_dirvcount > LFS_MAX_DIROP) { 546 DLOG((DLOG_DIROP, "lfs_set_dirop: sleeping with dirops=%d, " 547 "dirvcount=%d\n", fs->lfs_dirops, lfs_dirvcount)); 548 if ((error = mtsleep(&lfs_dirvcount, 549 PCATCH | PUSER | PNORELOCK, "lfs_maxdirop", 0, 550 &lfs_lock)) != 0) { 551 mutex_exit(&lfs_lock); 552 goto unreserve; 553 } 554 mutex_exit(&lfs_lock); 555 goto restart; 556 } 557 558 ++fs->lfs_dirops; 559 /* fs->lfs_doifile = 1; */ /* XXX why? --ks */ 560 mutex_exit(&lfs_lock); 561 562 /* Hold a reference so SET_ENDOP will be happy */ 563 vref(dvp); 564 if (vp) { 565 vref(vp); 566 MARK_VNODE(vp); 567 } 568 569 MARK_VNODE(dvp); 570 return 0; 571 572 unreserve: 573 lfs_reserve(fs, dvp, vp, -LFS_NRESERVE(fs)); 574 return error; 575 } 576 577 /* 578 * Opposite of lfs_set_dirop... mostly. For now at least must call 579 * UNMARK_VNODE(dvp) explicitly first. (XXX: clean that up) 580 */ 581 void 582 lfs_unset_dirop(struct lfs *fs, struct vnode *dvp, const char *str) 583 { 584 mutex_enter(&lfs_lock); 585 --fs->lfs_dirops; 586 if (!fs->lfs_dirops) { 587 if (fs->lfs_nadirop) { 588 panic("lfs_unset_dirop: %s: no dirops but " 589 " nadirop=%d", str, 590 fs->lfs_nadirop); 591 } 592 wakeup(&fs->lfs_writer); 593 mutex_exit(&lfs_lock); 594 lfs_check(dvp, LFS_UNUSED_LBN, 0); 595 } else { 596 mutex_exit(&lfs_lock); 597 } 598 lfs_reserve(fs, dvp, NULL, -LFS_NRESERVE(fs)); 599 } 600 601 void 602 lfs_mark_vnode(struct vnode *vp) 603 { 604 struct inode *ip = VTOI(vp); 605 struct lfs *fs = ip->i_lfs; 606 607 mutex_enter(&lfs_lock); 608 if (!(ip->i_state & IN_ADIROP)) { 609 if (!(vp->v_uflag & VU_DIROP)) { 610 mutex_exit(&lfs_lock); 611 vref(vp); 612 mutex_enter(&lfs_lock); 613 ++lfs_dirvcount; 614 ++fs->lfs_dirvcount; 615 TAILQ_INSERT_TAIL(&fs->lfs_dchainhd, ip, i_lfs_dchain); 616 vp->v_uflag |= VU_DIROP; 617 } 618 ++fs->lfs_nadirop; 619 ip->i_state &= ~IN_CDIROP; 620 ip->i_state |= IN_ADIROP; 621 } else 622 KASSERT(vp->v_uflag & VU_DIROP); 623 mutex_exit(&lfs_lock); 624 } 625 626 void 627 lfs_unmark_vnode(struct vnode *vp) 628 { 629 struct inode *ip = VTOI(vp); 630 631 mutex_enter(&lfs_lock); 632 if (ip && (ip->i_state & IN_ADIROP)) { 633 KASSERT(vp->v_uflag & VU_DIROP); 634 --ip->i_lfs->lfs_nadirop; 635 ip->i_state &= ~IN_ADIROP; 636 } 637 mutex_exit(&lfs_lock); 638 } 639 640 int 641 lfs_symlink(void *v) 642 { 643 struct vop_symlink_v3_args /* { 644 struct vnode *a_dvp; 645 struct vnode **a_vpp; 646 struct componentname *a_cnp; 647 struct vattr *a_vap; 648 char *a_target; 649 } */ *ap = v; 650 struct lfs *fs; 651 struct vnode *dvp, **vpp; 652 struct inode *ip; 653 struct ulfs_lookup_results *ulr; 654 ssize_t len; /* XXX should be size_t */ 655 int error; 656 657 dvp = ap->a_dvp; 658 vpp = ap->a_vpp; 659 660 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 661 KASSERT(vpp != NULL); 662 KASSERT(*vpp == NULL); 663 KASSERT(ap->a_vap->va_type == VLNK); 664 665 /* XXX should handle this material another way */ 666 ulr = &VTOI(ap->a_dvp)->i_crap; 667 ULFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp)); 668 669 fs = VFSTOULFS(dvp->v_mount)->um_lfs; 670 ASSERT_NO_SEGLOCK(fs); 671 if (fs->lfs_ronly) { 672 return EROFS; 673 } 674 675 error = lfs_set_dirop(dvp, NULL); 676 if (error) 677 return error; 678 679 error = lfs_makeinode(ap->a_vap, dvp, ulr, vpp, ap->a_cnp); 680 if (error) { 681 goto out; 682 } 683 KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE); 684 685 ip = VTOI(*vpp); 686 687 /* 688 * This test is off by one. um_maxsymlinklen contains the 689 * number of bytes available, and we aren't storing a \0, so 690 * the test should properly be <=. However, it cannot be 691 * changed as this would break compatibility with existing fs 692 * images -- see the way ulfs_readlink() works. 693 */ 694 len = strlen(ap->a_target); 695 if (len < ip->i_lfs->um_maxsymlinklen) { 696 memcpy((char *)SHORTLINK(ip), ap->a_target, len); 697 ip->i_size = len; 698 DIP_ASSIGN(ip, size, len); 699 uvm_vnp_setsize(*vpp, ip->i_size); 700 ip->i_state |= IN_CHANGE | IN_UPDATE; 701 if ((*vpp)->v_mount->mnt_flag & MNT_RELATIME) 702 ip->i_state |= IN_ACCESS; 703 } else { 704 error = ulfs_bufio(UIO_WRITE, *vpp, ap->a_target, len, (off_t)0, 705 IO_NODELOCKED | IO_JOURNALLOCKED, ap->a_cnp->cn_cred, NULL, 706 NULL); 707 } 708 709 VOP_UNLOCK(*vpp); 710 if (error) 711 vrele(*vpp); 712 713 out: 714 UNMARK_VNODE(dvp); 715 /* XXX: is it even possible for the symlink to get MARK'd? */ 716 UNMARK_VNODE(*vpp); 717 if (error) { 718 *vpp = NULL; 719 } 720 lfs_unset_dirop(fs, dvp, "symlink"); 721 722 vrele(dvp); 723 return (error); 724 } 725 726 int 727 lfs_mknod(void *v) 728 { 729 struct vop_mknod_v3_args /* { 730 struct vnode *a_dvp; 731 struct vnode **a_vpp; 732 struct componentname *a_cnp; 733 struct vattr *a_vap; 734 } */ *ap = v; 735 struct lfs *fs; 736 struct vnode *dvp, **vpp; 737 struct vattr *vap; 738 struct inode *ip; 739 int error; 740 ino_t ino; 741 struct ulfs_lookup_results *ulr; 742 743 dvp = ap->a_dvp; 744 vpp = ap->a_vpp; 745 vap = ap->a_vap; 746 747 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 748 KASSERT(vpp != NULL); 749 KASSERT(*vpp == NULL); 750 751 /* XXX should handle this material another way */ 752 ulr = &VTOI(dvp)->i_crap; 753 ULFS_CHECK_CRAPCOUNTER(VTOI(dvp)); 754 755 fs = VFSTOULFS(dvp->v_mount)->um_lfs; 756 ASSERT_NO_SEGLOCK(fs); 757 if (fs->lfs_ronly) { 758 return EROFS; 759 } 760 761 error = lfs_set_dirop(dvp, NULL); 762 if (error) 763 return error; 764 765 error = lfs_makeinode(vap, dvp, ulr, vpp, ap->a_cnp); 766 767 /* Either way we're done with the dirop at this point */ 768 UNMARK_VNODE(dvp); 769 UNMARK_VNODE(*vpp); 770 lfs_unset_dirop(fs, dvp, "mknod"); 771 772 if (error) { 773 vrele(dvp); 774 *vpp = NULL; 775 return (error); 776 } 777 KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE); 778 779 ip = VTOI(*vpp); 780 ino = ip->i_number; 781 ip->i_state |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 782 783 /* 784 * Call fsync to write the vnode so that we don't have to deal with 785 * flushing it when it's marked VU_DIROP or reclaiming. 786 * 787 * XXX KS - If we can't flush we also can't call vgone(), so must 788 * return. But, that leaves this vnode in limbo, also not good. 789 * Can this ever happen (barring hardware failure)? 790 */ 791 if ((error = VOP_FSYNC(*vpp, NOCRED, FSYNC_WAIT, 0, 0)) != 0) { 792 panic("lfs_mknod: couldn't fsync (ino %llu)", 793 (unsigned long long) ino); 794 /* return (error); */ 795 } 796 797 vrele(dvp); 798 KASSERT(error == 0); 799 VOP_UNLOCK(*vpp); 800 return (0); 801 } 802 803 /* 804 * Create a regular file 805 */ 806 int 807 lfs_create(void *v) 808 { 809 struct vop_create_v3_args /* { 810 struct vnode *a_dvp; 811 struct vnode **a_vpp; 812 struct componentname *a_cnp; 813 struct vattr *a_vap; 814 } */ *ap = v; 815 struct lfs *fs; 816 struct vnode *dvp, **vpp; 817 struct vattr *vap; 818 struct ulfs_lookup_results *ulr; 819 int error; 820 821 dvp = ap->a_dvp; 822 vpp = ap->a_vpp; 823 vap = ap->a_vap; 824 825 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 826 KASSERT(vpp != NULL); 827 KASSERT(*vpp == NULL); 828 829 /* XXX should handle this material another way */ 830 ulr = &VTOI(dvp)->i_crap; 831 ULFS_CHECK_CRAPCOUNTER(VTOI(dvp)); 832 833 fs = VFSTOULFS(dvp->v_mount)->um_lfs; 834 ASSERT_NO_SEGLOCK(fs); 835 if (fs->lfs_ronly) { 836 return EROFS; 837 } 838 839 error = lfs_set_dirop(dvp, NULL); 840 if (error) 841 return error; 842 843 error = lfs_makeinode(vap, dvp, ulr, vpp, ap->a_cnp); 844 if (error) { 845 goto out; 846 } 847 KASSERT(VOP_ISLOCKED(*vpp) == LK_EXCLUSIVE); 848 VOP_UNLOCK(*vpp); 849 850 out: 851 852 UNMARK_VNODE(dvp); 853 UNMARK_VNODE(*vpp); 854 if (error) { 855 *vpp = NULL; 856 } 857 lfs_unset_dirop(fs, dvp, "create"); 858 859 vrele(dvp); 860 return (error); 861 } 862 863 int 864 lfs_mkdir(void *v) 865 { 866 struct vop_mkdir_v3_args /* { 867 struct vnode *a_dvp; 868 struct vnode **a_vpp; 869 struct componentname *a_cnp; 870 struct vattr *a_vap; 871 } */ *ap = v; 872 struct lfs *fs; 873 struct vnode *dvp, *tvp, **vpp; 874 struct inode *dp, *ip; 875 struct componentname *cnp; 876 struct vattr *vap; 877 struct ulfs_lookup_results *ulr; 878 struct buf *bp; 879 LFS_DIRHEADER *dirp; 880 int dirblksiz; 881 int error; 882 883 dvp = ap->a_dvp; 884 tvp = NULL; 885 vpp = ap->a_vpp; 886 cnp = ap->a_cnp; 887 vap = ap->a_vap; 888 889 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 890 891 dp = VTOI(dvp); 892 ip = NULL; 893 894 KASSERT(vap->va_type == VDIR); 895 KASSERT(vpp != NULL); 896 KASSERT(*vpp == NULL); 897 898 /* XXX should handle this material another way */ 899 ulr = &dp->i_crap; 900 ULFS_CHECK_CRAPCOUNTER(dp); 901 902 fs = VFSTOULFS(dvp->v_mount)->um_lfs; 903 ASSERT_NO_SEGLOCK(fs); 904 if (fs->lfs_ronly) { 905 return EROFS; 906 } 907 908 if ((nlink_t)dp->i_nlink >= LINK_MAX) { 909 return EMLINK; 910 } 911 912 dirblksiz = fs->um_dirblksiz; 913 /* XXX dholland 20150911 I believe this to be true, but... */ 914 //KASSERT(dirblksiz == LFS_DIRBLKSIZ); 915 916 error = lfs_set_dirop(dvp, NULL); 917 if (error) 918 return error; 919 920 /* 921 * Must simulate part of lfs_makeinode here to acquire the inode, 922 * but not have it entered in the parent directory. The entry is 923 * made later after writing "." and ".." entries. 924 */ 925 error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, 926 ap->a_vpp); 927 if (error) 928 goto out; 929 930 error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE); 931 if (error) { 932 vrele(*ap->a_vpp); 933 *ap->a_vpp = NULL; 934 goto out; 935 } 936 937 tvp = *ap->a_vpp; 938 MARK_VNODE(tvp); 939 ip = VTOI(tvp); 940 ip->i_state |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 941 ip->i_nlink = 2; 942 DIP_ASSIGN(ip, nlink, 2); 943 if (cnp->cn_flags & ISWHITEOUT) { 944 ip->i_flags |= UF_OPAQUE; 945 DIP_ASSIGN(ip, flags, ip->i_flags); 946 } 947 948 /* 949 * Bump link count in parent directory to reflect work done below. 950 */ 951 dp->i_nlink++; 952 DIP_ASSIGN(dp, nlink, dp->i_nlink); 953 dp->i_state |= IN_CHANGE; 954 if ((error = lfs_update(dvp, NULL, NULL, UPDATE_DIROP)) != 0) 955 goto bad; 956 957 /* 958 * Initialize directory with "." and "..". This used to use a 959 * static template but that adds moving parts for very little 960 * benefit. 961 */ 962 if ((error = lfs_balloc(tvp, (off_t)0, dirblksiz, cnp->cn_cred, 963 B_CLRBUF, &bp)) != 0) 964 goto bad; 965 ip->i_size = dirblksiz; 966 DIP_ASSIGN(ip, size, dirblksiz); 967 ip->i_state |= IN_ACCESS | IN_CHANGE | IN_UPDATE; 968 uvm_vnp_setsize(tvp, ip->i_size); 969 dirp = bp->b_data; 970 971 /* . */ 972 lfs_dir_setino(fs, dirp, ip->i_number); 973 lfs_dir_setreclen(fs, dirp, LFS_DIRECTSIZ(fs, 1)); 974 lfs_dir_settype(fs, dirp, LFS_DT_DIR); 975 lfs_dir_setnamlen(fs, dirp, 1); 976 lfs_copydirname(fs, lfs_dir_nameptr(fs, dirp), ".", 1, 977 LFS_DIRECTSIZ(fs, 1)); 978 dirp = LFS_NEXTDIR(fs, dirp); 979 /* .. */ 980 lfs_dir_setino(fs, dirp, dp->i_number); 981 lfs_dir_setreclen(fs, dirp, dirblksiz - LFS_DIRECTSIZ(fs, 1)); 982 lfs_dir_settype(fs, dirp, LFS_DT_DIR); 983 lfs_dir_setnamlen(fs, dirp, 2); 984 lfs_copydirname(fs, lfs_dir_nameptr(fs, dirp), "..", 2, 985 dirblksiz - LFS_DIRECTSIZ(fs, 1)); 986 987 /* 988 * Directory set up; now install its entry in the parent directory. 989 */ 990 if ((error = VOP_BWRITE(bp->b_vp, bp)) != 0) 991 goto bad; 992 if ((error = lfs_update(tvp, NULL, NULL, UPDATE_DIROP)) != 0) { 993 goto bad; 994 } 995 error = ulfs_direnter(dvp, ulr, tvp, 996 cnp, ip->i_number, LFS_IFTODT(ip->i_mode), bp); 997 bad: 998 if (error == 0) { 999 VOP_UNLOCK(tvp); 1000 } else { 1001 dp->i_nlink--; 1002 DIP_ASSIGN(dp, nlink, dp->i_nlink); 1003 dp->i_state |= IN_CHANGE; 1004 /* 1005 * No need to do an explicit lfs_truncate here, vrele will 1006 * do this for us because we set the link count to 0. 1007 */ 1008 ip->i_nlink = 0; 1009 DIP_ASSIGN(ip, nlink, 0); 1010 ip->i_state |= IN_CHANGE; 1011 /* If IN_ADIROP, account for it */ 1012 UNMARK_VNODE(tvp); 1013 vput(tvp); 1014 } 1015 1016 out: 1017 UNMARK_VNODE(dvp); 1018 UNMARK_VNODE(*vpp); 1019 if (error) { 1020 *vpp = NULL; 1021 } 1022 lfs_unset_dirop(fs, dvp, "mkdir"); 1023 1024 vrele(dvp); 1025 return (error); 1026 } 1027 1028 int 1029 lfs_remove(void *v) 1030 { 1031 struct vop_remove_v3_args /* { 1032 struct vnode *a_dvp; 1033 struct vnode *a_vp; 1034 struct componentname *a_cnp; 1035 nlink_t ctx_vp_new_nlink; 1036 } */ *ap = v; 1037 struct vnode *dvp, *vp; 1038 struct inode *ip; 1039 int error; 1040 1041 dvp = ap->a_dvp; 1042 vp = ap->a_vp; 1043 1044 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 1045 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1046 1047 ip = VTOI(vp); 1048 if ((error = lfs_set_dirop(dvp, vp)) != 0) { 1049 if (dvp == vp) 1050 vrele(vp); 1051 else 1052 vput(vp); 1053 return error; 1054 } 1055 error = ulfs_remove(ap); 1056 if (ip->i_nlink == 0) 1057 lfs_orphan(ip->i_lfs, vp); 1058 1059 UNMARK_VNODE(dvp); 1060 if (ap->a_vp) { 1061 UNMARK_VNODE(ap->a_vp); 1062 } 1063 lfs_unset_dirop(ip->i_lfs, dvp, "remove"); 1064 vrele(dvp); 1065 if (ap->a_vp) { 1066 vrele(ap->a_vp); 1067 } 1068 1069 return (error); 1070 } 1071 1072 int 1073 lfs_rmdir(void *v) 1074 { 1075 struct vop_rmdir_v2_args /* { 1076 struct vnodeop_desc *a_desc; 1077 struct vnode *a_dvp; 1078 struct vnode *a_vp; 1079 struct componentname *a_cnp; 1080 } */ *ap = v; 1081 struct vnode *vp; 1082 struct inode *ip; 1083 int error; 1084 1085 vp = ap->a_vp; 1086 1087 KASSERT(VOP_ISLOCKED(ap->a_dvp) == LK_EXCLUSIVE); 1088 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1089 1090 ip = VTOI(vp); 1091 if ((error = lfs_set_dirop(ap->a_dvp, ap->a_vp)) != 0) { 1092 if (ap->a_dvp == vp) 1093 vrele(vp); 1094 else 1095 vput(vp); 1096 return error; 1097 } 1098 error = ulfs_rmdir(ap); 1099 if (ip->i_nlink == 0) 1100 lfs_orphan(ip->i_lfs, vp); 1101 1102 UNMARK_VNODE(ap->a_dvp); 1103 if (ap->a_vp) { 1104 UNMARK_VNODE(ap->a_vp); 1105 } 1106 lfs_unset_dirop(ip->i_lfs, ap->a_dvp, "rmdir"); 1107 vrele(ap->a_dvp); 1108 if (ap->a_vp) { 1109 vrele(ap->a_vp); 1110 } 1111 1112 return (error); 1113 } 1114 1115 int 1116 lfs_link(void *v) 1117 { 1118 struct vop_link_v2_args /* { 1119 struct vnode *a_dvp; 1120 struct vnode *a_vp; 1121 struct componentname *a_cnp; 1122 } */ *ap = v; 1123 struct lfs *fs; 1124 struct vnode *dvp, *vp; 1125 int error; 1126 1127 dvp = ap->a_dvp; 1128 vp = ap->a_vp; 1129 1130 KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 1131 1132 fs = VFSTOULFS(dvp->v_mount)->um_lfs; 1133 ASSERT_NO_SEGLOCK(fs); 1134 if (fs->lfs_ronly) { 1135 return EROFS; 1136 } 1137 1138 error = vn_lock(vp, LK_EXCLUSIVE); 1139 if (error) 1140 return error; 1141 error = lfs_set_dirop(dvp, vp); 1142 VOP_UNLOCK(vp); 1143 if (error) 1144 return error; 1145 1146 error = ulfs_link(ap); 1147 1148 UNMARK_VNODE(vp); 1149 UNMARK_VNODE(dvp); 1150 lfs_unset_dirop(fs, dvp, "link"); 1151 vrele(vp); 1152 vrele(dvp); 1153 1154 return (error); 1155 } 1156 1157 /* XXX hack to avoid calling ITIMES in getattr */ 1158 int 1159 lfs_getattr(void *v) 1160 { 1161 struct vop_getattr_args /* { 1162 struct vnode *a_vp; 1163 struct vattr *a_vap; 1164 kauth_cred_t a_cred; 1165 } */ *ap = v; 1166 struct vnode *vp = ap->a_vp; 1167 struct inode *ip; 1168 struct vattr *vap = ap->a_vap; 1169 struct lfs *fs; 1170 1171 KASSERT(VOP_ISLOCKED(vp)); 1172 1173 ip = VTOI(vp); 1174 fs = ip->i_lfs; 1175 1176 /* 1177 * Copy from inode table 1178 */ 1179 vap->va_fsid = ip->i_dev; 1180 vap->va_fileid = ip->i_number; 1181 vap->va_mode = ip->i_mode & ~LFS_IFMT; 1182 vap->va_nlink = ip->i_nlink; 1183 vap->va_uid = ip->i_uid; 1184 vap->va_gid = ip->i_gid; 1185 switch (vp->v_type) { 1186 case VBLK: 1187 case VCHR: 1188 vap->va_rdev = (dev_t)lfs_dino_getrdev(fs, ip->i_din); 1189 break; 1190 default: 1191 vap->va_rdev = NODEV; 1192 break; 1193 } 1194 vap->va_size = vp->v_size; 1195 vap->va_atime.tv_sec = lfs_dino_getatime(fs, ip->i_din); 1196 vap->va_atime.tv_nsec = lfs_dino_getatimensec(fs, ip->i_din); 1197 vap->va_mtime.tv_sec = lfs_dino_getmtime(fs, ip->i_din); 1198 vap->va_mtime.tv_nsec = lfs_dino_getmtimensec(fs, ip->i_din); 1199 vap->va_ctime.tv_sec = lfs_dino_getctime(fs, ip->i_din); 1200 vap->va_ctime.tv_nsec = lfs_dino_getctimensec(fs, ip->i_din); 1201 vap->va_flags = ip->i_flags; 1202 vap->va_gen = ip->i_gen; 1203 /* this doesn't belong here */ 1204 if (vp->v_type == VBLK) 1205 vap->va_blocksize = BLKDEV_IOSIZE; 1206 else if (vp->v_type == VCHR) 1207 vap->va_blocksize = MAXBSIZE; 1208 else 1209 vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; 1210 vap->va_bytes = lfs_fsbtob(fs, ip->i_lfs_effnblks); 1211 vap->va_type = vp->v_type; 1212 vap->va_filerev = ip->i_modrev; 1213 return (0); 1214 } 1215 1216 /* 1217 * Check to make sure the inode blocks won't choke the buffer 1218 * cache, then call ulfs_setattr as usual. 1219 */ 1220 int 1221 lfs_setattr(void *v) 1222 { 1223 struct vop_setattr_args /* { 1224 struct vnode *a_vp; 1225 struct vattr *a_vap; 1226 kauth_cred_t a_cred; 1227 } */ *ap = v; 1228 struct vnode *vp = ap->a_vp; 1229 1230 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1231 lfs_check(vp, LFS_UNUSED_LBN, 0); 1232 return ulfs_setattr(v); 1233 } 1234 1235 /* 1236 * Release the block we hold on lfs_newseg wrapping. Called on file close, 1237 * or explicitly from LFCNWRAPGO. Called with the interlock held. 1238 */ 1239 static int 1240 lfs_wrapgo(struct lfs *fs, struct inode *ip, int waitfor) 1241 { 1242 if (fs->lfs_stoplwp != curlwp) 1243 return EBUSY; 1244 1245 fs->lfs_stoplwp = NULL; 1246 cv_signal(&fs->lfs_stopcv); 1247 1248 KASSERT(fs->lfs_nowrap > 0); 1249 if (fs->lfs_nowrap <= 0) { 1250 return 0; 1251 } 1252 1253 if (--fs->lfs_nowrap == 0) { 1254 log(LOG_NOTICE, "%s: re-enabled log wrap\n", 1255 lfs_sb_getfsmnt(fs)); 1256 wakeup(&fs->lfs_wrappass); 1257 lfs_wakeup_cleaner(fs); 1258 } 1259 if (waitfor) { 1260 cv_wait_sig(&fs->lfs_nextsegsleep, &lfs_lock); 1261 } 1262 1263 return 0; 1264 } 1265 1266 /* 1267 * Close called. 1268 * 1269 * Update the times on the inode. 1270 */ 1271 /* ARGSUSED */ 1272 int 1273 lfs_close(void *v) 1274 { 1275 struct vop_close_args /* { 1276 struct vnode *a_vp; 1277 int a_fflag; 1278 kauth_cred_t a_cred; 1279 } */ *ap = v; 1280 struct vnode *vp = ap->a_vp; 1281 struct inode *ip; 1282 struct lfs *fs; 1283 1284 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1285 1286 ip = VTOI(vp); 1287 fs = ip->i_lfs; 1288 1289 if ((ip->i_number == ULFS_ROOTINO || ip->i_number == LFS_IFILE_INUM) && 1290 fs->lfs_stoplwp == curlwp) { 1291 mutex_enter(&lfs_lock); 1292 log(LOG_NOTICE, "lfs_close: releasing log wrap control\n"); 1293 lfs_wrapgo(fs, ip, 0); 1294 mutex_exit(&lfs_lock); 1295 } 1296 1297 /* When closing an anonymous file, maybe mark it IN_DEAD */ 1298 if (ip->i_nlink == 0) 1299 lfs_orphan(fs, vp); 1300 1301 if (vp == ip->i_lfs->lfs_ivnode && 1302 vp->v_mount->mnt_iflag & (IMNT_UNMOUNT | IMNT_WANTRDONLY)) 1303 return 0; 1304 1305 if (vrefcnt(vp) > 1 && vp != ip->i_lfs->lfs_ivnode) { 1306 LFS_ITIMES(ip, NULL, NULL, NULL); 1307 } 1308 return (0); 1309 } 1310 1311 /* 1312 * Close wrapper for special devices. 1313 * 1314 * Update the times on the inode then do device close. 1315 */ 1316 int 1317 lfsspec_close(void *v) 1318 { 1319 struct vop_close_args /* { 1320 struct vnode *a_vp; 1321 int a_fflag; 1322 kauth_cred_t a_cred; 1323 } */ *ap = v; 1324 struct vnode *vp; 1325 struct inode *ip; 1326 1327 vp = ap->a_vp; 1328 1329 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1330 1331 ip = VTOI(vp); 1332 if (vrefcnt(vp) > 1) { 1333 LFS_ITIMES(ip, NULL, NULL, NULL); 1334 } 1335 return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap)); 1336 } 1337 1338 /* 1339 * Close wrapper for fifo's. 1340 * 1341 * Update the times on the inode then do device close. 1342 */ 1343 int 1344 lfsfifo_close(void *v) 1345 { 1346 struct vop_close_args /* { 1347 struct vnode *a_vp; 1348 int a_fflag; 1349 kauth_cred_ a_cred; 1350 } */ *ap = v; 1351 struct vnode *vp; 1352 struct inode *ip; 1353 1354 vp = ap->a_vp; 1355 1356 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 1357 1358 ip = VTOI(vp); 1359 if (vrefcnt(ap->a_vp) > 1) { 1360 LFS_ITIMES(ip, NULL, NULL, NULL); 1361 } 1362 return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap)); 1363 } 1364 1365 /* 1366 * Reclaim an inode so that it can be used for other purposes. 1367 */ 1368 1369 int 1370 lfs_reclaim(void *v) 1371 { 1372 struct vop_reclaim_v2_args /* { 1373 struct vnode *a_vp; 1374 } */ *ap = v; 1375 struct vnode *vp = ap->a_vp; 1376 struct inode *ip; 1377 struct lfs *fs; 1378 int error; 1379 1380 VOP_UNLOCK(vp); 1381 1382 ip = VTOI(vp); 1383 fs = ip->i_lfs; 1384 1385 KASSERT(!(ip->i_state & IN_CLEANING)); 1386 1387 /* 1388 * The inode must be freed and updated before being removed 1389 * from its hash chain. Other threads trying to gain a hold 1390 * or lock on the inode will be stalled. 1391 */ 1392 if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 1393 lfs_vfree(vp, ip->i_number, ip->i_omode); 1394 1395 mutex_enter(&lfs_lock); 1396 LFS_CLR_UINO(ip, IN_ALLMOD); 1397 mutex_exit(&lfs_lock); 1398 if ((error = ulfs_reclaim(vp))) 1399 return (error); 1400 1401 /* 1402 * Take us off the paging and/or dirop queues if we were on them. 1403 * We shouldn't be on them. 1404 */ 1405 mutex_enter(&lfs_lock); 1406 if (ip->i_state & IN_PAGING) { 1407 log(LOG_WARNING, "%s: reclaimed vnode is IN_PAGING\n", 1408 lfs_sb_getfsmnt(fs)); 1409 ip->i_state &= ~IN_PAGING; 1410 TAILQ_REMOVE(&fs->lfs_pchainhd, ip, i_lfs_pchain); 1411 } 1412 if (vp->v_uflag & VU_DIROP) 1413 panic("reclaimed vnode is VU_DIROP"); 1414 mutex_exit(&lfs_lock); 1415 1416 pool_put(&lfs_dinode_pool, ip->i_din); 1417 lfs_deregister_all(vp); 1418 pool_put(&lfs_inoext_pool, ip->inode_ext.lfs); 1419 ip->inode_ext.lfs = NULL; 1420 genfs_node_destroy(vp); 1421 pool_put(&lfs_inode_pool, vp->v_data); 1422 vp->v_data = NULL; 1423 return (0); 1424 } 1425 1426 /* 1427 * Read a block from a storage device. 1428 * 1429 * Calculate the logical to physical mapping if not done already, 1430 * then call the device strategy routine. 1431 * 1432 * In order to avoid reading blocks that are in the process of being 1433 * written by the cleaner---and hence are not mutexed by the normal 1434 * buffer cache / page cache mechanisms---check for collisions before 1435 * reading. 1436 * 1437 * We inline ulfs_strategy to make sure that the VOP_BMAP occurs *before* 1438 * the active cleaner test. 1439 * 1440 * XXX This code assumes that lfs_markv makes synchronous checkpoints. 1441 */ 1442 int 1443 lfs_strategy(void *v) 1444 { 1445 struct vop_strategy_args /* { 1446 struct vnode *a_vp; 1447 struct buf *a_bp; 1448 } */ *ap = v; 1449 struct buf *bp; 1450 struct lfs *fs; 1451 struct vnode *vp; 1452 struct inode *ip; 1453 daddr_t tbn; 1454 #define MAXLOOP 25 1455 int i, sn, error, slept, loopcount; 1456 1457 bp = ap->a_bp; 1458 vp = ap->a_vp; 1459 ip = VTOI(vp); 1460 fs = ip->i_lfs; 1461 1462 /* lfs uses its strategy routine only for read */ 1463 KASSERT(bp->b_flags & B_READ); 1464 1465 if (vp->v_type == VBLK || vp->v_type == VCHR) 1466 panic("lfs_strategy: spec"); 1467 KASSERT(bp->b_bcount != 0); 1468 if (bp->b_blkno == bp->b_lblkno) { 1469 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, 1470 NULL); 1471 if (error) { 1472 bp->b_error = error; 1473 bp->b_resid = bp->b_bcount; 1474 biodone(bp); 1475 return (error); 1476 } 1477 if ((long)bp->b_blkno == -1) /* no valid data */ 1478 clrbuf(bp); 1479 } 1480 if ((long)bp->b_blkno < 0) { /* block is not on disk */ 1481 bp->b_resid = bp->b_bcount; 1482 biodone(bp); 1483 return (0); 1484 } 1485 1486 slept = 1; 1487 loopcount = 0; 1488 mutex_enter(&lfs_lock); 1489 while (slept && fs->lfs_seglock) { 1490 mutex_exit(&lfs_lock); 1491 /* 1492 * Look through list of intervals. 1493 * There will only be intervals to look through 1494 * if the cleaner holds the seglock. 1495 * Since the cleaner is synchronous, we can trust 1496 * the list of intervals to be current. 1497 */ 1498 tbn = LFS_DBTOFSB(fs, bp->b_blkno); 1499 sn = lfs_dtosn(fs, tbn); 1500 slept = 0; 1501 for (i = 0; i < fs->lfs_cleanind; i++) { 1502 if (sn == lfs_dtosn(fs, fs->lfs_cleanint[i]) && 1503 tbn >= fs->lfs_cleanint[i]) { 1504 DLOG((DLOG_CLEAN, 1505 "lfs_strategy: ino %llu lbn %" PRId64 1506 " ind %d sn %d fsb %" PRIx64 1507 " given sn %d fsb %" PRIx64 "\n", 1508 (unsigned long long) ip->i_number, 1509 bp->b_lblkno, i, 1510 lfs_dtosn(fs, fs->lfs_cleanint[i]), 1511 fs->lfs_cleanint[i], sn, tbn)); 1512 DLOG((DLOG_CLEAN, 1513 "lfs_strategy: sleeping on ino %llu lbn %" 1514 PRId64 "\n", 1515 (unsigned long long) ip->i_number, 1516 bp->b_lblkno)); 1517 mutex_enter(&lfs_lock); 1518 if (LFS_SEGLOCK_HELD(fs) && fs->lfs_iocount) { 1519 /* 1520 * Cleaner can't wait for itself. 1521 * Instead, wait for the blocks 1522 * to be written to disk. 1523 * XXX we need pribio in the test 1524 * XXX here. 1525 */ 1526 mtsleep(&fs->lfs_iocount, 1527 (PRIBIO + 1) | PNORELOCK, 1528 "clean2", hz/10 + 1, 1529 &lfs_lock); 1530 slept = 1; 1531 ++loopcount; 1532 break; 1533 } else if (fs->lfs_seglock) { 1534 mtsleep(&fs->lfs_seglock, 1535 (PRIBIO + 1) | PNORELOCK, 1536 "clean1", 0, 1537 &lfs_lock); 1538 slept = 1; 1539 break; 1540 } 1541 mutex_exit(&lfs_lock); 1542 } 1543 } 1544 mutex_enter(&lfs_lock); 1545 if (loopcount > MAXLOOP) { 1546 printf("lfs_strategy: breaking out of clean2 loop\n"); 1547 break; 1548 } 1549 } 1550 mutex_exit(&lfs_lock); 1551 1552 vp = ip->i_devvp; 1553 return VOP_STRATEGY(vp, bp); 1554 } 1555 1556 /* 1557 * Inline lfs_segwrite/lfs_writevnodes, but just for dirops. 1558 * Technically this is a checkpoint (the on-disk state is valid) 1559 * even though we are leaving out all the file data. 1560 */ 1561 int 1562 lfs_flush_dirops(struct lfs *fs) 1563 { 1564 struct inode *ip, *marker; 1565 struct vnode *vp; 1566 extern int lfs_dostats; /* XXX this does not belong here */ 1567 struct segment *sp; 1568 SEGSUM *ssp; 1569 int flags = 0; 1570 int error = 0; 1571 1572 ASSERT_MAYBE_SEGLOCK(fs); 1573 KASSERT(fs->lfs_nadirop == 0); /* stable during lfs_writer */ 1574 KASSERT(fs->lfs_dirops == 0); /* stable during lfs_writer */ 1575 1576 if (fs->lfs_ronly) 1577 return EROFS; 1578 1579 mutex_enter(&lfs_lock); 1580 if (TAILQ_FIRST(&fs->lfs_dchainhd) == NULL) { 1581 mutex_exit(&lfs_lock); 1582 return 0; 1583 } else 1584 mutex_exit(&lfs_lock); 1585 1586 if (lfs_dostats) 1587 ++lfs_stats.flush_invoked; 1588 1589 marker = pool_get(&lfs_inode_pool, PR_WAITOK); 1590 memset(marker, 0, sizeof(*marker)); 1591 marker->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK); 1592 memset(marker->inode_ext.lfs, 0, sizeof(*marker->inode_ext.lfs)); 1593 marker->i_state = IN_MARKER; 1594 1595 lfs_imtime(fs); 1596 lfs_seglock(fs, flags); 1597 sp = fs->lfs_sp; 1598 1599 /* 1600 * lfs_writevnodes, optimized to get dirops out of the way. 1601 * Only write dirops, and don't flush files' pages, only 1602 * blocks from the directories. 1603 * 1604 * We don't need to vref these files because they are 1605 * dirops and so hold an extra reference until the 1606 * segunlock clears them of that status. 1607 * 1608 * We don't need to check for IN_ADIROP because we know that 1609 * no dirops are active. 1610 * 1611 */ 1612 mutex_enter(&lfs_lock); 1613 KASSERT(fs->lfs_writer); 1614 TAILQ_INSERT_HEAD(&fs->lfs_dchainhd, marker, i_lfs_dchain); 1615 while ((ip = TAILQ_NEXT(marker, i_lfs_dchain)) != NULL) { 1616 TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain); 1617 TAILQ_INSERT_AFTER(&fs->lfs_dchainhd, ip, marker, 1618 i_lfs_dchain); 1619 if (ip->i_state & IN_MARKER) 1620 continue; 1621 vp = ITOV(ip); 1622 1623 /* 1624 * Prevent the vnode from going away if it's just been 1625 * put out in the segment and lfs_unmark_dirop is about 1626 * to release it. While it is on the list it is always 1627 * referenced, so it cannot be reclaimed until we 1628 * release it. 1629 */ 1630 vref(vp); 1631 1632 /* 1633 * Since we hold lfs_writer, the node can't be in an 1634 * active dirop. Since it's on the list and we hold a 1635 * reference to it, it can't be reclaimed now. 1636 */ 1637 KASSERT((ip->i_state & IN_ADIROP) == 0); 1638 KASSERT(vp->v_uflag & VU_DIROP); 1639 1640 /* 1641 * After we release lfs_lock, if we were in the middle 1642 * of writing a segment, lfs_unmark_dirop may end up 1643 * clearing VU_DIROP, and we have no way to stop it. 1644 * That should be OK -- we'll just have less to do 1645 * here. 1646 */ 1647 mutex_exit(&lfs_lock); 1648 1649 /* 1650 * All writes to directories come from dirops; all 1651 * writes to files' direct blocks go through the page 1652 * cache, which we're not touching. Reads to files 1653 * and/or directories will not be affected by writing 1654 * directory blocks inodes and file inodes. So we don't 1655 * really need to lock. 1656 */ 1657 if (vp->v_type != VREG && 1658 ((ip->i_state & IN_ALLMOD) || !VPISEMPTY(vp))) { 1659 error = lfs_writefile(fs, sp, vp); 1660 if (!VPISEMPTY(vp) && !WRITEINPROG(vp) && 1661 !(ip->i_state & IN_ALLMOD)) { 1662 mutex_enter(&lfs_lock); 1663 LFS_SET_UINO(ip, IN_MODIFIED); 1664 mutex_exit(&lfs_lock); 1665 } 1666 if (error && (sp->seg_flags & SEGM_SINGLE)) { 1667 vrele(vp); 1668 mutex_enter(&lfs_lock); 1669 error = EAGAIN; 1670 break; 1671 } 1672 } 1673 KASSERT(ip->i_number != LFS_IFILE_INUM); 1674 error = lfs_writeinode(fs, sp, ip); 1675 if (error && (sp->seg_flags & SEGM_SINGLE)) { 1676 vrele(vp); 1677 mutex_enter(&lfs_lock); 1678 error = EAGAIN; 1679 break; 1680 } 1681 1682 /* 1683 * We might need to update files' inodes again; 1684 * for example, if they have data blocks to write. 1685 * Make sure that after this flush, they are still 1686 * marked IN_MODIFIED so that we don't forget to 1687 * write them. 1688 */ 1689 mutex_enter(&lfs_lock); 1690 if (vp->v_type == VREG) 1691 LFS_SET_UINO(ip, IN_MODIFIED); 1692 mutex_exit(&lfs_lock); 1693 1694 vrele(vp); 1695 mutex_enter(&lfs_lock); 1696 } 1697 TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain); 1698 mutex_exit(&lfs_lock); 1699 1700 /* We've written all the dirops there are */ 1701 ssp = (SEGSUM *)sp->segsum; 1702 lfs_ss_setflags(fs, ssp, lfs_ss_getflags(fs, ssp) & ~(SS_CONT)); 1703 lfs_finalize_fs_seguse(fs); 1704 (void) lfs_writeseg(fs, sp); 1705 lfs_segunlock(fs); 1706 1707 pool_put(&lfs_inoext_pool, marker->inode_ext.lfs); 1708 pool_put(&lfs_inode_pool, marker); 1709 1710 return error; 1711 } 1712 1713 /* 1714 * Flush all vnodes for which the pagedaemon has requested pageouts. 1715 * Skip over any files that are marked VU_DIROP (since lfs_flush_dirop() 1716 * has just run, this would be an error). If we have to skip a vnode 1717 * for any reason, just skip it; if we have to wait for the cleaner, 1718 * abort. The writer daemon will call us again later. 1719 */ 1720 int 1721 lfs_flush_pchain(struct lfs *fs) 1722 { 1723 struct inode *ip, *nip; 1724 struct vnode *vp; 1725 extern int lfs_dostats; 1726 struct segment *sp; 1727 int error, error2; 1728 1729 ASSERT_NO_SEGLOCK(fs); 1730 KASSERT(fs->lfs_writer); 1731 1732 if (fs->lfs_ronly) 1733 return EROFS; 1734 1735 mutex_enter(&lfs_lock); 1736 if (TAILQ_FIRST(&fs->lfs_pchainhd) == NULL) { 1737 mutex_exit(&lfs_lock); 1738 return 0; 1739 } else 1740 mutex_exit(&lfs_lock); 1741 1742 /* Get dirops out of the way */ 1743 if ((error = lfs_flush_dirops(fs)) != 0) 1744 return error; 1745 1746 if (lfs_dostats) 1747 ++lfs_stats.flush_invoked; 1748 1749 /* 1750 * Inline lfs_segwrite/lfs_writevnodes, but just for pageouts. 1751 */ 1752 lfs_imtime(fs); 1753 lfs_seglock(fs, 0); 1754 sp = fs->lfs_sp; 1755 1756 /* 1757 * lfs_writevnodes, optimized to clear pageout requests. 1758 * Only write non-dirop files that are in the pageout queue. 1759 * We're very conservative about what we write; we want to be 1760 * fast and async. 1761 */ 1762 mutex_enter(&lfs_lock); 1763 top: 1764 for (ip = TAILQ_FIRST(&fs->lfs_pchainhd); ip != NULL; ip = nip) { 1765 struct mount *mp = ITOV(ip)->v_mount; 1766 ino_t ino = ip->i_number; 1767 1768 nip = TAILQ_NEXT(ip, i_lfs_pchain); 1769 1770 if (!(ip->i_state & IN_PAGING)) 1771 goto top; 1772 1773 mutex_exit(&lfs_lock); 1774 if (vcache_get(mp, &ino, sizeof(ino), &vp) != 0) { 1775 mutex_enter(&lfs_lock); 1776 continue; 1777 }; 1778 if (vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT) != 0) { 1779 vrele(vp); 1780 mutex_enter(&lfs_lock); 1781 continue; 1782 } 1783 ip = VTOI(vp); 1784 mutex_enter(&lfs_lock); 1785 if ((vp->v_uflag & VU_DIROP) != 0 || vp->v_type != VREG || 1786 !(ip->i_state & IN_PAGING)) { 1787 mutex_exit(&lfs_lock); 1788 vput(vp); 1789 mutex_enter(&lfs_lock); 1790 goto top; 1791 } 1792 mutex_exit(&lfs_lock); 1793 1794 error = lfs_writefile(fs, sp, vp); 1795 if (!VPISEMPTY(vp) && !WRITEINPROG(vp) && 1796 !(ip->i_state & IN_ALLMOD)) { 1797 mutex_enter(&lfs_lock); 1798 LFS_SET_UINO(ip, IN_MODIFIED); 1799 mutex_exit(&lfs_lock); 1800 } 1801 KASSERT(ip->i_number != LFS_IFILE_INUM); 1802 error2 = lfs_writeinode(fs, sp, ip); 1803 1804 VOP_UNLOCK(vp); 1805 vrele(vp); 1806 1807 if (error == EAGAIN || error2 == EAGAIN) { 1808 lfs_writeseg(fs, sp); 1809 mutex_enter(&lfs_lock); 1810 break; 1811 } 1812 mutex_enter(&lfs_lock); 1813 } 1814 mutex_exit(&lfs_lock); 1815 (void) lfs_writeseg(fs, sp); 1816 lfs_segunlock(fs); 1817 1818 return 0; 1819 } 1820 1821 /* 1822 * Conversion for compat. 1823 */ 1824 static void 1825 block_info_from_70(BLOCK_INFO *bi, const BLOCK_INFO_70 *bi70) 1826 { 1827 bi->bi_inode = bi70->bi_inode; 1828 bi->bi_lbn = bi70->bi_lbn; 1829 bi->bi_daddr = bi70->bi_daddr; 1830 bi->bi_segcreate = bi70->bi_segcreate; 1831 bi->bi_version = bi70->bi_version; 1832 bi->bi_bp = bi70->bi_bp; 1833 bi->bi_size = bi70->bi_size; 1834 } 1835 1836 static void 1837 block_info_to_70(BLOCK_INFO_70 *bi70, const BLOCK_INFO *bi) 1838 { 1839 bi70->bi_inode = bi->bi_inode; 1840 bi70->bi_lbn = bi->bi_lbn; 1841 bi70->bi_daddr = bi->bi_daddr; 1842 bi70->bi_segcreate = bi->bi_segcreate; 1843 bi70->bi_version = bi->bi_version; 1844 bi70->bi_bp = bi->bi_bp; 1845 bi70->bi_size = bi->bi_size; 1846 } 1847 1848 /* 1849 * Provide a fcntl interface to sys_lfs_{segwait,bmapv,markv}. 1850 */ 1851 int 1852 lfs_fcntl(void *v) 1853 { 1854 struct vop_fcntl_args /* { 1855 struct vnode *a_vp; 1856 u_int a_command; 1857 void * a_data; 1858 int a_fflag; 1859 kauth_cred_t a_cred; 1860 } */ *ap = v; 1861 struct timeval tv; 1862 struct timeval *tvp; 1863 struct timeval50 *tvp50; 1864 BLOCK_INFO *blkiov; 1865 BLOCK_INFO_70 *blkiov70; 1866 CLEANERINFO *cip; 1867 CLEANERINFO64 ci; 1868 SEGUSE *sup, *sua; 1869 int blkcnt, i, error; 1870 size_t fh_size, size; 1871 struct lfs_fcntl_markv blkvp; 1872 struct lfs_fcntl_markv_70 blkvp70; 1873 struct lfs_inode_array inotbl; 1874 struct lfs_segnum_array snap; 1875 struct lfs_filestat_req lfr; 1876 struct lfs_write_stats lws; 1877 struct lfs_filestats *fss; 1878 struct lfs_seguse_array suap; 1879 struct lfs_autoclean_params params; 1880 struct lwp *l; 1881 fsid_t *fsidp; 1882 struct lfs *fs; 1883 struct buf *bp; 1884 fhandle_t *fhp; 1885 daddr_t off; 1886 int oclean, *sna, direct, offset; 1887 ino_t *inoa; 1888 bool scramble; 1889 ino_t maxino; 1890 1891 /* Only respect LFS fcntls on fs root or Ifile */ 1892 if (VTOI(ap->a_vp)->i_number != ULFS_ROOTINO && 1893 VTOI(ap->a_vp)->i_number != LFS_IFILE_INUM) { 1894 return genfs_fcntl(v); 1895 } 1896 1897 /* Avoid locking a draining lock */ 1898 if (ap->a_vp->v_mount->mnt_iflag & IMNT_UNMOUNT) { 1899 return ESHUTDOWN; 1900 } 1901 1902 /* LFS control and monitoring fcntls are available only to root */ 1903 l = curlwp; 1904 if (((ap->a_command & 0xff00) >> 8) == 'L' && 1905 (error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 1906 KAUTH_REQ_SYSTEM_LFS_FCNTL, NULL, NULL, NULL)) != 0) 1907 return (error); 1908 1909 fs = VTOI(ap->a_vp)->i_lfs; 1910 fsidp = &ap->a_vp->v_mount->mnt_stat.f_fsidx; 1911 1912 maxino = ((VTOI(fs->lfs_ivnode)->i_size >> lfs_sb_getbshift(fs)) 1913 - lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) 1914 * lfs_sb_getifpb(fs); 1915 1916 error = 0; 1917 switch ((int)ap->a_command) { 1918 case LFCNSEGWAITALL_COMPAT_50: 1919 case LFCNSEGWAITALL_COMPAT: 1920 fsidp = NULL; 1921 /* FALLTHROUGH */ 1922 case LFCNSEGWAIT_COMPAT_50: 1923 case LFCNSEGWAIT_COMPAT: 1924 tvp50 = (struct timeval50 *)ap->a_data; 1925 timeval50_to_timeval(tvp50, &tv); 1926 tvp = &tv; 1927 goto segwait_common; 1928 1929 case LFCNSEGWAITALL: 1930 fsidp = NULL; 1931 /* FALLTHROUGH */ 1932 case LFCNSEGWAIT: 1933 tvp = (struct timeval *)ap->a_data; 1934 segwait_common: 1935 mutex_enter(&lfs_lock); 1936 ++fs->lfs_sleepers; 1937 mutex_exit(&lfs_lock); 1938 1939 error = lfs_segwait(fsidp, tvp); 1940 1941 mutex_enter(&lfs_lock); 1942 if (--fs->lfs_sleepers == 0) 1943 cv_broadcast(&fs->lfs_sleeperscv); 1944 mutex_exit(&lfs_lock); 1945 return error; 1946 1947 case LFCNBMAPV_COMPAT_70: 1948 case LFCNMARKV_COMPAT_70: 1949 blkvp70 = *(struct lfs_fcntl_markv_70 *)ap->a_data; 1950 1951 blkcnt = blkvp70.blkcnt; 1952 if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT) 1953 return (EINVAL); 1954 blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 1955 blkiov70 = lfs_malloc(fs, sizeof(BLOCK_INFO_70), LFS_NB_BLKIOV); 1956 for (i = 0; i < blkcnt; i++) { 1957 error = copyin(&blkvp70.blkiov[i], blkiov70, 1958 sizeof(*blkiov70)); 1959 if (error) { 1960 lfs_free(fs, blkiov70, LFS_NB_BLKIOV); 1961 lfs_free(fs, blkiov, LFS_NB_BLKIOV); 1962 return error; 1963 } 1964 block_info_from_70(&blkiov[i], blkiov70); 1965 } 1966 1967 mutex_enter(&lfs_lock); 1968 ++fs->lfs_sleepers; 1969 mutex_exit(&lfs_lock); 1970 if (ap->a_command == LFCNBMAPV) 1971 error = lfs_bmapv(l, fsidp, blkiov, blkcnt); 1972 else /* LFCNMARKV */ 1973 error = lfs_markv(l, fsidp, blkiov, blkcnt); 1974 if (error == 0) { 1975 for (i = 0; i < blkcnt; i++) { 1976 block_info_to_70(blkiov70, &blkiov[i]); 1977 error = copyout(blkiov70, &blkvp70.blkiov[i], 1978 sizeof(*blkiov70)); 1979 if (error) { 1980 break; 1981 } 1982 } 1983 } 1984 mutex_enter(&lfs_lock); 1985 if (--fs->lfs_sleepers == 0) 1986 cv_broadcast(&fs->lfs_sleeperscv); 1987 mutex_exit(&lfs_lock); 1988 lfs_free(fs, blkiov, LFS_NB_BLKIOV); 1989 return error; 1990 1991 case LFCNBMAPV: 1992 case LFCNMARKV: 1993 blkvp = *(struct lfs_fcntl_markv *)ap->a_data; 1994 1995 blkcnt = blkvp.blkcnt; 1996 if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT) 1997 return (EINVAL); 1998 blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 1999 if ((error = copyin(blkvp.blkiov, blkiov, 2000 blkcnt * sizeof(BLOCK_INFO))) != 0) { 2001 lfs_free(fs, blkiov, LFS_NB_BLKIOV); 2002 return error; 2003 } 2004 2005 mutex_enter(&lfs_lock); 2006 ++fs->lfs_sleepers; 2007 mutex_exit(&lfs_lock); 2008 if (ap->a_command == LFCNBMAPV) 2009 error = lfs_bmapv(l, fsidp, blkiov, blkcnt); 2010 else /* LFCNMARKV */ 2011 error = lfs_markv(l, fsidp, blkiov, blkcnt); 2012 if (error == 0) 2013 error = copyout(blkiov, blkvp.blkiov, 2014 blkcnt * sizeof(BLOCK_INFO)); 2015 mutex_enter(&lfs_lock); 2016 if (--fs->lfs_sleepers == 0) 2017 cv_broadcast(&fs->lfs_sleeperscv); 2018 mutex_exit(&lfs_lock); 2019 lfs_free(fs, blkiov, LFS_NB_BLKIOV); 2020 return error; 2021 2022 case LFCNRECLAIM: 2023 /* 2024 * Flush dirops and write Ifile, allowing empty segments 2025 * to be immediately reclaimed. 2026 */ 2027 lfs_writer_enter(fs, "pndirop"); 2028 off = lfs_sb_getoffset(fs); 2029 lfs_prelock(fs, 0); 2030 lfs_flush_dirops(fs); 2031 LFS_CLEANERINFO(cip, fs, bp); 2032 oclean = lfs_ci_getclean(fs, cip); 2033 LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); 2034 2035 lfs_seglock(fs, 0); 2036 lfs_segwrite(ap->a_vp->v_mount, SEGM_CKP | SEGM_FORCE_CKP); 2037 2038 /* Copy out write stats while fs->lfs_sp still exists */ 2039 memset(&lws, 0, sizeof(lws)); 2040 lws.direct = 0; 2041 lws.offset = lfs_btofsb(fs, fs->lfs_sp->bytes_written); 2042 *(struct lfs_write_stats *)ap->a_data = lws; 2043 2044 lfs_segunlock(fs); 2045 lfs_preunlock(fs); 2046 lfs_writer_leave(fs); 2047 2048 #ifdef DEBUG 2049 LFS_CLEANERINFO(cip, fs, bp); 2050 DLOG((DLOG_CLEAN, "lfs_fcntl: reclaim wrote %" PRId64 2051 " blocks, cleaned %" PRId32 " segments (activesb %d)\n", 2052 lfs_sb_getoffset(fs) - off, 2053 lfs_ci_getclean(fs, cip) - oclean, 2054 fs->lfs_activesb)); 2055 LFS_SYNC_CLEANERINFO(cip, fs, bp, 0); 2056 #else 2057 __USE(oclean); 2058 __USE(off); 2059 #endif 2060 2061 return 0; 2062 2063 case LFCNIFILEFH_COMPAT: 2064 /* Return the filehandle of the Ifile */ 2065 if ((error = kauth_authorize_system(l->l_cred, 2066 KAUTH_SYSTEM_FILEHANDLE, 2067 0, NULL, NULL, NULL)) != 0) 2068 return (error); 2069 fhp = (struct fhandle *)ap->a_data; 2070 fhp->fh_fsid = *fsidp; 2071 fh_size = 16; /* former VFS_MAXFIDSIZ */ 2072 return lfs_vptofh(fs->lfs_ivnode, &(fhp->fh_fid), &fh_size); 2073 2074 case LFCNIFILEFH_COMPAT2: 2075 case LFCNIFILEFH: 2076 /* Return the filehandle of the Ifile */ 2077 fhp = (struct fhandle *)ap->a_data; 2078 fhp->fh_fsid = *fsidp; 2079 fh_size = sizeof(struct lfs_fhandle) - 2080 offsetof(fhandle_t, fh_fid); 2081 return lfs_vptofh(fs->lfs_ivnode, &(fhp->fh_fid), &fh_size); 2082 2083 case LFCNREWIND: 2084 /* Move lfs_offset to the lowest-numbered segment */ 2085 return lfs_rewind(fs, *(int *)ap->a_data); 2086 2087 case LFCNINVAL: 2088 /* Mark a segment SEGUSE_INVAL */ 2089 return lfs_invalidate(fs, *(int *)ap->a_data); 2090 2091 case LFCNRESIZE: 2092 /* Resize the filesystem */ 2093 return lfs_resize_fs(fs, *(int *)ap->a_data); 2094 2095 case LFCNWRAPSTOP: 2096 case LFCNWRAPSTOP_COMPAT: 2097 /* 2098 * Hold lfs_newseg at segment 0; if requested, sleep until 2099 * the filesystem wraps around. To support external agents 2100 * (dump, fsck-based regression test) that need to look at 2101 * a snapshot of the filesystem, without necessarily 2102 * requiring that all fs activity stops. 2103 */ 2104 if (fs->lfs_stoplwp == curlwp) 2105 return EALREADY; 2106 2107 mutex_enter(&lfs_lock); 2108 while (fs->lfs_stoplwp != NULL) 2109 cv_wait(&fs->lfs_stopcv, &lfs_lock); 2110 fs->lfs_stoplwp = curlwp; 2111 if (fs->lfs_nowrap == 0) 2112 log(LOG_NOTICE, "%s: disabled log wrap\n", 2113 lfs_sb_getfsmnt(fs)); 2114 ++fs->lfs_nowrap; 2115 if (*(int *)ap->a_data == 1 2116 || ap->a_command == LFCNWRAPSTOP_COMPAT) { 2117 log(LOG_NOTICE, "LFCNSTOPWRAP waiting for log wrap\n"); 2118 error = mtsleep(&fs->lfs_nowrap, PCATCH | PUSER, 2119 "segwrap", 0, &lfs_lock); 2120 log(LOG_NOTICE, "LFCNSTOPWRAP done waiting\n"); 2121 if (error) { 2122 lfs_wrapgo(fs, VTOI(ap->a_vp), 0); 2123 } 2124 } 2125 mutex_exit(&lfs_lock); 2126 return 0; 2127 2128 case LFCNWRAPGO: 2129 case LFCNWRAPGO_COMPAT: 2130 /* 2131 * Having done its work, the agent wakes up the writer. 2132 * If the argument is 1, it sleeps until a new segment 2133 * is selected. 2134 */ 2135 mutex_enter(&lfs_lock); 2136 error = lfs_wrapgo(fs, VTOI(ap->a_vp), 2137 ap->a_command == LFCNWRAPGO_COMPAT ? 1 : 2138 *((int *)ap->a_data)); 2139 mutex_exit(&lfs_lock); 2140 return error; 2141 2142 case LFCNWRAPPASS: 2143 if ((VTOI(ap->a_vp)->i_lfs_iflags & LFSI_WRAPWAIT)) 2144 return EALREADY; 2145 mutex_enter(&lfs_lock); 2146 if (fs->lfs_stoplwp != curlwp) { 2147 mutex_exit(&lfs_lock); 2148 return EALREADY; 2149 } 2150 if (fs->lfs_nowrap == 0) { 2151 mutex_exit(&lfs_lock); 2152 return EBUSY; 2153 } 2154 fs->lfs_wrappass = 1; 2155 wakeup(&fs->lfs_wrappass); 2156 /* Wait for the log to wrap, if asked */ 2157 if (*(int *)ap->a_data) { 2158 vref(ap->a_vp); 2159 VTOI(ap->a_vp)->i_lfs_iflags |= LFSI_WRAPWAIT; 2160 log(LOG_NOTICE, "LFCNPASS waiting for log wrap\n"); 2161 error = mtsleep(&fs->lfs_nowrap, PCATCH | PUSER, 2162 "segwrap", 0, &lfs_lock); 2163 log(LOG_NOTICE, "LFCNPASS done waiting\n"); 2164 VTOI(ap->a_vp)->i_lfs_iflags &= ~LFSI_WRAPWAIT; 2165 vrele(ap->a_vp); 2166 } 2167 mutex_exit(&lfs_lock); 2168 return error; 2169 2170 case LFCNWRAPSTATUS: 2171 mutex_enter(&lfs_lock); 2172 *(int *)ap->a_data = fs->lfs_wrapstatus; 2173 mutex_exit(&lfs_lock); 2174 return 0; 2175 2176 case LFCNFILESTATS: 2177 /* Retrieve fragmentation statistics from these inodes */ 2178 lfr = *(struct lfs_filestat_req *)ap->a_data; 2179 if (lfr.len < 0 || lfr.len > LFS_FILESTATS_MAXCNT) 2180 return EINVAL; 2181 if (lfr.ino < LFS_IFILE_INUM || lfr.len < 1 2182 || lfr.ino >= maxino || lfr.ino + lfr.len >= maxino) 2183 return EINVAL; 2184 fss = lfs_malloc(fs, lfr.len * sizeof(*fss), LFS_NB_BLKIOV); 2185 if ((error = copyin(lfr.fss, fss, 2186 lfr.len * sizeof(*fss))) != 0) { 2187 lfs_free(fs, fss, LFS_NB_BLKIOV); 2188 return error; 2189 } 2190 2191 for (i = 0; i < lfr.len; ++i) { 2192 error = lfs_filestats(fs, lfr.ino + i, &fss[i]); 2193 if (error == ENOENT) 2194 error = 0; 2195 if (error) 2196 break; 2197 } 2198 2199 if (error == 0) 2200 error = copyout(fss, lfr.fss, lfr.len * sizeof(*fss)); 2201 2202 lfs_free(fs, fss, LFS_NB_BLKIOV); 2203 return error; 2204 2205 case LFCNREWRITESEGS: 2206 /* Rewrite (clean) the listed segments */ 2207 snap = *(struct lfs_segnum_array *)ap->a_data; 2208 if (snap.len > LFS_REWRITE_MAXCNT) 2209 return EINVAL; 2210 sna = lfs_malloc(fs, snap.len * sizeof(int), LFS_NB_BLKIOV); 2211 if ((error = copyin(snap.segments, sna, 2212 snap.len * sizeof(int))) != 0) { 2213 lfs_free(fs, sna, LFS_NB_BLKIOV); 2214 return error; 2215 } 2216 2217 for (i = 0; i < snap.len; i++) 2218 if (sna[i] < 0 || sna[i] >= lfs_sb_getnseg(fs)) 2219 return EINVAL; 2220 2221 direct = offset = 0; 2222 error = lfs_rewrite_segments(fs, sna, snap.len, &direct, 2223 &offset, curlwp); 2224 lfs_free(fs, sna, LFS_NB_BLKIOV); 2225 2226 /* Copy out write stats */ 2227 snap.stats.direct = direct; 2228 snap.stats.offset = offset; 2229 *(struct lfs_write_stats *) 2230 &(((struct lfs_segnum_array *)ap->a_data)->stats) 2231 = snap.stats; 2232 return error; 2233 2234 case LFCNREWRITEFILE: 2235 case LFCNSCRAMBLE: 2236 /* Rewrite (coalesce) the listed inodes */ 2237 scramble = ((int)ap->a_command == LFCNSCRAMBLE); 2238 inotbl = *(struct lfs_inode_array *)ap->a_data; 2239 if (inotbl.len > LFS_REWRITE_MAXCNT) 2240 return EINVAL; 2241 inoa = lfs_malloc(fs, inotbl.len * sizeof(ino_t), 2242 LFS_NB_BLKIOV); 2243 if ((error = copyin(inotbl.inodes, inoa, 2244 inotbl.len * sizeof(ino_t))) != 0) { 2245 lfs_free(fs, inoa, LFS_NB_BLKIOV); 2246 return error; 2247 } 2248 2249 for (i = 0; i < inotbl.len; i++) { 2250 if (inoa[i] <= LFS_IFILE_INUM || inoa[i] >= maxino) 2251 return EINVAL; 2252 } 2253 2254 direct = offset = 0; 2255 error = lfs_rewrite_file(fs, inoa, inotbl.len, scramble, 2256 &direct, &offset); 2257 lfs_free(fs, inoa, LFS_NB_BLKIOV); 2258 2259 /* Copy out write stats */ 2260 inotbl.stats.direct = direct; 2261 inotbl.stats.offset = offset; 2262 *(struct lfs_write_stats *) 2263 &(((struct lfs_inode_array *)ap->a_data)->stats) 2264 = inotbl.stats; 2265 2266 return error; 2267 2268 case LFCNCLEANERINFO: 2269 /* 2270 * Get current CLEANERINFO information. 2271 */ 2272 memset(&ci, 0, sizeof ci); 2273 ci.clean = lfs_sb_getnclean(fs); 2274 ci.dirty = lfs_sb_getnseg(fs) - lfs_sb_getnclean(fs); 2275 ci.bfree = lfs_sb_getbfree(fs); 2276 ci.avail = lfs_sb_getavail(fs) - fs->lfs_ravail 2277 - fs->lfs_favail; 2278 ci.flags = (fs->lfs_flags & LFS_MUSTCLEAN) 2279 ? LFS_CLEANER_MUST_CLEAN : 0; 2280 *(CLEANERINFO64 *)ap->a_data = ci; 2281 2282 return 0; 2283 2284 case LFCNSEGUSE: 2285 /* 2286 * Retrieve SEGUSE information for one or more segments. 2287 */ 2288 if (lfs_sb_getversion(fs) == 1) 2289 return EINVAL; 2290 suap = *(struct lfs_seguse_array *)ap->a_data; 2291 if (suap.start < 0 2292 /* || suap.len < 0 */ 2293 || suap.len > LFS_SEGUSE_MAXCNT 2294 || suap.start >= lfs_sb_getnseg(fs)) 2295 return EINVAL; 2296 if (suap.start + suap.len >= lfs_sb_getnseg(fs)) { 2297 suap.len = lfs_sb_getnseg(fs) - suap.start; 2298 *(struct lfs_seguse_array *)ap->a_data = suap; 2299 } 2300 sua = lfs_malloc(fs, suap.len * sizeof *sua, LFS_NB_BLKIOV); 2301 2302 for (i = 0; i < suap.len; i++) { 2303 LFS_SEGENTRY(sup, fs, suap.start + i, bp); 2304 memcpy(sua + i, sup, sizeof(*sup)); 2305 brelse(bp, 0); 2306 } 2307 2308 error = copyout(sua, suap.seguse, suap.len * sizeof *sua); 2309 lfs_free(fs, sua, LFS_NB_BLKIOV); 2310 return error; 2311 2312 case LFCNAUTOCLEAN: 2313 /* 2314 * Control the in-kernel cleaner. 2315 */ 2316 size = *(size_t *)ap->a_data; 2317 if (size > sizeof(params)) 2318 return EINVAL; 2319 memset(¶ms, 0, sizeof(params)); 2320 memcpy(¶ms, (struct lfs_autoclean_params *)ap->a_data, 2321 size); 2322 return lfs_cleanctl(fs, ¶ms); 2323 2324 default: 2325 return genfs_fcntl(v); 2326 } 2327 return 0; 2328 } 2329 2330 /* 2331 * Report continuity statistics for this file. Two measures are provided: 2332 * the number of discontinuities, and the total length, in fragment units, 2333 * of all the gaps between contiguously allocated file extents. Only 2334 * direct blocks are considered. 2335 * 2336 * A single-block file will show zero for both measures, as will any file 2337 * that fits completely within its partial-segment. In general, the minimum 2338 * discontinuity count for any files will be N-1, where N is the number 2339 * of segments required to store the file, rounded up; and the minimum 2340 * total gap length will also be N, with only the partial-segment headers 2341 * breaking up the file data (indirect blocks are written at the end). 2342 * 2343 * Some files will be too large to be written in their entirety without 2344 * a checkpoint in the middle; those will have a higher minimum total gap 2345 * measure but about the same discountinuity count. 2346 * 2347 * The coalescing cleaner will use these statistics to identify files that 2348 * need to be rewritten to be contiguous on disk. 2349 */ 2350 static int 2351 lfs_filestats(struct lfs *fs, ino_t ino, struct lfs_filestats *lfp) 2352 { 2353 int error, step, run; 2354 daddr_t lbn, odaddr, daddr, diff, hiblk; 2355 struct vnode *vp; 2356 struct inode *ip; 2357 2358 memset(lfp, 0, sizeof(*lfp)); 2359 lfp->ino = ino; 2360 2361 /* Contiguous blocks will be this far apart */ 2362 step = lfs_sb_getbsize(fs) >> DEV_BSHIFT; 2363 2364 error = VFS_VGET(fs->lfs_ivnode->v_mount, ino, LK_SHARED, &vp); 2365 if (error) 2366 return error; 2367 ip = VTOI(vp); 2368 2369 /* Highest block in this inode */ 2370 hiblk = lfs_lblkno(fs, ip->i_size + lfs_sb_getbsize(fs) - 1) - 1; 2371 lfp->nblk = 0; 2372 2373 odaddr = 0x0; 2374 for (lbn = 0; lbn <= hiblk; ++lbn) { 2375 error = VOP_BMAP(vp, lbn, NULL, &daddr, &run); 2376 if (error) 2377 break; 2378 2379 /* Count all blocks */ 2380 if (daddr > 0) 2381 lfp->nblk += (run + 1); 2382 2383 /* Holes and yet-unwritten data only count once */ 2384 if (daddr == odaddr && daddr <= 0) 2385 continue; 2386 2387 /* Count any discontinuities */ 2388 if (lbn > 0 && daddr != odaddr + step) { 2389 ++lfp->dc_count; 2390 diff = daddr - odaddr; 2391 if (diff < 0) 2392 diff = -diff; 2393 lfp->dc_sum += diff; 2394 } 2395 lbn += run; 2396 odaddr = daddr + run * step; 2397 } 2398 VOP_UNLOCK(vp); 2399 vrele(vp); 2400 2401 return 0; 2402 } 2403 2404 /* 2405 * Return the last logical file offset that should be written for this file 2406 * if we're doing a write that ends at "size". If writing, we need to know 2407 * about sizes on disk, i.e. fragments if there are any; if reading, we need 2408 * to know about entire blocks. 2409 */ 2410 void 2411 lfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 2412 { 2413 struct inode *ip = VTOI(vp); 2414 struct lfs *fs = ip->i_lfs; 2415 daddr_t olbn, nlbn; 2416 2417 olbn = lfs_lblkno(fs, ip->i_size); 2418 nlbn = lfs_lblkno(fs, size); 2419 if (!(flags & GOP_SIZE_MEM) && nlbn < ULFS_NDADDR && olbn <= nlbn) { 2420 *eobp = lfs_fragroundup(fs, size); 2421 } else { 2422 *eobp = lfs_blkroundup(fs, size); 2423 } 2424 } 2425 2426 #ifdef DEBUG 2427 void lfs_dump_vop(void *); 2428 2429 void 2430 lfs_dump_vop(void *v) 2431 { 2432 struct vop_putpages_args /* { 2433 struct vnode *a_vp; 2434 voff_t a_offlo; 2435 voff_t a_offhi; 2436 int a_flags; 2437 } */ *ap = v; 2438 2439 struct inode *ip = VTOI(ap->a_vp); 2440 struct lfs *fs = ip->i_lfs; 2441 2442 #ifdef DDB 2443 vfs_vnode_print(ap->a_vp, 0, printf); 2444 #endif 2445 lfs_dump_dinode(fs, ip->i_din); 2446 } 2447 #endif 2448 2449 int 2450 lfs_mmap(void *v) 2451 { 2452 struct vop_mmap_args /* { 2453 const struct vnodeop_desc *a_desc; 2454 struct vnode *a_vp; 2455 vm_prot_t a_prot; 2456 kauth_cred_t a_cred; 2457 } */ *ap = v; 2458 2459 if (VTOI(ap->a_vp)->i_number == LFS_IFILE_INUM) 2460 return EOPNOTSUPP; 2461 return genfs_mmap(v); 2462 } 2463 2464 static int 2465 lfs_openextattr(void *v) 2466 { 2467 struct vop_openextattr_args /* { 2468 struct vnode *a_vp; 2469 kauth_cred_t a_cred; 2470 struct proc *a_p; 2471 } */ *ap = v; 2472 struct vnode *vp = ap->a_vp; 2473 struct inode *ip; 2474 struct ulfsmount *ump; 2475 2476 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2477 2478 ip = VTOI(vp); 2479 ump = ip->i_ump; 2480 2481 /* Not supported for ULFS1 file systems. */ 2482 if (ump->um_fstype == ULFS1) 2483 return (EOPNOTSUPP); 2484 2485 /* XXX Not implemented for ULFS2 file systems. */ 2486 return (EOPNOTSUPP); 2487 } 2488 2489 static int 2490 lfs_closeextattr(void *v) 2491 { 2492 struct vop_closeextattr_args /* { 2493 struct vnode *a_vp; 2494 int a_commit; 2495 kauth_cred_t a_cred; 2496 struct proc *a_p; 2497 } */ *ap = v; 2498 struct vnode *vp = ap->a_vp; 2499 struct inode *ip; 2500 struct ulfsmount *ump; 2501 2502 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2503 2504 ip = VTOI(vp); 2505 ump = ip->i_ump; 2506 2507 /* Not supported for ULFS1 file systems. */ 2508 if (ump->um_fstype == ULFS1) 2509 return (EOPNOTSUPP); 2510 2511 /* XXX Not implemented for ULFS2 file systems. */ 2512 return (EOPNOTSUPP); 2513 } 2514 2515 static int 2516 lfs_getextattr(void *v) 2517 { 2518 struct vop_getextattr_args /* { 2519 struct vnode *a_vp; 2520 int a_attrnamespace; 2521 const char *a_name; 2522 struct uio *a_uio; 2523 size_t *a_size; 2524 kauth_cred_t a_cred; 2525 struct proc *a_p; 2526 } */ *ap = v; 2527 struct vnode *vp = ap->a_vp; 2528 struct inode *ip; 2529 struct ulfsmount *ump; 2530 int error; 2531 2532 KASSERT(VOP_ISLOCKED(vp)); 2533 2534 ip = VTOI(vp); 2535 ump = ip->i_ump; 2536 2537 if (ump->um_fstype == ULFS1) { 2538 #ifdef LFS_EXTATTR 2539 error = ulfs_getextattr(ap); 2540 #else 2541 error = EOPNOTSUPP; 2542 #endif 2543 return error; 2544 } 2545 2546 /* XXX Not implemented for ULFS2 file systems. */ 2547 return (EOPNOTSUPP); 2548 } 2549 2550 static int 2551 lfs_setextattr(void *v) 2552 { 2553 struct vop_setextattr_args /* { 2554 struct vnode *a_vp; 2555 int a_attrnamespace; 2556 const char *a_name; 2557 struct uio *a_uio; 2558 kauth_cred_t a_cred; 2559 struct proc *a_p; 2560 } */ *ap = v; 2561 struct vnode *vp = ap->a_vp; 2562 struct inode *ip; 2563 struct ulfsmount *ump; 2564 int error; 2565 2566 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2567 2568 ip = VTOI(vp); 2569 ump = ip->i_ump; 2570 2571 if (ump->um_fstype == ULFS1) { 2572 #ifdef LFS_EXTATTR 2573 error = ulfs_setextattr(ap); 2574 #else 2575 error = EOPNOTSUPP; 2576 #endif 2577 return error; 2578 } 2579 2580 /* XXX Not implemented for ULFS2 file systems. */ 2581 return (EOPNOTSUPP); 2582 } 2583 2584 static int 2585 lfs_listextattr(void *v) 2586 { 2587 struct vop_listextattr_args /* { 2588 struct vnode *a_vp; 2589 int a_attrnamespace; 2590 struct uio *a_uio; 2591 size_t *a_size; 2592 kauth_cred_t a_cred; 2593 struct proc *a_p; 2594 } */ *ap = v; 2595 struct vnode *vp = ap->a_vp; 2596 struct inode *ip; 2597 struct ulfsmount *ump; 2598 int error; 2599 2600 KASSERT(VOP_ISLOCKED(vp)); 2601 2602 ip = VTOI(vp); 2603 ump = ip->i_ump; 2604 2605 if (ump->um_fstype == ULFS1) { 2606 #ifdef LFS_EXTATTR 2607 error = ulfs_listextattr(ap); 2608 #else 2609 error = EOPNOTSUPP; 2610 #endif 2611 return error; 2612 } 2613 2614 /* XXX Not implemented for ULFS2 file systems. */ 2615 return (EOPNOTSUPP); 2616 } 2617 2618 static int 2619 lfs_deleteextattr(void *v) 2620 { 2621 struct vop_deleteextattr_args /* { 2622 struct vnode *a_vp; 2623 int a_attrnamespace; 2624 kauth_cred_t a_cred; 2625 struct proc *a_p; 2626 } */ *ap = v; 2627 struct vnode *vp = ap->a_vp; 2628 struct inode *ip; 2629 struct ulfsmount *ump; 2630 int error; 2631 2632 KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); 2633 2634 ip = VTOI(vp); 2635 ump = ip->i_ump; 2636 2637 if (ump->um_fstype == ULFS1) { 2638 #ifdef LFS_EXTATTR 2639 error = ulfs_deleteextattr(ap); 2640 #else 2641 error = EOPNOTSUPP; 2642 #endif 2643 return error; 2644 } 2645 2646 /* XXX Not implemented for ULFS2 file systems. */ 2647 return (EOPNOTSUPP); 2648 } 2649 2650