aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-09-08 11:33:12 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-09-08 11:33:12 -0400
commit9529d461d0992959026264b8fc002ac01d226708 (patch)
tree25e08068af33bf8fe05cdca944e0100642b87190
parent06d0e3cf3d527f927681773c6ffbe697ccc5db7f (diff)
NTFS: Use ntfs_malloc_nofs_nofail() in runlist.c::ntfs_runlists_merge()
in the two critical regions. This means we no longer need to panic() when the allocation fails as it now cannot fail. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
-rw-r--r--fs/ntfs/ChangeLog3
-rw-r--r--fs/ntfs/runlist.c68
2 files changed, 53 insertions, 18 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index c3bf17be0e19..c5bbedff5ae5 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -40,6 +40,9 @@ ToDo/Notes:
40 - Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to 40 - Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
41 ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and 41 ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
42 hence cannot fail. 42 hence cannot fail.
43 - Use ntfs_malloc_nofs_nofail() in the two critical regions in
44 fs/ntfs/runlist.c::ntfs_runlists_merge(). This means we no longer
45 need to panic() if the allocation fails as it now cannot fail.
43 46
442.1.23 - Implement extension of resident files and make writing safe as well as 472.1.23 - Implement extension of resident files and make writing safe as well as
45 many bug fixes, cleanups, and enhancements... 48 many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index 758855b0414e..3bb4a57d1fa9 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -35,7 +35,7 @@ static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
35 int size) 35 int size)
36{ 36{
37 if (likely((dst != src) && (size > 0))) 37 if (likely((dst != src) && (size > 0)))
38 memmove(base + dst, base + src, size * sizeof (*base)); 38 memmove(base + dst, base + src, size * sizeof(*base));
39} 39}
40 40
41/** 41/**
@@ -95,6 +95,51 @@ static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
95} 95}
96 96
97/** 97/**
98 * ntfs_rl_realloc_nofail - Reallocate memory for runlists
99 * @rl: original runlist
100 * @old_size: number of runlist elements in the original runlist @rl
101 * @new_size: number of runlist elements we need space for
102 *
103 * As the runlists grow, more memory will be required. To prevent the
104 * kernel having to allocate and reallocate large numbers of small bits of
105 * memory, this function returns an entire page of memory.
106 *
107 * This function guarantees that the allocation will succeed. It will sleep
108 * for as long as it takes to complete the allocation.
109 *
110 * It is up to the caller to serialize access to the runlist @rl.
111 *
112 * N.B. If the new allocation doesn't require a different number of pages in
113 * memory, the function will return the original pointer.
114 *
115 * On success, return a pointer to the newly allocated, or recycled, memory.
116 * On error, return -errno. The following error codes are defined:
117 * -ENOMEM - Not enough memory to allocate runlist array.
118 * -EINVAL - Invalid parameters were passed in.
119 */
120static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
121 int old_size, int new_size)
122{
123 runlist_element *new_rl;
124
125 old_size = PAGE_ALIGN(old_size * sizeof(*rl));
126 new_size = PAGE_ALIGN(new_size * sizeof(*rl));
127 if (old_size == new_size)
128 return rl;
129
130 new_rl = ntfs_malloc_nofs_nofail(new_size);
131 BUG_ON(!new_rl);
132
133 if (likely(rl != NULL)) {
134 if (unlikely(old_size > new_size))
135 old_size = new_size;
136 memcpy(new_rl, rl, old_size);
137 ntfs_free(rl);
138 }
139 return new_rl;
140}
141
142/**
98 * ntfs_are_rl_mergeable - test if two runlists can be joined together 143 * ntfs_are_rl_mergeable - test if two runlists can be joined together
99 * @dst: original runlist 144 * @dst: original runlist
100 * @src: new runlist to test for mergeability with @dst 145 * @src: new runlist to test for mergeability with @dst
@@ -621,11 +666,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
621 if (drl[ds].lcn != LCN_RL_NOT_MAPPED) { 666 if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
622 /* Add an unmapped runlist element. */ 667 /* Add an unmapped runlist element. */
623 if (!slots) { 668 if (!slots) {
624 /* FIXME/TODO: We need to have the 669 drl = ntfs_rl_realloc_nofail(drl, ds,
625 * extra memory already! (AIA) */ 670 ds + 2);
626 drl = ntfs_rl_realloc(drl, ds, ds + 2);
627 if (!drl)
628 goto critical_error;
629 slots = 2; 671 slots = 2;
630 } 672 }
631 ds++; 673 ds++;
@@ -640,13 +682,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
640 drl[ds].length = marker_vcn - drl[ds].vcn; 682 drl[ds].length = marker_vcn - drl[ds].vcn;
641 /* Finally add the ENOENT terminator. */ 683 /* Finally add the ENOENT terminator. */
642 ds++; 684 ds++;
643 if (!slots) { 685 if (!slots)
644 /* FIXME/TODO: We need to have the extra 686 drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
645 * memory already! (AIA) */
646 drl = ntfs_rl_realloc(drl, ds, ds + 1);
647 if (!drl)
648 goto critical_error;
649 }
650 drl[ds].vcn = marker_vcn; 687 drl[ds].vcn = marker_vcn;
651 drl[ds].lcn = LCN_ENOENT; 688 drl[ds].lcn = LCN_ENOENT;
652 drl[ds].length = (s64)0; 689 drl[ds].length = (s64)0;
@@ -659,11 +696,6 @@ finished:
659 ntfs_debug("Merged runlist:"); 696 ntfs_debug("Merged runlist:");
660 ntfs_debug_dump_runlist(drl); 697 ntfs_debug_dump_runlist(drl);
661 return drl; 698 return drl;
662
663critical_error:
664 /* Critical error! We cannot afford to fail here. */
665 ntfs_error(NULL, "Critical error! Not enough memory.");
666 panic("NTFS: Cannot continue.");
667} 699}
668 700
669/** 701/**