1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95 34 * $FreeBSD: src/sys/ufs/ffs/ffs_vnops.c,v 1.64 2000/01/10 12:04:25 phk Exp $ 35 * $DragonFly: src/sys/vfs/ufs/ffs_vnops.c,v 1.11 2004/08/24 14:01:57 drhodus Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/resourcevar.h> 41 #include <sys/signalvar.h> 42 #include <sys/kernel.h> 43 #include <sys/stat.h> 44 #include <sys/buf.h> 45 #include <sys/proc.h> 46 #include <sys/mount.h> 47 #include <sys/vnode.h> 48 #include <sys/conf.h> 49 50 #include <machine/limits.h> 51 52 #include <vm/vm.h> 53 #include <vm/vm_page.h> 54 #include <vm/vm_object.h> 55 #include <vm/vm_extern.h> 56 57 #include <sys/buf2.h> 58 59 #include "quota.h" 60 #include "inode.h" 61 #include "ufsmount.h" 62 #include "ufs_extern.h" 63 64 #include "fs.h" 65 #include "ffs_extern.h" 66 67 static int ffs_fsync (struct vop_fsync_args *); 68 static int ffs_getpages (struct vop_getpages_args *); 69 static int ffs_putpages (struct vop_putpages_args *); 70 static int ffs_read (struct vop_read_args *); 71 static int ffs_write (struct vop_write_args *); 72 73 /* Global vfs data structures for ufs. */ 74 struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { 75 { &vop_default_desc, (void *) ufs_vnoperate }, 76 { &vop_fsync_desc, (void *) ffs_fsync }, 77 { &vop_getpages_desc, (void *) ffs_getpages }, 78 { &vop_putpages_desc, (void *) ffs_putpages }, 79 { &vop_read_desc, (void *) ffs_read }, 80 { &vop_balloc_desc, (void *) ffs_balloc }, 81 { &vop_reallocblks_desc, (void *) ffs_reallocblks }, 82 { &vop_write_desc, (void *) ffs_write }, 83 { NULL, NULL } 84 }; 85 86 struct vnodeopv_entry_desc ffs_specop_entries[] = { 87 { &vop_default_desc, (void *) ufs_vnoperatespec }, 88 { &vop_fsync_desc, (void *) ffs_fsync }, 89 { NULL, NULL } 90 }; 91 92 struct vnodeopv_entry_desc ffs_fifoop_entries[] = { 93 { &vop_default_desc, (void *) ufs_vnoperatefifo }, 94 { &vop_fsync_desc, (void *) ffs_fsync }, 95 { NULL, NULL } 96 }; 97 98 #include "ufs_readwrite.c" 99 100 /* 101 * Synch an open file. 102 * 103 * ffs_fsync(struct vnode *a_vp, struct ucred *a_cred, int a_waitfor, 104 * struct proc *a_p) 105 */ 106 /* ARGSUSED */ 107 static int 108 ffs_fsync(struct vop_fsync_args *ap) 109 { 110 struct vnode *vp = ap->a_vp; 111 struct buf *bp; 112 struct buf *nbp; 113 int s, error, wait, passes, skipmeta; 114 daddr_t lbn; 115 116 wait = (ap->a_waitfor == MNT_WAIT); 117 if (vn_isdisk(vp, NULL)) { 118 lbn = INT_MAX; 119 if (vp->v_rdev && vp->v_rdev->si_mountpoint != NULL && 120 (vp->v_rdev->si_mountpoint->mnt_flag & MNT_SOFTDEP)) 121 softdep_fsync_mountdev(vp); 122 } else { 123 struct inode *ip; 124 ip = VTOI(vp); 125 lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); 126 } 127 128 /* 129 * Flush all dirty buffers associated with a vnode. 130 */ 131 passes = NIADDR + 1; 132 skipmeta = 0; 133 if (wait) 134 skipmeta = 1; 135 s = splbio(); 136 loop: 137 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; 138 bp = TAILQ_NEXT(bp, b_vnbufs)) 139 bp->b_flags &= ~B_SCANNED; 140 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { 141 nbp = TAILQ_NEXT(bp, b_vnbufs); 142 /* 143 * Reasons to skip this buffer: it has already been considered 144 * on this pass, this pass is the first time through on a 145 * synchronous flush request and the buffer being considered 146 * is metadata, the buffer has dependencies that will cause 147 * it to be redirtied and it has not already been deferred, 148 * or it is already being written. 149 */ 150 if ((bp->b_flags & B_SCANNED) != 0) 151 continue; 152 bp->b_flags |= B_SCANNED; 153 if ((skipmeta == 1 && bp->b_lblkno < 0)) 154 continue; 155 if (!wait && LIST_FIRST(&bp->b_dep) != NULL && 156 (bp->b_flags & B_DEFERRED) == 0 && 157 bioops.io_countdeps && (*bioops.io_countdeps)(bp, 0)) { 158 bp->b_flags |= B_DEFERRED; 159 continue; 160 } 161 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) 162 continue; 163 if ((bp->b_flags & B_DELWRI) == 0) 164 panic("ffs_fsync: not dirty"); 165 if (vp != bp->b_vp) 166 panic("ffs_fsync: vp != vp->b_vp"); 167 /* 168 * If this is a synchronous flush request, or it is not a 169 * file or device, start the write on this buffer immediatly. 170 */ 171 if (wait || (vp->v_type != VREG && vp->v_type != VBLK)) { 172 173 /* 174 * On our final pass through, do all I/O synchronously 175 * so that we can find out if our flush is failing 176 * because of write errors. 177 */ 178 if (passes > 0 || !wait) { 179 if ((bp->b_flags & B_CLUSTEROK) && !wait) { 180 BUF_UNLOCK(bp); 181 (void) vfs_bio_awrite(bp); 182 } else { 183 bremfree(bp); 184 splx(s); 185 (void) bawrite(bp); 186 s = splbio(); 187 } 188 } else { 189 bremfree(bp); 190 splx(s); 191 if ((error = bwrite(bp)) != 0) 192 return (error); 193 s = splbio(); 194 } 195 } else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) { 196 /* 197 * If the buffer is for data that has been truncated 198 * off the file, then throw it away. 199 */ 200 bremfree(bp); 201 bp->b_flags |= B_INVAL | B_NOCACHE; 202 splx(s); 203 brelse(bp); 204 s = splbio(); 205 } else { 206 BUF_UNLOCK(bp); 207 vfs_bio_awrite(bp); 208 } 209 /* 210 * Since we may have slept during the I/O, we need 211 * to start from a known point. 212 */ 213 nbp = TAILQ_FIRST(&vp->v_dirtyblkhd); 214 } 215 /* 216 * If we were asked to do this synchronously, then go back for 217 * another pass, this time doing the metadata. 218 */ 219 if (skipmeta) { 220 skipmeta = 0; 221 goto loop; 222 } 223 224 if (wait) { 225 while (vp->v_numoutput) { 226 vp->v_flag |= VBWAIT; 227 (void)tsleep((caddr_t)&vp->v_numoutput, 0, "ffsfsn", 0); 228 } 229 230 /* 231 * Ensure that any filesystem metatdata associated 232 * with the vnode has been written. 233 */ 234 splx(s); 235 if ((error = softdep_sync_metadata(ap)) != 0) 236 return (error); 237 s = splbio(); 238 239 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { 240 /* 241 * Block devices associated with filesystems may 242 * have new I/O requests posted for them even if 243 * the vnode is locked, so no amount of trying will 244 * get them clean. Thus we give block devices a 245 * good effort, then just give up. For all other file 246 * types, go around and try again until it is clean. 247 */ 248 if (passes > 0) { 249 passes -= 1; 250 goto loop; 251 } 252 #ifdef DIAGNOSTIC 253 if (!vn_isdisk(vp, NULL)) 254 vprint("ffs_fsync: dirty", vp); 255 #endif 256 } 257 } 258 splx(s); 259 return (UFS_UPDATE(vp, wait)); 260 } 261