1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) International Business Machines Corp., 2000-2004 4 */ 5 6 #include <linux/fs.h> 7 #include <linux/quotaops.h> 8 #include "jfs_incore.h" 9 #include "jfs_inode.h" 10 #include "jfs_superblock.h" 11 #include "jfs_dmap.h" 12 #include "jfs_extent.h" 13 #include "jfs_debug.h" 14 15 /* 16 * forward references 17 */ 18 static int extBalloc(struct inode *, s64, s64 *, s64 *); 19 static s64 extRoundDown(s64 nb); 20 21 #define DPD(a) (printk("(a): %d\n",(a))) 22 #define DPC(a) (printk("(a): %c\n",(a))) 23 #define DPL1(a) \ 24 { \ 25 if ((a) >> 32) \ 26 printk("(a): %x%08x ",(a)); \ 27 else \ 28 printk("(a): %x ",(a) << 32); \ 29 } 30 #define DPL(a) \ 31 { \ 32 if ((a) >> 32) \ 33 printk("(a): %x%08x\n",(a)); \ 34 else \ 35 printk("(a): %x\n",(a) << 32); \ 36 } 37 38 #define DPD1(a) (printk("(a): %d ",(a))) 39 #define DPX(a) (printk("(a): %08x\n",(a))) 40 #define DPX1(a) (printk("(a): %08x ",(a))) 41 #define DPS(a) (printk("%s\n",(a))) 42 #define DPE(a) (printk("\nENTERING: %s\n",(a))) 43 #define DPE1(a) (printk("\nENTERING: %s",(a))) 44 #define DPS1(a) (printk(" %s ",(a))) 45 46 47 /* 48 * NAME: extAlloc() 49 * 50 * FUNCTION: allocate an extent for a specified page range within a 51 * file. 52 * 53 * PARAMETERS: 54 * ip - the inode of the file. 55 * xlen - requested extent length. 56 * pno - the starting page number with the file. 57 * xp - pointer to an xad. on entry, xad describes an 58 * extent that is used as an allocation hint if the 59 * xaddr of the xad is non-zero. on successful exit, 60 * the xad describes the newly allocated extent. 61 * abnr - bool indicating whether the newly allocated extent 62 * should be marked as allocated but not recorded. 63 * 64 * RETURN VALUES: 65 * 0 - success 66 * -EIO - i/o error. 67 * -ENOSPC - insufficient disk resources. 68 */ 69 int 70 extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) 71 { 72 struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 73 s64 nxlen, nxaddr, xoff, hint, xaddr = 0; 74 int rc; 75 int xflag; 76 77 if (isReadOnly(ip)) { 78 jfs_error(ip->i_sb, "read-only filesystem\n"); 79 return -EIO; 80 } 81 82 /* This blocks if we are low on resources */ 83 txBeginAnon(ip->i_sb); 84 85 /* Avoid race with jfs_commit_inode() */ 86 mutex_lock(&JFS_IP(ip)->commit_mutex); 87 88 /* validate extent length */ 89 if (xlen > MAXXLEN) 90 xlen = MAXXLEN; 91 92 /* get the page's starting extent offset */ 93 xoff = pno << sbi->l2nbperpage; 94 95 /* check if an allocation hint was provided */ 96 if ((hint = addressXAD(xp))) { 97 /* get the size of the extent described by the hint */ 98 nxlen = lengthXAD(xp); 99 100 /* check if the hint is for the portion of the file 101 * immediately previous to the current allocation 102 * request and if hint extent has the same abnr 103 * value as the current request. if so, we can 104 * extend the hint extent to include the current 105 * extent if we can allocate the blocks immediately 106 * following the hint extent. 107 */ 108 if (offsetXAD(xp) + nxlen == xoff && 109 abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false)) 110 xaddr = hint + nxlen; 111 112 /* adjust the hint to the last block of the extent */ 113 hint += (nxlen - 1); 114 } 115 116 /* allocate the disk blocks for the extent. initially, extBalloc() 117 * will try to allocate disk blocks for the requested size (xlen). 118 * if this fails (xlen contiguous free blocks not available), it'll 119 * try to allocate a smaller number of blocks (producing a smaller 120 * extent), with this smaller number of blocks consisting of the 121 * requested number of blocks rounded down to the next smaller 122 * power of 2 number (i.e. 16 -> 8). it'll continue to round down 123 * and retry the allocation until the number of blocks to allocate 124 * is smaller than the number of blocks per page. 125 */ 126 nxlen = xlen; 127 if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) { 128 mutex_unlock(&JFS_IP(ip)->commit_mutex); 129 return (rc); 130 } 131 132 /* Allocate blocks to quota. */ 133 rc = dquot_alloc_block(ip, nxlen); 134 if (rc) { 135 dbFree(ip, nxaddr, (s64) nxlen); 136 mutex_unlock(&JFS_IP(ip)->commit_mutex); 137 return rc; 138 } 139 140 /* determine the value of the extent flag */ 141 xflag = abnr ? XAD_NOTRECORDED : 0; 142 143 /* if we can extend the hint extent to cover the current request, 144 * extend it. otherwise, insert a new extent to 145 * cover the current request. 146 */ 147 if (xaddr && xaddr == nxaddr) 148 rc = xtExtend(0, ip, xoff, (int) nxlen, 0); 149 else 150 rc = xtInsert(0, ip, xflag, xoff, (int) nxlen, &nxaddr, 0); 151 152 /* if the extend or insert failed, 153 * free the newly allocated blocks and return the error. 154 */ 155 if (rc) { 156 dbFree(ip, nxaddr, nxlen); 157 dquot_free_block(ip, nxlen); 158 mutex_unlock(&JFS_IP(ip)->commit_mutex); 159 return (rc); 160 } 161 162 /* set the results of the extent allocation */ 163 XADaddress(xp, nxaddr); 164 XADlength(xp, nxlen); 165 XADoffset(xp, xoff); 166 xp->flag = xflag; 167 168 mark_inode_dirty(ip); 169 170 mutex_unlock(&JFS_IP(ip)->commit_mutex); 171 /* 172 * COMMIT_SyncList flags an anonymous tlock on page that is on 173 * sync list. 174 * We need to commit the inode to get the page written to the disk. 175 */ 176 if (test_and_clear_cflag(COMMIT_Synclist,ip)) 177 jfs_commit_inode(ip, 0); 178 179 return (0); 180 } 181 182 /* 183 * NAME: extHint() 184 * 185 * FUNCTION: produce an extent allocation hint for a file offset. 186 * 187 * PARAMETERS: 188 * ip - the inode of the file. 189 * offset - file offset for which the hint is needed. 190 * xp - pointer to the xad that is to be filled in with 191 * the hint. 192 * 193 * RETURN VALUES: 194 * 0 - success 195 * -EIO - i/o error. 196 */ 197 int extHint(struct inode *ip, s64 offset, xad_t * xp) 198 { 199 struct super_block *sb = ip->i_sb; 200 int nbperpage = JFS_SBI(sb)->nbperpage; 201 s64 prev; 202 int rc = 0; 203 s64 xaddr; 204 int xlen; 205 int xflag; 206 207 /* init the hint as "no hint provided" */ 208 XADaddress(xp, 0); 209 210 /* determine the starting extent offset of the page previous 211 * to the page containing the offset. 212 */ 213 prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage; 214 215 /* if the offset is in the first page of the file, no hint provided. 216 */ 217 if (prev < 0) 218 goto out; 219 220 rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0); 221 222 if ((rc == 0) && xlen) { 223 if (xlen != nbperpage) { 224 jfs_error(ip->i_sb, "corrupt xtree\n"); 225 rc = -EIO; 226 } 227 XADaddress(xp, xaddr); 228 XADlength(xp, xlen); 229 XADoffset(xp, prev); 230 /* 231 * only preserve the abnr flag within the xad flags 232 * of the returned hint. 233 */ 234 xp->flag = xflag & XAD_NOTRECORDED; 235 } else 236 rc = 0; 237 238 out: 239 return (rc); 240 } 241 242 243 /* 244 * NAME: extRecord() 245 * 246 * FUNCTION: change a page with a file from not recorded to recorded. 247 * 248 * PARAMETERS: 249 * ip - inode of the file. 250 * cp - cbuf of the file page. 251 * 252 * RETURN VALUES: 253 * 0 - success 254 * -EIO - i/o error. 255 * -ENOSPC - insufficient disk resources. 256 */ 257 int extRecord(struct inode *ip, xad_t * xp) 258 { 259 int rc; 260 261 if (isReadOnly(ip)) { 262 jfs_error(ip->i_sb, "read-only filesystem\n"); 263 return -EIO; 264 } 265 266 txBeginAnon(ip->i_sb); 267 268 mutex_lock(&JFS_IP(ip)->commit_mutex); 269 270 /* update the extent */ 271 rc = xtUpdate(0, ip, xp); 272 273 mutex_unlock(&JFS_IP(ip)->commit_mutex); 274 return rc; 275 } 276 277 /* 278 * NAME: extBalloc() 279 * 280 * FUNCTION: allocate disk blocks to form an extent. 281 * 282 * initially, we will try to allocate disk blocks for the 283 * requested size (nblocks). if this fails (nblocks 284 * contiguous free blocks not available), we'll try to allocate 285 * a smaller number of blocks (producing a smaller extent), with 286 * this smaller number of blocks consisting of the requested 287 * number of blocks rounded down to the next smaller power of 2 288 * number (i.e. 16 -> 8). we'll continue to round down and 289 * retry the allocation until the number of blocks to allocate 290 * is smaller than the number of blocks per page. 291 * 292 * PARAMETERS: 293 * ip - the inode of the file. 294 * hint - disk block number to be used as an allocation hint. 295 * *nblocks - pointer to an s64 value. on entry, this value specifies 296 * the desired number of block to be allocated. on successful 297 * exit, this value is set to the number of blocks actually 298 * allocated. 299 * blkno - pointer to a block address that is filled in on successful 300 * return with the starting block number of the newly 301 * allocated block range. 302 * 303 * RETURN VALUES: 304 * 0 - success 305 * -EIO - i/o error. 306 * -ENOSPC - insufficient disk resources. 307 */ 308 static int 309 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) 310 { 311 struct jfs_inode_info *ji = JFS_IP(ip); 312 struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); 313 s64 nb, nblks, daddr, max; 314 int rc, nbperpage = sbi->nbperpage; 315 struct bmap *bmp = sbi->bmap; 316 int ag; 317 318 /* get the number of blocks to initially attempt to allocate. 319 * we'll first try the number of blocks requested unless this 320 * number is greater than the maximum number of contiguous free 321 * blocks in the map. in that case, we'll start off with the 322 * maximum free. 323 */ 324 325 /* give up if no space left */ 326 if (bmp->db_maxfreebud == -1) 327 return -ENOSPC; 328 329 max = (s64) 1 << bmp->db_maxfreebud; 330 if (*nblocks >= max && *nblocks > nbperpage) 331 nb = nblks = (max > nbperpage) ? max : nbperpage; 332 else 333 nb = nblks = *nblocks; 334 335 /* try to allocate blocks */ 336 while ((rc = dbAlloc(ip, hint, nb, &daddr)) != 0) { 337 /* if something other than an out of space error, 338 * stop and return this error. 339 */ 340 if (rc != -ENOSPC) 341 return (rc); 342 343 /* decrease the allocation request size */ 344 nb = min(nblks, extRoundDown(nb)); 345 346 /* give up if we cannot cover a page */ 347 if (nb < nbperpage) 348 return (rc); 349 } 350 351 *nblocks = nb; 352 *blkno = daddr; 353 354 if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) { 355 ag = BLKTOAG(daddr, sbi); 356 spin_lock_irq(&ji->ag_lock); 357 if (ji->active_ag == -1) { 358 atomic_inc(&bmp->db_active[ag]); 359 ji->active_ag = ag; 360 } else if (ji->active_ag != ag) { 361 atomic_dec(&bmp->db_active[ji->active_ag]); 362 atomic_inc(&bmp->db_active[ag]); 363 ji->active_ag = ag; 364 } 365 spin_unlock_irq(&ji->ag_lock); 366 } 367 368 return (0); 369 } 370 371 /* 372 * NAME: extRoundDown() 373 * 374 * FUNCTION: round down a specified number of blocks to the next 375 * smallest power of 2 number. 376 * 377 * PARAMETERS: 378 * nb - the inode of the file. 379 * 380 * RETURN VALUES: 381 * next smallest power of 2 number. 382 */ 383 static s64 extRoundDown(s64 nb) 384 { 385 int i; 386 u64 m, k; 387 388 for (i = 0, m = (u64) 1 << 63; i < 64; i++, m >>= 1) { 389 if (m & nb) 390 break; 391 } 392 393 i = 63 - i; 394 k = (u64) 1 << i; 395 k = ((k - 1) & nb) ? k : k >> 1; 396 397 return (k); 398 } 399