1 1.138 chs /* $NetBSD: ffs_vnops.c,v 1.138 2021/12/14 11:06:12 chs Exp $ */ 2 1.100 simonb 3 1.100 simonb /*- 4 1.109 ad * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 1.100 simonb * All rights reserved. 6 1.100 simonb * 7 1.100 simonb * This code is derived from software contributed to The NetBSD Foundation 8 1.109 ad * by Wasabi Systems, Inc, and by Andrew Doran. 9 1.100 simonb * 10 1.100 simonb * Redistribution and use in source and binary forms, with or without 11 1.100 simonb * modification, are permitted provided that the following conditions 12 1.100 simonb * are met: 13 1.100 simonb * 1. Redistributions of source code must retain the above copyright 14 1.100 simonb * notice, this list of conditions and the following disclaimer. 15 1.100 simonb * 2. Redistributions in binary form must reproduce the above copyright 16 1.100 simonb * notice, this list of conditions and the following disclaimer in the 17 1.100 simonb * documentation and/or other materials provided with the distribution. 18 1.100 simonb * 19 1.100 simonb * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.100 simonb * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.100 simonb * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.100 simonb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.100 simonb * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.100 simonb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.100 simonb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.100 simonb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.100 simonb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.100 simonb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.100 simonb * POSSIBILITY OF SUCH DAMAGE. 30 1.100 simonb */ 31 1.3 cgd 32 1.1 mycroft /* 33 1.1 mycroft * Copyright (c) 1982, 1986, 1989, 1993 34 1.1 mycroft * The Regents of the University of California. All rights reserved. 35 1.1 mycroft * 36 1.1 mycroft * Redistribution and use in source and binary forms, with or without 37 1.1 mycroft * modification, are permitted provided that the following conditions 38 1.1 mycroft * are met: 39 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 40 1.1 mycroft * notice, this list of conditions and the following disclaimer. 41 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 43 1.1 mycroft * documentation and/or other materials provided with the distribution. 44 1.60 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 mycroft * may be used to endorse or promote products derived from this software 46 1.1 mycroft * without specific prior written permission. 47 1.1 mycroft * 48 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 mycroft * SUCH DAMAGE. 59 1.1 mycroft * 60 1.12 fvdl * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 61 1.1 mycroft */ 62 1.44 lukem 63 1.44 lukem #include <sys/cdefs.h> 64 1.138 chs __KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.138 2021/12/14 11:06:12 chs Exp $"); 65 1.100 simonb 66 1.100 simonb #if defined(_KERNEL_OPT) 67 1.100 simonb #include "opt_ffs.h" 68 1.100 simonb #include "opt_wapbl.h" 69 1.100 simonb #endif 70 1.11 mrg 71 1.1 mycroft #include <sys/param.h> 72 1.1 mycroft #include <sys/systm.h> 73 1.1 mycroft #include <sys/resourcevar.h> 74 1.1 mycroft #include <sys/kernel.h> 75 1.1 mycroft #include <sys/file.h> 76 1.1 mycroft #include <sys/stat.h> 77 1.1 mycroft #include <sys/buf.h> 78 1.50 jdolecek #include <sys/event.h> 79 1.1 mycroft #include <sys/proc.h> 80 1.1 mycroft #include <sys/mount.h> 81 1.1 mycroft #include <sys/vnode.h> 82 1.16 thorpej #include <sys/pool.h> 83 1.6 christos #include <sys/signalvar.h> 84 1.80 elad #include <sys/kauth.h> 85 1.100 simonb #include <sys/wapbl.h> 86 1.1 mycroft 87 1.8 mycroft #include <miscfs/fifofs/fifo.h> 88 1.8 mycroft #include <miscfs/genfs/genfs.h> 89 1.1 mycroft #include <miscfs/specfs/specdev.h> 90 1.1 mycroft 91 1.132 christos #include <ufs/ufs/acl.h> 92 1.1 mycroft #include <ufs/ufs/inode.h> 93 1.1 mycroft #include <ufs/ufs/dir.h> 94 1.1 mycroft #include <ufs/ufs/ufs_extern.h> 95 1.2 mycroft #include <ufs/ufs/ufsmount.h> 96 1.100 simonb #include <ufs/ufs/ufs_wapbl.h> 97 1.1 mycroft 98 1.1 mycroft #include <ufs/ffs/fs.h> 99 1.1 mycroft #include <ufs/ffs/ffs_extern.h> 100 1.1 mycroft 101 1.1 mycroft /* Global vfs data structures for ufs. */ 102 1.74 xtraeme int (**ffs_vnodeop_p)(void *); 103 1.37 jdolecek const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { 104 1.1 mycroft { &vop_default_desc, vn_default_error }, 105 1.134 dholland { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ 106 1.1 mycroft { &vop_lookup_desc, ufs_lookup }, /* lookup */ 107 1.1 mycroft { &vop_create_desc, ufs_create }, /* create */ 108 1.5 mycroft { &vop_whiteout_desc, ufs_whiteout }, /* whiteout */ 109 1.1 mycroft { &vop_mknod_desc, ufs_mknod }, /* mknod */ 110 1.1 mycroft { &vop_open_desc, ufs_open }, /* open */ 111 1.1 mycroft { &vop_close_desc, ufs_close }, /* close */ 112 1.132 christos { &vop_access_desc, genfs_access }, /* access */ 113 1.132 christos { &vop_accessx_desc, ufs_accessx }, /* accessx */ 114 1.1 mycroft { &vop_getattr_desc, ufs_getattr }, /* getattr */ 115 1.1 mycroft { &vop_setattr_desc, ufs_setattr }, /* setattr */ 116 1.1 mycroft { &vop_read_desc, ffs_read }, /* read */ 117 1.1 mycroft { &vop_write_desc, ffs_write }, /* write */ 118 1.125 dholland { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 119 1.125 dholland { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 120 1.137 dholland { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ 121 1.137 dholland { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 122 1.137 dholland { &vop_poll_desc, genfs_poll }, /* poll */ 123 1.50 jdolecek { &vop_kqfilter_desc, genfs_kqfilter }, /* kqfilter */ 124 1.137 dholland { &vop_revoke_desc, genfs_revoke }, /* revoke */ 125 1.137 dholland { &vop_mmap_desc, genfs_mmap }, /* mmap */ 126 1.1 mycroft { &vop_fsync_desc, ffs_fsync }, /* fsync */ 127 1.137 dholland { &vop_seek_desc, genfs_seek }, /* seek */ 128 1.1 mycroft { &vop_remove_desc, ufs_remove }, /* remove */ 129 1.1 mycroft { &vop_link_desc, ufs_link }, /* link */ 130 1.1 mycroft { &vop_rename_desc, ufs_rename }, /* rename */ 131 1.1 mycroft { &vop_mkdir_desc, ufs_mkdir }, /* mkdir */ 132 1.1 mycroft { &vop_rmdir_desc, ufs_rmdir }, /* rmdir */ 133 1.1 mycroft { &vop_symlink_desc, ufs_symlink }, /* symlink */ 134 1.1 mycroft { &vop_readdir_desc, ufs_readdir }, /* readdir */ 135 1.1 mycroft { &vop_readlink_desc, ufs_readlink }, /* readlink */ 136 1.137 dholland { &vop_abortop_desc, genfs_abortop }, /* abortop */ 137 1.1 mycroft { &vop_inactive_desc, ufs_inactive }, /* inactive */ 138 1.1 mycroft { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ 139 1.137 dholland { &vop_lock_desc, genfs_lock }, /* lock */ 140 1.137 dholland { &vop_unlock_desc, genfs_unlock }, /* unlock */ 141 1.1 mycroft { &vop_bmap_desc, ufs_bmap }, /* bmap */ 142 1.1 mycroft { &vop_strategy_desc, ufs_strategy }, /* strategy */ 143 1.1 mycroft { &vop_print_desc, ufs_print }, /* print */ 144 1.137 dholland { &vop_islocked_desc, genfs_islocked }, /* islocked */ 145 1.1 mycroft { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ 146 1.1 mycroft { &vop_advlock_desc, ufs_advlock }, /* advlock */ 147 1.8 mycroft { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 148 1.88 yamt { &vop_getpages_desc, genfs_getpages }, /* getpages */ 149 1.75 yamt { &vop_putpages_desc, genfs_putpages }, /* putpages */ 150 1.73 thorpej { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ 151 1.73 thorpej { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ 152 1.73 thorpej { &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ 153 1.73 thorpej { &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ 154 1.73 thorpej { &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ 155 1.73 thorpej { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ 156 1.132 christos { &vop_getacl_desc, ufs_getacl }, /* getacl */ 157 1.132 christos { &vop_setacl_desc, ufs_setacl }, /* setacl */ 158 1.132 christos { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */ 159 1.35 chs { NULL, NULL } 160 1.1 mycroft }; 161 1.37 jdolecek const struct vnodeopv_desc ffs_vnodeop_opv_desc = 162 1.1 mycroft { &ffs_vnodeop_p, ffs_vnodeop_entries }; 163 1.1 mycroft 164 1.74 xtraeme int (**ffs_specop_p)(void *); 165 1.37 jdolecek const struct vnodeopv_entry_desc ffs_specop_entries[] = { 166 1.1 mycroft { &vop_default_desc, vn_default_error }, 167 1.136 dholland GENFS_SPECOP_ENTRIES, 168 1.1 mycroft { &vop_close_desc, ufsspec_close }, /* close */ 169 1.132 christos { &vop_access_desc, genfs_access }, /* access */ 170 1.132 christos { &vop_accessx_desc, ufs_accessx }, /* accessx */ 171 1.1 mycroft { &vop_getattr_desc, ufs_getattr }, /* getattr */ 172 1.1 mycroft { &vop_setattr_desc, ufs_setattr }, /* setattr */ 173 1.1 mycroft { &vop_read_desc, ufsspec_read }, /* read */ 174 1.1 mycroft { &vop_write_desc, ufsspec_write }, /* write */ 175 1.137 dholland { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 176 1.118 hannken { &vop_fsync_desc, ffs_spec_fsync }, /* fsync */ 177 1.1 mycroft { &vop_inactive_desc, ufs_inactive }, /* inactive */ 178 1.1 mycroft { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ 179 1.137 dholland { &vop_lock_desc, genfs_lock }, /* lock */ 180 1.137 dholland { &vop_unlock_desc, genfs_unlock }, /* unlock */ 181 1.1 mycroft { &vop_print_desc, ufs_print }, /* print */ 182 1.137 dholland { &vop_islocked_desc, genfs_islocked }, /* islocked */ 183 1.8 mycroft { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 184 1.73 thorpej { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ 185 1.73 thorpej { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ 186 1.73 thorpej { &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ 187 1.73 thorpej { &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ 188 1.73 thorpej { &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ 189 1.73 thorpej { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ 190 1.132 christos { &vop_getacl_desc, ufs_getacl }, /* getacl */ 191 1.132 christos { &vop_setacl_desc, ufs_setacl }, /* setacl */ 192 1.132 christos { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */ 193 1.35 chs { NULL, NULL } 194 1.1 mycroft }; 195 1.37 jdolecek const struct vnodeopv_desc ffs_specop_opv_desc = 196 1.1 mycroft { &ffs_specop_p, ffs_specop_entries }; 197 1.1 mycroft 198 1.74 xtraeme int (**ffs_fifoop_p)(void *); 199 1.37 jdolecek const struct vnodeopv_entry_desc ffs_fifoop_entries[] = { 200 1.1 mycroft { &vop_default_desc, vn_default_error }, 201 1.136 dholland GENFS_FIFOOP_ENTRIES, 202 1.1 mycroft { &vop_close_desc, ufsfifo_close }, /* close */ 203 1.132 christos { &vop_access_desc, genfs_access }, /* access */ 204 1.132 christos { &vop_accessx_desc, ufs_accessx }, /* accessx */ 205 1.1 mycroft { &vop_getattr_desc, ufs_getattr }, /* getattr */ 206 1.1 mycroft { &vop_setattr_desc, ufs_setattr }, /* setattr */ 207 1.1 mycroft { &vop_read_desc, ufsfifo_read }, /* read */ 208 1.1 mycroft { &vop_write_desc, ufsfifo_write }, /* write */ 209 1.137 dholland { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 210 1.1 mycroft { &vop_fsync_desc, ffs_fsync }, /* fsync */ 211 1.1 mycroft { &vop_inactive_desc, ufs_inactive }, /* inactive */ 212 1.1 mycroft { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ 213 1.137 dholland { &vop_lock_desc, genfs_lock }, /* lock */ 214 1.137 dholland { &vop_unlock_desc, genfs_unlock }, /* unlock */ 215 1.138 chs { &vop_bmap_desc, ufs_bmap }, /* bmap */ 216 1.135 christos { &vop_strategy_desc, ffsext_strategy }, /* strategy */ 217 1.1 mycroft { &vop_print_desc, ufs_print }, /* print */ 218 1.137 dholland { &vop_islocked_desc, genfs_islocked }, /* islocked */ 219 1.138 chs { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ 220 1.8 mycroft { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 221 1.73 thorpej { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ 222 1.73 thorpej { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ 223 1.73 thorpej { &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ 224 1.73 thorpej { &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ 225 1.73 thorpej { &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ 226 1.73 thorpej { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ 227 1.132 christos { &vop_getacl_desc, ufs_getacl }, /* getacl */ 228 1.132 christos { &vop_setacl_desc, ufs_setacl }, /* setacl */ 229 1.132 christos { &vop_aclcheck_desc, ufs_aclcheck }, /* aclcheck */ 230 1.35 chs { NULL, NULL } 231 1.1 mycroft }; 232 1.37 jdolecek const struct vnodeopv_desc ffs_fifoop_opv_desc = 233 1.1 mycroft { &ffs_fifoop_p, ffs_fifoop_entries }; 234 1.1 mycroft 235 1.1 mycroft #include <ufs/ufs/ufs_readwrite.c> 236 1.20 fvdl 237 1.33 fvdl int 238 1.118 hannken ffs_spec_fsync(void *v) 239 1.118 hannken { 240 1.118 hannken struct vop_fsync_args /* { 241 1.118 hannken struct vnode *a_vp; 242 1.118 hannken kauth_cred_t a_cred; 243 1.118 hannken int a_flags; 244 1.118 hannken off_t a_offlo; 245 1.118 hannken off_t a_offhi; 246 1.118 hannken struct lwp *a_l; 247 1.118 hannken } */ *ap = v; 248 1.118 hannken int error, flags, uflags; 249 1.118 hannken struct vnode *vp; 250 1.118 hannken 251 1.118 hannken flags = ap->a_flags; 252 1.118 hannken uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0); 253 1.118 hannken vp = ap->a_vp; 254 1.118 hannken 255 1.118 hannken error = spec_fsync(v); 256 1.118 hannken if (error) 257 1.118 hannken goto out; 258 1.118 hannken 259 1.118 hannken #ifdef WAPBL 260 1.128 christos struct mount *mp = vp->v_mount; 261 1.128 christos 262 1.118 hannken if (mp && mp->mnt_wapbl) { 263 1.118 hannken /* 264 1.118 hannken * Don't bother writing out metadata if the syncer is 265 1.118 hannken * making the request. We will let the sync vnode 266 1.118 hannken * write it out in a single burst through a call to 267 1.118 hannken * VFS_SYNC(). 268 1.118 hannken */ 269 1.118 hannken if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) 270 1.118 hannken goto out; 271 1.118 hannken if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE 272 1.118 hannken | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) { 273 1.118 hannken error = UFS_WAPBL_BEGIN(mp); 274 1.118 hannken if (error != 0) 275 1.118 hannken goto out; 276 1.118 hannken error = ffs_update(vp, NULL, NULL, uflags); 277 1.118 hannken UFS_WAPBL_END(mp); 278 1.118 hannken } 279 1.118 hannken goto out; 280 1.118 hannken } 281 1.118 hannken #endif /* WAPBL */ 282 1.118 hannken 283 1.118 hannken error = ffs_update(vp, NULL, NULL, uflags); 284 1.118 hannken 285 1.118 hannken out: 286 1.118 hannken return error; 287 1.118 hannken } 288 1.118 hannken 289 1.118 hannken int 290 1.70 thorpej ffs_fsync(void *v) 291 1.33 fvdl { 292 1.33 fvdl struct vop_fsync_args /* { 293 1.33 fvdl struct vnode *a_vp; 294 1.80 elad kauth_cred_t a_cred; 295 1.33 fvdl int a_flags; 296 1.46 chs off_t a_offlo; 297 1.46 chs off_t a_offhi; 298 1.77 christos struct lwp *a_l; 299 1.33 fvdl } */ *ap = v; 300 1.35 chs struct buf *bp; 301 1.94 ad int num, error, i; 302 1.122 dholland struct indir ia[UFS_NIADDR + 1]; 303 1.33 fvdl int bsize; 304 1.45 simonb daddr_t blk_high; 305 1.33 fvdl struct vnode *vp; 306 1.100 simonb struct mount *mp; 307 1.33 fvdl 308 1.84 hannken vp = ap->a_vp; 309 1.117 hannken mp = vp->v_mount; 310 1.84 hannken 311 1.111 ad if ((ap->a_offlo == 0 && ap->a_offhi == 0) || (vp->v_type != VREG)) { 312 1.111 ad error = ffs_full_fsync(vp, ap->a_flags); 313 1.84 hannken goto out; 314 1.84 hannken } 315 1.33 fvdl 316 1.117 hannken bsize = mp->mnt_stat.f_iosize; 317 1.33 fvdl blk_high = ap->a_offhi / bsize; 318 1.33 fvdl if (ap->a_offhi % bsize != 0) 319 1.33 fvdl blk_high++; 320 1.33 fvdl 321 1.33 fvdl /* 322 1.35 chs * First, flush all pages in range. 323 1.33 fvdl */ 324 1.35 chs 325 1.130 ad rw_enter(vp->v_uobj.vmobjlock, RW_WRITER); 326 1.64 dbj error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo), 327 1.64 dbj round_page(ap->a_offhi), PGO_CLEANIT | 328 1.64 dbj ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0)); 329 1.64 dbj if (error) { 330 1.84 hannken goto out; 331 1.39 chs } 332 1.33 fvdl 333 1.100 simonb #ifdef WAPBL 334 1.117 hannken KASSERT(vp->v_type == VREG); 335 1.100 simonb if (mp->mnt_wapbl) { 336 1.110 ad /* 337 1.110 ad * Don't bother writing out metadata if the syncer is 338 1.110 ad * making the request. We will let the sync vnode 339 1.110 ad * write it out in a single burst through a call to 340 1.110 ad * VFS_SYNC(). 341 1.110 ad */ 342 1.110 ad if ((ap->a_flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) { 343 1.100 simonb return 0; 344 1.100 simonb } 345 1.100 simonb error = 0; 346 1.100 simonb if (vp->v_tag == VT_UFS && VTOI(vp)->i_flag & 347 1.100 simonb (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY | 348 1.100 simonb IN_MODIFIED | IN_ACCESSED)) { 349 1.100 simonb error = UFS_WAPBL_BEGIN(mp); 350 1.100 simonb if (error) { 351 1.100 simonb return error; 352 1.100 simonb } 353 1.112 ad error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE | 354 1.112 ad ((ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0)); 355 1.100 simonb UFS_WAPBL_END(mp); 356 1.100 simonb } 357 1.110 ad if (error || (ap->a_flags & FSYNC_NOLOG) != 0) { 358 1.100 simonb return error; 359 1.100 simonb } 360 1.100 simonb error = wapbl_flush(mp->mnt_wapbl, 0); 361 1.100 simonb return error; 362 1.100 simonb } 363 1.100 simonb #endif /* WAPBL */ 364 1.100 simonb 365 1.33 fvdl /* 366 1.35 chs * Then, flush indirect blocks. 367 1.33 fvdl */ 368 1.35 chs 369 1.122 dholland if (blk_high >= UFS_NDADDR) { 370 1.33 fvdl error = ufs_getlbns(vp, blk_high, ia, &num); 371 1.94 ad if (error) 372 1.84 hannken goto out; 373 1.94 ad 374 1.94 ad mutex_enter(&bufcache_lock); 375 1.33 fvdl for (i = 0; i < num; i++) { 376 1.94 ad if ((bp = incore(vp, ia[i].in_lbn)) == NULL) 377 1.94 ad continue; 378 1.94 ad if ((bp->b_cflags & BC_BUSY) != 0 || 379 1.94 ad (bp->b_oflags & BO_DELWRI) == 0) 380 1.94 ad continue; 381 1.94 ad bp->b_cflags |= BC_BUSY | BC_VFLUSH; 382 1.94 ad mutex_exit(&bufcache_lock); 383 1.94 ad bawrite(bp); 384 1.94 ad mutex_enter(&bufcache_lock); 385 1.33 fvdl } 386 1.94 ad mutex_exit(&bufcache_lock); 387 1.33 fvdl } 388 1.33 fvdl 389 1.33 fvdl if (ap->a_flags & FSYNC_WAIT) { 390 1.119 rmind mutex_enter(vp->v_interlock); 391 1.94 ad while (vp->v_numoutput > 0) 392 1.119 rmind cv_wait(&vp->v_cv, vp->v_interlock); 393 1.119 rmind mutex_exit(vp->v_interlock); 394 1.33 fvdl } 395 1.33 fvdl 396 1.112 ad error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE | 397 1.112 ad (((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) == FSYNC_WAIT) 398 1.112 ad ? UPDATE_WAIT : 0)); 399 1.67 wrstuden 400 1.67 wrstuden if (error == 0 && ap->a_flags & FSYNC_CACHE) { 401 1.67 wrstuden int l = 0; 402 1.67 wrstuden VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE, 403 1.93 pooka curlwp->l_cred); 404 1.67 wrstuden } 405 1.67 wrstuden 406 1.84 hannken out: 407 1.67 wrstuden return error; 408 1.33 fvdl } 409 1.33 fvdl 410 1.20 fvdl /* 411 1.110 ad * Synch an open file. Called for VOP_FSYNC(). 412 1.20 fvdl */ 413 1.20 fvdl /* ARGSUSED */ 414 1.94 ad int 415 1.94 ad ffs_full_fsync(struct vnode *vp, int flags) 416 1.20 fvdl { 417 1.118 hannken int error, i, uflags; 418 1.99 ad 419 1.118 hannken KASSERT(vp->v_tag == VT_UFS); 420 1.110 ad KASSERT(VTOI(vp) != NULL); 421 1.118 hannken KASSERT(vp->v_type != VCHR && vp->v_type != VBLK); 422 1.110 ad 423 1.118 hannken uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0); 424 1.24 fvdl 425 1.121 chs #ifdef WAPBL 426 1.121 chs struct mount *mp = vp->v_mount; 427 1.128 christos 428 1.121 chs if (mp && mp->mnt_wapbl) { 429 1.105 ad 430 1.121 chs /* 431 1.121 chs * Flush all dirty data associated with the vnode. 432 1.121 chs */ 433 1.121 chs if (vp->v_type == VREG) { 434 1.121 chs int pflags = PGO_ALLPAGES | PGO_CLEANIT; 435 1.101 oster 436 1.121 chs if ((flags & FSYNC_LAZY)) 437 1.121 chs pflags |= PGO_LAZY; 438 1.121 chs if ((flags & FSYNC_WAIT)) 439 1.121 chs pflags |= PGO_SYNCIO; 440 1.130 ad rw_enter(vp->v_uobj.vmobjlock, RW_WRITER); 441 1.121 chs error = VOP_PUTPAGES(vp, 0, 0, pflags); 442 1.121 chs if (error) 443 1.121 chs return error; 444 1.121 chs } 445 1.100 simonb 446 1.110 ad /* 447 1.110 ad * Don't bother writing out metadata if the syncer is 448 1.110 ad * making the request. We will let the sync vnode 449 1.110 ad * write it out in a single burst through a call to 450 1.110 ad * VFS_SYNC(). 451 1.110 ad */ 452 1.110 ad if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) 453 1.110 ad return 0; 454 1.100 simonb 455 1.110 ad if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE 456 1.109 ad | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) { 457 1.100 simonb error = UFS_WAPBL_BEGIN(mp); 458 1.100 simonb if (error) 459 1.100 simonb return error; 460 1.118 hannken error = ffs_update(vp, NULL, NULL, uflags); 461 1.100 simonb UFS_WAPBL_END(mp); 462 1.121 chs } else { 463 1.121 chs error = 0; 464 1.100 simonb } 465 1.110 ad if (error || (flags & FSYNC_NOLOG) != 0) 466 1.100 simonb return error; 467 1.106 ad 468 1.100 simonb /* 469 1.100 simonb * Don't flush the log if the vnode being flushed 470 1.100 simonb * contains no dirty buffers that could be in the log. 471 1.100 simonb */ 472 1.109 ad if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { 473 1.100 simonb error = wapbl_flush(mp->mnt_wapbl, 0); 474 1.100 simonb if (error) 475 1.100 simonb return error; 476 1.100 simonb } 477 1.100 simonb 478 1.109 ad if ((flags & FSYNC_WAIT) != 0) { 479 1.119 rmind mutex_enter(vp->v_interlock); 480 1.110 ad while (vp->v_numoutput != 0) 481 1.119 rmind cv_wait(&vp->v_cv, vp->v_interlock); 482 1.119 rmind mutex_exit(vp->v_interlock); 483 1.100 simonb } 484 1.100 simonb 485 1.100 simonb return error; 486 1.100 simonb } 487 1.100 simonb #endif /* WAPBL */ 488 1.35 chs 489 1.121 chs error = vflushbuf(vp, flags); 490 1.118 hannken if (error == 0) 491 1.118 hannken error = ffs_update(vp, NULL, NULL, uflags); 492 1.109 ad if (error == 0 && (flags & FSYNC_CACHE) != 0) { 493 1.118 hannken i = 1; 494 1.110 ad (void)VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE, 495 1.110 ad kauth_cred_get()); 496 1.67 wrstuden } 497 1.67 wrstuden 498 1.67 wrstuden return error; 499 1.20 fvdl } 500 1.1 mycroft 501 1.1 mycroft /* 502 1.1 mycroft * Reclaim an inode so that it can be used for other purposes. 503 1.1 mycroft */ 504 1.1 mycroft int 505 1.70 thorpej ffs_reclaim(void *v) 506 1.6 christos { 507 1.129 riastrad struct vop_reclaim_v2_args /* { 508 1.1 mycroft struct vnode *a_vp; 509 1.77 christos struct lwp *a_l; 510 1.6 christos } */ *ap = v; 511 1.26 augustss struct vnode *vp = ap->a_vp; 512 1.56 fvdl struct inode *ip = VTOI(vp); 513 1.84 hannken struct mount *mp = vp->v_mount; 514 1.56 fvdl struct ufsmount *ump = ip->i_ump; 515 1.94 ad void *data; 516 1.1 mycroft int error; 517 1.1 mycroft 518 1.129 riastrad VOP_UNLOCK(vp); 519 1.129 riastrad 520 1.115 hannken /* 521 1.115 hannken * The inode must be freed and updated before being removed 522 1.115 hannken * from its hash chain. Other threads trying to gain a hold 523 1.124 hannken * or lock on the inode will be stalled. 524 1.115 hannken */ 525 1.115 hannken error = UFS_WAPBL_BEGIN(mp); 526 1.115 hannken if (error) { 527 1.115 hannken return error; 528 1.115 hannken } 529 1.116 hannken if (ip->i_nlink <= 0 && ip->i_omode != 0 && 530 1.116 hannken (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 531 1.115 hannken ffs_vfree(vp, ip->i_number, ip->i_omode); 532 1.115 hannken UFS_WAPBL_END(mp); 533 1.93 pooka if ((error = ufs_reclaim(vp)) != 0) { 534 1.1 mycroft return (error); 535 1.84 hannken } 536 1.57 fvdl if (ip->i_din.ffs1_din != NULL) { 537 1.57 fvdl if (ump->um_fstype == UFS1) 538 1.95 ad pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din); 539 1.57 fvdl else 540 1.95 ad pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din); 541 1.57 fvdl } 542 1.16 thorpej /* 543 1.94 ad * To interlock with ffs_sync(). 544 1.94 ad */ 545 1.94 ad genfs_node_destroy(vp); 546 1.119 rmind mutex_enter(vp->v_interlock); 547 1.94 ad data = vp->v_data; 548 1.94 ad vp->v_data = NULL; 549 1.119 rmind mutex_exit(vp->v_interlock); 550 1.94 ad 551 1.94 ad /* 552 1.16 thorpej * XXX MFS ends up here, too, to free an inode. Should we create 553 1.16 thorpej * XXX a separate pool for MFS inodes? 554 1.16 thorpej */ 555 1.95 ad pool_cache_put(ffs_inode_cache, data); 556 1.1 mycroft return (0); 557 1.35 chs } 558 1.35 chs 559 1.35 chs /* 560 1.35 chs * Return the last logical file offset that should be written for this file 561 1.35 chs * if we're doing a write that ends at "size". 562 1.35 chs */ 563 1.39 chs 564 1.39 chs void 565 1.83 christos ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 566 1.35 chs { 567 1.39 chs struct inode *ip = VTOI(vp); 568 1.35 chs struct fs *fs = ip->i_fs; 569 1.52 fvdl daddr_t olbn, nlbn; 570 1.55 perseant 571 1.123 dholland olbn = ffs_lblkno(fs, ip->i_size); 572 1.123 dholland nlbn = ffs_lblkno(fs, size); 573 1.122 dholland if (nlbn < UFS_NDADDR && olbn <= nlbn) { 574 1.123 dholland *eobp = ffs_fragroundup(fs, size); 575 1.35 chs } else { 576 1.123 dholland *eobp = ffs_blkroundup(fs, size); 577 1.35 chs } 578 1.1 mycroft } 579