ASSERT(list_empty(&bp->b_hash_list));
- if (bp->b_flags & _XBF_PAGE_CACHE) {
+ if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
uint i;
if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
for (i = 0; i < bp->b_page_count; i++) {
struct page *page = bp->b_pages[i];
- ASSERT(!PagePrivate(page));
+ if (bp->b_flags & _XBF_PAGE_CACHE)
+ ASSERT(!PagePrivate(page));
page_cache_release(page);
}
_xfs_buf_free_pages(bp);
- } else if (bp->b_flags & _XBF_KMEM_ALLOC) {
- /*
- * XXX(hch): bp->b_count_desired might be incorrect (see
- * xfs_buf_associate_memory for details), but fortunately
- * the Linux version of kmem_free ignores the len argument..
- */
- kmem_free(bp->b_addr, bp->b_count_desired);
- _xfs_buf_free_pages(bp);
}
xfs_buf_deallocate(bp);
size_t len,
xfs_buftarg_t *target)
{
- size_t malloc_len = len;
+ unsigned long page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
+ int error, i;
xfs_buf_t *bp;
- void *data;
- int error;
bp = xfs_buf_allocate(0);
if (unlikely(bp == NULL))
goto fail;
_xfs_buf_initialize(bp, target, 0, len, 0);
- try_again:
- data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
- if (unlikely(data == NULL))
+ error = _xfs_buf_get_pages(bp, page_count, 0);
+ if (error)
goto fail_free_buf;
- /* check whether alignment matches.. */
- if ((__psunsigned_t)data !=
- ((__psunsigned_t)data & ~target->bt_smask)) {
- /* .. else double the size and try again */
- kmem_free(data, malloc_len);
- malloc_len <<= 1;
- goto try_again;
+ for (i = 0; i < page_count; i++) {
+ bp->b_pages[i] = alloc_page(GFP_KERNEL);
+ if (!bp->b_pages[i])
+ goto fail_free_mem;
}
+ bp->b_flags |= _XBF_PAGES;
- error = xfs_buf_associate_memory(bp, data, len);
- if (error)
+ error = _xfs_buf_map_pages(bp, XBF_MAPPED);
+ if (unlikely(error)) {
+ printk(KERN_WARNING "%s: failed to map pages\n",
+ __FUNCTION__);
goto fail_free_mem;
- bp->b_flags |= _XBF_KMEM_ALLOC;
+ }
xfs_buf_unlock(bp);
- XB_TRACE(bp, "no_daddr", data);
+ XB_TRACE(bp, "no_daddr", len);
return bp;
+
fail_free_mem:
- kmem_free(data, malloc_len);
+ while (--i >= 0)
+ __free_page(bp->b_pages[i]);
fail_free_buf:
xfs_buf_free(bp);
fail:
*iclogp = (xlog_in_core_t *)
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
iclog = *iclogp;
- iclog->hic_data = (xlog_in_core_2_t *)
- kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
-
iclog->ic_prev = prev_iclog;
prev_iclog = iclog;
+
+ bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+ if (!XFS_BUF_CPSEMA(bp))
+ ASSERT(0);
+ XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
+ XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
+ XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+ iclog->ic_bp = bp;
+ iclog->hic_data = bp->b_addr;
+
log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
head = &iclog->ic_header;
INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
- bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
- XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
- XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
- XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
- iclog->ic_bp = bp;
iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
iclog->ic_state = XLOG_STATE_ACTIVE;
}
#endif
next_iclog = iclog->ic_next;
- kmem_free(iclog->hic_data, log->l_iclog_size);
kmem_free(iclog, sizeof(xlog_in_core_t));
iclog = next_iclog;
}