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