151139Sbostic /*- 263375Sbostic * Copyright (c) 1991, 1993 363375Sbostic * The Regents of the University of California. All rights reserved. 451139Sbostic * 551139Sbostic * %sccs.include.redist.c% 651139Sbostic * 7*64607Sbostic * @(#)lfs.h 8.3 (Berkeley) 09/23/93 851139Sbostic */ 951139Sbostic 1051140Sbostic #define LFS_LABELPAD 8192 /* LFS label size */ 1151140Sbostic #define LFS_SBPAD 8192 /* LFS superblock size */ 1251139Sbostic 1355546Sbostic /* 1455546Sbostic * XXX 1555546Sbostic * This is a kluge and NEEDS to go away. 1655546Sbostic * 1755546Sbostic * Right now, ufs code handles most of the calls for directory operations 1855546Sbostic * such as create, mkdir, link, etc. As a result VOP_UPDATE is being 1955546Sbostic * called with waitfor set (since ffs does these things synchronously). 2055546Sbostic * Since LFS does not want to do these synchronously, we treat the last 2155546Sbostic * argument to lfs_update as a set of flags. If LFS_SYNC is set, then 2255546Sbostic * the update should be synchronous, if not, do it asynchronously. 2355546Sbostic * Unfortunately, this means that LFS won't work with NFS yet because 2455546Sbostic * NFS goes through paths that will make normal calls to ufs which will 2555546Sbostic * call lfs with a last argument of 1. 2655546Sbostic */ 2755546Sbostic #define LFS_SYNC 0x02 2855546Sbostic 2951155Sbostic /* On-disk and in-memory checkpoint segment usage structure. */ 3051183Sbostic typedef struct segusage SEGUSE; 3151183Sbostic struct segusage { 3251155Sbostic u_long su_nbytes; /* number of live bytes */ 3351350Sbostic u_long su_lastmod; /* SEGUSE last modified timestamp */ 3455587Sbostic u_short su_nsums; /* number of summaries in segment */ 3555587Sbostic u_short su_ninos; /* number of inode blocks in seg */ 3651912Sbostic #define SEGUSE_ACTIVE 0x1 /* segment is currently being written */ 3751912Sbostic #define SEGUSE_DIRTY 0x2 /* segment has data in it */ 3851912Sbostic #define SEGUSE_SUPERBLOCK 0x4 /* segment contains a superblock */ 3951155Sbostic u_long su_flags; 4051183Sbostic }; 4151155Sbostic 4255793Sbostic #define SEGUPB(fs) (1 << (fs)->lfs_sushift) 43*64607Sbostic #define SEGTABSIZE_SU(fs) \ 4455793Sbostic (((fs)->lfs_nseg + SEGUPB(fs) - 1) >> (fs)->lfs_sushift) 4551850Sbostic 4651183Sbostic /* On-disk file information. One per file with data blocks in the segment. */ 4751183Sbostic typedef struct finfo FINFO; 4851183Sbostic struct finfo { 4951183Sbostic u_long fi_nblocks; /* number of blocks */ 5051183Sbostic u_long fi_version; /* version number */ 5151215Sbostic u_long fi_ino; /* inode number */ 5251183Sbostic long fi_blocks[1]; /* array of logical block numbers */ 5351183Sbostic }; 5451183Sbostic 5551155Sbostic /* On-disk and in-memory super block. */ 5651183Sbostic struct lfs { 5752149Sbostic #define LFS_MAGIC 0x070162 5851139Sbostic u_long lfs_magic; /* magic number */ 5951140Sbostic #define LFS_VERSION 1 6051139Sbostic u_long lfs_version; /* version number */ 6151139Sbostic 6251139Sbostic u_long lfs_size; /* number of blocks in fs */ 6351139Sbostic u_long lfs_ssize; /* number of blocks per segment */ 6456154Smargo u_long lfs_dsize; /* number of disk blocks in fs */ 6556154Smargo u_long lfs_bsize; /* file system block size */ 6651139Sbostic u_long lfs_fsize; /* size of frag blocks in fs */ 6751139Sbostic u_long lfs_frag; /* number of frags in a block in fs */ 6851139Sbostic 6951139Sbostic /* Checkpoint region. */ 7051139Sbostic ino_t lfs_free; /* start of the free list */ 7155587Sbostic u_long lfs_bfree; /* number of free disk blocks */ 7251155Sbostic u_long lfs_nfiles; /* number of allocated inodes */ 7356367Smargo long lfs_avail; /* blocks available for writing */ 7455934Sbostic u_long lfs_uinodes; /* inodes in cache not yet on disk */ 7551139Sbostic daddr_t lfs_idaddr; /* inode file disk address */ 7651139Sbostic ino_t lfs_ifile; /* inode file inode number */ 7751303Sbostic daddr_t lfs_lastseg; /* address of last segment written */ 7851303Sbostic daddr_t lfs_nextseg; /* address of next segment to write */ 7951912Sbostic daddr_t lfs_curseg; /* current segment being written */ 8051850Sbostic daddr_t lfs_offset; /* offset in curseg for next partial */ 8154264Sbostic daddr_t lfs_lastpseg; /* address of last partial written */ 8251139Sbostic u_long lfs_tstamp; /* time stamp */ 8351139Sbostic 8451139Sbostic /* These are configuration parameters. */ 8551139Sbostic u_long lfs_minfree; /* minimum percentage of free blocks */ 8651139Sbostic 8751139Sbostic /* These fields can be computed from the others. */ 8855454Sbostic u_quad_t lfs_maxfilesize; /* maximum representable file size */ 8951850Sbostic u_long lfs_dbpseg; /* disk blocks per segment */ 9051139Sbostic u_long lfs_inopb; /* inodes per block */ 9151139Sbostic u_long lfs_ifpb; /* IFILE entries per block */ 9251850Sbostic u_long lfs_sepb; /* SEGUSE entries per block */ 9351139Sbostic u_long lfs_nindir; /* indirect pointers per block */ 9451139Sbostic u_long lfs_nseg; /* number of segments */ 9551139Sbostic u_long lfs_nspf; /* number of sectors per fragment */ 9651850Sbostic u_long lfs_cleansz; /* cleaner info size in blocks */ 9751139Sbostic u_long lfs_segtabsz; /* segment table size in blocks */ 9851139Sbostic 9951139Sbostic u_long lfs_segmask; /* calculate offset within a segment */ 10051139Sbostic u_long lfs_segshift; /* fast mult/div for segments */ 10151139Sbostic u_long lfs_bmask; /* calc block offset from file offset */ 10251139Sbostic u_long lfs_bshift; /* calc block number from file offset */ 10351139Sbostic u_long lfs_ffmask; /* calc frag offset from file offset */ 10451139Sbostic u_long lfs_ffshift; /* fast mult/div for frag from file */ 10551139Sbostic u_long lfs_fbmask; /* calc frag offset from block offset */ 10651139Sbostic u_long lfs_fbshift; /* fast mult/div for frag from block */ 10751139Sbostic u_long lfs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ 10855587Sbostic u_long lfs_sushift; /* fast mult/div for segusage table */ 10951139Sbostic 11051155Sbostic #define LFS_MIN_SBINTERVAL 5 /* minimum superblock segment spacing */ 11151155Sbostic #define LFS_MAXNUMSB 10 /* superblock disk offsets */ 11251155Sbostic daddr_t lfs_sboffs[LFS_MAXNUMSB]; 11351139Sbostic 11451155Sbostic /* These fields are set at mount time and are meaningless on disk. */ 11557065Smargo struct segment *lfs_sp; /* current segment being written */ 11653146Sbostic struct vnode *lfs_ivnode; /* vnode for the ifile */ 11754685Sbostic u_long lfs_seglock; /* single-thread the segment writer */ 11857065Smargo pid_t lfs_lockpid; /* pid of lock holder */ 11951303Sbostic u_long lfs_iocount; /* number of ios pending */ 12054264Sbostic u_long lfs_writer; /* don't allow any dirops to start */ 12154264Sbostic u_long lfs_dirops; /* count of active directory ops */ 12254264Sbostic u_long lfs_doifile; /* Write ifile blocks on next write */ 12355934Sbostic u_long lfs_nactive; /* Number of segments since last ckp */ 12451155Sbostic u_char lfs_fmod; /* super block modified flag */ 12551155Sbostic u_char lfs_clean; /* file system is clean flag */ 12651155Sbostic u_char lfs_ronly; /* mounted read-only flag */ 12751155Sbostic u_char lfs_flags; /* currently unused flag */ 12854685Sbostic u_char lfs_fsmnt[MNAMELEN]; /* name mounted on */ 12951155Sbostic u_char pad[3]; /* long-align */ 13051139Sbostic 13151155Sbostic /* Checksum; valid on disk. */ 13251155Sbostic u_long lfs_cksum; /* checksum for superblock checking */ 13351183Sbostic }; 13451139Sbostic 13551155Sbostic /* 13652079Sbostic * Inode 0 is the out-of-band inode number, inode 1 is the inode number for 13752079Sbostic * the IFILE, the root inode is 2 and the lost+found inode is 3. 13851155Sbostic */ 13951139Sbostic 14051140Sbostic /* Fixed inode numbers. */ 14151303Sbostic #define LFS_UNUSED_INUM 0 /* out of band inode number */ 14252079Sbostic #define LFS_IFILE_INUM 1 /* IFILE inode number */ 14352079Sbostic #define LOSTFOUNDINO 3 /* lost+found inode number */ 14452079Sbostic #define LFS_FIRST_INUM 4 /* first free inode number */ 14551139Sbostic 14651850Sbostic /* Address calculations for metadata located in the inode */ 14751850Sbostic #define S_INDIR(fs) -NDADDR 14852997Sstaelin #define D_INDIR(fs) (S_INDIR(fs) - NINDIR(fs) - 1) 14952997Sstaelin #define T_INDIR(fs) (D_INDIR(fs) - NINDIR(fs) * NINDIR(fs) - 1) 15051183Sbostic 15151350Sbostic /* Unassigned disk address. */ 15251350Sbostic #define UNASSIGNED -1 15351350Sbostic 15455934Sbostic /* Unused logical block number */ 15555934Sbostic #define LFS_UNUSED_LBN -1 15655934Sbostic 15751183Sbostic typedef struct ifile IFILE; 15851183Sbostic struct ifile { 15951139Sbostic u_long if_version; /* inode version number */ 16051155Sbostic #define LFS_UNUSED_DADDR 0 /* out-of-band daddr */ 16151139Sbostic daddr_t if_daddr; /* inode disk address */ 16252079Sbostic ino_t if_nextfree; /* next-unallocated inode */ 16351183Sbostic }; 16451139Sbostic 16551850Sbostic /* 16651850Sbostic * Cleaner information structure. This resides in the ifile and is used 16751850Sbostic * to pass information between the cleaner and the kernel. 16851850Sbostic */ 16951850Sbostic typedef struct _cleanerinfo { 17051850Sbostic u_long clean; /* K: number of clean segments */ 17151850Sbostic u_long dirty; /* K: number of dirty segments */ 17251850Sbostic } CLEANERINFO; 17351139Sbostic 174*64607Sbostic #define CLEANSIZE_SU(fs) \ 17551850Sbostic ((sizeof(CLEANERINFO) + (fs)->lfs_bsize - 1) >> (fs)->lfs_bshift) 17651140Sbostic 17751140Sbostic /* 17851140Sbostic * All summary blocks are the same size, so we can always read a summary 17951303Sbostic * block easily from a segment. 18051140Sbostic */ 18151140Sbostic #define LFS_SUMMARY_SIZE 512 18251140Sbostic 18351139Sbostic /* On-disk segment summary information */ 18451183Sbostic typedef struct segsum SEGSUM; 18551183Sbostic struct segsum { 18651850Sbostic u_long ss_sumsum; /* check sum of summary block */ 18751850Sbostic u_long ss_datasum; /* check sum of data */ 18851139Sbostic daddr_t ss_next; /* next segment */ 18951139Sbostic u_long ss_create; /* creation time stamp */ 19054264Sbostic u_short ss_nfinfo; /* number of file info structures */ 19154264Sbostic u_short ss_ninos; /* number of inodes in summary */ 19254264Sbostic #define SS_DIROP 0x01 /* segment begins a dirop */ 19354264Sbostic #define SS_CONT 0x02 /* more partials to finish this write*/ 19454264Sbostic u_short ss_flags; /* used for directory operations */ 19554264Sbostic u_short ss_pad; /* extra space */ 19652993Sbostic /* FINFO's and inode daddr's... */ 19751183Sbostic }; 19851139Sbostic 19951155Sbostic /* NINDIR is the number of indirects in a file system block. */ 20051155Sbostic #define NINDIR(fs) ((fs)->lfs_nindir) 20151155Sbostic 20251155Sbostic /* INOPB is the number of inodes in a secondary storage block. */ 20351155Sbostic #define INOPB(fs) ((fs)->lfs_inopb) 20451155Sbostic 20551155Sbostic #define blksize(fs) ((fs)->lfs_bsize) 20651155Sbostic #define blkoff(fs, loc) ((loc) & (fs)->lfs_bmask) 20751155Sbostic #define fsbtodb(fs, b) ((b) << (fs)->lfs_fsbtodb) 20855587Sbostic #define dbtofsb(fs, b) ((b) >> (fs)->lfs_fsbtodb) 20951155Sbostic #define lblkno(fs, loc) ((loc) >> (fs)->lfs_bshift) 21051155Sbostic #define lblktosize(fs, blk) ((blk) << (fs)->lfs_bshift) 211*64607Sbostic #define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ 21251183Sbostic ((loc) >> (fs)->lfs_bshift) 21351350Sbostic 214*64607Sbostic #define datosn(fs, daddr) /* disk address to segment number */ \ 21552079Sbostic (((daddr) - (fs)->lfs_sboffs[0]) / fsbtodb((fs), (fs)->lfs_ssize)) 216*64607Sbostic #define sntoda(fs, sn) /* segment number to disk address */ \ 217*64607Sbostic ((daddr_t)((sn) * ((fs)->lfs_ssize << (fs)->lfs_fsbtodb) + \ 21852079Sbostic (fs)->lfs_sboffs[0])) 21952079Sbostic 22051925Sbostic /* Read in the block with the cleaner info from the ifile. */ 221*64607Sbostic #define LFS_CLEANERINFO(CP, F, BP) { \ 222*64607Sbostic VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 223*64607Sbostic if (bread((F)->lfs_ivnode, \ 224*64607Sbostic (daddr_t)0, (F)->lfs_bsize, NOCRED, &(BP))) \ 225*64607Sbostic panic("lfs: ifile read"); \ 226*64607Sbostic (CP) = (CLEANERINFO *)(BP)->b_data; \ 22751925Sbostic } 22851925Sbostic 22951850Sbostic /* Read in the block with a specific inode from the ifile. */ 230*64607Sbostic #define LFS_IENTRY(IP, F, IN, BP) { \ 231*64607Sbostic int _e; \ 232*64607Sbostic VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 233*64607Sbostic if (_e = bread((F)->lfs_ivnode, \ 234*64607Sbostic (IN) / (F)->lfs_ifpb + (F)->lfs_cleansz + (F)->lfs_segtabsz,\ 235*64607Sbostic (F)->lfs_bsize, NOCRED, &(BP))) \ 236*64607Sbostic panic("lfs: ifile read %d", _e); \ 237*64607Sbostic (IP) = (IFILE *)(BP)->b_data + (IN) % (F)->lfs_ifpb; \ 23851481Sbostic } 23951481Sbostic 24051850Sbostic /* Read in the block with a specific segment usage entry from the ifile. */ 241*64607Sbostic #define LFS_SEGENTRY(SP, F, IN, BP) { \ 242*64607Sbostic int _e; \ 243*64607Sbostic VTOI((F)->lfs_ivnode)->i_flag |= IN_ACCESS; \ 244*64607Sbostic if (_e = bread((F)->lfs_ivnode, \ 245*64607Sbostic ((IN) >> (F)->lfs_sushift) + (F)->lfs_cleansz, \ 246*64607Sbostic (F)->lfs_bsize, NOCRED, &(BP))) \ 247*64607Sbostic panic("lfs: ifile read: %d", _e); \ 248*64607Sbostic (SP) = (SEGUSE *)(BP)->b_data + ((IN) & (F)->lfs_sepb - 1); \ 24951850Sbostic } 25051850Sbostic 25155934Sbostic /* 25255934Sbostic * Determine if there is enough room currently available to write db 25355934Sbostic * disk blocks. We need enough blocks for the new blocks, the current, 25455934Sbostic * inode blocks, a summary block, plus potentially the ifile inode and 25555934Sbostic * the segment usage table, plus an ifile page. 25655934Sbostic */ 25755934Sbostic #define LFS_FITS(fs, db) \ 25856367Smargo ((long)((db + ((fs)->lfs_uinodes + INOPB((fs))) / INOPB((fs)) + \ 259*64607Sbostic fsbtodb(fs, 1) + LFS_SUMMARY_SIZE / DEV_BSIZE + \ 260*64607Sbostic (fs)->lfs_segtabsz)) < (fs)->lfs_avail) 26151936Sbostic 26255934Sbostic /* Determine if a buffer belongs to the ifile */ 26355934Sbostic #define IS_IFILE(bp) (VTOI(bp->b_vp)->i_number == LFS_IFILE_INUM) 264*64607Sbostic 26551850Sbostic /* 26651850Sbostic * Structures used by lfs_bmapv and lfs_markv to communicate information 26751850Sbostic * about inodes and data blocks. 26851850Sbostic */ 26951850Sbostic typedef struct block_info { 27051850Sbostic ino_t bi_inode; /* inode # */ 27155667Sbostic daddr_t bi_lbn; /* logical block w/in file */ 27251850Sbostic daddr_t bi_daddr; /* disk address of block */ 27351850Sbostic time_t bi_segcreate; /* origin segment create time */ 27456189Smargo int bi_version; /* file version number */ 27551850Sbostic void *bi_bp; /* data buffer */ 27651850Sbostic } BLOCK_INFO; 27751850Sbostic 27855934Sbostic /* In-memory description of a segment about to be written. */ 27955934Sbostic struct segment { 28055934Sbostic struct lfs *fs; /* file system pointer */ 28155934Sbostic struct buf **bpp; /* pointer to buffer array */ 28255934Sbostic struct buf **cbpp; /* pointer to next available bp */ 28355934Sbostic struct buf **start_bpp; /* pointer to first bp in this set */ 28455934Sbostic struct buf *ibp; /* buffer pointer to inode page */ 28555934Sbostic struct finfo *fip; /* current fileinfo pointer */ 28656024Sbostic struct vnode *vp; /* vnode being gathered */ 28755934Sbostic void *segsum; /* segment summary info */ 28855934Sbostic u_long ninodes; /* number of inodes in this segment */ 28955934Sbostic u_long seg_bytes_left; /* bytes left in segment */ 29055934Sbostic u_long sum_bytes_left; /* bytes left in summary block */ 29155934Sbostic u_long seg_number; /* number of this segment */ 29255934Sbostic daddr_t *start_lbp; /* beginning lbn for this set */ 29355934Sbostic #define SEGM_CKP 0x01 /* doing a checkpoint */ 29455934Sbostic #define SEGM_CLEAN 0x02 /* cleaner call; don't sort */ 29557065Smargo #define SEGM_SYNC 0x04 /* wait for segment */ 29655934Sbostic u_long seg_flags; /* run-time flags for this segment */ 29755934Sbostic }; 29856154Smargo 299*64607Sbostic #define ISSPACE(F, BB, C) \ 300*64607Sbostic (((C)->cr_uid == 0 && (F)->lfs_bfree >= (BB)) || \ 30156154Smargo ((C)->cr_uid != 0 && IS_FREESPACE(F, BB))) 30256154Smargo 303*64607Sbostic #define IS_FREESPACE(F, BB) \ 30456154Smargo ((F)->lfs_bfree > ((F)->lfs_dsize * (F)->lfs_minfree / 100 + (BB))) 30556154Smargo 306*64607Sbostic #define ISSPACE_XXX(F, BB) \ 30756154Smargo ((F)->lfs_bfree >= (BB)) 30856154Smargo 30957065Smargo #define DOSTATS 31057065Smargo #ifdef DOSTATS 31157065Smargo /* Statistics Counters */ 31257065Smargo struct lfs_stats { 31357065Smargo int segsused; 31457065Smargo int psegwrites; 31557065Smargo int psyncwrites; 31657065Smargo int pcleanwrites; 31757065Smargo int blocktot; 31857065Smargo int cleanblocks; 31957065Smargo int ncheckpoints; 32057065Smargo int nwrites; 32157065Smargo int nsync_writes; 32257065Smargo int wait_exceeded; 32357065Smargo int write_exceeded; 32457065Smargo int flush_invoked; 32557065Smargo }; 32657065Smargo extern struct lfs_stats lfs_stats; 32757065Smargo #endif 328