Annotation of XNU/bsd/ufs/lfs/lfs.h, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*     $NetBSD: lfs.h,v 1.6 1994/12/21 20:01:01 mycroft Exp $  */
        !            23: 
        !            24: /*-
        !            25:  * Copyright (c) 1991, 1993
        !            26:  *     The Regents of the University of California.  All rights reserved.
        !            27:  *
        !            28:  * Redistribution and use in source and binary forms, with or without
        !            29:  * modification, are permitted provided that the following conditions
        !            30:  * are met:
        !            31:  * 1. Redistributions of source code must retain the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer.
        !            33:  * 2. Redistributions in binary form must reproduce the above copyright
        !            34:  *    notice, this list of conditions and the following disclaimer in the
        !            35:  *    documentation and/or other materials provided with the distribution.
        !            36:  * 3. All advertising materials mentioning features or use of this software
        !            37:  *    must display the following acknowledgement:
        !            38:  *     This product includes software developed by the University of
        !            39:  *     California, Berkeley and its contributors.
        !            40:  * 4. Neither the name of the University nor the names of its contributors
        !            41:  *    may be used to endorse or promote products derived from this software
        !            42:  *    without specific prior written permission.
        !            43:  *
        !            44:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            45:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            46:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            47:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            48:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            49:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            50:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            51:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            52:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            53:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            54:  * SUCH DAMAGE.
        !            55:  *
        !            56:  *     @(#)lfs.h       8.5 (Berkeley) 7/8/94
        !            57:  */
        !            58: 
        !            59: #define        LFS_LABELPAD    8192            /* LFS label size */
        !            60: #define        LFS_SBPAD       8192            /* LFS superblock size */
        !            61: 
        !            62: /*
        !            63:  * XXX
        !            64:  * This is a kluge and NEEDS to go away.
        !            65:  *
        !            66:  * Right now, ufs code handles most of the calls for directory operations
        !            67:  * such as create, mkdir, link, etc.  As a result VOP_UPDATE is being
        !            68:  * called with waitfor set (since ffs does these things synchronously).
        !            69:  * Since LFS does not want to do these synchronously, we treat the last
        !            70:  * argument to lfs_update as a set of flags.  If LFS_SYNC is set, then
        !            71:  * the update should be synchronous, if not, do it asynchronously.
        !            72:  * Unfortunately, this means that LFS won't work with NFS yet because
        !            73:  * NFS goes through paths that will make normal calls to ufs which will
        !            74:  * call lfs with a last argument of 1.
        !            75:  */
        !            76: #define        LFS_SYNC        0x02
        !            77: 
        !            78: /* On-disk and in-memory checkpoint segment usage structure. */
        !            79: typedef struct segusage SEGUSE;
        !            80: struct segusage {
        !            81:        u_int32_t su_nbytes;            /* number of live bytes */
        !            82:        u_int32_t su_lastmod;           /* SEGUSE last modified timestamp */
        !            83:        u_int16_t su_nsums;             /* number of summaries in segment */
        !            84:        u_int16_t su_ninos;             /* number of inode blocks in seg */
        !            85: 
        !            86: #define        SEGUSE_ACTIVE           0x01    /* segment is currently being written */
        !            87: #define        SEGUSE_DIRTY            0x02    /* segment has data in it */
        !            88: #define        SEGUSE_SUPERBLOCK       0x04    /* segment contains a superblock */
        !            89:        u_int32_t su_flags;
        !            90: };
        !            91: 
        !            92: #define        SEGUPB(fs)      (1 << (fs)->lfs_sushift)
        !            93: #define        SEGTABSIZE_SU(fs)                                               \
        !            94:        (((fs)->lfs_nseg + SEGUPB(fs) - 1) >> (fs)->lfs_sushift)
        !            95: 
        !            96: /* On-disk file information.  One per file with data blocks in the segment. */
        !            97: typedef struct finfo FINFO;
        !            98: struct finfo {
        !            99:        u_int32_t fi_nblocks;           /* number of blocks */
        !           100:        u_int32_t fi_version;           /* version number */
        !           101:        u_int32_t fi_ino;               /* inode number */
        !           102:        daddr_t   fi_blocks[1];         /* array of logical block numbers */
        !           103: };
        !           104: 
        !           105: /* On-disk and in-memory super block. */
        !           106: struct lfs {
        !           107: #define        LFS_MAGIC       0x070162
        !           108:        u_int32_t lfs_magic;            /* magic number */
        !           109: #define        LFS_VERSION     1
        !           110:        u_int32_t lfs_version;          /* version number */
        !           111: 
        !           112:        u_int32_t lfs_size;             /* number of blocks in fs */
        !           113:        u_int32_t lfs_ssize;            /* number of blocks per segment */
        !           114:        u_int32_t lfs_dsize;            /* number of disk blocks in fs */
        !           115:        u_int32_t lfs_bsize;            /* file system block size */
        !           116:        u_int32_t lfs_fsize;            /* size of frag blocks in fs */
        !           117:        u_int32_t lfs_frag;             /* number of frags in a block in fs */
        !           118: 
        !           119: /* Checkpoint region. */
        !           120:        ino_t     lfs_free;             /* start of the free list */
        !           121:        u_int32_t lfs_bfree;            /* number of free disk blocks */
        !           122:        u_int32_t lfs_nfiles;           /* number of allocated inodes */
        !           123:        int32_t   lfs_avail;            /* blocks available for writing */
        !           124:        u_int32_t lfs_uinodes;          /* inodes in cache not yet on disk */
        !           125:        daddr_t   lfs_idaddr;           /* inode file disk address */
        !           126:        ino_t     lfs_ifile;            /* inode file inode number */
        !           127:        daddr_t   lfs_lastseg;          /* address of last segment written */
        !           128:        daddr_t   lfs_nextseg;          /* address of next segment to write */
        !           129:        daddr_t   lfs_curseg;           /* current segment being written */
        !           130:        daddr_t   lfs_offset;           /* offset in curseg for next partial */
        !           131:        daddr_t   lfs_lastpseg;         /* address of last partial written */
        !           132:        u_int32_t lfs_tstamp;           /* time stamp */
        !           133: 
        !           134: /* These are configuration parameters. */
        !           135:        u_int32_t lfs_minfree;          /* minimum percentage of free blocks */
        !           136: 
        !           137: /* These fields can be computed from the others. */
        !           138:        u_int64_t lfs_maxfilesize;      /* maximum representable file size */
        !           139:        u_int32_t lfs_dbpseg;           /* disk blocks per segment */
        !           140:        u_int32_t lfs_inopb;            /* inodes per block */
        !           141:        u_int32_t lfs_ifpb;             /* IFILE entries per block */
        !           142:        u_int32_t lfs_sepb;             /* SEGUSE entries per block */
        !           143:        u_int32_t lfs_nindir;           /* indirect pointers per block */
        !           144:        u_int32_t lfs_nseg;             /* number of segments */
        !           145:        u_int32_t lfs_nspf;             /* number of sectors per fragment */
        !           146:        u_int32_t lfs_cleansz;          /* cleaner info size in blocks */
        !           147:        u_int32_t lfs_segtabsz;         /* segment table size in blocks */
        !           148: 
        !           149:        u_int32_t lfs_segmask;          /* calculate offset within a segment */
        !           150:        u_int32_t lfs_segshift;         /* fast mult/div for segments */
        !           151:        u_int32_t lfs_bmask;            /* calc block offset from file offset */
        !           152:        u_int32_t lfs_bshift;           /* calc block number from file offset */
        !           153:        u_int32_t lfs_ffmask;           /* calc frag offset from file offset */
        !           154:        u_int32_t lfs_ffshift;          /* fast mult/div for frag from file */
        !           155:        u_int32_t lfs_fbmask;           /* calc frag offset from block offset */
        !           156:        u_int32_t lfs_fbshift;          /* fast mult/div for frag from block */
        !           157:        u_int32_t lfs_fsbtodb;          /* fsbtodb and dbtofsb shift constant */
        !           158:        u_int32_t lfs_sushift;          /* fast mult/div for segusage table */
        !           159: 
        !           160:        int32_t   lfs_maxsymlinklen;    /* max length of an internal symlink */
        !           161: 
        !           162: #define        LFS_MIN_SBINTERVAL      5       /* minimum superblock segment spacing */
        !           163: #define        LFS_MAXNUMSB            10      /* superblock disk offsets */
        !           164:        daddr_t   lfs_sboffs[LFS_MAXNUMSB];
        !           165: 
        !           166: /* Checksum -- last valid disk field. */
        !           167:        u_int32_t lfs_cksum;            /* checksum for superblock checking */
        !           168: 
        !           169: /* These fields are set at mount time and are meaningless on disk. */
        !           170:        struct segment *lfs_sp;         /* current segment being written */
        !           171:        struct vnode *lfs_ivnode;       /* vnode for the ifile */
        !           172:        u_long    lfs_seglock;          /* single-thread the segment writer */
        !           173:        pid_t     lfs_lockpid;          /* pid of lock holder */
        !           174:        u_long    lfs_iocount;          /* number of ios pending */
        !           175:        u_long    lfs_writer;           /* don't allow any dirops to start */
        !           176:        u_long    lfs_dirops;           /* count of active directory ops */
        !           177:        u_long    lfs_doifile;          /* Write ifile blocks on next write */
        !           178:        u_long    lfs_nactive;          /* Number of segments since last ckp */
        !           179:        int8_t    lfs_fmod;             /* super block modified flag */
        !           180:        int8_t    lfs_clean;            /* file system is clean flag */
        !           181:        int8_t    lfs_ronly;            /* mounted read-only flag */
        !           182:        int8_t    lfs_flags;            /* currently unused flag */
        !           183:        u_char    lfs_fsmnt[MNAMELEN];  /* name mounted on */
        !           184: 
        !           185:        int32_t   lfs_pad[40];          /* round to 512 bytes */
        !           186: };
        !           187: 
        !           188: /*
        !           189:  * Inode 0:    out-of-band inode number
        !           190:  * Inode 1:    IFILE inode number
        !           191:  * Inode 2:    root inode
        !           192:  * Inode 3:    lost+found inode number
        !           193:  */
        !           194: #define        LFS_UNUSED_INUM 0               /* out of band inode number */
        !           195: #define        LFS_IFILE_INUM  1               /* IFILE inode number */
        !           196: #define        LOSTFOUNDINO    3               /* lost+found inode number */
        !           197: #define        LFS_FIRST_INUM  4               /* first free inode number */
        !           198: 
        !           199: /* Address calculations for metadata located in the inode */
        !           200: #define        S_INDIR(fs)     -NDADDR
        !           201: #define        D_INDIR(fs)     (S_INDIR(fs) - NINDIR(fs) - 1)
        !           202: #define        T_INDIR(fs)     (D_INDIR(fs) - NINDIR(fs) * NINDIR(fs) - 1)
        !           203: 
        !           204: /* Unassigned disk address. */
        !           205: #define        UNASSIGNED      -1
        !           206: 
        !           207: /* Unused logical block number */
        !           208: #define LFS_UNUSED_LBN -1
        !           209: 
        !           210: typedef struct ifile IFILE;
        !           211: struct ifile {
        !           212:        u_int32_t if_version;           /* inode version number */
        !           213: #define        LFS_UNUSED_DADDR        0       /* out-of-band daddr */
        !           214:        daddr_t   if_daddr;             /* inode disk address */
        !           215:        ino_t     if_nextfree;          /* next-unallocated inode */
        !           216: };
        !           217: 
        !           218: /*
        !           219:  * Cleaner information structure.  This resides in the ifile and is used
        !           220:  * to pass information between the cleaner and the kernel.
        !           221:  */
        !           222: typedef struct _cleanerinfo {
        !           223:        u_int32_t clean;                /* K: number of clean segments */
        !           224:        u_int32_t dirty;                /* K: number of dirty segments */
        !           225: } CLEANERINFO;
        !           226: 
        !           227: #define        CLEANSIZE_SU(fs)                                                \
        !           228:        ((sizeof(CLEANERINFO) + (fs)->lfs_bsize - 1) >> (fs)->lfs_bshift)
        !           229: 
        !           230: /*
        !           231:  * All summary blocks are the same size, so we can always read a summary
        !           232:  * block easily from a segment.
        !           233:  */
        !           234: #define        LFS_SUMMARY_SIZE        512
        !           235: 
        !           236: /* On-disk segment summary information */
        !           237: typedef struct segsum SEGSUM;
        !           238: struct segsum {
        !           239:        u_int32_t ss_sumsum;            /* check sum of summary block */
        !           240:        u_int32_t ss_datasum;           /* check sum of data */
        !           241:        daddr_t   ss_next;              /* next segment */
        !           242:        u_int32_t ss_create;            /* creation time stamp */
        !           243:        u_int16_t ss_nfinfo;            /* number of file info structures */
        !           244:        u_int16_t ss_ninos;             /* number of inodes in summary */
        !           245: 
        !           246: #define        SS_DIROP        0x01            /* segment begins a dirop */
        !           247: #define        SS_CONT         0x02            /* more partials to finish this write*/
        !           248:        u_int16_t ss_flags;             /* used for directory operations */
        !           249:        u_int16_t ss_pad;               /* extra space */
        !           250:        /* FINFO's and inode daddr's... */
        !           251: };
        !           252: 
        !           253: /* NINDIR is the number of indirects in a file system block. */
        !           254: #define        NINDIR(fs)      ((fs)->lfs_nindir)
        !           255: 
        !           256: /* INOPB is the number of inodes in a secondary storage block. */
        !           257: #define        INOPB(fs)       ((fs)->lfs_inopb)
        !           258: 
        !           259: #define        blksize(fs)             ((fs)->lfs_bsize)
        !           260: #define        blkoff(fs, loc)         ((loc) & (fs)->lfs_bmask)
        !           261: #define        fsbtodb(fs, b)          ((b) << (fs)->lfs_fsbtodb)
        !           262: #define        dbtofsb(fs, b)          ((b) >> (fs)->lfs_fsbtodb)
        !           263: #define        lblkno(fs, loc)         ((loc) >> (fs)->lfs_bshift)
        !           264: #define        lblktosize(fs, blk)     ((blk) << (fs)->lfs_bshift)
        !           265: #define numfrags(fs, loc)      /* calculates (loc / fs->fs_fsize) */   \
        !           266:        ((loc) >> (fs)->lfs_bshift)
        !           267: 
        !           268: #define        datosn(fs, daddr)       /* disk address to segment number */    \
        !           269:        (((daddr) - (fs)->lfs_sboffs[0]) / fsbtodb((fs), (fs)->lfs_ssize))
        !           270: #define sntoda(fs, sn)                 /* segment number to disk address */    \
        !           271:        ((daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) +      \
        !           272:            (fs)->lfs_sboffs[0]))
        !           273: 
        !           274: /* Read in the block with the cleaner info from the ifile. */
        !           275: #define LFS_CLEANERINFO(CP, F, BP) {                                   \
        !           276:        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        !           277:        if (bread((F)->lfs_ivnode,                                      \
        !           278:            (daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP)))                 \
        !           279:                panic("lfs: ifile read");                               \
        !           280:        (CP) = (CLEANERINFO *)(BP)->b_data;                             \
        !           281: }
        !           282: 
        !           283: /* Read in the block with a specific inode from the ifile. */
        !           284: #define        LFS_IENTRY(IP, F, IN, BP) {                                     \
        !           285:        int _e;                                                         \
        !           286:        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        !           287:        if (_e = bread((F)->lfs_ivnode,                                 \
        !           288:            (IN) / (F)->lfs_ifpb + (F)->lfs_cleansz + (F)->lfs_segtabsz,\
        !           289:            (F)->lfs_bsize, NOCRED, &(BP)))                             \
        !           290:                panic("lfs: ifile read %d", _e);                        \
        !           291:        (IP) = (IFILE *)(BP)->b_data + (IN) % (F)->lfs_ifpb;            \
        !           292: }
        !           293: 
        !           294: /* Read in the block with a specific segment usage entry from the ifile. */
        !           295: #define        LFS_SEGENTRY(SP, F, IN, BP) {                                   \
        !           296:        int _e;                                                         \
        !           297:        VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS;                     \
        !           298:        if (_e = bread((F)->lfs_ivnode,                                 \
        !           299:            ((IN) >> (F)->lfs_sushift) + (F)->lfs_cleansz,              \
        !           300:            (F)->lfs_bsize, NOCRED, &(BP)))                             \
        !           301:                panic("lfs: ifile read: %d", _e);                       \
        !           302:        (SP) = (SEGUSE *)(BP)->b_data + ((IN) & (F)->lfs_sepb - 1);     \
        !           303: }
        !           304: 
        !           305: /* 
        !           306:  * Determine if there is enough room currently available to write db
        !           307:  * disk blocks.  We need enough blocks for the new blocks, the current,
        !           308:  * inode blocks, a summary block, plus potentially the ifile inode and
        !           309:  * the segment usage table, plus an ifile page.
        !           310:  */
        !           311: #define LFS_FITS(fs, db)                                               \
        !           312:        ((int32_t)((db + ((fs)->lfs_uinodes + INOPB((fs))) /            \
        !           313:        INOPB((fs)) + fsbtodb(fs, 1) + LFS_SUMMARY_SIZE / DEV_BSIZE +   \
        !           314:        (fs)->lfs_segtabsz)) < (fs)->lfs_avail)
        !           315: 
        !           316: /* Determine if a buffer belongs to the ifile */
        !           317: #define IS_IFILE(bp)   (VTOI(bp->b_vp)->i_number == LFS_IFILE_INUM)
        !           318: 
        !           319: /*
        !           320:  * Structures used by lfs_bmapv and lfs_markv to communicate information
        !           321:  * about inodes and data blocks.
        !           322:  */
        !           323: typedef struct block_info {
        !           324:        ino_t   bi_inode;               /* inode # */
        !           325:        daddr_t bi_lbn;                 /* logical block w/in file */
        !           326:        daddr_t bi_daddr;               /* disk address of block */
        !           327:        time_t  bi_segcreate;           /* origin segment create time */
        !           328:        int     bi_version;             /* file version number */
        !           329:        void    *bi_bp;                 /* data buffer */
        !           330: } BLOCK_INFO;
        !           331: 
        !           332: /* In-memory description of a segment about to be written. */
        !           333: struct segment {
        !           334:        struct lfs       *fs;           /* file system pointer */
        !           335:        struct buf      **bpp;          /* pointer to buffer array */
        !           336:        struct buf      **cbpp;         /* pointer to next available bp */
        !           337:        struct buf      **start_bpp;    /* pointer to first bp in this set */
        !           338:        struct buf       *ibp;          /* buffer pointer to inode page */
        !           339:        struct finfo     *fip;          /* current fileinfo pointer */
        !           340:        struct vnode     *vp;           /* vnode being gathered */
        !           341:        void     *segsum;               /* segment summary info */
        !           342:        u_int32_t ninodes;              /* number of inodes in this segment */
        !           343:        u_int32_t seg_bytes_left;       /* bytes left in segment */
        !           344:        u_int32_t sum_bytes_left;       /* bytes left in summary block */
        !           345:        u_int32_t seg_number;           /* number of this segment */
        !           346:        daddr_t  *start_lbp;            /* beginning lbn for this set */
        !           347: 
        !           348: #define        SEGM_CKP        0x01            /* doing a checkpoint */
        !           349: #define        SEGM_CLEAN      0x02            /* cleaner call; don't sort */
        !           350: #define        SEGM_SYNC       0x04            /* wait for segment */
        !           351:        u_int16_t seg_flags;            /* run-time flags for this segment */
        !           352: };
        !           353: 
        !           354: #define ISSPACE(F, BB, C)                                              \
        !           355:        (((C)->cr_uid == 0 && (F)->lfs_bfree >= (BB)) ||                \
        !           356:        ((C)->cr_uid != 0 && IS_FREESPACE(F, BB)))
        !           357: 
        !           358: #define IS_FREESPACE(F, BB)                                            \
        !           359:        ((F)->lfs_bfree > ((F)->lfs_dsize * (F)->lfs_minfree / 100 + (BB)))
        !           360: 
        !           361: #define ISSPACE_XXX(F, BB)                                             \
        !           362:        ((F)->lfs_bfree >= (BB))
        !           363: 
        !           364: #define DOSTATS
        !           365: #ifdef DOSTATS
        !           366: /* Statistics Counters */
        !           367: struct lfs_stats {
        !           368:        u_int   segsused;
        !           369:        u_int   psegwrites;
        !           370:        u_int   psyncwrites;
        !           371:        u_int   pcleanwrites;
        !           372:        u_int   blocktot;
        !           373:        u_int   cleanblocks;
        !           374:        u_int   ncheckpoints;
        !           375:        u_int   nwrites;
        !           376:        u_int   nsync_writes;
        !           377:        u_int   wait_exceeded;
        !           378:        u_int   write_exceeded;
        !           379:        u_int   flush_invoked;
        !           380: };
        !           381: extern struct lfs_stats lfs_stats;
        !           382: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.