Skip to content

Commit

Permalink
NTFS: Use ntfs_malloc_nofs_nofail() in runlist.c::ntfs_runlists_merge()
Browse files Browse the repository at this point in the history
      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>
  • Loading branch information
Anton Altaparmakov committed Sep 8, 2005
1 parent 06d0e3c commit 9529d46
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 18 deletions.
3 changes: 3 additions & 0 deletions fs/ntfs/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ ToDo/Notes:
- Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
hence cannot fail.
- Use ntfs_malloc_nofs_nofail() in the two critical regions in
fs/ntfs/runlist.c::ntfs_runlists_merge(). This means we no longer
need to panic() if the allocation fails as it now cannot fail.

2.1.23 - Implement extension of resident files and make writing safe as well as
many bug fixes, cleanups, and enhancements...
Expand Down
68 changes: 50 additions & 18 deletions fs/ntfs/runlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
int size)
{
if (likely((dst != src) && (size > 0)))
memmove(base + dst, base + src, size * sizeof (*base));
memmove(base + dst, base + src, size * sizeof(*base));
}

/**
Expand Down Expand Up @@ -94,6 +94,51 @@ static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
return new_rl;
}

/**
* ntfs_rl_realloc_nofail - Reallocate memory for runlists
* @rl: original runlist
* @old_size: number of runlist elements in the original runlist @rl
* @new_size: number of runlist elements we need space for
*
* As the runlists grow, more memory will be required. To prevent the
* kernel having to allocate and reallocate large numbers of small bits of
* memory, this function returns an entire page of memory.
*
* This function guarantees that the allocation will succeed. It will sleep
* for as long as it takes to complete the allocation.
*
* It is up to the caller to serialize access to the runlist @rl.
*
* N.B. If the new allocation doesn't require a different number of pages in
* memory, the function will return the original pointer.
*
* On success, return a pointer to the newly allocated, or recycled, memory.
* On error, return -errno. The following error codes are defined:
* -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl,
int old_size, int new_size)
{
runlist_element *new_rl;

old_size = PAGE_ALIGN(old_size * sizeof(*rl));
new_size = PAGE_ALIGN(new_size * sizeof(*rl));
if (old_size == new_size)
return rl;

new_rl = ntfs_malloc_nofs_nofail(new_size);
BUG_ON(!new_rl);

if (likely(rl != NULL)) {
if (unlikely(old_size > new_size))
old_size = new_size;
memcpy(new_rl, rl, old_size);
ntfs_free(rl);
}
return new_rl;
}

/**
* ntfs_are_rl_mergeable - test if two runlists can be joined together
* @dst: original runlist
Expand Down Expand Up @@ -621,11 +666,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
if (drl[ds].lcn != LCN_RL_NOT_MAPPED) {
/* Add an unmapped runlist element. */
if (!slots) {
/* FIXME/TODO: We need to have the
* extra memory already! (AIA) */
drl = ntfs_rl_realloc(drl, ds, ds + 2);
if (!drl)
goto critical_error;
drl = ntfs_rl_realloc_nofail(drl, ds,
ds + 2);
slots = 2;
}
ds++;
Expand All @@ -640,13 +682,8 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
drl[ds].length = marker_vcn - drl[ds].vcn;
/* Finally add the ENOENT terminator. */
ds++;
if (!slots) {
/* FIXME/TODO: We need to have the extra
* memory already! (AIA) */
drl = ntfs_rl_realloc(drl, ds, ds + 1);
if (!drl)
goto critical_error;
}
if (!slots)
drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1);
drl[ds].vcn = marker_vcn;
drl[ds].lcn = LCN_ENOENT;
drl[ds].length = (s64)0;
Expand All @@ -659,11 +696,6 @@ runlist_element *ntfs_runlists_merge(runlist_element *drl,
ntfs_debug("Merged runlist:");
ntfs_debug_dump_runlist(drl);
return drl;

critical_error:
/* Critical error! We cannot afford to fail here. */
ntfs_error(NULL, "Critical error! Not enough memory.");
panic("NTFS: Cannot continue.");
}

/**
Expand Down

0 comments on commit 9529d46

Please sign in to comment.