From 864de9cee16696e5c764c91fe8aa670bdfe26c70 Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Thu, 7 Apr 2005 12:17:46 +0000 Subject: [PATCH] Allow offline extension of snapshot volumes. NB Requires kernel patch that is not upstream. --- WHATS_NEW | 3 ++- lib/device/dev-io.c | 29 +++++++++++++++++++++++++---- lib/device/device.h | 4 +++- tools/lvresize.c | 22 +++++++++++++++++----- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index c6facc32d..6e7cc324c 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,7 +1,8 @@ Version 2.01.10 - ================================ + Allow offline extension of snapshot volumes. Move from 2-step to 3-step on-disk metadata commit. - Scan ramdisks too. + Scan ramdisks too and allow non-O_DIRECT fallback. Annotate, tidy and extend list.h. Alignment tidying. diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c index 7b0b8f2ad..a9ae466a1 100644 --- a/lib/device/dev-io.c +++ b/lib/device/dev-io.c @@ -330,8 +330,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) } #ifdef O_DIRECT_SUPPORT - if (direct) - flags |= O_DIRECT; + if (direct) { + if (!(dev->flags & DEV_O_DIRECT_TESTED)) + dev->flags |= DEV_O_DIRECT; + + if ((dev->flags & DEV_O_DIRECT)) + flags |= O_DIRECT; + } #endif #ifdef O_NOATIME @@ -341,6 +346,16 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) #endif if ((dev->fd = open(name, flags, 0777)) < 0) { +#ifdef O_DIRECT_SUPPORT + if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) { + flags &= ~O_DIRECT; + if ((dev->fd = open(name, flags, 0777)) >= 0) { + dev->flags &= ~DEV_O_DIRECT; + log_debug("%s: Not using O_DIRECT", name); + goto opened; + } + } +#endif if (quiet) log_sys_debug("open", name); else @@ -348,8 +363,13 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) return 0; } + opened: dev->open_count++; dev->flags &= ~DEV_ACCESSED_W; +#ifdef O_DIRECT_SUPPORT + if (direct) + dev->flags |= DEV_O_DIRECT_TESTED; +#endif if ((flags & O_ACCMODE) == O_RDWR) dev->flags |= DEV_OPENED_RW; else @@ -373,8 +393,9 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet) list_add(&_open_devices, &dev->open_list); - log_debug("Opened %s %s", dev_name(dev), - dev->flags & DEV_OPENED_RW ? "RW" : "RO"); + log_debug("Opened %s %s%s", dev_name(dev), + dev->flags & DEV_OPENED_RW ? "RW" : "RO", + dev->flags & DEV_O_DIRECT ? " O_DIRECT" : ""); return 1; } diff --git a/lib/device/device.h b/lib/device/device.h index ac7bd955e..f1698a4ea 100644 --- a/lib/device/device.h +++ b/lib/device/device.h @@ -23,6 +23,8 @@ #define DEV_REGULAR 0x00000002 /* Regular file? */ #define DEV_ALLOCED 0x00000004 /* dbg_malloc used */ #define DEV_OPENED_RW 0x00000008 /* Opened RW */ +#define DEV_O_DIRECT 0x00000010 /* Use O_DIRECT */ +#define DEV_O_DIRECT_TESTED 0x00000020 /* DEV_O_DIRECT is reliable */ /* * All devices in LVM will be represented by one of these. @@ -64,7 +66,7 @@ int dev_get_sectsize(struct device *dev, uint32_t *size); /* Use quiet version if device number could change e.g. when opening LV */ int dev_open(struct device *dev); int dev_open_quiet(struct device *dev); -int dev_open_flags(struct device *dev, int flags, int append, int quiet); +int dev_open_flags(struct device *dev, int flags, int direct, int quiet); int dev_close(struct device *dev); int dev_close_immediate(struct device *dev); void dev_close_all(void); diff --git a/tools/lvresize.c b/tools/lvresize.c index 734fd7056..c788c988e 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -180,11 +180,6 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) return ECMD_FAILED; } - if (lv_is_origin(lv)) { - log_error("Snapshot origin volumes cannot be resized yet."); - return ECMD_FAILED; - } - alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, lv->alloc); if (lp->size) { @@ -352,6 +347,23 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) lp->resize = LV_EXTEND; } + + if (lv_is_origin(lv)) { + if (lp->resize == LV_REDUCE) { + log_error("Snapshot origin volumes cannot be reduced " + "in size yet."); + return ECMD_FAILED; + } + + memset(&info, 0, sizeof(info)); + + if (lv_info(lv, &info, 0) && info.exists) { + log_error("Snapshot origin volumes can be resized " + "only while inactive: try lvchange -an"); + return ECMD_FAILED; + } + } + if (lp->resize == LV_REDUCE) { if (lp->argc) log_print("Ignoring PVs on command line when reducing");