From patchwork Wed Jan 19 01:15:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shaohua Li X-Patchwork-Id: 487921 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0J1FWS6011441 for ; Wed, 19 Jan 2011 01:15:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753158Ab1ASBP2 (ORCPT ); Tue, 18 Jan 2011 20:15:28 -0500 Received: from mga11.intel.com ([192.55.52.93]:61372 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753139Ab1ASBP1 (ORCPT ); Tue, 18 Jan 2011 20:15:27 -0500 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 18 Jan 2011 17:15:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.60,341,1291622400"; d="scan'208";a="648464611" Received: from sli10-conroe.sh.intel.com (HELO [10.239.36.124]) ([10.239.36.124]) by fmsmga002.fm.intel.com with ESMTP; 18 Jan 2011 17:15:25 -0800 Subject: [PATCH v3 2/5] implement metadata_incore in btrfs From: Shaohua Li To: "linux-btrfs@vger.kernel.org" , "linux-fsdevel@vger.kernel.org" Cc: Chris Mason , Christoph Hellwig , Andrew Morton , Arjan van de Ven , "Yan, Zheng" , "Wu, Fengguang" , linux-api , manpages Date: Wed, 19 Jan 2011 09:15:20 +0800 Message-ID: <1295399720.1949.865.camel@sli10-conroe> Mime-Version: 1.0 X-Mailer: Evolution 2.30.3 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 19 Jan 2011 01:15:32 +0000 (UTC) Index: linux/fs/btrfs/super.c =================================================================== --- linux.orig/fs/btrfs/super.c 2011-01-18 10:15:17.000000000 +0800 +++ linux/fs/btrfs/super.c 2011-01-18 15:03:53.000000000 +0800 @@ -39,6 +39,7 @@ #include #include #include +#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -1085,6 +1086,67 @@ 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; + pgoff_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]; + + /* + * we only account referenced pages here. Say we collect + * metadata info in one boot, do metadata readahead in next + * boot and we collect metadata again. The readahead could read + * garbage data in as metadata could be changed from first run. + * If we don't filter the garbage data, the metadata info + * collected by userspace will increase every run. Btrfs + * alloc_extent_buffer will do mark_page_accessed() for pages + * which will be used soon, so we could use referenced bit to + * filter some garbage pages. + */ + if (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); + + /* + * all pages are filtered out because of referenced bit, but this + * doesn't mean we have no pages anymore in the btree_inode. so we + * retry the search and 'index' is already set to next start address + */ + 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, @@ -1099,6 +1161,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 = {