From patchwork Sat Nov 16 17:09:03 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goffredo Baroncelli X-Patchwork-Id: 3192921 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1FE659F3AE for ; Sat, 16 Nov 2013 17:09:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EA2912082C for ; Sat, 16 Nov 2013 17:09:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E90AB20233 for ; Sat, 16 Nov 2013 17:09:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752166Ab3KPRJY (ORCPT ); Sat, 16 Nov 2013 12:09:24 -0500 Received: from mail-wg0-f51.google.com ([74.125.82.51]:49369 "EHLO mail-wg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751348Ab3KPRJP (ORCPT ); Sat, 16 Nov 2013 12:09:15 -0500 Received: by mail-wg0-f51.google.com with SMTP id m15so4620511wgh.6 for ; Sat, 16 Nov 2013 09:09:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=A2YEZBp3hCk0ttdrA7hQkrwY6HztVqTy28o+YbdygA0=; b=mFcsLqyjiistj6bsTDYSTLaw4WJn0DlYOnagphqAS4D0shbIc/OaSysJqvTlqMaMcu MwUakNv6dYB7srHwdWMJw49lLPdIlllRrPsmp5TqZc6p8P8NFQej/dKbZOSk+LfoaD4u LnEUK1NQSMuT6PAwX7bTJZ5IriYkE0hW3DvPp7wbKZ3dyVI/NqHGbN4qf59fTZU1VM0N KsGjqZnvc/JoeyVZWL/+4bW+Wd0dCMhsLwvWR/69g3rcHfrHhzd97Sm65fQD9VdwkRCc WLrhUF5o9J/kelwTMLu82wqtkELmtWOOi5AMysnSOZe2C43L5Sc6M9UWNkgIuRP/89Qb V6DQ== X-Received: by 10.180.39.140 with SMTP id p12mr11189394wik.12.1384621754710; Sat, 16 Nov 2013 09:09:14 -0800 (PST) Received: from venice.bhome (ppp-80-52.24-151.libero.it. [151.24.52.80]) by mx.google.com with ESMTPSA id e1sm6584799wij.6.2013.11.16.09.09.14 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 16 Nov 2013 09:09:14 -0800 (PST) From: Goffredo Baroncelli To: linux-btrfs@vger.kernel.org Cc: Goffredo Baroncelli Subject: [PATCH 3/7] recursive btrfs snapshot/delete: create traverse_list_subvol_rec() Date: Sat, 16 Nov 2013 18:09:03 +0100 Message-Id: <1384621747-25441-4-git-send-email-kreijack@inwind.it> X-Mailer: git-send-email 1.8.4.3 In-Reply-To: <1384621747-25441-1-git-send-email-kreijack@inwind.it> References: <1384621747-25441-1-git-send-email-kreijack@inwind.it> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Create the traverse_list_subvol_rec() function. Its aim is to permit to process recursively the filesystems subvolumes. Signed-off-by: Goffredo Baroncelli --- btrfs-list.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ btrfs-list.h | 3 ++ 2 files changed, 124 insertions(+) diff --git a/btrfs-list.c b/btrfs-list.c index 66f3127..b45c4d9 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -2012,3 +2012,124 @@ void free_root_info(struct root_info *ri) free(ri->name); free(ri->full_path); } + + +/* + * List and sort all subvolumes + */ +static int btrfs_list_all_subvols(int fd, struct root_lookup *root_sort, + struct root_lookup *root_lookup, int ascending) +{ + int ret = 0; + u64 top_id = 0; + struct btrfs_list_filter_set *filter_set; + struct btrfs_list_comparer_set *comp_set; + + filter_set = btrfs_list_alloc_filter_set(); + comp_set = btrfs_list_alloc_comparer_set(); + + btrfs_list_setup_filter(&filter_set, + BTRFS_LIST_FILTER_FULL_PATH, + top_id); + btrfs_list_setup_comparer(&comp_set, BTRFS_LIST_COMP_PATH, ascending); + + ret = btrfs_list_subvols(fd, root_lookup); + if (ret) + goto exit; + __filter_and_sort_subvol(root_lookup, root_sort, filter_set, + comp_set, top_id); + + ret = 0; +exit: + if (filter_set) + btrfs_list_free_filter_set(filter_set); + if (comp_set) + btrfs_list_free_comparer_set(comp_set); + + return ret; +} + +/* + * traverse the subvolumes list, calling func() for each subvolume path + * data is passed to func(). If all == true, func is called on all + * filesystem subvolumes. ascending set the order criteria + */ +int traverse_list_subvol_rec(char *path, int all, int ascending, + int (*func)(char *real_root, char *relative_root, char *path, void *data), + void *data) +{ + struct root_lookup root_lookup = {{0}}, root_to_free = {{0}}; + int ret, l=0, fd=-1; + DIR *fddir; + struct rb_node *n; + struct root_info ri = {{0}}; + char *rootpath = NULL; + + ret = 1; /* failure */ + + if (!all) { + /* search the full_path of path */ + ret = get_root_info(path, &ri); + if (ret) { + fprintf(stderr, "ERROR: cannot get info on '%s'\n", path); + goto out; + } + } + + fd = open_file_or_dir(path, &fddir); + if (fd < 0) { + fprintf(stderr, "ERROR: can't access to '%s'\n", path); + goto out; + } + ret = btrfs_list_all_subvols(fd, &root_lookup, &root_to_free, ascending); + /* doesn't leak fd & fddir */ + close_file_or_dir(fd, fddir); + + if (ret) { + fprintf(stderr, "ERROR: cannot list the subvols\n"); + goto out; + } + + if (!all) { + n = rb_first(&root_lookup.root); + while (n) { + struct root_info *entry; + + entry = rb_entry(n, struct root_info, sort_node); + if (entry->root_id == ri.root_id) { + rootpath = entry->full_path; + break; + } + n = rb_next(n); + } + BUG_ON(!rootpath); + + } else { + rootpath = ""; + } + l = strlen(rootpath); + + for (n = rb_first(&root_lookup.root) ; n ; n = rb_next(n)) { + struct root_info *entry; + + entry = rb_entry(n, struct root_info, sort_node); + if (!all && strncmp(rootpath, entry->full_path,l)) { + continue; + } + + ret = func(rootpath, path, entry->full_path+l, data); + if (ret) + goto out; + + } + ret = 0; + +out: + + __free_all_subvolumn(&root_to_free); + if (!all) + free_root_info(&ri); + + return ret; + +} diff --git a/btrfs-list.h b/btrfs-list.h index db32805..5c246e1 100644 --- a/btrfs-list.h +++ b/btrfs-list.h @@ -168,5 +168,8 @@ int btrfs_list_get_path_rootid(int fd, u64 *treeid); int btrfs_get_subvol(int fd, struct root_info *the_ri); int get_root_info(char *path, struct root_info *get_ri); void free_root_info(struct root_info *ri); +int traverse_list_subvol_rec(char *path, int all, int ascending, + int (*func)(char *real_root, char *relative_root, char *path, void *data), + void *data); #endif