Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 252484
b: refs/heads/master
c: 33b5371
h: refs/heads/master
v: v3
  • Loading branch information
Grant Erickson authored and David Woodhouse committed May 25, 2011
1 parent a2efa94 commit 3abb8d0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 431e1ecabddcd7cbba237182ddf431771f98bb4c
refs/heads/master: 33b53716bc4b3ff3da2bc41581226424443f9d5a
49 changes: 49 additions & 0 deletions trunk/drivers/mtd/mtdcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,54 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
return ret;
}

/**
* mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
* @size: A pointer to the ideal or maximum size of the allocation. Points
* to the actual allocation size on success.
*
* This routine attempts to allocate a contiguous kernel buffer up to
* the specified size, backing off the size of the request exponentially
* until the request succeeds or until the allocation size falls below
* the system page size. This attempts to make sure it does not adversely
* impact system performance, so when allocating more than one page, we
* ask the memory allocator to avoid re-trying, swapping, writing back
* or performing I/O.
*
* Note, this function also makes sure that the allocated buffer is aligned to
* the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
*
* This is called, for example by mtd_{read,write} and jffs2_scan_medium,
* to handle smaller (i.e. degraded) buffer allocations under low- or
* fragmented-memory situations where such reduced allocations, from a
* requested ideal, are allowed.
*
* Returns a pointer to the allocated buffer on success; otherwise, NULL.
*/
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
{
gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
__GFP_NORETRY | __GFP_NO_KSWAPD;
size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
void *kbuf;

*size = min_t(size_t, *size, KMALLOC_MAX_SIZE);

while (*size > min_alloc) {
kbuf = kmalloc(*size, flags);
if (kbuf)
return kbuf;

*size >>= 1;
*size = ALIGN(*size, mtd->writesize);
}

/*
* For the last resort allocation allow 'kmalloc()' to do all sorts of
* things (write-back, dropping caches, etc) by using GFP_KERNEL.
*/
return kmalloc(*size, GFP_KERNEL);
}

EXPORT_SYMBOL_GPL(add_mtd_device);
EXPORT_SYMBOL_GPL(del_mtd_device);
EXPORT_SYMBOL_GPL(get_mtd_device);
Expand All @@ -648,6 +696,7 @@ EXPORT_SYMBOL_GPL(__put_mtd_device);
EXPORT_SYMBOL_GPL(register_mtd_user);
EXPORT_SYMBOL_GPL(unregister_mtd_user);
EXPORT_SYMBOL_GPL(default_mtd_writev);
EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);

#ifdef CONFIG_PROC_FS

Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/mtd/mtd.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
unsigned long count, loff_t from, size_t *retlen);

void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);

#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
#else
Expand Down

0 comments on commit 3abb8d0

Please sign in to comment.