lfs_ubwrite fixed
[unix-history] / usr / src / sys / ufs / lfs / lfs.h
index c89686d..89cdd1a 100644 (file)
@@ -4,17 +4,9 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)lfs.h       5.7 (Berkeley) %G%
+ *     @(#)lfs.h       7.13 (Berkeley) %G%
  */
 
  */
 
-typedef struct buf     BUF;
-typedef struct dinode  DINODE;
-typedef struct inode   INODE;
-typedef struct mount   MOUNT;
-typedef struct ucred   UCRED;
-typedef struct ufsmount        UFSMOUNT;
-typedef struct vnode   VNODE;
-
 #define        LFS_LABELPAD    8192            /* LFS label size */
 #define        LFS_SBPAD       8192            /* LFS superblock size */
 #define MAXMNTLEN      512             /* XXX move from fs.h to mount.h */
 #define        LFS_LABELPAD    8192            /* LFS label size */
 #define        LFS_SBPAD       8192            /* LFS superblock size */
 #define MAXMNTLEN      512             /* XXX move from fs.h to mount.h */
@@ -24,10 +16,16 @@ typedef struct segusage SEGUSE;
 struct segusage {
        u_long  su_nbytes;              /* number of live bytes */
        u_long  su_lastmod;             /* SEGUSE last modified timestamp */
 struct segusage {
        u_long  su_nbytes;              /* number of live bytes */
        u_long  su_lastmod;             /* SEGUSE last modified timestamp */
-#define        SEGUSE_DIRTY    0x1             /* XXX fill in comment */
+#define        SEGUSE_ACTIVE           0x1     /* segment is currently being written */
+#define        SEGUSE_DIRTY            0x2     /* segment has data in it */
+#define        SEGUSE_SUPERBLOCK       0x4     /* segment contains a superblock */
        u_long  su_flags;
 };
 
        u_long  su_flags;
 };
 
+#define        SEGTABSIZE_SU(fs) \
+       (((fs)->lfs_nseg * sizeof(SEGUSE) + \
+       ((fs)->lfs_bsize - 1)) >> (fs)->lfs_bshift)
+
 /* On-disk file information.  One per file with data blocks in the segment. */
 typedef struct finfo FINFO;
 struct finfo {
 /* On-disk file information.  One per file with data blocks in the segment. */
 typedef struct finfo FINFO;
 struct finfo {
@@ -37,29 +35,9 @@ struct finfo {
        long    fi_blocks[1];           /* array of logical block numbers */
 };
 
        long    fi_blocks[1];           /* array of logical block numbers */
 };
 
-/* In-memory description of a segment about to be written */
-typedef struct segment SEGMENT;
-struct segment {
-       SEGMENT *nextp;                 /* links segments together */
-       BUF     **bpp;                  /* pointer to buffer array */
-       BUF     **cbpp;                 /* pointer to next available bp */
-       BUF     *ibp;                   /* buffer pointer to inode page */
-       BUF     *sbp;                   /* segment summary buffer pointer */
-       void    *segsum;                /* segment Summary info */
-       u_long  seg_bytes_left;         /* bytes left in segment */
-       u_long  sum_bytes_left;         /* bytes left in summary block */
-       daddr_t saddr;                  /* current disk address */
-       daddr_t sum_addr;               /* address of current summary */
-       u_long  ninodes;                /* number of inodes in this segment */
-       u_long  nsums;                  /* number of SEGSUMs in this segment */
-       u_long  seg_number;             /* number of this segment */
-       FINFO   *fip;                   /* current fileinfo pointer */
-};
-
 /* On-disk and in-memory super block. */
 /* On-disk and in-memory super block. */
-typedef struct lfs LFS;
 struct lfs {
 struct lfs {
-#define        LFS_MAGIC       0xbedead
+#define        LFS_MAGIC       0x070162
        u_long  lfs_magic;              /* magic number */
 #define        LFS_VERSION     1
        u_long  lfs_version;            /* version number */
        u_long  lfs_magic;              /* magic number */
 #define        LFS_VERSION     1
        u_long  lfs_version;            /* version number */
@@ -79,17 +57,22 @@ struct lfs {
        ino_t   lfs_ifile;              /* inode file inode number */
        daddr_t lfs_lastseg;            /* address of last segment written */
        daddr_t lfs_nextseg;            /* address of next segment to write */
        ino_t   lfs_ifile;              /* inode file inode number */
        daddr_t lfs_lastseg;            /* address of last segment written */
        daddr_t lfs_nextseg;            /* address of next segment to write */
+       daddr_t lfs_curseg;             /* current segment being written */
+       daddr_t lfs_offset;             /* offset in curseg for next partial */
        u_long  lfs_tstamp;             /* time stamp */
 
 /* These are configuration parameters. */
        u_long  lfs_minfree;            /* minimum percentage of free blocks */
 
 /* These fields can be computed from the others. */
        u_long  lfs_tstamp;             /* time stamp */
 
 /* These are configuration parameters. */
        u_long  lfs_minfree;            /* minimum percentage of free blocks */
 
 /* These fields can be computed from the others. */
+       u_long  lfs_dbpseg;             /* disk blocks per segment */
        u_long  lfs_inopb;              /* inodes per block */
        u_long  lfs_ifpb;               /* IFILE entries per block */
        u_long  lfs_inopb;              /* inodes per block */
        u_long  lfs_ifpb;               /* IFILE entries per block */
+       u_long  lfs_sepb;               /* SEGUSE entries per block */
        u_long  lfs_nindir;             /* indirect pointers per block */
        u_long  lfs_nseg;               /* number of segments */
        u_long  lfs_nspf;               /* number of sectors per fragment */
        u_long  lfs_nindir;             /* indirect pointers per block */
        u_long  lfs_nseg;               /* number of segments */
        u_long  lfs_nspf;               /* number of sectors per fragment */
+       u_long  lfs_cleansz;            /* cleaner info size in blocks */
        u_long  lfs_segtabsz;           /* segment table size in blocks */
 
        u_long  lfs_segmask;            /* calculate offset within a segment */
        u_long  lfs_segtabsz;           /* segment table size in blocks */
 
        u_long  lfs_segmask;            /* calculate offset within a segment */
@@ -107,9 +90,10 @@ struct lfs {
        daddr_t lfs_sboffs[LFS_MAXNUMSB];
 
 /* These fields are set at mount time and are meaningless on disk. */
        daddr_t lfs_sboffs[LFS_MAXNUMSB];
 
 /* These fields are set at mount time and are meaningless on disk. */
-       VNODE   *lfs_ivnode;            /* vnode for the ifile */
+       struct  vnode *lfs_ivnode;      /* vnode for the ifile */
        SEGUSE  *lfs_segtab;            /* in-memory segment usage table */
        SEGUSE  *lfs_segtab;            /* in-memory segment usage table */
-       SEGMENT *lfs_seglist;           /* list of segments being written */
+                                       /* XXX NOT USED */
+       void    *XXXlfs_seglist;        /* list of segments being written */
        u_long  lfs_iocount;            /* number of ios pending */
        u_char  lfs_fmod;               /* super block modified flag */
        u_char  lfs_clean;              /* file system is clean flag */
        u_long  lfs_iocount;            /* number of ios pending */
        u_char  lfs_fmod;               /* super block modified flag */
        u_char  lfs_clean;              /* file system is clean flag */
@@ -123,18 +107,15 @@ struct lfs {
 };
 
 /*
 };
 
 /*
- * The root inode is the root of the file system.  Inode 0 is the out-of-band
- * inode, and inode 1 is the inode number for the ifile.  Thus the root inode
- * is 2.
+ * Inode 0 is the out-of-band inode number, inode 1 is the inode number for
+ * the IFILE, the root inode is 2 and the lost+found inode is 3.
  */
  */
-#define ROOTINO         ((ino_t)2)
-#define        LOSTFOUNDINO    ((ino_t)3)
 
 /* Fixed inode numbers. */
 #define        LFS_UNUSED_INUM 0               /* out of band inode number */
 
 /* Fixed inode numbers. */
 #define        LFS_UNUSED_INUM 0               /* out of band inode number */
-#define        LFS_IFILE_INUM  1               /* inode number of the ifile */
-                                       /* first free inode number */
-#define        LFS_FIRST_INUM  (LOSTFOUNDINO + 1)
+#define        LFS_IFILE_INUM  1               /* IFILE inode number */
+#define        LOSTFOUNDINO    3               /* lost+found inode number */
+#define        LFS_FIRST_INUM  4               /* first free inode number */
 
 /*
  * Used to access the first spare of the dinode which we use to store
 
 /*
  * Used to access the first spare of the dinode which we use to store
@@ -142,10 +123,16 @@ struct lfs {
  */
 #define        di_inum di_spare[0]
 
  */
 #define        di_inum di_spare[0]
 
-/* Logical block numbers of indirect blocks. */
-#define S_INDIR        -1
-#define D_INDIR -2
-#define T_INDIR -3
+/* Address calculations for metadata located in the inode */
+#define        S_INDIR(fs)     -NDADDR
+#define        D_INDIR(fs)     (S_INDIR(fs) - NINDIR(fs) - 1)
+#define        T_INDIR(fs)     (D_INDIR(fs) - NINDIR(fs) * NINDIR(fs) - 1)
+
+/* Structure used to pass around logical block paths. */
+typedef struct _indir {
+       long    in_lbn;                 /* logical block number */
+       int     in_off;                 /* offset in buffer */
+} INDIR;
 
 /* Unassigned disk address. */
 #define        UNASSIGNED      -1
 
 /* Unassigned disk address. */
 #define        UNASSIGNED      -1
@@ -155,22 +142,20 @@ struct ifile {
        u_long  if_version;             /* inode version number */
 #define        LFS_UNUSED_DADDR        0       /* out-of-band daddr */
        daddr_t if_daddr;               /* inode disk address */
        u_long  if_version;             /* inode version number */
 #define        LFS_UNUSED_DADDR        0       /* out-of-band daddr */
        daddr_t if_daddr;               /* inode disk address */
-       union {
-               ino_t   nextfree;       /* next-unallocated inode */
-               time_t  st_atime;       /* access time */
-       } __ifile_u;
-#define        if_st_atime     __ifile_u.st_atime
-#define        if_nextfree     __ifile_u.nextfree
+       ino_t   if_nextfree;            /* next-unallocated inode */
 };
 
 };
 
-/* Segment table size, in blocks. */
-#define        SEGTABSIZE(fs) \
-       (((fs)->fs_nseg * sizeof(SEGUSE) + \
-           ((fs)->fs_bsize - 1)) >> (fs)->fs_bshift)
+/*
+ * Cleaner information structure.  This resides in the ifile and is used
+ * to pass information between the cleaner and the kernel.
+ */
+typedef struct _cleanerinfo {
+       u_long  clean;                  /* K: number of clean segments */
+       u_long  dirty;                  /* K: number of dirty segments */
+} CLEANERINFO;
 
 
-#define        SEGTABSIZE_SU(fs) \
-       (((fs)->lfs_nseg * sizeof(SEGUSE) + \
-           ((fs)->lfs_bsize - 1)) >> (fs)->lfs_bshift)
+#define        CLEANSIZE_SU(fs) \
+       ((sizeof(CLEANERINFO) + (fs)->lfs_bsize - 1) >> (fs)->lfs_bshift)
 
 /*
  * All summary blocks are the same size, so we can always read a summary
 
 /*
  * All summary blocks are the same size, so we can always read a summary
@@ -181,14 +166,13 @@ struct ifile {
 /* On-disk segment summary information */
 typedef struct segsum SEGSUM;
 struct segsum {
 /* On-disk segment summary information */
 typedef struct segsum SEGSUM;
 struct segsum {
-       u_long  ss_cksum;               /* check sum */
+       u_long  ss_sumsum;              /* check sum of summary block */
+       u_long  ss_datasum;             /* check sum of data */
        daddr_t ss_next;                /* next segment */
        daddr_t ss_next;                /* next segment */
-       daddr_t ss_prev;                /* next segment */
-       daddr_t ss_nextsum;             /* next summary block */
        u_long  ss_create;              /* creation time stamp */
        u_long  ss_nfinfo;              /* number of file info structures */
        u_long  ss_create;              /* creation time stamp */
        u_long  ss_nfinfo;              /* number of file info structures */
-       u_long  ss_ninos;               /* number of inode blocks */
-       /* FINFO's... */
+       u_long  ss_ninos;               /* number of inodes in summary */
+       /* FINFO's and inode daddr's... */
 };
 
 /* NINDIR is the number of indirects in a file system block. */
 };
 
 /* NINDIR is the number of indirects in a file system block. */
@@ -197,9 +181,6 @@ struct segsum {
 /* INOPB is the number of inodes in a secondary storage block. */
 #define        INOPB(fs)       ((fs)->lfs_inopb)
 
 /* INOPB is the number of inodes in a secondary storage block. */
 #define        INOPB(fs)       ((fs)->lfs_inopb)
 
-/* IFPB -- IFILE's per block */
-#define        IFPB(fs)        ((fs)->lfs_ifpb)
-
 #define        blksize(fs)             ((fs)->lfs_bsize)
 #define        blkoff(fs, loc)         ((loc) & (fs)->lfs_bmask)
 #define        fsbtodb(fs, b)          ((b) << (fs)->lfs_fsbtodb)
 #define        blksize(fs)             ((fs)->lfs_bsize)
 #define        blkoff(fs, loc)         ((loc) & (fs)->lfs_bmask)
 #define        fsbtodb(fs, b)          ((b) << (fs)->lfs_fsbtodb)
@@ -213,3 +194,55 @@ struct segsum {
 #define sntoda(fs, sn)                 /* segment number to disk address */ \
        ((daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \
            (fs)->lfs_sboffs[0]))
 #define sntoda(fs, sn)                 /* segment number to disk address */ \
        ((daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \
            (fs)->lfs_sboffs[0]))
+
+/* Read in the block with the cleaner info from the ifile. */
+#define LFS_CLEANERINFO(CP, F, BP) { \
+       VTOI((F)->lfs_ivnode)->i_flag |= IACC; \
+       if (bread((F)->lfs_ivnode, (daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP))) \
+               panic("lfs: ifile read"); \
+       (CP) = (CLEANERINFO *)(BP)->b_un.b_addr; \
+}
+
+/* Read in the block with a specific inode from the ifile. */
+#define        LFS_IENTRY(IP, F, IN, BP) { \
+       VTOI((F)->lfs_ivnode)->i_flag |= IACC; \
+       if (bread((F)->lfs_ivnode, \
+           (IN) / (F)->lfs_ifpb + (F)->lfs_cleansz + (F)->lfs_segtabsz, \
+           (F)->lfs_bsize, NOCRED, &(BP))) \
+               panic("lfs: ifile read"); \
+       (IP) = (IFILE *)(BP)->b_un.b_addr + (IN) % (F)->lfs_ifpb; \
+}
+
+/* Read in the block with a specific segment usage entry from the ifile. */
+#define        LFS_SEGENTRY(SP, F, IN, BP) { \
+       VTOI((F)->lfs_ivnode)->i_flag |= IACC; \
+       if (bread((F)->lfs_ivnode, (IN) / (F)->lfs_sepb + (F)->lfs_cleansz, \
+           (F)->lfs_bsize, NOCRED, &(BP))) \
+               panic("lfs: ifile read"); \
+       (SP) = (SEGUSE *)(BP)->b_un.b_addr + (IN) % (F)->lfs_sepb; \
+}
+
+/* Write a block and update the inode change times. */
+#define        LFS_UBWRITE(BP) { \
+       VTOI((BP)->b_vp)->i_flag |= ICHG | IUPD; \
+       lfs_bwrite(BP); \
+}
+
+/*
+ * Structures used by lfs_bmapv and lfs_markv to communicate information
+ * about inodes and data blocks.
+ */
+typedef struct block_info {
+       ino_t   bi_inode;               /* inode # */
+       off_t   bi_lbn;                 /* logical block w/in file */
+       daddr_t bi_daddr;               /* disk address of block */
+       time_t  bi_segcreate;           /* origin segment create time */
+       void    *bi_bp;                 /* data buffer */
+} BLOCK_INFO;
+
+typedef struct inode_info {
+       ino_t   ii_inode;               /* inode # */
+       daddr_t ii_daddr;               /* disk address of block */
+       time_t  ii_segcreate;           /* origin segment create time */
+       struct dinode *ii_dinode;       /* data buffer */
+} INODE_INFO;