1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Refuse to run pvcreate/pvremove on devices we can't open exclusively.

This commit is contained in:
Alasdair Kergon 2005-10-03 21:10:41 +00:00
parent 9c9e30cd6d
commit 9b02bdbce0
5 changed files with 61 additions and 9 deletions

View File

@ -1,5 +1,6 @@
Version 2.01.15 - Version 2.01.15 -
================================= =================================
Refuse to run pvcreate/pvremove on devices we can't open exclusively.
Use ORPHAN lock definition throughout. Use ORPHAN lock definition throughout.
Validate chunksize in lvcreate. Validate chunksize in lvcreate.
Reduce chunksize limit to 512k. Reduce chunksize limit to 512k.

View File

@ -320,15 +320,22 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
{ {
struct stat buf; struct stat buf;
const char *name; const char *name;
int need_excl = 0, need_rw = 0;
if ((flags & O_ACCMODE) == O_RDWR)
need_rw = 1;
if ((flags & O_EXCL))
need_excl = 1;
if (dev->fd >= 0) { if (dev->fd >= 0) {
if ((dev->flags & DEV_OPENED_RW) || if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
((flags & O_ACCMODE) != O_RDWR)) { ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
dev->open_count++; dev->open_count++;
return 1; return 1;
} }
if (dev->open_count) { if (dev->open_count && !need_excl) {
/* FIXME Ensure we never get here */ /* FIXME Ensure we never get here */
log_debug("WARNING: %s already opened read-only", log_debug("WARNING: %s already opened read-only",
dev_name(dev)); dev_name(dev));
@ -397,11 +404,16 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
dev->open_count++; dev->open_count++;
dev->flags &= ~DEV_ACCESSED_W; dev->flags &= ~DEV_ACCESSED_W;
if ((flags & O_ACCMODE) == O_RDWR) if (need_rw)
dev->flags |= DEV_OPENED_RW; dev->flags |= DEV_OPENED_RW;
else else
dev->flags &= ~DEV_OPENED_RW; dev->flags &= ~DEV_OPENED_RW;
if (need_excl)
dev->flags |= DEV_OPENED_EXCL;
else
dev->flags &= ~DEV_OPENED_EXCL;
if (!(dev->flags & DEV_REGULAR) && if (!(dev->flags & DEV_REGULAR) &&
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) { ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
log_error("%s: fstat failed: Has device name changed?", name); log_error("%s: fstat failed: Has device name changed?", name);
@ -420,8 +432,9 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
list_add(&_open_devices, &dev->open_list); list_add(&_open_devices, &dev->open_list);
log_debug("Opened %s %s%s", dev_name(dev), log_debug("Opened %s %s%s%s", dev_name(dev),
dev->flags & DEV_OPENED_RW ? "RW" : "RO", dev->flags & DEV_OPENED_RW ? "RW" : "RO",
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : ""); dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
return 1; return 1;
@ -445,6 +458,21 @@ int dev_open(struct device *dev)
return dev_open_flags(dev, flags, 1, 0); return dev_open_flags(dev, flags, 1, 0);
} }
int dev_test_excl(struct device *dev)
{
int flags;
int r;
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
flags |= O_EXCL;
r = dev_open_flags(dev, flags, 1, 1);
if (r)
dev_close_immediate(dev);
return r;
}
static void _close(struct device *dev) static void _close(struct device *dev)
{ {
if (close(dev->fd)) if (close(dev->fd))
@ -479,6 +507,11 @@ static int _dev_close(struct device *dev, int immediate)
if (dev->open_count > 0) if (dev->open_count > 0)
dev->open_count--; dev->open_count--;
if (immediate && dev->open_count) {
log_debug("%s: Immediate close attempt while still referenced");
dev->open_count = 0;
}
/* FIXME lookup device in cache to get vgname and see if it's locked? */ /* FIXME lookup device in cache to get vgname and see if it's locked? */
if (immediate || (dev->open_count < 1 && !vgs_locked())) if (immediate || (dev->open_count < 1 && !vgs_locked()))
_close(dev); _close(dev);

View File

@ -23,8 +23,9 @@
#define DEV_REGULAR 0x00000002 /* Regular file? */ #define DEV_REGULAR 0x00000002 /* Regular file? */
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */ #define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
#define DEV_OPENED_RW 0x00000008 /* Opened RW */ #define DEV_OPENED_RW 0x00000008 /* Opened RW */
#define DEV_O_DIRECT 0x00000010 /* Use O_DIRECT */ #define DEV_OPENED_EXCL 0x00000010 /* Opened EXCL */
#define DEV_O_DIRECT_TESTED 0x00000020 /* DEV_O_DIRECT is reliable */ #define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
#define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */
/* /*
* All devices in LVM will be represented by one of these. * All devices in LVM will be represented by one of these.
@ -70,6 +71,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet);
int dev_close(struct device *dev); int dev_close(struct device *dev);
int dev_close_immediate(struct device *dev); int dev_close_immediate(struct device *dev);
void dev_close_all(void); void dev_close_all(void);
int dev_test_excl(struct device *dev);
static inline int dev_fd(struct device *dev) static inline int dev_fd(struct device *dev)
{ {

View File

@ -82,6 +82,12 @@ static int pvcreate_check(struct cmd_context *cmd, const char *name)
return 0; return 0;
} }
if (!dev_test_excl(dev)) {
log_error("Can't open %s exclusively. Mounted filesystem?",
name);
return 0;
}
/* Wipe superblock? */ /* Wipe superblock? */
if (dev_is_md(dev, &md_superblock) && if (dev_is_md(dev, &md_superblock) &&
((!arg_count(cmd, uuidstr_ARG) && ((!arg_count(cmd, uuidstr_ARG) &&
@ -219,7 +225,11 @@ static int pvcreate_single(struct cmd_context *cmd, const char *pv_name,
goto error; goto error;
} }
dev_zero(dev, UINT64_C(0), (size_t) 2048); if (!dev_zero(dev, UINT64_C(0), (size_t) 2048)) {
log_error("%s not wiped: aborting", pv_name);
dev_close(dev);
goto error;
}
dev_close(dev); dev_close(dev);
} }

View File

@ -86,6 +86,12 @@ static int pvremove_single(struct cmd_context *cmd, const char *pv_name,
goto error; goto error;
} }
if (!dev_test_excl(dev)) {
log_error("Can't open %s exclusively. Mounted filesystem?",
dev_name(dev));
return 0;
}
/* Wipe existing label(s) */ /* Wipe existing label(s) */
if (!label_remove(dev)) { if (!label_remove(dev)) {
log_error("Failed to wipe existing label(s) on %s", pv_name); log_error("Failed to wipe existing label(s) on %s", pv_name);