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
| 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
|
45#include <sys/buf.h> 46#include <sys/proc.h> 47#include <sys/mount.h> 48#include <sys/vnode.h> 49#include <sys/conf.h> 50 51#include <machine/limits.h> 52 53#include <vm/vm.h> 54#include <vm/vm_page.h> 55#include <vm/vm_object.h> 56#include <vm/vm_extern.h> 57 58#include <ufs/ufs/extattr.h> 59#include <ufs/ufs/quota.h> 60#include <ufs/ufs/inode.h> 61#include <ufs/ufs/ufsmount.h> 62#include <ufs/ufs/ufs_extern.h> 63 64#include <ufs/ffs/fs.h> 65#include <ufs/ffs/ffs_extern.h> 66 67static int ffs_fsync __P((struct vop_fsync_args *)); 68static int ffs_getpages __P((struct vop_getpages_args *)); 69static int ffs_putpages __P((struct vop_putpages_args *)); 70static int ffs_read __P((struct vop_read_args *)); 71static int ffs_write __P((struct vop_write_args *)); 72 73/* Global vfs data structures for ufs. */ 74vop_t **ffs_vnodeop_p; 75static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { 76 { &vop_default_desc, (vop_t *) ufs_vnoperate }, 77 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 78 { &vop_getpages_desc, (vop_t *) ffs_getpages }, 79 { &vop_putpages_desc, (vop_t *) ffs_putpages }, 80 { &vop_read_desc, (vop_t *) ffs_read }, 81 { &vop_balloc_desc, (vop_t *) ffs_balloc }, 82 { &vop_reallocblks_desc, (vop_t *) ffs_reallocblks }, 83 { &vop_write_desc, (vop_t *) ffs_write }, 84#ifdef FFS_EXTATTR 85 { &vop_getextattr_desc, (vop_t *) ufs_vop_getextattr }, 86 { &vop_setextattr_desc, (vop_t *) ufs_vop_setextattr }, 87#endif 88 { NULL, NULL } 89}; 90static struct vnodeopv_desc ffs_vnodeop_opv_desc = 91 { &ffs_vnodeop_p, ffs_vnodeop_entries }; 92 93vop_t **ffs_specop_p; 94static struct vnodeopv_entry_desc ffs_specop_entries[] = { 95 { &vop_default_desc, (vop_t *) ufs_vnoperatespec }, 96 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 97 { NULL, NULL } 98}; 99static struct vnodeopv_desc ffs_specop_opv_desc = 100 { &ffs_specop_p, ffs_specop_entries }; 101 102vop_t **ffs_fifoop_p; 103static struct vnodeopv_entry_desc ffs_fifoop_entries[] = { 104 { &vop_default_desc, (vop_t *) ufs_vnoperatefifo }, 105 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 106 { NULL, NULL } 107}; 108static struct vnodeopv_desc ffs_fifoop_opv_desc = 109 { &ffs_fifoop_p, ffs_fifoop_entries }; 110 111VNODEOP_SET(ffs_vnodeop_opv_desc); 112VNODEOP_SET(ffs_specop_opv_desc); 113VNODEOP_SET(ffs_fifoop_opv_desc); 114 115#include <ufs/ufs/ufs_readwrite.c> 116 117/* 118 * Synch an open file. 119 */ 120/* ARGSUSED */ 121static int 122ffs_fsync(ap) 123 struct vop_fsync_args /* { 124 struct vnode *a_vp; 125 struct ucred *a_cred; 126 int a_waitfor; 127 struct proc *a_p; 128 } */ *ap; 129{ 130 struct vnode *vp = ap->a_vp; 131 struct buf *bp; 132 struct buf *nbp; 133 int s, error, wait, passes, skipmeta; 134 daddr_t lbn; 135 136 wait = (ap->a_waitfor == MNT_WAIT); 137 if (vn_isdisk(vp, NULL)) { 138 lbn = INT_MAX; 139 if (vp->v_specmountpoint != NULL && 140 (vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) 141 softdep_fsync_mountdev(vp); 142 } else { 143 struct inode *ip; 144 ip = VTOI(vp); 145 lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); 146 } 147 148 /* 149 * Flush all dirty buffers associated with a vnode. 150 */ 151 passes = NIADDR + 1; 152 skipmeta = 0; 153 if (wait) 154 skipmeta = 1; 155 s = splbio(); 156loop: 157 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; 158 bp = TAILQ_NEXT(bp, b_vnbufs)) 159 bp->b_flags &= ~B_SCANNED; 160 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { 161 nbp = TAILQ_NEXT(bp, b_vnbufs); 162 /* 163 * Reasons to skip this buffer: it has already been considered 164 * on this pass, this pass is the first time through on a 165 * synchronous flush request and the buffer being considered 166 * is metadata, the buffer has dependencies that will cause 167 * it to be redirtied and it has not already been deferred, 168 * or it is already being written. 169 */ 170 if ((bp->b_flags & B_SCANNED) != 0) 171 continue; 172 bp->b_flags |= B_SCANNED; 173 if ((skipmeta == 1 && bp->b_lblkno < 0)) 174 continue; 175 if (!wait && LIST_FIRST(&bp->b_dep) != NULL && 176 (bp->b_flags & B_DEFERRED) == 0 && 177 bioops.io_countdeps && (*bioops.io_countdeps)(bp, 0)) { 178 bp->b_flags |= B_DEFERRED; 179 continue; 180 } 181 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) 182 continue; 183 if ((bp->b_flags & B_DELWRI) == 0) 184 panic("ffs_fsync: not dirty"); 185 if (vp != bp->b_vp) 186 panic("ffs_fsync: vp != vp->b_vp"); 187 /* 188 * If this is a synchronous flush request, or it is not a 189 * file or device, start the write on this buffer immediatly. 190 */ 191 if (wait || (vp->v_type != VREG && vp->v_type != VBLK)) { 192 193 /* 194 * On our final pass through, do all I/O synchronously 195 * so that we can find out if our flush is failing 196 * because of write errors. 197 */ 198 if (passes > 0 || !wait) { 199 if ((bp->b_flags & B_CLUSTEROK) && !wait) { 200 BUF_UNLOCK(bp); 201 (void) vfs_bio_awrite(bp); 202 } else { 203 bremfree(bp); 204 splx(s); 205 (void) bawrite(bp); 206 s = splbio(); 207 } 208 } else { 209 bremfree(bp); 210 splx(s); 211 if ((error = bwrite(bp)) != 0) 212 return (error); 213 s = splbio(); 214 } 215 } else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) { 216 /* 217 * If the buffer is for data that has been truncated 218 * off the file, then throw it away. 219 */ 220 bremfree(bp); 221 bp->b_flags |= B_INVAL | B_NOCACHE; 222 splx(s); 223 brelse(bp); 224 s = splbio(); 225 } else { 226 BUF_UNLOCK(bp); 227 vfs_bio_awrite(bp); 228 } 229 /* 230 * Since we may have slept during the I/O, we need 231 * to start from a known point. 232 */ 233 nbp = TAILQ_FIRST(&vp->v_dirtyblkhd); 234 } 235 /* 236 * If we were asked to do this synchronously, then go back for 237 * another pass, this time doing the metadata. 238 */ 239 if (skipmeta) { 240 skipmeta = 0; 241 goto loop; 242 } 243 244 if (wait) { 245 while (vp->v_numoutput) { 246 vp->v_flag |= VBWAIT; 247 (void) tsleep((caddr_t)&vp->v_numoutput, 248 PRIBIO + 4, "ffsfsn", 0); 249 } 250 251 /* 252 * Ensure that any filesystem metatdata associated 253 * with the vnode has been written. 254 */ 255 splx(s); 256 if ((error = softdep_sync_metadata(ap)) != 0) 257 return (error); 258 s = splbio(); 259 260 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { 261 /* 262 * Block devices associated with filesystems may 263 * have new I/O requests posted for them even if 264 * the vnode is locked, so no amount of trying will 265 * get them clean. Thus we give block devices a 266 * good effort, then just give up. For all other file 267 * types, go around and try again until it is clean. 268 */ 269 if (passes > 0) { 270 passes -= 1; 271 goto loop; 272 } 273#ifdef DIAGNOSTIC 274 if (!vn_isdisk(vp, NULL)) 275 vprint("ffs_fsync: dirty", vp); 276#endif 277 } 278 } 279 splx(s); 280 return (UFS_UPDATE(vp, wait)); 281}
| 46#include <sys/buf.h> 47#include <sys/proc.h> 48#include <sys/mount.h> 49#include <sys/vnode.h> 50#include <sys/conf.h> 51 52#include <machine/limits.h> 53 54#include <vm/vm.h> 55#include <vm/vm_page.h> 56#include <vm/vm_object.h> 57#include <vm/vm_extern.h> 58 59#include <ufs/ufs/extattr.h> 60#include <ufs/ufs/quota.h> 61#include <ufs/ufs/inode.h> 62#include <ufs/ufs/ufsmount.h> 63#include <ufs/ufs/ufs_extern.h> 64 65#include <ufs/ffs/fs.h> 66#include <ufs/ffs/ffs_extern.h> 67 68static int ffs_fsync __P((struct vop_fsync_args *)); 69static int ffs_getpages __P((struct vop_getpages_args *)); 70static int ffs_putpages __P((struct vop_putpages_args *)); 71static int ffs_read __P((struct vop_read_args *)); 72static int ffs_write __P((struct vop_write_args *)); 73 74/* Global vfs data structures for ufs. */ 75vop_t **ffs_vnodeop_p; 76static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { 77 { &vop_default_desc, (vop_t *) ufs_vnoperate }, 78 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 79 { &vop_getpages_desc, (vop_t *) ffs_getpages }, 80 { &vop_putpages_desc, (vop_t *) ffs_putpages }, 81 { &vop_read_desc, (vop_t *) ffs_read }, 82 { &vop_balloc_desc, (vop_t *) ffs_balloc }, 83 { &vop_reallocblks_desc, (vop_t *) ffs_reallocblks }, 84 { &vop_write_desc, (vop_t *) ffs_write }, 85#ifdef FFS_EXTATTR 86 { &vop_getextattr_desc, (vop_t *) ufs_vop_getextattr }, 87 { &vop_setextattr_desc, (vop_t *) ufs_vop_setextattr }, 88#endif 89 { NULL, NULL } 90}; 91static struct vnodeopv_desc ffs_vnodeop_opv_desc = 92 { &ffs_vnodeop_p, ffs_vnodeop_entries }; 93 94vop_t **ffs_specop_p; 95static struct vnodeopv_entry_desc ffs_specop_entries[] = { 96 { &vop_default_desc, (vop_t *) ufs_vnoperatespec }, 97 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 98 { NULL, NULL } 99}; 100static struct vnodeopv_desc ffs_specop_opv_desc = 101 { &ffs_specop_p, ffs_specop_entries }; 102 103vop_t **ffs_fifoop_p; 104static struct vnodeopv_entry_desc ffs_fifoop_entries[] = { 105 { &vop_default_desc, (vop_t *) ufs_vnoperatefifo }, 106 { &vop_fsync_desc, (vop_t *) ffs_fsync }, 107 { NULL, NULL } 108}; 109static struct vnodeopv_desc ffs_fifoop_opv_desc = 110 { &ffs_fifoop_p, ffs_fifoop_entries }; 111 112VNODEOP_SET(ffs_vnodeop_opv_desc); 113VNODEOP_SET(ffs_specop_opv_desc); 114VNODEOP_SET(ffs_fifoop_opv_desc); 115 116#include <ufs/ufs/ufs_readwrite.c> 117 118/* 119 * Synch an open file. 120 */ 121/* ARGSUSED */ 122static int 123ffs_fsync(ap) 124 struct vop_fsync_args /* { 125 struct vnode *a_vp; 126 struct ucred *a_cred; 127 int a_waitfor; 128 struct proc *a_p; 129 } */ *ap; 130{ 131 struct vnode *vp = ap->a_vp; 132 struct buf *bp; 133 struct buf *nbp; 134 int s, error, wait, passes, skipmeta; 135 daddr_t lbn; 136 137 wait = (ap->a_waitfor == MNT_WAIT); 138 if (vn_isdisk(vp, NULL)) { 139 lbn = INT_MAX; 140 if (vp->v_specmountpoint != NULL && 141 (vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) 142 softdep_fsync_mountdev(vp); 143 } else { 144 struct inode *ip; 145 ip = VTOI(vp); 146 lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); 147 } 148 149 /* 150 * Flush all dirty buffers associated with a vnode. 151 */ 152 passes = NIADDR + 1; 153 skipmeta = 0; 154 if (wait) 155 skipmeta = 1; 156 s = splbio(); 157loop: 158 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; 159 bp = TAILQ_NEXT(bp, b_vnbufs)) 160 bp->b_flags &= ~B_SCANNED; 161 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { 162 nbp = TAILQ_NEXT(bp, b_vnbufs); 163 /* 164 * Reasons to skip this buffer: it has already been considered 165 * on this pass, this pass is the first time through on a 166 * synchronous flush request and the buffer being considered 167 * is metadata, the buffer has dependencies that will cause 168 * it to be redirtied and it has not already been deferred, 169 * or it is already being written. 170 */ 171 if ((bp->b_flags & B_SCANNED) != 0) 172 continue; 173 bp->b_flags |= B_SCANNED; 174 if ((skipmeta == 1 && bp->b_lblkno < 0)) 175 continue; 176 if (!wait && LIST_FIRST(&bp->b_dep) != NULL && 177 (bp->b_flags & B_DEFERRED) == 0 && 178 bioops.io_countdeps && (*bioops.io_countdeps)(bp, 0)) { 179 bp->b_flags |= B_DEFERRED; 180 continue; 181 } 182 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) 183 continue; 184 if ((bp->b_flags & B_DELWRI) == 0) 185 panic("ffs_fsync: not dirty"); 186 if (vp != bp->b_vp) 187 panic("ffs_fsync: vp != vp->b_vp"); 188 /* 189 * If this is a synchronous flush request, or it is not a 190 * file or device, start the write on this buffer immediatly. 191 */ 192 if (wait || (vp->v_type != VREG && vp->v_type != VBLK)) { 193 194 /* 195 * On our final pass through, do all I/O synchronously 196 * so that we can find out if our flush is failing 197 * because of write errors. 198 */ 199 if (passes > 0 || !wait) { 200 if ((bp->b_flags & B_CLUSTEROK) && !wait) { 201 BUF_UNLOCK(bp); 202 (void) vfs_bio_awrite(bp); 203 } else { 204 bremfree(bp); 205 splx(s); 206 (void) bawrite(bp); 207 s = splbio(); 208 } 209 } else { 210 bremfree(bp); 211 splx(s); 212 if ((error = bwrite(bp)) != 0) 213 return (error); 214 s = splbio(); 215 } 216 } else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) { 217 /* 218 * If the buffer is for data that has been truncated 219 * off the file, then throw it away. 220 */ 221 bremfree(bp); 222 bp->b_flags |= B_INVAL | B_NOCACHE; 223 splx(s); 224 brelse(bp); 225 s = splbio(); 226 } else { 227 BUF_UNLOCK(bp); 228 vfs_bio_awrite(bp); 229 } 230 /* 231 * Since we may have slept during the I/O, we need 232 * to start from a known point. 233 */ 234 nbp = TAILQ_FIRST(&vp->v_dirtyblkhd); 235 } 236 /* 237 * If we were asked to do this synchronously, then go back for 238 * another pass, this time doing the metadata. 239 */ 240 if (skipmeta) { 241 skipmeta = 0; 242 goto loop; 243 } 244 245 if (wait) { 246 while (vp->v_numoutput) { 247 vp->v_flag |= VBWAIT; 248 (void) tsleep((caddr_t)&vp->v_numoutput, 249 PRIBIO + 4, "ffsfsn", 0); 250 } 251 252 /* 253 * Ensure that any filesystem metatdata associated 254 * with the vnode has been written. 255 */ 256 splx(s); 257 if ((error = softdep_sync_metadata(ap)) != 0) 258 return (error); 259 s = splbio(); 260 261 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { 262 /* 263 * Block devices associated with filesystems may 264 * have new I/O requests posted for them even if 265 * the vnode is locked, so no amount of trying will 266 * get them clean. Thus we give block devices a 267 * good effort, then just give up. For all other file 268 * types, go around and try again until it is clean. 269 */ 270 if (passes > 0) { 271 passes -= 1; 272 goto loop; 273 } 274#ifdef DIAGNOSTIC 275 if (!vn_isdisk(vp, NULL)) 276 vprint("ffs_fsync: dirty", vp); 277#endif 278 } 279 } 280 splx(s); 281 return (UFS_UPDATE(vp, wait)); 282}
|