From patchwork Tue Dec 14 19:05:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goffredo Baroncelli X-Patchwork-Id: 410951 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 oBEJ0lYk018129 for ; Tue, 14 Dec 2010 19:00:48 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758380Ab0LNTAp (ORCPT ); Tue, 14 Dec 2010 14:00:45 -0500 Received: from smtp209.alice.it ([82.57.200.105]:43649 "EHLO smtp209.alice.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757540Ab0LNTAo (ORCPT ); Tue, 14 Dec 2010 14:00:44 -0500 Received: from venice.localnet (87.3.236.95) by smtp209.alice.it (8.5.124.08) id 4C1A27590CA6D96D; Tue, 14 Dec 2010 20:00:34 +0100 From: Goffredo Baroncelli Reply-To: kreijack@libero.it To: Chris Mason Subject: [PATCH] BTRFS_IOC_TREE_SEARCH: store and use the last key found Date: Tue, 14 Dec 2010 20:05:43 +0100 User-Agent: KMail/1.13.5 (Linux/2.6.37-rc5+; KDE/4.5.3; x86_64; ; ) Cc: Li Zefan , linux-btrfs@vger.kernel.org MIME-Version: 1.0 Message-Id: <201012142005.51289.kreijack@libero.it> 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.3 (demeter1.kernel.org [140.211.167.41]); Tue, 14 Dec 2010 19:00:48 +0000 (UTC) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f87552a..52075ed 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1134,11 +1134,11 @@ advance_key: if (key->offset < (u64)-1 && key->offset < sk->max_offset) key->offset++; else if (key->type < (u8)-1 && key->type < sk->max_type) { - key->offset = 0; + key->offset = sk->min_offset; key->type++; } else if (key->objectid < (u64)-1 && key->objectid < sk- >max_objectid) { - key->offset = 0; - key->type = 0; + key->offset = sk->min_offset; + key->type = sk->min_type; key->objectid++; } else ret = 1; @@ -1180,9 +1180,9 @@ static noinline int search_ioctl(struct inode *inode, } } - key.objectid = sk->min_objectid; - key.type = sk->min_type; - key.offset = sk->min_offset; + key.objectid = max(sk->start_objectid, sk->min_objectid); + key.type = max(sk->start_type,sk->min_type); + key.offset = max(sk->start_offset, sk->min_offset); max_key.objectid = sk->max_objectid; max_key.type = sk->max_type; @@ -1207,6 +1207,11 @@ static noinline int search_ioctl(struct inode *inode, } ret = 0; err: + /* save the key for an hypothetic next iteration */ + sk->start_objectid = key.objectid; + sk->start_type = key.type; + sk->start_offset = key.offset; + sk->nr_items = num_found; btrfs_free_path(path); return ret; @@ -1234,6 +1239,39 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, return ret; } +static noinline int btrfs_ioctl_tree_search_old(struct file *file, + void __user *argp) +{ + struct btrfs_ioctl_search_args *args; + struct inode *inode; + int ret; + + printk(KERN_WARNING "BTRFS: Pid=%d(%s) is using the buggy " + "BTRFS_IOC_TREE_SEARCH_V0 ioctl\n", + current->pid, current->comm); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + args = memdup_user(argp, sizeof(*args)); + if (IS_ERR(args)) + return PTR_ERR(args); + + inode = fdentry(file)->d_inode; + + /* for compatibility */ + args->key.start_objectid = 0; + args->key.start_type = 0; + args->key.start_offset = 0; + + ret = search_ioctl(inode, args); + if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) + ret = -EFAULT; + kfree(args); + return ret; +} + + /* * Search INODE_REFs to identify path name of 'dirid' directory * in a 'tree_id' tree. and sets path name to 'name'. @@ -2286,6 +2324,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_trans_start(file); case BTRFS_IOC_TRANS_END: return btrfs_ioctl_trans_end(file); + case BTRFS_IOC_TREE_SEARCH_V0: + return btrfs_ioctl_tree_search_old(file, argp); case BTRFS_IOC_TREE_SEARCH: return btrfs_ioctl_tree_search(file, argp); case BTRFS_IOC_INO_LOOKUP: diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index c344d12..41dfde8 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h @@ -74,12 +74,12 @@ struct btrfs_ioctl_search_key { */ __u32 nr_items; - /* align to 64 bits */ - __u32 unused; + /* starting search key fields */ + __u32 start_type; + __u64 start_objectid; + __u64 start_offset; /* some extra for later */ - __u64 unused1; - __u64 unused2; __u64 unused3; __u64 unused4; }; @@ -182,7 +182,12 @@ struct btrfs_ioctl_space_args { struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG_RANGE _IOW(BTRFS_IOCTL_MAGIC, 16, \ struct btrfs_ioctl_defrag_range_args) -#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ + +/* buggy, don't use */ + +#define BTRFS_IOC_TREE_SEARCH_V0 _IOWR(BTRFS_IOCTL_MAGIC, 17, \ + struct btrfs_ioctl_search_args) +#define BTRFS_IOC_TREE_SEARCH_V1 _IOWR(BTRFS_IOCTL_MAGIC, 25, \ struct btrfs_ioctl_search_args) #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ struct btrfs_ioctl_ino_lookup_args)