1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 5*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 6*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 7*1da177e4SLinus Torvalds * (at your option) any later version. 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 10*1da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12*1da177e4SLinus Torvalds * the GNU General Public License for more details. 13*1da177e4SLinus Torvalds * 14*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 15*1da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 16*1da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*1da177e4SLinus Torvalds */ 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds /* 20*1da177e4SLinus Torvalds * jfs_imap.c: inode allocation map manager 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * Serialization: 23*1da177e4SLinus Torvalds * Each AG has a simple lock which is used to control the serialization of 24*1da177e4SLinus Torvalds * the AG level lists. This lock should be taken first whenever an AG 25*1da177e4SLinus Torvalds * level list will be modified or accessed. 26*1da177e4SLinus Torvalds * 27*1da177e4SLinus Torvalds * Each IAG is locked by obtaining the buffer for the IAG page. 28*1da177e4SLinus Torvalds * 29*1da177e4SLinus Torvalds * There is also a inode lock for the inode map inode. A read lock needs to 30*1da177e4SLinus Torvalds * be taken whenever an IAG is read from the map or the global level 31*1da177e4SLinus Torvalds * information is read. A write lock needs to be taken whenever the global 32*1da177e4SLinus Torvalds * level information is modified or an atomic operation needs to be used. 33*1da177e4SLinus Torvalds * 34*1da177e4SLinus Torvalds * If more than one IAG is read at one time, the read lock may not 35*1da177e4SLinus Torvalds * be given up until all of the IAG's are read. Otherwise, a deadlock 36*1da177e4SLinus Torvalds * may occur when trying to obtain the read lock while another thread 37*1da177e4SLinus Torvalds * holding the read lock is waiting on the IAG already being held. 38*1da177e4SLinus Torvalds * 39*1da177e4SLinus Torvalds * The control page of the inode map is read into memory by diMount(). 40*1da177e4SLinus Torvalds * Thereafter it should only be modified in memory and then it will be 41*1da177e4SLinus Torvalds * written out when the filesystem is unmounted by diUnmount(). 42*1da177e4SLinus Torvalds */ 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds #include <linux/fs.h> 45*1da177e4SLinus Torvalds #include <linux/buffer_head.h> 46*1da177e4SLinus Torvalds #include <linux/pagemap.h> 47*1da177e4SLinus Torvalds #include <linux/quotaops.h> 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds #include "jfs_incore.h" 50*1da177e4SLinus Torvalds #include "jfs_filsys.h" 51*1da177e4SLinus Torvalds #include "jfs_dinode.h" 52*1da177e4SLinus Torvalds #include "jfs_dmap.h" 53*1da177e4SLinus Torvalds #include "jfs_imap.h" 54*1da177e4SLinus Torvalds #include "jfs_metapage.h" 55*1da177e4SLinus Torvalds #include "jfs_superblock.h" 56*1da177e4SLinus Torvalds #include "jfs_debug.h" 57*1da177e4SLinus Torvalds 58*1da177e4SLinus Torvalds /* 59*1da177e4SLinus Torvalds * imap locks 60*1da177e4SLinus Torvalds */ 61*1da177e4SLinus Torvalds /* iag free list lock */ 62*1da177e4SLinus Torvalds #define IAGFREE_LOCK_INIT(imap) init_MUTEX(&imap->im_freelock) 63*1da177e4SLinus Torvalds #define IAGFREE_LOCK(imap) down(&imap->im_freelock) 64*1da177e4SLinus Torvalds #define IAGFREE_UNLOCK(imap) up(&imap->im_freelock) 65*1da177e4SLinus Torvalds 66*1da177e4SLinus Torvalds /* per ag iag list locks */ 67*1da177e4SLinus Torvalds #define AG_LOCK_INIT(imap,index) init_MUTEX(&(imap->im_aglock[index])) 68*1da177e4SLinus Torvalds #define AG_LOCK(imap,agno) down(&imap->im_aglock[agno]) 69*1da177e4SLinus Torvalds #define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno]) 70*1da177e4SLinus Torvalds 71*1da177e4SLinus Torvalds /* 72*1da177e4SLinus Torvalds * external references 73*1da177e4SLinus Torvalds */ 74*1da177e4SLinus Torvalds extern struct address_space_operations jfs_aops; 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds /* 77*1da177e4SLinus Torvalds * forward references 78*1da177e4SLinus Torvalds */ 79*1da177e4SLinus Torvalds static int diAllocAG(struct inomap *, int, boolean_t, struct inode *); 80*1da177e4SLinus Torvalds static int diAllocAny(struct inomap *, int, boolean_t, struct inode *); 81*1da177e4SLinus Torvalds static int diAllocBit(struct inomap *, struct iag *, int); 82*1da177e4SLinus Torvalds static int diAllocExt(struct inomap *, int, struct inode *); 83*1da177e4SLinus Torvalds static int diAllocIno(struct inomap *, int, struct inode *); 84*1da177e4SLinus Torvalds static int diFindFree(u32, int); 85*1da177e4SLinus Torvalds static int diNewExt(struct inomap *, struct iag *, int); 86*1da177e4SLinus Torvalds static int diNewIAG(struct inomap *, int *, int, struct metapage **); 87*1da177e4SLinus Torvalds static void duplicateIXtree(struct super_block *, s64, int, s64 *); 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds static int diIAGRead(struct inomap * imap, int, struct metapage **); 90*1da177e4SLinus Torvalds static int copy_from_dinode(struct dinode *, struct inode *); 91*1da177e4SLinus Torvalds static void copy_to_dinode(struct dinode *, struct inode *); 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds /* 94*1da177e4SLinus Torvalds * debug code for double-checking inode map 95*1da177e4SLinus Torvalds */ 96*1da177e4SLinus Torvalds /* #define _JFS_DEBUG_IMAP 1 */ 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds #ifdef _JFS_DEBUG_IMAP 99*1da177e4SLinus Torvalds #define DBG_DIINIT(imap) DBGdiInit(imap) 100*1da177e4SLinus Torvalds #define DBG_DIALLOC(imap, ino) DBGdiAlloc(imap, ino) 101*1da177e4SLinus Torvalds #define DBG_DIFREE(imap, ino) DBGdiFree(imap, ino) 102*1da177e4SLinus Torvalds 103*1da177e4SLinus Torvalds static void *DBGdiInit(struct inomap * imap); 104*1da177e4SLinus Torvalds static void DBGdiAlloc(struct inomap * imap, ino_t ino); 105*1da177e4SLinus Torvalds static void DBGdiFree(struct inomap * imap, ino_t ino); 106*1da177e4SLinus Torvalds #else 107*1da177e4SLinus Torvalds #define DBG_DIINIT(imap) 108*1da177e4SLinus Torvalds #define DBG_DIALLOC(imap, ino) 109*1da177e4SLinus Torvalds #define DBG_DIFREE(imap, ino) 110*1da177e4SLinus Torvalds #endif /* _JFS_DEBUG_IMAP */ 111*1da177e4SLinus Torvalds 112*1da177e4SLinus Torvalds /* 113*1da177e4SLinus Torvalds * NAME: diMount() 114*1da177e4SLinus Torvalds * 115*1da177e4SLinus Torvalds * FUNCTION: initialize the incore inode map control structures for 116*1da177e4SLinus Torvalds * a fileset or aggregate init time. 117*1da177e4SLinus Torvalds * 118*1da177e4SLinus Torvalds * the inode map's control structure (dinomap) is 119*1da177e4SLinus Torvalds * brought in from disk and placed in virtual memory. 120*1da177e4SLinus Torvalds * 121*1da177e4SLinus Torvalds * PARAMETERS: 122*1da177e4SLinus Torvalds * ipimap - pointer to inode map inode for the aggregate or fileset. 123*1da177e4SLinus Torvalds * 124*1da177e4SLinus Torvalds * RETURN VALUES: 125*1da177e4SLinus Torvalds * 0 - success 126*1da177e4SLinus Torvalds * -ENOMEM - insufficient free virtual memory. 127*1da177e4SLinus Torvalds * -EIO - i/o error. 128*1da177e4SLinus Torvalds */ 129*1da177e4SLinus Torvalds int diMount(struct inode *ipimap) 130*1da177e4SLinus Torvalds { 131*1da177e4SLinus Torvalds struct inomap *imap; 132*1da177e4SLinus Torvalds struct metapage *mp; 133*1da177e4SLinus Torvalds int index; 134*1da177e4SLinus Torvalds struct dinomap_disk *dinom_le; 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds /* 137*1da177e4SLinus Torvalds * allocate/initialize the in-memory inode map control structure 138*1da177e4SLinus Torvalds */ 139*1da177e4SLinus Torvalds /* allocate the in-memory inode map control structure. */ 140*1da177e4SLinus Torvalds imap = (struct inomap *) kmalloc(sizeof(struct inomap), GFP_KERNEL); 141*1da177e4SLinus Torvalds if (imap == NULL) { 142*1da177e4SLinus Torvalds jfs_err("diMount: kmalloc returned NULL!"); 143*1da177e4SLinus Torvalds return -ENOMEM; 144*1da177e4SLinus Torvalds } 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds /* read the on-disk inode map control structure. */ 147*1da177e4SLinus Torvalds 148*1da177e4SLinus Torvalds mp = read_metapage(ipimap, 149*1da177e4SLinus Torvalds IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage, 150*1da177e4SLinus Torvalds PSIZE, 0); 151*1da177e4SLinus Torvalds if (mp == NULL) { 152*1da177e4SLinus Torvalds kfree(imap); 153*1da177e4SLinus Torvalds return -EIO; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds /* copy the on-disk version to the in-memory version. */ 157*1da177e4SLinus Torvalds dinom_le = (struct dinomap_disk *) mp->data; 158*1da177e4SLinus Torvalds imap->im_freeiag = le32_to_cpu(dinom_le->in_freeiag); 159*1da177e4SLinus Torvalds imap->im_nextiag = le32_to_cpu(dinom_le->in_nextiag); 160*1da177e4SLinus Torvalds atomic_set(&imap->im_numinos, le32_to_cpu(dinom_le->in_numinos)); 161*1da177e4SLinus Torvalds atomic_set(&imap->im_numfree, le32_to_cpu(dinom_le->in_numfree)); 162*1da177e4SLinus Torvalds imap->im_nbperiext = le32_to_cpu(dinom_le->in_nbperiext); 163*1da177e4SLinus Torvalds imap->im_l2nbperiext = le32_to_cpu(dinom_le->in_l2nbperiext); 164*1da177e4SLinus Torvalds for (index = 0; index < MAXAG; index++) { 165*1da177e4SLinus Torvalds imap->im_agctl[index].inofree = 166*1da177e4SLinus Torvalds le32_to_cpu(dinom_le->in_agctl[index].inofree); 167*1da177e4SLinus Torvalds imap->im_agctl[index].extfree = 168*1da177e4SLinus Torvalds le32_to_cpu(dinom_le->in_agctl[index].extfree); 169*1da177e4SLinus Torvalds imap->im_agctl[index].numinos = 170*1da177e4SLinus Torvalds le32_to_cpu(dinom_le->in_agctl[index].numinos); 171*1da177e4SLinus Torvalds imap->im_agctl[index].numfree = 172*1da177e4SLinus Torvalds le32_to_cpu(dinom_le->in_agctl[index].numfree); 173*1da177e4SLinus Torvalds } 174*1da177e4SLinus Torvalds 175*1da177e4SLinus Torvalds /* release the buffer. */ 176*1da177e4SLinus Torvalds release_metapage(mp); 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds /* 179*1da177e4SLinus Torvalds * allocate/initialize inode allocation map locks 180*1da177e4SLinus Torvalds */ 181*1da177e4SLinus Torvalds /* allocate and init iag free list lock */ 182*1da177e4SLinus Torvalds IAGFREE_LOCK_INIT(imap); 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds /* allocate and init ag list locks */ 185*1da177e4SLinus Torvalds for (index = 0; index < MAXAG; index++) { 186*1da177e4SLinus Torvalds AG_LOCK_INIT(imap, index); 187*1da177e4SLinus Torvalds } 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds /* bind the inode map inode and inode map control structure 190*1da177e4SLinus Torvalds * to each other. 191*1da177e4SLinus Torvalds */ 192*1da177e4SLinus Torvalds imap->im_ipimap = ipimap; 193*1da177e4SLinus Torvalds JFS_IP(ipimap)->i_imap = imap; 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds // DBG_DIINIT(imap); 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds return (0); 198*1da177e4SLinus Torvalds } 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds /* 202*1da177e4SLinus Torvalds * NAME: diUnmount() 203*1da177e4SLinus Torvalds * 204*1da177e4SLinus Torvalds * FUNCTION: write to disk the incore inode map control structures for 205*1da177e4SLinus Torvalds * a fileset or aggregate at unmount time. 206*1da177e4SLinus Torvalds * 207*1da177e4SLinus Torvalds * PARAMETERS: 208*1da177e4SLinus Torvalds * ipimap - pointer to inode map inode for the aggregate or fileset. 209*1da177e4SLinus Torvalds * 210*1da177e4SLinus Torvalds * RETURN VALUES: 211*1da177e4SLinus Torvalds * 0 - success 212*1da177e4SLinus Torvalds * -ENOMEM - insufficient free virtual memory. 213*1da177e4SLinus Torvalds * -EIO - i/o error. 214*1da177e4SLinus Torvalds */ 215*1da177e4SLinus Torvalds int diUnmount(struct inode *ipimap, int mounterror) 216*1da177e4SLinus Torvalds { 217*1da177e4SLinus Torvalds struct inomap *imap = JFS_IP(ipimap)->i_imap; 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds /* 220*1da177e4SLinus Torvalds * update the on-disk inode map control structure 221*1da177e4SLinus Torvalds */ 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds if (!(mounterror || isReadOnly(ipimap))) 224*1da177e4SLinus Torvalds diSync(ipimap); 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds /* 227*1da177e4SLinus Torvalds * Invalidate the page cache buffers 228*1da177e4SLinus Torvalds */ 229*1da177e4SLinus Torvalds truncate_inode_pages(ipimap->i_mapping, 0); 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds /* 232*1da177e4SLinus Torvalds * free in-memory control structure 233*1da177e4SLinus Torvalds */ 234*1da177e4SLinus Torvalds kfree(imap); 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds return (0); 237*1da177e4SLinus Torvalds } 238*1da177e4SLinus Torvalds 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds /* 241*1da177e4SLinus Torvalds * diSync() 242*1da177e4SLinus Torvalds */ 243*1da177e4SLinus Torvalds int diSync(struct inode *ipimap) 244*1da177e4SLinus Torvalds { 245*1da177e4SLinus Torvalds struct dinomap_disk *dinom_le; 246*1da177e4SLinus Torvalds struct inomap *imp = JFS_IP(ipimap)->i_imap; 247*1da177e4SLinus Torvalds struct metapage *mp; 248*1da177e4SLinus Torvalds int index; 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds /* 251*1da177e4SLinus Torvalds * write imap global conrol page 252*1da177e4SLinus Torvalds */ 253*1da177e4SLinus Torvalds /* read the on-disk inode map control structure */ 254*1da177e4SLinus Torvalds mp = get_metapage(ipimap, 255*1da177e4SLinus Torvalds IMAPBLKNO << JFS_SBI(ipimap->i_sb)->l2nbperpage, 256*1da177e4SLinus Torvalds PSIZE, 0); 257*1da177e4SLinus Torvalds if (mp == NULL) { 258*1da177e4SLinus Torvalds jfs_err("diSync: get_metapage failed!"); 259*1da177e4SLinus Torvalds return -EIO; 260*1da177e4SLinus Torvalds } 261*1da177e4SLinus Torvalds 262*1da177e4SLinus Torvalds /* copy the in-memory version to the on-disk version */ 263*1da177e4SLinus Torvalds dinom_le = (struct dinomap_disk *) mp->data; 264*1da177e4SLinus Torvalds dinom_le->in_freeiag = cpu_to_le32(imp->im_freeiag); 265*1da177e4SLinus Torvalds dinom_le->in_nextiag = cpu_to_le32(imp->im_nextiag); 266*1da177e4SLinus Torvalds dinom_le->in_numinos = cpu_to_le32(atomic_read(&imp->im_numinos)); 267*1da177e4SLinus Torvalds dinom_le->in_numfree = cpu_to_le32(atomic_read(&imp->im_numfree)); 268*1da177e4SLinus Torvalds dinom_le->in_nbperiext = cpu_to_le32(imp->im_nbperiext); 269*1da177e4SLinus Torvalds dinom_le->in_l2nbperiext = cpu_to_le32(imp->im_l2nbperiext); 270*1da177e4SLinus Torvalds for (index = 0; index < MAXAG; index++) { 271*1da177e4SLinus Torvalds dinom_le->in_agctl[index].inofree = 272*1da177e4SLinus Torvalds cpu_to_le32(imp->im_agctl[index].inofree); 273*1da177e4SLinus Torvalds dinom_le->in_agctl[index].extfree = 274*1da177e4SLinus Torvalds cpu_to_le32(imp->im_agctl[index].extfree); 275*1da177e4SLinus Torvalds dinom_le->in_agctl[index].numinos = 276*1da177e4SLinus Torvalds cpu_to_le32(imp->im_agctl[index].numinos); 277*1da177e4SLinus Torvalds dinom_le->in_agctl[index].numfree = 278*1da177e4SLinus Torvalds cpu_to_le32(imp->im_agctl[index].numfree); 279*1da177e4SLinus Torvalds } 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds /* write out the control structure */ 282*1da177e4SLinus Torvalds write_metapage(mp); 283*1da177e4SLinus Torvalds 284*1da177e4SLinus Torvalds /* 285*1da177e4SLinus Torvalds * write out dirty pages of imap 286*1da177e4SLinus Torvalds */ 287*1da177e4SLinus Torvalds filemap_fdatawrite(ipimap->i_mapping); 288*1da177e4SLinus Torvalds filemap_fdatawait(ipimap->i_mapping); 289*1da177e4SLinus Torvalds 290*1da177e4SLinus Torvalds diWriteSpecial(ipimap, 0); 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds return (0); 293*1da177e4SLinus Torvalds } 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds /* 297*1da177e4SLinus Torvalds * NAME: diRead() 298*1da177e4SLinus Torvalds * 299*1da177e4SLinus Torvalds * FUNCTION: initialize an incore inode from disk. 300*1da177e4SLinus Torvalds * 301*1da177e4SLinus Torvalds * on entry, the specifed incore inode should itself 302*1da177e4SLinus Torvalds * specify the disk inode number corresponding to the 303*1da177e4SLinus Torvalds * incore inode (i.e. i_number should be initialized). 304*1da177e4SLinus Torvalds * 305*1da177e4SLinus Torvalds * this routine handles incore inode initialization for 306*1da177e4SLinus Torvalds * both "special" and "regular" inodes. special inodes 307*1da177e4SLinus Torvalds * are those required early in the mount process and 308*1da177e4SLinus Torvalds * require special handling since much of the file system 309*1da177e4SLinus Torvalds * is not yet initialized. these "special" inodes are 310*1da177e4SLinus Torvalds * identified by a NULL inode map inode pointer and are 311*1da177e4SLinus Torvalds * actually initialized by a call to diReadSpecial(). 312*1da177e4SLinus Torvalds * 313*1da177e4SLinus Torvalds * for regular inodes, the iag describing the disk inode 314*1da177e4SLinus Torvalds * is read from disk to determine the inode extent address 315*1da177e4SLinus Torvalds * for the disk inode. with the inode extent address in 316*1da177e4SLinus Torvalds * hand, the page of the extent that contains the disk 317*1da177e4SLinus Torvalds * inode is read and the disk inode is copied to the 318*1da177e4SLinus Torvalds * incore inode. 319*1da177e4SLinus Torvalds * 320*1da177e4SLinus Torvalds * PARAMETERS: 321*1da177e4SLinus Torvalds * ip - pointer to incore inode to be initialized from disk. 322*1da177e4SLinus Torvalds * 323*1da177e4SLinus Torvalds * RETURN VALUES: 324*1da177e4SLinus Torvalds * 0 - success 325*1da177e4SLinus Torvalds * -EIO - i/o error. 326*1da177e4SLinus Torvalds * -ENOMEM - insufficient memory 327*1da177e4SLinus Torvalds * 328*1da177e4SLinus Torvalds */ 329*1da177e4SLinus Torvalds int diRead(struct inode *ip) 330*1da177e4SLinus Torvalds { 331*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 332*1da177e4SLinus Torvalds int iagno, ino, extno, rc; 333*1da177e4SLinus Torvalds struct inode *ipimap; 334*1da177e4SLinus Torvalds struct dinode *dp; 335*1da177e4SLinus Torvalds struct iag *iagp; 336*1da177e4SLinus Torvalds struct metapage *mp; 337*1da177e4SLinus Torvalds s64 blkno, agstart; 338*1da177e4SLinus Torvalds struct inomap *imap; 339*1da177e4SLinus Torvalds int block_offset; 340*1da177e4SLinus Torvalds int inodes_left; 341*1da177e4SLinus Torvalds uint pageno; 342*1da177e4SLinus Torvalds int rel_inode; 343*1da177e4SLinus Torvalds 344*1da177e4SLinus Torvalds jfs_info("diRead: ino = %ld", ip->i_ino); 345*1da177e4SLinus Torvalds 346*1da177e4SLinus Torvalds ipimap = sbi->ipimap; 347*1da177e4SLinus Torvalds JFS_IP(ip)->ipimap = ipimap; 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds /* determine the iag number for this inode (number) */ 350*1da177e4SLinus Torvalds iagno = INOTOIAG(ip->i_ino); 351*1da177e4SLinus Torvalds 352*1da177e4SLinus Torvalds /* read the iag */ 353*1da177e4SLinus Torvalds imap = JFS_IP(ipimap)->i_imap; 354*1da177e4SLinus Torvalds IREAD_LOCK(ipimap); 355*1da177e4SLinus Torvalds rc = diIAGRead(imap, iagno, &mp); 356*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 357*1da177e4SLinus Torvalds if (rc) { 358*1da177e4SLinus Torvalds jfs_err("diRead: diIAGRead returned %d", rc); 359*1da177e4SLinus Torvalds return (rc); 360*1da177e4SLinus Torvalds } 361*1da177e4SLinus Torvalds 362*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds /* determine inode extent that holds the disk inode */ 365*1da177e4SLinus Torvalds ino = ip->i_ino & (INOSPERIAG - 1); 366*1da177e4SLinus Torvalds extno = ino >> L2INOSPEREXT; 367*1da177e4SLinus Torvalds 368*1da177e4SLinus Torvalds if ((lengthPXD(&iagp->inoext[extno]) != imap->im_nbperiext) || 369*1da177e4SLinus Torvalds (addressPXD(&iagp->inoext[extno]) == 0)) { 370*1da177e4SLinus Torvalds release_metapage(mp); 371*1da177e4SLinus Torvalds return -ESTALE; 372*1da177e4SLinus Torvalds } 373*1da177e4SLinus Torvalds 374*1da177e4SLinus Torvalds /* get disk block number of the page within the inode extent 375*1da177e4SLinus Torvalds * that holds the disk inode. 376*1da177e4SLinus Torvalds */ 377*1da177e4SLinus Torvalds blkno = INOPBLK(&iagp->inoext[extno], ino, sbi->l2nbperpage); 378*1da177e4SLinus Torvalds 379*1da177e4SLinus Torvalds /* get the ag for the iag */ 380*1da177e4SLinus Torvalds agstart = le64_to_cpu(iagp->agstart); 381*1da177e4SLinus Torvalds 382*1da177e4SLinus Torvalds release_metapage(mp); 383*1da177e4SLinus Torvalds 384*1da177e4SLinus Torvalds rel_inode = (ino & (INOSPERPAGE - 1)); 385*1da177e4SLinus Torvalds pageno = blkno >> sbi->l2nbperpage; 386*1da177e4SLinus Torvalds 387*1da177e4SLinus Torvalds if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) { 388*1da177e4SLinus Torvalds /* 389*1da177e4SLinus Torvalds * OS/2 didn't always align inode extents on page boundaries 390*1da177e4SLinus Torvalds */ 391*1da177e4SLinus Torvalds inodes_left = 392*1da177e4SLinus Torvalds (sbi->nbperpage - block_offset) << sbi->l2niperblk; 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds if (rel_inode < inodes_left) 395*1da177e4SLinus Torvalds rel_inode += block_offset << sbi->l2niperblk; 396*1da177e4SLinus Torvalds else { 397*1da177e4SLinus Torvalds pageno += 1; 398*1da177e4SLinus Torvalds rel_inode -= inodes_left; 399*1da177e4SLinus Torvalds } 400*1da177e4SLinus Torvalds } 401*1da177e4SLinus Torvalds 402*1da177e4SLinus Torvalds /* read the page of disk inode */ 403*1da177e4SLinus Torvalds mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1); 404*1da177e4SLinus Torvalds if (mp == 0) { 405*1da177e4SLinus Torvalds jfs_err("diRead: read_metapage failed"); 406*1da177e4SLinus Torvalds return -EIO; 407*1da177e4SLinus Torvalds } 408*1da177e4SLinus Torvalds 409*1da177e4SLinus Torvalds /* locate the the disk inode requested */ 410*1da177e4SLinus Torvalds dp = (struct dinode *) mp->data; 411*1da177e4SLinus Torvalds dp += rel_inode; 412*1da177e4SLinus Torvalds 413*1da177e4SLinus Torvalds if (ip->i_ino != le32_to_cpu(dp->di_number)) { 414*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diRead: i_ino != di_number"); 415*1da177e4SLinus Torvalds rc = -EIO; 416*1da177e4SLinus Torvalds } else if (le32_to_cpu(dp->di_nlink) == 0) 417*1da177e4SLinus Torvalds rc = -ESTALE; 418*1da177e4SLinus Torvalds else 419*1da177e4SLinus Torvalds /* copy the disk inode to the in-memory inode */ 420*1da177e4SLinus Torvalds rc = copy_from_dinode(dp, ip); 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds release_metapage(mp); 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds /* set the ag for the inode */ 425*1da177e4SLinus Torvalds JFS_IP(ip)->agno = BLKTOAG(agstart, sbi); 426*1da177e4SLinus Torvalds JFS_IP(ip)->active_ag = -1; 427*1da177e4SLinus Torvalds 428*1da177e4SLinus Torvalds return (rc); 429*1da177e4SLinus Torvalds } 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds 432*1da177e4SLinus Torvalds /* 433*1da177e4SLinus Torvalds * NAME: diReadSpecial() 434*1da177e4SLinus Torvalds * 435*1da177e4SLinus Torvalds * FUNCTION: initialize a 'special' inode from disk. 436*1da177e4SLinus Torvalds * 437*1da177e4SLinus Torvalds * this routines handles aggregate level inodes. The 438*1da177e4SLinus Torvalds * inode cache cannot differentiate between the 439*1da177e4SLinus Torvalds * aggregate inodes and the filesystem inodes, so we 440*1da177e4SLinus Torvalds * handle these here. We don't actually use the aggregate 441*1da177e4SLinus Torvalds * inode map, since these inodes are at a fixed location 442*1da177e4SLinus Torvalds * and in some cases the aggregate inode map isn't initialized 443*1da177e4SLinus Torvalds * yet. 444*1da177e4SLinus Torvalds * 445*1da177e4SLinus Torvalds * PARAMETERS: 446*1da177e4SLinus Torvalds * sb - filesystem superblock 447*1da177e4SLinus Torvalds * inum - aggregate inode number 448*1da177e4SLinus Torvalds * secondary - 1 if secondary aggregate inode table 449*1da177e4SLinus Torvalds * 450*1da177e4SLinus Torvalds * RETURN VALUES: 451*1da177e4SLinus Torvalds * new inode - success 452*1da177e4SLinus Torvalds * NULL - i/o error. 453*1da177e4SLinus Torvalds */ 454*1da177e4SLinus Torvalds struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) 455*1da177e4SLinus Torvalds { 456*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 457*1da177e4SLinus Torvalds uint address; 458*1da177e4SLinus Torvalds struct dinode *dp; 459*1da177e4SLinus Torvalds struct inode *ip; 460*1da177e4SLinus Torvalds struct metapage *mp; 461*1da177e4SLinus Torvalds 462*1da177e4SLinus Torvalds ip = new_inode(sb); 463*1da177e4SLinus Torvalds if (ip == NULL) { 464*1da177e4SLinus Torvalds jfs_err("diReadSpecial: new_inode returned NULL!"); 465*1da177e4SLinus Torvalds return ip; 466*1da177e4SLinus Torvalds } 467*1da177e4SLinus Torvalds 468*1da177e4SLinus Torvalds if (secondary) { 469*1da177e4SLinus Torvalds address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage; 470*1da177e4SLinus Torvalds JFS_IP(ip)->ipimap = sbi->ipaimap2; 471*1da177e4SLinus Torvalds } else { 472*1da177e4SLinus Torvalds address = AITBL_OFF >> L2PSIZE; 473*1da177e4SLinus Torvalds JFS_IP(ip)->ipimap = sbi->ipaimap; 474*1da177e4SLinus Torvalds } 475*1da177e4SLinus Torvalds 476*1da177e4SLinus Torvalds ASSERT(inum < INOSPEREXT); 477*1da177e4SLinus Torvalds 478*1da177e4SLinus Torvalds ip->i_ino = inum; 479*1da177e4SLinus Torvalds 480*1da177e4SLinus Torvalds address += inum >> 3; /* 8 inodes per 4K page */ 481*1da177e4SLinus Torvalds 482*1da177e4SLinus Torvalds /* read the page of fixed disk inode (AIT) in raw mode */ 483*1da177e4SLinus Torvalds mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1); 484*1da177e4SLinus Torvalds if (mp == NULL) { 485*1da177e4SLinus Torvalds ip->i_nlink = 1; /* Don't want iput() deleting it */ 486*1da177e4SLinus Torvalds iput(ip); 487*1da177e4SLinus Torvalds return (NULL); 488*1da177e4SLinus Torvalds } 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds /* get the pointer to the disk inode of interest */ 491*1da177e4SLinus Torvalds dp = (struct dinode *) (mp->data); 492*1da177e4SLinus Torvalds dp += inum % 8; /* 8 inodes per 4K page */ 493*1da177e4SLinus Torvalds 494*1da177e4SLinus Torvalds /* copy on-disk inode to in-memory inode */ 495*1da177e4SLinus Torvalds if ((copy_from_dinode(dp, ip)) != 0) { 496*1da177e4SLinus Torvalds /* handle bad return by returning NULL for ip */ 497*1da177e4SLinus Torvalds ip->i_nlink = 1; /* Don't want iput() deleting it */ 498*1da177e4SLinus Torvalds iput(ip); 499*1da177e4SLinus Torvalds /* release the page */ 500*1da177e4SLinus Torvalds release_metapage(mp); 501*1da177e4SLinus Torvalds return (NULL); 502*1da177e4SLinus Torvalds 503*1da177e4SLinus Torvalds } 504*1da177e4SLinus Torvalds 505*1da177e4SLinus Torvalds ip->i_mapping->a_ops = &jfs_aops; 506*1da177e4SLinus Torvalds mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); 507*1da177e4SLinus Torvalds 508*1da177e4SLinus Torvalds /* Allocations to metadata inodes should not affect quotas */ 509*1da177e4SLinus Torvalds ip->i_flags |= S_NOQUOTA; 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) { 512*1da177e4SLinus Torvalds sbi->gengen = le32_to_cpu(dp->di_gengen); 513*1da177e4SLinus Torvalds sbi->inostamp = le32_to_cpu(dp->di_inostamp); 514*1da177e4SLinus Torvalds } 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds /* release the page */ 517*1da177e4SLinus Torvalds release_metapage(mp); 518*1da177e4SLinus Torvalds 519*1da177e4SLinus Torvalds return (ip); 520*1da177e4SLinus Torvalds } 521*1da177e4SLinus Torvalds 522*1da177e4SLinus Torvalds /* 523*1da177e4SLinus Torvalds * NAME: diWriteSpecial() 524*1da177e4SLinus Torvalds * 525*1da177e4SLinus Torvalds * FUNCTION: Write the special inode to disk 526*1da177e4SLinus Torvalds * 527*1da177e4SLinus Torvalds * PARAMETERS: 528*1da177e4SLinus Torvalds * ip - special inode 529*1da177e4SLinus Torvalds * secondary - 1 if secondary aggregate inode table 530*1da177e4SLinus Torvalds * 531*1da177e4SLinus Torvalds * RETURN VALUES: none 532*1da177e4SLinus Torvalds */ 533*1da177e4SLinus Torvalds 534*1da177e4SLinus Torvalds void diWriteSpecial(struct inode *ip, int secondary) 535*1da177e4SLinus Torvalds { 536*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 537*1da177e4SLinus Torvalds uint address; 538*1da177e4SLinus Torvalds struct dinode *dp; 539*1da177e4SLinus Torvalds ino_t inum = ip->i_ino; 540*1da177e4SLinus Torvalds struct metapage *mp; 541*1da177e4SLinus Torvalds 542*1da177e4SLinus Torvalds ip->i_state &= ~I_DIRTY; 543*1da177e4SLinus Torvalds 544*1da177e4SLinus Torvalds if (secondary) 545*1da177e4SLinus Torvalds address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage; 546*1da177e4SLinus Torvalds else 547*1da177e4SLinus Torvalds address = AITBL_OFF >> L2PSIZE; 548*1da177e4SLinus Torvalds 549*1da177e4SLinus Torvalds ASSERT(inum < INOSPEREXT); 550*1da177e4SLinus Torvalds 551*1da177e4SLinus Torvalds address += inum >> 3; /* 8 inodes per 4K page */ 552*1da177e4SLinus Torvalds 553*1da177e4SLinus Torvalds /* read the page of fixed disk inode (AIT) in raw mode */ 554*1da177e4SLinus Torvalds mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1); 555*1da177e4SLinus Torvalds if (mp == NULL) { 556*1da177e4SLinus Torvalds jfs_err("diWriteSpecial: failed to read aggregate inode " 557*1da177e4SLinus Torvalds "extent!"); 558*1da177e4SLinus Torvalds return; 559*1da177e4SLinus Torvalds } 560*1da177e4SLinus Torvalds 561*1da177e4SLinus Torvalds /* get the pointer to the disk inode of interest */ 562*1da177e4SLinus Torvalds dp = (struct dinode *) (mp->data); 563*1da177e4SLinus Torvalds dp += inum % 8; /* 8 inodes per 4K page */ 564*1da177e4SLinus Torvalds 565*1da177e4SLinus Torvalds /* copy on-disk inode to in-memory inode */ 566*1da177e4SLinus Torvalds copy_to_dinode(dp, ip); 567*1da177e4SLinus Torvalds memcpy(&dp->di_xtroot, &JFS_IP(ip)->i_xtroot, 288); 568*1da177e4SLinus Torvalds 569*1da177e4SLinus Torvalds if (inum == FILESYSTEM_I) 570*1da177e4SLinus Torvalds dp->di_gengen = cpu_to_le32(sbi->gengen); 571*1da177e4SLinus Torvalds 572*1da177e4SLinus Torvalds /* write the page */ 573*1da177e4SLinus Torvalds write_metapage(mp); 574*1da177e4SLinus Torvalds } 575*1da177e4SLinus Torvalds 576*1da177e4SLinus Torvalds /* 577*1da177e4SLinus Torvalds * NAME: diFreeSpecial() 578*1da177e4SLinus Torvalds * 579*1da177e4SLinus Torvalds * FUNCTION: Free allocated space for special inode 580*1da177e4SLinus Torvalds */ 581*1da177e4SLinus Torvalds void diFreeSpecial(struct inode *ip) 582*1da177e4SLinus Torvalds { 583*1da177e4SLinus Torvalds if (ip == NULL) { 584*1da177e4SLinus Torvalds jfs_err("diFreeSpecial called with NULL ip!"); 585*1da177e4SLinus Torvalds return; 586*1da177e4SLinus Torvalds } 587*1da177e4SLinus Torvalds filemap_fdatawrite(ip->i_mapping); 588*1da177e4SLinus Torvalds filemap_fdatawait(ip->i_mapping); 589*1da177e4SLinus Torvalds truncate_inode_pages(ip->i_mapping, 0); 590*1da177e4SLinus Torvalds iput(ip); 591*1da177e4SLinus Torvalds } 592*1da177e4SLinus Torvalds 593*1da177e4SLinus Torvalds 594*1da177e4SLinus Torvalds 595*1da177e4SLinus Torvalds /* 596*1da177e4SLinus Torvalds * NAME: diWrite() 597*1da177e4SLinus Torvalds * 598*1da177e4SLinus Torvalds * FUNCTION: write the on-disk inode portion of the in-memory inode 599*1da177e4SLinus Torvalds * to its corresponding on-disk inode. 600*1da177e4SLinus Torvalds * 601*1da177e4SLinus Torvalds * on entry, the specifed incore inode should itself 602*1da177e4SLinus Torvalds * specify the disk inode number corresponding to the 603*1da177e4SLinus Torvalds * incore inode (i.e. i_number should be initialized). 604*1da177e4SLinus Torvalds * 605*1da177e4SLinus Torvalds * the inode contains the inode extent address for the disk 606*1da177e4SLinus Torvalds * inode. with the inode extent address in hand, the 607*1da177e4SLinus Torvalds * page of the extent that contains the disk inode is 608*1da177e4SLinus Torvalds * read and the disk inode portion of the incore inode 609*1da177e4SLinus Torvalds * is copied to the disk inode. 610*1da177e4SLinus Torvalds * 611*1da177e4SLinus Torvalds * PARAMETERS: 612*1da177e4SLinus Torvalds * tid - transacation id 613*1da177e4SLinus Torvalds * ip - pointer to incore inode to be written to the inode extent. 614*1da177e4SLinus Torvalds * 615*1da177e4SLinus Torvalds * RETURN VALUES: 616*1da177e4SLinus Torvalds * 0 - success 617*1da177e4SLinus Torvalds * -EIO - i/o error. 618*1da177e4SLinus Torvalds */ 619*1da177e4SLinus Torvalds int diWrite(tid_t tid, struct inode *ip) 620*1da177e4SLinus Torvalds { 621*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 622*1da177e4SLinus Torvalds struct jfs_inode_info *jfs_ip = JFS_IP(ip); 623*1da177e4SLinus Torvalds int rc = 0; 624*1da177e4SLinus Torvalds s32 ino; 625*1da177e4SLinus Torvalds struct dinode *dp; 626*1da177e4SLinus Torvalds s64 blkno; 627*1da177e4SLinus Torvalds int block_offset; 628*1da177e4SLinus Torvalds int inodes_left; 629*1da177e4SLinus Torvalds struct metapage *mp; 630*1da177e4SLinus Torvalds uint pageno; 631*1da177e4SLinus Torvalds int rel_inode; 632*1da177e4SLinus Torvalds int dioffset; 633*1da177e4SLinus Torvalds struct inode *ipimap; 634*1da177e4SLinus Torvalds uint type; 635*1da177e4SLinus Torvalds lid_t lid; 636*1da177e4SLinus Torvalds struct tlock *ditlck, *tlck; 637*1da177e4SLinus Torvalds struct linelock *dilinelock, *ilinelock; 638*1da177e4SLinus Torvalds struct lv *lv; 639*1da177e4SLinus Torvalds int n; 640*1da177e4SLinus Torvalds 641*1da177e4SLinus Torvalds ipimap = jfs_ip->ipimap; 642*1da177e4SLinus Torvalds 643*1da177e4SLinus Torvalds ino = ip->i_ino & (INOSPERIAG - 1); 644*1da177e4SLinus Torvalds 645*1da177e4SLinus Torvalds if (!addressPXD(&(jfs_ip->ixpxd)) || 646*1da177e4SLinus Torvalds (lengthPXD(&(jfs_ip->ixpxd)) != 647*1da177e4SLinus Torvalds JFS_IP(ipimap)->i_imap->im_nbperiext)) { 648*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diWrite: ixpxd invalid"); 649*1da177e4SLinus Torvalds return -EIO; 650*1da177e4SLinus Torvalds } 651*1da177e4SLinus Torvalds 652*1da177e4SLinus Torvalds /* 653*1da177e4SLinus Torvalds * read the page of disk inode containing the specified inode: 654*1da177e4SLinus Torvalds */ 655*1da177e4SLinus Torvalds /* compute the block address of the page */ 656*1da177e4SLinus Torvalds blkno = INOPBLK(&(jfs_ip->ixpxd), ino, sbi->l2nbperpage); 657*1da177e4SLinus Torvalds 658*1da177e4SLinus Torvalds rel_inode = (ino & (INOSPERPAGE - 1)); 659*1da177e4SLinus Torvalds pageno = blkno >> sbi->l2nbperpage; 660*1da177e4SLinus Torvalds 661*1da177e4SLinus Torvalds if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) { 662*1da177e4SLinus Torvalds /* 663*1da177e4SLinus Torvalds * OS/2 didn't always align inode extents on page boundaries 664*1da177e4SLinus Torvalds */ 665*1da177e4SLinus Torvalds inodes_left = 666*1da177e4SLinus Torvalds (sbi->nbperpage - block_offset) << sbi->l2niperblk; 667*1da177e4SLinus Torvalds 668*1da177e4SLinus Torvalds if (rel_inode < inodes_left) 669*1da177e4SLinus Torvalds rel_inode += block_offset << sbi->l2niperblk; 670*1da177e4SLinus Torvalds else { 671*1da177e4SLinus Torvalds pageno += 1; 672*1da177e4SLinus Torvalds rel_inode -= inodes_left; 673*1da177e4SLinus Torvalds } 674*1da177e4SLinus Torvalds } 675*1da177e4SLinus Torvalds /* read the page of disk inode */ 676*1da177e4SLinus Torvalds retry: 677*1da177e4SLinus Torvalds mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1); 678*1da177e4SLinus Torvalds if (mp == 0) 679*1da177e4SLinus Torvalds return -EIO; 680*1da177e4SLinus Torvalds 681*1da177e4SLinus Torvalds /* get the pointer to the disk inode */ 682*1da177e4SLinus Torvalds dp = (struct dinode *) mp->data; 683*1da177e4SLinus Torvalds dp += rel_inode; 684*1da177e4SLinus Torvalds 685*1da177e4SLinus Torvalds dioffset = (ino & (INOSPERPAGE - 1)) << L2DISIZE; 686*1da177e4SLinus Torvalds 687*1da177e4SLinus Torvalds /* 688*1da177e4SLinus Torvalds * acquire transaction lock on the on-disk inode; 689*1da177e4SLinus Torvalds * N.B. tlock is acquired on ipimap not ip; 690*1da177e4SLinus Torvalds */ 691*1da177e4SLinus Torvalds if ((ditlck = 692*1da177e4SLinus Torvalds txLock(tid, ipimap, mp, tlckINODE | tlckENTRY)) == NULL) 693*1da177e4SLinus Torvalds goto retry; 694*1da177e4SLinus Torvalds dilinelock = (struct linelock *) & ditlck->lock; 695*1da177e4SLinus Torvalds 696*1da177e4SLinus Torvalds /* 697*1da177e4SLinus Torvalds * copy btree root from in-memory inode to on-disk inode 698*1da177e4SLinus Torvalds * 699*1da177e4SLinus Torvalds * (tlock is taken from inline B+-tree root in in-memory 700*1da177e4SLinus Torvalds * inode when the B+-tree root is updated, which is pointed 701*1da177e4SLinus Torvalds * by jfs_ip->blid as well as being on tx tlock list) 702*1da177e4SLinus Torvalds * 703*1da177e4SLinus Torvalds * further processing of btree root is based on the copy 704*1da177e4SLinus Torvalds * in in-memory inode, where txLog() will log from, and, 705*1da177e4SLinus Torvalds * for xtree root, txUpdateMap() will update map and reset 706*1da177e4SLinus Torvalds * XAD_NEW bit; 707*1da177e4SLinus Torvalds */ 708*1da177e4SLinus Torvalds 709*1da177e4SLinus Torvalds if (S_ISDIR(ip->i_mode) && (lid = jfs_ip->xtlid)) { 710*1da177e4SLinus Torvalds /* 711*1da177e4SLinus Torvalds * This is the special xtree inside the directory for storing 712*1da177e4SLinus Torvalds * the directory table 713*1da177e4SLinus Torvalds */ 714*1da177e4SLinus Torvalds xtpage_t *p, *xp; 715*1da177e4SLinus Torvalds xad_t *xad; 716*1da177e4SLinus Torvalds 717*1da177e4SLinus Torvalds jfs_ip->xtlid = 0; 718*1da177e4SLinus Torvalds tlck = lid_to_tlock(lid); 719*1da177e4SLinus Torvalds assert(tlck->type & tlckXTREE); 720*1da177e4SLinus Torvalds tlck->type |= tlckBTROOT; 721*1da177e4SLinus Torvalds tlck->mp = mp; 722*1da177e4SLinus Torvalds ilinelock = (struct linelock *) & tlck->lock; 723*1da177e4SLinus Torvalds 724*1da177e4SLinus Torvalds /* 725*1da177e4SLinus Torvalds * copy xtree root from inode to dinode: 726*1da177e4SLinus Torvalds */ 727*1da177e4SLinus Torvalds p = &jfs_ip->i_xtroot; 728*1da177e4SLinus Torvalds xp = (xtpage_t *) &dp->di_dirtable; 729*1da177e4SLinus Torvalds lv = ilinelock->lv; 730*1da177e4SLinus Torvalds for (n = 0; n < ilinelock->index; n++, lv++) { 731*1da177e4SLinus Torvalds memcpy(&xp->xad[lv->offset], &p->xad[lv->offset], 732*1da177e4SLinus Torvalds lv->length << L2XTSLOTSIZE); 733*1da177e4SLinus Torvalds } 734*1da177e4SLinus Torvalds 735*1da177e4SLinus Torvalds /* reset on-disk (metadata page) xtree XAD_NEW bit */ 736*1da177e4SLinus Torvalds xad = &xp->xad[XTENTRYSTART]; 737*1da177e4SLinus Torvalds for (n = XTENTRYSTART; 738*1da177e4SLinus Torvalds n < le16_to_cpu(xp->header.nextindex); n++, xad++) 739*1da177e4SLinus Torvalds if (xad->flag & (XAD_NEW | XAD_EXTENDED)) 740*1da177e4SLinus Torvalds xad->flag &= ~(XAD_NEW | XAD_EXTENDED); 741*1da177e4SLinus Torvalds } 742*1da177e4SLinus Torvalds 743*1da177e4SLinus Torvalds if ((lid = jfs_ip->blid) == 0) 744*1da177e4SLinus Torvalds goto inlineData; 745*1da177e4SLinus Torvalds jfs_ip->blid = 0; 746*1da177e4SLinus Torvalds 747*1da177e4SLinus Torvalds tlck = lid_to_tlock(lid); 748*1da177e4SLinus Torvalds type = tlck->type; 749*1da177e4SLinus Torvalds tlck->type |= tlckBTROOT; 750*1da177e4SLinus Torvalds tlck->mp = mp; 751*1da177e4SLinus Torvalds ilinelock = (struct linelock *) & tlck->lock; 752*1da177e4SLinus Torvalds 753*1da177e4SLinus Torvalds /* 754*1da177e4SLinus Torvalds * regular file: 16 byte (XAD slot) granularity 755*1da177e4SLinus Torvalds */ 756*1da177e4SLinus Torvalds if (type & tlckXTREE) { 757*1da177e4SLinus Torvalds xtpage_t *p, *xp; 758*1da177e4SLinus Torvalds xad_t *xad; 759*1da177e4SLinus Torvalds 760*1da177e4SLinus Torvalds /* 761*1da177e4SLinus Torvalds * copy xtree root from inode to dinode: 762*1da177e4SLinus Torvalds */ 763*1da177e4SLinus Torvalds p = &jfs_ip->i_xtroot; 764*1da177e4SLinus Torvalds xp = &dp->di_xtroot; 765*1da177e4SLinus Torvalds lv = ilinelock->lv; 766*1da177e4SLinus Torvalds for (n = 0; n < ilinelock->index; n++, lv++) { 767*1da177e4SLinus Torvalds memcpy(&xp->xad[lv->offset], &p->xad[lv->offset], 768*1da177e4SLinus Torvalds lv->length << L2XTSLOTSIZE); 769*1da177e4SLinus Torvalds } 770*1da177e4SLinus Torvalds 771*1da177e4SLinus Torvalds /* reset on-disk (metadata page) xtree XAD_NEW bit */ 772*1da177e4SLinus Torvalds xad = &xp->xad[XTENTRYSTART]; 773*1da177e4SLinus Torvalds for (n = XTENTRYSTART; 774*1da177e4SLinus Torvalds n < le16_to_cpu(xp->header.nextindex); n++, xad++) 775*1da177e4SLinus Torvalds if (xad->flag & (XAD_NEW | XAD_EXTENDED)) 776*1da177e4SLinus Torvalds xad->flag &= ~(XAD_NEW | XAD_EXTENDED); 777*1da177e4SLinus Torvalds } 778*1da177e4SLinus Torvalds /* 779*1da177e4SLinus Torvalds * directory: 32 byte (directory entry slot) granularity 780*1da177e4SLinus Torvalds */ 781*1da177e4SLinus Torvalds else if (type & tlckDTREE) { 782*1da177e4SLinus Torvalds dtpage_t *p, *xp; 783*1da177e4SLinus Torvalds 784*1da177e4SLinus Torvalds /* 785*1da177e4SLinus Torvalds * copy dtree root from inode to dinode: 786*1da177e4SLinus Torvalds */ 787*1da177e4SLinus Torvalds p = (dtpage_t *) &jfs_ip->i_dtroot; 788*1da177e4SLinus Torvalds xp = (dtpage_t *) & dp->di_dtroot; 789*1da177e4SLinus Torvalds lv = ilinelock->lv; 790*1da177e4SLinus Torvalds for (n = 0; n < ilinelock->index; n++, lv++) { 791*1da177e4SLinus Torvalds memcpy(&xp->slot[lv->offset], &p->slot[lv->offset], 792*1da177e4SLinus Torvalds lv->length << L2DTSLOTSIZE); 793*1da177e4SLinus Torvalds } 794*1da177e4SLinus Torvalds } else { 795*1da177e4SLinus Torvalds jfs_err("diWrite: UFO tlock"); 796*1da177e4SLinus Torvalds } 797*1da177e4SLinus Torvalds 798*1da177e4SLinus Torvalds inlineData: 799*1da177e4SLinus Torvalds /* 800*1da177e4SLinus Torvalds * copy inline symlink from in-memory inode to on-disk inode 801*1da177e4SLinus Torvalds */ 802*1da177e4SLinus Torvalds if (S_ISLNK(ip->i_mode) && ip->i_size < IDATASIZE) { 803*1da177e4SLinus Torvalds lv = & dilinelock->lv[dilinelock->index]; 804*1da177e4SLinus Torvalds lv->offset = (dioffset + 2 * 128) >> L2INODESLOTSIZE; 805*1da177e4SLinus Torvalds lv->length = 2; 806*1da177e4SLinus Torvalds memcpy(&dp->di_fastsymlink, jfs_ip->i_inline, IDATASIZE); 807*1da177e4SLinus Torvalds dilinelock->index++; 808*1da177e4SLinus Torvalds } 809*1da177e4SLinus Torvalds /* 810*1da177e4SLinus Torvalds * copy inline data from in-memory inode to on-disk inode: 811*1da177e4SLinus Torvalds * 128 byte slot granularity 812*1da177e4SLinus Torvalds */ 813*1da177e4SLinus Torvalds if (test_cflag(COMMIT_Inlineea, ip)) { 814*1da177e4SLinus Torvalds lv = & dilinelock->lv[dilinelock->index]; 815*1da177e4SLinus Torvalds lv->offset = (dioffset + 3 * 128) >> L2INODESLOTSIZE; 816*1da177e4SLinus Torvalds lv->length = 1; 817*1da177e4SLinus Torvalds memcpy(&dp->di_inlineea, jfs_ip->i_inline_ea, INODESLOTSIZE); 818*1da177e4SLinus Torvalds dilinelock->index++; 819*1da177e4SLinus Torvalds 820*1da177e4SLinus Torvalds clear_cflag(COMMIT_Inlineea, ip); 821*1da177e4SLinus Torvalds } 822*1da177e4SLinus Torvalds 823*1da177e4SLinus Torvalds /* 824*1da177e4SLinus Torvalds * lock/copy inode base: 128 byte slot granularity 825*1da177e4SLinus Torvalds */ 826*1da177e4SLinus Torvalds // baseDinode: 827*1da177e4SLinus Torvalds lv = & dilinelock->lv[dilinelock->index]; 828*1da177e4SLinus Torvalds lv->offset = dioffset >> L2INODESLOTSIZE; 829*1da177e4SLinus Torvalds copy_to_dinode(dp, ip); 830*1da177e4SLinus Torvalds if (test_and_clear_cflag(COMMIT_Dirtable, ip)) { 831*1da177e4SLinus Torvalds lv->length = 2; 832*1da177e4SLinus Torvalds memcpy(&dp->di_dirtable, &jfs_ip->i_dirtable, 96); 833*1da177e4SLinus Torvalds } else 834*1da177e4SLinus Torvalds lv->length = 1; 835*1da177e4SLinus Torvalds dilinelock->index++; 836*1da177e4SLinus Torvalds 837*1da177e4SLinus Torvalds #ifdef _JFS_FASTDASD 838*1da177e4SLinus Torvalds /* 839*1da177e4SLinus Torvalds * We aren't logging changes to the DASD used in directory inodes, 840*1da177e4SLinus Torvalds * but we need to write them to disk. If we don't unmount cleanly, 841*1da177e4SLinus Torvalds * mount will recalculate the DASD used. 842*1da177e4SLinus Torvalds */ 843*1da177e4SLinus Torvalds if (S_ISDIR(ip->i_mode) 844*1da177e4SLinus Torvalds && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED)) 845*1da177e4SLinus Torvalds memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd)); 846*1da177e4SLinus Torvalds #endif /* _JFS_FASTDASD */ 847*1da177e4SLinus Torvalds 848*1da177e4SLinus Torvalds /* release the buffer holding the updated on-disk inode. 849*1da177e4SLinus Torvalds * the buffer will be later written by commit processing. 850*1da177e4SLinus Torvalds */ 851*1da177e4SLinus Torvalds write_metapage(mp); 852*1da177e4SLinus Torvalds 853*1da177e4SLinus Torvalds return (rc); 854*1da177e4SLinus Torvalds } 855*1da177e4SLinus Torvalds 856*1da177e4SLinus Torvalds 857*1da177e4SLinus Torvalds /* 858*1da177e4SLinus Torvalds * NAME: diFree(ip) 859*1da177e4SLinus Torvalds * 860*1da177e4SLinus Torvalds * FUNCTION: free a specified inode from the inode working map 861*1da177e4SLinus Torvalds * for a fileset or aggregate. 862*1da177e4SLinus Torvalds * 863*1da177e4SLinus Torvalds * if the inode to be freed represents the first (only) 864*1da177e4SLinus Torvalds * free inode within the iag, the iag will be placed on 865*1da177e4SLinus Torvalds * the ag free inode list. 866*1da177e4SLinus Torvalds * 867*1da177e4SLinus Torvalds * freeing the inode will cause the inode extent to be 868*1da177e4SLinus Torvalds * freed if the inode is the only allocated inode within 869*1da177e4SLinus Torvalds * the extent. in this case all the disk resource backing 870*1da177e4SLinus Torvalds * up the inode extent will be freed. in addition, the iag 871*1da177e4SLinus Torvalds * will be placed on the ag extent free list if the extent 872*1da177e4SLinus Torvalds * is the first free extent in the iag. if freeing the 873*1da177e4SLinus Torvalds * extent also means that no free inodes will exist for 874*1da177e4SLinus Torvalds * the iag, the iag will also be removed from the ag free 875*1da177e4SLinus Torvalds * inode list. 876*1da177e4SLinus Torvalds * 877*1da177e4SLinus Torvalds * the iag describing the inode will be freed if the extent 878*1da177e4SLinus Torvalds * is to be freed and it is the only backed extent within 879*1da177e4SLinus Torvalds * the iag. in this case, the iag will be removed from the 880*1da177e4SLinus Torvalds * ag free extent list and ag free inode list and placed on 881*1da177e4SLinus Torvalds * the inode map's free iag list. 882*1da177e4SLinus Torvalds * 883*1da177e4SLinus Torvalds * a careful update approach is used to provide consistency 884*1da177e4SLinus Torvalds * in the face of updates to multiple buffers. under this 885*1da177e4SLinus Torvalds * approach, all required buffers are obtained before making 886*1da177e4SLinus Torvalds * any updates and are held until all updates are complete. 887*1da177e4SLinus Torvalds * 888*1da177e4SLinus Torvalds * PARAMETERS: 889*1da177e4SLinus Torvalds * ip - inode to be freed. 890*1da177e4SLinus Torvalds * 891*1da177e4SLinus Torvalds * RETURN VALUES: 892*1da177e4SLinus Torvalds * 0 - success 893*1da177e4SLinus Torvalds * -EIO - i/o error. 894*1da177e4SLinus Torvalds */ 895*1da177e4SLinus Torvalds int diFree(struct inode *ip) 896*1da177e4SLinus Torvalds { 897*1da177e4SLinus Torvalds int rc; 898*1da177e4SLinus Torvalds ino_t inum = ip->i_ino; 899*1da177e4SLinus Torvalds struct iag *iagp, *aiagp, *biagp, *ciagp, *diagp; 900*1da177e4SLinus Torvalds struct metapage *mp, *amp, *bmp, *cmp, *dmp; 901*1da177e4SLinus Torvalds int iagno, ino, extno, bitno, sword, agno; 902*1da177e4SLinus Torvalds int back, fwd; 903*1da177e4SLinus Torvalds u32 bitmap, mask; 904*1da177e4SLinus Torvalds struct inode *ipimap = JFS_SBI(ip->i_sb)->ipimap; 905*1da177e4SLinus Torvalds struct inomap *imap = JFS_IP(ipimap)->i_imap; 906*1da177e4SLinus Torvalds pxd_t freepxd; 907*1da177e4SLinus Torvalds tid_t tid; 908*1da177e4SLinus Torvalds struct inode *iplist[3]; 909*1da177e4SLinus Torvalds struct tlock *tlck; 910*1da177e4SLinus Torvalds struct pxd_lock *pxdlock; 911*1da177e4SLinus Torvalds 912*1da177e4SLinus Torvalds /* 913*1da177e4SLinus Torvalds * This is just to suppress compiler warnings. The same logic that 914*1da177e4SLinus Torvalds * references these variables is used to initialize them. 915*1da177e4SLinus Torvalds */ 916*1da177e4SLinus Torvalds aiagp = biagp = ciagp = diagp = NULL; 917*1da177e4SLinus Torvalds 918*1da177e4SLinus Torvalds /* get the iag number containing the inode. 919*1da177e4SLinus Torvalds */ 920*1da177e4SLinus Torvalds iagno = INOTOIAG(inum); 921*1da177e4SLinus Torvalds 922*1da177e4SLinus Torvalds /* make sure that the iag is contained within 923*1da177e4SLinus Torvalds * the map. 924*1da177e4SLinus Torvalds */ 925*1da177e4SLinus Torvalds if (iagno >= imap->im_nextiag) { 926*1da177e4SLinus Torvalds dump_mem("imap", imap, 32); 927*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 928*1da177e4SLinus Torvalds "diFree: inum = %d, iagno = %d, nextiag = %d", 929*1da177e4SLinus Torvalds (uint) inum, iagno, imap->im_nextiag); 930*1da177e4SLinus Torvalds return -EIO; 931*1da177e4SLinus Torvalds } 932*1da177e4SLinus Torvalds 933*1da177e4SLinus Torvalds /* get the allocation group for this ino. 934*1da177e4SLinus Torvalds */ 935*1da177e4SLinus Torvalds agno = JFS_IP(ip)->agno; 936*1da177e4SLinus Torvalds 937*1da177e4SLinus Torvalds /* Lock the AG specific inode map information 938*1da177e4SLinus Torvalds */ 939*1da177e4SLinus Torvalds AG_LOCK(imap, agno); 940*1da177e4SLinus Torvalds 941*1da177e4SLinus Torvalds /* Obtain read lock in imap inode. Don't release it until we have 942*1da177e4SLinus Torvalds * read all of the IAG's that we are going to. 943*1da177e4SLinus Torvalds */ 944*1da177e4SLinus Torvalds IREAD_LOCK(ipimap); 945*1da177e4SLinus Torvalds 946*1da177e4SLinus Torvalds /* read the iag. 947*1da177e4SLinus Torvalds */ 948*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, iagno, &mp))) { 949*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 950*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 951*1da177e4SLinus Torvalds return (rc); 952*1da177e4SLinus Torvalds } 953*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 954*1da177e4SLinus Torvalds 955*1da177e4SLinus Torvalds /* get the inode number and extent number of the inode within 956*1da177e4SLinus Torvalds * the iag and the inode number within the extent. 957*1da177e4SLinus Torvalds */ 958*1da177e4SLinus Torvalds ino = inum & (INOSPERIAG - 1); 959*1da177e4SLinus Torvalds extno = ino >> L2INOSPEREXT; 960*1da177e4SLinus Torvalds bitno = ino & (INOSPEREXT - 1); 961*1da177e4SLinus Torvalds mask = HIGHORDER >> bitno; 962*1da177e4SLinus Torvalds 963*1da177e4SLinus Torvalds if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { 964*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 965*1da177e4SLinus Torvalds "diFree: wmap shows inode already free"); 966*1da177e4SLinus Torvalds } 967*1da177e4SLinus Torvalds 968*1da177e4SLinus Torvalds if (!addressPXD(&iagp->inoext[extno])) { 969*1da177e4SLinus Torvalds release_metapage(mp); 970*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 971*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 972*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diFree: invalid inoext"); 973*1da177e4SLinus Torvalds return -EIO; 974*1da177e4SLinus Torvalds } 975*1da177e4SLinus Torvalds 976*1da177e4SLinus Torvalds /* compute the bitmap for the extent reflecting the freed inode. 977*1da177e4SLinus Torvalds */ 978*1da177e4SLinus Torvalds bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask; 979*1da177e4SLinus Torvalds 980*1da177e4SLinus Torvalds if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) { 981*1da177e4SLinus Torvalds release_metapage(mp); 982*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 983*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 984*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diFree: numfree > numinos"); 985*1da177e4SLinus Torvalds return -EIO; 986*1da177e4SLinus Torvalds } 987*1da177e4SLinus Torvalds /* 988*1da177e4SLinus Torvalds * inode extent still has some inodes or below low water mark: 989*1da177e4SLinus Torvalds * keep the inode extent; 990*1da177e4SLinus Torvalds */ 991*1da177e4SLinus Torvalds if (bitmap || 992*1da177e4SLinus Torvalds imap->im_agctl[agno].numfree < 96 || 993*1da177e4SLinus Torvalds (imap->im_agctl[agno].numfree < 288 && 994*1da177e4SLinus Torvalds (((imap->im_agctl[agno].numfree * 100) / 995*1da177e4SLinus Torvalds imap->im_agctl[agno].numinos) <= 25))) { 996*1da177e4SLinus Torvalds /* if the iag currently has no free inodes (i.e., 997*1da177e4SLinus Torvalds * the inode being freed is the first free inode of iag), 998*1da177e4SLinus Torvalds * insert the iag at head of the inode free list for the ag. 999*1da177e4SLinus Torvalds */ 1000*1da177e4SLinus Torvalds if (iagp->nfreeinos == 0) { 1001*1da177e4SLinus Torvalds /* check if there are any iags on the ag inode 1002*1da177e4SLinus Torvalds * free list. if so, read the first one so that 1003*1da177e4SLinus Torvalds * we can link the current iag onto the list at 1004*1da177e4SLinus Torvalds * the head. 1005*1da177e4SLinus Torvalds */ 1006*1da177e4SLinus Torvalds if ((fwd = imap->im_agctl[agno].inofree) >= 0) { 1007*1da177e4SLinus Torvalds /* read the iag that currently is the head 1008*1da177e4SLinus Torvalds * of the list. 1009*1da177e4SLinus Torvalds */ 1010*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, fwd, &))) { 1011*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1012*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1013*1da177e4SLinus Torvalds release_metapage(mp); 1014*1da177e4SLinus Torvalds return (rc); 1015*1da177e4SLinus Torvalds } 1016*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 1017*1da177e4SLinus Torvalds 1018*1da177e4SLinus Torvalds /* make current head point back to the iag. 1019*1da177e4SLinus Torvalds */ 1020*1da177e4SLinus Torvalds aiagp->inofreeback = cpu_to_le32(iagno); 1021*1da177e4SLinus Torvalds 1022*1da177e4SLinus Torvalds write_metapage(amp); 1023*1da177e4SLinus Torvalds } 1024*1da177e4SLinus Torvalds 1025*1da177e4SLinus Torvalds /* iag points forward to current head and iag 1026*1da177e4SLinus Torvalds * becomes the new head of the list. 1027*1da177e4SLinus Torvalds */ 1028*1da177e4SLinus Torvalds iagp->inofreefwd = 1029*1da177e4SLinus Torvalds cpu_to_le32(imap->im_agctl[agno].inofree); 1030*1da177e4SLinus Torvalds iagp->inofreeback = cpu_to_le32(-1); 1031*1da177e4SLinus Torvalds imap->im_agctl[agno].inofree = iagno; 1032*1da177e4SLinus Torvalds } 1033*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1034*1da177e4SLinus Torvalds 1035*1da177e4SLinus Torvalds /* update the free inode summary map for the extent if 1036*1da177e4SLinus Torvalds * freeing the inode means the extent will now have free 1037*1da177e4SLinus Torvalds * inodes (i.e., the inode being freed is the first free 1038*1da177e4SLinus Torvalds * inode of extent), 1039*1da177e4SLinus Torvalds */ 1040*1da177e4SLinus Torvalds if (iagp->wmap[extno] == cpu_to_le32(ONES)) { 1041*1da177e4SLinus Torvalds sword = extno >> L2EXTSPERSUM; 1042*1da177e4SLinus Torvalds bitno = extno & (EXTSPERSUM - 1); 1043*1da177e4SLinus Torvalds iagp->inosmap[sword] &= 1044*1da177e4SLinus Torvalds cpu_to_le32(~(HIGHORDER >> bitno)); 1045*1da177e4SLinus Torvalds } 1046*1da177e4SLinus Torvalds 1047*1da177e4SLinus Torvalds /* update the bitmap. 1048*1da177e4SLinus Torvalds */ 1049*1da177e4SLinus Torvalds iagp->wmap[extno] = cpu_to_le32(bitmap); 1050*1da177e4SLinus Torvalds DBG_DIFREE(imap, inum); 1051*1da177e4SLinus Torvalds 1052*1da177e4SLinus Torvalds /* update the free inode counts at the iag, ag and 1053*1da177e4SLinus Torvalds * map level. 1054*1da177e4SLinus Torvalds */ 1055*1da177e4SLinus Torvalds iagp->nfreeinos = 1056*1da177e4SLinus Torvalds cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 1); 1057*1da177e4SLinus Torvalds imap->im_agctl[agno].numfree += 1; 1058*1da177e4SLinus Torvalds atomic_inc(&imap->im_numfree); 1059*1da177e4SLinus Torvalds 1060*1da177e4SLinus Torvalds /* release the AG inode map lock 1061*1da177e4SLinus Torvalds */ 1062*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1063*1da177e4SLinus Torvalds 1064*1da177e4SLinus Torvalds /* write the iag */ 1065*1da177e4SLinus Torvalds write_metapage(mp); 1066*1da177e4SLinus Torvalds 1067*1da177e4SLinus Torvalds return (0); 1068*1da177e4SLinus Torvalds } 1069*1da177e4SLinus Torvalds 1070*1da177e4SLinus Torvalds 1071*1da177e4SLinus Torvalds /* 1072*1da177e4SLinus Torvalds * inode extent has become free and above low water mark: 1073*1da177e4SLinus Torvalds * free the inode extent; 1074*1da177e4SLinus Torvalds */ 1075*1da177e4SLinus Torvalds 1076*1da177e4SLinus Torvalds /* 1077*1da177e4SLinus Torvalds * prepare to update iag list(s) (careful update step 1) 1078*1da177e4SLinus Torvalds */ 1079*1da177e4SLinus Torvalds amp = bmp = cmp = dmp = NULL; 1080*1da177e4SLinus Torvalds fwd = back = -1; 1081*1da177e4SLinus Torvalds 1082*1da177e4SLinus Torvalds /* check if the iag currently has no free extents. if so, 1083*1da177e4SLinus Torvalds * it will be placed on the head of the ag extent free list. 1084*1da177e4SLinus Torvalds */ 1085*1da177e4SLinus Torvalds if (iagp->nfreeexts == 0) { 1086*1da177e4SLinus Torvalds /* check if the ag extent free list has any iags. 1087*1da177e4SLinus Torvalds * if so, read the iag at the head of the list now. 1088*1da177e4SLinus Torvalds * this (head) iag will be updated later to reflect 1089*1da177e4SLinus Torvalds * the addition of the current iag at the head of 1090*1da177e4SLinus Torvalds * the list. 1091*1da177e4SLinus Torvalds */ 1092*1da177e4SLinus Torvalds if ((fwd = imap->im_agctl[agno].extfree) >= 0) { 1093*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, fwd, &))) 1094*1da177e4SLinus Torvalds goto error_out; 1095*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 1096*1da177e4SLinus Torvalds } 1097*1da177e4SLinus Torvalds } else { 1098*1da177e4SLinus Torvalds /* iag has free extents. check if the addition of a free 1099*1da177e4SLinus Torvalds * extent will cause all extents to be free within this 1100*1da177e4SLinus Torvalds * iag. if so, the iag will be removed from the ag extent 1101*1da177e4SLinus Torvalds * free list and placed on the inode map's free iag list. 1102*1da177e4SLinus Torvalds */ 1103*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) { 1104*1da177e4SLinus Torvalds /* in preparation for removing the iag from the 1105*1da177e4SLinus Torvalds * ag extent free list, read the iags preceeding 1106*1da177e4SLinus Torvalds * and following the iag on the ag extent free 1107*1da177e4SLinus Torvalds * list. 1108*1da177e4SLinus Torvalds */ 1109*1da177e4SLinus Torvalds if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) { 1110*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, fwd, &))) 1111*1da177e4SLinus Torvalds goto error_out; 1112*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 1113*1da177e4SLinus Torvalds } 1114*1da177e4SLinus Torvalds 1115*1da177e4SLinus Torvalds if ((back = le32_to_cpu(iagp->extfreeback)) >= 0) { 1116*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, back, &bmp))) 1117*1da177e4SLinus Torvalds goto error_out; 1118*1da177e4SLinus Torvalds biagp = (struct iag *) bmp->data; 1119*1da177e4SLinus Torvalds } 1120*1da177e4SLinus Torvalds } 1121*1da177e4SLinus Torvalds } 1122*1da177e4SLinus Torvalds 1123*1da177e4SLinus Torvalds /* remove the iag from the ag inode free list if freeing 1124*1da177e4SLinus Torvalds * this extent cause the iag to have no free inodes. 1125*1da177e4SLinus Torvalds */ 1126*1da177e4SLinus Torvalds if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) { 1127*1da177e4SLinus Torvalds int inofreeback = le32_to_cpu(iagp->inofreeback); 1128*1da177e4SLinus Torvalds int inofreefwd = le32_to_cpu(iagp->inofreefwd); 1129*1da177e4SLinus Torvalds 1130*1da177e4SLinus Torvalds /* in preparation for removing the iag from the 1131*1da177e4SLinus Torvalds * ag inode free list, read the iags preceeding 1132*1da177e4SLinus Torvalds * and following the iag on the ag inode free 1133*1da177e4SLinus Torvalds * list. before reading these iags, we must make 1134*1da177e4SLinus Torvalds * sure that we already don't have them in hand 1135*1da177e4SLinus Torvalds * from up above, since re-reading an iag (buffer) 1136*1da177e4SLinus Torvalds * we are currently holding would cause a deadlock. 1137*1da177e4SLinus Torvalds */ 1138*1da177e4SLinus Torvalds if (inofreefwd >= 0) { 1139*1da177e4SLinus Torvalds 1140*1da177e4SLinus Torvalds if (inofreefwd == fwd) 1141*1da177e4SLinus Torvalds ciagp = (struct iag *) amp->data; 1142*1da177e4SLinus Torvalds else if (inofreefwd == back) 1143*1da177e4SLinus Torvalds ciagp = (struct iag *) bmp->data; 1144*1da177e4SLinus Torvalds else { 1145*1da177e4SLinus Torvalds if ((rc = 1146*1da177e4SLinus Torvalds diIAGRead(imap, inofreefwd, &cmp))) 1147*1da177e4SLinus Torvalds goto error_out; 1148*1da177e4SLinus Torvalds ciagp = (struct iag *) cmp->data; 1149*1da177e4SLinus Torvalds } 1150*1da177e4SLinus Torvalds assert(ciagp != NULL); 1151*1da177e4SLinus Torvalds } 1152*1da177e4SLinus Torvalds 1153*1da177e4SLinus Torvalds if (inofreeback >= 0) { 1154*1da177e4SLinus Torvalds if (inofreeback == fwd) 1155*1da177e4SLinus Torvalds diagp = (struct iag *) amp->data; 1156*1da177e4SLinus Torvalds else if (inofreeback == back) 1157*1da177e4SLinus Torvalds diagp = (struct iag *) bmp->data; 1158*1da177e4SLinus Torvalds else { 1159*1da177e4SLinus Torvalds if ((rc = 1160*1da177e4SLinus Torvalds diIAGRead(imap, inofreeback, &dmp))) 1161*1da177e4SLinus Torvalds goto error_out; 1162*1da177e4SLinus Torvalds diagp = (struct iag *) dmp->data; 1163*1da177e4SLinus Torvalds } 1164*1da177e4SLinus Torvalds assert(diagp != NULL); 1165*1da177e4SLinus Torvalds } 1166*1da177e4SLinus Torvalds } 1167*1da177e4SLinus Torvalds 1168*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1169*1da177e4SLinus Torvalds 1170*1da177e4SLinus Torvalds /* 1171*1da177e4SLinus Torvalds * invalidate any page of the inode extent freed from buffer cache; 1172*1da177e4SLinus Torvalds */ 1173*1da177e4SLinus Torvalds freepxd = iagp->inoext[extno]; 1174*1da177e4SLinus Torvalds invalidate_pxd_metapages(ip, freepxd); 1175*1da177e4SLinus Torvalds 1176*1da177e4SLinus Torvalds /* 1177*1da177e4SLinus Torvalds * update iag list(s) (careful update step 2) 1178*1da177e4SLinus Torvalds */ 1179*1da177e4SLinus Torvalds /* add the iag to the ag extent free list if this is the 1180*1da177e4SLinus Torvalds * first free extent for the iag. 1181*1da177e4SLinus Torvalds */ 1182*1da177e4SLinus Torvalds if (iagp->nfreeexts == 0) { 1183*1da177e4SLinus Torvalds if (fwd >= 0) 1184*1da177e4SLinus Torvalds aiagp->extfreeback = cpu_to_le32(iagno); 1185*1da177e4SLinus Torvalds 1186*1da177e4SLinus Torvalds iagp->extfreefwd = 1187*1da177e4SLinus Torvalds cpu_to_le32(imap->im_agctl[agno].extfree); 1188*1da177e4SLinus Torvalds iagp->extfreeback = cpu_to_le32(-1); 1189*1da177e4SLinus Torvalds imap->im_agctl[agno].extfree = iagno; 1190*1da177e4SLinus Torvalds } else { 1191*1da177e4SLinus Torvalds /* remove the iag from the ag extent list if all extents 1192*1da177e4SLinus Torvalds * are now free and place it on the inode map iag free list. 1193*1da177e4SLinus Torvalds */ 1194*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) { 1195*1da177e4SLinus Torvalds if (fwd >= 0) 1196*1da177e4SLinus Torvalds aiagp->extfreeback = iagp->extfreeback; 1197*1da177e4SLinus Torvalds 1198*1da177e4SLinus Torvalds if (back >= 0) 1199*1da177e4SLinus Torvalds biagp->extfreefwd = iagp->extfreefwd; 1200*1da177e4SLinus Torvalds else 1201*1da177e4SLinus Torvalds imap->im_agctl[agno].extfree = 1202*1da177e4SLinus Torvalds le32_to_cpu(iagp->extfreefwd); 1203*1da177e4SLinus Torvalds 1204*1da177e4SLinus Torvalds iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); 1205*1da177e4SLinus Torvalds 1206*1da177e4SLinus Torvalds IAGFREE_LOCK(imap); 1207*1da177e4SLinus Torvalds iagp->iagfree = cpu_to_le32(imap->im_freeiag); 1208*1da177e4SLinus Torvalds imap->im_freeiag = iagno; 1209*1da177e4SLinus Torvalds IAGFREE_UNLOCK(imap); 1210*1da177e4SLinus Torvalds } 1211*1da177e4SLinus Torvalds } 1212*1da177e4SLinus Torvalds 1213*1da177e4SLinus Torvalds /* remove the iag from the ag inode free list if freeing 1214*1da177e4SLinus Torvalds * this extent causes the iag to have no free inodes. 1215*1da177e4SLinus Torvalds */ 1216*1da177e4SLinus Torvalds if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) { 1217*1da177e4SLinus Torvalds if ((int) le32_to_cpu(iagp->inofreefwd) >= 0) 1218*1da177e4SLinus Torvalds ciagp->inofreeback = iagp->inofreeback; 1219*1da177e4SLinus Torvalds 1220*1da177e4SLinus Torvalds if ((int) le32_to_cpu(iagp->inofreeback) >= 0) 1221*1da177e4SLinus Torvalds diagp->inofreefwd = iagp->inofreefwd; 1222*1da177e4SLinus Torvalds else 1223*1da177e4SLinus Torvalds imap->im_agctl[agno].inofree = 1224*1da177e4SLinus Torvalds le32_to_cpu(iagp->inofreefwd); 1225*1da177e4SLinus Torvalds 1226*1da177e4SLinus Torvalds iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); 1227*1da177e4SLinus Torvalds } 1228*1da177e4SLinus Torvalds 1229*1da177e4SLinus Torvalds /* update the inode extent address and working map 1230*1da177e4SLinus Torvalds * to reflect the free extent. 1231*1da177e4SLinus Torvalds * the permanent map should have been updated already 1232*1da177e4SLinus Torvalds * for the inode being freed. 1233*1da177e4SLinus Torvalds */ 1234*1da177e4SLinus Torvalds if (iagp->pmap[extno] != 0) { 1235*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diFree: the pmap does not show inode free"); 1236*1da177e4SLinus Torvalds } 1237*1da177e4SLinus Torvalds iagp->wmap[extno] = 0; 1238*1da177e4SLinus Torvalds DBG_DIFREE(imap, inum); 1239*1da177e4SLinus Torvalds PXDlength(&iagp->inoext[extno], 0); 1240*1da177e4SLinus Torvalds PXDaddress(&iagp->inoext[extno], 0); 1241*1da177e4SLinus Torvalds 1242*1da177e4SLinus Torvalds /* update the free extent and free inode summary maps 1243*1da177e4SLinus Torvalds * to reflect the freed extent. 1244*1da177e4SLinus Torvalds * the inode summary map is marked to indicate no inodes 1245*1da177e4SLinus Torvalds * available for the freed extent. 1246*1da177e4SLinus Torvalds */ 1247*1da177e4SLinus Torvalds sword = extno >> L2EXTSPERSUM; 1248*1da177e4SLinus Torvalds bitno = extno & (EXTSPERSUM - 1); 1249*1da177e4SLinus Torvalds mask = HIGHORDER >> bitno; 1250*1da177e4SLinus Torvalds iagp->inosmap[sword] |= cpu_to_le32(mask); 1251*1da177e4SLinus Torvalds iagp->extsmap[sword] &= cpu_to_le32(~mask); 1252*1da177e4SLinus Torvalds 1253*1da177e4SLinus Torvalds /* update the number of free inodes and number of free extents 1254*1da177e4SLinus Torvalds * for the iag. 1255*1da177e4SLinus Torvalds */ 1256*1da177e4SLinus Torvalds iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1257*1da177e4SLinus Torvalds (INOSPEREXT - 1)); 1258*1da177e4SLinus Torvalds iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) + 1); 1259*1da177e4SLinus Torvalds 1260*1da177e4SLinus Torvalds /* update the number of free inodes and backed inodes 1261*1da177e4SLinus Torvalds * at the ag and inode map level. 1262*1da177e4SLinus Torvalds */ 1263*1da177e4SLinus Torvalds imap->im_agctl[agno].numfree -= (INOSPEREXT - 1); 1264*1da177e4SLinus Torvalds imap->im_agctl[agno].numinos -= INOSPEREXT; 1265*1da177e4SLinus Torvalds atomic_sub(INOSPEREXT - 1, &imap->im_numfree); 1266*1da177e4SLinus Torvalds atomic_sub(INOSPEREXT, &imap->im_numinos); 1267*1da177e4SLinus Torvalds 1268*1da177e4SLinus Torvalds if (amp) 1269*1da177e4SLinus Torvalds write_metapage(amp); 1270*1da177e4SLinus Torvalds if (bmp) 1271*1da177e4SLinus Torvalds write_metapage(bmp); 1272*1da177e4SLinus Torvalds if (cmp) 1273*1da177e4SLinus Torvalds write_metapage(cmp); 1274*1da177e4SLinus Torvalds if (dmp) 1275*1da177e4SLinus Torvalds write_metapage(dmp); 1276*1da177e4SLinus Torvalds 1277*1da177e4SLinus Torvalds /* 1278*1da177e4SLinus Torvalds * start transaction to update block allocation map 1279*1da177e4SLinus Torvalds * for the inode extent freed; 1280*1da177e4SLinus Torvalds * 1281*1da177e4SLinus Torvalds * N.B. AG_LOCK is released and iag will be released below, and 1282*1da177e4SLinus Torvalds * other thread may allocate inode from/reusing the ixad freed 1283*1da177e4SLinus Torvalds * BUT with new/different backing inode extent from the extent 1284*1da177e4SLinus Torvalds * to be freed by the transaction; 1285*1da177e4SLinus Torvalds */ 1286*1da177e4SLinus Torvalds tid = txBegin(ipimap->i_sb, COMMIT_FORCE); 1287*1da177e4SLinus Torvalds down(&JFS_IP(ipimap)->commit_sem); 1288*1da177e4SLinus Torvalds 1289*1da177e4SLinus Torvalds /* acquire tlock of the iag page of the freed ixad 1290*1da177e4SLinus Torvalds * to force the page NOHOMEOK (even though no data is 1291*1da177e4SLinus Torvalds * logged from the iag page) until NOREDOPAGE|FREEXTENT log 1292*1da177e4SLinus Torvalds * for the free of the extent is committed; 1293*1da177e4SLinus Torvalds * write FREEXTENT|NOREDOPAGE log record 1294*1da177e4SLinus Torvalds * N.B. linelock is overlaid as freed extent descriptor; 1295*1da177e4SLinus Torvalds */ 1296*1da177e4SLinus Torvalds tlck = txLock(tid, ipimap, mp, tlckINODE | tlckFREE); 1297*1da177e4SLinus Torvalds pxdlock = (struct pxd_lock *) & tlck->lock; 1298*1da177e4SLinus Torvalds pxdlock->flag = mlckFREEPXD; 1299*1da177e4SLinus Torvalds pxdlock->pxd = freepxd; 1300*1da177e4SLinus Torvalds pxdlock->index = 1; 1301*1da177e4SLinus Torvalds 1302*1da177e4SLinus Torvalds write_metapage(mp); 1303*1da177e4SLinus Torvalds 1304*1da177e4SLinus Torvalds iplist[0] = ipimap; 1305*1da177e4SLinus Torvalds 1306*1da177e4SLinus Torvalds /* 1307*1da177e4SLinus Torvalds * logredo needs the IAG number and IAG extent index in order 1308*1da177e4SLinus Torvalds * to ensure that the IMap is consistent. The least disruptive 1309*1da177e4SLinus Torvalds * way to pass these values through to the transaction manager 1310*1da177e4SLinus Torvalds * is in the iplist array. 1311*1da177e4SLinus Torvalds * 1312*1da177e4SLinus Torvalds * It's not pretty, but it works. 1313*1da177e4SLinus Torvalds */ 1314*1da177e4SLinus Torvalds iplist[1] = (struct inode *) (size_t)iagno; 1315*1da177e4SLinus Torvalds iplist[2] = (struct inode *) (size_t)extno; 1316*1da177e4SLinus Torvalds 1317*1da177e4SLinus Torvalds rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); 1318*1da177e4SLinus Torvalds 1319*1da177e4SLinus Torvalds txEnd(tid); 1320*1da177e4SLinus Torvalds up(&JFS_IP(ipimap)->commit_sem); 1321*1da177e4SLinus Torvalds 1322*1da177e4SLinus Torvalds /* unlock the AG inode map information */ 1323*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1324*1da177e4SLinus Torvalds 1325*1da177e4SLinus Torvalds return (0); 1326*1da177e4SLinus Torvalds 1327*1da177e4SLinus Torvalds error_out: 1328*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1329*1da177e4SLinus Torvalds 1330*1da177e4SLinus Torvalds if (amp) 1331*1da177e4SLinus Torvalds release_metapage(amp); 1332*1da177e4SLinus Torvalds if (bmp) 1333*1da177e4SLinus Torvalds release_metapage(bmp); 1334*1da177e4SLinus Torvalds if (cmp) 1335*1da177e4SLinus Torvalds release_metapage(cmp); 1336*1da177e4SLinus Torvalds if (dmp) 1337*1da177e4SLinus Torvalds release_metapage(dmp); 1338*1da177e4SLinus Torvalds 1339*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1340*1da177e4SLinus Torvalds 1341*1da177e4SLinus Torvalds release_metapage(mp); 1342*1da177e4SLinus Torvalds 1343*1da177e4SLinus Torvalds return (rc); 1344*1da177e4SLinus Torvalds } 1345*1da177e4SLinus Torvalds 1346*1da177e4SLinus Torvalds /* 1347*1da177e4SLinus Torvalds * There are several places in the diAlloc* routines where we initialize 1348*1da177e4SLinus Torvalds * the inode. 1349*1da177e4SLinus Torvalds */ 1350*1da177e4SLinus Torvalds static inline void 1351*1da177e4SLinus Torvalds diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp) 1352*1da177e4SLinus Torvalds { 1353*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 1354*1da177e4SLinus Torvalds struct jfs_inode_info *jfs_ip = JFS_IP(ip); 1355*1da177e4SLinus Torvalds 1356*1da177e4SLinus Torvalds ip->i_ino = (iagno << L2INOSPERIAG) + ino; 1357*1da177e4SLinus Torvalds DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino); 1358*1da177e4SLinus Torvalds jfs_ip->ixpxd = iagp->inoext[extno]; 1359*1da177e4SLinus Torvalds jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); 1360*1da177e4SLinus Torvalds jfs_ip->active_ag = -1; 1361*1da177e4SLinus Torvalds } 1362*1da177e4SLinus Torvalds 1363*1da177e4SLinus Torvalds 1364*1da177e4SLinus Torvalds /* 1365*1da177e4SLinus Torvalds * NAME: diAlloc(pip,dir,ip) 1366*1da177e4SLinus Torvalds * 1367*1da177e4SLinus Torvalds * FUNCTION: allocate a disk inode from the inode working map 1368*1da177e4SLinus Torvalds * for a fileset or aggregate. 1369*1da177e4SLinus Torvalds * 1370*1da177e4SLinus Torvalds * PARAMETERS: 1371*1da177e4SLinus Torvalds * pip - pointer to incore inode for the parent inode. 1372*1da177e4SLinus Torvalds * dir - TRUE if the new disk inode is for a directory. 1373*1da177e4SLinus Torvalds * ip - pointer to a new inode 1374*1da177e4SLinus Torvalds * 1375*1da177e4SLinus Torvalds * RETURN VALUES: 1376*1da177e4SLinus Torvalds * 0 - success. 1377*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 1378*1da177e4SLinus Torvalds * -EIO - i/o error. 1379*1da177e4SLinus Torvalds */ 1380*1da177e4SLinus Torvalds int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip) 1381*1da177e4SLinus Torvalds { 1382*1da177e4SLinus Torvalds int rc, ino, iagno, addext, extno, bitno, sword; 1383*1da177e4SLinus Torvalds int nwords, rem, i, agno; 1384*1da177e4SLinus Torvalds u32 mask, inosmap, extsmap; 1385*1da177e4SLinus Torvalds struct inode *ipimap; 1386*1da177e4SLinus Torvalds struct metapage *mp; 1387*1da177e4SLinus Torvalds ino_t inum; 1388*1da177e4SLinus Torvalds struct iag *iagp; 1389*1da177e4SLinus Torvalds struct inomap *imap; 1390*1da177e4SLinus Torvalds 1391*1da177e4SLinus Torvalds /* get the pointers to the inode map inode and the 1392*1da177e4SLinus Torvalds * corresponding imap control structure. 1393*1da177e4SLinus Torvalds */ 1394*1da177e4SLinus Torvalds ipimap = JFS_SBI(pip->i_sb)->ipimap; 1395*1da177e4SLinus Torvalds imap = JFS_IP(ipimap)->i_imap; 1396*1da177e4SLinus Torvalds JFS_IP(ip)->ipimap = ipimap; 1397*1da177e4SLinus Torvalds JFS_IP(ip)->fileset = FILESYSTEM_I; 1398*1da177e4SLinus Torvalds 1399*1da177e4SLinus Torvalds /* for a directory, the allocation policy is to start 1400*1da177e4SLinus Torvalds * at the ag level using the preferred ag. 1401*1da177e4SLinus Torvalds */ 1402*1da177e4SLinus Torvalds if (dir == TRUE) { 1403*1da177e4SLinus Torvalds agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap); 1404*1da177e4SLinus Torvalds AG_LOCK(imap, agno); 1405*1da177e4SLinus Torvalds goto tryag; 1406*1da177e4SLinus Torvalds } 1407*1da177e4SLinus Torvalds 1408*1da177e4SLinus Torvalds /* for files, the policy starts off by trying to allocate from 1409*1da177e4SLinus Torvalds * the same iag containing the parent disk inode: 1410*1da177e4SLinus Torvalds * try to allocate the new disk inode close to the parent disk 1411*1da177e4SLinus Torvalds * inode, using parent disk inode number + 1 as the allocation 1412*1da177e4SLinus Torvalds * hint. (we use a left-to-right policy to attempt to avoid 1413*1da177e4SLinus Torvalds * moving backward on the disk.) compute the hint within the 1414*1da177e4SLinus Torvalds * file system and the iag. 1415*1da177e4SLinus Torvalds */ 1416*1da177e4SLinus Torvalds 1417*1da177e4SLinus Torvalds /* get the ag number of this iag */ 1418*1da177e4SLinus Torvalds agno = JFS_IP(pip)->agno; 1419*1da177e4SLinus Torvalds 1420*1da177e4SLinus Torvalds if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { 1421*1da177e4SLinus Torvalds /* 1422*1da177e4SLinus Torvalds * There is an open file actively growing. We want to 1423*1da177e4SLinus Torvalds * allocate new inodes from a different ag to avoid 1424*1da177e4SLinus Torvalds * fragmentation problems. 1425*1da177e4SLinus Torvalds */ 1426*1da177e4SLinus Torvalds agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap); 1427*1da177e4SLinus Torvalds AG_LOCK(imap, agno); 1428*1da177e4SLinus Torvalds goto tryag; 1429*1da177e4SLinus Torvalds } 1430*1da177e4SLinus Torvalds 1431*1da177e4SLinus Torvalds inum = pip->i_ino + 1; 1432*1da177e4SLinus Torvalds ino = inum & (INOSPERIAG - 1); 1433*1da177e4SLinus Torvalds 1434*1da177e4SLinus Torvalds /* back off the the hint if it is outside of the iag */ 1435*1da177e4SLinus Torvalds if (ino == 0) 1436*1da177e4SLinus Torvalds inum = pip->i_ino; 1437*1da177e4SLinus Torvalds 1438*1da177e4SLinus Torvalds /* lock the AG inode map information */ 1439*1da177e4SLinus Torvalds AG_LOCK(imap, agno); 1440*1da177e4SLinus Torvalds 1441*1da177e4SLinus Torvalds /* Get read lock on imap inode */ 1442*1da177e4SLinus Torvalds IREAD_LOCK(ipimap); 1443*1da177e4SLinus Torvalds 1444*1da177e4SLinus Torvalds /* get the iag number and read the iag */ 1445*1da177e4SLinus Torvalds iagno = INOTOIAG(inum); 1446*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, iagno, &mp))) { 1447*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1448*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1449*1da177e4SLinus Torvalds return (rc); 1450*1da177e4SLinus Torvalds } 1451*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 1452*1da177e4SLinus Torvalds 1453*1da177e4SLinus Torvalds /* determine if new inode extent is allowed to be added to the iag. 1454*1da177e4SLinus Torvalds * new inode extent can be added to the iag if the ag 1455*1da177e4SLinus Torvalds * has less than 32 free disk inodes and the iag has free extents. 1456*1da177e4SLinus Torvalds */ 1457*1da177e4SLinus Torvalds addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts); 1458*1da177e4SLinus Torvalds 1459*1da177e4SLinus Torvalds /* 1460*1da177e4SLinus Torvalds * try to allocate from the IAG 1461*1da177e4SLinus Torvalds */ 1462*1da177e4SLinus Torvalds /* check if the inode may be allocated from the iag 1463*1da177e4SLinus Torvalds * (i.e. the inode has free inodes or new extent can be added). 1464*1da177e4SLinus Torvalds */ 1465*1da177e4SLinus Torvalds if (iagp->nfreeinos || addext) { 1466*1da177e4SLinus Torvalds /* determine the extent number of the hint. 1467*1da177e4SLinus Torvalds */ 1468*1da177e4SLinus Torvalds extno = ino >> L2INOSPEREXT; 1469*1da177e4SLinus Torvalds 1470*1da177e4SLinus Torvalds /* check if the extent containing the hint has backed 1471*1da177e4SLinus Torvalds * inodes. if so, try to allocate within this extent. 1472*1da177e4SLinus Torvalds */ 1473*1da177e4SLinus Torvalds if (addressPXD(&iagp->inoext[extno])) { 1474*1da177e4SLinus Torvalds bitno = ino & (INOSPEREXT - 1); 1475*1da177e4SLinus Torvalds if ((bitno = 1476*1da177e4SLinus Torvalds diFindFree(le32_to_cpu(iagp->wmap[extno]), 1477*1da177e4SLinus Torvalds bitno)) 1478*1da177e4SLinus Torvalds < INOSPEREXT) { 1479*1da177e4SLinus Torvalds ino = (extno << L2INOSPEREXT) + bitno; 1480*1da177e4SLinus Torvalds 1481*1da177e4SLinus Torvalds /* a free inode (bit) was found within this 1482*1da177e4SLinus Torvalds * extent, so allocate it. 1483*1da177e4SLinus Torvalds */ 1484*1da177e4SLinus Torvalds rc = diAllocBit(imap, iagp, ino); 1485*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1486*1da177e4SLinus Torvalds if (rc) { 1487*1da177e4SLinus Torvalds assert(rc == -EIO); 1488*1da177e4SLinus Torvalds } else { 1489*1da177e4SLinus Torvalds /* set the results of the allocation 1490*1da177e4SLinus Torvalds * and write the iag. 1491*1da177e4SLinus Torvalds */ 1492*1da177e4SLinus Torvalds diInitInode(ip, iagno, ino, extno, 1493*1da177e4SLinus Torvalds iagp); 1494*1da177e4SLinus Torvalds mark_metapage_dirty(mp); 1495*1da177e4SLinus Torvalds } 1496*1da177e4SLinus Torvalds release_metapage(mp); 1497*1da177e4SLinus Torvalds 1498*1da177e4SLinus Torvalds /* free the AG lock and return. 1499*1da177e4SLinus Torvalds */ 1500*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1501*1da177e4SLinus Torvalds return (rc); 1502*1da177e4SLinus Torvalds } 1503*1da177e4SLinus Torvalds 1504*1da177e4SLinus Torvalds if (!addext) 1505*1da177e4SLinus Torvalds extno = 1506*1da177e4SLinus Torvalds (extno == 1507*1da177e4SLinus Torvalds EXTSPERIAG - 1) ? 0 : extno + 1; 1508*1da177e4SLinus Torvalds } 1509*1da177e4SLinus Torvalds 1510*1da177e4SLinus Torvalds /* 1511*1da177e4SLinus Torvalds * no free inodes within the extent containing the hint. 1512*1da177e4SLinus Torvalds * 1513*1da177e4SLinus Torvalds * try to allocate from the backed extents following 1514*1da177e4SLinus Torvalds * hint or, if appropriate (i.e. addext is true), allocate 1515*1da177e4SLinus Torvalds * an extent of free inodes at or following the extent 1516*1da177e4SLinus Torvalds * containing the hint. 1517*1da177e4SLinus Torvalds * 1518*1da177e4SLinus Torvalds * the free inode and free extent summary maps are used 1519*1da177e4SLinus Torvalds * here, so determine the starting summary map position 1520*1da177e4SLinus Torvalds * and the number of words we'll have to examine. again, 1521*1da177e4SLinus Torvalds * the approach is to allocate following the hint, so we 1522*1da177e4SLinus Torvalds * might have to initially ignore prior bits of the summary 1523*1da177e4SLinus Torvalds * map that represent extents prior to the extent containing 1524*1da177e4SLinus Torvalds * the hint and later revisit these bits. 1525*1da177e4SLinus Torvalds */ 1526*1da177e4SLinus Torvalds bitno = extno & (EXTSPERSUM - 1); 1527*1da177e4SLinus Torvalds nwords = (bitno == 0) ? SMAPSZ : SMAPSZ + 1; 1528*1da177e4SLinus Torvalds sword = extno >> L2EXTSPERSUM; 1529*1da177e4SLinus Torvalds 1530*1da177e4SLinus Torvalds /* mask any prior bits for the starting words of the 1531*1da177e4SLinus Torvalds * summary map. 1532*1da177e4SLinus Torvalds */ 1533*1da177e4SLinus Torvalds mask = ONES << (EXTSPERSUM - bitno); 1534*1da177e4SLinus Torvalds inosmap = le32_to_cpu(iagp->inosmap[sword]) | mask; 1535*1da177e4SLinus Torvalds extsmap = le32_to_cpu(iagp->extsmap[sword]) | mask; 1536*1da177e4SLinus Torvalds 1537*1da177e4SLinus Torvalds /* scan the free inode and free extent summary maps for 1538*1da177e4SLinus Torvalds * free resources. 1539*1da177e4SLinus Torvalds */ 1540*1da177e4SLinus Torvalds for (i = 0; i < nwords; i++) { 1541*1da177e4SLinus Torvalds /* check if this word of the free inode summary 1542*1da177e4SLinus Torvalds * map describes an extent with free inodes. 1543*1da177e4SLinus Torvalds */ 1544*1da177e4SLinus Torvalds if (~inosmap) { 1545*1da177e4SLinus Torvalds /* an extent with free inodes has been 1546*1da177e4SLinus Torvalds * found. determine the extent number 1547*1da177e4SLinus Torvalds * and the inode number within the extent. 1548*1da177e4SLinus Torvalds */ 1549*1da177e4SLinus Torvalds rem = diFindFree(inosmap, 0); 1550*1da177e4SLinus Torvalds extno = (sword << L2EXTSPERSUM) + rem; 1551*1da177e4SLinus Torvalds rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 1552*1da177e4SLinus Torvalds 0); 1553*1da177e4SLinus Torvalds if (rem >= INOSPEREXT) { 1554*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1555*1da177e4SLinus Torvalds release_metapage(mp); 1556*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1557*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 1558*1da177e4SLinus Torvalds "diAlloc: can't find free bit " 1559*1da177e4SLinus Torvalds "in wmap"); 1560*1da177e4SLinus Torvalds return EIO; 1561*1da177e4SLinus Torvalds } 1562*1da177e4SLinus Torvalds 1563*1da177e4SLinus Torvalds /* determine the inode number within the 1564*1da177e4SLinus Torvalds * iag and allocate the inode from the 1565*1da177e4SLinus Torvalds * map. 1566*1da177e4SLinus Torvalds */ 1567*1da177e4SLinus Torvalds ino = (extno << L2INOSPEREXT) + rem; 1568*1da177e4SLinus Torvalds rc = diAllocBit(imap, iagp, ino); 1569*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1570*1da177e4SLinus Torvalds if (rc) 1571*1da177e4SLinus Torvalds assert(rc == -EIO); 1572*1da177e4SLinus Torvalds else { 1573*1da177e4SLinus Torvalds /* set the results of the allocation 1574*1da177e4SLinus Torvalds * and write the iag. 1575*1da177e4SLinus Torvalds */ 1576*1da177e4SLinus Torvalds diInitInode(ip, iagno, ino, extno, 1577*1da177e4SLinus Torvalds iagp); 1578*1da177e4SLinus Torvalds mark_metapage_dirty(mp); 1579*1da177e4SLinus Torvalds } 1580*1da177e4SLinus Torvalds release_metapage(mp); 1581*1da177e4SLinus Torvalds 1582*1da177e4SLinus Torvalds /* free the AG lock and return. 1583*1da177e4SLinus Torvalds */ 1584*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1585*1da177e4SLinus Torvalds return (rc); 1586*1da177e4SLinus Torvalds 1587*1da177e4SLinus Torvalds } 1588*1da177e4SLinus Torvalds 1589*1da177e4SLinus Torvalds /* check if we may allocate an extent of free 1590*1da177e4SLinus Torvalds * inodes and whether this word of the free 1591*1da177e4SLinus Torvalds * extents summary map describes a free extent. 1592*1da177e4SLinus Torvalds */ 1593*1da177e4SLinus Torvalds if (addext && ~extsmap) { 1594*1da177e4SLinus Torvalds /* a free extent has been found. determine 1595*1da177e4SLinus Torvalds * the extent number. 1596*1da177e4SLinus Torvalds */ 1597*1da177e4SLinus Torvalds rem = diFindFree(extsmap, 0); 1598*1da177e4SLinus Torvalds extno = (sword << L2EXTSPERSUM) + rem; 1599*1da177e4SLinus Torvalds 1600*1da177e4SLinus Torvalds /* allocate an extent of free inodes. 1601*1da177e4SLinus Torvalds */ 1602*1da177e4SLinus Torvalds if ((rc = diNewExt(imap, iagp, extno))) { 1603*1da177e4SLinus Torvalds /* if there is no disk space for a 1604*1da177e4SLinus Torvalds * new extent, try to allocate the 1605*1da177e4SLinus Torvalds * disk inode from somewhere else. 1606*1da177e4SLinus Torvalds */ 1607*1da177e4SLinus Torvalds if (rc == -ENOSPC) 1608*1da177e4SLinus Torvalds break; 1609*1da177e4SLinus Torvalds 1610*1da177e4SLinus Torvalds assert(rc == -EIO); 1611*1da177e4SLinus Torvalds } else { 1612*1da177e4SLinus Torvalds /* set the results of the allocation 1613*1da177e4SLinus Torvalds * and write the iag. 1614*1da177e4SLinus Torvalds */ 1615*1da177e4SLinus Torvalds diInitInode(ip, iagno, 1616*1da177e4SLinus Torvalds extno << L2INOSPEREXT, 1617*1da177e4SLinus Torvalds extno, iagp); 1618*1da177e4SLinus Torvalds mark_metapage_dirty(mp); 1619*1da177e4SLinus Torvalds } 1620*1da177e4SLinus Torvalds release_metapage(mp); 1621*1da177e4SLinus Torvalds /* free the imap inode & the AG lock & return. 1622*1da177e4SLinus Torvalds */ 1623*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1624*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1625*1da177e4SLinus Torvalds return (rc); 1626*1da177e4SLinus Torvalds } 1627*1da177e4SLinus Torvalds 1628*1da177e4SLinus Torvalds /* move on to the next set of summary map words. 1629*1da177e4SLinus Torvalds */ 1630*1da177e4SLinus Torvalds sword = (sword == SMAPSZ - 1) ? 0 : sword + 1; 1631*1da177e4SLinus Torvalds inosmap = le32_to_cpu(iagp->inosmap[sword]); 1632*1da177e4SLinus Torvalds extsmap = le32_to_cpu(iagp->extsmap[sword]); 1633*1da177e4SLinus Torvalds } 1634*1da177e4SLinus Torvalds } 1635*1da177e4SLinus Torvalds /* unlock imap inode */ 1636*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 1637*1da177e4SLinus Torvalds 1638*1da177e4SLinus Torvalds /* nothing doing in this iag, so release it. */ 1639*1da177e4SLinus Torvalds release_metapage(mp); 1640*1da177e4SLinus Torvalds 1641*1da177e4SLinus Torvalds tryag: 1642*1da177e4SLinus Torvalds /* 1643*1da177e4SLinus Torvalds * try to allocate anywhere within the same AG as the parent inode. 1644*1da177e4SLinus Torvalds */ 1645*1da177e4SLinus Torvalds rc = diAllocAG(imap, agno, dir, ip); 1646*1da177e4SLinus Torvalds 1647*1da177e4SLinus Torvalds AG_UNLOCK(imap, agno); 1648*1da177e4SLinus Torvalds 1649*1da177e4SLinus Torvalds if (rc != -ENOSPC) 1650*1da177e4SLinus Torvalds return (rc); 1651*1da177e4SLinus Torvalds 1652*1da177e4SLinus Torvalds /* 1653*1da177e4SLinus Torvalds * try to allocate in any AG. 1654*1da177e4SLinus Torvalds */ 1655*1da177e4SLinus Torvalds return (diAllocAny(imap, agno, dir, ip)); 1656*1da177e4SLinus Torvalds } 1657*1da177e4SLinus Torvalds 1658*1da177e4SLinus Torvalds 1659*1da177e4SLinus Torvalds /* 1660*1da177e4SLinus Torvalds * NAME: diAllocAG(imap,agno,dir,ip) 1661*1da177e4SLinus Torvalds * 1662*1da177e4SLinus Torvalds * FUNCTION: allocate a disk inode from the allocation group. 1663*1da177e4SLinus Torvalds * 1664*1da177e4SLinus Torvalds * this routine first determines if a new extent of free 1665*1da177e4SLinus Torvalds * inodes should be added for the allocation group, with 1666*1da177e4SLinus Torvalds * the current request satisfied from this extent. if this 1667*1da177e4SLinus Torvalds * is the case, an attempt will be made to do just that. if 1668*1da177e4SLinus Torvalds * this attempt fails or it has been determined that a new 1669*1da177e4SLinus Torvalds * extent should not be added, an attempt is made to satisfy 1670*1da177e4SLinus Torvalds * the request by allocating an existing (backed) free inode 1671*1da177e4SLinus Torvalds * from the allocation group. 1672*1da177e4SLinus Torvalds * 1673*1da177e4SLinus Torvalds * PRE CONDITION: Already have the AG lock for this AG. 1674*1da177e4SLinus Torvalds * 1675*1da177e4SLinus Torvalds * PARAMETERS: 1676*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 1677*1da177e4SLinus Torvalds * agno - allocation group to allocate from. 1678*1da177e4SLinus Torvalds * dir - TRUE if the new disk inode is for a directory. 1679*1da177e4SLinus Torvalds * ip - pointer to the new inode to be filled in on successful return 1680*1da177e4SLinus Torvalds * with the disk inode number allocated, its extent address 1681*1da177e4SLinus Torvalds * and the start of the ag. 1682*1da177e4SLinus Torvalds * 1683*1da177e4SLinus Torvalds * RETURN VALUES: 1684*1da177e4SLinus Torvalds * 0 - success. 1685*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 1686*1da177e4SLinus Torvalds * -EIO - i/o error. 1687*1da177e4SLinus Torvalds */ 1688*1da177e4SLinus Torvalds static int 1689*1da177e4SLinus Torvalds diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip) 1690*1da177e4SLinus Torvalds { 1691*1da177e4SLinus Torvalds int rc, addext, numfree, numinos; 1692*1da177e4SLinus Torvalds 1693*1da177e4SLinus Torvalds /* get the number of free and the number of backed disk 1694*1da177e4SLinus Torvalds * inodes currently within the ag. 1695*1da177e4SLinus Torvalds */ 1696*1da177e4SLinus Torvalds numfree = imap->im_agctl[agno].numfree; 1697*1da177e4SLinus Torvalds numinos = imap->im_agctl[agno].numinos; 1698*1da177e4SLinus Torvalds 1699*1da177e4SLinus Torvalds if (numfree > numinos) { 1700*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diAllocAG: numfree > numinos"); 1701*1da177e4SLinus Torvalds return -EIO; 1702*1da177e4SLinus Torvalds } 1703*1da177e4SLinus Torvalds 1704*1da177e4SLinus Torvalds /* determine if we should allocate a new extent of free inodes 1705*1da177e4SLinus Torvalds * within the ag: for directory inodes, add a new extent 1706*1da177e4SLinus Torvalds * if there are a small number of free inodes or number of free 1707*1da177e4SLinus Torvalds * inodes is a small percentage of the number of backed inodes. 1708*1da177e4SLinus Torvalds */ 1709*1da177e4SLinus Torvalds if (dir == TRUE) 1710*1da177e4SLinus Torvalds addext = (numfree < 64 || 1711*1da177e4SLinus Torvalds (numfree < 256 1712*1da177e4SLinus Torvalds && ((numfree * 100) / numinos) <= 20)); 1713*1da177e4SLinus Torvalds else 1714*1da177e4SLinus Torvalds addext = (numfree == 0); 1715*1da177e4SLinus Torvalds 1716*1da177e4SLinus Torvalds /* 1717*1da177e4SLinus Torvalds * try to allocate a new extent of free inodes. 1718*1da177e4SLinus Torvalds */ 1719*1da177e4SLinus Torvalds if (addext) { 1720*1da177e4SLinus Torvalds /* if free space is not avaliable for this new extent, try 1721*1da177e4SLinus Torvalds * below to allocate a free and existing (already backed) 1722*1da177e4SLinus Torvalds * inode from the ag. 1723*1da177e4SLinus Torvalds */ 1724*1da177e4SLinus Torvalds if ((rc = diAllocExt(imap, agno, ip)) != -ENOSPC) 1725*1da177e4SLinus Torvalds return (rc); 1726*1da177e4SLinus Torvalds } 1727*1da177e4SLinus Torvalds 1728*1da177e4SLinus Torvalds /* 1729*1da177e4SLinus Torvalds * try to allocate an existing free inode from the ag. 1730*1da177e4SLinus Torvalds */ 1731*1da177e4SLinus Torvalds return (diAllocIno(imap, agno, ip)); 1732*1da177e4SLinus Torvalds } 1733*1da177e4SLinus Torvalds 1734*1da177e4SLinus Torvalds 1735*1da177e4SLinus Torvalds /* 1736*1da177e4SLinus Torvalds * NAME: diAllocAny(imap,agno,dir,iap) 1737*1da177e4SLinus Torvalds * 1738*1da177e4SLinus Torvalds * FUNCTION: allocate a disk inode from any other allocation group. 1739*1da177e4SLinus Torvalds * 1740*1da177e4SLinus Torvalds * this routine is called when an allocation attempt within 1741*1da177e4SLinus Torvalds * the primary allocation group has failed. if attempts to 1742*1da177e4SLinus Torvalds * allocate an inode from any allocation group other than the 1743*1da177e4SLinus Torvalds * specified primary group. 1744*1da177e4SLinus Torvalds * 1745*1da177e4SLinus Torvalds * PARAMETERS: 1746*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 1747*1da177e4SLinus Torvalds * agno - primary allocation group (to avoid). 1748*1da177e4SLinus Torvalds * dir - TRUE if the new disk inode is for a directory. 1749*1da177e4SLinus Torvalds * ip - pointer to a new inode to be filled in on successful return 1750*1da177e4SLinus Torvalds * with the disk inode number allocated, its extent address 1751*1da177e4SLinus Torvalds * and the start of the ag. 1752*1da177e4SLinus Torvalds * 1753*1da177e4SLinus Torvalds * RETURN VALUES: 1754*1da177e4SLinus Torvalds * 0 - success. 1755*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 1756*1da177e4SLinus Torvalds * -EIO - i/o error. 1757*1da177e4SLinus Torvalds */ 1758*1da177e4SLinus Torvalds static int 1759*1da177e4SLinus Torvalds diAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip) 1760*1da177e4SLinus Torvalds { 1761*1da177e4SLinus Torvalds int ag, rc; 1762*1da177e4SLinus Torvalds int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag; 1763*1da177e4SLinus Torvalds 1764*1da177e4SLinus Torvalds 1765*1da177e4SLinus Torvalds /* try to allocate from the ags following agno up to 1766*1da177e4SLinus Torvalds * the maximum ag number. 1767*1da177e4SLinus Torvalds */ 1768*1da177e4SLinus Torvalds for (ag = agno + 1; ag <= maxag; ag++) { 1769*1da177e4SLinus Torvalds AG_LOCK(imap, ag); 1770*1da177e4SLinus Torvalds 1771*1da177e4SLinus Torvalds rc = diAllocAG(imap, ag, dir, ip); 1772*1da177e4SLinus Torvalds 1773*1da177e4SLinus Torvalds AG_UNLOCK(imap, ag); 1774*1da177e4SLinus Torvalds 1775*1da177e4SLinus Torvalds if (rc != -ENOSPC) 1776*1da177e4SLinus Torvalds return (rc); 1777*1da177e4SLinus Torvalds } 1778*1da177e4SLinus Torvalds 1779*1da177e4SLinus Torvalds /* try to allocate from the ags in front of agno. 1780*1da177e4SLinus Torvalds */ 1781*1da177e4SLinus Torvalds for (ag = 0; ag < agno; ag++) { 1782*1da177e4SLinus Torvalds AG_LOCK(imap, ag); 1783*1da177e4SLinus Torvalds 1784*1da177e4SLinus Torvalds rc = diAllocAG(imap, ag, dir, ip); 1785*1da177e4SLinus Torvalds 1786*1da177e4SLinus Torvalds AG_UNLOCK(imap, ag); 1787*1da177e4SLinus Torvalds 1788*1da177e4SLinus Torvalds if (rc != -ENOSPC) 1789*1da177e4SLinus Torvalds return (rc); 1790*1da177e4SLinus Torvalds } 1791*1da177e4SLinus Torvalds 1792*1da177e4SLinus Torvalds /* no free disk inodes. 1793*1da177e4SLinus Torvalds */ 1794*1da177e4SLinus Torvalds return -ENOSPC; 1795*1da177e4SLinus Torvalds } 1796*1da177e4SLinus Torvalds 1797*1da177e4SLinus Torvalds 1798*1da177e4SLinus Torvalds /* 1799*1da177e4SLinus Torvalds * NAME: diAllocIno(imap,agno,ip) 1800*1da177e4SLinus Torvalds * 1801*1da177e4SLinus Torvalds * FUNCTION: allocate a disk inode from the allocation group's free 1802*1da177e4SLinus Torvalds * inode list, returning an error if this free list is 1803*1da177e4SLinus Torvalds * empty (i.e. no iags on the list). 1804*1da177e4SLinus Torvalds * 1805*1da177e4SLinus Torvalds * allocation occurs from the first iag on the list using 1806*1da177e4SLinus Torvalds * the iag's free inode summary map to find the leftmost 1807*1da177e4SLinus Torvalds * free inode in the iag. 1808*1da177e4SLinus Torvalds * 1809*1da177e4SLinus Torvalds * PRE CONDITION: Already have AG lock for this AG. 1810*1da177e4SLinus Torvalds * 1811*1da177e4SLinus Torvalds * PARAMETERS: 1812*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 1813*1da177e4SLinus Torvalds * agno - allocation group. 1814*1da177e4SLinus Torvalds * ip - pointer to new inode to be filled in on successful return 1815*1da177e4SLinus Torvalds * with the disk inode number allocated, its extent address 1816*1da177e4SLinus Torvalds * and the start of the ag. 1817*1da177e4SLinus Torvalds * 1818*1da177e4SLinus Torvalds * RETURN VALUES: 1819*1da177e4SLinus Torvalds * 0 - success. 1820*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 1821*1da177e4SLinus Torvalds * -EIO - i/o error. 1822*1da177e4SLinus Torvalds */ 1823*1da177e4SLinus Torvalds static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) 1824*1da177e4SLinus Torvalds { 1825*1da177e4SLinus Torvalds int iagno, ino, rc, rem, extno, sword; 1826*1da177e4SLinus Torvalds struct metapage *mp; 1827*1da177e4SLinus Torvalds struct iag *iagp; 1828*1da177e4SLinus Torvalds 1829*1da177e4SLinus Torvalds /* check if there are iags on the ag's free inode list. 1830*1da177e4SLinus Torvalds */ 1831*1da177e4SLinus Torvalds if ((iagno = imap->im_agctl[agno].inofree) < 0) 1832*1da177e4SLinus Torvalds return -ENOSPC; 1833*1da177e4SLinus Torvalds 1834*1da177e4SLinus Torvalds /* obtain read lock on imap inode */ 1835*1da177e4SLinus Torvalds IREAD_LOCK(imap->im_ipimap); 1836*1da177e4SLinus Torvalds 1837*1da177e4SLinus Torvalds /* read the iag at the head of the list. 1838*1da177e4SLinus Torvalds */ 1839*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, iagno, &mp))) { 1840*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1841*1da177e4SLinus Torvalds return (rc); 1842*1da177e4SLinus Torvalds } 1843*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 1844*1da177e4SLinus Torvalds 1845*1da177e4SLinus Torvalds /* better be free inodes in this iag if it is on the 1846*1da177e4SLinus Torvalds * list. 1847*1da177e4SLinus Torvalds */ 1848*1da177e4SLinus Torvalds if (!iagp->nfreeinos) { 1849*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1850*1da177e4SLinus Torvalds release_metapage(mp); 1851*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 1852*1da177e4SLinus Torvalds "diAllocIno: nfreeinos = 0, but iag on freelist"); 1853*1da177e4SLinus Torvalds return -EIO; 1854*1da177e4SLinus Torvalds } 1855*1da177e4SLinus Torvalds 1856*1da177e4SLinus Torvalds /* scan the free inode summary map to find an extent 1857*1da177e4SLinus Torvalds * with free inodes. 1858*1da177e4SLinus Torvalds */ 1859*1da177e4SLinus Torvalds for (sword = 0;; sword++) { 1860*1da177e4SLinus Torvalds if (sword >= SMAPSZ) { 1861*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1862*1da177e4SLinus Torvalds release_metapage(mp); 1863*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 1864*1da177e4SLinus Torvalds "diAllocIno: free inode not found in summary map"); 1865*1da177e4SLinus Torvalds return -EIO; 1866*1da177e4SLinus Torvalds } 1867*1da177e4SLinus Torvalds 1868*1da177e4SLinus Torvalds if (~iagp->inosmap[sword]) 1869*1da177e4SLinus Torvalds break; 1870*1da177e4SLinus Torvalds } 1871*1da177e4SLinus Torvalds 1872*1da177e4SLinus Torvalds /* found a extent with free inodes. determine 1873*1da177e4SLinus Torvalds * the extent number. 1874*1da177e4SLinus Torvalds */ 1875*1da177e4SLinus Torvalds rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0); 1876*1da177e4SLinus Torvalds if (rem >= EXTSPERSUM) { 1877*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1878*1da177e4SLinus Torvalds release_metapage(mp); 1879*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diAllocIno: no free extent found"); 1880*1da177e4SLinus Torvalds return -EIO; 1881*1da177e4SLinus Torvalds } 1882*1da177e4SLinus Torvalds extno = (sword << L2EXTSPERSUM) + rem; 1883*1da177e4SLinus Torvalds 1884*1da177e4SLinus Torvalds /* find the first free inode in the extent. 1885*1da177e4SLinus Torvalds */ 1886*1da177e4SLinus Torvalds rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0); 1887*1da177e4SLinus Torvalds if (rem >= INOSPEREXT) { 1888*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1889*1da177e4SLinus Torvalds release_metapage(mp); 1890*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diAllocIno: free inode not found"); 1891*1da177e4SLinus Torvalds return -EIO; 1892*1da177e4SLinus Torvalds } 1893*1da177e4SLinus Torvalds 1894*1da177e4SLinus Torvalds /* compute the inode number within the iag. 1895*1da177e4SLinus Torvalds */ 1896*1da177e4SLinus Torvalds ino = (extno << L2INOSPEREXT) + rem; 1897*1da177e4SLinus Torvalds 1898*1da177e4SLinus Torvalds /* allocate the inode. 1899*1da177e4SLinus Torvalds */ 1900*1da177e4SLinus Torvalds rc = diAllocBit(imap, iagp, ino); 1901*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1902*1da177e4SLinus Torvalds if (rc) { 1903*1da177e4SLinus Torvalds release_metapage(mp); 1904*1da177e4SLinus Torvalds return (rc); 1905*1da177e4SLinus Torvalds } 1906*1da177e4SLinus Torvalds 1907*1da177e4SLinus Torvalds /* set the results of the allocation and write the iag. 1908*1da177e4SLinus Torvalds */ 1909*1da177e4SLinus Torvalds diInitInode(ip, iagno, ino, extno, iagp); 1910*1da177e4SLinus Torvalds write_metapage(mp); 1911*1da177e4SLinus Torvalds 1912*1da177e4SLinus Torvalds return (0); 1913*1da177e4SLinus Torvalds } 1914*1da177e4SLinus Torvalds 1915*1da177e4SLinus Torvalds 1916*1da177e4SLinus Torvalds /* 1917*1da177e4SLinus Torvalds * NAME: diAllocExt(imap,agno,ip) 1918*1da177e4SLinus Torvalds * 1919*1da177e4SLinus Torvalds * FUNCTION: add a new extent of free inodes to an iag, allocating 1920*1da177e4SLinus Torvalds * an inode from this extent to satisfy the current allocation 1921*1da177e4SLinus Torvalds * request. 1922*1da177e4SLinus Torvalds * 1923*1da177e4SLinus Torvalds * this routine first tries to find an existing iag with free 1924*1da177e4SLinus Torvalds * extents through the ag free extent list. if list is not 1925*1da177e4SLinus Torvalds * empty, the head of the list will be selected as the home 1926*1da177e4SLinus Torvalds * of the new extent of free inodes. otherwise (the list is 1927*1da177e4SLinus Torvalds * empty), a new iag will be allocated for the ag to contain 1928*1da177e4SLinus Torvalds * the extent. 1929*1da177e4SLinus Torvalds * 1930*1da177e4SLinus Torvalds * once an iag has been selected, the free extent summary map 1931*1da177e4SLinus Torvalds * is used to locate a free extent within the iag and diNewExt() 1932*1da177e4SLinus Torvalds * is called to initialize the extent, with initialization 1933*1da177e4SLinus Torvalds * including the allocation of the first inode of the extent 1934*1da177e4SLinus Torvalds * for the purpose of satisfying this request. 1935*1da177e4SLinus Torvalds * 1936*1da177e4SLinus Torvalds * PARAMETERS: 1937*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 1938*1da177e4SLinus Torvalds * agno - allocation group number. 1939*1da177e4SLinus Torvalds * ip - pointer to new inode to be filled in on successful return 1940*1da177e4SLinus Torvalds * with the disk inode number allocated, its extent address 1941*1da177e4SLinus Torvalds * and the start of the ag. 1942*1da177e4SLinus Torvalds * 1943*1da177e4SLinus Torvalds * RETURN VALUES: 1944*1da177e4SLinus Torvalds * 0 - success. 1945*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 1946*1da177e4SLinus Torvalds * -EIO - i/o error. 1947*1da177e4SLinus Torvalds */ 1948*1da177e4SLinus Torvalds static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) 1949*1da177e4SLinus Torvalds { 1950*1da177e4SLinus Torvalds int rem, iagno, sword, extno, rc; 1951*1da177e4SLinus Torvalds struct metapage *mp; 1952*1da177e4SLinus Torvalds struct iag *iagp; 1953*1da177e4SLinus Torvalds 1954*1da177e4SLinus Torvalds /* check if the ag has any iags with free extents. if not, 1955*1da177e4SLinus Torvalds * allocate a new iag for the ag. 1956*1da177e4SLinus Torvalds */ 1957*1da177e4SLinus Torvalds if ((iagno = imap->im_agctl[agno].extfree) < 0) { 1958*1da177e4SLinus Torvalds /* If successful, diNewIAG will obtain the read lock on the 1959*1da177e4SLinus Torvalds * imap inode. 1960*1da177e4SLinus Torvalds */ 1961*1da177e4SLinus Torvalds if ((rc = diNewIAG(imap, &iagno, agno, &mp))) { 1962*1da177e4SLinus Torvalds return (rc); 1963*1da177e4SLinus Torvalds } 1964*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 1965*1da177e4SLinus Torvalds 1966*1da177e4SLinus Torvalds /* set the ag number if this a brand new iag 1967*1da177e4SLinus Torvalds */ 1968*1da177e4SLinus Torvalds iagp->agstart = 1969*1da177e4SLinus Torvalds cpu_to_le64(AGTOBLK(agno, imap->im_ipimap)); 1970*1da177e4SLinus Torvalds } else { 1971*1da177e4SLinus Torvalds /* read the iag. 1972*1da177e4SLinus Torvalds */ 1973*1da177e4SLinus Torvalds IREAD_LOCK(imap->im_ipimap); 1974*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, iagno, &mp))) { 1975*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1976*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diAllocExt: error reading iag"); 1977*1da177e4SLinus Torvalds return rc; 1978*1da177e4SLinus Torvalds } 1979*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 1980*1da177e4SLinus Torvalds } 1981*1da177e4SLinus Torvalds 1982*1da177e4SLinus Torvalds /* using the free extent summary map, find a free extent. 1983*1da177e4SLinus Torvalds */ 1984*1da177e4SLinus Torvalds for (sword = 0;; sword++) { 1985*1da177e4SLinus Torvalds if (sword >= SMAPSZ) { 1986*1da177e4SLinus Torvalds release_metapage(mp); 1987*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 1988*1da177e4SLinus Torvalds jfs_error(ip->i_sb, 1989*1da177e4SLinus Torvalds "diAllocExt: free ext summary map not found"); 1990*1da177e4SLinus Torvalds return -EIO; 1991*1da177e4SLinus Torvalds } 1992*1da177e4SLinus Torvalds if (~iagp->extsmap[sword]) 1993*1da177e4SLinus Torvalds break; 1994*1da177e4SLinus Torvalds } 1995*1da177e4SLinus Torvalds 1996*1da177e4SLinus Torvalds /* determine the extent number of the free extent. 1997*1da177e4SLinus Torvalds */ 1998*1da177e4SLinus Torvalds rem = diFindFree(le32_to_cpu(iagp->extsmap[sword]), 0); 1999*1da177e4SLinus Torvalds if (rem >= EXTSPERSUM) { 2000*1da177e4SLinus Torvalds release_metapage(mp); 2001*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 2002*1da177e4SLinus Torvalds jfs_error(ip->i_sb, "diAllocExt: free extent not found"); 2003*1da177e4SLinus Torvalds return -EIO; 2004*1da177e4SLinus Torvalds } 2005*1da177e4SLinus Torvalds extno = (sword << L2EXTSPERSUM) + rem; 2006*1da177e4SLinus Torvalds 2007*1da177e4SLinus Torvalds /* initialize the new extent. 2008*1da177e4SLinus Torvalds */ 2009*1da177e4SLinus Torvalds rc = diNewExt(imap, iagp, extno); 2010*1da177e4SLinus Torvalds IREAD_UNLOCK(imap->im_ipimap); 2011*1da177e4SLinus Torvalds if (rc) { 2012*1da177e4SLinus Torvalds /* something bad happened. if a new iag was allocated, 2013*1da177e4SLinus Torvalds * place it back on the inode map's iag free list, and 2014*1da177e4SLinus Torvalds * clear the ag number information. 2015*1da177e4SLinus Torvalds */ 2016*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) { 2017*1da177e4SLinus Torvalds IAGFREE_LOCK(imap); 2018*1da177e4SLinus Torvalds iagp->iagfree = cpu_to_le32(imap->im_freeiag); 2019*1da177e4SLinus Torvalds imap->im_freeiag = iagno; 2020*1da177e4SLinus Torvalds IAGFREE_UNLOCK(imap); 2021*1da177e4SLinus Torvalds } 2022*1da177e4SLinus Torvalds write_metapage(mp); 2023*1da177e4SLinus Torvalds return (rc); 2024*1da177e4SLinus Torvalds } 2025*1da177e4SLinus Torvalds 2026*1da177e4SLinus Torvalds /* set the results of the allocation and write the iag. 2027*1da177e4SLinus Torvalds */ 2028*1da177e4SLinus Torvalds diInitInode(ip, iagno, extno << L2INOSPEREXT, extno, iagp); 2029*1da177e4SLinus Torvalds 2030*1da177e4SLinus Torvalds write_metapage(mp); 2031*1da177e4SLinus Torvalds 2032*1da177e4SLinus Torvalds return (0); 2033*1da177e4SLinus Torvalds } 2034*1da177e4SLinus Torvalds 2035*1da177e4SLinus Torvalds 2036*1da177e4SLinus Torvalds /* 2037*1da177e4SLinus Torvalds * NAME: diAllocBit(imap,iagp,ino) 2038*1da177e4SLinus Torvalds * 2039*1da177e4SLinus Torvalds * FUNCTION: allocate a backed inode from an iag. 2040*1da177e4SLinus Torvalds * 2041*1da177e4SLinus Torvalds * this routine performs the mechanics of allocating a 2042*1da177e4SLinus Torvalds * specified inode from a backed extent. 2043*1da177e4SLinus Torvalds * 2044*1da177e4SLinus Torvalds * if the inode to be allocated represents the last free 2045*1da177e4SLinus Torvalds * inode within the iag, the iag will be removed from the 2046*1da177e4SLinus Torvalds * ag free inode list. 2047*1da177e4SLinus Torvalds * 2048*1da177e4SLinus Torvalds * a careful update approach is used to provide consistency 2049*1da177e4SLinus Torvalds * in the face of updates to multiple buffers. under this 2050*1da177e4SLinus Torvalds * approach, all required buffers are obtained before making 2051*1da177e4SLinus Torvalds * any updates and are held all are updates are complete. 2052*1da177e4SLinus Torvalds * 2053*1da177e4SLinus Torvalds * PRE CONDITION: Already have buffer lock on iagp. Already have AG lock on 2054*1da177e4SLinus Torvalds * this AG. Must have read lock on imap inode. 2055*1da177e4SLinus Torvalds * 2056*1da177e4SLinus Torvalds * PARAMETERS: 2057*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 2058*1da177e4SLinus Torvalds * iagp - pointer to iag. 2059*1da177e4SLinus Torvalds * ino - inode number to be allocated within the iag. 2060*1da177e4SLinus Torvalds * 2061*1da177e4SLinus Torvalds * RETURN VALUES: 2062*1da177e4SLinus Torvalds * 0 - success. 2063*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 2064*1da177e4SLinus Torvalds * -EIO - i/o error. 2065*1da177e4SLinus Torvalds */ 2066*1da177e4SLinus Torvalds static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) 2067*1da177e4SLinus Torvalds { 2068*1da177e4SLinus Torvalds int extno, bitno, agno, sword, rc; 2069*1da177e4SLinus Torvalds struct metapage *amp = NULL, *bmp = NULL; 2070*1da177e4SLinus Torvalds struct iag *aiagp = NULL, *biagp = NULL; 2071*1da177e4SLinus Torvalds u32 mask; 2072*1da177e4SLinus Torvalds 2073*1da177e4SLinus Torvalds /* check if this is the last free inode within the iag. 2074*1da177e4SLinus Torvalds * if so, it will have to be removed from the ag free 2075*1da177e4SLinus Torvalds * inode list, so get the iags preceeding and following 2076*1da177e4SLinus Torvalds * it on the list. 2077*1da177e4SLinus Torvalds */ 2078*1da177e4SLinus Torvalds if (iagp->nfreeinos == cpu_to_le32(1)) { 2079*1da177e4SLinus Torvalds if ((int) le32_to_cpu(iagp->inofreefwd) >= 0) { 2080*1da177e4SLinus Torvalds if ((rc = 2081*1da177e4SLinus Torvalds diIAGRead(imap, le32_to_cpu(iagp->inofreefwd), 2082*1da177e4SLinus Torvalds &))) 2083*1da177e4SLinus Torvalds return (rc); 2084*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 2085*1da177e4SLinus Torvalds } 2086*1da177e4SLinus Torvalds 2087*1da177e4SLinus Torvalds if ((int) le32_to_cpu(iagp->inofreeback) >= 0) { 2088*1da177e4SLinus Torvalds if ((rc = 2089*1da177e4SLinus Torvalds diIAGRead(imap, 2090*1da177e4SLinus Torvalds le32_to_cpu(iagp->inofreeback), 2091*1da177e4SLinus Torvalds &bmp))) { 2092*1da177e4SLinus Torvalds if (amp) 2093*1da177e4SLinus Torvalds release_metapage(amp); 2094*1da177e4SLinus Torvalds return (rc); 2095*1da177e4SLinus Torvalds } 2096*1da177e4SLinus Torvalds biagp = (struct iag *) bmp->data; 2097*1da177e4SLinus Torvalds } 2098*1da177e4SLinus Torvalds } 2099*1da177e4SLinus Torvalds 2100*1da177e4SLinus Torvalds /* get the ag number, extent number, inode number within 2101*1da177e4SLinus Torvalds * the extent. 2102*1da177e4SLinus Torvalds */ 2103*1da177e4SLinus Torvalds agno = BLKTOAG(le64_to_cpu(iagp->agstart), JFS_SBI(imap->im_ipimap->i_sb)); 2104*1da177e4SLinus Torvalds extno = ino >> L2INOSPEREXT; 2105*1da177e4SLinus Torvalds bitno = ino & (INOSPEREXT - 1); 2106*1da177e4SLinus Torvalds 2107*1da177e4SLinus Torvalds /* compute the mask for setting the map. 2108*1da177e4SLinus Torvalds */ 2109*1da177e4SLinus Torvalds mask = HIGHORDER >> bitno; 2110*1da177e4SLinus Torvalds 2111*1da177e4SLinus Torvalds /* the inode should be free and backed. 2112*1da177e4SLinus Torvalds */ 2113*1da177e4SLinus Torvalds if (((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) || 2114*1da177e4SLinus Torvalds ((le32_to_cpu(iagp->wmap[extno]) & mask) != 0) || 2115*1da177e4SLinus Torvalds (addressPXD(&iagp->inoext[extno]) == 0)) { 2116*1da177e4SLinus Torvalds if (amp) 2117*1da177e4SLinus Torvalds release_metapage(amp); 2118*1da177e4SLinus Torvalds if (bmp) 2119*1da177e4SLinus Torvalds release_metapage(bmp); 2120*1da177e4SLinus Torvalds 2121*1da177e4SLinus Torvalds jfs_error(imap->im_ipimap->i_sb, 2122*1da177e4SLinus Torvalds "diAllocBit: iag inconsistent"); 2123*1da177e4SLinus Torvalds return -EIO; 2124*1da177e4SLinus Torvalds } 2125*1da177e4SLinus Torvalds 2126*1da177e4SLinus Torvalds /* mark the inode as allocated in the working map. 2127*1da177e4SLinus Torvalds */ 2128*1da177e4SLinus Torvalds iagp->wmap[extno] |= cpu_to_le32(mask); 2129*1da177e4SLinus Torvalds 2130*1da177e4SLinus Torvalds /* check if all inodes within the extent are now 2131*1da177e4SLinus Torvalds * allocated. if so, update the free inode summary 2132*1da177e4SLinus Torvalds * map to reflect this. 2133*1da177e4SLinus Torvalds */ 2134*1da177e4SLinus Torvalds if (iagp->wmap[extno] == cpu_to_le32(ONES)) { 2135*1da177e4SLinus Torvalds sword = extno >> L2EXTSPERSUM; 2136*1da177e4SLinus Torvalds bitno = extno & (EXTSPERSUM - 1); 2137*1da177e4SLinus Torvalds iagp->inosmap[sword] |= cpu_to_le32(HIGHORDER >> bitno); 2138*1da177e4SLinus Torvalds } 2139*1da177e4SLinus Torvalds 2140*1da177e4SLinus Torvalds /* if this was the last free inode in the iag, remove the 2141*1da177e4SLinus Torvalds * iag from the ag free inode list. 2142*1da177e4SLinus Torvalds */ 2143*1da177e4SLinus Torvalds if (iagp->nfreeinos == cpu_to_le32(1)) { 2144*1da177e4SLinus Torvalds if (amp) { 2145*1da177e4SLinus Torvalds aiagp->inofreeback = iagp->inofreeback; 2146*1da177e4SLinus Torvalds write_metapage(amp); 2147*1da177e4SLinus Torvalds } 2148*1da177e4SLinus Torvalds 2149*1da177e4SLinus Torvalds if (bmp) { 2150*1da177e4SLinus Torvalds biagp->inofreefwd = iagp->inofreefwd; 2151*1da177e4SLinus Torvalds write_metapage(bmp); 2152*1da177e4SLinus Torvalds } else { 2153*1da177e4SLinus Torvalds imap->im_agctl[agno].inofree = 2154*1da177e4SLinus Torvalds le32_to_cpu(iagp->inofreefwd); 2155*1da177e4SLinus Torvalds } 2156*1da177e4SLinus Torvalds iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); 2157*1da177e4SLinus Torvalds } 2158*1da177e4SLinus Torvalds 2159*1da177e4SLinus Torvalds /* update the free inode count at the iag, ag, inode 2160*1da177e4SLinus Torvalds * map levels. 2161*1da177e4SLinus Torvalds */ 2162*1da177e4SLinus Torvalds iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1); 2163*1da177e4SLinus Torvalds imap->im_agctl[agno].numfree -= 1; 2164*1da177e4SLinus Torvalds atomic_dec(&imap->im_numfree); 2165*1da177e4SLinus Torvalds 2166*1da177e4SLinus Torvalds return (0); 2167*1da177e4SLinus Torvalds } 2168*1da177e4SLinus Torvalds 2169*1da177e4SLinus Torvalds 2170*1da177e4SLinus Torvalds /* 2171*1da177e4SLinus Torvalds * NAME: diNewExt(imap,iagp,extno) 2172*1da177e4SLinus Torvalds * 2173*1da177e4SLinus Torvalds * FUNCTION: initialize a new extent of inodes for an iag, allocating 2174*1da177e4SLinus Torvalds * the first inode of the extent for use for the current 2175*1da177e4SLinus Torvalds * allocation request. 2176*1da177e4SLinus Torvalds * 2177*1da177e4SLinus Torvalds * disk resources are allocated for the new extent of inodes 2178*1da177e4SLinus Torvalds * and the inodes themselves are initialized to reflect their 2179*1da177e4SLinus Torvalds * existence within the extent (i.e. their inode numbers and 2180*1da177e4SLinus Torvalds * inode extent addresses are set) and their initial state 2181*1da177e4SLinus Torvalds * (mode and link count are set to zero). 2182*1da177e4SLinus Torvalds * 2183*1da177e4SLinus Torvalds * if the iag is new, it is not yet on an ag extent free list 2184*1da177e4SLinus Torvalds * but will now be placed on this list. 2185*1da177e4SLinus Torvalds * 2186*1da177e4SLinus Torvalds * if the allocation of the new extent causes the iag to 2187*1da177e4SLinus Torvalds * have no free extent, the iag will be removed from the 2188*1da177e4SLinus Torvalds * ag extent free list. 2189*1da177e4SLinus Torvalds * 2190*1da177e4SLinus Torvalds * if the iag has no free backed inodes, it will be placed 2191*1da177e4SLinus Torvalds * on the ag free inode list, since the addition of the new 2192*1da177e4SLinus Torvalds * extent will now cause it to have free inodes. 2193*1da177e4SLinus Torvalds * 2194*1da177e4SLinus Torvalds * a careful update approach is used to provide consistency 2195*1da177e4SLinus Torvalds * (i.e. list consistency) in the face of updates to multiple 2196*1da177e4SLinus Torvalds * buffers. under this approach, all required buffers are 2197*1da177e4SLinus Torvalds * obtained before making any updates and are held until all 2198*1da177e4SLinus Torvalds * updates are complete. 2199*1da177e4SLinus Torvalds * 2200*1da177e4SLinus Torvalds * PRE CONDITION: Already have buffer lock on iagp. Already have AG lock on 2201*1da177e4SLinus Torvalds * this AG. Must have read lock on imap inode. 2202*1da177e4SLinus Torvalds * 2203*1da177e4SLinus Torvalds * PARAMETERS: 2204*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 2205*1da177e4SLinus Torvalds * iagp - pointer to iag. 2206*1da177e4SLinus Torvalds * extno - extent number. 2207*1da177e4SLinus Torvalds * 2208*1da177e4SLinus Torvalds * RETURN VALUES: 2209*1da177e4SLinus Torvalds * 0 - success. 2210*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 2211*1da177e4SLinus Torvalds * -EIO - i/o error. 2212*1da177e4SLinus Torvalds */ 2213*1da177e4SLinus Torvalds static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) 2214*1da177e4SLinus Torvalds { 2215*1da177e4SLinus Torvalds int agno, iagno, fwd, back, freei = 0, sword, rc; 2216*1da177e4SLinus Torvalds struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL; 2217*1da177e4SLinus Torvalds struct metapage *amp, *bmp, *cmp, *dmp; 2218*1da177e4SLinus Torvalds struct inode *ipimap; 2219*1da177e4SLinus Torvalds s64 blkno, hint; 2220*1da177e4SLinus Torvalds int i, j; 2221*1da177e4SLinus Torvalds u32 mask; 2222*1da177e4SLinus Torvalds ino_t ino; 2223*1da177e4SLinus Torvalds struct dinode *dp; 2224*1da177e4SLinus Torvalds struct jfs_sb_info *sbi; 2225*1da177e4SLinus Torvalds 2226*1da177e4SLinus Torvalds /* better have free extents. 2227*1da177e4SLinus Torvalds */ 2228*1da177e4SLinus Torvalds if (!iagp->nfreeexts) { 2229*1da177e4SLinus Torvalds jfs_error(imap->im_ipimap->i_sb, "diNewExt: no free extents"); 2230*1da177e4SLinus Torvalds return -EIO; 2231*1da177e4SLinus Torvalds } 2232*1da177e4SLinus Torvalds 2233*1da177e4SLinus Torvalds /* get the inode map inode. 2234*1da177e4SLinus Torvalds */ 2235*1da177e4SLinus Torvalds ipimap = imap->im_ipimap; 2236*1da177e4SLinus Torvalds sbi = JFS_SBI(ipimap->i_sb); 2237*1da177e4SLinus Torvalds 2238*1da177e4SLinus Torvalds amp = bmp = cmp = NULL; 2239*1da177e4SLinus Torvalds 2240*1da177e4SLinus Torvalds /* get the ag and iag numbers for this iag. 2241*1da177e4SLinus Torvalds */ 2242*1da177e4SLinus Torvalds agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); 2243*1da177e4SLinus Torvalds iagno = le32_to_cpu(iagp->iagnum); 2244*1da177e4SLinus Torvalds 2245*1da177e4SLinus Torvalds /* check if this is the last free extent within the 2246*1da177e4SLinus Torvalds * iag. if so, the iag must be removed from the ag 2247*1da177e4SLinus Torvalds * free extent list, so get the iags preceeding and 2248*1da177e4SLinus Torvalds * following the iag on this list. 2249*1da177e4SLinus Torvalds */ 2250*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(1)) { 2251*1da177e4SLinus Torvalds if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) { 2252*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, fwd, &))) 2253*1da177e4SLinus Torvalds return (rc); 2254*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 2255*1da177e4SLinus Torvalds } 2256*1da177e4SLinus Torvalds 2257*1da177e4SLinus Torvalds if ((back = le32_to_cpu(iagp->extfreeback)) >= 0) { 2258*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, back, &bmp))) 2259*1da177e4SLinus Torvalds goto error_out; 2260*1da177e4SLinus Torvalds biagp = (struct iag *) bmp->data; 2261*1da177e4SLinus Torvalds } 2262*1da177e4SLinus Torvalds } else { 2263*1da177e4SLinus Torvalds /* the iag has free extents. if all extents are free 2264*1da177e4SLinus Torvalds * (as is the case for a newly allocated iag), the iag 2265*1da177e4SLinus Torvalds * must be added to the ag free extent list, so get 2266*1da177e4SLinus Torvalds * the iag at the head of the list in preparation for 2267*1da177e4SLinus Torvalds * adding this iag to this list. 2268*1da177e4SLinus Torvalds */ 2269*1da177e4SLinus Torvalds fwd = back = -1; 2270*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) { 2271*1da177e4SLinus Torvalds if ((fwd = imap->im_agctl[agno].extfree) >= 0) { 2272*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, fwd, &))) 2273*1da177e4SLinus Torvalds goto error_out; 2274*1da177e4SLinus Torvalds aiagp = (struct iag *) amp->data; 2275*1da177e4SLinus Torvalds } 2276*1da177e4SLinus Torvalds } 2277*1da177e4SLinus Torvalds } 2278*1da177e4SLinus Torvalds 2279*1da177e4SLinus Torvalds /* check if the iag has no free inodes. if so, the iag 2280*1da177e4SLinus Torvalds * will have to be added to the ag free inode list, so get 2281*1da177e4SLinus Torvalds * the iag at the head of the list in preparation for 2282*1da177e4SLinus Torvalds * adding this iag to this list. in doing this, we must 2283*1da177e4SLinus Torvalds * check if we already have the iag at the head of 2284*1da177e4SLinus Torvalds * the list in hand. 2285*1da177e4SLinus Torvalds */ 2286*1da177e4SLinus Torvalds if (iagp->nfreeinos == 0) { 2287*1da177e4SLinus Torvalds freei = imap->im_agctl[agno].inofree; 2288*1da177e4SLinus Torvalds 2289*1da177e4SLinus Torvalds if (freei >= 0) { 2290*1da177e4SLinus Torvalds if (freei == fwd) { 2291*1da177e4SLinus Torvalds ciagp = aiagp; 2292*1da177e4SLinus Torvalds } else if (freei == back) { 2293*1da177e4SLinus Torvalds ciagp = biagp; 2294*1da177e4SLinus Torvalds } else { 2295*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, freei, &cmp))) 2296*1da177e4SLinus Torvalds goto error_out; 2297*1da177e4SLinus Torvalds ciagp = (struct iag *) cmp->data; 2298*1da177e4SLinus Torvalds } 2299*1da177e4SLinus Torvalds if (ciagp == NULL) { 2300*1da177e4SLinus Torvalds jfs_error(imap->im_ipimap->i_sb, 2301*1da177e4SLinus Torvalds "diNewExt: ciagp == NULL"); 2302*1da177e4SLinus Torvalds rc = -EIO; 2303*1da177e4SLinus Torvalds goto error_out; 2304*1da177e4SLinus Torvalds } 2305*1da177e4SLinus Torvalds } 2306*1da177e4SLinus Torvalds } 2307*1da177e4SLinus Torvalds 2308*1da177e4SLinus Torvalds /* allocate disk space for the inode extent. 2309*1da177e4SLinus Torvalds */ 2310*1da177e4SLinus Torvalds if ((extno == 0) || (addressPXD(&iagp->inoext[extno - 1]) == 0)) 2311*1da177e4SLinus Torvalds hint = ((s64) agno << sbi->bmap->db_agl2size) - 1; 2312*1da177e4SLinus Torvalds else 2313*1da177e4SLinus Torvalds hint = addressPXD(&iagp->inoext[extno - 1]) + 2314*1da177e4SLinus Torvalds lengthPXD(&iagp->inoext[extno - 1]) - 1; 2315*1da177e4SLinus Torvalds 2316*1da177e4SLinus Torvalds if ((rc = dbAlloc(ipimap, hint, (s64) imap->im_nbperiext, &blkno))) 2317*1da177e4SLinus Torvalds goto error_out; 2318*1da177e4SLinus Torvalds 2319*1da177e4SLinus Torvalds /* compute the inode number of the first inode within the 2320*1da177e4SLinus Torvalds * extent. 2321*1da177e4SLinus Torvalds */ 2322*1da177e4SLinus Torvalds ino = (iagno << L2INOSPERIAG) + (extno << L2INOSPEREXT); 2323*1da177e4SLinus Torvalds 2324*1da177e4SLinus Torvalds /* initialize the inodes within the newly allocated extent a 2325*1da177e4SLinus Torvalds * page at a time. 2326*1da177e4SLinus Torvalds */ 2327*1da177e4SLinus Torvalds for (i = 0; i < imap->im_nbperiext; i += sbi->nbperpage) { 2328*1da177e4SLinus Torvalds /* get a buffer for this page of disk inodes. 2329*1da177e4SLinus Torvalds */ 2330*1da177e4SLinus Torvalds dmp = get_metapage(ipimap, blkno + i, PSIZE, 1); 2331*1da177e4SLinus Torvalds if (dmp == NULL) { 2332*1da177e4SLinus Torvalds rc = -EIO; 2333*1da177e4SLinus Torvalds goto error_out; 2334*1da177e4SLinus Torvalds } 2335*1da177e4SLinus Torvalds dp = (struct dinode *) dmp->data; 2336*1da177e4SLinus Torvalds 2337*1da177e4SLinus Torvalds /* initialize the inode number, mode, link count and 2338*1da177e4SLinus Torvalds * inode extent address. 2339*1da177e4SLinus Torvalds */ 2340*1da177e4SLinus Torvalds for (j = 0; j < INOSPERPAGE; j++, dp++, ino++) { 2341*1da177e4SLinus Torvalds dp->di_inostamp = cpu_to_le32(sbi->inostamp); 2342*1da177e4SLinus Torvalds dp->di_number = cpu_to_le32(ino); 2343*1da177e4SLinus Torvalds dp->di_fileset = cpu_to_le32(FILESYSTEM_I); 2344*1da177e4SLinus Torvalds dp->di_mode = 0; 2345*1da177e4SLinus Torvalds dp->di_nlink = 0; 2346*1da177e4SLinus Torvalds PXDaddress(&(dp->di_ixpxd), blkno); 2347*1da177e4SLinus Torvalds PXDlength(&(dp->di_ixpxd), imap->im_nbperiext); 2348*1da177e4SLinus Torvalds } 2349*1da177e4SLinus Torvalds write_metapage(dmp); 2350*1da177e4SLinus Torvalds } 2351*1da177e4SLinus Torvalds 2352*1da177e4SLinus Torvalds /* if this is the last free extent within the iag, remove the 2353*1da177e4SLinus Torvalds * iag from the ag free extent list. 2354*1da177e4SLinus Torvalds */ 2355*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(1)) { 2356*1da177e4SLinus Torvalds if (fwd >= 0) 2357*1da177e4SLinus Torvalds aiagp->extfreeback = iagp->extfreeback; 2358*1da177e4SLinus Torvalds 2359*1da177e4SLinus Torvalds if (back >= 0) 2360*1da177e4SLinus Torvalds biagp->extfreefwd = iagp->extfreefwd; 2361*1da177e4SLinus Torvalds else 2362*1da177e4SLinus Torvalds imap->im_agctl[agno].extfree = 2363*1da177e4SLinus Torvalds le32_to_cpu(iagp->extfreefwd); 2364*1da177e4SLinus Torvalds 2365*1da177e4SLinus Torvalds iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); 2366*1da177e4SLinus Torvalds } else { 2367*1da177e4SLinus Torvalds /* if the iag has all free extents (newly allocated iag), 2368*1da177e4SLinus Torvalds * add the iag to the ag free extent list. 2369*1da177e4SLinus Torvalds */ 2370*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) { 2371*1da177e4SLinus Torvalds if (fwd >= 0) 2372*1da177e4SLinus Torvalds aiagp->extfreeback = cpu_to_le32(iagno); 2373*1da177e4SLinus Torvalds 2374*1da177e4SLinus Torvalds iagp->extfreefwd = cpu_to_le32(fwd); 2375*1da177e4SLinus Torvalds iagp->extfreeback = cpu_to_le32(-1); 2376*1da177e4SLinus Torvalds imap->im_agctl[agno].extfree = iagno; 2377*1da177e4SLinus Torvalds } 2378*1da177e4SLinus Torvalds } 2379*1da177e4SLinus Torvalds 2380*1da177e4SLinus Torvalds /* if the iag has no free inodes, add the iag to the 2381*1da177e4SLinus Torvalds * ag free inode list. 2382*1da177e4SLinus Torvalds */ 2383*1da177e4SLinus Torvalds if (iagp->nfreeinos == 0) { 2384*1da177e4SLinus Torvalds if (freei >= 0) 2385*1da177e4SLinus Torvalds ciagp->inofreeback = cpu_to_le32(iagno); 2386*1da177e4SLinus Torvalds 2387*1da177e4SLinus Torvalds iagp->inofreefwd = 2388*1da177e4SLinus Torvalds cpu_to_le32(imap->im_agctl[agno].inofree); 2389*1da177e4SLinus Torvalds iagp->inofreeback = cpu_to_le32(-1); 2390*1da177e4SLinus Torvalds imap->im_agctl[agno].inofree = iagno; 2391*1da177e4SLinus Torvalds } 2392*1da177e4SLinus Torvalds 2393*1da177e4SLinus Torvalds /* initialize the extent descriptor of the extent. */ 2394*1da177e4SLinus Torvalds PXDlength(&iagp->inoext[extno], imap->im_nbperiext); 2395*1da177e4SLinus Torvalds PXDaddress(&iagp->inoext[extno], blkno); 2396*1da177e4SLinus Torvalds 2397*1da177e4SLinus Torvalds /* initialize the working and persistent map of the extent. 2398*1da177e4SLinus Torvalds * the working map will be initialized such that 2399*1da177e4SLinus Torvalds * it indicates the first inode of the extent is allocated. 2400*1da177e4SLinus Torvalds */ 2401*1da177e4SLinus Torvalds iagp->wmap[extno] = cpu_to_le32(HIGHORDER); 2402*1da177e4SLinus Torvalds iagp->pmap[extno] = 0; 2403*1da177e4SLinus Torvalds 2404*1da177e4SLinus Torvalds /* update the free inode and free extent summary maps 2405*1da177e4SLinus Torvalds * for the extent to indicate the extent has free inodes 2406*1da177e4SLinus Torvalds * and no longer represents a free extent. 2407*1da177e4SLinus Torvalds */ 2408*1da177e4SLinus Torvalds sword = extno >> L2EXTSPERSUM; 2409*1da177e4SLinus Torvalds mask = HIGHORDER >> (extno & (EXTSPERSUM - 1)); 2410*1da177e4SLinus Torvalds iagp->extsmap[sword] |= cpu_to_le32(mask); 2411*1da177e4SLinus Torvalds iagp->inosmap[sword] &= cpu_to_le32(~mask); 2412*1da177e4SLinus Torvalds 2413*1da177e4SLinus Torvalds /* update the free inode and free extent counts for the 2414*1da177e4SLinus Torvalds * iag. 2415*1da177e4SLinus Torvalds */ 2416*1da177e4SLinus Torvalds iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 2417*1da177e4SLinus Torvalds (INOSPEREXT - 1)); 2418*1da177e4SLinus Torvalds iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) - 1); 2419*1da177e4SLinus Torvalds 2420*1da177e4SLinus Torvalds /* update the free and backed inode counts for the ag. 2421*1da177e4SLinus Torvalds */ 2422*1da177e4SLinus Torvalds imap->im_agctl[agno].numfree += (INOSPEREXT - 1); 2423*1da177e4SLinus Torvalds imap->im_agctl[agno].numinos += INOSPEREXT; 2424*1da177e4SLinus Torvalds 2425*1da177e4SLinus Torvalds /* update the free and backed inode counts for the inode map. 2426*1da177e4SLinus Torvalds */ 2427*1da177e4SLinus Torvalds atomic_add(INOSPEREXT - 1, &imap->im_numfree); 2428*1da177e4SLinus Torvalds atomic_add(INOSPEREXT, &imap->im_numinos); 2429*1da177e4SLinus Torvalds 2430*1da177e4SLinus Torvalds /* write the iags. 2431*1da177e4SLinus Torvalds */ 2432*1da177e4SLinus Torvalds if (amp) 2433*1da177e4SLinus Torvalds write_metapage(amp); 2434*1da177e4SLinus Torvalds if (bmp) 2435*1da177e4SLinus Torvalds write_metapage(bmp); 2436*1da177e4SLinus Torvalds if (cmp) 2437*1da177e4SLinus Torvalds write_metapage(cmp); 2438*1da177e4SLinus Torvalds 2439*1da177e4SLinus Torvalds return (0); 2440*1da177e4SLinus Torvalds 2441*1da177e4SLinus Torvalds error_out: 2442*1da177e4SLinus Torvalds 2443*1da177e4SLinus Torvalds /* release the iags. 2444*1da177e4SLinus Torvalds */ 2445*1da177e4SLinus Torvalds if (amp) 2446*1da177e4SLinus Torvalds release_metapage(amp); 2447*1da177e4SLinus Torvalds if (bmp) 2448*1da177e4SLinus Torvalds release_metapage(bmp); 2449*1da177e4SLinus Torvalds if (cmp) 2450*1da177e4SLinus Torvalds release_metapage(cmp); 2451*1da177e4SLinus Torvalds 2452*1da177e4SLinus Torvalds return (rc); 2453*1da177e4SLinus Torvalds } 2454*1da177e4SLinus Torvalds 2455*1da177e4SLinus Torvalds 2456*1da177e4SLinus Torvalds /* 2457*1da177e4SLinus Torvalds * NAME: diNewIAG(imap,iagnop,agno) 2458*1da177e4SLinus Torvalds * 2459*1da177e4SLinus Torvalds * FUNCTION: allocate a new iag for an allocation group. 2460*1da177e4SLinus Torvalds * 2461*1da177e4SLinus Torvalds * first tries to allocate the iag from the inode map 2462*1da177e4SLinus Torvalds * iagfree list: 2463*1da177e4SLinus Torvalds * if the list has free iags, the head of the list is removed 2464*1da177e4SLinus Torvalds * and returned to satisfy the request. 2465*1da177e4SLinus Torvalds * if the inode map's iag free list is empty, the inode map 2466*1da177e4SLinus Torvalds * is extended to hold a new iag. this new iag is initialized 2467*1da177e4SLinus Torvalds * and returned to satisfy the request. 2468*1da177e4SLinus Torvalds * 2469*1da177e4SLinus Torvalds * PARAMETERS: 2470*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 2471*1da177e4SLinus Torvalds * iagnop - pointer to an iag number set with the number of the 2472*1da177e4SLinus Torvalds * newly allocated iag upon successful return. 2473*1da177e4SLinus Torvalds * agno - allocation group number. 2474*1da177e4SLinus Torvalds * bpp - Buffer pointer to be filled in with new IAG's buffer 2475*1da177e4SLinus Torvalds * 2476*1da177e4SLinus Torvalds * RETURN VALUES: 2477*1da177e4SLinus Torvalds * 0 - success. 2478*1da177e4SLinus Torvalds * -ENOSPC - insufficient disk resources. 2479*1da177e4SLinus Torvalds * -EIO - i/o error. 2480*1da177e4SLinus Torvalds * 2481*1da177e4SLinus Torvalds * serialization: 2482*1da177e4SLinus Torvalds * AG lock held on entry/exit; 2483*1da177e4SLinus Torvalds * write lock on the map is held inside; 2484*1da177e4SLinus Torvalds * read lock on the map is held on successful completion; 2485*1da177e4SLinus Torvalds * 2486*1da177e4SLinus Torvalds * note: new iag transaction: 2487*1da177e4SLinus Torvalds * . synchronously write iag; 2488*1da177e4SLinus Torvalds * . write log of xtree and inode of imap; 2489*1da177e4SLinus Torvalds * . commit; 2490*1da177e4SLinus Torvalds * . synchronous write of xtree (right to left, bottom to top); 2491*1da177e4SLinus Torvalds * . at start of logredo(): init in-memory imap with one additional iag page; 2492*1da177e4SLinus Torvalds * . at end of logredo(): re-read imap inode to determine 2493*1da177e4SLinus Torvalds * new imap size; 2494*1da177e4SLinus Torvalds */ 2495*1da177e4SLinus Torvalds static int 2496*1da177e4SLinus Torvalds diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) 2497*1da177e4SLinus Torvalds { 2498*1da177e4SLinus Torvalds int rc; 2499*1da177e4SLinus Torvalds int iagno, i, xlen; 2500*1da177e4SLinus Torvalds struct inode *ipimap; 2501*1da177e4SLinus Torvalds struct super_block *sb; 2502*1da177e4SLinus Torvalds struct jfs_sb_info *sbi; 2503*1da177e4SLinus Torvalds struct metapage *mp; 2504*1da177e4SLinus Torvalds struct iag *iagp; 2505*1da177e4SLinus Torvalds s64 xaddr = 0; 2506*1da177e4SLinus Torvalds s64 blkno; 2507*1da177e4SLinus Torvalds tid_t tid; 2508*1da177e4SLinus Torvalds #ifdef _STILL_TO_PORT 2509*1da177e4SLinus Torvalds xad_t xad; 2510*1da177e4SLinus Torvalds #endif /* _STILL_TO_PORT */ 2511*1da177e4SLinus Torvalds struct inode *iplist[1]; 2512*1da177e4SLinus Torvalds 2513*1da177e4SLinus Torvalds /* pick up pointers to the inode map and mount inodes */ 2514*1da177e4SLinus Torvalds ipimap = imap->im_ipimap; 2515*1da177e4SLinus Torvalds sb = ipimap->i_sb; 2516*1da177e4SLinus Torvalds sbi = JFS_SBI(sb); 2517*1da177e4SLinus Torvalds 2518*1da177e4SLinus Torvalds /* acquire the free iag lock */ 2519*1da177e4SLinus Torvalds IAGFREE_LOCK(imap); 2520*1da177e4SLinus Torvalds 2521*1da177e4SLinus Torvalds /* if there are any iags on the inode map free iag list, 2522*1da177e4SLinus Torvalds * allocate the iag from the head of the list. 2523*1da177e4SLinus Torvalds */ 2524*1da177e4SLinus Torvalds if (imap->im_freeiag >= 0) { 2525*1da177e4SLinus Torvalds /* pick up the iag number at the head of the list */ 2526*1da177e4SLinus Torvalds iagno = imap->im_freeiag; 2527*1da177e4SLinus Torvalds 2528*1da177e4SLinus Torvalds /* determine the logical block number of the iag */ 2529*1da177e4SLinus Torvalds blkno = IAGTOLBLK(iagno, sbi->l2nbperpage); 2530*1da177e4SLinus Torvalds } else { 2531*1da177e4SLinus Torvalds /* no free iags. the inode map will have to be extented 2532*1da177e4SLinus Torvalds * to include a new iag. 2533*1da177e4SLinus Torvalds */ 2534*1da177e4SLinus Torvalds 2535*1da177e4SLinus Torvalds /* acquire inode map lock */ 2536*1da177e4SLinus Torvalds IWRITE_LOCK(ipimap); 2537*1da177e4SLinus Torvalds 2538*1da177e4SLinus Torvalds if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) { 2539*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2540*1da177e4SLinus Torvalds IAGFREE_UNLOCK(imap); 2541*1da177e4SLinus Torvalds jfs_error(imap->im_ipimap->i_sb, 2542*1da177e4SLinus Torvalds "diNewIAG: ipimap->i_size is wrong"); 2543*1da177e4SLinus Torvalds return -EIO; 2544*1da177e4SLinus Torvalds } 2545*1da177e4SLinus Torvalds 2546*1da177e4SLinus Torvalds 2547*1da177e4SLinus Torvalds /* get the next avaliable iag number */ 2548*1da177e4SLinus Torvalds iagno = imap->im_nextiag; 2549*1da177e4SLinus Torvalds 2550*1da177e4SLinus Torvalds /* make sure that we have not exceeded the maximum inode 2551*1da177e4SLinus Torvalds * number limit. 2552*1da177e4SLinus Torvalds */ 2553*1da177e4SLinus Torvalds if (iagno > (MAXIAGS - 1)) { 2554*1da177e4SLinus Torvalds /* release the inode map lock */ 2555*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2556*1da177e4SLinus Torvalds 2557*1da177e4SLinus Torvalds rc = -ENOSPC; 2558*1da177e4SLinus Torvalds goto out; 2559*1da177e4SLinus Torvalds } 2560*1da177e4SLinus Torvalds 2561*1da177e4SLinus Torvalds /* 2562*1da177e4SLinus Torvalds * synchronously append new iag page. 2563*1da177e4SLinus Torvalds */ 2564*1da177e4SLinus Torvalds /* determine the logical address of iag page to append */ 2565*1da177e4SLinus Torvalds blkno = IAGTOLBLK(iagno, sbi->l2nbperpage); 2566*1da177e4SLinus Torvalds 2567*1da177e4SLinus Torvalds /* Allocate extent for new iag page */ 2568*1da177e4SLinus Torvalds xlen = sbi->nbperpage; 2569*1da177e4SLinus Torvalds if ((rc = dbAlloc(ipimap, 0, (s64) xlen, &xaddr))) { 2570*1da177e4SLinus Torvalds /* release the inode map lock */ 2571*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2572*1da177e4SLinus Torvalds 2573*1da177e4SLinus Torvalds goto out; 2574*1da177e4SLinus Torvalds } 2575*1da177e4SLinus Torvalds 2576*1da177e4SLinus Torvalds /* assign a buffer for the page */ 2577*1da177e4SLinus Torvalds mp = get_metapage(ipimap, xaddr, PSIZE, 1); 2578*1da177e4SLinus Torvalds if (!mp) { 2579*1da177e4SLinus Torvalds /* Free the blocks allocated for the iag since it was 2580*1da177e4SLinus Torvalds * not successfully added to the inode map 2581*1da177e4SLinus Torvalds */ 2582*1da177e4SLinus Torvalds dbFree(ipimap, xaddr, (s64) xlen); 2583*1da177e4SLinus Torvalds 2584*1da177e4SLinus Torvalds /* release the inode map lock */ 2585*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2586*1da177e4SLinus Torvalds 2587*1da177e4SLinus Torvalds rc = -EIO; 2588*1da177e4SLinus Torvalds goto out; 2589*1da177e4SLinus Torvalds } 2590*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 2591*1da177e4SLinus Torvalds 2592*1da177e4SLinus Torvalds /* init the iag */ 2593*1da177e4SLinus Torvalds memset(iagp, 0, sizeof(struct iag)); 2594*1da177e4SLinus Torvalds iagp->iagnum = cpu_to_le32(iagno); 2595*1da177e4SLinus Torvalds iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1); 2596*1da177e4SLinus Torvalds iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1); 2597*1da177e4SLinus Torvalds iagp->iagfree = cpu_to_le32(-1); 2598*1da177e4SLinus Torvalds iagp->nfreeinos = 0; 2599*1da177e4SLinus Torvalds iagp->nfreeexts = cpu_to_le32(EXTSPERIAG); 2600*1da177e4SLinus Torvalds 2601*1da177e4SLinus Torvalds /* initialize the free inode summary map (free extent 2602*1da177e4SLinus Torvalds * summary map initialization handled by bzero). 2603*1da177e4SLinus Torvalds */ 2604*1da177e4SLinus Torvalds for (i = 0; i < SMAPSZ; i++) 2605*1da177e4SLinus Torvalds iagp->inosmap[i] = cpu_to_le32(ONES); 2606*1da177e4SLinus Torvalds 2607*1da177e4SLinus Torvalds /* 2608*1da177e4SLinus Torvalds * Invalidate the page after writing and syncing it. 2609*1da177e4SLinus Torvalds * After it's initialized, we access it in a different 2610*1da177e4SLinus Torvalds * address space 2611*1da177e4SLinus Torvalds */ 2612*1da177e4SLinus Torvalds set_bit(META_discard, &mp->flag); 2613*1da177e4SLinus Torvalds flush_metapage(mp); 2614*1da177e4SLinus Torvalds 2615*1da177e4SLinus Torvalds /* 2616*1da177e4SLinus Torvalds * start tyransaction of update of the inode map 2617*1da177e4SLinus Torvalds * addressing structure pointing to the new iag page; 2618*1da177e4SLinus Torvalds */ 2619*1da177e4SLinus Torvalds tid = txBegin(sb, COMMIT_FORCE); 2620*1da177e4SLinus Torvalds down(&JFS_IP(ipimap)->commit_sem); 2621*1da177e4SLinus Torvalds 2622*1da177e4SLinus Torvalds /* update the inode map addressing structure to point to it */ 2623*1da177e4SLinus Torvalds if ((rc = 2624*1da177e4SLinus Torvalds xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { 2625*1da177e4SLinus Torvalds txEnd(tid); 2626*1da177e4SLinus Torvalds up(&JFS_IP(ipimap)->commit_sem); 2627*1da177e4SLinus Torvalds /* Free the blocks allocated for the iag since it was 2628*1da177e4SLinus Torvalds * not successfully added to the inode map 2629*1da177e4SLinus Torvalds */ 2630*1da177e4SLinus Torvalds dbFree(ipimap, xaddr, (s64) xlen); 2631*1da177e4SLinus Torvalds 2632*1da177e4SLinus Torvalds /* release the inode map lock */ 2633*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2634*1da177e4SLinus Torvalds 2635*1da177e4SLinus Torvalds goto out; 2636*1da177e4SLinus Torvalds } 2637*1da177e4SLinus Torvalds 2638*1da177e4SLinus Torvalds /* update the inode map's inode to reflect the extension */ 2639*1da177e4SLinus Torvalds ipimap->i_size += PSIZE; 2640*1da177e4SLinus Torvalds inode_add_bytes(ipimap, PSIZE); 2641*1da177e4SLinus Torvalds 2642*1da177e4SLinus Torvalds /* 2643*1da177e4SLinus Torvalds * txCommit(COMMIT_FORCE) will synchronously write address 2644*1da177e4SLinus Torvalds * index pages and inode after commit in careful update order 2645*1da177e4SLinus Torvalds * of address index pages (right to left, bottom up); 2646*1da177e4SLinus Torvalds */ 2647*1da177e4SLinus Torvalds iplist[0] = ipimap; 2648*1da177e4SLinus Torvalds rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE); 2649*1da177e4SLinus Torvalds 2650*1da177e4SLinus Torvalds txEnd(tid); 2651*1da177e4SLinus Torvalds up(&JFS_IP(ipimap)->commit_sem); 2652*1da177e4SLinus Torvalds 2653*1da177e4SLinus Torvalds duplicateIXtree(sb, blkno, xlen, &xaddr); 2654*1da177e4SLinus Torvalds 2655*1da177e4SLinus Torvalds /* update the next avaliable iag number */ 2656*1da177e4SLinus Torvalds imap->im_nextiag += 1; 2657*1da177e4SLinus Torvalds 2658*1da177e4SLinus Torvalds /* Add the iag to the iag free list so we don't lose the iag 2659*1da177e4SLinus Torvalds * if a failure happens now. 2660*1da177e4SLinus Torvalds */ 2661*1da177e4SLinus Torvalds imap->im_freeiag = iagno; 2662*1da177e4SLinus Torvalds 2663*1da177e4SLinus Torvalds /* Until we have logredo working, we want the imap inode & 2664*1da177e4SLinus Torvalds * control page to be up to date. 2665*1da177e4SLinus Torvalds */ 2666*1da177e4SLinus Torvalds diSync(ipimap); 2667*1da177e4SLinus Torvalds 2668*1da177e4SLinus Torvalds /* release the inode map lock */ 2669*1da177e4SLinus Torvalds IWRITE_UNLOCK(ipimap); 2670*1da177e4SLinus Torvalds } 2671*1da177e4SLinus Torvalds 2672*1da177e4SLinus Torvalds /* obtain read lock on map */ 2673*1da177e4SLinus Torvalds IREAD_LOCK(ipimap); 2674*1da177e4SLinus Torvalds 2675*1da177e4SLinus Torvalds /* read the iag */ 2676*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, iagno, &mp))) { 2677*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 2678*1da177e4SLinus Torvalds rc = -EIO; 2679*1da177e4SLinus Torvalds goto out; 2680*1da177e4SLinus Torvalds } 2681*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 2682*1da177e4SLinus Torvalds 2683*1da177e4SLinus Torvalds /* remove the iag from the iag free list */ 2684*1da177e4SLinus Torvalds imap->im_freeiag = le32_to_cpu(iagp->iagfree); 2685*1da177e4SLinus Torvalds iagp->iagfree = cpu_to_le32(-1); 2686*1da177e4SLinus Torvalds 2687*1da177e4SLinus Torvalds /* set the return iag number and buffer pointer */ 2688*1da177e4SLinus Torvalds *iagnop = iagno; 2689*1da177e4SLinus Torvalds *mpp = mp; 2690*1da177e4SLinus Torvalds 2691*1da177e4SLinus Torvalds out: 2692*1da177e4SLinus Torvalds /* release the iag free lock */ 2693*1da177e4SLinus Torvalds IAGFREE_UNLOCK(imap); 2694*1da177e4SLinus Torvalds 2695*1da177e4SLinus Torvalds return (rc); 2696*1da177e4SLinus Torvalds } 2697*1da177e4SLinus Torvalds 2698*1da177e4SLinus Torvalds /* 2699*1da177e4SLinus Torvalds * NAME: diIAGRead() 2700*1da177e4SLinus Torvalds * 2701*1da177e4SLinus Torvalds * FUNCTION: get the buffer for the specified iag within a fileset 2702*1da177e4SLinus Torvalds * or aggregate inode map. 2703*1da177e4SLinus Torvalds * 2704*1da177e4SLinus Torvalds * PARAMETERS: 2705*1da177e4SLinus Torvalds * imap - pointer to inode map control structure. 2706*1da177e4SLinus Torvalds * iagno - iag number. 2707*1da177e4SLinus Torvalds * bpp - point to buffer pointer to be filled in on successful 2708*1da177e4SLinus Torvalds * exit. 2709*1da177e4SLinus Torvalds * 2710*1da177e4SLinus Torvalds * SERIALIZATION: 2711*1da177e4SLinus Torvalds * must have read lock on imap inode 2712*1da177e4SLinus Torvalds * (When called by diExtendFS, the filesystem is quiesced, therefore 2713*1da177e4SLinus Torvalds * the read lock is unnecessary.) 2714*1da177e4SLinus Torvalds * 2715*1da177e4SLinus Torvalds * RETURN VALUES: 2716*1da177e4SLinus Torvalds * 0 - success. 2717*1da177e4SLinus Torvalds * -EIO - i/o error. 2718*1da177e4SLinus Torvalds */ 2719*1da177e4SLinus Torvalds static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp) 2720*1da177e4SLinus Torvalds { 2721*1da177e4SLinus Torvalds struct inode *ipimap = imap->im_ipimap; 2722*1da177e4SLinus Torvalds s64 blkno; 2723*1da177e4SLinus Torvalds 2724*1da177e4SLinus Torvalds /* compute the logical block number of the iag. */ 2725*1da177e4SLinus Torvalds blkno = IAGTOLBLK(iagno, JFS_SBI(ipimap->i_sb)->l2nbperpage); 2726*1da177e4SLinus Torvalds 2727*1da177e4SLinus Torvalds /* read the iag. */ 2728*1da177e4SLinus Torvalds *mpp = read_metapage(ipimap, blkno, PSIZE, 0); 2729*1da177e4SLinus Torvalds if (*mpp == NULL) { 2730*1da177e4SLinus Torvalds return -EIO; 2731*1da177e4SLinus Torvalds } 2732*1da177e4SLinus Torvalds 2733*1da177e4SLinus Torvalds return (0); 2734*1da177e4SLinus Torvalds } 2735*1da177e4SLinus Torvalds 2736*1da177e4SLinus Torvalds /* 2737*1da177e4SLinus Torvalds * NAME: diFindFree() 2738*1da177e4SLinus Torvalds * 2739*1da177e4SLinus Torvalds * FUNCTION: find the first free bit in a word starting at 2740*1da177e4SLinus Torvalds * the specified bit position. 2741*1da177e4SLinus Torvalds * 2742*1da177e4SLinus Torvalds * PARAMETERS: 2743*1da177e4SLinus Torvalds * word - word to be examined. 2744*1da177e4SLinus Torvalds * start - starting bit position. 2745*1da177e4SLinus Torvalds * 2746*1da177e4SLinus Torvalds * RETURN VALUES: 2747*1da177e4SLinus Torvalds * bit position of first free bit in the word or 32 if 2748*1da177e4SLinus Torvalds * no free bits were found. 2749*1da177e4SLinus Torvalds */ 2750*1da177e4SLinus Torvalds static int diFindFree(u32 word, int start) 2751*1da177e4SLinus Torvalds { 2752*1da177e4SLinus Torvalds int bitno; 2753*1da177e4SLinus Torvalds assert(start < 32); 2754*1da177e4SLinus Torvalds /* scan the word for the first free bit. */ 2755*1da177e4SLinus Torvalds for (word <<= start, bitno = start; bitno < 32; 2756*1da177e4SLinus Torvalds bitno++, word <<= 1) { 2757*1da177e4SLinus Torvalds if ((word & HIGHORDER) == 0) 2758*1da177e4SLinus Torvalds break; 2759*1da177e4SLinus Torvalds } 2760*1da177e4SLinus Torvalds return (bitno); 2761*1da177e4SLinus Torvalds } 2762*1da177e4SLinus Torvalds 2763*1da177e4SLinus Torvalds /* 2764*1da177e4SLinus Torvalds * NAME: diUpdatePMap() 2765*1da177e4SLinus Torvalds * 2766*1da177e4SLinus Torvalds * FUNCTION: Update the persistent map in an IAG for the allocation or 2767*1da177e4SLinus Torvalds * freeing of the specified inode. 2768*1da177e4SLinus Torvalds * 2769*1da177e4SLinus Torvalds * PRE CONDITIONS: Working map has already been updated for allocate. 2770*1da177e4SLinus Torvalds * 2771*1da177e4SLinus Torvalds * PARAMETERS: 2772*1da177e4SLinus Torvalds * ipimap - Incore inode map inode 2773*1da177e4SLinus Torvalds * inum - Number of inode to mark in permanent map 2774*1da177e4SLinus Torvalds * is_free - If TRUE indicates inode should be marked freed, otherwise 2775*1da177e4SLinus Torvalds * indicates inode should be marked allocated. 2776*1da177e4SLinus Torvalds * 2777*1da177e4SLinus Torvalds * RETURN VALUES: 2778*1da177e4SLinus Torvalds * 0 for success 2779*1da177e4SLinus Torvalds */ 2780*1da177e4SLinus Torvalds int 2781*1da177e4SLinus Torvalds diUpdatePMap(struct inode *ipimap, 2782*1da177e4SLinus Torvalds unsigned long inum, boolean_t is_free, struct tblock * tblk) 2783*1da177e4SLinus Torvalds { 2784*1da177e4SLinus Torvalds int rc; 2785*1da177e4SLinus Torvalds struct iag *iagp; 2786*1da177e4SLinus Torvalds struct metapage *mp; 2787*1da177e4SLinus Torvalds int iagno, ino, extno, bitno; 2788*1da177e4SLinus Torvalds struct inomap *imap; 2789*1da177e4SLinus Torvalds u32 mask; 2790*1da177e4SLinus Torvalds struct jfs_log *log; 2791*1da177e4SLinus Torvalds int lsn, difft, diffp; 2792*1da177e4SLinus Torvalds 2793*1da177e4SLinus Torvalds imap = JFS_IP(ipimap)->i_imap; 2794*1da177e4SLinus Torvalds /* get the iag number containing the inode */ 2795*1da177e4SLinus Torvalds iagno = INOTOIAG(inum); 2796*1da177e4SLinus Torvalds /* make sure that the iag is contained within the map */ 2797*1da177e4SLinus Torvalds if (iagno >= imap->im_nextiag) { 2798*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2799*1da177e4SLinus Torvalds "diUpdatePMap: the iag is outside the map"); 2800*1da177e4SLinus Torvalds return -EIO; 2801*1da177e4SLinus Torvalds } 2802*1da177e4SLinus Torvalds /* read the iag */ 2803*1da177e4SLinus Torvalds IREAD_LOCK(ipimap); 2804*1da177e4SLinus Torvalds rc = diIAGRead(imap, iagno, &mp); 2805*1da177e4SLinus Torvalds IREAD_UNLOCK(ipimap); 2806*1da177e4SLinus Torvalds if (rc) 2807*1da177e4SLinus Torvalds return (rc); 2808*1da177e4SLinus Torvalds iagp = (struct iag *) mp->data; 2809*1da177e4SLinus Torvalds /* get the inode number and extent number of the inode within 2810*1da177e4SLinus Torvalds * the iag and the inode number within the extent. 2811*1da177e4SLinus Torvalds */ 2812*1da177e4SLinus Torvalds ino = inum & (INOSPERIAG - 1); 2813*1da177e4SLinus Torvalds extno = ino >> L2INOSPEREXT; 2814*1da177e4SLinus Torvalds bitno = ino & (INOSPEREXT - 1); 2815*1da177e4SLinus Torvalds mask = HIGHORDER >> bitno; 2816*1da177e4SLinus Torvalds /* 2817*1da177e4SLinus Torvalds * mark the inode free in persistent map: 2818*1da177e4SLinus Torvalds */ 2819*1da177e4SLinus Torvalds if (is_free == TRUE) { 2820*1da177e4SLinus Torvalds /* The inode should have been allocated both in working 2821*1da177e4SLinus Torvalds * map and in persistent map; 2822*1da177e4SLinus Torvalds * the inode will be freed from working map at the release 2823*1da177e4SLinus Torvalds * of last reference release; 2824*1da177e4SLinus Torvalds */ 2825*1da177e4SLinus Torvalds if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { 2826*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2827*1da177e4SLinus Torvalds "diUpdatePMap: inode %ld not marked as " 2828*1da177e4SLinus Torvalds "allocated in wmap!", inum); 2829*1da177e4SLinus Torvalds } 2830*1da177e4SLinus Torvalds if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) { 2831*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2832*1da177e4SLinus Torvalds "diUpdatePMap: inode %ld not marked as " 2833*1da177e4SLinus Torvalds "allocated in pmap!", inum); 2834*1da177e4SLinus Torvalds } 2835*1da177e4SLinus Torvalds /* update the bitmap for the extent of the freed inode */ 2836*1da177e4SLinus Torvalds iagp->pmap[extno] &= cpu_to_le32(~mask); 2837*1da177e4SLinus Torvalds } 2838*1da177e4SLinus Torvalds /* 2839*1da177e4SLinus Torvalds * mark the inode allocated in persistent map: 2840*1da177e4SLinus Torvalds */ 2841*1da177e4SLinus Torvalds else { 2842*1da177e4SLinus Torvalds /* The inode should be already allocated in the working map 2843*1da177e4SLinus Torvalds * and should be free in persistent map; 2844*1da177e4SLinus Torvalds */ 2845*1da177e4SLinus Torvalds if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { 2846*1da177e4SLinus Torvalds release_metapage(mp); 2847*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2848*1da177e4SLinus Torvalds "diUpdatePMap: the inode is not allocated in " 2849*1da177e4SLinus Torvalds "the working map"); 2850*1da177e4SLinus Torvalds return -EIO; 2851*1da177e4SLinus Torvalds } 2852*1da177e4SLinus Torvalds if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) { 2853*1da177e4SLinus Torvalds release_metapage(mp); 2854*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2855*1da177e4SLinus Torvalds "diUpdatePMap: the inode is not free in the " 2856*1da177e4SLinus Torvalds "persistent map"); 2857*1da177e4SLinus Torvalds return -EIO; 2858*1da177e4SLinus Torvalds } 2859*1da177e4SLinus Torvalds /* update the bitmap for the extent of the allocated inode */ 2860*1da177e4SLinus Torvalds iagp->pmap[extno] |= cpu_to_le32(mask); 2861*1da177e4SLinus Torvalds } 2862*1da177e4SLinus Torvalds /* 2863*1da177e4SLinus Torvalds * update iag lsn 2864*1da177e4SLinus Torvalds */ 2865*1da177e4SLinus Torvalds lsn = tblk->lsn; 2866*1da177e4SLinus Torvalds log = JFS_SBI(tblk->sb)->log; 2867*1da177e4SLinus Torvalds if (mp->lsn != 0) { 2868*1da177e4SLinus Torvalds /* inherit older/smaller lsn */ 2869*1da177e4SLinus Torvalds logdiff(difft, lsn, log); 2870*1da177e4SLinus Torvalds logdiff(diffp, mp->lsn, log); 2871*1da177e4SLinus Torvalds if (difft < diffp) { 2872*1da177e4SLinus Torvalds mp->lsn = lsn; 2873*1da177e4SLinus Torvalds /* move mp after tblock in logsync list */ 2874*1da177e4SLinus Torvalds LOGSYNC_LOCK(log); 2875*1da177e4SLinus Torvalds list_move(&mp->synclist, &tblk->synclist); 2876*1da177e4SLinus Torvalds LOGSYNC_UNLOCK(log); 2877*1da177e4SLinus Torvalds } 2878*1da177e4SLinus Torvalds /* inherit younger/larger clsn */ 2879*1da177e4SLinus Torvalds LOGSYNC_LOCK(log); 2880*1da177e4SLinus Torvalds assert(mp->clsn); 2881*1da177e4SLinus Torvalds logdiff(difft, tblk->clsn, log); 2882*1da177e4SLinus Torvalds logdiff(diffp, mp->clsn, log); 2883*1da177e4SLinus Torvalds if (difft > diffp) 2884*1da177e4SLinus Torvalds mp->clsn = tblk->clsn; 2885*1da177e4SLinus Torvalds LOGSYNC_UNLOCK(log); 2886*1da177e4SLinus Torvalds } else { 2887*1da177e4SLinus Torvalds mp->log = log; 2888*1da177e4SLinus Torvalds mp->lsn = lsn; 2889*1da177e4SLinus Torvalds /* insert mp after tblock in logsync list */ 2890*1da177e4SLinus Torvalds LOGSYNC_LOCK(log); 2891*1da177e4SLinus Torvalds log->count++; 2892*1da177e4SLinus Torvalds list_add(&mp->synclist, &tblk->synclist); 2893*1da177e4SLinus Torvalds mp->clsn = tblk->clsn; 2894*1da177e4SLinus Torvalds LOGSYNC_UNLOCK(log); 2895*1da177e4SLinus Torvalds } 2896*1da177e4SLinus Torvalds write_metapage(mp); 2897*1da177e4SLinus Torvalds return (0); 2898*1da177e4SLinus Torvalds } 2899*1da177e4SLinus Torvalds 2900*1da177e4SLinus Torvalds /* 2901*1da177e4SLinus Torvalds * diExtendFS() 2902*1da177e4SLinus Torvalds * 2903*1da177e4SLinus Torvalds * function: update imap for extendfs(); 2904*1da177e4SLinus Torvalds * 2905*1da177e4SLinus Torvalds * note: AG size has been increased s.t. each k old contiguous AGs are 2906*1da177e4SLinus Torvalds * coalesced into a new AG; 2907*1da177e4SLinus Torvalds */ 2908*1da177e4SLinus Torvalds int diExtendFS(struct inode *ipimap, struct inode *ipbmap) 2909*1da177e4SLinus Torvalds { 2910*1da177e4SLinus Torvalds int rc, rcx = 0; 2911*1da177e4SLinus Torvalds struct inomap *imap = JFS_IP(ipimap)->i_imap; 2912*1da177e4SLinus Torvalds struct iag *iagp = NULL, *hiagp = NULL; 2913*1da177e4SLinus Torvalds struct bmap *mp = JFS_SBI(ipbmap->i_sb)->bmap; 2914*1da177e4SLinus Torvalds struct metapage *bp, *hbp; 2915*1da177e4SLinus Torvalds int i, n, head; 2916*1da177e4SLinus Torvalds int numinos, xnuminos = 0, xnumfree = 0; 2917*1da177e4SLinus Torvalds s64 agstart; 2918*1da177e4SLinus Torvalds 2919*1da177e4SLinus Torvalds jfs_info("diExtendFS: nextiag:%d numinos:%d numfree:%d", 2920*1da177e4SLinus Torvalds imap->im_nextiag, atomic_read(&imap->im_numinos), 2921*1da177e4SLinus Torvalds atomic_read(&imap->im_numfree)); 2922*1da177e4SLinus Torvalds 2923*1da177e4SLinus Torvalds /* 2924*1da177e4SLinus Torvalds * reconstruct imap 2925*1da177e4SLinus Torvalds * 2926*1da177e4SLinus Torvalds * coalesce contiguous k (newAGSize/oldAGSize) AGs; 2927*1da177e4SLinus Torvalds * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn; 2928*1da177e4SLinus Torvalds * note: new AG size = old AG size * (2**x). 2929*1da177e4SLinus Torvalds */ 2930*1da177e4SLinus Torvalds 2931*1da177e4SLinus Torvalds /* init per AG control information im_agctl[] */ 2932*1da177e4SLinus Torvalds for (i = 0; i < MAXAG; i++) { 2933*1da177e4SLinus Torvalds imap->im_agctl[i].inofree = -1; 2934*1da177e4SLinus Torvalds imap->im_agctl[i].extfree = -1; 2935*1da177e4SLinus Torvalds imap->im_agctl[i].numinos = 0; /* number of backed inodes */ 2936*1da177e4SLinus Torvalds imap->im_agctl[i].numfree = 0; /* number of free backed inodes */ 2937*1da177e4SLinus Torvalds } 2938*1da177e4SLinus Torvalds 2939*1da177e4SLinus Torvalds /* 2940*1da177e4SLinus Torvalds * process each iag page of the map. 2941*1da177e4SLinus Torvalds * 2942*1da177e4SLinus Torvalds * rebuild AG Free Inode List, AG Free Inode Extent List; 2943*1da177e4SLinus Torvalds */ 2944*1da177e4SLinus Torvalds for (i = 0; i < imap->im_nextiag; i++) { 2945*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, i, &bp))) { 2946*1da177e4SLinus Torvalds rcx = rc; 2947*1da177e4SLinus Torvalds continue; 2948*1da177e4SLinus Torvalds } 2949*1da177e4SLinus Torvalds iagp = (struct iag *) bp->data; 2950*1da177e4SLinus Torvalds if (le32_to_cpu(iagp->iagnum) != i) { 2951*1da177e4SLinus Torvalds release_metapage(bp); 2952*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 2953*1da177e4SLinus Torvalds "diExtendFs: unexpected value of iagnum"); 2954*1da177e4SLinus Torvalds return -EIO; 2955*1da177e4SLinus Torvalds } 2956*1da177e4SLinus Torvalds 2957*1da177e4SLinus Torvalds /* leave free iag in the free iag list */ 2958*1da177e4SLinus Torvalds if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) { 2959*1da177e4SLinus Torvalds release_metapage(bp); 2960*1da177e4SLinus Torvalds continue; 2961*1da177e4SLinus Torvalds } 2962*1da177e4SLinus Torvalds 2963*1da177e4SLinus Torvalds /* agstart that computes to the same ag is treated as same; */ 2964*1da177e4SLinus Torvalds agstart = le64_to_cpu(iagp->agstart); 2965*1da177e4SLinus Torvalds /* iagp->agstart = agstart & ~(mp->db_agsize - 1); */ 2966*1da177e4SLinus Torvalds n = agstart >> mp->db_agl2size; 2967*1da177e4SLinus Torvalds 2968*1da177e4SLinus Torvalds /* compute backed inodes */ 2969*1da177e4SLinus Torvalds numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts)) 2970*1da177e4SLinus Torvalds << L2INOSPEREXT; 2971*1da177e4SLinus Torvalds if (numinos > 0) { 2972*1da177e4SLinus Torvalds /* merge AG backed inodes */ 2973*1da177e4SLinus Torvalds imap->im_agctl[n].numinos += numinos; 2974*1da177e4SLinus Torvalds xnuminos += numinos; 2975*1da177e4SLinus Torvalds } 2976*1da177e4SLinus Torvalds 2977*1da177e4SLinus Torvalds /* if any backed free inodes, insert at AG free inode list */ 2978*1da177e4SLinus Torvalds if ((int) le32_to_cpu(iagp->nfreeinos) > 0) { 2979*1da177e4SLinus Torvalds if ((head = imap->im_agctl[n].inofree) == -1) { 2980*1da177e4SLinus Torvalds iagp->inofreefwd = cpu_to_le32(-1); 2981*1da177e4SLinus Torvalds iagp->inofreeback = cpu_to_le32(-1); 2982*1da177e4SLinus Torvalds } else { 2983*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, head, &hbp))) { 2984*1da177e4SLinus Torvalds rcx = rc; 2985*1da177e4SLinus Torvalds goto nextiag; 2986*1da177e4SLinus Torvalds } 2987*1da177e4SLinus Torvalds hiagp = (struct iag *) hbp->data; 2988*1da177e4SLinus Torvalds hiagp->inofreeback = iagp->iagnum; 2989*1da177e4SLinus Torvalds iagp->inofreefwd = cpu_to_le32(head); 2990*1da177e4SLinus Torvalds iagp->inofreeback = cpu_to_le32(-1); 2991*1da177e4SLinus Torvalds write_metapage(hbp); 2992*1da177e4SLinus Torvalds } 2993*1da177e4SLinus Torvalds 2994*1da177e4SLinus Torvalds imap->im_agctl[n].inofree = 2995*1da177e4SLinus Torvalds le32_to_cpu(iagp->iagnum); 2996*1da177e4SLinus Torvalds 2997*1da177e4SLinus Torvalds /* merge AG backed free inodes */ 2998*1da177e4SLinus Torvalds imap->im_agctl[n].numfree += 2999*1da177e4SLinus Torvalds le32_to_cpu(iagp->nfreeinos); 3000*1da177e4SLinus Torvalds xnumfree += le32_to_cpu(iagp->nfreeinos); 3001*1da177e4SLinus Torvalds } 3002*1da177e4SLinus Torvalds 3003*1da177e4SLinus Torvalds /* if any free extents, insert at AG free extent list */ 3004*1da177e4SLinus Torvalds if (le32_to_cpu(iagp->nfreeexts) > 0) { 3005*1da177e4SLinus Torvalds if ((head = imap->im_agctl[n].extfree) == -1) { 3006*1da177e4SLinus Torvalds iagp->extfreefwd = cpu_to_le32(-1); 3007*1da177e4SLinus Torvalds iagp->extfreeback = cpu_to_le32(-1); 3008*1da177e4SLinus Torvalds } else { 3009*1da177e4SLinus Torvalds if ((rc = diIAGRead(imap, head, &hbp))) { 3010*1da177e4SLinus Torvalds rcx = rc; 3011*1da177e4SLinus Torvalds goto nextiag; 3012*1da177e4SLinus Torvalds } 3013*1da177e4SLinus Torvalds hiagp = (struct iag *) hbp->data; 3014*1da177e4SLinus Torvalds hiagp->extfreeback = iagp->iagnum; 3015*1da177e4SLinus Torvalds iagp->extfreefwd = cpu_to_le32(head); 3016*1da177e4SLinus Torvalds iagp->extfreeback = cpu_to_le32(-1); 3017*1da177e4SLinus Torvalds write_metapage(hbp); 3018*1da177e4SLinus Torvalds } 3019*1da177e4SLinus Torvalds 3020*1da177e4SLinus Torvalds imap->im_agctl[n].extfree = 3021*1da177e4SLinus Torvalds le32_to_cpu(iagp->iagnum); 3022*1da177e4SLinus Torvalds } 3023*1da177e4SLinus Torvalds 3024*1da177e4SLinus Torvalds nextiag: 3025*1da177e4SLinus Torvalds write_metapage(bp); 3026*1da177e4SLinus Torvalds } 3027*1da177e4SLinus Torvalds 3028*1da177e4SLinus Torvalds if (xnuminos != atomic_read(&imap->im_numinos) || 3029*1da177e4SLinus Torvalds xnumfree != atomic_read(&imap->im_numfree)) { 3030*1da177e4SLinus Torvalds jfs_error(ipimap->i_sb, 3031*1da177e4SLinus Torvalds "diExtendFs: numinos or numfree incorrect"); 3032*1da177e4SLinus Torvalds return -EIO; 3033*1da177e4SLinus Torvalds } 3034*1da177e4SLinus Torvalds 3035*1da177e4SLinus Torvalds return rcx; 3036*1da177e4SLinus Torvalds } 3037*1da177e4SLinus Torvalds 3038*1da177e4SLinus Torvalds 3039*1da177e4SLinus Torvalds /* 3040*1da177e4SLinus Torvalds * duplicateIXtree() 3041*1da177e4SLinus Torvalds * 3042*1da177e4SLinus Torvalds * serialization: IWRITE_LOCK held on entry/exit 3043*1da177e4SLinus Torvalds * 3044*1da177e4SLinus Torvalds * note: shadow page with regular inode (rel.2); 3045*1da177e4SLinus Torvalds */ 3046*1da177e4SLinus Torvalds static void duplicateIXtree(struct super_block *sb, s64 blkno, 3047*1da177e4SLinus Torvalds int xlen, s64 *xaddr) 3048*1da177e4SLinus Torvalds { 3049*1da177e4SLinus Torvalds struct jfs_superblock *j_sb; 3050*1da177e4SLinus Torvalds struct buffer_head *bh; 3051*1da177e4SLinus Torvalds struct inode *ip; 3052*1da177e4SLinus Torvalds tid_t tid; 3053*1da177e4SLinus Torvalds 3054*1da177e4SLinus Torvalds /* if AIT2 ipmap2 is bad, do not try to update it */ 3055*1da177e4SLinus Torvalds if (JFS_SBI(sb)->mntflag & JFS_BAD_SAIT) /* s_flag */ 3056*1da177e4SLinus Torvalds return; 3057*1da177e4SLinus Torvalds ip = diReadSpecial(sb, FILESYSTEM_I, 1); 3058*1da177e4SLinus Torvalds if (ip == NULL) { 3059*1da177e4SLinus Torvalds JFS_SBI(sb)->mntflag |= JFS_BAD_SAIT; 3060*1da177e4SLinus Torvalds if (readSuper(sb, &bh)) 3061*1da177e4SLinus Torvalds return; 3062*1da177e4SLinus Torvalds j_sb = (struct jfs_superblock *)bh->b_data; 3063*1da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); 3064*1da177e4SLinus Torvalds 3065*1da177e4SLinus Torvalds mark_buffer_dirty(bh); 3066*1da177e4SLinus Torvalds sync_dirty_buffer(bh); 3067*1da177e4SLinus Torvalds brelse(bh); 3068*1da177e4SLinus Torvalds return; 3069*1da177e4SLinus Torvalds } 3070*1da177e4SLinus Torvalds 3071*1da177e4SLinus Torvalds /* start transaction */ 3072*1da177e4SLinus Torvalds tid = txBegin(sb, COMMIT_FORCE); 3073*1da177e4SLinus Torvalds /* update the inode map addressing structure to point to it */ 3074*1da177e4SLinus Torvalds if (xtInsert(tid, ip, 0, blkno, xlen, xaddr, 0)) { 3075*1da177e4SLinus Torvalds JFS_SBI(sb)->mntflag |= JFS_BAD_SAIT; 3076*1da177e4SLinus Torvalds txAbort(tid, 1); 3077*1da177e4SLinus Torvalds goto cleanup; 3078*1da177e4SLinus Torvalds 3079*1da177e4SLinus Torvalds } 3080*1da177e4SLinus Torvalds /* update the inode map's inode to reflect the extension */ 3081*1da177e4SLinus Torvalds ip->i_size += PSIZE; 3082*1da177e4SLinus Torvalds inode_add_bytes(ip, PSIZE); 3083*1da177e4SLinus Torvalds txCommit(tid, 1, &ip, COMMIT_FORCE); 3084*1da177e4SLinus Torvalds cleanup: 3085*1da177e4SLinus Torvalds txEnd(tid); 3086*1da177e4SLinus Torvalds diFreeSpecial(ip); 3087*1da177e4SLinus Torvalds } 3088*1da177e4SLinus Torvalds 3089*1da177e4SLinus Torvalds /* 3090*1da177e4SLinus Torvalds * NAME: copy_from_dinode() 3091*1da177e4SLinus Torvalds * 3092*1da177e4SLinus Torvalds * FUNCTION: Copies inode info from disk inode to in-memory inode 3093*1da177e4SLinus Torvalds * 3094*1da177e4SLinus Torvalds * RETURN VALUES: 3095*1da177e4SLinus Torvalds * 0 - success 3096*1da177e4SLinus Torvalds * -ENOMEM - insufficient memory 3097*1da177e4SLinus Torvalds */ 3098*1da177e4SLinus Torvalds static int copy_from_dinode(struct dinode * dip, struct inode *ip) 3099*1da177e4SLinus Torvalds { 3100*1da177e4SLinus Torvalds struct jfs_inode_info *jfs_ip = JFS_IP(ip); 3101*1da177e4SLinus Torvalds 3102*1da177e4SLinus Torvalds jfs_ip->fileset = le32_to_cpu(dip->di_fileset); 3103*1da177e4SLinus Torvalds jfs_ip->mode2 = le32_to_cpu(dip->di_mode); 3104*1da177e4SLinus Torvalds 3105*1da177e4SLinus Torvalds ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff; 3106*1da177e4SLinus Torvalds ip->i_nlink = le32_to_cpu(dip->di_nlink); 3107*1da177e4SLinus Torvalds ip->i_uid = le32_to_cpu(dip->di_uid); 3108*1da177e4SLinus Torvalds ip->i_gid = le32_to_cpu(dip->di_gid); 3109*1da177e4SLinus Torvalds ip->i_size = le64_to_cpu(dip->di_size); 3110*1da177e4SLinus Torvalds ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec); 3111*1da177e4SLinus Torvalds ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec); 3112*1da177e4SLinus Torvalds ip->i_mtime.tv_sec = le32_to_cpu(dip->di_mtime.tv_sec); 3113*1da177e4SLinus Torvalds ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec); 3114*1da177e4SLinus Torvalds ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec); 3115*1da177e4SLinus Torvalds ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec); 3116*1da177e4SLinus Torvalds ip->i_blksize = ip->i_sb->s_blocksize; 3117*1da177e4SLinus Torvalds ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks)); 3118*1da177e4SLinus Torvalds ip->i_generation = le32_to_cpu(dip->di_gen); 3119*1da177e4SLinus Torvalds 3120*1da177e4SLinus Torvalds jfs_ip->ixpxd = dip->di_ixpxd; /* in-memory pxd's are little-endian */ 3121*1da177e4SLinus Torvalds jfs_ip->acl = dip->di_acl; /* as are dxd's */ 3122*1da177e4SLinus Torvalds jfs_ip->ea = dip->di_ea; 3123*1da177e4SLinus Torvalds jfs_ip->next_index = le32_to_cpu(dip->di_next_index); 3124*1da177e4SLinus Torvalds jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec); 3125*1da177e4SLinus Torvalds jfs_ip->acltype = le32_to_cpu(dip->di_acltype); 3126*1da177e4SLinus Torvalds 3127*1da177e4SLinus Torvalds if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) { 3128*1da177e4SLinus Torvalds jfs_ip->dev = le32_to_cpu(dip->di_rdev); 3129*1da177e4SLinus Torvalds ip->i_rdev = new_decode_dev(jfs_ip->dev); 3130*1da177e4SLinus Torvalds } 3131*1da177e4SLinus Torvalds 3132*1da177e4SLinus Torvalds if (S_ISDIR(ip->i_mode)) { 3133*1da177e4SLinus Torvalds memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384); 3134*1da177e4SLinus Torvalds } else if (S_ISREG(ip->i_mode) || S_ISLNK(ip->i_mode)) { 3135*1da177e4SLinus Torvalds memcpy(&jfs_ip->i_xtroot, &dip->di_xtroot, 288); 3136*1da177e4SLinus Torvalds } else 3137*1da177e4SLinus Torvalds memcpy(&jfs_ip->i_inline_ea, &dip->di_inlineea, 128); 3138*1da177e4SLinus Torvalds 3139*1da177e4SLinus Torvalds /* Zero the in-memory-only stuff */ 3140*1da177e4SLinus Torvalds jfs_ip->cflag = 0; 3141*1da177e4SLinus Torvalds jfs_ip->btindex = 0; 3142*1da177e4SLinus Torvalds jfs_ip->btorder = 0; 3143*1da177e4SLinus Torvalds jfs_ip->bxflag = 0; 3144*1da177e4SLinus Torvalds jfs_ip->blid = 0; 3145*1da177e4SLinus Torvalds jfs_ip->atlhead = 0; 3146*1da177e4SLinus Torvalds jfs_ip->atltail = 0; 3147*1da177e4SLinus Torvalds jfs_ip->xtlid = 0; 3148*1da177e4SLinus Torvalds return (0); 3149*1da177e4SLinus Torvalds } 3150*1da177e4SLinus Torvalds 3151*1da177e4SLinus Torvalds /* 3152*1da177e4SLinus Torvalds * NAME: copy_to_dinode() 3153*1da177e4SLinus Torvalds * 3154*1da177e4SLinus Torvalds * FUNCTION: Copies inode info from in-memory inode to disk inode 3155*1da177e4SLinus Torvalds */ 3156*1da177e4SLinus Torvalds static void copy_to_dinode(struct dinode * dip, struct inode *ip) 3157*1da177e4SLinus Torvalds { 3158*1da177e4SLinus Torvalds struct jfs_inode_info *jfs_ip = JFS_IP(ip); 3159*1da177e4SLinus Torvalds 3160*1da177e4SLinus Torvalds dip->di_fileset = cpu_to_le32(jfs_ip->fileset); 3161*1da177e4SLinus Torvalds dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp); 3162*1da177e4SLinus Torvalds dip->di_number = cpu_to_le32(ip->i_ino); 3163*1da177e4SLinus Torvalds dip->di_gen = cpu_to_le32(ip->i_generation); 3164*1da177e4SLinus Torvalds dip->di_size = cpu_to_le64(ip->i_size); 3165*1da177e4SLinus Torvalds dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks)); 3166*1da177e4SLinus Torvalds dip->di_nlink = cpu_to_le32(ip->i_nlink); 3167*1da177e4SLinus Torvalds dip->di_uid = cpu_to_le32(ip->i_uid); 3168*1da177e4SLinus Torvalds dip->di_gid = cpu_to_le32(ip->i_gid); 3169*1da177e4SLinus Torvalds /* 3170*1da177e4SLinus Torvalds * mode2 is only needed for storing the higher order bits. 3171*1da177e4SLinus Torvalds * Trust i_mode for the lower order ones 3172*1da177e4SLinus Torvalds */ 3173*1da177e4SLinus Torvalds dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode); 3174*1da177e4SLinus Torvalds dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec); 3175*1da177e4SLinus Torvalds dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec); 3176*1da177e4SLinus Torvalds dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec); 3177*1da177e4SLinus Torvalds dip->di_ctime.tv_nsec = cpu_to_le32(ip->i_ctime.tv_nsec); 3178*1da177e4SLinus Torvalds dip->di_mtime.tv_sec = cpu_to_le32(ip->i_mtime.tv_sec); 3179*1da177e4SLinus Torvalds dip->di_mtime.tv_nsec = cpu_to_le32(ip->i_mtime.tv_nsec); 3180*1da177e4SLinus Torvalds dip->di_ixpxd = jfs_ip->ixpxd; /* in-memory pxd's are little-endian */ 3181*1da177e4SLinus Torvalds dip->di_acl = jfs_ip->acl; /* as are dxd's */ 3182*1da177e4SLinus Torvalds dip->di_ea = jfs_ip->ea; 3183*1da177e4SLinus Torvalds dip->di_next_index = cpu_to_le32(jfs_ip->next_index); 3184*1da177e4SLinus Torvalds dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime); 3185*1da177e4SLinus Torvalds dip->di_otime.tv_nsec = 0; 3186*1da177e4SLinus Torvalds dip->di_acltype = cpu_to_le32(jfs_ip->acltype); 3187*1da177e4SLinus Torvalds if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) 3188*1da177e4SLinus Torvalds dip->di_rdev = cpu_to_le32(jfs_ip->dev); 3189*1da177e4SLinus Torvalds } 3190*1da177e4SLinus Torvalds 3191*1da177e4SLinus Torvalds #ifdef _JFS_DEBUG_IMAP 3192*1da177e4SLinus Torvalds /* 3193*1da177e4SLinus Torvalds * DBGdiInit() 3194*1da177e4SLinus Torvalds */ 3195*1da177e4SLinus Torvalds static void *DBGdiInit(struct inomap * imap) 3196*1da177e4SLinus Torvalds { 3197*1da177e4SLinus Torvalds u32 *dimap; 3198*1da177e4SLinus Torvalds int size; 3199*1da177e4SLinus Torvalds size = 64 * 1024; 3200*1da177e4SLinus Torvalds if ((dimap = (u32 *) xmalloc(size, L2PSIZE, kernel_heap)) == NULL) 3201*1da177e4SLinus Torvalds assert(0); 3202*1da177e4SLinus Torvalds bzero((void *) dimap, size); 3203*1da177e4SLinus Torvalds imap->im_DBGdimap = dimap; 3204*1da177e4SLinus Torvalds } 3205*1da177e4SLinus Torvalds 3206*1da177e4SLinus Torvalds /* 3207*1da177e4SLinus Torvalds * DBGdiAlloc() 3208*1da177e4SLinus Torvalds */ 3209*1da177e4SLinus Torvalds static void DBGdiAlloc(struct inomap * imap, ino_t ino) 3210*1da177e4SLinus Torvalds { 3211*1da177e4SLinus Torvalds u32 *dimap = imap->im_DBGdimap; 3212*1da177e4SLinus Torvalds int w, b; 3213*1da177e4SLinus Torvalds u32 m; 3214*1da177e4SLinus Torvalds w = ino >> 5; 3215*1da177e4SLinus Torvalds b = ino & 31; 3216*1da177e4SLinus Torvalds m = 0x80000000 >> b; 3217*1da177e4SLinus Torvalds assert(w < 64 * 256); 3218*1da177e4SLinus Torvalds if (dimap[w] & m) { 3219*1da177e4SLinus Torvalds printk("DEBUG diAlloc: duplicate alloc ino:0x%x\n", ino); 3220*1da177e4SLinus Torvalds } 3221*1da177e4SLinus Torvalds dimap[w] |= m; 3222*1da177e4SLinus Torvalds } 3223*1da177e4SLinus Torvalds 3224*1da177e4SLinus Torvalds /* 3225*1da177e4SLinus Torvalds * DBGdiFree() 3226*1da177e4SLinus Torvalds */ 3227*1da177e4SLinus Torvalds static void DBGdiFree(struct inomap * imap, ino_t ino) 3228*1da177e4SLinus Torvalds { 3229*1da177e4SLinus Torvalds u32 *dimap = imap->im_DBGdimap; 3230*1da177e4SLinus Torvalds int w, b; 3231*1da177e4SLinus Torvalds u32 m; 3232*1da177e4SLinus Torvalds w = ino >> 5; 3233*1da177e4SLinus Torvalds b = ino & 31; 3234*1da177e4SLinus Torvalds m = 0x80000000 >> b; 3235*1da177e4SLinus Torvalds assert(w < 64 * 256); 3236*1da177e4SLinus Torvalds if ((dimap[w] & m) == 0) { 3237*1da177e4SLinus Torvalds printk("DEBUG diFree: duplicate free ino:0x%x\n", ino); 3238*1da177e4SLinus Torvalds } 3239*1da177e4SLinus Torvalds dimap[w] &= ~m; 3240*1da177e4SLinus Torvalds } 3241*1da177e4SLinus Torvalds 3242*1da177e4SLinus Torvalds static void dump_cp(struct inomap * ipimap, char *function, int line) 3243*1da177e4SLinus Torvalds { 3244*1da177e4SLinus Torvalds printk("\n* ********* *\nControl Page %s %d\n", function, line); 3245*1da177e4SLinus Torvalds printk("FreeIAG %d\tNextIAG %d\n", ipimap->im_freeiag, 3246*1da177e4SLinus Torvalds ipimap->im_nextiag); 3247*1da177e4SLinus Torvalds printk("NumInos %d\tNumFree %d\n", 3248*1da177e4SLinus Torvalds atomic_read(&ipimap->im_numinos), 3249*1da177e4SLinus Torvalds atomic_read(&ipimap->im_numfree)); 3250*1da177e4SLinus Torvalds printk("AG InoFree %d\tAG ExtFree %d\n", 3251*1da177e4SLinus Torvalds ipimap->im_agctl[0].inofree, ipimap->im_agctl[0].extfree); 3252*1da177e4SLinus Torvalds printk("AG NumInos %d\tAG NumFree %d\n", 3253*1da177e4SLinus Torvalds ipimap->im_agctl[0].numinos, ipimap->im_agctl[0].numfree); 3254*1da177e4SLinus Torvalds } 3255*1da177e4SLinus Torvalds 3256*1da177e4SLinus Torvalds static void dump_iag(struct iag * iag, char *function, int line) 3257*1da177e4SLinus Torvalds { 3258*1da177e4SLinus Torvalds printk("\n* ********* *\nIAG %s %d\n", function, line); 3259*1da177e4SLinus Torvalds printk("IagNum %d\tIAG Free %d\n", le32_to_cpu(iag->iagnum), 3260*1da177e4SLinus Torvalds le32_to_cpu(iag->iagfree)); 3261*1da177e4SLinus Torvalds printk("InoFreeFwd %d\tInoFreeBack %d\n", 3262*1da177e4SLinus Torvalds le32_to_cpu(iag->inofreefwd), 3263*1da177e4SLinus Torvalds le32_to_cpu(iag->inofreeback)); 3264*1da177e4SLinus Torvalds printk("ExtFreeFwd %d\tExtFreeBack %d\n", 3265*1da177e4SLinus Torvalds le32_to_cpu(iag->extfreefwd), 3266*1da177e4SLinus Torvalds le32_to_cpu(iag->extfreeback)); 3267*1da177e4SLinus Torvalds printk("NFreeInos %d\tNFreeExts %d\n", le32_to_cpu(iag->nfreeinos), 3268*1da177e4SLinus Torvalds le32_to_cpu(iag->nfreeexts)); 3269*1da177e4SLinus Torvalds } 3270*1da177e4SLinus Torvalds #endif /* _JFS_DEBUG_IMAP */ 3271