From patchwork Thu Dec 4 18:24:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Goffredo Baroncelli X-Patchwork-Id: 5439711 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 4A0E69F1D4 for ; Thu, 4 Dec 2014 18:25:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2579F2024D for ; Thu, 4 Dec 2014 18:25:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CF3C420225 for ; Thu, 4 Dec 2014 18:25:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932859AbaLDSY4 (ORCPT ); Thu, 4 Dec 2014 13:24:56 -0500 Received: from mail-wi0-f178.google.com ([209.85.212.178]:61832 "EHLO mail-wi0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932464AbaLDSYn (ORCPT ); Thu, 4 Dec 2014 13:24:43 -0500 Received: by mail-wi0-f178.google.com with SMTP id em10so9363519wid.17 for ; Thu, 04 Dec 2014 10:24:42 -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=TEop2Iu71eH/hSGWQ7dFMHwEGrebvfBlBMv/6Rvs3nY=; b=yTF2B40waiJUhge/mqtNFqoYqdKWfiPrzxbOTDKgNQFAdfV5mERImdXNBQUOpyc7Le RaPFPvTdUcOE2jZaPZwPxfipVP7zjGArGaPfca0iA49XN/82cLVdkJmdSreKBtpYA+SJ LYlDMaA1hX5SChGWZPriNeFv7mH9N0gzmffIYzTcsBYIjUkgfSZKJVTWkB1RndCv//ex RL52xMvW5XSTXmJb0L6wHyFcjIB6+GijhDfCYijGAaqPy9QdX1KnuzCtpNYwp2LcCHFS gllVJ5d5K7MxGwjuJtoBW/I308fRxB2lKvgL5jzAdLELa8q8tTPTF7UyUbxAUazY4UF9 wAIQ== X-Received: by 10.180.211.108 with SMTP id nb12mr112464080wic.76.1417717481904; Thu, 04 Dec 2014 10:24:41 -0800 (PST) Received: from venice.bhome (ppp-252-95.24-151.libero.it. [151.24.95.252]) by mx.google.com with ESMTPSA id wa5sm15767794wjc.8.2014.12.04.10.24.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Dec 2014 10:24:41 -0800 (PST) From: Goffredo Baroncelli X-Google-Original-From: Goffredo Baroncelli To: linux-btrfs@vger.kernel.org Cc: Goffredo Baroncelli Subject: [PATCH 1/5] Avoid to consider lvm snapshots when scanning devices. Date: Thu, 4 Dec 2014 19:24:26 +0100 Message-Id: <1417717470-6298-2-git-send-email-kreijack@inwind.it> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1417717470-6298-1-git-send-email-kreijack@inwind.it> References: <1417717470-6298-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, T_DKIM_INVALID, T_RP_MATCHES_RCVD, 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 LVM snapshots create a problem to the btrfs devices management. BTRFS assumes that each device haw an unique 'device UUID'. A LVM snapshot breaks this assumption. This patch skips LVM snapshots during the device scan phase. If you need to consider a LVM snapshot you have to set the environmental variable BTRFS_SKIP_LVM_SNAPSHOT to "no". To check if a device is a LVM snapshot, it is checked the 'udev' device property 'DM_UDEV_LOW_PRIORITY_FLAG' . If it is set to 1, the device has to be skipped. As conseguence, btrfs now depends by libudev. Programmatically you can control this behavior with the functions: - btrfs_scan_set_skip_lvm_snapshot(int new_value) - int btrfs_scan_get_skip_lvm_snapshot( ) Signed-off-by: Goffredo Baroncelli --- Makefile | 4 +-- utils.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 9 +++++- 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 4cae30c..9464361 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ TESTS = fsck-tests.sh convert-tests.sh INSTALL = install prefix ?= /usr/local bindir = $(prefix)/bin -lib_LIBS = -luuid -lblkid -lm -lz -llzo2 -L. +lib_LIBS = -luuid -lblkid -lm -lz -ludev -llzo2 -L. libdir ?= $(prefix)/lib incdir = $(prefix)/include/btrfs LIBS = $(lib_LIBS) $(libs_static) @@ -99,7 +99,7 @@ lib_links = libbtrfs.so.0 libbtrfs.so headers = $(libbtrfs_headers) # make C=1 to enable sparse -check_defs := .cc-defines.h +check_defs := .cc-defines.h ifdef C # # We're trying to use sparse against glibc headers which go wild diff --git a/utils.c b/utils.c index 2a92416..9887f8b 100644 --- a/utils.c +++ b/utils.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,13 @@ #define BLKDISCARD _IO(0x12,119) #endif +/* + * This variable controls if the lvm snapshot have to be skipped or not. + * Access this variable only via the btrfs_scan_[sg]et_skip_lvm_snapshot() + * functions + */ +static int __scan_device_skip_lvm_snapshot = -1; + static int btrfs_scan_done = 0; static char argv0_buf[ARGV0_BUF_SIZE] = "btrfs"; @@ -1593,6 +1601,9 @@ int btrfs_scan_block_devices(int run_ioctl) char fullpath[110]; int scans = 0; int special; + int skip_snapshot; + + skip_snapshot = btrfs_scan_get_skip_lvm_snapshot(); scan_again: proc_partitions = fopen("/proc/partitions","r"); @@ -1642,6 +1653,9 @@ scan_again: continue; } + if (skip_snapshot && is_low_priority_device(fullpath)) + continue; + fd = open(fullpath, O_RDONLY); if (fd < 0) { if (errno != ENOMEDIUM) @@ -2182,6 +2196,30 @@ int test_dev_for_mkfs(char *file, int force_overwrite, char *estr) return 0; } +int btrfs_scan_get_skip_lvm_snapshot( ) +{ + const char *value; + + if (__scan_device_skip_lvm_snapshot != -1 ) + return __scan_device_skip_lvm_snapshot; + + value = getenv(BTRFS_SKIP_LVM_SNAPSHOT_ENV_NAME); + if (value && !strcasecmp(value, "NO")) + __scan_device_skip_lvm_snapshot = 0; + else if (value && !strcasecmp(value, "YES")) + __scan_device_skip_lvm_snapshot = 1; + else + __scan_device_skip_lvm_snapshot = + BTRFS_SKIP_LVM_SNAPSHOT_DEFAULT; + + return __scan_device_skip_lvm_snapshot; +} + +void btrfs_scan_set_skip_lvm_snapshot(int new_value) +{ + __scan_device_skip_lvm_snapshot = !!new_value; +} + int btrfs_scan_lblkid() { int fd = -1; @@ -2192,6 +2230,9 @@ int btrfs_scan_lblkid() blkid_dev dev = NULL; blkid_cache cache = NULL; char path[PATH_MAX]; + int skip_snapshot; + + skip_snapshot = btrfs_scan_get_skip_lvm_snapshot(); if (btrfs_scan_done) return 0; @@ -2210,6 +2251,9 @@ int btrfs_scan_lblkid() /* if we are here its definitely a btrfs disk*/ strncpy(path, blkid_dev_devname(dev), PATH_MAX); + if (skip_snapshot && is_low_priority_device(path)) + continue; + fd = open(path, O_RDONLY); if (fd < 0) { printf("ERROR: could not open %s\n", path); @@ -2450,3 +2494,66 @@ int find_next_key(struct btrfs_path *path, struct btrfs_key *key) } return 1; } + +/* + * This function return 1 if the device (path) is consdered "LOW_PRIORITY" by + * LVM2 library. These device are typically the nsapshot. + * This function return < 0 in case of error; 0 otherwise. + */ +int is_low_priority_device(const char *path) +{ + + struct udev *udev=NULL; + struct udev_device *dev; + struct udev_enumerate *enumerate=NULL; + struct udev_list_entry *devices; + struct udev_list_entry *node, *list; + int ret=-1; + const char *value, *syspath; + char *rpath=NULL; + + rpath = realpath(path, NULL); + if (!rpath) { + fprintf(stderr, "ERROR: not enough memory\n"); + ret=-2; + goto exit; + } + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + fprintf(stderr, "ERROR: Can't create udev\n"); + ret=-1; + goto exit; + } + + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(enumerate, "block"); + udev_enumerate_add_match_property(enumerate, "DEVNAME", rpath); + udev_enumerate_scan_devices(enumerate); + + devices = udev_enumerate_get_list_entry(enumerate); + syspath = udev_list_entry_get_name(devices); + + dev = udev_device_new_from_syspath(udev, syspath); + + list = udev_device_get_properties_list_entry (dev); + + ret = 0; + node = udev_list_entry_get_by_name(list, "DM_UDEV_LOW_PRIORITY_FLAG"); + if (node) { + value = udev_list_entry_get_value(node); + if (value && !strcmp(value, "1")) + ret = 1; + } + +exit: + free(rpath); + + /* Free the enumerator object */ + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return ret; +} diff --git a/utils.h b/utils.h index 289e86b..9855f09 100644 --- a/utils.h +++ b/utils.h @@ -128,7 +128,7 @@ int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, int verify); int ask_user(char *question); int lookup_ino_rootid(int fd, u64 *rootid); -int btrfs_scan_lblkid(void); +int btrfs_scan_lblkid(); int get_btrfs_mount(const char *dev, char *mp, size_t mp_size); int find_mount_root(const char *path, char **mount_root); int get_device_info(int fd, u64 devid, @@ -161,4 +161,11 @@ static inline u64 btrfs_min_dev_size(u32 leafsize) int find_next_key(struct btrfs_path *path, struct btrfs_key *key); +#define BTRFS_SKIP_LVM_SNAPSHOT_DEFAULT 1 +#define BTRFS_SKIP_LVM_SNAPSHOT_ENV_NAME "BTRFS_SKIP_LVM_SNAPSHOT" + +int is_low_priority_device(const char *path); +void btrfs_scan_set_skip_lvm_snapshot(int new_value); +int btrfs_scan_get_skip_lvm_snapshot( ); + #endif