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