Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
jfs_extent.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) International Business Machines Corp., 2000-2004
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 #include <linux/fs.h>
20 #include <linux/quotaops.h>
21 #include "jfs_incore.h"
22 #include "jfs_inode.h"
23 #include "jfs_superblock.h"
24 #include "jfs_dmap.h"
25 #include "jfs_extent.h"
26 #include "jfs_debug.h"
27 
28 /*
29  * forward references
30  */
31 static int extBalloc(struct inode *, s64, s64 *, s64 *);
32 #ifdef _NOTYET
33 static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
34 #endif
35 static s64 extRoundDown(s64 nb);
36 
37 #define DPD(a) (printk("(a): %d\n",(a)))
38 #define DPC(a) (printk("(a): %c\n",(a)))
39 #define DPL1(a) \
40 { \
41  if ((a) >> 32) \
42  printk("(a): %x%08x ",(a)); \
43  else \
44  printk("(a): %x ",(a) << 32); \
45 }
46 #define DPL(a) \
47 { \
48  if ((a) >> 32) \
49  printk("(a): %x%08x\n",(a)); \
50  else \
51  printk("(a): %x\n",(a) << 32); \
52 }
53 
54 #define DPD1(a) (printk("(a): %d ",(a)))
55 #define DPX(a) (printk("(a): %08x\n",(a)))
56 #define DPX1(a) (printk("(a): %08x ",(a)))
57 #define DPS(a) (printk("%s\n",(a)))
58 #define DPE(a) (printk("\nENTERING: %s\n",(a)))
59 #define DPE1(a) (printk("\nENTERING: %s",(a)))
60 #define DPS1(a) (printk(" %s ",(a)))
61 
62 
63 /*
64  * NAME: extAlloc()
65  *
66  * FUNCTION: allocate an extent for a specified page range within a
67  * file.
68  *
69  * PARAMETERS:
70  * ip - the inode of the file.
71  * xlen - requested extent length.
72  * pno - the starting page number with the file.
73  * xp - pointer to an xad. on entry, xad describes an
74  * extent that is used as an allocation hint if the
75  * xaddr of the xad is non-zero. on successful exit,
76  * the xad describes the newly allocated extent.
77  * abnr - bool indicating whether the newly allocated extent
78  * should be marked as allocated but not recorded.
79  *
80  * RETURN VALUES:
81  * 0 - success
82  * -EIO - i/o error.
83  * -ENOSPC - insufficient disk resources.
84  */
85 int
86 extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
87 {
88  struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
89  s64 nxlen, nxaddr, xoff, hint, xaddr = 0;
90  int rc;
91  int xflag;
92 
93  /* This blocks if we are low on resources */
94  txBeginAnon(ip->i_sb);
95 
96  /* Avoid race with jfs_commit_inode() */
97  mutex_lock(&JFS_IP(ip)->commit_mutex);
98 
99  /* validate extent length */
100  if (xlen > MAXXLEN)
101  xlen = MAXXLEN;
102 
103  /* get the page's starting extent offset */
104  xoff = pno << sbi->l2nbperpage;
105 
106  /* check if an allocation hint was provided */
107  if ((hint = addressXAD(xp))) {
108  /* get the size of the extent described by the hint */
109  nxlen = lengthXAD(xp);
110 
111  /* check if the hint is for the portion of the file
112  * immediately previous to the current allocation
113  * request and if hint extent has the same abnr
114  * value as the current request. if so, we can
115  * extend the hint extent to include the current
116  * extent if we can allocate the blocks immediately
117  * following the hint extent.
118  */
119  if (offsetXAD(xp) + nxlen == xoff &&
120  abnr == ((xp->flag & XAD_NOTRECORDED) ? true : false))
121  xaddr = hint + nxlen;
122 
123  /* adjust the hint to the last block of the extent */
124  hint += (nxlen - 1);
125  }
126 
127  /* allocate the disk blocks for the extent. initially, extBalloc()
128  * will try to allocate disk blocks for the requested size (xlen).
129  * if this fails (xlen contiguous free blocks not available), it'll
130  * try to allocate a smaller number of blocks (producing a smaller
131  * extent), with this smaller number of blocks consisting of the
132  * requested number of blocks rounded down to the next smaller
133  * power of 2 number (i.e. 16 -> 8). it'll continue to round down
134  * and retry the allocation until the number of blocks to allocate
135  * is smaller than the number of blocks per page.
136  */
137  nxlen = xlen;
138  if ((rc = extBalloc(ip, hint ? hint : INOHINT(ip), &nxlen, &nxaddr))) {
139  mutex_unlock(&JFS_IP(ip)->commit_mutex);
140  return (rc);
141  }
142 
143  /* Allocate blocks to quota. */
144  rc = dquot_alloc_block(ip, nxlen);
145  if (rc) {
146  dbFree(ip, nxaddr, (s64) nxlen);
147  mutex_unlock(&JFS_IP(ip)->commit_mutex);
148  return rc;
149  }
150 
151  /* determine the value of the extent flag */
152  xflag = abnr ? XAD_NOTRECORDED : 0;
153 
154  /* if we can extend the hint extent to cover the current request,
155  * extend it. otherwise, insert a new extent to
156  * cover the current request.
157  */
158  if (xaddr && xaddr == nxaddr)
159  rc = xtExtend(0, ip, xoff, (int) nxlen, 0);
160  else
161  rc = xtInsert(0, ip, xflag, xoff, (int) nxlen, &nxaddr, 0);
162 
163  /* if the extend or insert failed,
164  * free the newly allocated blocks and return the error.
165  */
166  if (rc) {
167  dbFree(ip, nxaddr, nxlen);
168  dquot_free_block(ip, nxlen);
169  mutex_unlock(&JFS_IP(ip)->commit_mutex);
170  return (rc);
171  }
172 
173  /* set the results of the extent allocation */
174  XADaddress(xp, nxaddr);
175  XADlength(xp, nxlen);
176  XADoffset(xp, xoff);
177  xp->flag = xflag;
178 
179  mark_inode_dirty(ip);
180 
181  mutex_unlock(&JFS_IP(ip)->commit_mutex);
182  /*
183  * COMMIT_SyncList flags an anonymous tlock on page that is on
184  * sync list.
185  * We need to commit the inode to get the page written disk.
186  */
188  jfs_commit_inode(ip, 0);
189 
190  return (0);
191 }
192 
193 
194 #ifdef _NOTYET
195 /*
196  * NAME: extRealloc()
197  *
198  * FUNCTION: extend the allocation of a file extent containing a
199  * partial back last page.
200  *
201  * PARAMETERS:
202  * ip - the inode of the file.
203  * cp - cbuf for the partial backed last page.
204  * xlen - request size of the resulting extent.
205  * xp - pointer to an xad. on successful exit, the xad
206  * describes the newly allocated extent.
207  * abnr - bool indicating whether the newly allocated extent
208  * should be marked as allocated but not recorded.
209  *
210  * RETURN VALUES:
211  * 0 - success
212  * -EIO - i/o error.
213  * -ENOSPC - insufficient disk resources.
214  */
215 int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
216 {
217  struct super_block *sb = ip->i_sb;
218  s64 xaddr, xlen, nxaddr, delta, xoff;
219  s64 ntail, nextend, ninsert;
220  int rc, nbperpage = JFS_SBI(sb)->nbperpage;
221  int xflag;
222 
223  /* This blocks if we are low on resources */
224  txBeginAnon(ip->i_sb);
225 
226  mutex_lock(&JFS_IP(ip)->commit_mutex);
227  /* validate extent length */
228  if (nxlen > MAXXLEN)
229  nxlen = MAXXLEN;
230 
231  /* get the extend (partial) page's disk block address and
232  * number of blocks.
233  */
234  xaddr = addressXAD(xp);
235  xlen = lengthXAD(xp);
236  xoff = offsetXAD(xp);
237 
238  /* if the extend page is abnr and if the request is for
239  * the extent to be allocated and recorded,
240  * make the page allocated and recorded.
241  */
242  if ((xp->flag & XAD_NOTRECORDED) && !abnr) {
243  xp->flag = 0;
244  if ((rc = xtUpdate(0, ip, xp)))
245  goto exit;
246  }
247 
248  /* try to allocated the request number of blocks for the
249  * extent. dbRealloc() first tries to satisfy the request
250  * by extending the allocation in place. otherwise, it will
251  * try to allocate a new set of blocks large enough for the
252  * request. in satisfying a request, dbReAlloc() may allocate
253  * less than what was request but will always allocate enough
254  * space as to satisfy the extend page.
255  */
256  if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr)))
257  goto exit;
258 
259  /* Allocat blocks to quota. */
260  rc = dquot_alloc_block(ip, nxlen);
261  if (rc) {
262  dbFree(ip, nxaddr, (s64) nxlen);
263  mutex_unlock(&JFS_IP(ip)->commit_mutex);
264  return rc;
265  }
266 
267  delta = nxlen - xlen;
268 
269  /* check if the extend page is not abnr but the request is abnr
270  * and the allocated disk space is for more than one page. if this
271  * is the case, there is a miss match of abnr between the extend page
272  * and the one or more pages following the extend page. as a result,
273  * two extents will have to be manipulated. the first will be that
274  * of the extent of the extend page and will be manipulated thru
275  * an xtExtend() or an xtTailgate(), depending upon whether the
276  * disk allocation occurred as an inplace extension. the second
277  * extent will be manipulated (created) through an xtInsert() and
278  * will be for the pages following the extend page.
279  */
280  if (abnr && (!(xp->flag & XAD_NOTRECORDED)) && (nxlen > nbperpage)) {
281  ntail = nbperpage;
282  nextend = ntail - xlen;
283  ninsert = nxlen - nbperpage;
284 
285  xflag = XAD_NOTRECORDED;
286  } else {
287  ntail = nxlen;
288  nextend = delta;
289  ninsert = 0;
290 
291  xflag = xp->flag;
292  }
293 
294  /* if we were able to extend the disk allocation in place,
295  * extend the extent. otherwise, move the extent to a
296  * new disk location.
297  */
298  if (xaddr == nxaddr) {
299  /* extend the extent */
300  if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
301  dbFree(ip, xaddr + xlen, delta);
302  dquot_free_block(ip, nxlen);
303  goto exit;
304  }
305  } else {
306  /*
307  * move the extent to a new location:
308  *
309  * xtTailgate() accounts for relocated tail extent;
310  */
311  if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
312  dbFree(ip, nxaddr, nxlen);
313  dquot_free_block(ip, nxlen);
314  goto exit;
315  }
316  }
317 
318 
319  /* check if we need to also insert a new extent */
320  if (ninsert) {
321  /* perform the insert. if it fails, free the blocks
322  * to be inserted and make it appear that we only did
323  * the xtExtend() or xtTailgate() above.
324  */
325  xaddr = nxaddr + ntail;
326  if (xtInsert (0, ip, xflag, xoff + ntail, (int) ninsert,
327  &xaddr, 0)) {
328  dbFree(ip, xaddr, (s64) ninsert);
329  delta = nextend;
330  nxlen = ntail;
331  xflag = 0;
332  }
333  }
334 
335  /* set the return results */
336  XADaddress(xp, nxaddr);
337  XADlength(xp, nxlen);
338  XADoffset(xp, xoff);
339  xp->flag = xflag;
340 
341  mark_inode_dirty(ip);
342 exit:
343  mutex_unlock(&JFS_IP(ip)->commit_mutex);
344  return (rc);
345 }
346 #endif /* _NOTYET */
347 
348 
349 /*
350  * NAME: extHint()
351  *
352  * FUNCTION: produce an extent allocation hint for a file offset.
353  *
354  * PARAMETERS:
355  * ip - the inode of the file.
356  * offset - file offset for which the hint is needed.
357  * xp - pointer to the xad that is to be filled in with
358  * the hint.
359  *
360  * RETURN VALUES:
361  * 0 - success
362  * -EIO - i/o error.
363  */
364 int extHint(struct inode *ip, s64 offset, xad_t * xp)
365 {
366  struct super_block *sb = ip->i_sb;
367  int nbperpage = JFS_SBI(sb)->nbperpage;
368  s64 prev;
369  int rc = 0;
370  s64 xaddr;
371  int xlen;
372  int xflag;
373 
374  /* init the hint as "no hint provided" */
375  XADaddress(xp, 0);
376 
377  /* determine the starting extent offset of the page previous
378  * to the page containing the offset.
379  */
380  prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage;
381 
382  /* if the offset is in the first page of the file, no hint provided.
383  */
384  if (prev < 0)
385  goto out;
386 
387  rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0);
388 
389  if ((rc == 0) && xlen) {
390  if (xlen != nbperpage) {
391  jfs_error(ip->i_sb, "extHint: corrupt xtree");
392  rc = -EIO;
393  }
394  XADaddress(xp, xaddr);
395  XADlength(xp, xlen);
396  XADoffset(xp, prev);
397  /*
398  * only preserve the abnr flag within the xad flags
399  * of the returned hint.
400  */
401  xp->flag = xflag & XAD_NOTRECORDED;
402  } else
403  rc = 0;
404 
405 out:
406  return (rc);
407 }
408 
409 
410 /*
411  * NAME: extRecord()
412  *
413  * FUNCTION: change a page with a file from not recorded to recorded.
414  *
415  * PARAMETERS:
416  * ip - inode of the file.
417  * cp - cbuf of the file page.
418  *
419  * RETURN VALUES:
420  * 0 - success
421  * -EIO - i/o error.
422  * -ENOSPC - insufficient disk resources.
423  */
424 int extRecord(struct inode *ip, xad_t * xp)
425 {
426  int rc;
427 
428  txBeginAnon(ip->i_sb);
429 
430  mutex_lock(&JFS_IP(ip)->commit_mutex);
431 
432  /* update the extent */
433  rc = xtUpdate(0, ip, xp);
434 
435  mutex_unlock(&JFS_IP(ip)->commit_mutex);
436  return rc;
437 }
438 
439 
440 #ifdef _NOTYET
441 /*
442  * NAME: extFill()
443  *
444  * FUNCTION: allocate disk space for a file page that represents
445  * a file hole.
446  *
447  * PARAMETERS:
448  * ip - the inode of the file.
449  * cp - cbuf of the file page represent the hole.
450  *
451  * RETURN VALUES:
452  * 0 - success
453  * -EIO - i/o error.
454  * -ENOSPC - insufficient disk resources.
455  */
456 int extFill(struct inode *ip, xad_t * xp)
457 {
458  int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
459  s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
460 
461 // assert(ISSPARSE(ip));
462 
463  /* initialize the extent allocation hint */
464  XADaddress(xp, 0);
465 
466  /* allocate an extent to fill the hole */
467  if ((rc = extAlloc(ip, nbperpage, blkno, xp, false)))
468  return (rc);
469 
470  assert(lengthPXD(xp) == nbperpage);
471 
472  return (0);
473 }
474 #endif /* _NOTYET */
475 
476 
477 /*
478  * NAME: extBalloc()
479  *
480  * FUNCTION: allocate disk blocks to form an extent.
481  *
482  * initially, we will try to allocate disk blocks for the
483  * requested size (nblocks). if this fails (nblocks
484  * contiguous free blocks not available), we'll try to allocate
485  * a smaller number of blocks (producing a smaller extent), with
486  * this smaller number of blocks consisting of the requested
487  * number of blocks rounded down to the next smaller power of 2
488  * number (i.e. 16 -> 8). we'll continue to round down and
489  * retry the allocation until the number of blocks to allocate
490  * is smaller than the number of blocks per page.
491  *
492  * PARAMETERS:
493  * ip - the inode of the file.
494  * hint - disk block number to be used as an allocation hint.
495  * *nblocks - pointer to an s64 value. on entry, this value specifies
496  * the desired number of block to be allocated. on successful
497  * exit, this value is set to the number of blocks actually
498  * allocated.
499  * blkno - pointer to a block address that is filled in on successful
500  * return with the starting block number of the newly
501  * allocated block range.
502  *
503  * RETURN VALUES:
504  * 0 - success
505  * -EIO - i/o error.
506  * -ENOSPC - insufficient disk resources.
507  */
508 static int
509 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
510 {
511  struct jfs_inode_info *ji = JFS_IP(ip);
512  struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
513  s64 nb, nblks, daddr, max;
514  int rc, nbperpage = sbi->nbperpage;
515  struct bmap *bmp = sbi->bmap;
516  int ag;
517 
518  /* get the number of blocks to initially attempt to allocate.
519  * we'll first try the number of blocks requested unless this
520  * number is greater than the maximum number of contiguous free
521  * blocks in the map. in that case, we'll start off with the
522  * maximum free.
523  */
524  max = (s64) 1 << bmp->db_maxfreebud;
525  if (*nblocks >= max && *nblocks > nbperpage)
526  nb = nblks = (max > nbperpage) ? max : nbperpage;
527  else
528  nb = nblks = *nblocks;
529 
530  /* try to allocate blocks */
531  while ((rc = dbAlloc(ip, hint, nb, &daddr)) != 0) {
532  /* if something other than an out of space error,
533  * stop and return this error.
534  */
535  if (rc != -ENOSPC)
536  return (rc);
537 
538  /* decrease the allocation request size */
539  nb = min(nblks, extRoundDown(nb));
540 
541  /* give up if we cannot cover a page */
542  if (nb < nbperpage)
543  return (rc);
544  }
545 
546  *nblocks = nb;
547  *blkno = daddr;
548 
549  if (S_ISREG(ip->i_mode) && (ji->fileset == FILESYSTEM_I)) {
550  ag = BLKTOAG(daddr, sbi);
551  spin_lock_irq(&ji->ag_lock);
552  if (ji->active_ag == -1) {
553  atomic_inc(&bmp->db_active[ag]);
554  ji->active_ag = ag;
555  } else if (ji->active_ag != ag) {
556  atomic_dec(&bmp->db_active[ji->active_ag]);
557  atomic_inc(&bmp->db_active[ag]);
558  ji->active_ag = ag;
559  }
560  spin_unlock_irq(&ji->ag_lock);
561  }
562 
563  return (0);
564 }
565 
566 
567 #ifdef _NOTYET
568 /*
569  * NAME: extBrealloc()
570  *
571  * FUNCTION: attempt to extend an extent's allocation.
572  *
573  * Initially, we will try to extend the extent's allocation
574  * in place. If this fails, we'll try to move the extent
575  * to a new set of blocks. If moving the extent, we initially
576  * will try to allocate disk blocks for the requested size
577  * (newnblks). if this fails (new contiguous free blocks not
578  * available), we'll try to allocate a smaller number of
579  * blocks (producing a smaller extent), with this smaller
580  * number of blocks consisting of the requested number of
581  * blocks rounded down to the next smaller power of 2
582  * number (i.e. 16 -> 8). We'll continue to round down and
583  * retry the allocation until the number of blocks to allocate
584  * is smaller than the number of blocks per page.
585  *
586  * PARAMETERS:
587  * ip - the inode of the file.
588  * blkno - starting block number of the extents current allocation.
589  * nblks - number of blocks within the extents current allocation.
590  * newnblks - pointer to a s64 value. on entry, this value is the
591  * the new desired extent size (number of blocks). on
592  * successful exit, this value is set to the extent's actual
593  * new size (new number of blocks).
594  * newblkno - the starting block number of the extents new allocation.
595  *
596  * RETURN VALUES:
597  * 0 - success
598  * -EIO - i/o error.
599  * -ENOSPC - insufficient disk resources.
600  */
601 static int
602 extBrealloc(struct inode *ip,
603  s64 blkno, s64 nblks, s64 * newnblks, s64 * newblkno)
604 {
605  int rc;
606 
607  /* try to extend in place */
608  if ((rc = dbExtend(ip, blkno, nblks, *newnblks - nblks)) == 0) {
609  *newblkno = blkno;
610  return (0);
611  } else {
612  if (rc != -ENOSPC)
613  return (rc);
614  }
615 
616  /* in place extension not possible.
617  * try to move the extent to a new set of blocks.
618  */
619  return (extBalloc(ip, blkno, newnblks, newblkno));
620 }
621 #endif /* _NOTYET */
622 
623 
624 /*
625  * NAME: extRoundDown()
626  *
627  * FUNCTION: round down a specified number of blocks to the next
628  * smallest power of 2 number.
629  *
630  * PARAMETERS:
631  * nb - the inode of the file.
632  *
633  * RETURN VALUES:
634  * next smallest power of 2 number.
635  */
636 static s64 extRoundDown(s64 nb)
637 {
638  int i;
639  u64 m, k;
640 
641  for (i = 0, m = (u64) 1 << 63; i < 64; i++, m >>= 1) {
642  if (m & nb)
643  break;
644  }
645 
646  i = 63 - i;
647  k = (u64) 1 << i;
648  k = ((k - 1) & nb) ? k : k >> 1;
649 
650  return (k);
651 }