===================================================================
@@ -39,6 +39,7 @@
#include <linux/miscdevice.h>
#include <linux/magic.h>
#include <linux/slab.h>
+#include <linux/pagevec.h>
#include "compat.h"
#include "ctree.h"
#include "disk-io.h"
@@ -845,6 +846,52 @@ static int btrfs_unfreeze(struct super_b
return 0;
}
+static int btrfs_metadata_incore(struct super_block *sb, loff_t *offset,
+ ssize_t *size)
+{
+ struct btrfs_root *tree_root = btrfs_sb(sb);
+ struct inode *btree_inode = tree_root->fs_info->btree_inode;
+ struct pagevec pvec;
+ loff_t index = (*offset) >> PAGE_CACHE_SHIFT;
+ int i, nr_pages;
+
+ *size = 0;
+retry:
+ pagevec_init(&pvec, 0);
+ nr_pages = pagevec_lookup(&pvec, btree_inode->i_mapping, index,
+ PAGEVEC_SIZE);
+ if (nr_pages == 0)
+ goto out;
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = pvec.pages[i];
+
+ /* Only take pages with 'referenced' bit set */
+ if (PageUptodate(page) && PageReferenced(page)) {
+ if (*size == 0) {
+ *size += PAGE_CACHE_SIZE;
+ *offset = page->index << PAGE_CACHE_SHIFT;
+ continue;
+ }
+ if (page->index !=
+ (*offset + *size) >> PAGE_CACHE_SHIFT)
+ break;
+ *size += PAGE_CACHE_SIZE;
+ } else if (*size > 0)
+ break;
+ else
+ index = page->index + 1;
+ }
+ pagevec_release(&pvec);
+
+ if (nr_pages > 0 && *size == 0)
+ goto retry;
+out:
+ if (*size > 0)
+ return 0;
+ else
+ return -ENOENT;
+}
+
static const struct super_operations btrfs_super_ops = {
.drop_inode = btrfs_drop_inode,
.evict_inode = btrfs_evict_inode,
@@ -859,6 +906,7 @@ static const struct super_operations btr
.remount_fs = btrfs_remount,
.freeze_fs = btrfs_freeze,
.unfreeze_fs = btrfs_unfreeze,
+ .metadata_incore = btrfs_metadata_incore,
};
static const struct file_operations btrfs_ctl_fops = {