1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)inode.h 1.4 (2.11BSD GTE) 1995/12/24 7: */ 8: 9: /* 10: * The I node is the focus of all file activity in UNIX. 11: * There is a unique inode allocated for each active file, 12: * each current directory, each mounted-on file, text file, and the root. 13: * An inode is 'named' by its dev/inumber pair. (iget/iget.c) 14: * Data in icommon1 and icommon2 is read in from permanent inode on volume. 15: */ 16: 17: /* 18: * 28 of the di_addr address bytes are used; 7 addresses of 4 19: * bytes each: 4 direct (4Kb directly accessible) and 3 indirect. 20: */ 21: #define NDADDR 4 /* direct addresses in inode */ 22: #define NIADDR 3 /* indirect addresses in inode */ 23: #define NADDR (NDADDR + NIADDR) /* total addresses in inode */ 24: 25: struct icommon2 { 26: time_t ic_atime; /* time last accessed */ 27: time_t ic_mtime; /* time last modified */ 28: time_t ic_ctime; /* time created */ 29: }; 30: 31: struct inode { 32: struct inode *i_chain[2]; /* must be first */ 33: u_short i_flag; 34: u_short i_count; /* reference count */ 35: dev_t i_dev; /* device where inode resides */ 36: ino_t i_number; /* i number, 1-to-1 with device address */ 37: u_short i_id; /* unique identifier */ 38: struct fs *i_fs; /* file sys associated with this inode */ 39: union { 40: struct { 41: u_char I_shlockc; /* count of shared locks */ 42: u_char I_exlockc; /* count of exclusive locks */ 43: } i_l; 44: struct proc *I_rsel; /* pipe read select */ 45: } i_un0; 46: union { 47: struct text *I_text; /* text entry, if any */ 48: struct proc *I_wsel; /* pipe write select */ 49: } i_un1; 50: union { 51: daddr_t I_addr[NADDR]; /* normal file/directory */ 52: struct { 53: daddr_t I_db[NDADDR]; /* normal file/directory */ 54: daddr_t I_ib[NIADDR]; 55: } i_f; 56: struct { 57: /* 58: * the dummy field is here so that the de/compression 59: * part of the iget/iput routines works for special 60: * files. 61: */ 62: u_short I_dummy; 63: dev_t I_rdev; /* dev type */ 64: } i_d; 65: } i_un2; 66: union { 67: daddr_t if_lastr; /* last read (read-ahead) */ 68: struct socket *is_socket; 69: struct { 70: struct inode *if_freef; /* free list forward */ 71: struct inode **if_freeb; /* free list back */ 72: } i_fr; 73: } i_un3; 74: struct icommon1 { 75: u_short ic_mode; /* mode and type of file */ 76: u_short ic_nlink; /* number of links to file */ 77: uid_t ic_uid; /* owner's user id */ 78: gid_t ic_gid; /* owner's group id */ 79: off_t ic_size; /* number of bytes in file */ 80: } i_ic1; 81: /* 82: * Can't afford another 4 bytes and mapping the flags out would be prohibitively 83: * expensive. So, a 'u_short' is used for the flags - see the comments in 84: * stat.h for more information. 85: */ 86: u_short i_flags; /* user changeable flags */ 87: #ifndef EXTERNALITIMES 88: struct icommon2 i_ic2; 89: #endif 90: }; 91: 92: /* 93: * Inode structure as it appears on 94: * a disk block. 95: */ 96: struct dinode { 97: struct icommon1 di_icom1; 98: daddr_t di_addr[7]; /* 7 block addresses 4 bytes each */ 99: u_short di_reserved[5]; /* pad of 10 to make total size 64 */ 100: u_short di_flags; 101: struct icommon2 di_icom2; 102: }; 103: 104: #define i_mode i_ic1.ic_mode 105: #define i_nlink i_ic1.ic_nlink 106: #define i_uid i_ic1.ic_uid 107: #define i_gid i_ic1.ic_gid 108: #define i_size i_ic1.ic_size 109: #define i_shlockc i_un0.i_l.I_shlockc 110: #define i_exlockc i_un0.i_l.I_exlockc 111: #define i_rsel i_un0.I_rsel 112: #define i_text i_un1.I_text 113: #define i_wsel i_un1.I_wsel 114: #define i_db i_un2.i_f.I_db 115: #define i_ib i_un2.i_f.I_ib 116: #ifndef EXTERNALITIMES 117: #define i_atime i_ic2.ic_atime 118: #define i_mtime i_ic2.ic_mtime 119: #define i_ctime i_ic2.ic_ctime 120: #endif 121: #define i_rdev i_un2.i_d.I_rdev 122: #define i_addr i_un2.I_addr 123: #define i_dummy i_un2.i_d.I_dummy 124: #define i_lastr i_un3.if_lastr 125: #define i_socket i_un3.is_socket 126: #define i_forw i_chain[0] 127: #define i_back i_chain[1] 128: #define i_freef i_un3.i_fr.if_freef 129: #define i_freeb i_un3.i_fr.if_freeb 130: 131: #define di_ic1 di_icom1 132: #define di_ic2 di_icom2 133: #define di_mode di_ic1.ic_mode 134: #define di_nlink di_ic1.ic_nlink 135: #define di_uid di_ic1.ic_uid 136: #define di_gid di_ic1.ic_gid 137: #define di_size di_ic1.ic_size 138: #define di_atime di_ic2.ic_atime 139: #define di_mtime di_ic2.ic_mtime 140: #define di_ctime di_ic2.ic_ctime 141: 142: #if defined(KERNEL) && !defined(SUPERVISOR) 143: /* 144: * Invalidate an inode. Used by the namei cache to detect stale 145: * information. In order to save space and also reduce somewhat the 146: * overhead - the i_id field is made into a u_short. If a pdp-11 can 147: * invalidate 100 inodes per second, the cache will have to be invalidated 148: * in about 11 minutes. Ha! 149: * Assumes the cacheinvalall routine will map the namei cache. 150: */ 151: #define cacheinvalall _cinvall 152: 153: #define cacheinval(ip) \ 154: (ip)->i_id = ++nextinodeid; \ 155: if (nextinodeid == 0) \ 156: cacheinvalall(); 157: 158: u_short nextinodeid; /* unique id generator */ 159: 160: #ifdef EXTERNALITIMES 161: memaddr xitimes; 162: u_int xitdesc; 163: #endif 164: struct inode inode[]; /* the inode table itself */ 165: struct inode *inodeNINODE; /* the end of the inode table */ 166: int ninode; /* the number of slots in the table */ 167: 168: struct inode *rootdir; /* pointer to inode of root directory */ 169: 170: struct inode *getinode(); 171: struct inode *ialloc(); 172: struct inode *iget(); 173: struct inode *owner(); 174: struct inode *maknode(); 175: struct inode *namei(); 176: #endif 177: 178: /* i_flag */ 179: #define ILOCKED 0x1 /* inode is locked */ 180: #define IUPD 0x2 /* file has been modified */ 181: #define IACC 0x4 /* inode access time to be updated */ 182: #define IMOUNT 0x8 /* inode is mounted on */ 183: #define IWANT 0x10 /* some process waiting on lock */ 184: #define ITEXT 0x20 /* inode is pure text prototype */ 185: #define ICHG 0x40 /* inode has been changed */ 186: #define ISHLOCK 0x80 /* file has shared lock */ 187: #define IEXLOCK 0x100 /* file has exclusive lock */ 188: #define ILWAIT 0x200 /* someone waiting on file lock */ 189: #define IMOD 0x400 /* inode has been modified */ 190: #define IRENAME 0x800 /* inode is being renamed */ 191: #define IPIPE 0x1000 /* inode is a pipe */ 192: #define IRCOLL 0x2000 /* read select collision on pipe */ 193: #define IWCOLL 0x4000 /* write select collision on pipe */ 194: #define IXMOD 0x8000 /* inode is text, but impure (XXX) */ 195: 196: /* i_mode */ 197: #define IFMT 0170000 /* type of file */ 198: #define IFCHR 0020000 /* character special */ 199: #define IFDIR 0040000 /* directory */ 200: #define IFBLK 0060000 /* block special */ 201: #define IFREG 0100000 /* regular */ 202: #define IFLNK 0120000 /* symbolic link */ 203: #define IFSOCK 0140000 /* socket */ 204: #define ISUID 04000 /* set user id on execution */ 205: #define ISGID 02000 /* set group id on execution */ 206: #define ISVTX 01000 /* save swapped text even after use */ 207: #define IREAD 0400 /* read, write, execute permissions */ 208: #define IWRITE 0200 209: #define IEXEC 0100 210: 211: #if defined(KERNEL) && !defined(SUPERVISOR) 212: /* 213: * Flags for va_cflags. 214: */ 215: #define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ 216: 217: /* 218: * Flags for ioflag. 219: */ 220: #define IO_UNIT 0x01 /* do I/O as atomic unit */ 221: #define IO_APPEND 0x02 /* append write to end */ 222: #define IO_SYNC 0x04 /* do I/O synchronously */ 223: /* #define IO_NODELOCKED 0x08 /* not implemented */ 224: #define IO_NDELAY 0x10 /* FNDELAY flag set in file table */ 225: 226: /* 227: * Token indicating no attribute value yet assigned. 228: */ 229: #define VNOVAL (-1) 230: 231: #define VATTR_NULL(vp) (vattr_null(vp)) 232: 233: /* 234: * This is a bit of a misnomer. 2.11BSD does not have 'vnodes' but it was 235: * easier/simpler to keep the name 'vattr' than changing the name to something 236: * like 'iattr'. 237: * 238: * This structure is a _subset_ of 4.4BSD's vnode attribute structure. ONLY 239: * those attributes which can be *changed by the user* are present. Since we 240: * do not have vnodes why initialize (and carry around) un-used members. 241: * 242: * NOTE: For reasons of speed the function 'vattr_null()' was written in 243: * very compact assembly code and placed in pdp/mch_xxx.s. If you change 244: * the 'vattr' structure be sure and change vattr_null in pdp/mch_xxx.s! 245: */ 246: 247: struct vattr 248: { 249: mode_t va_mode; 250: uid_t va_uid; 251: gid_t va_gid; 252: off_t va_size; 253: time_t va_atime; 254: time_t va_mtime; 255: u_short va_flags; 256: u_short va_vaflags; 257: }; 258: 259: /* 260: * N.B: If the above structure changes be sure to modify the function 261: * vattr_null in pdp/mch_xxx.s! 262: */ 263: #endif 264: 265: #ifndef SUPERVISOR 266: #define ILOCK(ip) { \ 267: while ((ip)->i_flag & ILOCKED) { \ 268: (ip)->i_flag |= IWANT; \ 269: sleep((caddr_t)(ip), PINOD); \ 270: } \ 271: (ip)->i_flag |= ILOCKED; \ 272: } 273: 274: #define IUNLOCK(ip) { \ 275: (ip)->i_flag &= ~ILOCKED; \ 276: if ((ip)->i_flag&IWANT) { \ 277: (ip)->i_flag &= ~IWANT; \ 278: wakeup((caddr_t)(ip)); \ 279: } \ 280: } 281: 282: #define IUPDAT(ip, t1, t2, waitfor) { \ 283: if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) \ 284: iupdat(ip, t1, t2, waitfor); \ 285: } 286: 287: #ifdef EXTERNALITIMES 288: #define ITIMES(ip, t1, t2) { \ 289: if ((ip)->i_flag&(IUPD|IACC|ICHG)) { \ 290: struct icommon2 *ic2= &((struct icommon2 *)SEG5)[ip-inode]; \ 291: mapseg5(xitimes, xitdesc); \ 292: (ip)->i_flag |= IMOD; \ 293: if ((ip)->i_flag&IACC) \ 294: ic2->ic_atime = (t1)->tv_sec; \ 295: if ((ip)->i_flag&IUPD) \ 296: ic2->ic_mtime = (t2)->tv_sec; \ 297: if ((ip)->i_flag&ICHG) \ 298: ic2->ic_ctime = time.tv_sec; \ 299: (ip)->i_flag &= ~(IACC|IUPD|ICHG); \ 300: normalseg5(); \ 301: } \ 302: } 303: #else 304: #define ITIMES(ip, t1, t2) { \ 305: if ((ip)->i_flag&(IUPD|IACC|ICHG)) { \ 306: (ip)->i_flag |= IMOD; \ 307: if ((ip)->i_flag&IACC) \ 308: (ip)->i_atime = (t1)->tv_sec; \ 309: if ((ip)->i_flag&IUPD) \ 310: (ip)->i_mtime = (t2)->tv_sec; \ 311: if ((ip)->i_flag&ICHG) \ 312: (ip)->i_ctime = time.tv_sec; \ 313: (ip)->i_flag &= ~(IACC|IUPD|ICHG); \ 314: } \ 315: } 316: #endif 317: #endif