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