1 /* $NetBSD: ulfs_inode.h,v 1.11 2014/03/18 18:20:44 riastradh Exp $ */ 2 /* from NetBSD: inode.h,v 1.64 2012/11/19 00:36:21 jakllsch Exp */ 3 4 /* 5 * Copyright (c) 1982, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)inode.h 8.9 (Berkeley) 5/14/95 38 */ 39 40 #ifndef _UFS_LFS_ULFS_INODE_H_ 41 #define _UFS_LFS_ULFS_INODE_H_ 42 43 #include <sys/vnode.h> 44 #include <ufs/lfs/lfs_inode.h> 45 #include <ufs/lfs/ulfs_dinode.h> 46 #include <ufs/lfs/ulfs_quotacommon.h> 47 48 /* 49 * These macros are used to bracket ULFS directory ops, so that we can 50 * identify all the pages touched during directory ops which need to 51 * be ordered and flushed atomically, so that they may be recovered. 52 * 53 * Because we have to mark nodes VU_DIROP in order to prevent 54 * the cache from reclaiming them while a dirop is in progress, we must 55 * also manage the number of nodes so marked (otherwise we can run out). 56 * We do this by setting lfs_dirvcount to the number of marked vnodes; it 57 * is decremented during segment write, when VU_DIROP is taken off. 58 */ 59 #define MARK_VNODE(vp) lfs_mark_vnode(vp) 60 #define UNMARK_VNODE(vp) lfs_unmark_vnode(vp) 61 #define SET_DIROP_CREATE(dvp, vpp) lfs_set_dirop_create((dvp), (vpp)) 62 #define SET_DIROP_REMOVE(dvp, vp) lfs_set_dirop((dvp), (vp)) 63 int lfs_set_dirop_create(struct vnode *, struct vnode **); 64 int lfs_set_dirop(struct vnode *, struct vnode *); 65 66 #define SET_ENDOP_BASE(fs, dvp, str) \ 67 do { \ 68 mutex_enter(&lfs_lock); \ 69 --(fs)->lfs_dirops; \ 70 if (!(fs)->lfs_dirops) { \ 71 if ((fs)->lfs_nadirop) { \ 72 panic("SET_ENDOP: %s: no dirops but " \ 73 " nadirop=%d", (str), \ 74 (fs)->lfs_nadirop); \ 75 } \ 76 wakeup(&(fs)->lfs_writer); \ 77 mutex_exit(&lfs_lock); \ 78 lfs_check((dvp), LFS_UNUSED_LBN, 0); \ 79 } else \ 80 mutex_exit(&lfs_lock); \ 81 } while(0) 82 #define SET_ENDOP_CREATE(fs, dvp, nvpp, str) \ 83 do { \ 84 UNMARK_VNODE(dvp); \ 85 if (nvpp && *nvpp) \ 86 UNMARK_VNODE(*nvpp); \ 87 /* Check for error return to stem vnode leakage */ \ 88 if (nvpp && *nvpp && !((*nvpp)->v_uflag & VU_DIROP)) \ 89 ungetnewvnode(*(nvpp)); \ 90 SET_ENDOP_BASE((fs), (dvp), (str)); \ 91 lfs_reserve((fs), (dvp), NULL, -LFS_NRESERVE(fs)); \ 92 vrele(dvp); \ 93 } while(0) 94 #define SET_ENDOP_CREATE_AP(ap, str) \ 95 SET_ENDOP_CREATE(VTOI((ap)->a_dvp)->i_lfs, (ap)->a_dvp, \ 96 (ap)->a_vpp, (str)) 97 #define SET_ENDOP_REMOVE(fs, dvp, ovp, str) \ 98 do { \ 99 UNMARK_VNODE(dvp); \ 100 if (ovp) \ 101 UNMARK_VNODE(ovp); \ 102 SET_ENDOP_BASE((fs), (dvp), (str)); \ 103 lfs_reserve((fs), (dvp), (ovp), -LFS_NRESERVE(fs)); \ 104 vrele(dvp); \ 105 if (ovp) \ 106 vrele(ovp); \ 107 } while(0) 108 109 110 111 /* Misc. definitions */ 112 #define BW_CLEAN 1 /* Flag for lfs_bwrite_ext() */ 113 #define PG_DELWRI PG_PAGER1 /* Local def for delayed pageout */ 114 115 /* Resource limits */ 116 #define LFS_MAX_RESOURCE(x, u) (((x) >> 2) - 10 * (u)) 117 #define LFS_WAIT_RESOURCE(x, u) (((x) >> 1) - ((x) >> 3) - 10 * (u)) 118 #define LFS_INVERSE_MAX_RESOURCE(x, u) (((x) + 10 * (u)) << 2) 119 #define LFS_MAX_BUFS LFS_MAX_RESOURCE(nbuf, 1) 120 #define LFS_WAIT_BUFS LFS_WAIT_RESOURCE(nbuf, 1) 121 #define LFS_INVERSE_MAX_BUFS(n) LFS_INVERSE_MAX_RESOURCE(n, 1) 122 #define LFS_MAX_BYTES LFS_MAX_RESOURCE(bufmem_lowater, PAGE_SIZE) 123 #define LFS_INVERSE_MAX_BYTES(n) LFS_INVERSE_MAX_RESOURCE(n, PAGE_SIZE) 124 #define LFS_WAIT_BYTES LFS_WAIT_RESOURCE(bufmem_lowater, PAGE_SIZE) 125 #define LFS_MAX_DIROP ((desiredvnodes >> 2) + (desiredvnodes >> 3)) 126 #define SIZEOF_DIROP(fs) (2 * ((fs)->lfs_bsize + LFS_DINODE1_SIZE)) 127 #define LFS_MAX_FSDIROP(fs) \ 128 ((fs)->lfs_nclean <= (fs)->lfs_resvseg ? 0 : \ 129 (((fs)->lfs_nclean - (fs)->lfs_resvseg) * (fs)->lfs_ssize) / \ 130 (2 * SIZEOF_DIROP(fs))) 131 #define LFS_MAX_PAGES lfs_max_pages() 132 #define LFS_WAIT_PAGES lfs_wait_pages() 133 #define LFS_BUFWAIT 2 /* How long to wait if over *_WAIT_* */ 134 135 #ifdef _KERNEL 136 extern u_long bufmem_lowater, bufmem_hiwater; /* XXX */ 137 138 int lfs_wait_pages(void); 139 int lfs_max_pages(void); 140 #endif /* _KERNEL */ 141 142 /* How starved can we be before we start holding back page writes */ 143 #define LFS_STARVED_FOR_SEGS(fs) ((fs)->lfs_nclean < (fs)->lfs_resvseg) 144 145 /* 146 * Reserved blocks for lfs_malloc 147 */ 148 149 /* Structure to keep reserved blocks */ 150 typedef struct lfs_res_blk { 151 void *p; 152 LIST_ENTRY(lfs_res_blk) res; 153 int size; 154 char inuse; 155 } res_t; 156 157 /* Types for lfs_newbuf and lfs_malloc */ 158 #define LFS_NB_UNKNOWN -1 159 #define LFS_NB_SUMMARY 0 160 #define LFS_NB_SBLOCK 1 161 #define LFS_NB_IBLOCK 2 162 #define LFS_NB_CLUSTER 3 163 #define LFS_NB_CLEAN 4 164 #define LFS_NB_BLKIOV 5 165 #define LFS_NB_COUNT 6 /* always last */ 166 167 /* Number of reserved memory blocks of each type */ 168 #define LFS_N_SUMMARIES 2 169 #define LFS_N_SBLOCKS 1 /* Always 1, to throttle superblock writes */ 170 #define LFS_N_IBLOCKS 16 /* In theory ssize/bsize; in practice around 2 */ 171 #define LFS_N_CLUSTERS 16 /* In theory ssize/MAXPHYS */ 172 #define LFS_N_CLEAN 0 173 #define LFS_N_BLKIOV 1 174 175 /* Total count of "large" (non-pool) types */ 176 #define LFS_N_TOTAL (LFS_N_SUMMARIES + LFS_N_SBLOCKS + LFS_N_IBLOCKS + \ 177 LFS_N_CLUSTERS + LFS_N_CLEAN + LFS_N_BLKIOV) 178 179 /* Counts for pool types */ 180 #define LFS_N_CL LFS_N_CLUSTERS 181 #define LFS_N_BPP 2 182 #define LFS_N_SEG 2 183 184 /* 185 * "struct buf" associated definitions 186 */ 187 188 /* Determine if a buffer belongs to the ifile */ 189 #define IS_IFILE(bp) (VTOI(bp->b_vp)->i_number == LFS_IFILE_INUM) 190 191 #ifdef _KERNEL 192 /* This overlays the fid structure (see fstypes.h). */ 193 struct ulfs_ufid { 194 u_int16_t ufid_len; /* Length of structure. */ 195 u_int16_t ufid_pad; /* Force 32-bit alignment. */ 196 u_int32_t ufid_ino; /* File number (ino). */ 197 int32_t ufid_gen; /* Generation number. */ 198 }; 199 /* Filehandle structure for exported LFSes */ 200 struct lfid { 201 struct ulfs_ufid lfid_ufid; 202 #define lfid_len lfid_ufid.ufid_len 203 #define lfid_ino lfid_ufid.ufid_ino 204 #define lfid_gen lfid_ufid.ufid_gen 205 uint32_t lfid_ident; 206 }; 207 #endif /* _KERNEL */ 208 209 /* Address calculations for metadata located in the inode */ 210 #define S_INDIR(fs) -ULFS_NDADDR 211 #define D_INDIR(fs) (S_INDIR(fs) - LFS_NINDIR(fs) - 1) 212 #define T_INDIR(fs) (D_INDIR(fs) - LFS_NINDIR(fs) * LFS_NINDIR(fs) - 1) 213 214 /* 215 * "struct vnode" associated definitions 216 */ 217 218 /* Heuristic emptiness measure */ 219 #define VPISEMPTY(vp) (LIST_EMPTY(&(vp)->v_dirtyblkhd) && \ 220 !(vp->v_type == VREG && (vp)->v_iflag & VI_ONWORKLST) &&\ 221 VTOI(vp)->i_lfs_nbtree == 0) 222 223 #define WRITEINPROG(vp) ((vp)->v_numoutput > 0 || \ 224 (!LIST_EMPTY(&(vp)->v_dirtyblkhd) && \ 225 !(VTOI(vp)->i_flag & (IN_MODIFIED | IN_ACCESSED | IN_CLEANING)))) 226 227 228 229 230 231 #if defined(_KERNEL) 232 233 /* 234 * The DIP macro is used to access fields in the dinode that are 235 * not cached in the inode itself. 236 */ 237 #define DIP(ip, field) \ 238 (((ip)->i_ump->um_fstype == ULFS1) ? \ 239 (ip)->i_ffs1_##field : (ip)->i_ffs2_##field) 240 241 #define DIP_ASSIGN(ip, field, value) \ 242 do { \ 243 if ((ip)->i_ump->um_fstype == ULFS1) \ 244 (ip)->i_ffs1_##field = (value); \ 245 else \ 246 (ip)->i_ffs2_##field = (value); \ 247 } while(0) 248 249 #define DIP_ADD(ip, field, value) \ 250 do { \ 251 if ((ip)->i_ump->um_fstype == ULFS1) \ 252 (ip)->i_ffs1_##field += (value); \ 253 else \ 254 (ip)->i_ffs2_##field += (value); \ 255 } while(0) 256 257 #define SHORTLINK(ip) \ 258 (((ip)->i_ump->um_fstype == ULFS1) ? \ 259 (void *)(ip)->i_ffs1_db : (void *)(ip)->i_ffs2_db) 260 261 262 /* 263 * Structure used to pass around logical block paths generated by 264 * ulfs_getlbns and used by truncate and bmap code. 265 */ 266 struct indir { 267 daddr_t in_lbn; /* Logical block number. */ 268 int in_off; /* Offset in buffer. */ 269 int in_exists; /* Flag if the block exists. */ 270 }; 271 272 /* Convert between inode pointers and vnode pointers. */ 273 #define VTOI(vp) ((struct inode *)(vp)->v_data) 274 #define ITOV(ip) ((ip)->i_vnode) 275 276 #endif /* _KERNEL */ 277 278 #endif /* !_UFS_LFS_ULFS_INODE_H_ */ 279