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:
parent
9c9e30cd6d
commit
9b02bdbce0
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user