From patchwork Wed Jun 29 20:10:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Jansen X-Patchwork-Id: 930372 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p5TKCn4T031115 for ; Wed, 29 Jun 2011 20:12:50 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757404Ab1F2UKQ (ORCPT ); Wed, 29 Jun 2011 16:10:16 -0400 Received: from mort.rzone.de ([81.169.144.234]:26410 "EHLO mort.rzone.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757273Ab1F2UKM (ORCPT ); Wed, 29 Jun 2011 16:10:12 -0400 Received: from gargravarr.store (gargravarr.store [192.168.42.236]) by mort.rzone.de (Postfix) with ESMTP id ACE60CB9; Wed, 29 Jun 2011 22:10:10 +0200 (MEST) Received: by gargravarr.store (Postfix, from userid 32466) id A702F44E00; Wed, 29 Jun 2011 22:10:10 +0200 (CEST) From: Arne Jansen To: chris.mason@oracle.com, linux-btrfs@vger.kernel.org Subject: [PATCH v4 6/7] btrfs: test ioctl for readahead Date: Wed, 29 Jun 2011 22:10:09 +0200 Message-Id: <07e874ae6c7f9a6a6991e7771dc0f50f16be5262.1309375866.git.sensille@gmx.net> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: 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 (demeter2.kernel.org [140.211.167.43]); Wed, 29 Jun 2011 20:12:50 +0000 (UTC) This ioctl is added to trigger a readahead from user mode. It implements a readahead using the new interface and also a traditional tree walk. This way it's possible to measure the two side by side. Signed-off-by: Arne Jansen --- fs/btrfs/ioctl.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/btrfs/ioctl.h | 16 +++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a3c4751..6e77c20 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2784,6 +2784,93 @@ static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp) return btrfs_wait_for_commit(root, transid); } +static noinline long btrfs_ioctl_reada_test(struct btrfs_fs_info *fs_info, + void __user *argp) +{ + struct btrfs_key start = { 0 }; + struct btrfs_key end = { + .objectid = (u64)-1, + .type = (u8)-1, + .offset = (u64)-1 + }; + struct btrfs_ioctl_reada_args reada_args; + struct btrfs_key key; + struct btrfs_root *root = NULL; + + if (!argp) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&reada_args, + (struct btrfs_ioctl_reada_args __user *)argp, + sizeof(reada_args))) + return -EFAULT; + + start.objectid = reada_args.start_objectid; + start.type = reada_args.start_type; + start.offset = reada_args.start_offset; + end.objectid = reada_args.end_objectid; + end.type = reada_args.end_type; + end.offset = reada_args.end_offset; + + key.objectid = reada_args.tree; + key.type = BTRFS_ROOT_ITEM_KEY; + key.offset = (u64)-1; + root = btrfs_read_fs_root_no_name(fs_info, &key); + if (IS_ERR(root)) + return -ENOENT; + + if (!(reada_args.flags & BTRFS_READA_IOC_FLAGS_TRAD)) { + void *handle; + + handle = btrfs_reada_add(root, &start, &end); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + if (reada_args.flags & BTRFS_READA_IOC_FLAGS_WAIT) + btrfs_reada_wait(handle); + else + btrfs_reada_detach(handle); + } else { + struct btrfs_path *path; + struct extent_buffer *leaf; + int slot; + int ret; + + /* + * enumerate the tree the traditional way + */ + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + path->reada = 2; + + ret = btrfs_search_slot(NULL, root, &start, path, 0, 0); + if (ret < 0) + goto out; + + do { + leaf = path->nodes[0]; + slot = path->slots[0]; + btrfs_item_key_to_cpu(leaf, &key, slot); + + if (key.objectid > end.objectid) + break; + if (key.objectid == end.objectid && key.type > end.type) + break; + if (key.objectid == end.objectid && + key.type == end.type && key.offset > end.offset) + break; + } while ((ret = btrfs_next_leaf(root, path)) == 0); +out: + btrfs_free_path(path); + return ret >= 0 ? 0 : ret; + } + return 0; +} + static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) { int ret; @@ -2836,8 +2923,7 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, return ret; } -long btrfs_ioctl(struct file *file, unsigned int - cmd, unsigned long arg) +long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; void __user *argp = (void __user *)arg; @@ -2908,7 +2994,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_scrub_cancel(root, argp); case BTRFS_IOC_SCRUB_PROGRESS: return btrfs_ioctl_scrub_progress(root, argp); + case BTRFS_IOC_READA_TEST: + return btrfs_ioctl_reada_test(root->fs_info, argp); } - return -ENOTTY; } diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index ad1ea78..ee83259 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -193,6 +193,20 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_space_info spaces[0]; }; +#define BTRFS_READA_IOC_FLAGS_WAIT 1 +#define BTRFS_READA_IOC_FLAGS_TRAD 2 +struct btrfs_ioctl_reada_args { + __u64 flags; + __u64 tree; + __u64 start_objectid; + __u8 start_type; + __u64 start_offset; + __u64 end_objectid; + __u8 end_type; + __u64 end_offset; + __u64 unused[100]; +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -248,4 +262,6 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_dev_info_args) #define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ struct btrfs_ioctl_fs_info_args) +#define BTRFS_IOC_READA_TEST _IOW(BTRFS_IOCTL_MAGIC, 99, \ + struct btrfs_ioctl_reada_args) #endif