[BACK]Return to ffs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ffs

Annotation of src/sys/ufs/ffs/ffs_vnops.c, Revision 1.89.6.2

1.89.6.2! pooka       1: /*     $NetBSD: ffs_vnops.c,v 1.89 2007/07/20 16:46:45 pooka Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1982, 1986, 1989, 1993
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. Neither the name of the University nor the names of its contributors
        !            16:  *    may be used to endorse or promote products derived from this software
        !            17:  *    without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  *
        !            31:  *     @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
        !            32:  */
        !            33:
        !            34: #include <sys/cdefs.h>
        !            35: __KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.89 2007/07/20 16:46:45 pooka Exp $");
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/resourcevar.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/file.h>
        !            42: #include <sys/stat.h>
        !            43: #include <sys/buf.h>
        !            44: #include <sys/event.h>
        !            45: #include <sys/proc.h>
        !            46: #include <sys/mount.h>
        !            47: #include <sys/vnode.h>
        !            48: #include <sys/pool.h>
        !            49: #include <sys/signalvar.h>
        !            50: #include <sys/kauth.h>
        !            51: #include <sys/fstrans.h>
        !            52:
        !            53: #include <miscfs/fifofs/fifo.h>
        !            54: #include <miscfs/genfs/genfs.h>
        !            55: #include <miscfs/specfs/specdev.h>
        !            56:
        !            57: #include <ufs/ufs/inode.h>
        !            58: #include <ufs/ufs/dir.h>
        !            59: #include <ufs/ufs/ufs_extern.h>
        !            60: #include <ufs/ufs/ufsmount.h>
        !            61:
        !            62: #include <ufs/ffs/fs.h>
        !            63: #include <ufs/ffs/ffs_extern.h>
        !            64:
        !            65: #include <uvm/uvm.h>
        !            66:
        !            67: static int ffs_full_fsync(void *);
        !            68:
        !            69: /* Global vfs data structures for ufs. */
        !            70: int (**ffs_vnodeop_p)(void *);
        !            71: const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
        !            72:        { &vop_default_desc, vn_default_error },
        !            73:        { &vop_lookup_desc, ufs_lookup },               /* lookup */
        !            74:        { &vop_create_desc, ufs_create },               /* create */
        !            75:        { &vop_whiteout_desc, ufs_whiteout },           /* whiteout */
        !            76:        { &vop_mknod_desc, ufs_mknod },                 /* mknod */
        !            77:        { &vop_open_desc, ufs_open },                   /* open */
        !            78:        { &vop_close_desc, ufs_close },                 /* close */
        !            79:        { &vop_access_desc, ufs_access },               /* access */
        !            80:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
        !            81:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
        !            82:        { &vop_read_desc, ffs_read },                   /* read */
        !            83:        { &vop_write_desc, ffs_write },                 /* write */
        !            84:        { &vop_lease_desc, ufs_lease_check },           /* lease */
        !            85:        { &vop_ioctl_desc, ufs_ioctl },                 /* ioctl */
        !            86:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
        !            87:        { &vop_poll_desc, ufs_poll },                   /* poll */
        !            88:        { &vop_kqfilter_desc, genfs_kqfilter },         /* kqfilter */
        !            89:        { &vop_revoke_desc, ufs_revoke },               /* revoke */
        !            90:        { &vop_mmap_desc, ufs_mmap },                   /* mmap */
        !            91:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
        !            92:        { &vop_seek_desc, ufs_seek },                   /* seek */
        !            93:        { &vop_remove_desc, ufs_remove },               /* remove */
        !            94:        { &vop_link_desc, ufs_link },                   /* link */
        !            95:        { &vop_rename_desc, ufs_rename },               /* rename */
        !            96:        { &vop_mkdir_desc, ufs_mkdir },                 /* mkdir */
        !            97:        { &vop_rmdir_desc, ufs_rmdir },                 /* rmdir */
        !            98:        { &vop_symlink_desc, ufs_symlink },             /* symlink */
        !            99:        { &vop_readdir_desc, ufs_readdir },             /* readdir */
        !           100:        { &vop_readlink_desc, ufs_readlink },           /* readlink */
        !           101:        { &vop_abortop_desc, ufs_abortop },             /* abortop */
        !           102:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
        !           103:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
        !           104:        { &vop_lock_desc, ufs_lock },                   /* lock */
        !           105:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        !           106:        { &vop_bmap_desc, ufs_bmap },                   /* bmap */
        !           107:        { &vop_strategy_desc, ufs_strategy },           /* strategy */
        !           108:        { &vop_print_desc, ufs_print },                 /* print */
        !           109:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        !           110:        { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
        !           111:        { &vop_advlock_desc, ufs_advlock },             /* advlock */
        !           112:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
        !           113:        { &vop_getpages_desc, genfs_getpages },         /* getpages */
        !           114:        { &vop_putpages_desc, genfs_putpages },         /* putpages */
        !           115:        { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
        !           116:        { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
        !           117:        { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
        !           118:        { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
        !           119:        { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
        !           120:        { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
        !           121:        { NULL, NULL }
        !           122: };
        !           123: const struct vnodeopv_desc ffs_vnodeop_opv_desc =
        !           124:        { &ffs_vnodeop_p, ffs_vnodeop_entries };
        !           125:
        !           126: int (**ffs_specop_p)(void *);
        !           127: const struct vnodeopv_entry_desc ffs_specop_entries[] = {
        !           128:        { &vop_default_desc, vn_default_error },
        !           129:        { &vop_lookup_desc, spec_lookup },              /* lookup */
        !           130:        { &vop_create_desc, spec_create },              /* create */
        !           131:        { &vop_mknod_desc, spec_mknod },                /* mknod */
        !           132:        { &vop_open_desc, spec_open },                  /* open */
        !           133:        { &vop_close_desc, ufsspec_close },             /* close */
        !           134:        { &vop_access_desc, ufs_access },               /* access */
        !           135:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
        !           136:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
        !           137:        { &vop_read_desc, ufsspec_read },               /* read */
        !           138:        { &vop_write_desc, ufsspec_write },             /* write */
        !           139:        { &vop_lease_desc, spec_lease_check },          /* lease */
        !           140:        { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
        !           141:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
        !           142:        { &vop_poll_desc, spec_poll },                  /* poll */
        !           143:        { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
        !           144:        { &vop_revoke_desc, spec_revoke },              /* revoke */
        !           145:        { &vop_mmap_desc, spec_mmap },                  /* mmap */
        !           146:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
        !           147:        { &vop_seek_desc, spec_seek },                  /* seek */
        !           148:        { &vop_remove_desc, spec_remove },              /* remove */
        !           149:        { &vop_link_desc, spec_link },                  /* link */
        !           150:        { &vop_rename_desc, spec_rename },              /* rename */
        !           151:        { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
        !           152:        { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
        !           153:        { &vop_symlink_desc, spec_symlink },            /* symlink */
        !           154:        { &vop_readdir_desc, spec_readdir },            /* readdir */
        !           155:        { &vop_readlink_desc, spec_readlink },          /* readlink */
        !           156:        { &vop_abortop_desc, spec_abortop },            /* abortop */
        !           157:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
        !           158:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
        !           159:        { &vop_lock_desc, ufs_lock },                   /* lock */
        !           160:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        !           161:        { &vop_bmap_desc, spec_bmap },                  /* bmap */
        !           162:        { &vop_strategy_desc, spec_strategy },          /* strategy */
        !           163:        { &vop_print_desc, ufs_print },                 /* print */
        !           164:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        !           165:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
        !           166:        { &vop_advlock_desc, spec_advlock },            /* advlock */
        !           167:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
        !           168:        { &vop_getpages_desc, spec_getpages },          /* getpages */
        !           169:        { &vop_putpages_desc, spec_putpages },          /* putpages */
        !           170:        { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
        !           171:        { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
        !           172:        { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
        !           173:        { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
        !           174:        { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
        !           175:        { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
        !           176:        { NULL, NULL }
        !           177: };
        !           178: const struct vnodeopv_desc ffs_specop_opv_desc =
        !           179:        { &ffs_specop_p, ffs_specop_entries };
        !           180:
        !           181: int (**ffs_fifoop_p)(void *);
        !           182: const struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
        !           183:        { &vop_default_desc, vn_default_error },
        !           184:        { &vop_lookup_desc, fifo_lookup },              /* lookup */
        !           185:        { &vop_create_desc, fifo_create },              /* create */
        !           186:        { &vop_mknod_desc, fifo_mknod },                /* mknod */
        !           187:        { &vop_open_desc, fifo_open },                  /* open */
        !           188:        { &vop_close_desc, ufsfifo_close },             /* close */
        !           189:        { &vop_access_desc, ufs_access },               /* access */
        !           190:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
        !           191:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
        !           192:        { &vop_read_desc, ufsfifo_read },               /* read */
        !           193:        { &vop_write_desc, ufsfifo_write },             /* write */
        !           194:        { &vop_lease_desc, fifo_lease_check },          /* lease */
        !           195:        { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
        !           196:        { &vop_fcntl_desc, ufs_fcntl },                 /* fcntl */
        !           197:        { &vop_poll_desc, fifo_poll },                  /* poll */
        !           198:        { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
        !           199:        { &vop_revoke_desc, fifo_revoke },              /* revoke */
        !           200:        { &vop_mmap_desc, fifo_mmap },                  /* mmap */
        !           201:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
        !           202:        { &vop_seek_desc, fifo_seek },                  /* seek */
        !           203:        { &vop_remove_desc, fifo_remove },              /* remove */
        !           204:        { &vop_link_desc, fifo_link },                  /* link */
        !           205:        { &vop_rename_desc, fifo_rename },              /* rename */
        !           206:        { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
        !           207:        { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
        !           208:        { &vop_symlink_desc, fifo_symlink },            /* symlink */
        !           209:        { &vop_readdir_desc, fifo_readdir },            /* readdir */
        !           210:        { &vop_readlink_desc, fifo_readlink },          /* readlink */
        !           211:        { &vop_abortop_desc, fifo_abortop },            /* abortop */
        !           212:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
        !           213:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
        !           214:        { &vop_lock_desc, ufs_lock },                   /* lock */
        !           215:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        !           216:        { &vop_bmap_desc, fifo_bmap },                  /* bmap */
        !           217:        { &vop_strategy_desc, fifo_strategy },          /* strategy */
        !           218:        { &vop_print_desc, ufs_print },                 /* print */
        !           219:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        !           220:        { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
        !           221:        { &vop_advlock_desc, fifo_advlock },            /* advlock */
        !           222:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
        !           223:        { &vop_putpages_desc, fifo_putpages },          /* putpages */
        !           224:        { &vop_openextattr_desc, ffs_openextattr },     /* openextattr */
        !           225:        { &vop_closeextattr_desc, ffs_closeextattr },   /* closeextattr */
        !           226:        { &vop_getextattr_desc, ffs_getextattr },       /* getextattr */
        !           227:        { &vop_setextattr_desc, ffs_setextattr },       /* setextattr */
        !           228:        { &vop_listextattr_desc, ffs_listextattr },     /* listextattr */
        !           229:        { &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */
        !           230:        { NULL, NULL }
        !           231: };
        !           232: const struct vnodeopv_desc ffs_fifoop_opv_desc =
        !           233:        { &ffs_fifoop_p, ffs_fifoop_entries };
        !           234:
        !           235: #include <ufs/ufs/ufs_readwrite.c>
        !           236:
        !           237: int
        !           238: ffs_fsync(void *v)
        !           239: {
        !           240:        struct vop_fsync_args /* {
        !           241:                struct vnode *a_vp;
        !           242:                kauth_cred_t a_cred;
        !           243:                int a_flags;
        !           244:                off_t a_offlo;
        !           245:                off_t a_offhi;
        !           246:                struct lwp *a_l;
        !           247:        } */ *ap = v;
        !           248:        struct buf *bp;
        !           249:        int s, num, error, i;
        !           250:        struct indir ia[NIADDR + 1];
        !           251:        int bsize;
        !           252:        daddr_t blk_high;
        !           253:        struct vnode *vp;
        !           254:
        !           255:        vp = ap->a_vp;
        !           256:
        !           257:        fstrans_start(vp->v_mount, FSTRANS_LAZY);
        !           258:        /*
        !           259:         * XXX no easy way to sync a range in a file with softdep.
        !           260:         */
        !           261:        if ((ap->a_offlo == 0 && ap->a_offhi == 0) || DOINGSOFTDEP(vp) ||
        !           262:            (vp->v_type != VREG)) {
        !           263:                error = ffs_full_fsync(v);
        !           264:                goto out;
        !           265:        }
        !           266:
        !           267:        bsize = vp->v_mount->mnt_stat.f_iosize;
        !           268:        blk_high = ap->a_offhi / bsize;
        !           269:        if (ap->a_offhi % bsize != 0)
        !           270:                blk_high++;
        !           271:
        !           272:        /*
        !           273:         * First, flush all pages in range.
        !           274:         */
        !           275:
        !           276:        simple_lock(&vp->v_interlock);
        !           277:        error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
        !           278:            round_page(ap->a_offhi), PGO_CLEANIT |
        !           279:            ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0));
        !           280:        if (error) {
        !           281:                goto out;
        !           282:        }
        !           283:
        !           284:        /*
        !           285:         * Then, flush indirect blocks.
        !           286:         */
        !           287:
        !           288:        s = splbio();
        !           289:        if (blk_high >= NDADDR) {
        !           290:                error = ufs_getlbns(vp, blk_high, ia, &num);
        !           291:                if (error) {
        !           292:                        splx(s);
        !           293:                        goto out;
        !           294:                }
        !           295:                for (i = 0; i < num; i++) {
        !           296:                        bp = incore(vp, ia[i].in_lbn);
        !           297:                        if (bp != NULL) {
        !           298:                                simple_lock(&bp->b_interlock);
        !           299:                                if (!(bp->b_flags & B_BUSY) && (bp->b_flags & B_DELWRI)) {
        !           300:                                        bp->b_flags |= B_BUSY | B_VFLUSH;
        !           301:                                        simple_unlock(&bp->b_interlock);
        !           302:                                        splx(s);
        !           303:                                        bawrite(bp);
        !           304:                                        s = splbio();
        !           305:                                } else {
        !           306:                                        simple_unlock(&bp->b_interlock);
        !           307:                                }
        !           308:                        }
        !           309:                }
        !           310:        }
        !           311:
        !           312:        if (ap->a_flags & FSYNC_WAIT) {
        !           313:                simple_lock(&global_v_numoutput_slock);
        !           314:                while (vp->v_numoutput > 0) {
        !           315:                        vp->v_flag |= VBWAIT;
        !           316:                        ltsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0,
        !           317:                                &global_v_numoutput_slock);
        !           318:                }
        !           319:                simple_unlock(&global_v_numoutput_slock);
        !           320:        }
        !           321:        splx(s);
        !           322:
        !           323:        error = ffs_update(vp, NULL, NULL,
        !           324:            ((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) == FSYNC_WAIT)
        !           325:            ? UPDATE_WAIT : 0);
        !           326:
        !           327:        if (error == 0 && ap->a_flags & FSYNC_CACHE) {
        !           328:                int l = 0;
        !           329:                VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE,
        !           330:                        ap->a_l->l_cred, ap->a_l);
        !           331:        }
        !           332:
        !           333: out:
        !           334:        fstrans_done(vp->v_mount);
        !           335:        return error;
        !           336: }
        !           337:
        !           338: /*
        !           339:  * Synch an open file.
        !           340:  */
        !           341: /* ARGSUSED */
        !           342: static int
        !           343: ffs_full_fsync(void *v)
        !           344: {
        !           345:        struct vop_fsync_args /* {
        !           346:                struct vnode *a_vp;
        !           347:                kauth_cred_t a_cred;
        !           348:                int a_flags;
        !           349:                off_t a_offlo;
        !           350:                off_t a_offhi;
        !           351:                struct lwp *a_l;
        !           352:        } */ *ap = v;
        !           353:        struct vnode *vp = ap->a_vp;
        !           354:        struct buf *bp, *nbp;
        !           355:        int s, error, passes, skipmeta, inodedeps_only, waitfor;
        !           356:
        !           357:        if (vp->v_type == VBLK &&
        !           358:            vp->v_specmountpoint != NULL &&
        !           359:            (vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP))
        !           360:                softdep_fsync_mountdev(vp);
        !           361:
        !           362:        inodedeps_only = DOINGSOFTDEP(vp) && (ap->a_flags & FSYNC_RECLAIM)
        !           363:            && UVM_OBJ_IS_CLEAN(&vp->v_uobj) && LIST_EMPTY(&vp->v_dirtyblkhd);
        !           364:
        !           365:        /*
        !           366:         * Flush all dirty data associated with a vnode.
        !           367:         */
        !           368:
        !           369:        if (vp->v_type == VREG || vp->v_type == VBLK) {
        !           370:                simple_lock(&vp->v_interlock);
        !           371:                error = VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES | PGO_CLEANIT |
        !           372:                    ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0) |
        !           373:                    (fstrans_getstate(vp->v_mount) == FSTRANS_SUSPENDING ?
        !           374:                        PGO_FREE : 0));
        !           375:                if (error) {
        !           376:                        return error;
        !           377:                }
        !           378:        }
        !           379:
        !           380:        passes = NIADDR + 1;
        !           381:        skipmeta = 0;
        !           382:        if (ap->a_flags & FSYNC_WAIT)
        !           383:                skipmeta = 1;
        !           384:        s = splbio();
        !           385:
        !           386: loop:
        !           387:        LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs)
        !           388:                bp->b_flags &= ~B_SCANNED;
        !           389:        for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
        !           390:                nbp = LIST_NEXT(bp, b_vnbufs);
        !           391:                simple_lock(&bp->b_interlock);
        !           392:                if (bp->b_flags & (B_BUSY | B_SCANNED)) {
        !           393:                        simple_unlock(&bp->b_interlock);
        !           394:                        continue;
        !           395:                }
        !           396:                if ((bp->b_flags & B_DELWRI) == 0)
        !           397:                        panic("ffs_fsync: not dirty");
        !           398:                if (skipmeta && bp->b_lblkno < 0) {
        !           399:                        simple_unlock(&bp->b_interlock);
        !           400:                        continue;
        !           401:                }
        !           402:                simple_unlock(&bp->b_interlock);
        !           403:                bp->b_flags |= B_BUSY | B_VFLUSH | B_SCANNED;
        !           404:                splx(s);
        !           405:                /*
        !           406:                 * On our final pass through, do all I/O synchronously
        !           407:                 * so that we can find out if our flush is failing
        !           408:                 * because of write errors.
        !           409:                 */
        !           410:                if (passes > 0 || !(ap->a_flags & FSYNC_WAIT))
        !           411:                        (void) bawrite(bp);
        !           412:                else if ((error = bwrite(bp)) != 0)
        !           413:                        return (error);
        !           414:                s = splbio();
        !           415:                /*
        !           416:                 * Since we may have slept during the I/O, we need
        !           417:                 * to start from a known point.
        !           418:                 */
        !           419:                nbp = LIST_FIRST(&vp->v_dirtyblkhd);
        !           420:        }
        !           421:        if (skipmeta) {
        !           422:                skipmeta = 0;
        !           423:                goto loop;
        !           424:        }
        !           425:        if (ap->a_flags & FSYNC_WAIT) {
        !           426:                simple_lock(&global_v_numoutput_slock);
        !           427:                while (vp->v_numoutput) {
        !           428:                        vp->v_flag |= VBWAIT;
        !           429:                        (void) ltsleep(&vp->v_numoutput, PRIBIO + 1,
        !           430:                            "ffsfsync", 0, &global_v_numoutput_slock);
        !           431:                }
        !           432:                simple_unlock(&global_v_numoutput_slock);
        !           433:                splx(s);
        !           434:
        !           435:                /*
        !           436:                 * Ensure that any filesystem metadata associated
        !           437:                 * with the vnode has been written.
        !           438:                 */
        !           439:                if ((error = softdep_sync_metadata(ap)) != 0)
        !           440:                        return (error);
        !           441:
        !           442:                s = splbio();
        !           443:                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
        !           444:                        /*
        !           445:                        * Block devices associated with filesystems may
        !           446:                        * have new I/O requests posted for them even if
        !           447:                        * the vnode is locked, so no amount of trying will
        !           448:                        * get them clean. Thus we give block devices a
        !           449:                        * good effort, then just give up. For all other file
        !           450:                        * types, go around and try again until it is clean.
        !           451:                        */
        !           452:                        if (passes > 0) {
        !           453:                                passes--;
        !           454:                                goto loop;
        !           455:                        }
        !           456: #ifdef DIAGNOSTIC
        !           457:                        if (vp->v_type != VBLK)
        !           458:                                vprint("ffs_fsync: dirty", vp);
        !           459: #endif
        !           460:                }
        !           461:        }
        !           462:        splx(s);
        !           463:
        !           464:        if (inodedeps_only)
        !           465:                waitfor = 0;
        !           466:        else
        !           467:                waitfor = (ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0;
        !           468:        error = ffs_update(vp, NULL, NULL, waitfor);
        !           469:
        !           470:        if (error == 0 && ap->a_flags & FSYNC_CACHE) {
        !           471:                int i = 0;
        !           472:                VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE,
        !           473:                        ap->a_l->l_cred, ap->a_l);
        !           474:        }
        !           475:
        !           476:        return error;
        !           477: }
        !           478:
        !           479: /*
        !           480:  * Reclaim an inode so that it can be used for other purposes.
        !           481:  */
        !           482: int
        !           483: ffs_reclaim(void *v)
        !           484: {
        !           485:        struct vop_reclaim_args /* {
        !           486:                struct vnode *a_vp;
        !           487:                struct lwp *a_l;
        !           488:        } */ *ap = v;
        !           489:        struct vnode *vp = ap->a_vp;
        !           490:        struct inode *ip = VTOI(vp);
        !           491:        struct mount *mp = vp->v_mount;
        !           492:        struct ufsmount *ump = ip->i_ump;
        !           493:        int error;
        !           494:
        !           495:        fstrans_start(mp, FSTRANS_LAZY);
        !           496:        if ((error = ufs_reclaim(vp, ap->a_l)) != 0) {
        !           497:                fstrans_done(mp);
        !           498:                return (error);
        !           499:        }
        !           500:        if (ip->i_din.ffs1_din != NULL) {
        !           501:                if (ump->um_fstype == UFS1)
        !           502:                        pool_put(&ffs_dinode1_pool, ip->i_din.ffs1_din);
        !           503:                else
        !           504:                        pool_put(&ffs_dinode2_pool, ip->i_din.ffs2_din);
        !           505:        }
        !           506:        /*
        !           507:         * XXX MFS ends up here, too, to free an inode.  Should we create
        !           508:         * XXX a separate pool for MFS inodes?
        !           509:         */
        !           510:        genfs_node_destroy(vp);
        !           511:        pool_put(&ffs_inode_pool, vp->v_data);
        !           512:        vp->v_data = NULL;
        !           513:        fstrans_done(mp);
        !           514:        return (0);
        !           515: }
        !           516:
        !           517: #if 0
        !           518: int
        !           519: ffs_getpages(void *v)
        !           520: {
        !           521:        struct vop_getpages_args /* {
        !           522:                struct vnode *a_vp;
        !           523:                voff_t a_offset;
        !           524:                struct vm_page **a_m;
        !           525:                int *a_count;
        !           526:                int a_centeridx;
        !           527:                vm_prot_t a_access_type;
        !           528:                int a_advice;
        !           529:                int a_flags;
        !           530:        } */ *ap = v;
        !           531:        struct vnode *vp = ap->a_vp;
        !           532:        struct inode *ip = VTOI(vp);
        !           533:        struct fs *fs = ip->i_fs;
        !           534:
        !           535:        /*
        !           536:         * don't allow a softdep write to create pages for only part of a block.
        !           537:         * the dependency tracking requires that all pages be in memory for
        !           538:         * a block involved in a dependency.
        !           539:         */
        !           540:
        !           541:        if (ap->a_flags & PGO_OVERWRITE &&
        !           542:            (blkoff(fs, ap->a_offset) != 0 ||
        !           543:             blkoff(fs, *ap->a_count << PAGE_SHIFT) != 0) &&
        !           544:            DOINGSOFTDEP(ap->a_vp)) {
        !           545:                if ((ap->a_flags & PGO_LOCKED) == 0) {
        !           546:                        simple_unlock(&vp->v_interlock);
        !           547:                }
        !           548:                return EINVAL;
        !           549:        }
        !           550:        return genfs_getpages(v);
        !           551: }
        !           552: #endif
        !           553:
        !           554: /*
        !           555:  * Return the last logical file offset that should be written for this file
        !           556:  * if we're doing a write that ends at "size".
        !           557:  */
        !           558:
        !           559: void
        !           560: ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
        !           561: {
        !           562:        struct inode *ip = VTOI(vp);
        !           563:        struct fs *fs = ip->i_fs;
        !           564:        daddr_t olbn, nlbn;
        !           565:
        !           566:        olbn = lblkno(fs, ip->i_size);
        !           567:        nlbn = lblkno(fs, size);
        !           568:        if (nlbn < NDADDR && olbn <= nlbn) {
        !           569:                *eobp = fragroundup(fs, size);
        !           570:        } else {
        !           571:                *eobp = blkroundup(fs, size);
        !           572:        }
        !           573: }
        !           574:
        !           575: int
        !           576: ffs_openextattr(void *v)
        !           577: {
        !           578:        struct vop_openextattr_args /* {
        !           579:                struct vnode *a_vp;
        !           580:                kauth_cred_t a_cred;
        !           581:                struct proc *a_p;
        !           582:        } */ *ap = v;
        !           583:        struct inode *ip = VTOI(ap->a_vp);
        !           584:        struct fs *fs = ip->i_fs;
        !           585:
        !           586:        /* Not supported for UFS1 file systems. */
        !           587:        if (fs->fs_magic == FS_UFS1_MAGIC)
        !           588:                return (EOPNOTSUPP);
        !           589:
        !           590:        /* XXX Not implemented for UFS2 file systems. */
        !           591:        return (EOPNOTSUPP);
        !           592: }
        !           593:
        !           594: int
        !           595: ffs_closeextattr(void *v)
        !           596: {
        !           597:        struct vop_closeextattr_args /* {
        !           598:                struct vnode *a_vp;
        !           599:                int a_commit;
        !           600:                kauth_cred_t a_cred;
        !           601:                struct proc *a_p;
        !           602:        } */ *ap = v;
        !           603:        struct inode *ip = VTOI(ap->a_vp);
        !           604:        struct fs *fs = ip->i_fs;
        !           605:
        !           606:        /* Not supported for UFS1 file systems. */
        !           607:        if (fs->fs_magic == FS_UFS1_MAGIC)
        !           608:                return (EOPNOTSUPP);
        !           609:
        !           610:        /* XXX Not implemented for UFS2 file systems. */
        !           611:        return (EOPNOTSUPP);
        !           612: }
        !           613:
        !           614: int
        !           615: ffs_getextattr(void *v)
        !           616: {
        !           617:        struct vop_getextattr_args /* {
        !           618:                struct vnode *a_vp;
        !           619:                int a_attrnamespace;
        !           620:                const char *a_name;
        !           621:                struct uio *a_uio;
        !           622:                size_t *a_size;
        !           623:                kauth_cred_t a_cred;
        !           624:                struct proc *a_p;
        !           625:        } */ *ap = v;
        !           626:        struct vnode *vp = ap->a_vp;
        !           627:        struct inode *ip = VTOI(vp);
        !           628:        struct fs *fs = ip->i_fs;
        !           629:
        !           630:        if (fs->fs_magic == FS_UFS1_MAGIC) {
        !           631: #ifdef UFS_EXTATTR
        !           632:                int error;
        !           633:
        !           634:                fstrans_start(vp->v_mount, FSTRANS_SHARED);
        !           635:                error = ufs_getextattr(ap);
        !           636:                fstrans_done(vp->v_mount);
        !           637:                return error;
        !           638: #else
        !           639:                return (EOPNOTSUPP);
        !           640: #endif
        !           641:        }
        !           642:
        !           643:        /* XXX Not implemented for UFS2 file systems. */
        !           644:        return (EOPNOTSUPP);
        !           645: }
        !           646:
        !           647: int
        !           648: ffs_setextattr(void *v)
        !           649: {
        !           650:        struct vop_setextattr_args /* {
        !           651:                struct vnode *a_vp;
        !           652:                int a_attrnamespace;
        !           653:                const char *a_name;
        !           654:                struct uio *a_uio;
        !           655:                kauth_cred_t a_cred;
        !           656:                struct proc *a_p;
        !           657:        } */ *ap = v;
        !           658:        struct vnode *vp = ap->a_vp;
        !           659:        struct inode *ip = VTOI(vp);
        !           660:        struct fs *fs = ip->i_fs;
        !           661:
        !           662:        if (fs->fs_magic == FS_UFS1_MAGIC) {
        !           663: #ifdef UFS_EXTATTR
        !           664:                int error;
        !           665:
        !           666:                fstrans_start(vp->v_mount, FSTRANS_SHARED);
        !           667:                error = ufs_setextattr(ap);
        !           668:                fstrans_done(vp->v_mount);
        !           669:                return error;
        !           670: #else
        !           671:                return (EOPNOTSUPP);
        !           672: #endif
        !           673:        }
        !           674:
        !           675:        /* XXX Not implemented for UFS2 file systems. */
        !           676:        return (EOPNOTSUPP);
        !           677: }
        !           678:
        !           679: int
        !           680: ffs_listextattr(void *v)
        !           681: {
        !           682:        struct vop_listextattr_args /* {
        !           683:                struct vnode *a_vp;
        !           684:                int a_attrnamespace;
        !           685:                struct uio *a_uio;
        !           686:                size_t *a_size;
        !           687:                kauth_cred_t a_cred;
        !           688:                struct proc *a_p;
        !           689:        } */ *ap = v;
        !           690:        struct inode *ip = VTOI(ap->a_vp);
        !           691:        struct fs *fs = ip->i_fs;
        !           692:
        !           693:        /* Not supported for UFS1 file systems. */
        !           694:        if (fs->fs_magic == FS_UFS1_MAGIC)
        !           695:                return (EOPNOTSUPP);
        !           696:
        !           697:        /* XXX Not implemented for UFS2 file systems. */
        !           698:        return (EOPNOTSUPP);
        !           699: }
        !           700:
        !           701: int
        !           702: ffs_deleteextattr(void *v)
        !           703: {
        !           704:        struct vop_deleteextattr_args /* {
        !           705:                struct vnode *a_vp;
        !           706:                int a_attrnamespace;
        !           707:                kauth_cred_t a_cred;
        !           708:                struct proc *a_p;
        !           709:        } */ *ap = v;
        !           710:        struct vnode *vp = ap->a_vp;
        !           711:        struct inode *ip = VTOI(vp);
        !           712:        struct fs *fs = ip->i_fs;
        !           713:
        !           714:        if (fs->fs_magic == FS_UFS1_MAGIC) {
        !           715: #ifdef UFS_EXTATTR
        !           716:                int error;
        !           717:
        !           718:                fstrans_start(vp->v_mount, FSTRANS_SHARED);
        !           719:                error = ufs_deleteextattr(ap);
        !           720:                fstrans_done(vp->v_mount);
        !           721:                return error;
        !           722: #else
        !           723:                return (EOPNOTSUPP);
        !           724: #endif
        !           725:        }
        !           726:
        !           727:        /* XXX Not implemented for UFS2 file systems. */
        !           728:        return (EOPNOTSUPP);
        !           729: }

CVSweb <webmaster@jp.NetBSD.org>