aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_buf.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c67
1 files changed, 30 insertions, 37 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index fe4f66a5af14..b0f0e58866de 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -35,10 +35,13 @@
35#include <linux/freezer.h> 35#include <linux/freezer.h>
36 36
37static kmem_zone_t *xfs_buf_zone; 37static kmem_zone_t *xfs_buf_zone;
38static kmem_shaker_t xfs_buf_shake;
39STATIC int xfsbufd(void *); 38STATIC int xfsbufd(void *);
40STATIC int xfsbufd_wakeup(int, gfp_t); 39STATIC int xfsbufd_wakeup(int, gfp_t);
41STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); 40STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
41static struct shrinker xfs_buf_shake = {
42 .shrink = xfsbufd_wakeup,
43 .seeks = DEFAULT_SEEKS,
44};
42 45
43static struct workqueue_struct *xfslogd_workqueue; 46static struct workqueue_struct *xfslogd_workqueue;
44struct workqueue_struct *xfsdatad_workqueue; 47struct workqueue_struct *xfsdatad_workqueue;
@@ -314,7 +317,7 @@ xfs_buf_free(
314 317
315 ASSERT(list_empty(&bp->b_hash_list)); 318 ASSERT(list_empty(&bp->b_hash_list));
316 319
317 if (bp->b_flags & _XBF_PAGE_CACHE) { 320 if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
318 uint i; 321 uint i;
319 322
320 if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1)) 323 if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
@@ -323,18 +326,11 @@ xfs_buf_free(
323 for (i = 0; i < bp->b_page_count; i++) { 326 for (i = 0; i < bp->b_page_count; i++) {
324 struct page *page = bp->b_pages[i]; 327 struct page *page = bp->b_pages[i];
325 328
326 ASSERT(!PagePrivate(page)); 329 if (bp->b_flags & _XBF_PAGE_CACHE)
330 ASSERT(!PagePrivate(page));
327 page_cache_release(page); 331 page_cache_release(page);
328 } 332 }
329 _xfs_buf_free_pages(bp); 333 _xfs_buf_free_pages(bp);
330 } else if (bp->b_flags & _XBF_KMEM_ALLOC) {
331 /*
332 * XXX(hch): bp->b_count_desired might be incorrect (see
333 * xfs_buf_associate_memory for details), but fortunately
334 * the Linux version of kmem_free ignores the len argument..
335 */
336 kmem_free(bp->b_addr, bp->b_count_desired);
337 _xfs_buf_free_pages(bp);
338 } 334 }
339 335
340 xfs_buf_deallocate(bp); 336 xfs_buf_deallocate(bp);
@@ -764,43 +760,44 @@ xfs_buf_get_noaddr(
764 size_t len, 760 size_t len,
765 xfs_buftarg_t *target) 761 xfs_buftarg_t *target)
766{ 762{
767 size_t malloc_len = len; 763 unsigned long page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
764 int error, i;
768 xfs_buf_t *bp; 765 xfs_buf_t *bp;
769 void *data;
770 int error;
771 766
772 bp = xfs_buf_allocate(0); 767 bp = xfs_buf_allocate(0);
773 if (unlikely(bp == NULL)) 768 if (unlikely(bp == NULL))
774 goto fail; 769 goto fail;
775 _xfs_buf_initialize(bp, target, 0, len, 0); 770 _xfs_buf_initialize(bp, target, 0, len, 0);
776 771
777 try_again: 772 error = _xfs_buf_get_pages(bp, page_count, 0);
778 data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE); 773 if (error)
779 if (unlikely(data == NULL))
780 goto fail_free_buf; 774 goto fail_free_buf;
781 775
782 /* check whether alignment matches.. */ 776 for (i = 0; i < page_count; i++) {
783 if ((__psunsigned_t)data != 777 bp->b_pages[i] = alloc_page(GFP_KERNEL);
784 ((__psunsigned_t)data & ~target->bt_smask)) { 778 if (!bp->b_pages[i])
785 /* .. else double the size and try again */ 779 goto fail_free_mem;
786 kmem_free(data, malloc_len);
787 malloc_len <<= 1;
788 goto try_again;
789 } 780 }
781 bp->b_flags |= _XBF_PAGES;
790 782
791 error = xfs_buf_associate_memory(bp, data, len); 783 error = _xfs_buf_map_pages(bp, XBF_MAPPED);
792 if (error) 784 if (unlikely(error)) {
785 printk(KERN_WARNING "%s: failed to map pages\n",
786 __FUNCTION__);
793 goto fail_free_mem; 787 goto fail_free_mem;
794 bp->b_flags |= _XBF_KMEM_ALLOC; 788 }
795 789
796 xfs_buf_unlock(bp); 790 xfs_buf_unlock(bp);
797 791
798 XB_TRACE(bp, "no_daddr", data); 792 XB_TRACE(bp, "no_daddr", len);
799 return bp; 793 return bp;
794
800 fail_free_mem: 795 fail_free_mem:
801 kmem_free(data, malloc_len); 796 while (--i >= 0)
797 __free_page(bp->b_pages[i]);
798 _xfs_buf_free_pages(bp);
802 fail_free_buf: 799 fail_free_buf:
803 xfs_buf_free(bp); 800 xfs_buf_deallocate(bp);
804 fail: 801 fail:
805 return NULL; 802 return NULL;
806} 803}
@@ -1453,6 +1450,7 @@ xfs_free_buftarg(
1453 int external) 1450 int external)
1454{ 1451{
1455 xfs_flush_buftarg(btp, 1); 1452 xfs_flush_buftarg(btp, 1);
1453 xfs_blkdev_issue_flush(btp);
1456 if (external) 1454 if (external)
1457 xfs_blkdev_put(btp->bt_bdev); 1455 xfs_blkdev_put(btp->bt_bdev);
1458 xfs_free_bufhash(btp); 1456 xfs_free_bufhash(btp);
@@ -1837,14 +1835,9 @@ xfs_buf_init(void)
1837 if (!xfsdatad_workqueue) 1835 if (!xfsdatad_workqueue)
1838 goto out_destroy_xfslogd_workqueue; 1836 goto out_destroy_xfslogd_workqueue;
1839 1837
1840 xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup); 1838 register_shrinker(&xfs_buf_shake);
1841 if (!xfs_buf_shake)
1842 goto out_destroy_xfsdatad_workqueue;
1843
1844 return 0; 1839 return 0;
1845 1840
1846 out_destroy_xfsdatad_workqueue:
1847 destroy_workqueue(xfsdatad_workqueue);
1848 out_destroy_xfslogd_workqueue: 1841 out_destroy_xfslogd_workqueue:
1849 destroy_workqueue(xfslogd_workqueue); 1842 destroy_workqueue(xfslogd_workqueue);
1850 out_free_buf_zone: 1843 out_free_buf_zone:
@@ -1859,7 +1852,7 @@ xfs_buf_init(void)
1859void 1852void
1860xfs_buf_terminate(void) 1853xfs_buf_terminate(void)
1861{ 1854{
1862 kmem_shake_deregister(xfs_buf_shake); 1855 unregister_shrinker(&xfs_buf_shake);
1863 destroy_workqueue(xfsdatad_workqueue); 1856 destroy_workqueue(xfsdatad_workqueue);
1864 destroy_workqueue(xfslogd_workqueue); 1857 destroy_workqueue(xfslogd_workqueue);
1865 kmem_zone_destroy(xfs_buf_zone); 1858 kmem_zone_destroy(xfs_buf_zone);