Annotation of XNU/bsd/ufs/lfs/lfs.h, revision 1.1.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.