]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/nilfs2/page.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / fs / nilfs2 / page.c
index a6c3c2e817f8b0203994cfe9d11a2526173aba27..a585b35fd6bc201c9d3063005792101da769ab01 100644 (file)
@@ -491,19 +491,6 @@ unsigned nilfs_page_count_clean_buffers(struct page *page,
        }
        return nc;
 }
-void nilfs_mapping_init_once(struct address_space *mapping)
-{
-       memset(mapping, 0, sizeof(*mapping));
-       INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
-       spin_lock_init(&mapping->tree_lock);
-       INIT_LIST_HEAD(&mapping->private_list);
-       spin_lock_init(&mapping->private_lock);
-
-       spin_lock_init(&mapping->i_mmap_lock);
-       INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
-       INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
-}
 
 void nilfs_mapping_init(struct address_space *mapping,
                        struct backing_dev_info *bdi,
@@ -546,3 +533,87 @@ int __nilfs_clear_page_dirty(struct page *page)
        }
        return TestClearPageDirty(page);
 }
+
+/**
+ * nilfs_find_uncommitted_extent - find extent of uncommitted data
+ * @inode: inode
+ * @start_blk: start block offset (in)
+ * @blkoff: start offset of the found extent (out)
+ *
+ * This function searches an extent of buffers marked "delayed" which
+ * starts from a block offset equal to or larger than @start_blk.  If
+ * such an extent was found, this will store the start offset in
+ * @blkoff and return its length in blocks.  Otherwise, zero is
+ * returned.
+ */
+unsigned long nilfs_find_uncommitted_extent(struct inode *inode,
+                                           sector_t start_blk,
+                                           sector_t *blkoff)
+{
+       unsigned int i;
+       pgoff_t index;
+       unsigned int nblocks_in_page;
+       unsigned long length = 0;
+       sector_t b;
+       struct pagevec pvec;
+       struct page *page;
+
+       if (inode->i_mapping->nrpages == 0)
+               return 0;
+
+       index = start_blk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+       nblocks_in_page = 1U << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+       pagevec_init(&pvec, 0);
+
+repeat:
+       pvec.nr = find_get_pages_contig(inode->i_mapping, index, PAGEVEC_SIZE,
+                                       pvec.pages);
+       if (pvec.nr == 0)
+               return length;
+
+       if (length > 0 && pvec.pages[0]->index > index)
+               goto out;
+
+       b = pvec.pages[0]->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+       i = 0;
+       do {
+               page = pvec.pages[i];
+
+               lock_page(page);
+               if (page_has_buffers(page)) {
+                       struct buffer_head *bh, *head;
+
+                       bh = head = page_buffers(page);
+                       do {
+                               if (b < start_blk)
+                                       continue;
+                               if (buffer_delay(bh)) {
+                                       if (length == 0)
+                                               *blkoff = b;
+                                       length++;
+                               } else if (length > 0) {
+                                       goto out_locked;
+                               }
+                       } while (++b, bh = bh->b_this_page, bh != head);
+               } else {
+                       if (length > 0)
+                               goto out_locked;
+
+                       b += nblocks_in_page;
+               }
+               unlock_page(page);
+
+       } while (++i < pagevec_count(&pvec));
+
+       index = page->index + 1;
+       pagevec_release(&pvec);
+       cond_resched();
+       goto repeat;
+
+out_locked:
+       unlock_page(page);
+out:
+       pagevec_release(&pvec);
+       return length;
+}