1 1.176 chs /* $NetBSD: lfs_syscalls.c,v 1.176 2020/02/18 20:23:17 chs Exp $ */ 2 1.3 cgd 3 1.1 mycroft /*- 4 1.129 ad * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007, 2008 5 1.128 ad * The NetBSD Foundation, Inc. 6 1.22 perseant * All rights reserved. 7 1.22 perseant * 8 1.22 perseant * This code is derived from software contributed to The NetBSD Foundation 9 1.22 perseant * by Konrad E. Schroder <perseant (at) hhhh.org>. 10 1.22 perseant * 11 1.22 perseant * Redistribution and use in source and binary forms, with or without 12 1.22 perseant * modification, are permitted provided that the following conditions 13 1.22 perseant * are met: 14 1.22 perseant * 1. Redistributions of source code must retain the above copyright 15 1.22 perseant * notice, this list of conditions and the following disclaimer. 16 1.22 perseant * 2. Redistributions in binary form must reproduce the above copyright 17 1.22 perseant * notice, this list of conditions and the following disclaimer in the 18 1.22 perseant * documentation and/or other materials provided with the distribution. 19 1.22 perseant * 20 1.22 perseant * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.22 perseant * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.22 perseant * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.22 perseant * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.22 perseant * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.22 perseant * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.22 perseant * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.22 perseant * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.22 perseant * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.22 perseant * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.22 perseant * POSSIBILITY OF SUCH DAMAGE. 31 1.22 perseant */ 32 1.22 perseant /*- 33 1.1 mycroft * Copyright (c) 1991, 1993, 1994 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.97 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.16 fvdl * @(#)lfs_syscalls.c 8.10 (Berkeley) 5/14/95 61 1.1 mycroft */ 62 1.61 lukem 63 1.61 lukem #include <sys/cdefs.h> 64 1.176 chs __KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.176 2020/02/18 20:23:17 chs Exp $"); 65 1.15 thorpej 66 1.86 perseant #ifndef LFS 67 1.86 perseant # define LFS /* for prototypes in syscallargs.h */ 68 1.86 perseant #endif 69 1.1 mycroft 70 1.1 mycroft #include <sys/param.h> 71 1.5 cgd #include <sys/systm.h> 72 1.1 mycroft #include <sys/proc.h> 73 1.1 mycroft #include <sys/buf.h> 74 1.1 mycroft #include <sys/mount.h> 75 1.1 mycroft #include <sys/vnode.h> 76 1.1 mycroft #include <sys/kernel.h> 77 1.113 elad #include <sys/kauth.h> 78 1.5 cgd #include <sys/syscallargs.h> 79 1.5 cgd 80 1.145 dholland #include <ufs/lfs/ulfs_inode.h> 81 1.145 dholland #include <ufs/lfs/ulfsmount.h> 82 1.145 dholland #include <ufs/lfs/ulfs_extern.h> 83 1.1 mycroft 84 1.1 mycroft #include <ufs/lfs/lfs.h> 85 1.163 dholland #include <ufs/lfs/lfs_accessors.h> 86 1.148 dholland #include <ufs/lfs/lfs_kernel.h> 87 1.1 mycroft #include <ufs/lfs/lfs_extern.h> 88 1.10 christos 89 1.160 hannken static int lfs_fastvget(struct mount *, ino_t, BLOCK_INFO *, int, 90 1.160 hannken struct vnode **); 91 1.165 dholland static struct buf *lfs_fakebuf(struct lfs *, struct vnode *, daddr_t, 92 1.165 dholland size_t, void *); 93 1.80 perseant 94 1.1 mycroft /* 95 1.31 christos * sys_lfs_markv: 96 1.1 mycroft * 97 1.1 mycroft * This will mark inodes and blocks dirty, so they are written into the log. 98 1.1 mycroft * It will block until all the blocks have been written. The segment create 99 1.1 mycroft * time passed in the block_info and inode_info structures is used to decide 100 1.1 mycroft * if the data is valid for each block (in case some process dirtied a block 101 1.1 mycroft * or inode that is being cleaned between the determination that a block is 102 1.1 mycroft * live and the lfs_markv call). 103 1.1 mycroft * 104 1.1 mycroft * 0 on success 105 1.1 mycroft * -1/errno is return on error. 106 1.1 mycroft */ 107 1.57 perseant #ifdef USE_64BIT_SYSCALLS 108 1.1 mycroft int 109 1.125 dsl sys_lfs_markv(struct lwp *l, const struct sys_lfs_markv_args *uap, register_t *retval) 110 1.9 thorpej { 111 1.125 dsl /* { 112 1.5 cgd syscallarg(fsid_t *) fsidp; 113 1.5 cgd syscallarg(struct block_info *) blkiov; 114 1.5 cgd syscallarg(int) blkcnt; 115 1.125 dsl } */ 116 1.57 perseant BLOCK_INFO *blkiov; 117 1.57 perseant int blkcnt, error; 118 1.57 perseant fsid_t fsid; 119 1.105 perseant struct lfs *fs; 120 1.105 perseant struct mount *mntp; 121 1.57 perseant 122 1.57 perseant if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 123 1.57 perseant return (error); 124 1.57 perseant 125 1.171 dholland if ((mntp = vfs_getvfs(&fsid)) == NULL) 126 1.105 perseant return (ENOENT); 127 1.146 dholland fs = VFSTOULFS(mntp)->um_lfs; 128 1.105 perseant 129 1.57 perseant blkcnt = SCARG(uap, blkcnt); 130 1.84 perseant if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT) 131 1.58 jdolecek return (EINVAL); 132 1.58 jdolecek 133 1.129 ad KERNEL_LOCK(1, NULL); 134 1.105 perseant blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 135 1.57 perseant if ((error = copyin(SCARG(uap, blkiov), blkiov, 136 1.57 perseant blkcnt * sizeof(BLOCK_INFO))) != 0) 137 1.57 perseant goto out; 138 1.57 perseant 139 1.171 dholland if ((error = lfs_markv(l, &fsid, blkiov, blkcnt)) == 0) 140 1.57 perseant copyout(blkiov, SCARG(uap, blkiov), 141 1.57 perseant blkcnt * sizeof(BLOCK_INFO)); 142 1.57 perseant out: 143 1.105 perseant lfs_free(fs, blkiov, LFS_NB_BLKIOV); 144 1.129 ad KERNEL_UNLOCK_ONE(NULL); 145 1.57 perseant return error; 146 1.57 perseant } 147 1.57 perseant #else 148 1.57 perseant int 149 1.125 dsl sys_lfs_markv(struct lwp *l, const struct sys_lfs_markv_args *uap, register_t *retval) 150 1.57 perseant { 151 1.125 dsl /* { 152 1.57 perseant syscallarg(fsid_t *) fsidp; 153 1.57 perseant syscallarg(struct block_info *) blkiov; 154 1.57 perseant syscallarg(int) blkcnt; 155 1.125 dsl } */ 156 1.57 perseant BLOCK_INFO *blkiov; 157 1.57 perseant BLOCK_INFO_15 *blkiov15; 158 1.57 perseant int i, blkcnt, error; 159 1.57 perseant fsid_t fsid; 160 1.105 perseant struct lfs *fs; 161 1.105 perseant struct mount *mntp; 162 1.57 perseant 163 1.57 perseant if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 164 1.57 perseant return (error); 165 1.57 perseant 166 1.105 perseant if ((mntp = vfs_getvfs(&fsid)) == NULL) 167 1.105 perseant return (ENOENT); 168 1.146 dholland fs = VFSTOULFS(mntp)->um_lfs; 169 1.105 perseant 170 1.57 perseant blkcnt = SCARG(uap, blkcnt); 171 1.84 perseant if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT) 172 1.58 jdolecek return (EINVAL); 173 1.58 jdolecek 174 1.129 ad KERNEL_LOCK(1, NULL); 175 1.105 perseant blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 176 1.105 perseant blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV); 177 1.57 perseant if ((error = copyin(SCARG(uap, blkiov), blkiov15, 178 1.57 perseant blkcnt * sizeof(BLOCK_INFO_15))) != 0) 179 1.57 perseant goto out; 180 1.57 perseant 181 1.57 perseant for (i = 0; i < blkcnt; i++) { 182 1.57 perseant blkiov[i].bi_inode = blkiov15[i].bi_inode; 183 1.57 perseant blkiov[i].bi_lbn = blkiov15[i].bi_lbn; 184 1.57 perseant blkiov[i].bi_daddr = blkiov15[i].bi_daddr; 185 1.57 perseant blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate; 186 1.57 perseant blkiov[i].bi_version = blkiov15[i].bi_version; 187 1.82 perseant blkiov[i].bi_bp = blkiov15[i].bi_bp; 188 1.57 perseant blkiov[i].bi_size = blkiov15[i].bi_size; 189 1.57 perseant } 190 1.57 perseant 191 1.166 dholland if ((error = lfs_markv(l, &fsid, blkiov, blkcnt)) == 0) { 192 1.57 perseant for (i = 0; i < blkcnt; i++) { 193 1.82 perseant blkiov15[i].bi_inode = blkiov[i].bi_inode; 194 1.82 perseant blkiov15[i].bi_lbn = blkiov[i].bi_lbn; 195 1.82 perseant blkiov15[i].bi_daddr = blkiov[i].bi_daddr; 196 1.57 perseant blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate; 197 1.82 perseant blkiov15[i].bi_version = blkiov[i].bi_version; 198 1.82 perseant blkiov15[i].bi_bp = blkiov[i].bi_bp; 199 1.82 perseant blkiov15[i].bi_size = blkiov[i].bi_size; 200 1.57 perseant } 201 1.57 perseant copyout(blkiov15, SCARG(uap, blkiov), 202 1.57 perseant blkcnt * sizeof(BLOCK_INFO_15)); 203 1.57 perseant } 204 1.57 perseant out: 205 1.105 perseant lfs_free(fs, blkiov, LFS_NB_BLKIOV); 206 1.105 perseant lfs_free(fs, blkiov15, LFS_NB_BLKIOV); 207 1.129 ad KERNEL_UNLOCK_ONE(NULL); 208 1.57 perseant return error; 209 1.57 perseant } 210 1.57 perseant #endif 211 1.57 perseant 212 1.77 yamt #define LFS_MARKV_MAX_BLOCKS (LFS_MAX_BUFS) 213 1.77 yamt 214 1.84 perseant int 215 1.166 dholland lfs_markv(struct lwp *l, fsid_t *fsidp, BLOCK_INFO *blkiov, 216 1.117 christos int blkcnt) 217 1.57 perseant { 218 1.1 mycroft BLOCK_INFO *blkp; 219 1.1 mycroft IFILE *ifp; 220 1.96 yamt struct buf *bp; 221 1.10 christos struct inode *ip = NULL; 222 1.1 mycroft struct lfs *fs; 223 1.1 mycroft struct mount *mntp; 224 1.159 hannken struct ulfsmount *ump; 225 1.159 hannken struct vnode *vp; 226 1.1 mycroft ino_t lastino; 227 1.159 hannken daddr_t b_daddr; 228 1.74 yamt int cnt, error; 229 1.62 chs int do_again = 0; 230 1.74 yamt int numrefed = 0; 231 1.49 perseant ino_t maxino; 232 1.69 perseant size_t obsize; 233 1.1 mycroft 234 1.77 yamt /* number of blocks/inodes that we have already bwrite'ed */ 235 1.77 yamt int nblkwritten, ninowritten; 236 1.77 yamt 237 1.166 dholland error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 238 1.166 dholland KAUTH_REQ_SYSTEM_LFS_MARKV, NULL, NULL, NULL); 239 1.166 dholland if (error) 240 1.166 dholland return (error); 241 1.166 dholland 242 1.57 perseant if ((mntp = vfs_getvfs(fsidp)) == NULL) 243 1.53 perseant return (ENOENT); 244 1.1 mycroft 245 1.159 hannken ump = VFSTOULFS(mntp); 246 1.159 hannken fs = ump->um_lfs; 247 1.96 yamt 248 1.96 yamt if (fs->lfs_ronly) 249 1.96 yamt return EROFS; 250 1.96 yamt 251 1.170 dholland maxino = (lfs_fragstoblks(fs, lfs_dino_getblocks(fs, VTOI(fs->lfs_ivnode)->i_din)) - 252 1.161 dholland lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs); 253 1.49 perseant 254 1.57 perseant cnt = blkcnt; 255 1.102 perry 256 1.174 hannken if ((error = vfs_busy(mntp)) != 0) 257 1.53 perseant return (error); 258 1.53 perseant 259 1.22 perseant /* 260 1.22 perseant * This seglock is just to prevent the fact that we might have to sleep 261 1.22 perseant * from allowing the possibility that our blocks might become 262 1.22 perseant * invalid. 263 1.22 perseant * 264 1.22 perseant * It is also important to note here that unless we specify SEGM_CKP, 265 1.22 perseant * any Ifile blocks that we might be asked to clean will never get 266 1.22 perseant * to the disk. 267 1.22 perseant */ 268 1.67 perseant lfs_seglock(fs, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC); 269 1.102 perry 270 1.1 mycroft /* Mark blocks/inodes dirty. */ 271 1.1 mycroft error = 0; 272 1.1 mycroft 273 1.22 perseant /* these were inside the initialization for the for loop */ 274 1.159 hannken vp = NULL; 275 1.22 perseant lastino = LFS_UNUSED_INUM; 276 1.77 yamt nblkwritten = ninowritten = 0; 277 1.57 perseant for (blkp = blkiov; cnt--; ++blkp) 278 1.22 perseant { 279 1.49 perseant /* Bounds-check incoming data, avoid panic for failed VGET */ 280 1.49 perseant if (blkp->bi_inode <= 0 || blkp->bi_inode >= maxino) { 281 1.49 perseant error = EINVAL; 282 1.96 yamt goto err3; 283 1.49 perseant } 284 1.1 mycroft /* 285 1.1 mycroft * Get the IFILE entry (only once) and see if the file still 286 1.1 mycroft * exists. 287 1.1 mycroft */ 288 1.1 mycroft if (lastino != blkp->bi_inode) { 289 1.22 perseant /* 290 1.159 hannken * Finish the old file, if there was one. 291 1.22 perseant */ 292 1.159 hannken if (vp != NULL) { 293 1.160 hannken vput(vp); 294 1.159 hannken vp = NULL; 295 1.22 perseant numrefed--; 296 1.1 mycroft } 297 1.1 mycroft 298 1.22 perseant /* 299 1.22 perseant * Start a new file 300 1.22 perseant */ 301 1.1 mycroft lastino = blkp->bi_inode; 302 1.1 mycroft 303 1.1 mycroft /* Get the vnode/inode. */ 304 1.159 hannken error = lfs_fastvget(mntp, blkp->bi_inode, blkp, 305 1.159 hannken LK_EXCLUSIVE | LK_NOWAIT, &vp); 306 1.62 chs if (error) { 307 1.103 perseant DLOG((DLOG_CLEAN, "lfs_markv: lfs_fastvget" 308 1.103 perseant " failed with %d (ino %d, segment %d)\n", 309 1.103 perseant error, blkp->bi_inode, 310 1.147 christos lfs_dtosn(fs, blkp->bi_daddr))); 311 1.22 perseant /* 312 1.22 perseant * If we got EAGAIN, that means that the 313 1.22 perseant * Inode was locked. This is 314 1.22 perseant * recoverable: just clean the rest of 315 1.22 perseant * this segment, and let the cleaner try 316 1.82 perseant * again with another. (When the 317 1.22 perseant * cleaner runs again, this segment will 318 1.22 perseant * sort high on the list, since it is 319 1.159 hannken * now almost entirely empty.) 320 1.22 perseant */ 321 1.62 chs if (error == EAGAIN) { 322 1.22 perseant error = 0; 323 1.22 perseant do_again++; 324 1.159 hannken } else 325 1.159 hannken KASSERT(error == ENOENT); 326 1.159 hannken KASSERT(vp == NULL); 327 1.22 perseant ip = NULL; 328 1.1 mycroft continue; 329 1.19 pk } 330 1.159 hannken 331 1.1 mycroft ip = VTOI(vp); 332 1.159 hannken numrefed++; 333 1.77 yamt ninowritten++; 334 1.159 hannken } else if (vp == NULL) { 335 1.22 perseant /* 336 1.22 perseant * This can only happen if the vnode is dead (or 337 1.22 perseant * in any case we can't get it...e.g., it is 338 1.22 perseant * inlocked). Keep going. 339 1.22 perseant */ 340 1.1 mycroft continue; 341 1.22 perseant } 342 1.22 perseant 343 1.22 perseant /* Past this point we are guaranteed that vp, ip are valid. */ 344 1.1 mycroft 345 1.124 ad /* Can't clean VU_DIROP directories in case of truncation */ 346 1.116 perseant /* XXX - maybe we should mark removed dirs specially? */ 347 1.124 ad if (vp->v_type == VDIR && (vp->v_uflag & VU_DIROP)) { 348 1.116 perseant do_again++; 349 1.116 perseant continue; 350 1.116 perseant } 351 1.116 perseant 352 1.1 mycroft /* If this BLOCK_INFO didn't contain a block, keep going. */ 353 1.22 perseant if (blkp->bi_lbn == LFS_UNUSED_LBN) { 354 1.22 perseant /* XXX need to make sure that the inode gets written in this case */ 355 1.22 perseant /* XXX but only write the inode if it's the right one */ 356 1.53 perseant if (blkp->bi_inode != LFS_IFILE_INUM) { 357 1.53 perseant LFS_IENTRY(ifp, fs, blkp->bi_inode, bp); 358 1.168 dholland if (lfs_if_getdaddr(fs, ifp) == blkp->bi_daddr) { 359 1.126 ad mutex_enter(&lfs_lock); 360 1.47 perseant LFS_SET_UINO(ip, IN_CLEANING); 361 1.126 ad mutex_exit(&lfs_lock); 362 1.126 ad } 363 1.123 ad brelse(bp, 0); 364 1.53 perseant } 365 1.1 mycroft continue; 366 1.22 perseant } 367 1.22 perseant 368 1.22 perseant b_daddr = 0; 369 1.112 perseant if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) || 370 1.147 christos LFS_DBTOFSB(fs, b_daddr) != blkp->bi_daddr) 371 1.112 perseant { 372 1.147 christos if (lfs_dtosn(fs, LFS_DBTOFSB(fs, b_daddr)) == 373 1.147 christos lfs_dtosn(fs, blkp->bi_daddr)) 374 1.22 perseant { 375 1.165 dholland DLOG((DLOG_CLEAN, "lfs_markv: wrong da same seg: %jx vs %jx\n", 376 1.165 dholland (intmax_t)blkp->bi_daddr, (intmax_t)LFS_DBTOFSB(fs, b_daddr))); 377 1.22 perseant } 378 1.112 perseant do_again++; 379 1.112 perseant continue; 380 1.22 perseant } 381 1.69 perseant 382 1.69 perseant /* 383 1.69 perseant * Check block sizes. The blocks being cleaned come from 384 1.69 perseant * disk, so they should have the same size as their on-disk 385 1.69 perseant * counterparts. 386 1.69 perseant */ 387 1.72 yamt if (blkp->bi_lbn >= 0) 388 1.147 christos obsize = lfs_blksize(fs, ip, blkp->bi_lbn); 389 1.72 yamt else 390 1.161 dholland obsize = lfs_sb_getbsize(fs); 391 1.69 perseant /* Check for fragment size change */ 392 1.146 dholland if (blkp->bi_lbn >= 0 && blkp->bi_lbn < ULFS_NDADDR) { 393 1.69 perseant obsize = ip->i_lfs_fragsize[blkp->bi_lbn]; 394 1.69 perseant } 395 1.69 perseant if (obsize != blkp->bi_size) { 396 1.165 dholland DLOG((DLOG_CLEAN, "lfs_markv: ino %d lbn %jd wrong" 397 1.103 perseant " size (%ld != %d), try again\n", 398 1.165 dholland blkp->bi_inode, (intmax_t)blkp->bi_lbn, 399 1.103 perseant (long) obsize, blkp->bi_size)); 400 1.69 perseant do_again++; 401 1.69 perseant continue; 402 1.69 perseant } 403 1.69 perseant 404 1.22 perseant /* 405 1.69 perseant * If we get to here, then we are keeping the block. If 406 1.22 perseant * it is an indirect block, we want to actually put it 407 1.22 perseant * in the buffer cache so that it can be updated in the 408 1.82 perseant * finish_meta section. If it's not, we need to 409 1.22 perseant * allocate a fake buffer so that writeseg can perform 410 1.22 perseant * the copyin and write the buffer. 411 1.22 perseant */ 412 1.38 perseant if (ip->i_number != LFS_IFILE_INUM && blkp->bi_lbn >= 0) { 413 1.38 perseant /* Data Block */ 414 1.65 perseant bp = lfs_fakebuf(fs, vp, blkp->bi_lbn, 415 1.23 perseant blkp->bi_size, blkp->bi_bp); 416 1.23 perseant /* Pretend we used bread() to get it */ 417 1.147 christos bp->b_blkno = LFS_FSBTODB(fs, blkp->bi_daddr); 418 1.38 perseant } else { 419 1.75 yamt /* Indirect block or ifile */ 420 1.161 dholland if (blkp->bi_size != lfs_sb_getbsize(fs) && 421 1.75 yamt ip->i_number != LFS_IFILE_INUM) 422 1.72 yamt panic("lfs_markv: partial indirect block?" 423 1.72 yamt " size=%d\n", blkp->bi_size); 424 1.22 perseant bp = getblk(vp, blkp->bi_lbn, blkp->bi_size, 0, 0); 425 1.126 ad if (!(bp->b_oflags & (BO_DONE|BO_DELWRI))) { 426 1.22 perseant /* 427 1.22 perseant * The block in question was not found 428 1.22 perseant * in the cache; i.e., the block that 429 1.82 perseant * getblk() returned is empty. So, we 430 1.22 perseant * can (and should) copy in the 431 1.22 perseant * contents, because we've already 432 1.22 perseant * determined that this was the right 433 1.22 perseant * version of this block on disk. 434 1.22 perseant * 435 1.22 perseant * And, it can't have changed underneath 436 1.22 perseant * us, because we have the segment lock. 437 1.22 perseant */ 438 1.22 perseant error = copyin(blkp->bi_bp, bp->b_data, blkp->bi_size); 439 1.62 chs if (error) 440 1.22 perseant goto err2; 441 1.22 perseant } 442 1.22 perseant } 443 1.96 yamt if ((error = lfs_bwrite_ext(bp, BW_CLEAN)) != 0) 444 1.22 perseant goto err2; 445 1.77 yamt 446 1.77 yamt nblkwritten++; 447 1.77 yamt /* 448 1.77 yamt * XXX should account indirect blocks and ifile pages as well 449 1.77 yamt */ 450 1.169 dholland if (nblkwritten + lfs_lblkno(fs, ninowritten * DINOSIZE(fs)) 451 1.77 yamt > LFS_MARKV_MAX_BLOCKS) { 452 1.103 perseant DLOG((DLOG_CLEAN, "lfs_markv: writing %d blks %d inos\n", 453 1.103 perseant nblkwritten, ninowritten)); 454 1.77 yamt lfs_segwrite(mntp, SEGM_CLEAN); 455 1.77 yamt nblkwritten = ninowritten = 0; 456 1.77 yamt } 457 1.22 perseant } 458 1.102 perry 459 1.22 perseant /* 460 1.22 perseant * Finish the old file, if there was one 461 1.22 perseant */ 462 1.159 hannken if (vp != NULL) { 463 1.160 hannken vput(vp); 464 1.159 hannken vp = NULL; 465 1.22 perseant numrefed--; 466 1.22 perseant } 467 1.102 perry 468 1.173 riastrad KASSERTMSG((numrefed == 0), "lfs_markv: numrefed=%d", numrefed); 469 1.103 perseant DLOG((DLOG_CLEAN, "lfs_markv: writing %d blks %d inos (check point)\n", 470 1.103 perseant nblkwritten, ninowritten)); 471 1.102 perry 472 1.22 perseant /* 473 1.22 perseant * The last write has to be SEGM_SYNC, because of calling semantics. 474 1.22 perseant * It also has to be SEGM_CKP, because otherwise we could write 475 1.22 perseant * over the newly cleaned data contained in a checkpoint, and then 476 1.22 perseant * we'd be unhappy at recovery time. 477 1.22 perseant */ 478 1.67 perseant lfs_segwrite(mntp, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC); 479 1.102 perry 480 1.1 mycroft lfs_segunlock(fs); 481 1.1 mycroft 482 1.174 hannken vfs_unbusy(mntp); 483 1.62 chs if (error) 484 1.22 perseant return (error); 485 1.62 chs else if (do_again) 486 1.22 perseant return EAGAIN; 487 1.1 mycroft 488 1.22 perseant return 0; 489 1.102 perry 490 1.96 yamt err2: 491 1.103 perseant DLOG((DLOG_CLEAN, "lfs_markv err2\n")); 492 1.53 perseant 493 1.96 yamt /* 494 1.96 yamt * XXX we're here because copyin() failed. 495 1.96 yamt * XXX it means that we can't trust the cleanerd. too bad. 496 1.96 yamt * XXX how can we recover from this? 497 1.96 yamt */ 498 1.96 yamt 499 1.96 yamt err3: 500 1.96 yamt /* 501 1.96 yamt * XXX should do segwrite here anyway? 502 1.96 yamt */ 503 1.96 yamt 504 1.159 hannken if (vp != NULL) { 505 1.160 hannken vput(vp); 506 1.159 hannken vp = NULL; 507 1.96 yamt --numrefed; 508 1.22 perseant } 509 1.96 yamt 510 1.1 mycroft lfs_segunlock(fs); 511 1.174 hannken vfs_unbusy(mntp); 512 1.173 riastrad KASSERTMSG((numrefed == 0), "lfs_markv: numrefed=%d", numrefed); 513 1.53 perseant 514 1.22 perseant return (error); 515 1.1 mycroft } 516 1.1 mycroft 517 1.1 mycroft /* 518 1.31 christos * sys_lfs_bmapv: 519 1.1 mycroft * 520 1.1 mycroft * This will fill in the current disk address for arrays of blocks. 521 1.1 mycroft * 522 1.1 mycroft * 0 on success 523 1.1 mycroft * -1/errno is return on error. 524 1.1 mycroft */ 525 1.57 perseant #ifdef USE_64BIT_SYSCALLS 526 1.57 perseant int 527 1.125 dsl sys_lfs_bmapv(struct lwp *l, const struct sys_lfs_bmapv_args *uap, register_t *retval) 528 1.57 perseant { 529 1.125 dsl /* { 530 1.57 perseant syscallarg(fsid_t *) fsidp; 531 1.57 perseant syscallarg(struct block_info *) blkiov; 532 1.57 perseant syscallarg(int) blkcnt; 533 1.125 dsl } */ 534 1.57 perseant BLOCK_INFO *blkiov; 535 1.57 perseant int blkcnt, error; 536 1.57 perseant fsid_t fsid; 537 1.105 perseant struct lfs *fs; 538 1.105 perseant struct mount *mntp; 539 1.22 perseant 540 1.57 perseant if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 541 1.57 perseant return (error); 542 1.57 perseant 543 1.105 perseant if ((mntp = vfs_getvfs(&fsid)) == NULL) 544 1.105 perseant return (ENOENT); 545 1.146 dholland fs = VFSTOULFS(mntp)->um_lfs; 546 1.105 perseant 547 1.57 perseant blkcnt = SCARG(uap, blkcnt); 548 1.171 dholland #if SIZE_T_MAX <= UINT_MAX 549 1.71 itojun if ((u_int) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO)) 550 1.71 itojun return (EINVAL); 551 1.171 dholland #endif 552 1.129 ad KERNEL_LOCK(1, NULL); 553 1.105 perseant blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 554 1.57 perseant if ((error = copyin(SCARG(uap, blkiov), blkiov, 555 1.57 perseant blkcnt * sizeof(BLOCK_INFO))) != 0) 556 1.57 perseant goto out; 557 1.57 perseant 558 1.171 dholland if ((error = lfs_bmapv(l, &fsid, blkiov, blkcnt)) == 0) 559 1.57 perseant copyout(blkiov, SCARG(uap, blkiov), 560 1.57 perseant blkcnt * sizeof(BLOCK_INFO)); 561 1.57 perseant out: 562 1.105 perseant lfs_free(fs, blkiov, LFS_NB_BLKIOV); 563 1.129 ad KERNEL_UNLOCK_ONE(NULL); 564 1.57 perseant return error; 565 1.57 perseant } 566 1.57 perseant #else 567 1.1 mycroft int 568 1.125 dsl sys_lfs_bmapv(struct lwp *l, const struct sys_lfs_bmapv_args *uap, register_t *retval) 569 1.9 thorpej { 570 1.125 dsl /* { 571 1.32 drochner syscallarg(fsid_t *) fsidp; 572 1.32 drochner syscallarg(struct block_info *) blkiov; 573 1.32 drochner syscallarg(int) blkcnt; 574 1.125 dsl } */ 575 1.57 perseant BLOCK_INFO *blkiov; 576 1.57 perseant BLOCK_INFO_15 *blkiov15; 577 1.57 perseant int i, blkcnt, error; 578 1.57 perseant fsid_t fsid; 579 1.105 perseant struct lfs *fs; 580 1.105 perseant struct mount *mntp; 581 1.57 perseant 582 1.57 perseant if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 583 1.57 perseant return (error); 584 1.57 perseant 585 1.105 perseant if ((mntp = vfs_getvfs(&fsid)) == NULL) 586 1.105 perseant return (ENOENT); 587 1.146 dholland fs = VFSTOULFS(mntp)->um_lfs; 588 1.105 perseant 589 1.57 perseant blkcnt = SCARG(uap, blkcnt); 590 1.90 nakayama if ((size_t) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO)) 591 1.71 itojun return (EINVAL); 592 1.129 ad KERNEL_LOCK(1, NULL); 593 1.105 perseant blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV); 594 1.105 perseant blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV); 595 1.57 perseant if ((error = copyin(SCARG(uap, blkiov), blkiov15, 596 1.57 perseant blkcnt * sizeof(BLOCK_INFO_15))) != 0) 597 1.57 perseant goto out; 598 1.57 perseant 599 1.57 perseant for (i = 0; i < blkcnt; i++) { 600 1.57 perseant blkiov[i].bi_inode = blkiov15[i].bi_inode; 601 1.57 perseant blkiov[i].bi_lbn = blkiov15[i].bi_lbn; 602 1.57 perseant blkiov[i].bi_daddr = blkiov15[i].bi_daddr; 603 1.57 perseant blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate; 604 1.57 perseant blkiov[i].bi_version = blkiov15[i].bi_version; 605 1.82 perseant blkiov[i].bi_bp = blkiov15[i].bi_bp; 606 1.57 perseant blkiov[i].bi_size = blkiov15[i].bi_size; 607 1.57 perseant } 608 1.57 perseant 609 1.166 dholland if ((error = lfs_bmapv(l, &fsid, blkiov, blkcnt)) == 0) { 610 1.57 perseant for (i = 0; i < blkcnt; i++) { 611 1.82 perseant blkiov15[i].bi_inode = blkiov[i].bi_inode; 612 1.82 perseant blkiov15[i].bi_lbn = blkiov[i].bi_lbn; 613 1.82 perseant blkiov15[i].bi_daddr = blkiov[i].bi_daddr; 614 1.57 perseant blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate; 615 1.82 perseant blkiov15[i].bi_version = blkiov[i].bi_version; 616 1.82 perseant blkiov15[i].bi_bp = blkiov[i].bi_bp; 617 1.82 perseant blkiov15[i].bi_size = blkiov[i].bi_size; 618 1.57 perseant } 619 1.57 perseant copyout(blkiov15, SCARG(uap, blkiov), 620 1.57 perseant blkcnt * sizeof(BLOCK_INFO_15)); 621 1.57 perseant } 622 1.57 perseant out: 623 1.105 perseant lfs_free(fs, blkiov, LFS_NB_BLKIOV); 624 1.105 perseant lfs_free(fs, blkiov15, LFS_NB_BLKIOV); 625 1.129 ad KERNEL_UNLOCK_ONE(NULL); 626 1.57 perseant return error; 627 1.57 perseant } 628 1.57 perseant #endif 629 1.57 perseant 630 1.84 perseant int 631 1.166 dholland lfs_bmapv(struct lwp *l, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt) 632 1.57 perseant { 633 1.1 mycroft BLOCK_INFO *blkp; 634 1.22 perseant IFILE *ifp; 635 1.22 perseant struct buf *bp; 636 1.22 perseant struct inode *ip = NULL; 637 1.22 perseant struct lfs *fs; 638 1.1 mycroft struct mount *mntp; 639 1.160 hannken struct ulfsmount *ump; 640 1.1 mycroft struct vnode *vp; 641 1.22 perseant ino_t lastino; 642 1.79 fvdl daddr_t v_daddr; 643 1.74 yamt int cnt, error; 644 1.74 yamt int numrefed = 0; 645 1.1 mycroft 646 1.166 dholland error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 647 1.166 dholland KAUTH_REQ_SYSTEM_LFS_BMAPV, NULL, NULL, NULL); 648 1.166 dholland if (error) 649 1.166 dholland return (error); 650 1.166 dholland 651 1.57 perseant if ((mntp = vfs_getvfs(fsidp)) == NULL) 652 1.53 perseant return (ENOENT); 653 1.102 perry 654 1.174 hannken if ((error = vfs_busy(mntp)) != 0) 655 1.53 perseant return (error); 656 1.102 perry 657 1.172 dholland ump = VFSTOULFS(mntp); 658 1.172 dholland fs = ump->um_lfs; 659 1.172 dholland 660 1.172 dholland if (fs->lfs_cleaner_thread == NULL) 661 1.172 dholland fs->lfs_cleaner_thread = curlwp; 662 1.172 dholland KASSERT(fs->lfs_cleaner_thread == curlwp); 663 1.160 hannken 664 1.57 perseant cnt = blkcnt; 665 1.102 perry 666 1.22 perseant error = 0; 667 1.102 perry 668 1.22 perseant /* these were inside the initialization for the for loop */ 669 1.159 hannken vp = NULL; 670 1.22 perseant v_daddr = LFS_UNUSED_DADDR; 671 1.22 perseant lastino = LFS_UNUSED_INUM; 672 1.57 perseant for (blkp = blkiov; cnt--; ++blkp) 673 1.22 perseant { 674 1.16 fvdl /* 675 1.22 perseant * Get the IFILE entry (only once) and see if the file still 676 1.22 perseant * exists. 677 1.16 fvdl */ 678 1.22 perseant if (lastino != blkp->bi_inode) { 679 1.22 perseant /* 680 1.159 hannken * Finish the old file, if there was one. 681 1.22 perseant */ 682 1.159 hannken if (vp != NULL) { 683 1.160 hannken vput(vp); 684 1.159 hannken vp = NULL; 685 1.22 perseant numrefed--; 686 1.22 perseant } 687 1.22 perseant 688 1.22 perseant /* 689 1.22 perseant * Start a new file 690 1.22 perseant */ 691 1.22 perseant lastino = blkp->bi_inode; 692 1.22 perseant if (blkp->bi_inode == LFS_IFILE_INUM) 693 1.161 dholland v_daddr = lfs_sb_getidaddr(fs); 694 1.22 perseant else { 695 1.22 perseant LFS_IENTRY(ifp, fs, blkp->bi_inode, bp); 696 1.168 dholland v_daddr = lfs_if_getdaddr(fs, ifp); 697 1.123 ad brelse(bp, 0); 698 1.22 perseant } 699 1.22 perseant if (v_daddr == LFS_UNUSED_DADDR) { 700 1.22 perseant blkp->bi_daddr = LFS_UNUSED_DADDR; 701 1.22 perseant continue; 702 1.22 perseant } 703 1.159 hannken error = lfs_fastvget(mntp, blkp->bi_inode, NULL, 704 1.159 hannken LK_SHARED, &vp); 705 1.159 hannken if (error) { 706 1.159 hannken DLOG((DLOG_CLEAN, "lfs_bmapv: lfs_fastvget ino" 707 1.159 hannken "%d failed with %d", 708 1.159 hannken blkp->bi_inode,error)); 709 1.159 hannken KASSERT(vp == NULL); 710 1.159 hannken continue; 711 1.159 hannken } else { 712 1.159 hannken KASSERT(VOP_ISLOCKED(vp)); 713 1.43 perseant numrefed++; 714 1.22 perseant } 715 1.22 perseant ip = VTOI(vp); 716 1.159 hannken } else if (vp == NULL) { 717 1.22 perseant /* 718 1.22 perseant * This can only happen if the vnode is dead. 719 1.82 perseant * Keep going. Note that we DO NOT set the 720 1.22 perseant * bi_addr to anything -- if we failed to get 721 1.22 perseant * the vnode, for example, we want to assume 722 1.22 perseant * conservatively that all of its blocks *are* 723 1.22 perseant * located in the segment in question. 724 1.22 perseant * lfs_markv will throw them out if we are 725 1.22 perseant * wrong. 726 1.22 perseant */ 727 1.22 perseant continue; 728 1.22 perseant } 729 1.22 perseant 730 1.22 perseant /* Past this point we are guaranteed that vp, ip are valid. */ 731 1.22 perseant 732 1.62 chs if (blkp->bi_lbn == LFS_UNUSED_LBN) { 733 1.22 perseant /* 734 1.22 perseant * We just want the inode address, which is 735 1.22 perseant * conveniently in v_daddr. 736 1.22 perseant */ 737 1.22 perseant blkp->bi_daddr = v_daddr; 738 1.22 perseant } else { 739 1.79 fvdl daddr_t bi_daddr; 740 1.79 fvdl 741 1.22 perseant error = VOP_BMAP(vp, blkp->bi_lbn, NULL, 742 1.79 fvdl &bi_daddr, NULL); 743 1.62 chs if (error) 744 1.22 perseant { 745 1.22 perseant blkp->bi_daddr = LFS_UNUSED_DADDR; 746 1.22 perseant continue; 747 1.22 perseant } 748 1.147 christos blkp->bi_daddr = LFS_DBTOFSB(fs, bi_daddr); 749 1.66 perseant /* Fill in the block size, too */ 750 1.72 yamt if (blkp->bi_lbn >= 0) 751 1.147 christos blkp->bi_size = lfs_blksize(fs, ip, blkp->bi_lbn); 752 1.72 yamt else 753 1.161 dholland blkp->bi_size = lfs_sb_getbsize(fs); 754 1.22 perseant } 755 1.22 perseant } 756 1.102 perry 757 1.22 perseant /* 758 1.159 hannken * Finish the old file, if there was one. 759 1.22 perseant */ 760 1.159 hannken if (vp != NULL) { 761 1.160 hannken vput(vp); 762 1.159 hannken vp = NULL; 763 1.22 perseant numrefed--; 764 1.22 perseant } 765 1.102 perry 766 1.173 riastrad KASSERTMSG((numrefed == 0), "lfs_bmapv: numrefed=%d", numrefed); 767 1.102 perry 768 1.174 hannken vfs_unbusy(mntp); 769 1.102 perry 770 1.22 perseant return 0; 771 1.1 mycroft } 772 1.1 mycroft 773 1.1 mycroft /* 774 1.31 christos * sys_lfs_segclean: 775 1.1 mycroft * 776 1.1 mycroft * Mark the segment clean. 777 1.1 mycroft * 778 1.1 mycroft * 0 on success 779 1.1 mycroft * -1/errno is return on error. 780 1.1 mycroft */ 781 1.1 mycroft int 782 1.125 dsl sys_lfs_segclean(struct lwp *l, const struct sys_lfs_segclean_args *uap, register_t *retval) 783 1.9 thorpej { 784 1.125 dsl /* { 785 1.32 drochner syscallarg(fsid_t *) fsidp; 786 1.32 drochner syscallarg(u_long) segment; 787 1.125 dsl } */ 788 1.80 perseant struct lfs *fs; 789 1.1 mycroft struct mount *mntp; 790 1.1 mycroft fsid_t fsid; 791 1.1 mycroft int error; 792 1.67 perseant unsigned long segnum; 793 1.102 perry 794 1.142 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 795 1.142 elad KAUTH_REQ_SYSTEM_LFS_SEGCLEAN, NULL, NULL, NULL); 796 1.142 elad if (error) 797 1.1 mycroft return (error); 798 1.102 perry 799 1.10 christos if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 800 1.1 mycroft return (error); 801 1.16 fvdl if ((mntp = vfs_getvfs(&fsid)) == NULL) 802 1.53 perseant return (ENOENT); 803 1.102 perry 804 1.146 dholland fs = VFSTOULFS(mntp)->um_lfs; 805 1.67 perseant segnum = SCARG(uap, segment); 806 1.102 perry 807 1.174 hannken if ((error = vfs_busy(mntp)) != 0) 808 1.53 perseant return (error); 809 1.80 perseant 810 1.129 ad KERNEL_LOCK(1, NULL); 811 1.65 perseant lfs_seglock(fs, SEGM_PROT); 812 1.80 perseant error = lfs_do_segclean(fs, segnum); 813 1.80 perseant lfs_segunlock(fs); 814 1.129 ad KERNEL_UNLOCK_ONE(NULL); 815 1.174 hannken vfs_unbusy(mntp); 816 1.80 perseant return error; 817 1.80 perseant } 818 1.80 perseant 819 1.80 perseant /* 820 1.80 perseant * Actually mark the segment clean. 821 1.80 perseant * Must be called with the segment lock held. 822 1.80 perseant */ 823 1.80 perseant int 824 1.80 perseant lfs_do_segclean(struct lfs *fs, unsigned long segnum) 825 1.80 perseant { 826 1.107 perseant extern int lfs_dostats; 827 1.80 perseant struct buf *bp; 828 1.80 perseant CLEANERINFO *cip; 829 1.80 perseant SEGUSE *sup; 830 1.102 perry 831 1.161 dholland if (lfs_dtosn(fs, lfs_sb_getcurseg(fs)) == segnum) { 832 1.80 perseant return (EBUSY); 833 1.80 perseant } 834 1.102 perry 835 1.67 perseant LFS_SEGENTRY(sup, fs, segnum, bp); 836 1.67 perseant if (sup->su_nbytes) { 837 1.103 perseant DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" 838 1.103 perseant " %d live bytes\n", segnum, sup->su_nbytes)); 839 1.123 ad brelse(bp, 0); 840 1.67 perseant return (EBUSY); 841 1.67 perseant } 842 1.1 mycroft if (sup->su_flags & SEGUSE_ACTIVE) { 843 1.106 perseant DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" 844 1.106 perseant " segment is active\n", segnum)); 845 1.123 ad brelse(bp, 0); 846 1.1 mycroft return (EBUSY); 847 1.50 perseant } 848 1.50 perseant if (!(sup->su_flags & SEGUSE_DIRTY)) { 849 1.106 perseant DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:" 850 1.106 perseant " segment is already clean\n", segnum)); 851 1.123 ad brelse(bp, 0); 852 1.50 perseant return (EALREADY); 853 1.1 mycroft } 854 1.102 perry 855 1.161 dholland lfs_sb_addavail(fs, lfs_segtod(fs, 1)); 856 1.46 perseant if (sup->su_flags & SEGUSE_SUPERBLOCK) 857 1.161 dholland lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_SBPAD)); 858 1.164 dholland if (lfs_sb_getversion(fs) > 1 && segnum == 0 && 859 1.162 dholland lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD)) 860 1.162 dholland lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_LABELPAD) - lfs_sb_gets0addr(fs)); 861 1.126 ad mutex_enter(&lfs_lock); 862 1.162 dholland lfs_sb_addbfree(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) + 863 1.161 dholland lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs))); 864 1.162 dholland lfs_sb_subdmeta(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) + 865 1.161 dholland lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs))); 866 1.161 dholland if (lfs_sb_getdmeta(fs) < 0) 867 1.161 dholland lfs_sb_setdmeta(fs, 0); 868 1.126 ad mutex_exit(&lfs_lock); 869 1.1 mycroft sup->su_flags &= ~SEGUSE_DIRTY; 870 1.80 perseant LFS_WRITESEGENTRY(sup, fs, segnum, bp); 871 1.102 perry 872 1.1 mycroft LFS_CLEANERINFO(cip, fs, bp); 873 1.167 dholland lfs_ci_shiftdirtytoclean(fs, cip, 1); 874 1.167 dholland lfs_sb_setnclean(fs, lfs_ci_getclean(fs, cip)); 875 1.126 ad mutex_enter(&lfs_lock); 876 1.167 dholland lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs)); 877 1.167 dholland lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs) 878 1.167 dholland - fs->lfs_ravail - fs->lfs_favail); 879 1.161 dholland wakeup(&fs->lfs_availsleep); 880 1.126 ad mutex_exit(&lfs_lock); 881 1.65 perseant (void) LFS_BWRITE_LOG(bp); 882 1.22 perseant 883 1.107 perseant if (lfs_dostats) 884 1.107 perseant ++lfs_stats.segs_reclaimed; 885 1.106 perseant 886 1.1 mycroft return (0); 887 1.1 mycroft } 888 1.1 mycroft 889 1.1 mycroft /* 890 1.1 mycroft * This will block until a segment in file system fsid is written. A timeout 891 1.1 mycroft * in milliseconds may be specified which will awake the cleaner automatically. 892 1.1 mycroft * An fsid of -1 means any file system, and a timeout of 0 means forever. 893 1.84 perseant */ 894 1.84 perseant int 895 1.84 perseant lfs_segwait(fsid_t *fsidp, struct timeval *tv) 896 1.84 perseant { 897 1.84 perseant struct mount *mntp; 898 1.84 perseant void *addr; 899 1.84 perseant u_long timeout; 900 1.114 kardel int error; 901 1.84 perseant 902 1.175 maya mutex_enter(&lfs_lock); 903 1.106 perseant if (fsidp == NULL || (mntp = vfs_getvfs(fsidp)) == NULL) 904 1.84 perseant addr = &lfs_allclean_wakeup; 905 1.84 perseant else 906 1.161 dholland addr = &VFSTOULFS(mntp)->um_lfs->lfs_nextsegsleep; 907 1.84 perseant /* 908 1.84 perseant * XXX THIS COULD SLEEP FOREVER IF TIMEOUT IS {0,0}! 909 1.84 perseant * XXX IS THAT WHAT IS INTENDED? 910 1.84 perseant */ 911 1.114 kardel timeout = tvtohz(tv); 912 1.175 maya error = cv_timedwait_sig(addr, &lfs_lock, timeout); 913 1.175 maya mutex_exit(&lfs_lock); 914 1.84 perseant return (error == ERESTART ? EINTR : 0); 915 1.84 perseant } 916 1.84 perseant 917 1.84 perseant /* 918 1.84 perseant * sys_lfs_segwait: 919 1.84 perseant * 920 1.84 perseant * System call wrapper around lfs_segwait(). 921 1.1 mycroft * 922 1.1 mycroft * 0 on success 923 1.1 mycroft * 1 on timeout 924 1.1 mycroft * -1/errno is return on error. 925 1.1 mycroft */ 926 1.1 mycroft int 927 1.134 christos sys___lfs_segwait50(struct lwp *l, const struct sys___lfs_segwait50_args *uap, 928 1.134 christos register_t *retval) 929 1.9 thorpej { 930 1.125 dsl /* { 931 1.32 drochner syscallarg(fsid_t *) fsidp; 932 1.32 drochner syscallarg(struct timeval *) tv; 933 1.125 dsl } */ 934 1.1 mycroft struct timeval atv; 935 1.1 mycroft fsid_t fsid; 936 1.84 perseant int error; 937 1.102 perry 938 1.84 perseant /* XXX need we be su to segwait? */ 939 1.142 elad error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS, 940 1.142 elad KAUTH_REQ_SYSTEM_LFS_SEGWAIT, NULL, NULL, NULL); 941 1.142 elad if (error) 942 1.1 mycroft return (error); 943 1.10 christos if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0) 944 1.1 mycroft return (error); 945 1.102 perry 946 1.5 cgd if (SCARG(uap, tv)) { 947 1.10 christos error = copyin(SCARG(uap, tv), &atv, sizeof(struct timeval)); 948 1.10 christos if (error) 949 1.1 mycroft return (error); 950 1.1 mycroft if (itimerfix(&atv)) 951 1.1 mycroft return (EINVAL); 952 1.84 perseant } else /* NULL or invalid */ 953 1.84 perseant atv.tv_sec = atv.tv_usec = 0; 954 1.84 perseant return lfs_segwait(&fsid, &atv); 955 1.1 mycroft } 956 1.1 mycroft 957 1.1 mycroft /* 958 1.160 hannken * VFS_VGET call specialized for the cleaner. If the cleaner is 959 1.1 mycroft * processing IINFO structures, it may have the ondisk inode already, so 960 1.1 mycroft * don't go retrieving it again. 961 1.22 perseant * 962 1.160 hannken * Return the vnode referenced and locked. 963 1.1 mycroft */ 964 1.22 perseant 965 1.160 hannken static int 966 1.159 hannken lfs_fastvget(struct mount *mp, ino_t ino, BLOCK_INFO *blkp, int lk_flags, 967 1.159 hannken struct vnode **vpp) 968 1.1 mycroft { 969 1.146 dholland struct ulfsmount *ump; 970 1.172 dholland struct lfs *fs; 971 1.160 hannken int error; 972 1.102 perry 973 1.146 dholland ump = VFSTOULFS(mp); 974 1.172 dholland fs = ump->um_lfs; 975 1.172 dholland fs->lfs_cleaner_hint = blkp; 976 1.160 hannken error = vcache_get(mp, &ino, sizeof(ino), vpp); 977 1.172 dholland fs->lfs_cleaner_hint = NULL; 978 1.160 hannken if (error) 979 1.159 hannken return error; 980 1.160 hannken error = vn_lock(*vpp, lk_flags); 981 1.160 hannken if (error) { 982 1.159 hannken if (error == EBUSY) 983 1.159 hannken error = EAGAIN; 984 1.160 hannken vrele(*vpp); 985 1.101 perseant *vpp = NULL; 986 1.160 hannken return error; 987 1.44 fvdl } 988 1.44 fvdl 989 1.160 hannken return 0; 990 1.1 mycroft } 991 1.22 perseant 992 1.85 perseant /* 993 1.85 perseant * Make up a "fake" cleaner buffer, copy the data from userland into it. 994 1.85 perseant */ 995 1.165 dholland static struct buf * 996 1.165 dholland lfs_fakebuf(struct lfs *fs, struct vnode *vp, daddr_t lbn, size_t size, void *uaddr) 997 1.1 mycroft { 998 1.1 mycroft struct buf *bp; 999 1.25 perseant int error; 1000 1.75 yamt 1001 1.75 yamt KASSERT(VTOI(vp)->i_number != LFS_IFILE_INUM); 1002 1.73 yamt 1003 1.80 perseant bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, size, LFS_NB_CLEAN); 1004 1.25 perseant error = copyin(uaddr, bp->b_data, size); 1005 1.62 chs if (error) { 1006 1.80 perseant lfs_freebuf(fs, bp); 1007 1.25 perseant return NULL; 1008 1.22 perseant } 1009 1.176 chs KDASSERT(bp->b_iodone == lfs_free_aiodone); 1010 1.73 yamt 1011 1.65 perseant #if 0 1012 1.126 ad mutex_enter(&lfs_lock); 1013 1.65 perseant ++fs->lfs_iocount; 1014 1.126 ad mutex_exit(&lfs_lock); 1015 1.65 perseant #endif 1016 1.1 mycroft bp->b_bufsize = size; 1017 1.1 mycroft bp->b_bcount = size; 1018 1.1 mycroft return (bp); 1019 1.1 mycroft } 1020