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

Annotation of src/sys/ufs/ufs/ufs_inode.c, Revision 1.90.2.2

1.90.2.2! snj         1: /*     $NetBSD: ufs_inode.c,v 1.90.2.1 2015/01/28 18:34:11 martin Exp $        */
1.3       cgd         2:
1.1       mycroft     3: /*
                      4:  * Copyright (c) 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
1.40      agc        20:  * 3. Neither the name of the University nor the names of its contributors
1.1       mycroft    21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
1.10      fvdl       36:  *     @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95
1.1       mycroft    37:  */
1.28      lukem      38:
                     39: #include <sys/cdefs.h>
1.90.2.2! snj        40: __KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.90.2.1 2015/01/28 18:34:11 martin Exp $");
1.11      scottr     41:
1.46      dbj        42: #if defined(_KERNEL_OPT)
1.49      thorpej    43: #include "opt_ffs.h"
1.11      scottr     44: #include "opt_quota.h"
1.76      simonb     45: #include "opt_wapbl.h"
1.46      dbj        46: #endif
1.1       mycroft    47:
                     48: #include <sys/param.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/proc.h>
                     51: #include <sys/vnode.h>
                     52: #include <sys/mount.h>
                     53: #include <sys/kernel.h>
1.6       christos   54: #include <sys/namei.h>
1.59      elad       55: #include <sys/kauth.h>
1.76      simonb     56: #include <sys/wapbl.h>
1.63      hannken    57: #include <sys/fstrans.h>
1.68      pooka      58: #include <sys/kmem.h>
1.1       mycroft    59:
                     60: #include <ufs/ufs/inode.h>
                     61: #include <ufs/ufs/ufsmount.h>
                     62: #include <ufs/ufs/ufs_extern.h>
1.76      simonb     63: #include <ufs/ufs/ufs_wapbl.h>
1.47      rumble     64: #ifdef UFS_DIRHASH
                     65: #include <ufs/ufs/dirhash.h>
                     66: #endif
1.52      thorpej    67: #ifdef UFS_EXTATTR
                     68: #include <ufs/ufs/extattr.h>
                     69: #endif
1.1       mycroft    70:
1.16      chs        71: #include <uvm/uvm.h>
                     72:
1.19      tsutsui    73: extern int prtactive;
                     74:
1.1       mycroft    75: /*
                     76:  * Last reference to an inode.  If necessary, write or delete it.
                     77:  */
                     78: int
1.48      thorpej    79: ufs_inactive(void *v)
1.6       christos   80: {
1.1       mycroft    81:        struct vop_inactive_args /* {
                     82:                struct vnode *a_vp;
1.72      ad         83:                struct bool *a_recycle;
1.6       christos   84:        } */ *ap = v;
1.10      fvdl       85:        struct vnode *vp = ap->a_vp;
                     86:        struct inode *ip = VTOI(vp);
1.90.2.2! snj        87:        struct mount *mp = vp->v_mount;
1.36      fvdl       88:        mode_t mode;
1.90.2.2! snj        89:        int allerror = 0, error;
        !            90:        bool wapbl_locked = false;
1.76      simonb     91:
1.90.2.2! snj        92:        UFS_WAPBL_JUNLOCK_ASSERT(mp);
1.1       mycroft    93:
1.90.2.2! snj        94:        fstrans_start(mp, FSTRANS_LAZY);
1.10      fvdl       95:        /*
                     96:         * Ignore inodes related to stale file handles.
                     97:         */
1.36      fvdl       98:        if (ip->i_mode == 0)
1.10      fvdl       99:                goto out;
1.90.2.2! snj       100:        if (ip->i_nlink <= 0 && (mp->mnt_flag & MNT_RDONLY) == 0) {
1.86      manu      101: #ifdef UFS_EXTATTR
                    102:                ufs_extattr_vnode_inactive(vp, curlwp);
                    103: #endif
1.90.2.1  martin    104:                if (ip->i_size != 0)
1.90.2.2! snj       105:                        allerror = ufs_truncate(vp, 0, NOCRED);
1.84      bouyer    106: #if defined(QUOTA) || defined(QUOTA2)
1.90.2.2! snj       107:                error = UFS_WAPBL_BEGIN(mp);
        !           108:                if (error) {
        !           109:                        allerror = error;
        !           110:                } else {
        !           111:                        wapbl_locked = true;
        !           112:                        (void)chkiq(ip, -1, NOCRED, 0);
        !           113:                }
1.84      bouyer    114: #endif
1.37      kristerw  115:                DIP_ASSIGN(ip, rdev, 0);
1.36      fvdl      116:                mode = ip->i_mode;
                    117:                ip->i_mode = 0;
1.82      hannken   118:                ip->i_omode = mode;
1.37      kristerw  119:                DIP_ASSIGN(ip, mode, 0);
1.1       mycroft   120:                ip->i_flag |= IN_CHANGE | IN_UPDATE;
1.82      hannken   121:                /*
                    122:                 * Defer final inode free and update to ufs_reclaim().
                    123:                 */
1.74      ad        124:        }
                    125:
                    126:        if (ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) {
1.90.2.2! snj       127:                if (! wapbl_locked) {
        !           128:                        error = UFS_WAPBL_BEGIN(mp);
        !           129:                        if (error) {
        !           130:                                allerror = error;
        !           131:                                goto out;
        !           132:                        }
        !           133:                        wapbl_locked = true;
        !           134:                }
1.54      yamt      135:                UFS_UPDATE(vp, NULL, NULL, 0);
1.90.2.1  martin    136:        }
1.10      fvdl      137: out:
1.90.2.2! snj       138:        if (wapbl_locked)
        !           139:                UFS_WAPBL_END(mp);
1.1       mycroft   140:        /*
                    141:         * If we are done with the inode, reclaim it
                    142:         * so that it can be reused immediately.
                    143:         */
1.72      ad        144:        *ap->a_recycle = (ip->i_mode == 0);
1.81      hannken   145:        VOP_UNLOCK(vp);
1.90.2.2! snj       146:        fstrans_done(mp);
        !           147:        return (allerror);
1.1       mycroft   148: }
                    149:
                    150: /*
                    151:  * Reclaim an inode so that it can be used for other purposes.
                    152:  */
                    153: int
1.70      pooka     154: ufs_reclaim(struct vnode *vp)
1.1       mycroft   155: {
1.44      mycroft   156:        struct inode *ip = VTOI(vp);
1.1       mycroft   157:
1.72      ad        158:        if (prtactive && vp->v_usecount > 1)
1.1       mycroft   159:                vprint("ufs_reclaim: pushing active", vp);
1.45      dbj       160:
1.76      simonb    161:        if (!UFS_WAPBL_BEGIN(vp->v_mount)) {
                    162:                UFS_UPDATE(vp, NULL, NULL, UPDATE_CLOSE);
                    163:                UFS_WAPBL_END(vp->v_mount);
                    164:        }
1.54      yamt      165:        UFS_UPDATE(vp, NULL, NULL, UPDATE_CLOSE);
1.74      ad        166:
                    167:        /*
1.90      hannken   168:         * Remove the inode from the vnode cache.
1.74      ad        169:         */
1.90      hannken   170:        vcache_remove(vp->v_mount, &ip->i_number, sizeof(ip->i_number));
1.85      rmind     171:
1.1       mycroft   172:        if (ip->i_devvp) {
                    173:                vrele(ip->i_devvp);
                    174:                ip->i_devvp = 0;
                    175:        }
1.84      bouyer    176: #if defined(QUOTA) || defined(QUOTA2)
1.67      hannken   177:        ufsquota_free(ip);
1.1       mycroft   178: #endif
1.47      rumble    179: #ifdef UFS_DIRHASH
                    180:        if (ip->i_dirhash != NULL)
                    181:                ufsdirhash_free(ip);
                    182: #endif
1.1       mycroft   183:        return (0);
1.16      chs       184: }
                    185:
                    186: /*
                    187:  * allocate a range of blocks in a file.
                    188:  * after this function returns, any page entirely contained within the range
                    189:  * will map to invalid data and thus must be overwritten before it is made
                    190:  * accessible to others.
                    191:  */
                    192:
                    193: int
1.59      elad      194: ufs_balloc_range(struct vnode *vp, off_t off, off_t len, kauth_cred_t cred,
1.48      thorpej   195:     int flags)
1.16      chs       196: {
1.58      yamt      197:        off_t neweof;   /* file size after the operation */
                    198:        off_t neweob;   /* offset next to the last block after the operation */
                    199:        off_t pagestart; /* starting offset of range covered by pgs */
                    200:        off_t eob;      /* offset next to allocated blocks */
1.16      chs       201:        struct uvm_object *uobj;
1.29      chs       202:        int i, delta, error, npages;
1.16      chs       203:        int bshift = vp->v_mount->mnt_fs_bshift;
                    204:        int bsize = 1 << bshift;
1.22      chs       205:        int ppb = MAX(bsize >> PAGE_SHIFT, 1);
1.68      pooka     206:        struct vm_page **pgs;
                    207:        size_t pgssize;
1.16      chs       208:        UVMHIST_FUNC("ufs_balloc_range"); UVMHIST_CALLED(ubchist);
                    209:        UVMHIST_LOG(ubchist, "vp %p off 0x%x len 0x%x u_size 0x%x",
1.25      chs       210:                    vp, off, len, vp->v_size);
1.16      chs       211:
1.25      chs       212:        neweof = MAX(vp->v_size, off + len);
1.58      yamt      213:        GOP_SIZE(vp, neweof, &neweob, 0);
1.16      chs       214:
                    215:        error = 0;
1.25      chs       216:        uobj = &vp->v_uobj;
1.16      chs       217:
                    218:        /*
1.29      chs       219:         * read or create pages covering the range of the allocation and
                    220:         * keep them locked until the new block is allocated, so there
                    221:         * will be no window where the old contents of the new block are
                    222:         * visible to racing threads.
1.16      chs       223:         */
                    224:
1.29      chs       225:        pagestart = trunc_page(off) & ~(bsize - 1);
                    226:        npages = MIN(ppb, (round_page(neweob) - pagestart) >> PAGE_SHIFT);
1.68      pooka     227:        pgssize = npages * sizeof(struct vm_page *);
                    228:        pgs = kmem_zalloc(pgssize, KM_SLEEP);
                    229:
1.77      pooka     230:        /*
                    231:         * adjust off to be block-aligned.
                    232:         */
                    233:
                    234:        delta = off & (bsize - 1);
                    235:        off -= delta;
                    236:        len += delta;
                    237:
1.83      chs       238:        genfs_node_wrlock(vp);
1.87      rmind     239:        mutex_enter(uobj->vmobjlock);
1.29      chs       240:        error = VOP_GETPAGES(vp, pagestart, pgs, &npages, 0,
1.83      chs       241:            VM_PROT_WRITE, 0, PGO_SYNCIO | PGO_PASTEOF | PGO_NOBLOCKALLOC |
                    242:            PGO_NOTIMESTAMP | PGO_GLOCKHELD);
1.29      chs       243:        if (error) {
1.90.2.2! snj       244:                genfs_node_unlock(vp);
1.68      pooka     245:                goto out;
1.16      chs       246:        }
                    247:
                    248:        /*
1.77      pooka     249:         * now allocate the range.
1.16      chs       250:         */
                    251:
1.25      chs       252:        error = GOP_ALLOC(vp, off, len, flags, cred);
1.61      yamt      253:        genfs_node_unlock(vp);
1.16      chs       254:
                    255:        /*
1.88      chs       256:         * if the allocation succeeded, clear PG_CLEAN on all the pages
                    257:         * and clear PG_RDONLY on any pages that are now fully backed
                    258:         * by disk blocks.  if the allocation failed, we do not invalidate
                    259:         * the pages since they might have already existed and been dirty,
                    260:         * in which case we need to keep them around.  if we created the pages,
                    261:         * they will be clean and read-only, and leaving such pages
                    262:         * in the cache won't cause any problems.
1.16      chs       263:         */
                    264:
1.58      yamt      265:        GOP_SIZE(vp, off + len, &eob, 0);
1.87      rmind     266:        mutex_enter(uobj->vmobjlock);
1.88      chs       267:        mutex_enter(&uvm_pageqlock);
1.29      chs       268:        for (i = 0; i < npages; i++) {
1.88      chs       269:                KASSERT((pgs[i]->flags & PG_RELEASED) == 0);
                    270:                if (!error) {
                    271:                        if (off <= pagestart + (i << PAGE_SHIFT) &&
                    272:                            pagestart + ((i + 1) << PAGE_SHIFT) <= eob) {
                    273:                                pgs[i]->flags &= ~PG_RDONLY;
                    274:                        }
                    275:                        pgs[i]->flags &= ~PG_CLEAN;
1.24      chs       276:                }
1.88      chs       277:                uvm_pageactivate(pgs[i]);
1.16      chs       278:        }
1.88      chs       279:        mutex_exit(&uvm_pageqlock);
                    280:        uvm_page_unbusy(pgs, npages);
1.87      rmind     281:        mutex_exit(uobj->vmobjlock);
1.68      pooka     282:
                    283:  out:
1.72      ad        284:        kmem_free(pgs, pgssize);
1.16      chs       285:        return error;
1.1       mycroft   286: }
1.90.2.1  martin    287:
                    288: static int
                    289: ufs_wapbl_truncate(struct vnode *vp, uint64_t newsize, kauth_cred_t cred)
                    290: {
                    291:        struct inode *ip = VTOI(vp);
                    292:        int error = 0;
                    293:        uint64_t base, incr;
                    294:
                    295:        base = UFS_NDADDR << vp->v_mount->mnt_fs_bshift;
                    296:        incr = MNINDIR(ip->i_ump) << vp->v_mount->mnt_fs_bshift;/* Power of 2 */
                    297:        while (ip->i_size > base + incr &&
                    298:            (newsize == 0 || ip->i_size > newsize + incr)) {
                    299:                /*
                    300:                 * round down to next full indirect
                    301:                 * block boundary.
                    302:                 */
                    303:                uint64_t nsize = base + ((ip->i_size - base - 1) & ~(incr - 1));
                    304:                error = UFS_TRUNCATE(vp, nsize, 0, cred);
                    305:                if (error)
                    306:                        break;
                    307:                UFS_WAPBL_END(vp->v_mount);
                    308:                error = UFS_WAPBL_BEGIN(vp->v_mount);
                    309:                if (error)
                    310:                        return error;
                    311:        }
                    312:        return error;
                    313: }
                    314:
                    315: int
                    316: ufs_truncate(struct vnode *vp, uint64_t newsize, kauth_cred_t cred)
                    317: {
                    318:        int error;
                    319:
                    320:        error = UFS_WAPBL_BEGIN(vp->v_mount);
                    321:        if (error)
                    322:                return error;
                    323:
                    324:        if (vp->v_mount->mnt_wapbl)
                    325:                error = ufs_wapbl_truncate(vp, newsize, cred);
                    326:
                    327:        if (error == 0)
                    328:                error = UFS_TRUNCATE(vp, newsize, 0, cred);
                    329:        UFS_WAPBL_END(vp->v_mount);
                    330:
                    331:        return error;
                    332: }
                    333:

CVSweb <webmaster@jp.NetBSD.org>