]> git.karo-electronics.de Git - linux-beck.git/blobdiff - fs/xfs/linux-2.6/xfs_buf.c
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[linux-beck.git] / fs / xfs / linux-2.6 / xfs_buf.c
index d50df3a8101cdb50abffdd65d8c656e52262c787..6f76ba85f193e724e8bba96d5c8cc07e40fb1c50 100644 (file)
@@ -77,6 +77,27 @@ struct workqueue_struct *xfsconvertd_workqueue;
 #define xfs_buf_deallocate(bp) \
        kmem_zone_free(xfs_buf_zone, (bp));
 
+static inline int
+xfs_buf_is_vmapped(
+       struct xfs_buf  *bp)
+{
+       /*
+        * Return true if the buffer is vmapped.
+        *
+        * The XBF_MAPPED flag is set if the buffer should be mapped, but the
+        * code is clever enough to know it doesn't have to map a single page,
+        * so the check has to be both for XBF_MAPPED and bp->b_page_count > 1.
+        */
+       return (bp->b_flags & XBF_MAPPED) && bp->b_page_count > 1;
+}
+
+static inline int
+xfs_buf_vmap_len(
+       struct xfs_buf  *bp)
+{
+       return (bp->b_page_count * PAGE_SIZE) - bp->b_offset;
+}
+
 /*
  *     Page Region interfaces.
  *
@@ -315,7 +336,7 @@ xfs_buf_free(
        if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
                uint            i;
 
-               if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
+               if (xfs_buf_is_vmapped(bp))
                        free_address(bp->b_addr - bp->b_offset);
 
                for (i = 0; i < bp->b_page_count; i++) {
@@ -1236,6 +1257,9 @@ xfs_buf_bio_end_io(
 
        xfs_buf_ioerror(bp, -error);
 
+       if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+               invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
+
        do {
                struct page     *page = bvec->bv_page;
 
@@ -1345,6 +1369,10 @@ next_chunk:
 
 submit_io:
        if (likely(bio->bi_size)) {
+               if (xfs_buf_is_vmapped(bp)) {
+                       flush_kernel_vmap_range(bp->b_addr,
+                                               xfs_buf_vmap_len(bp));
+               }
                submit_bio(rw, bio);
                if (size)
                        goto next_chunk;