Commit 24f27632 authored by Dave Jones's avatar Dave Jones

[PATCH] LVM fixes.

Numerous LVM fixes & cleanups.
Gets things compiling again, and allegedly works according to feedback.
Mostly from Anders in absence of any maintainence by LVM people.

There are two critical problems with lvm in 2.5.2-pre11 (and earlier).
* ioctls on the chardev allocates a >4k lv_t on stack. if the ioctl is
LV_CREATE, LV_EXTEND, LV_REDUCE or LV_RENAME data is copied into this
and the task_struct will most certainly be corrupted.
* sizeof(lv_t) differs between user and kernelspace. The userspace version
of the lv_t structure is much smaller than the kernelspace version. This
leads to corruption of memory in the userspace application when an lv_t is
copied from kernelspace to userspace, as in "vgdisplay -v"

The following patch addresses these two issues. It puts the user-space
version of the lv_t into a substructure of the kernelspace version. When
communicating to userspace just the userlv_t part is used. This avoids the
allocation of the lv_t on the stack by allocation just a userlv_t instead.
parent 4d32c6ba
...@@ -170,11 +170,11 @@ static inline const char *_basename(const char *str) { ...@@ -170,11 +170,11 @@ static inline const char *_basename(const char *str) {
devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) { devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
struct proc_dir_entry *pde; struct proc_dir_entry *pde;
const char *name = _basename(lv->lv_name); const char *name = _basename(lv->u.lv_name);
lv_devfs_handle[minor(lv->lv_dev)] = devfs_register( lv_devfs_handle[minor(lv->u.lv_dev)] = devfs_register(
vg_devfs_handle[vg_ptr->vg_number], name, vg_devfs_handle[vg_ptr->vg_number], name,
DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, minor(lv->lv_dev), DEVFS_FL_DEFAULT, LVM_BLK_MAJOR, minor(lv->u.lv_dev),
S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
&lvm_blk_dops, NULL); &lvm_blk_dops, NULL);
...@@ -183,15 +183,15 @@ devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) { ...@@ -183,15 +183,15 @@ devfs_handle_t lvm_fs_create_lv(vg_t *vg_ptr, lv_t *lv) {
pde->read_proc = _proc_read_lv; pde->read_proc = _proc_read_lv;
pde->data = lv; pde->data = lv;
} }
return lv_devfs_handle[minor(lv->lv_dev)]; return lv_devfs_handle[minor(lv->u.lv_dev)];
} }
void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) { void lvm_fs_remove_lv(vg_t *vg_ptr, lv_t *lv) {
devfs_unregister(lv_devfs_handle[minor(lv->lv_dev)]); devfs_unregister(lv_devfs_handle[minor(lv->u.lv_dev)]);
lv_devfs_handle[minor(lv->lv_dev)] = NULL; lv_devfs_handle[minor(lv->u.lv_dev)] = NULL;
if(vg_ptr->lv_subdir_pde) { if(vg_ptr->lv_subdir_pde) {
const char *name = _basename(lv->lv_name); const char *name = _basename(lv->u.lv_name);
remove_proc_entry(name, vg_ptr->lv_subdir_pde); remove_proc_entry(name, vg_ptr->lv_subdir_pde);
} }
} }
...@@ -269,21 +269,21 @@ static int _proc_read_lv(char *page, char **start, off_t off, ...@@ -269,21 +269,21 @@ static int _proc_read_lv(char *page, char **start, off_t off,
int sz = 0; int sz = 0;
lv_t *lv = data; lv_t *lv = data;
sz += sprintf(page + sz, "name: %s\n", lv->lv_name); sz += sprintf(page + sz, "name: %s\n", lv->u.lv_name);
sz += sprintf(page + sz, "size: %u\n", lv->lv_size); sz += sprintf(page + sz, "size: %u\n", lv->u.lv_size);
sz += sprintf(page + sz, "access: %u\n", lv->lv_access); sz += sprintf(page + sz, "access: %u\n", lv->u.lv_access);
sz += sprintf(page + sz, "status: %u\n", lv->lv_status); sz += sprintf(page + sz, "status: %u\n", lv->u.lv_status);
sz += sprintf(page + sz, "number: %u\n", lv->lv_number); sz += sprintf(page + sz, "number: %u\n", lv->u.lv_number);
sz += sprintf(page + sz, "open: %u\n", lv->lv_open); sz += sprintf(page + sz, "open: %u\n", lv->u.lv_open);
sz += sprintf(page + sz, "allocation: %u\n", lv->lv_allocation); sz += sprintf(page + sz, "allocation: %u\n", lv->u.lv_allocation);
if(lv->lv_stripes > 1) { if(lv->u.lv_stripes > 1) {
sz += sprintf(page + sz, "stripes: %u\n", sz += sprintf(page + sz, "stripes: %u\n",
lv->lv_stripes); lv->u.lv_stripes);
sz += sprintf(page + sz, "stripesize: %u\n", sz += sprintf(page + sz, "stripesize: %u\n",
lv->lv_stripesize); lv->u.lv_stripesize);
} }
sz += sprintf(page + sz, "device: %02u:%02u\n", sz += sprintf(page + sz, "device: %02u:%02u\n",
major(lv->lv_dev), minor(lv->lv_dev)); major(lv->u.lv_dev), minor(lv->u.lv_dev));
return sz; return sz;
} }
...@@ -350,13 +350,13 @@ static int _proc_read_global(char *page, char **start, off_t pos, int count, ...@@ -350,13 +350,13 @@ static int _proc_read_global(char *page, char **start, off_t pos, int count,
if (vg_ptr->lv_cur > 0) { if (vg_ptr->lv_cur > 0) {
for (l = 0; l < vg[v]->lv_max; l++) { for (l = 0; l < vg[v]->lv_max; l++) {
if ((lv_ptr = vg_ptr->lv[l]) != NULL) { if ((lv_ptr = vg_ptr->lv[l]) != NULL) {
pe_t_bytes += lv_ptr->lv_allocated_le; pe_t_bytes += lv_ptr->u.lv_allocated_le;
hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size; hash_table_bytes += lv_ptr->lv_snapshot_hash_table_size;
if (lv_ptr->lv_block_exception != NULL) if (lv_ptr->u.lv_block_exception != NULL)
lv_block_exception_t_bytes += lv_ptr->lv_remap_end; lv_block_exception_t_bytes += lv_ptr->u.lv_remap_end;
if (lv_ptr->lv_open > 0) { if (lv_ptr->u.lv_open > 0) {
lv_open_counter++; lv_open_counter++;
lv_open_total += lv_ptr->lv_open; lv_open_total += lv_ptr->u.lv_open;
} }
} }
} }
...@@ -532,16 +532,16 @@ static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) { ...@@ -532,16 +532,16 @@ static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
char inactive_flag = 'A', allocation_flag = ' ', char inactive_flag = 'A', allocation_flag = ' ',
stripes_flag = ' ', rw_flag = ' ', *basename; stripes_flag = ' ', rw_flag = ' ', *basename;
if (!(lv_ptr->lv_status & LV_ACTIVE)) if (!(lv_ptr->u.lv_status & LV_ACTIVE))
inactive_flag = 'I'; inactive_flag = 'I';
rw_flag = 'R'; rw_flag = 'R';
if (lv_ptr->lv_access & LV_WRITE) if (lv_ptr->u.lv_access & LV_WRITE)
rw_flag = 'W'; rw_flag = 'W';
allocation_flag = 'D'; allocation_flag = 'D';
if (lv_ptr->lv_allocation & LV_CONTIGUOUS) if (lv_ptr->u.lv_allocation & LV_CONTIGUOUS)
allocation_flag = 'C'; allocation_flag = 'C';
stripes_flag = 'L'; stripes_flag = 'L';
if (lv_ptr->lv_stripes > 1) if (lv_ptr->u.lv_stripes > 1)
stripes_flag = 'S'; stripes_flag = 'S';
sz += sprintf(buf+sz, sz += sprintf(buf+sz,
"[%c%c%c%c", "[%c%c%c%c",
...@@ -549,29 +549,29 @@ static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) { ...@@ -549,29 +549,29 @@ static int _lv_info(vg_t *vg_ptr, lv_t *lv_ptr, char *buf) {
rw_flag, rw_flag,
allocation_flag, allocation_flag,
stripes_flag); stripes_flag);
if (lv_ptr->lv_stripes > 1) if (lv_ptr->u.lv_stripes > 1)
sz += sprintf(buf+sz, "%-2d", sz += sprintf(buf+sz, "%-2d",
lv_ptr->lv_stripes); lv_ptr->u.lv_stripes);
else else
sz += sprintf(buf+sz, " "); sz += sprintf(buf+sz, " ");
/* FIXME: use _basename */ /* FIXME: use _basename */
basename = strrchr(lv_ptr->lv_name, '/'); basename = strrchr(lv_ptr->u.lv_name, '/');
if ( basename == 0) basename = lv_ptr->lv_name; if ( basename == 0) basename = lv_ptr->u.lv_name;
else basename++; else basename++;
sz += sprintf(buf+sz, "] %-25s", basename); sz += sprintf(buf+sz, "] %-25s", basename);
if (strlen(basename) > 25) if (strlen(basename) > 25)
sz += sprintf(buf+sz, sz += sprintf(buf+sz,
"\n "); "\n ");
sz += sprintf(buf+sz, "%9d /%-6d ", sz += sprintf(buf+sz, "%9d /%-6d ",
lv_ptr->lv_size >> 1, lv_ptr->u.lv_size >> 1,
lv_ptr->lv_size / vg_ptr->pe_size); lv_ptr->u.lv_size / vg_ptr->pe_size);
if (lv_ptr->lv_open == 0) if (lv_ptr->u.lv_open == 0)
sz += sprintf(buf+sz, "close"); sz += sprintf(buf+sz, "close");
else else
sz += sprintf(buf+sz, "%dx open", sz += sprintf(buf+sz, "%dx open",
lv_ptr->lv_open); lv_ptr->u.lv_open);
return sz; return sz;
} }
......
...@@ -93,7 +93,7 @@ lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv) ...@@ -93,7 +93,7 @@ lvm_find_exception_table(kdev_t org_dev, unsigned long org_start, lv_t * lv)
{ {
struct list_head * hash_table = lv->lv_snapshot_hash_table, * next; struct list_head * hash_table = lv->lv_snapshot_hash_table, * next;
unsigned long mask = lv->lv_snapshot_hash_mask; unsigned long mask = lv->lv_snapshot_hash_mask;
int chunk_size = lv->lv_chunk_size; int chunk_size = lv->u.lv_chunk_size;
lv_block_exception_t * ret; lv_block_exception_t * ret;
int i = 0; int i = 0;
...@@ -127,7 +127,7 @@ inline void lvm_hash_link(lv_block_exception_t * exception, ...@@ -127,7 +127,7 @@ inline void lvm_hash_link(lv_block_exception_t * exception,
{ {
struct list_head * hash_table = lv->lv_snapshot_hash_table; struct list_head * hash_table = lv->lv_snapshot_hash_table;
unsigned long mask = lv->lv_snapshot_hash_mask; unsigned long mask = lv->lv_snapshot_hash_mask;
int chunk_size = lv->lv_chunk_size; int chunk_size = lv->u.lv_chunk_size;
hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)]; hash_table = &hash_table[hashfn(org_dev, org_start, mask, chunk_size)];
list_add(&exception->hash, hash_table); list_add(&exception->hash, hash_table);
...@@ -139,7 +139,7 @@ int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector, ...@@ -139,7 +139,7 @@ int lvm_snapshot_remap_block(kdev_t * org_dev, unsigned long * org_sector,
int ret; int ret;
unsigned long pe_off, pe_adjustment, __org_start; unsigned long pe_off, pe_adjustment, __org_start;
kdev_t __org_dev; kdev_t __org_dev;
int chunk_size = lv->lv_chunk_size; int chunk_size = lv->u.lv_chunk_size;
lv_block_exception_t * exception; lv_block_exception_t * exception;
pe_off = pe_start % chunk_size; pe_off = pe_start % chunk_size;
...@@ -164,26 +164,26 @@ void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason) ...@@ -164,26 +164,26 @@ void lvm_drop_snapshot(vg_t *vg, lv_t *lv_snap, const char *reason)
/* no exception storage space available for this snapshot /* no exception storage space available for this snapshot
or error on this snapshot --> release it */ or error on this snapshot --> release it */
invalidate_buffers(lv_snap->lv_dev); invalidate_buffers(lv_snap->u.lv_dev);
/* wipe the snapshot since it's inconsistent now */ /* wipe the snapshot since it's inconsistent now */
_disable_snapshot(vg, lv_snap); _disable_snapshot(vg, lv_snap);
last_dev = NODEV; last_dev = NODEV;
for (i = 0; i < lv_snap->lv_remap_ptr; i++) { for (i = 0; i < lv_snap->u.lv_remap_ptr; i++) {
if ( !kdev_same(lv_snap->lv_block_exception[i].rdev_new, if ( !kdev_same(lv_snap->u.lv_block_exception[i].rdev_new,
last_dev)) { last_dev)) {
last_dev = lv_snap->lv_block_exception[i].rdev_new; last_dev = lv_snap->u.lv_block_exception[i].rdev_new;
invalidate_buffers(last_dev); invalidate_buffers(last_dev);
} }
} }
lvm_snapshot_release(lv_snap); lvm_snapshot_release(lv_snap);
lv_snap->lv_status &= ~LV_ACTIVE; lv_snap->u.lv_status &= ~LV_ACTIVE;
printk(KERN_INFO printk(KERN_INFO
"%s -- giving up to snapshot %s on %s: %s\n", "%s -- giving up to snapshot %s on %s: %s\n",
lvm_name, lv_snap->lv_snapshot_org->lv_name, lv_snap->lv_name, lvm_name, lv_snap->u.lv_snapshot_org->u.lv_name, lv_snap->u.lv_name,
reason); reason);
} }
...@@ -234,7 +234,7 @@ static inline void invalidate_snap_cache(unsigned long start, unsigned long nr, ...@@ -234,7 +234,7 @@ static inline void invalidate_snap_cache(unsigned long start, unsigned long nr,
int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
{ {
uint pvn; uint pvn;
int id = 0, is = lv_snap->lv_remap_ptr; int id = 0, is = lv_snap->u.lv_remap_ptr;
ulong blksize_snap; ulong blksize_snap;
lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *) lv_COW_table_disk_t * lv_COW_table = (lv_COW_table_disk_t *)
page_address(lv_snap->lv_COW_table_iobuf->maplist[0]); page_address(lv_snap->lv_COW_table_iobuf->maplist[0]);
...@@ -244,13 +244,13 @@ int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap) ...@@ -244,13 +244,13 @@ int lvm_snapshot_fill_COW_page(vg_t * vg, lv_t * lv_snap)
is--; is--;
blksize_snap = blksize_snap =
block_size(lv_snap->lv_block_exception[is].rdev_new); block_size(lv_snap->u.lv_block_exception[is].rdev_new);
is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t)); is -= is % (blksize_snap / sizeof(lv_COW_table_disk_t));
memset(lv_COW_table, 0, blksize_snap); memset(lv_COW_table, 0, blksize_snap);
for ( ; is < lv_snap->lv_remap_ptr; is++, id++) { for ( ; is < lv_snap->u.lv_remap_ptr; is++, id++) {
/* store new COW_table entry */ /* store new COW_table entry */
lv_block_exception_t *be = lv_snap->lv_block_exception + is; lv_block_exception_t *be = lv_snap->u.lv_block_exception + is;
if(_pv_get_number(vg, be->rdev_org, &pvn)) if(_pv_get_number(vg, be->rdev_org, &pvn))
goto bad; goto bad;
...@@ -281,7 +281,7 @@ int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap) ...@@ -281,7 +281,7 @@ int lvm_write_COW_table_block(vg_t * vg, lv_t *lv_snap)
int r; int r;
const char *err; const char *err;
if((r = _write_COW_table_block(vg, lv_snap, if((r = _write_COW_table_block(vg, lv_snap,
lv_snap->lv_remap_ptr - 1, &err))) lv_snap->u.lv_remap_ptr - 1, &err)))
lvm_drop_snapshot(vg, lv_snap, err); lvm_drop_snapshot(vg, lv_snap, err);
return r; return r;
} }
...@@ -303,13 +303,13 @@ int lvm_snapshot_COW(kdev_t org_phys_dev, ...@@ -303,13 +303,13 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
const char * reason; const char * reason;
kdev_t snap_phys_dev; kdev_t snap_phys_dev;
unsigned long org_start, snap_start, virt_start, pe_off; unsigned long org_start, snap_start, virt_start, pe_off;
int idx = lv_snap->lv_remap_ptr, chunk_size = lv_snap->lv_chunk_size; int idx = lv_snap->u.lv_remap_ptr, chunk_size = lv_snap->u.lv_chunk_size;
struct kiobuf * iobuf; struct kiobuf * iobuf;
int blksize_snap, blksize_org, min_blksize, max_blksize; int blksize_snap, blksize_org, min_blksize, max_blksize;
int max_sectors, nr_sectors; int max_sectors, nr_sectors;
/* check if we are out of snapshot space */ /* check if we are out of snapshot space */
if (idx >= lv_snap->lv_remap_end) if (idx >= lv_snap->u.lv_remap_end)
goto fail_out_of_space; goto fail_out_of_space;
/* calculate physical boundaries of source chunk */ /* calculate physical boundaries of source chunk */
...@@ -318,8 +318,8 @@ int lvm_snapshot_COW(kdev_t org_phys_dev, ...@@ -318,8 +318,8 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
virt_start = org_virt_sector - (org_phys_sector - org_start); virt_start = org_virt_sector - (org_phys_sector - org_start);
/* calculate physical boundaries of destination chunk */ /* calculate physical boundaries of destination chunk */
snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
snap_start = lv_snap->lv_block_exception[idx].rsector_new; snap_start = lv_snap->u.lv_block_exception[idx].rsector_new;
#ifdef DEBUG_SNAPSHOT #ifdef DEBUG_SNAPSHOT
printk(KERN_INFO printk(KERN_INFO
...@@ -371,20 +371,20 @@ int lvm_snapshot_COW(kdev_t org_phys_dev, ...@@ -371,20 +371,20 @@ int lvm_snapshot_COW(kdev_t org_phys_dev,
#ifdef DEBUG_SNAPSHOT #ifdef DEBUG_SNAPSHOT
/* invalidate the logical snapshot buffer cache */ /* invalidate the logical snapshot buffer cache */
invalidate_snap_cache(virt_start, lv_snap->lv_chunk_size, invalidate_snap_cache(virt_start, lv_snap->u.lv_chunk_size,
lv_snap->lv_dev); lv_snap->u.lv_dev);
#endif #endif
/* the original chunk is now stored on the snapshot volume /* the original chunk is now stored on the snapshot volume
so update the execption table */ so update the execption table */
lv_snap->lv_block_exception[idx].rdev_org = org_phys_dev; lv_snap->u.lv_block_exception[idx].rdev_org = org_phys_dev;
lv_snap->lv_block_exception[idx].rsector_org = org_start; lv_snap->u.lv_block_exception[idx].rsector_org = org_start;
lvm_hash_link(lv_snap->lv_block_exception + idx, lvm_hash_link(lv_snap->u.lv_block_exception + idx,
org_phys_dev, org_start, lv_snap); org_phys_dev, org_start, lv_snap);
lv_snap->lv_remap_ptr = idx + 1; lv_snap->u.lv_remap_ptr = idx + 1;
if (lv_snap->lv_snapshot_use_rate > 0) { if (lv_snap->lv_snapshot_use_rate > 0) {
if (lv_snap->lv_remap_ptr * 100 / lv_snap->lv_remap_end >= lv_snap->lv_snapshot_use_rate) if (lv_snap->u.lv_remap_ptr * 100 / lv_snap->u.lv_remap_end >= lv_snap->lv_snapshot_use_rate)
wake_up_interruptible(&lv_snap->lv_snapshot_wait); wake_up_interruptible(&lv_snap->lv_snapshot_wait);
} }
return 0; return 0;
...@@ -462,7 +462,7 @@ int lvm_snapshot_alloc_hash_table(lv_t * lv) ...@@ -462,7 +462,7 @@ int lvm_snapshot_alloc_hash_table(lv_t * lv)
unsigned long buckets, max_buckets, size; unsigned long buckets, max_buckets, size;
struct list_head * hash; struct list_head * hash;
buckets = lv->lv_remap_end; buckets = lv->u.lv_remap_end;
max_buckets = calc_max_buckets(); max_buckets = calc_max_buckets();
buckets = min(buckets, max_buckets); buckets = min(buckets, max_buckets);
while (buckets & (buckets-1)) while (buckets & (buckets-1))
...@@ -531,10 +531,10 @@ int lvm_snapshot_alloc(lv_t * lv_snap) ...@@ -531,10 +531,10 @@ int lvm_snapshot_alloc(lv_t * lv_snap)
void lvm_snapshot_release(lv_t * lv) void lvm_snapshot_release(lv_t * lv)
{ {
if (lv->lv_block_exception) if (lv->u.lv_block_exception)
{ {
vfree(lv->lv_block_exception); vfree(lv->u.lv_block_exception);
lv->lv_block_exception = NULL; lv->u.lv_block_exception = NULL;
} }
if (lv->lv_snapshot_hash_table) if (lv->lv_snapshot_hash_table)
{ {
...@@ -578,8 +578,8 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap, ...@@ -578,8 +578,8 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap); COW_entries_per_pe = LVM_GET_COW_TABLE_ENTRIES_PER_PE(vg, lv_snap);
/* get physical addresse of destination chunk */ /* get physical addresse of destination chunk */
snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size; snap_pe_start = lv_snap->u.lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->u.lv_chunk_size;
blksize_snap = block_size(snap_phys_dev); blksize_snap = block_size(snap_phys_dev);
...@@ -595,7 +595,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap, ...@@ -595,7 +595,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10); blocks[0] = (snap_pe_start + COW_table_sector_offset) >> (blksize_snap >> 10);
/* store new COW_table entry */ /* store new COW_table entry */
be = lv_snap->lv_block_exception + idx; be = lv_snap->u.lv_block_exception + idx;
if(_pv_get_number(vg, be->rdev_org, &pvn)) if(_pv_get_number(vg, be->rdev_org, &pvn))
goto fail_pv_get_number; goto fail_pv_get_number;
...@@ -620,15 +620,15 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap, ...@@ -620,15 +620,15 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table) if (idx_COW_table % COW_entries_per_block == COW_entries_per_block - 1 || end_of_table)
{ {
/* don't go beyond the end */ /* don't go beyond the end */
if (idx + 1 >= lv_snap->lv_remap_end) goto out; if (idx + 1 >= lv_snap->u.lv_remap_end) goto out;
memset(lv_COW_table, 0, blksize_snap); memset(lv_COW_table, 0, blksize_snap);
if (end_of_table) if (end_of_table)
{ {
idx++; idx++;
snap_phys_dev = lv_snap->lv_block_exception[idx].rdev_new; snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
snap_pe_start = lv_snap->lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->lv_chunk_size; snap_pe_start = lv_snap->u.lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->u.lv_chunk_size;
blksize_snap = block_size(snap_phys_dev); blksize_snap = block_size(snap_phys_dev);
blocks[0] = snap_pe_start >> (blksize_snap >> 10); blocks[0] = snap_pe_start >> (blksize_snap >> 10);
} else blocks[0]++; } else blocks[0]++;
...@@ -664,7 +664,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap, ...@@ -664,7 +664,7 @@ static int _write_COW_table_block(vg_t *vg, lv_t *lv_snap,
static void _disable_snapshot(vg_t *vg, lv_t *lv) { static void _disable_snapshot(vg_t *vg, lv_t *lv) {
const char *err; const char *err;
lv->lv_block_exception[0].rsector_org = LVM_SNAPSHOT_DROPPED_SECTOR; lv->u.lv_block_exception[0].rsector_org = LVM_SNAPSHOT_DROPPED_SECTOR;
if(_write_COW_table_block(vg, lv, 0, &err) < 0) { if(_write_COW_table_block(vg, lv, 0, &err) < 0) {
printk(KERN_ERR "%s -- couldn't disable snapshot: %s\n", printk(KERN_ERR "%s -- couldn't disable snapshot: %s\n",
lvm_name, err); lvm_name, err);
......
...@@ -182,6 +182,9 @@ ...@@ -182,6 +182,9 @@
* 28/12/2001 - buffer_head -> bio * 28/12/2001 - buffer_head -> bio
* removed huge allocation of a lv_t on stack * removed huge allocation of a lv_t on stack
* (Anders Gustafsson) * (Anders Gustafsson)
* 07/01/2002 - fixed sizeof(lv_t) differences in user/kernel-space
* removed another huge allocation of a lv_t on stack
* (Anders Gustafsson)
* *
*/ */
...@@ -270,10 +273,10 @@ static int lvm_do_le_remap(vg_t *, void *); ...@@ -270,10 +273,10 @@ static int lvm_do_le_remap(vg_t *, void *);
static int lvm_do_pv_create(pv_t *, vg_t *, ulong); static int lvm_do_pv_create(pv_t *, vg_t *, ulong);
static int lvm_do_pv_remove(vg_t *, ulong); static int lvm_do_pv_remove(vg_t *, ulong);
static int lvm_do_lv_create(int, char *, lv_t *); static int lvm_do_lv_create(int, char *, userlv_t *);
static int lvm_do_lv_extend_reduce(int, char *, lv_t *); static int lvm_do_lv_extend_reduce(int, char *, userlv_t *);
static int lvm_do_lv_remove(int, char *, int); static int lvm_do_lv_remove(int, char *, int);
static int lvm_do_lv_rename(vg_t *, lv_req_t *, lv_t *); static int lvm_do_lv_rename(vg_t *, lv_req_t *, userlv_t *);
static int lvm_do_lv_status_byname(vg_t *r, void *); static int lvm_do_lv_status_byname(vg_t *r, void *);
static int lvm_do_lv_status_byindex(vg_t *, void *); static int lvm_do_lv_status_byindex(vg_t *, void *);
static int lvm_do_lv_status_bydev(vg_t *, void *); static int lvm_do_lv_status_bydev(vg_t *, void *);
...@@ -549,7 +552,7 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file, ...@@ -549,7 +552,7 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file,
int minor = minor(inode->i_rdev); int minor = minor(inode->i_rdev);
uint extendable, l, v; uint extendable, l, v;
void *arg = (void *) a; void *arg = (void *) a;
lv_t lv; userlv_t ulv;
vg_t* vg_ptr = vg[VG_CHR(minor)]; vg_t* vg_ptr = vg[VG_CHR(minor)];
/* otherwise cc will complain about unused variables */ /* otherwise cc will complain about unused variables */
...@@ -685,21 +688,21 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file, ...@@ -685,21 +688,21 @@ static int lvm_chr_ioctl(struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
if (command != LV_REMOVE) { if (command != LV_REMOVE) {
if (copy_from_user(&lv, lv_req.lv, sizeof(lv_t)) != 0) if (copy_from_user(&ulv, lv_req.lv, sizeof(userlv_t)) != 0)
return -EFAULT; return -EFAULT;
} }
switch (command) { switch (command) {
case LV_CREATE: case LV_CREATE:
return lvm_do_lv_create(minor, lv_req.lv_name, &lv); return lvm_do_lv_create(minor, lv_req.lv_name, &ulv);
case LV_EXTEND: case LV_EXTEND:
case LV_REDUCE: case LV_REDUCE:
return lvm_do_lv_extend_reduce(minor, lv_req.lv_name, &lv); return lvm_do_lv_extend_reduce(minor, lv_req.lv_name, &ulv);
case LV_REMOVE: case LV_REMOVE:
return lvm_do_lv_remove(minor, lv_req.lv_name, -1); return lvm_do_lv_remove(minor, lv_req.lv_name, -1);
case LV_RENAME: case LV_RENAME:
return lvm_do_lv_rename(vg_ptr, &lv_req, &lv); return lvm_do_lv_rename(vg_ptr, &lv_req, &ulv);
} }
...@@ -811,27 +814,27 @@ static int lvm_blk_open(struct inode *inode, struct file *file) ...@@ -811,27 +814,27 @@ static int lvm_blk_open(struct inode *inode, struct file *file)
LV_BLK(minor) < vg_ptr->lv_max) { LV_BLK(minor) < vg_ptr->lv_max) {
/* Check parallel LV spindown (LV remove) */ /* Check parallel LV spindown (LV remove) */
if (lv_ptr->lv_status & LV_SPINDOWN) return -EPERM; if (lv_ptr->u.lv_status & LV_SPINDOWN) return -EPERM;
/* Check inactive LV and open for read/write */ /* Check inactive LV and open for read/write */
/* We need to be able to "read" an inactive LV /* We need to be able to "read" an inactive LV
to re-activate it again */ to re-activate it again */
if ((file->f_mode & FMODE_WRITE) && if ((file->f_mode & FMODE_WRITE) &&
(!(lv_ptr->lv_status & LV_ACTIVE))) (!(lv_ptr->u.lv_status & LV_ACTIVE)))
return -EPERM; return -EPERM;
if (!(lv_ptr->lv_access & LV_WRITE) && if (!(lv_ptr->u.lv_access & LV_WRITE) &&
(file->f_mode & FMODE_WRITE)) (file->f_mode & FMODE_WRITE))
return -EACCES; return -EACCES;
/* be sure to increment VG counter */ /* be sure to increment VG counter */
if (lv_ptr->lv_open == 0) vg_ptr->lv_open++; if (lv_ptr->u.lv_open == 0) vg_ptr->lv_open++;
lv_ptr->lv_open++; lv_ptr->u.lv_open++;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
P_DEV("blk_open OK, LV size %d\n", lv_ptr->lv_size); P_DEV("blk_open OK, LV size %d\n", lv_ptr->u.lv_size);
return 0; return 0;
} }
...@@ -862,13 +865,13 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, ...@@ -862,13 +865,13 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
case BLKGETSIZE: case BLKGETSIZE:
/* return device size */ /* return device size */
P_IOCTL("BLKGETSIZE: %u\n", lv_ptr->lv_size); P_IOCTL("BLKGETSIZE: %u\n", lv_ptr->u.lv_size);
if (put_user(lv_ptr->lv_size, (unsigned long *)arg)) if (put_user(lv_ptr->u.lv_size, (unsigned long *)arg))
return -EFAULT; return -EFAULT;
break; break;
case BLKGETSIZE64: case BLKGETSIZE64:
if (put_user((u64)lv_ptr->lv_size << 9, (u64 *)arg)) if (put_user((u64)lv_ptr->u.lv_size << 9, (u64 *)arg))
return -EFAULT; return -EFAULT;
break; break;
...@@ -894,14 +897,14 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, ...@@ -894,14 +897,14 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
if ((long) arg < LVM_MIN_READ_AHEAD || if ((long) arg < LVM_MIN_READ_AHEAD ||
(long) arg > LVM_MAX_READ_AHEAD) (long) arg > LVM_MAX_READ_AHEAD)
return -EINVAL; return -EINVAL;
lv_ptr->lv_read_ahead = (long) arg; lv_ptr->u.lv_read_ahead = (long) arg;
break; break;
case BLKRAGET: case BLKRAGET:
/* get current read ahead setting */ /* get current read ahead setting */
P_IOCTL("BLKRAGET %d\n", lv_ptr->lv_read_ahead); P_IOCTL("BLKRAGET %d\n", lv_ptr->u.lv_read_ahead);
if (put_user(lv_ptr->lv_read_ahead, (long *)arg)) if (put_user(lv_ptr->u.lv_read_ahead, (long *)arg))
return -EFAULT; return -EFAULT;
break; break;
...@@ -915,7 +918,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, ...@@ -915,7 +918,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
unsigned char heads = 64; unsigned char heads = 64;
unsigned char sectors = 32; unsigned char sectors = 32;
long start = 0; long start = 0;
short cylinders = lv_ptr->lv_size / heads / sectors; short cylinders = lv_ptr->u.lv_size / heads / sectors;
if (copy_to_user((char *) &hd->heads, &heads, if (copy_to_user((char *) &hd->heads, &heads,
sizeof(heads)) != 0 || sizeof(heads)) != 0 ||
...@@ -936,26 +939,26 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, ...@@ -936,26 +939,26 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
case LV_SET_ACCESS: case LV_SET_ACCESS:
/* set access flags of a logical volume */ /* set access flags of a logical volume */
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!capable(CAP_SYS_ADMIN)) return -EACCES;
lv_ptr->lv_access = (ulong) arg; lv_ptr->u.lv_access = (ulong) arg;
if ( lv_ptr->lv_access & LV_WRITE) if ( lv_ptr->u.lv_access & LV_WRITE)
set_device_ro(lv_ptr->lv_dev, 0); set_device_ro(lv_ptr->u.lv_dev, 0);
else else
set_device_ro(lv_ptr->lv_dev, 1); set_device_ro(lv_ptr->u.lv_dev, 1);
break; break;
case LV_SET_STATUS: case LV_SET_STATUS:
/* set status flags of a logical volume */ /* set status flags of a logical volume */
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (!((ulong) arg & LV_ACTIVE) && lv_ptr->lv_open > 1) if (!((ulong) arg & LV_ACTIVE) && lv_ptr->u.lv_open > 1)
return -EPERM; return -EPERM;
lv_ptr->lv_status = (ulong) arg; lv_ptr->u.lv_status = (ulong) arg;
break; break;
case LV_BMAP: case LV_BMAP:
/* turn logical block into (dev_t, block). non privileged. */ /* turn logical block into (dev_t, block). non privileged. */
/* don't bmap a snapshot, since the mapping can change */ /* don't bmap a snapshot, since the mapping can change */
if(lv_ptr->lv_access & LV_SNAPSHOT) if(lv_ptr->u.lv_access & LV_SNAPSHOT)
return -EPERM; return -EPERM;
return lvm_user_bmap(inode, (struct lv_bmap *) arg); return lvm_user_bmap(inode, (struct lv_bmap *) arg);
...@@ -963,7 +966,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file, ...@@ -963,7 +966,7 @@ static int lvm_blk_ioctl(struct inode *inode, struct file *file,
case LV_SET_ALLOCATION: case LV_SET_ALLOCATION:
/* set allocation flags of a logical volume */ /* set allocation flags of a logical volume */
if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (!capable(CAP_SYS_ADMIN)) return -EACCES;
lv_ptr->lv_allocation = (ulong) arg; lv_ptr->u.lv_allocation = (ulong) arg;
break; break;
case LV_SNAPSHOT_USE_RATE: case LV_SNAPSHOT_USE_RATE:
...@@ -992,8 +995,8 @@ static int lvm_blk_close(struct inode *inode, struct file *file) ...@@ -992,8 +995,8 @@ static int lvm_blk_close(struct inode *inode, struct file *file)
P_DEV("blk_close MINOR: %d VG#: %d LV#: %d\n", P_DEV("blk_close MINOR: %d VG#: %d LV#: %d\n",
minor, VG_BLK(minor), LV_BLK(minor)); minor, VG_BLK(minor), LV_BLK(minor));
if (lv_ptr->lv_open == 1) vg_ptr->lv_open--; if (lv_ptr->u.lv_open == 1) vg_ptr->lv_open--;
lv_ptr->lv_open--; lv_ptr->u.lv_open--;
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
...@@ -1004,7 +1007,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg) ...@@ -1004,7 +1007,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg)
{ {
lv_snapshot_use_rate_req_t lv_rate_req; lv_snapshot_use_rate_req_t lv_rate_req;
if (!(lv->lv_access & LV_SNAPSHOT)) if (!(lv->u.lv_access & LV_SNAPSHOT))
return -EPERM; return -EPERM;
if (copy_from_user(&lv_rate_req, arg, sizeof(lv_rate_req))) if (copy_from_user(&lv_rate_req, arg, sizeof(lv_rate_req)))
...@@ -1016,7 +1019,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg) ...@@ -1016,7 +1019,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg)
switch (lv_rate_req.block) { switch (lv_rate_req.block) {
case 0: case 0:
lv->lv_snapshot_use_rate = lv_rate_req.rate; lv->lv_snapshot_use_rate = lv_rate_req.rate;
if (lv->lv_remap_ptr * 100 / lv->lv_remap_end < if (lv->u.lv_remap_ptr * 100 / lv->u.lv_remap_end <
lv->lv_snapshot_use_rate) lv->lv_snapshot_use_rate)
interruptible_sleep_on(&lv->lv_snapshot_wait); interruptible_sleep_on(&lv->lv_snapshot_wait);
break; break;
...@@ -1027,7 +1030,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg) ...@@ -1027,7 +1030,7 @@ static int lvm_get_snapshot_use_rate(lv_t *lv, void *arg)
default: default:
return -EINVAL; return -EINVAL;
} }
lv_rate_req.rate = lv->lv_remap_ptr * 100 / lv->lv_remap_end; lv_rate_req.rate = lv->u.lv_remap_ptr * 100 / lv->u.lv_remap_end;
return copy_to_user(arg, &lv_rate_req, return copy_to_user(arg, &lv_rate_req,
sizeof(lv_rate_req)) ? -EFAULT : 0; sizeof(lv_rate_req)) ? -EFAULT : 0;
...@@ -1044,7 +1047,7 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result) ...@@ -1044,7 +1047,7 @@ static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
memset(&bio,0,sizeof(bio)); memset(&bio,0,sizeof(bio));
bio.bi_dev = inode->i_rdev; bio.bi_dev = inode->i_rdev;
bio.bi_size = lvm_get_blksize(bio.bi_dev); /* NEEDED by bio_sectors */ bio.bi_size = block_size(bio.bi_dev); /* NEEDED by bio_sectors */
bio.bi_sector = block * bio_sectors(&bio); bio.bi_sector = block * bio_sectors(&bio);
bio.bi_rw = READ; bio.bi_rw = READ;
if ((err=lvm_map(&bio)) < 0) { if ((err=lvm_map(&bio)) < 0) {
...@@ -1134,18 +1137,18 @@ static int lvm_map(struct bio *bi) ...@@ -1134,18 +1137,18 @@ static int lvm_map(struct bio *bi)
int rw = bio_rw(bi); int rw = bio_rw(bi);
down_read(&lv->lv_lock); down_read(&lv->lv_lock);
if (!(lv->lv_status & LV_ACTIVE)) { if (!(lv->u.lv_status & LV_ACTIVE)) {
printk(KERN_ALERT printk(KERN_ALERT
"%s - lvm_map: ll_rw_blk for inactive LV %s\n", "%s - lvm_map: ll_rw_blk for inactive LV %s\n",
lvm_name, lv->lv_name); lvm_name, lv->u.lv_name);
goto bad; goto bad;
} }
if ((rw == WRITE || rw == WRITEA) && if ((rw == WRITE || rw == WRITEA) &&
!(lv->lv_access & LV_WRITE)) { !(lv->u.lv_access & LV_WRITE)) {
printk(KERN_CRIT printk(KERN_CRIT
"%s - lvm_map: ll_rw_blk write for readonly LV %s\n", "%s - lvm_map: ll_rw_blk write for readonly LV %s\n",
lvm_name, lv->lv_name); lvm_name, lv->u.lv_name);
goto bad; goto bad;
} }
...@@ -1154,7 +1157,7 @@ static int lvm_map(struct bio *bi) ...@@ -1154,7 +1157,7 @@ static int lvm_map(struct bio *bi)
kdevname(bi->bi_dev), kdevname(bi->bi_dev),
rsector_org, size); rsector_org, size);
if (rsector_org + size > lv->lv_size) { if (rsector_org + size > lv->u.lv_size) {
printk(KERN_ALERT printk(KERN_ALERT
"%s - lvm_map access beyond end of device; *rsector: " "%s - lvm_map access beyond end of device; *rsector: "
"%lu or size: %lu wrong for minor: %2d\n", "%lu or size: %lu wrong for minor: %2d\n",
...@@ -1163,39 +1166,39 @@ static int lvm_map(struct bio *bi) ...@@ -1163,39 +1166,39 @@ static int lvm_map(struct bio *bi)
} }
if (lv->lv_stripes < 2) { /* linear mapping */ if (lv->u.lv_stripes < 2) { /* linear mapping */
/* get the index */ /* get the index */
index = rsector_org / vg_this->pe_size; index = rsector_org / vg_this->pe_size;
pe_start = lv->lv_current_pe[index].pe; pe_start = lv->u.lv_current_pe[index].pe;
rsector_map = lv->lv_current_pe[index].pe + rsector_map = lv->u.lv_current_pe[index].pe +
(rsector_org % vg_this->pe_size); (rsector_org % vg_this->pe_size);
rdev_map = lv->lv_current_pe[index].dev; rdev_map = lv->u.lv_current_pe[index].dev;
P_MAP("lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n", P_MAP("u.lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n",
index, lv->lv_current_pe[index].pe, index, lv->u.lv_current_pe[index].pe,
kdevname(rdev_map), rsector_map); kdevname(rdev_map), rsector_map);
} else { /* striped mapping */ } else { /* striped mapping */
ulong stripe_index; ulong stripe_index;
ulong stripe_length; ulong stripe_length;
stripe_length = vg_this->pe_size * lv->lv_stripes; stripe_length = vg_this->pe_size * lv->u.lv_stripes;
stripe_index = (rsector_org % stripe_length) / stripe_index = (rsector_org % stripe_length) /
lv->lv_stripesize; lv->u.lv_stripesize;
index = rsector_org / stripe_length + index = rsector_org / stripe_length +
(stripe_index % lv->lv_stripes) * (stripe_index % lv->u.lv_stripes) *
(lv->lv_allocated_le / lv->lv_stripes); (lv->u.lv_allocated_le / lv->u.lv_stripes);
pe_start = lv->lv_current_pe[index].pe; pe_start = lv->u.lv_current_pe[index].pe;
rsector_map = lv->lv_current_pe[index].pe + rsector_map = lv->u.lv_current_pe[index].pe +
(rsector_org % stripe_length) - (rsector_org % stripe_length) -
(stripe_index % lv->lv_stripes) * lv->lv_stripesize - (stripe_index % lv->u.lv_stripes) * lv->u.lv_stripesize -
stripe_index / lv->lv_stripes * stripe_index / lv->u.lv_stripes *
(lv->lv_stripes - 1) * lv->lv_stripesize; (lv->u.lv_stripes - 1) * lv->u.lv_stripesize;
rdev_map = lv->lv_current_pe[index].dev; rdev_map = lv->u.lv_current_pe[index].dev;
P_MAP("lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n" P_MAP("u.lv_current_pe[%ld].pe: %d rdev: %s rsector:%ld\n"
"stripe_length: %ld stripe_index: %ld\n", "stripe_length: %ld stripe_index: %ld\n",
index, lv->lv_current_pe[index].pe, kdevname(rdev_map), index, lv->u.lv_current_pe[index].pe, kdevname(rdev_map),
rsector_map, stripe_length, stripe_index); rsector_map, stripe_length, stripe_index);
} }
...@@ -1212,16 +1215,16 @@ static int lvm_map(struct bio *bi) ...@@ -1212,16 +1215,16 @@ static int lvm_map(struct bio *bi)
return 0; return 0;
} }
lv->lv_current_pe[index].writes++; /* statistic */ lv->u.lv_current_pe[index].writes++; /* statistic */
} else } else
lv->lv_current_pe[index].reads++; /* statistic */ lv->u.lv_current_pe[index].reads++; /* statistic */
/* snapshot volume exception handling on physical device address base */ /* snapshot volume exception handling on physical device address base */
if (!(lv->lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG))) if (!(lv->u.lv_access & (LV_SNAPSHOT|LV_SNAPSHOT_ORG)))
goto out; goto out;
if (lv->lv_access & LV_SNAPSHOT) { /* remap snapshot */ if (lv->u.lv_access & LV_SNAPSHOT) { /* remap snapshot */
if (lv->lv_block_exception) if (lv->u.lv_block_exception)
lvm_snapshot_remap_block(&rdev_map, &rsector_map, lvm_snapshot_remap_block(&rdev_map, &rsector_map,
pe_start, lv); pe_start, lv);
else else
...@@ -1232,10 +1235,10 @@ static int lvm_map(struct bio *bi) ...@@ -1232,10 +1235,10 @@ static int lvm_map(struct bio *bi)
/* start with first snapshot and loop through all of /* start with first snapshot and loop through all of
them */ them */
for (snap = lv->lv_snapshot_next; snap; for (snap = lv->u.lv_snapshot_next; snap;
snap = snap->lv_snapshot_next) { snap = snap->u.lv_snapshot_next) {
/* Check for inactive snapshot */ /* Check for inactive snapshot */
if (!(snap->lv_status & LV_ACTIVE)) if (!(snap->u.lv_status & LV_ACTIVE))
continue; continue;
/* Serializes the COW with the accesses to the /* Serializes the COW with the accesses to the
...@@ -1274,8 +1277,8 @@ void lvm_hd_name(char *buf, int minor) ...@@ -1274,8 +1277,8 @@ void lvm_hd_name(char *buf, int minor)
if (vg[VG_BLK(minor)] == NULL || if (vg[VG_BLK(minor)] == NULL ||
(lv_ptr = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]) == NULL) (lv_ptr = vg[VG_BLK(minor)]->lv[LV_BLK(minor)]) == NULL)
return; return;
len = strlen(lv_ptr->lv_name) - 5; len = strlen(lv_ptr->u.lv_name) - 5;
memcpy(buf, &lv_ptr->lv_name[5], len); memcpy(buf, &lv_ptr->u.lv_name[5], len);
buf[len] = 0; buf[len] = 0;
return; return;
} }
...@@ -1307,7 +1310,7 @@ static int lvm_do_lock_lvm(void) ...@@ -1307,7 +1310,7 @@ static int lvm_do_lock_lvm(void)
P_DEV("lvm_do_lock_lvm: locked by pid %d ...\n", lock); P_DEV("lvm_do_lock_lvm: locked by pid %d ...\n", lock);
spin_unlock(&lvm_lock); spin_unlock(&lvm_lock);
interruptible_sleep_on(&lvm_wait); interruptible_sleep_on(&lvm_wait);
if (current->sigpending != 0) if (signal_pending(current))
return -EINTR; return -EINTR;
#ifdef LVM_TOTAL_RESET #ifdef LVM_TOTAL_RESET
if (lvm_reset_spindown > 0) if (lvm_reset_spindown > 0)
...@@ -1360,7 +1363,7 @@ static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg) ...@@ -1360,7 +1363,7 @@ static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
return -EBUSY; return -EBUSY;
} }
/* Should we do to_kdev_t() on the pv_dev and lv_dev??? */ /* Should we do to_kdev_t() on the pv_dev and u.lv_dev??? */
pe_lock_req.lock = LOCK_PE; pe_lock_req.lock = LOCK_PE;
pe_lock_req.data.lv_dev = new_lock.data.lv_dev; pe_lock_req.data.lv_dev = new_lock.data.lv_dev;
pe_lock_req.data.pv_dev = new_lock.data.pv_dev; pe_lock_req.data.pv_dev = new_lock.data.pv_dev;
...@@ -1407,16 +1410,16 @@ static int lvm_do_le_remap(vg_t *vg_ptr, void *arg) ...@@ -1407,16 +1410,16 @@ static int lvm_do_le_remap(vg_t *vg_ptr, void *arg)
for (l = 0; l < vg_ptr->lv_max; l++) { for (l = 0; l < vg_ptr->lv_max; l++) {
lv_ptr = vg_ptr->lv[l]; lv_ptr = vg_ptr->lv[l];
if (lv_ptr != NULL && if (lv_ptr != NULL &&
strcmp(lv_ptr->lv_name, strcmp(lv_ptr->u.lv_name,
le_remap_req.lv_name) == 0) { le_remap_req.lv_name) == 0) {
for (le = 0; le < lv_ptr->lv_allocated_le; le++) { for (le = 0; le < lv_ptr->u.lv_allocated_le; le++) {
if (kdev_same(lv_ptr->lv_current_pe[le].dev, if (kdev_same(lv_ptr->u.lv_current_pe[le].dev,
le_remap_req.old_dev) && le_remap_req.old_dev) &&
lv_ptr->lv_current_pe[le].pe == lv_ptr->u.lv_current_pe[le].pe ==
le_remap_req.old_pe) { le_remap_req.old_pe) {
lv_ptr->lv_current_pe[le].dev = lv_ptr->u.lv_current_pe[le].dev =
le_remap_req.new_dev; le_remap_req.new_dev;
lv_ptr->lv_current_pe[le].pe = lv_ptr->u.lv_current_pe[le].pe =
le_remap_req.new_pe; le_remap_req.new_pe;
__update_hardsectsize(lv_ptr); __update_hardsectsize(lv_ptr);
...@@ -1532,7 +1535,7 @@ static int lvm_do_vg_create(void *arg, int minor) ...@@ -1532,7 +1535,7 @@ static int lvm_do_vg_create(void *arg, int minor)
/* user space address */ /* user space address */
if ((lvp = vg_ptr->lv[l]) != NULL) { if ((lvp = vg_ptr->lv[l]) != NULL) {
if (copy_from_user(tmplv, lvp, sizeof(lv_t)) != 0) { if (copy_from_user(tmplv, lvp, sizeof(userlv_t)) != 0) {
P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n", P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n",
lvp, sizeof(lv_t)); lvp, sizeof(lv_t));
lvm_do_vg_remove(minor); lvm_do_vg_remove(minor);
...@@ -1540,7 +1543,7 @@ static int lvm_do_vg_create(void *arg, int minor) ...@@ -1540,7 +1543,7 @@ static int lvm_do_vg_create(void *arg, int minor)
kfree(tmplv); kfree(tmplv);
return -EFAULT; return -EFAULT;
} }
if ( tmplv->lv_access & LV_SNAPSHOT) { if ( tmplv->u.lv_access & LV_SNAPSHOT) {
snap_lv_ptr[ls] = lvp; snap_lv_ptr[ls] = lvp;
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
ls++; ls++;
...@@ -1548,7 +1551,7 @@ static int lvm_do_vg_create(void *arg, int minor) ...@@ -1548,7 +1551,7 @@ static int lvm_do_vg_create(void *arg, int minor)
} }
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
/* only create original logical volumes for now */ /* only create original logical volumes for now */
if (lvm_do_lv_create(minor, tmplv->lv_name, tmplv) != 0) { if (lvm_do_lv_create(minor, tmplv->u.lv_name, &tmplv->u) != 0) {
lvm_do_vg_remove(minor); lvm_do_vg_remove(minor);
vfree(snap_lv_ptr); vfree(snap_lv_ptr);
kfree(tmplv); kfree(tmplv);
...@@ -1561,13 +1564,13 @@ static int lvm_do_vg_create(void *arg, int minor) ...@@ -1561,13 +1564,13 @@ static int lvm_do_vg_create(void *arg, int minor)
in place during first path above */ in place during first path above */
for (l = 0; l < ls; l++) { for (l = 0; l < ls; l++) {
lv_t *lvp = snap_lv_ptr[l]; lv_t *lvp = snap_lv_ptr[l];
if (copy_from_user(tmplv, lvp, sizeof(lv_t)) != 0) { if (copy_from_user(tmplv, lvp, sizeof(userlv_t)) != 0) {
lvm_do_vg_remove(minor); lvm_do_vg_remove(minor);
vfree(snap_lv_ptr); vfree(snap_lv_ptr);
kfree(tmplv); kfree(tmplv);
return -EFAULT; return -EFAULT;
} }
if (lvm_do_lv_create(minor, tmplv->lv_name, tmplv) != 0) { if (lvm_do_lv_create(minor, tmplv->u.lv_name, &tmplv->u) != 0) {
lvm_do_vg_remove(minor); lvm_do_vg_remove(minor);
vfree(snap_lv_ptr); vfree(snap_lv_ptr);
kfree(tmplv); kfree(tmplv);
...@@ -1666,15 +1669,15 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg) ...@@ -1666,15 +1669,15 @@ static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg)
for ( l = 0; l < vg_ptr->lv_max; l++) for ( l = 0; l < vg_ptr->lv_max; l++)
{ {
if ((lv_ptr = vg_ptr->lv[l]) == NULL) continue; if ((lv_ptr = vg_ptr->lv[l]) == NULL) continue;
strncpy(lv_ptr->vg_name, vg_name, sizeof ( vg_name)); strncpy(lv_ptr->u.vg_name, vg_name, sizeof ( vg_name));
ptr = strrchr(lv_ptr->lv_name, '/'); ptr = strrchr(lv_ptr->u.lv_name, '/');
if (ptr == NULL) ptr = lv_ptr->lv_name; if (ptr == NULL) ptr = lv_ptr->u.lv_name;
strncpy(lv_name, ptr, sizeof ( lv_name)); strncpy(lv_name, ptr, sizeof ( lv_name));
len = sizeof(LVM_DIR_PREFIX); len = sizeof(LVM_DIR_PREFIX);
strcpy(lv_ptr->lv_name, LVM_DIR_PREFIX); strcpy(lv_ptr->u.lv_name, LVM_DIR_PREFIX);
strncat(lv_ptr->lv_name, vg_name, NAME_LEN - len); strncat(lv_ptr->u.lv_name, vg_name, NAME_LEN - len);
len += strlen ( vg_name); len += strlen ( vg_name);
strncat(lv_ptr->lv_name, lv_name, NAME_LEN - len); strncat(lv_ptr->u.lv_name, lv_name, NAME_LEN - len);
} }
for ( p = 0; p < vg_ptr->pv_max; p++) for ( p = 0; p < vg_ptr->pv_max; p++)
{ {
...@@ -1716,7 +1719,7 @@ static int lvm_do_vg_remove(int minor) ...@@ -1716,7 +1719,7 @@ static int lvm_do_vg_remove(int minor)
/* first free snapshot logical volumes */ /* first free snapshot logical volumes */
for (i = 0; i < vg_ptr->lv_max; i++) { for (i = 0; i < vg_ptr->lv_max; i++) {
if (vg_ptr->lv[i] != NULL && if (vg_ptr->lv[i] != NULL &&
vg_ptr->lv[i]->lv_access & LV_SNAPSHOT) { vg_ptr->lv[i]->u.lv_access & LV_SNAPSHOT) {
lvm_do_lv_remove(minor, NULL, i); lvm_do_lv_remove(minor, NULL, i);
current->state = TASK_UNINTERRUPTIBLE; current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(1); schedule_timeout(1);
...@@ -1819,8 +1822,8 @@ static void __update_hardsectsize(lv_t *lv) { ...@@ -1819,8 +1822,8 @@ static void __update_hardsectsize(lv_t *lv) {
int le, e; int le, e;
int max_hardsectsize = 0, hardsectsize; int max_hardsectsize = 0, hardsectsize;
for (le = 0; le < lv->lv_allocated_le; le++) { for (le = 0; le < lv->u.lv_allocated_le; le++) {
hardsectsize = get_hardsect_size(lv->lv_current_pe[le].dev); hardsectsize = get_hardsect_size(lv->u.lv_current_pe[le].dev);
if (hardsectsize == 0) if (hardsectsize == 0)
hardsectsize = 512; hardsectsize = 512;
if (hardsectsize > max_hardsectsize) if (hardsectsize > max_hardsectsize)
...@@ -1828,10 +1831,10 @@ static void __update_hardsectsize(lv_t *lv) { ...@@ -1828,10 +1831,10 @@ static void __update_hardsectsize(lv_t *lv) {
} }
/* only perform this operation on active snapshots */ /* only perform this operation on active snapshots */
if ((lv->lv_access & LV_SNAPSHOT) && if ((lv->u.lv_access & LV_SNAPSHOT) &&
(lv->lv_status & LV_ACTIVE)) { (lv->u.lv_status & LV_ACTIVE)) {
for (e = 0; e < lv->lv_remap_end; e++) { for (e = 0; e < lv->u.lv_remap_end; e++) {
hardsectsize = get_hardsect_size( lv->lv_block_exception[e].rdev_new); hardsectsize = get_hardsect_size( lv->u.lv_block_exception[e].rdev_new);
if (hardsectsize == 0) if (hardsectsize == 0)
hardsectsize = 512; hardsectsize = 512;
if (hardsectsize > max_hardsectsize) if (hardsectsize > max_hardsectsize)
...@@ -1843,31 +1846,31 @@ static void __update_hardsectsize(lv_t *lv) { ...@@ -1843,31 +1846,31 @@ static void __update_hardsectsize(lv_t *lv) {
/* /*
* character device support function logical volume create * character device support function logical volume create
*/ */
static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) static int lvm_do_lv_create(int minor, char *lv_name, userlv_t *ulv)
{ {
int e, ret, l, le, l_new, p, size, activate = 1; int e, ret, l, le, l_new, p, size, activate = 1;
ulong lv_status_save; ulong lv_status_save;
lv_block_exception_t *lvbe = lv->lv_block_exception; lv_block_exception_t *lvbe = ulv->lv_block_exception;
vg_t *vg_ptr = vg[VG_CHR(minor)]; vg_t *vg_ptr = vg[VG_CHR(minor)];
lv_t *lv_ptr = NULL; lv_t *lv_ptr = NULL;
pe_t *pep; pe_t *pep;
if (!(pep = lv->lv_current_pe)) if (!(pep = ulv->lv_current_pe))
return -EINVAL; return -EINVAL;
if (_sectors_to_k(lv->lv_chunk_size) > LVM_SNAPSHOT_MAX_CHUNK) if (_sectors_to_k(ulv->lv_chunk_size) > LVM_SNAPSHOT_MAX_CHUNK)
return -EINVAL; return -EINVAL;
for (l = 0; l < vg_ptr->lv_cur; l++) { for (l = 0; l < vg_ptr->lv_cur; l++) {
if (vg_ptr->lv[l] != NULL && if (vg_ptr->lv[l] != NULL &&
strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0) strcmp(vg_ptr->lv[l]->u.lv_name, lv_name) == 0)
return -EEXIST; return -EEXIST;
} }
/* in case of lv_remove(), lv_create() pair */ /* in case of lv_remove(), lv_create() pair */
l_new = -1; l_new = -1;
if (vg_ptr->lv[lv->lv_number] == NULL) if (vg_ptr->lv[ulv->lv_number] == NULL)
l_new = lv->lv_number; l_new = ulv->lv_number;
else { else {
for (l = 0; l < vg_ptr->lv_max; l++) { for (l = 0; l < vg_ptr->lv_max; l++) {
if (vg_ptr->lv[l] == NULL) if (vg_ptr->lv[l] == NULL)
...@@ -1883,14 +1886,14 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1883,14 +1886,14 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
return -ENOMEM; return -ENOMEM;
} }
/* copy preloaded LV */ /* copy preloaded LV */
memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t)); memcpy((char *) lv_ptr, (char *) ulv, sizeof(userlv_t));
lv_status_save = lv_ptr->lv_status; lv_status_save = lv_ptr->u.lv_status;
lv_ptr->lv_status &= ~LV_ACTIVE; lv_ptr->u.lv_status &= ~LV_ACTIVE;
lv_ptr->lv_snapshot_org = NULL; lv_ptr->u.lv_snapshot_org = NULL;
lv_ptr->lv_snapshot_prev = NULL; lv_ptr->u.lv_snapshot_prev = NULL;
lv_ptr->lv_snapshot_next = NULL; lv_ptr->u.lv_snapshot_next = NULL;
lv_ptr->lv_block_exception = NULL; lv_ptr->u.lv_block_exception = NULL;
lv_ptr->lv_iobuf = NULL; lv_ptr->lv_iobuf = NULL;
lv_ptr->lv_COW_table_iobuf = NULL; lv_ptr->lv_COW_table_iobuf = NULL;
lv_ptr->lv_snapshot_hash_table = NULL; lv_ptr->lv_snapshot_hash_table = NULL;
...@@ -1904,10 +1907,10 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1904,10 +1907,10 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
/* get the PE structures from user space if this /* get the PE structures from user space if this
is not a snapshot logical volume */ is not a snapshot logical volume */
if (!(lv_ptr->lv_access & LV_SNAPSHOT)) { if (!(lv_ptr->u.lv_access & LV_SNAPSHOT)) {
size = lv_ptr->lv_allocated_le * sizeof(pe_t); size = lv_ptr->u.lv_allocated_le * sizeof(pe_t);
if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) { if ((lv_ptr->u.lv_current_pe = vmalloc(size)) == NULL) {
printk(KERN_CRIT printk(KERN_CRIT
"%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte " "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte "
"at line %d\n", "at line %d\n",
...@@ -1917,30 +1920,30 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1917,30 +1920,30 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return -ENOMEM; return -ENOMEM;
} }
if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) { if (copy_from_user(lv_ptr->u.lv_current_pe, pep, size)) {
P_IOCTL("ERROR: copying PE ptr %p (%d bytes)\n", P_IOCTL("ERROR: copying PE ptr %p (%d bytes)\n",
pep, sizeof(size)); pep, sizeof(size));
vfree(lv_ptr->lv_current_pe); vfree(lv_ptr->u.lv_current_pe);
kfree(lv_ptr); kfree(lv_ptr);
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return -EFAULT; return -EFAULT;
} }
/* correct the PE count in PVs */ /* correct the PE count in PVs */
for (le = 0; le < lv_ptr->lv_allocated_le; le++) { for (le = 0; le < lv_ptr->u.lv_allocated_le; le++) {
vg_ptr->pe_allocated++; vg_ptr->pe_allocated++;
for (p = 0; p < vg_ptr->pv_cur; p++) { for (p = 0; p < vg_ptr->pv_cur; p++) {
if (kdev_same(vg_ptr->pv[p]->pv_dev, if (kdev_same(vg_ptr->pv[p]->pv_dev,
lv_ptr->lv_current_pe[le].dev)) lv_ptr->u.lv_current_pe[le].dev))
vg_ptr->pv[p]->pe_allocated++; vg_ptr->pv[p]->pe_allocated++;
} }
} }
} else { } else {
/* Get snapshot exception data and block list */ /* Get snapshot exception data and block list */
if (lvbe != NULL) { if (lvbe != NULL) {
lv_ptr->lv_snapshot_org = lv_ptr->u.lv_snapshot_org =
vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)]; vg_ptr->lv[LV_BLK(lv_ptr->u.lv_snapshot_minor)];
if (lv_ptr->lv_snapshot_org != NULL) { if (lv_ptr->u.lv_snapshot_org != NULL) {
size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t); size = lv_ptr->u.lv_remap_end * sizeof(lv_block_exception_t);
if(!size) { if(!size) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -1950,7 +1953,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1950,7 +1953,7 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
return -EINVAL; return -EINVAL;
} }
if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) { if ((lv_ptr->u.lv_block_exception = vmalloc(size)) == NULL) {
printk(KERN_CRIT printk(KERN_CRIT
"%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION " "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION "
"of %d byte at line %d\n", "of %d byte at line %d\n",
...@@ -1961,14 +1964,14 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1961,14 +1964,14 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return -ENOMEM; return -ENOMEM;
} }
if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) { if (copy_from_user(lv_ptr->u.lv_block_exception, lvbe, size)) {
vfree(lv_ptr->lv_block_exception); vfree(lv_ptr->u.lv_block_exception);
kfree(lv_ptr); kfree(lv_ptr);
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return -EFAULT; return -EFAULT;
} }
if(lv_ptr->lv_block_exception[0].rsector_org == if(lv_ptr->u.lv_block_exception[0].rsector_org ==
LVM_SNAPSHOT_DROPPED_SECTOR) LVM_SNAPSHOT_DROPPED_SECTOR)
{ {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -1979,36 +1982,36 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -1979,36 +1982,36 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
/* point to the original logical volume */ /* point to the original logical volume */
lv_ptr = lv_ptr->lv_snapshot_org; lv_ptr = lv_ptr->u.lv_snapshot_org;
lv_ptr->lv_snapshot_minor = 0; lv_ptr->u.lv_snapshot_minor = 0;
lv_ptr->lv_snapshot_org = lv_ptr; lv_ptr->u.lv_snapshot_org = lv_ptr;
/* our new one now back points to the previous last in the chain /* our new one now back points to the previous last in the chain
which can be the original logical volume */ which can be the original logical volume */
lv_ptr = vg_ptr->lv[l]; lv_ptr = vg_ptr->lv[l];
/* now lv_ptr points to our new last snapshot logical volume */ /* now lv_ptr points to our new last snapshot logical volume */
lv_ptr->lv_current_pe = lv_ptr->lv_snapshot_org->lv_current_pe; lv_ptr->u.lv_current_pe = lv_ptr->u.lv_snapshot_org->u.lv_current_pe;
lv_ptr->lv_allocated_snapshot_le = lv_ptr->lv_allocated_le; lv_ptr->lv_allocated_snapshot_le = lv_ptr->u.lv_allocated_le;
lv_ptr->lv_allocated_le = lv_ptr->lv_snapshot_org->lv_allocated_le; lv_ptr->u.lv_allocated_le = lv_ptr->u.lv_snapshot_org->u.lv_allocated_le;
lv_ptr->lv_current_le = lv_ptr->lv_snapshot_org->lv_current_le; lv_ptr->u.lv_current_le = lv_ptr->u.lv_snapshot_org->u.lv_current_le;
lv_ptr->lv_size = lv_ptr->lv_snapshot_org->lv_size; lv_ptr->u.lv_size = lv_ptr->u.lv_snapshot_org->u.lv_size;
lv_ptr->lv_stripes = lv_ptr->lv_snapshot_org->lv_stripes; lv_ptr->u.lv_stripes = lv_ptr->u.lv_snapshot_org->u.lv_stripes;
lv_ptr->lv_stripesize = lv_ptr->lv_snapshot_org->lv_stripesize; lv_ptr->u.lv_stripesize = lv_ptr->u.lv_snapshot_org->u.lv_stripesize;
/* Update the VG PE(s) used by snapshot reserve space. */ /* Update the VG PE(s) used by snapshot reserve space. */
vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le; vg_ptr->pe_allocated += lv_ptr->lv_allocated_snapshot_le;
if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0) if ((ret = lvm_snapshot_alloc(lv_ptr)) != 0)
{ {
vfree(lv_ptr->lv_block_exception); vfree(lv_ptr->u.lv_block_exception);
kfree(lv_ptr); kfree(lv_ptr);
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return ret; return ret;
} }
for ( e = 0; e < lv_ptr->lv_remap_ptr; e++) for ( e = 0; e < lv_ptr->u.lv_remap_ptr; e++)
lvm_hash_link (lv_ptr->lv_block_exception + e, lvm_hash_link (lv_ptr->u.lv_block_exception + e,
lv_ptr->lv_block_exception[e].rdev_org, lv_ptr->u.lv_block_exception[e].rdev_org,
lv_ptr->lv_block_exception[e].rsector_org, lv_ptr); lv_ptr->u.lv_block_exception[e].rsector_org, lv_ptr);
/* need to fill the COW exception table data /* need to fill the COW exception table data
into the page for disk i/o */ into the page for disk i/o */
if(lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr)) { if(lvm_snapshot_fill_COW_page(vg_ptr, lv_ptr)) {
...@@ -2027,62 +2030,62 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv) ...@@ -2027,62 +2030,62 @@ static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv)
vg_ptr->lv[l] = NULL; vg_ptr->lv[l] = NULL;
return -EINVAL; return -EINVAL;
} }
} /* if ( vg[VG_CHR(minor)]->lv[l]->lv_access & LV_SNAPSHOT) */ } /* if ( vg[VG_CHR(minor)]->lv[l]->u.lv_access & LV_SNAPSHOT) */
lv_ptr = vg_ptr->lv[l]; lv_ptr = vg_ptr->lv[l];
lvm_gendisk.part[minor(lv_ptr->lv_dev)].start_sect = 0; lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].start_sect = 0;
lvm_gendisk.part[minor(lv_ptr->lv_dev)].nr_sects = lv_ptr->lv_size; lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].nr_sects = lv_ptr->u.lv_size;
lvm_size[minor(lv_ptr->lv_dev)] = lv_ptr->lv_size >> 1; lvm_size[minor(lv_ptr->u.lv_dev)] = lv_ptr->u.lv_size >> 1;
vg_lv_map[minor(lv_ptr->lv_dev)].vg_number = vg_ptr->vg_number; vg_lv_map[minor(lv_ptr->u.lv_dev)].vg_number = vg_ptr->vg_number;
vg_lv_map[minor(lv_ptr->lv_dev)].lv_number = lv_ptr->lv_number; vg_lv_map[minor(lv_ptr->u.lv_dev)].lv_number = lv_ptr->u.lv_number;
LVM_CORRECT_READ_AHEAD(lv_ptr->lv_read_ahead); LVM_CORRECT_READ_AHEAD(lv_ptr->u.lv_read_ahead);
vg_ptr->lv_cur++; vg_ptr->lv_cur++;
lv_ptr->lv_status = lv_status_save; lv_ptr->u.lv_status = lv_status_save;
__update_hardsectsize(lv_ptr); __update_hardsectsize(lv_ptr);
/* optionally add our new snapshot LV */ /* optionally add our new snapshot LV */
if (lv_ptr->lv_access & LV_SNAPSHOT) { if (lv_ptr->u.lv_access & LV_SNAPSHOT) {
lv_t *org = lv_ptr->lv_snapshot_org, *last; lv_t *org = lv_ptr->u.lv_snapshot_org, *last;
/* sync the original logical volume */ /* sync the original logical volume */
fsync_dev(org->lv_dev); fsync_dev(org->u.lv_dev);
#ifdef LVM_VFS_ENHANCEMENT #ifdef LVM_VFS_ENHANCEMENT
/* VFS function call to sync and lock the filesystem */ /* VFS function call to sync and lock the filesystem */
fsync_dev_lockfs(org->lv_dev); fsync_dev_lockfs(org->u.lv_dev);
#endif #endif
down_write(&org->lv_lock); down_write(&org->lv_lock);
org->lv_access |= LV_SNAPSHOT_ORG; org->u.lv_access |= LV_SNAPSHOT_ORG;
lv_ptr->lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */ lv_ptr->u.lv_access &= ~LV_SNAPSHOT_ORG; /* this can only hide an userspace bug */
/* Link in the list of snapshot volumes */ /* Link in the list of snapshot volumes */
for (last = org; last->lv_snapshot_next; last = last->lv_snapshot_next); for (last = org; last->u.lv_snapshot_next; last = last->u.lv_snapshot_next);
lv_ptr->lv_snapshot_prev = last; lv_ptr->u.lv_snapshot_prev = last;
last->lv_snapshot_next = lv_ptr; last->u.lv_snapshot_next = lv_ptr;
up_write(&org->lv_lock); up_write(&org->lv_lock);
} }
/* activate the logical volume */ /* activate the logical volume */
if(activate) if(activate)
lv_ptr->lv_status |= LV_ACTIVE; lv_ptr->u.lv_status |= LV_ACTIVE;
else else
lv_ptr->lv_status &= ~LV_ACTIVE; lv_ptr->u.lv_status &= ~LV_ACTIVE;
if ( lv_ptr->lv_access & LV_WRITE) if ( lv_ptr->u.lv_access & LV_WRITE)
set_device_ro(lv_ptr->lv_dev, 0); set_device_ro(lv_ptr->u.lv_dev, 0);
else else
set_device_ro(lv_ptr->lv_dev, 1); set_device_ro(lv_ptr->u.lv_dev, 1);
#ifdef LVM_VFS_ENHANCEMENT #ifdef LVM_VFS_ENHANCEMENT
/* VFS function call to unlock the filesystem */ /* VFS function call to unlock the filesystem */
if (lv_ptr->lv_access & LV_SNAPSHOT) if (lv_ptr->u.lv_access & LV_SNAPSHOT)
unlockfs(lv_ptr->lv_snapshot_org->lv_dev); unlockfs(lv_ptr->u.lv_snapshot_org->u.lv_dev);
#endif #endif
lv_ptr->vg = vg_ptr; lv_ptr->vg = vg_ptr;
lvm_gendisk.part[minor(lv_ptr->lv_dev)].de = lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].de =
lvm_fs_create_lv(vg_ptr, lv_ptr); lvm_fs_create_lv(vg_ptr, lv_ptr);
return 0; return 0;
...@@ -2101,7 +2104,7 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) ...@@ -2101,7 +2104,7 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
if (l == -1) { if (l == -1) {
for (l = 0; l < vg_ptr->lv_max; l++) { for (l = 0; l < vg_ptr->lv_max; l++) {
if (vg_ptr->lv[l] != NULL && if (vg_ptr->lv[l] != NULL &&
strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0) { strcmp(vg_ptr->lv[l]->u.lv_name, lv_name) == 0) {
break; break;
} }
} }
...@@ -2110,38 +2113,38 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) ...@@ -2110,38 +2113,38 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
lv_ptr = vg_ptr->lv[l]; lv_ptr = vg_ptr->lv[l];
#ifdef LVM_TOTAL_RESET #ifdef LVM_TOTAL_RESET
if (lv_ptr->lv_open > 0 && lvm_reset_spindown == 0) if (lv_ptr->u.lv_open > 0 && lvm_reset_spindown == 0)
#else #else
if (lv_ptr->lv_open > 0) if (lv_ptr->u.lv_open > 0)
#endif #endif
return -EBUSY; return -EBUSY;
/* check for deletion of snapshot source while /* check for deletion of snapshot source while
snapshot volume still exists */ snapshot volume still exists */
if ((lv_ptr->lv_access & LV_SNAPSHOT_ORG) && if ((lv_ptr->u.lv_access & LV_SNAPSHOT_ORG) &&
lv_ptr->lv_snapshot_next != NULL) lv_ptr->u.lv_snapshot_next != NULL)
return -EPERM; return -EPERM;
lvm_fs_remove_lv(vg_ptr, lv_ptr); lvm_fs_remove_lv(vg_ptr, lv_ptr);
if (lv_ptr->lv_access & LV_SNAPSHOT) { if (lv_ptr->u.lv_access & LV_SNAPSHOT) {
/* /*
* Atomically make the the snapshot invisible * Atomically make the the snapshot invisible
* to the original lv before playing with it. * to the original lv before playing with it.
*/ */
lv_t * org = lv_ptr->lv_snapshot_org; lv_t * org = lv_ptr->u.lv_snapshot_org;
down_write(&org->lv_lock); down_write(&org->lv_lock);
/* remove this snapshot logical volume from the chain */ /* remove this snapshot logical volume from the chain */
lv_ptr->lv_snapshot_prev->lv_snapshot_next = lv_ptr->lv_snapshot_next; lv_ptr->u.lv_snapshot_prev->u.lv_snapshot_next = lv_ptr->u.lv_snapshot_next;
if (lv_ptr->lv_snapshot_next != NULL) { if (lv_ptr->u.lv_snapshot_next != NULL) {
lv_ptr->lv_snapshot_next->lv_snapshot_prev = lv_ptr->u.lv_snapshot_next->u.lv_snapshot_prev =
lv_ptr->lv_snapshot_prev; lv_ptr->u.lv_snapshot_prev;
} }
/* no more snapshots? */ /* no more snapshots? */
if (!org->lv_snapshot_next) { if (!org->u.lv_snapshot_next) {
org->lv_access &= ~LV_SNAPSHOT_ORG; org->u.lv_access &= ~LV_SNAPSHOT_ORG;
} }
up_write(&org->lv_lock); up_write(&org->lv_lock);
...@@ -2151,41 +2154,41 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l) ...@@ -2151,41 +2154,41 @@ static int lvm_do_lv_remove(int minor, char *lv_name, int l)
vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le; vg_ptr->pe_allocated -= lv_ptr->lv_allocated_snapshot_le;
} }
lv_ptr->lv_status |= LV_SPINDOWN; lv_ptr->u.lv_status |= LV_SPINDOWN;
/* sync the buffers */ /* sync the buffers */
fsync_dev(lv_ptr->lv_dev); fsync_dev(lv_ptr->u.lv_dev);
lv_ptr->lv_status &= ~LV_ACTIVE; lv_ptr->u.lv_status &= ~LV_ACTIVE;
/* invalidate the buffers */ /* invalidate the buffers */
invalidate_buffers(lv_ptr->lv_dev); invalidate_buffers(lv_ptr->u.lv_dev);
/* reset generic hd */ /* reset generic hd */
lvm_gendisk.part[minor(lv_ptr->lv_dev)].start_sect = -1; lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].start_sect = -1;
lvm_gendisk.part[minor(lv_ptr->lv_dev)].nr_sects = 0; lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].nr_sects = 0;
lvm_gendisk.part[minor(lv_ptr->lv_dev)].de = 0; lvm_gendisk.part[minor(lv_ptr->u.lv_dev)].de = 0;
lvm_size[minor(lv_ptr->lv_dev)] = 0; lvm_size[minor(lv_ptr->u.lv_dev)] = 0;
/* reset VG/LV mapping */ /* reset VG/LV mapping */
vg_lv_map[minor(lv_ptr->lv_dev)].vg_number = ABS_MAX_VG; vg_lv_map[minor(lv_ptr->u.lv_dev)].vg_number = ABS_MAX_VG;
vg_lv_map[minor(lv_ptr->lv_dev)].lv_number = -1; vg_lv_map[minor(lv_ptr->u.lv_dev)].lv_number = -1;
/* correct the PE count in PVs if this is not a snapshot /* correct the PE count in PVs if this is not a snapshot
logical volume */ logical volume */
if (!(lv_ptr->lv_access & LV_SNAPSHOT)) { if (!(lv_ptr->u.lv_access & LV_SNAPSHOT)) {
/* only if this is no snapshot logical volume because /* only if this is no snapshot logical volume because
we share the lv_current_pe[] structs with the we share the u.lv_current_pe[] structs with the
original logical volume */ original logical volume */
for (le = 0; le < lv_ptr->lv_allocated_le; le++) { for (le = 0; le < lv_ptr->u.lv_allocated_le; le++) {
vg_ptr->pe_allocated--; vg_ptr->pe_allocated--;
for (p = 0; p < vg_ptr->pv_cur; p++) { for (p = 0; p < vg_ptr->pv_cur; p++) {
if (kdev_same(vg_ptr->pv[p]->pv_dev, if (kdev_same(vg_ptr->pv[p]->pv_dev,
lv_ptr->lv_current_pe[le].dev)) lv_ptr->u.lv_current_pe[le].dev))
vg_ptr->pv[p]->pe_allocated--; vg_ptr->pv[p]->pe_allocated--;
} }
} }
vfree(lv_ptr->lv_current_pe); vfree(lv_ptr->u.lv_current_pe);
} }
P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__);
...@@ -2203,10 +2206,10 @@ static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2203,10 +2206,10 @@ static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
ulong size; ulong size;
lv_block_exception_t *lvbe; lv_block_exception_t *lvbe;
if (!new_lv->lv_block_exception) if (!new_lv->u.lv_block_exception)
return -ENXIO; return -ENXIO;
size = new_lv->lv_remap_end * sizeof(lv_block_exception_t); size = new_lv->u.lv_remap_end * sizeof(lv_block_exception_t);
if ((lvbe = vmalloc(size)) == NULL) { if ((lvbe = vmalloc(size)) == NULL) {
printk(KERN_CRIT printk(KERN_CRIT
"%s -- lvm_do_lv_extend_reduce: vmalloc " "%s -- lvm_do_lv_extend_reduce: vmalloc "
...@@ -2215,15 +2218,15 @@ static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2215,15 +2218,15 @@ static int __extend_reduce_snapshot(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
return -ENOMEM; return -ENOMEM;
} }
if ((new_lv->lv_remap_end > old_lv->lv_remap_end) && if ((new_lv->u.lv_remap_end > old_lv->u.lv_remap_end) &&
(copy_from_user(lvbe, new_lv->lv_block_exception, size))) { (copy_from_user(lvbe, new_lv->u.lv_block_exception, size))) {
vfree(lvbe); vfree(lvbe);
return -EFAULT; return -EFAULT;
} }
new_lv->lv_block_exception = lvbe; new_lv->u.lv_block_exception = lvbe;
if (lvm_snapshot_alloc_hash_table(new_lv)) { if (lvm_snapshot_alloc_hash_table(new_lv)) {
vfree(new_lv->lv_block_exception); vfree(new_lv->u.lv_block_exception);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2235,7 +2238,7 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2235,7 +2238,7 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
pe_t *pe; pe_t *pe;
/* allocate space for new pe structures */ /* allocate space for new pe structures */
size = new_lv->lv_current_le * sizeof(pe_t); size = new_lv->u.lv_current_le * sizeof(pe_t);
if ((pe = vmalloc(size)) == NULL) { if ((pe = vmalloc(size)) == NULL) {
printk(KERN_CRIT printk(KERN_CRIT
"%s -- lvm_do_lv_extend_reduce: " "%s -- lvm_do_lv_extend_reduce: "
...@@ -2245,21 +2248,21 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2245,21 +2248,21 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
} }
/* get the PE structures from user space */ /* get the PE structures from user space */
if (copy_from_user(pe, new_lv->lv_current_pe, size)) { if (copy_from_user(pe, new_lv->u.lv_current_pe, size)) {
if(old_lv->lv_access & LV_SNAPSHOT) if(old_lv->u.lv_access & LV_SNAPSHOT)
vfree(new_lv->lv_snapshot_hash_table); vfree(new_lv->lv_snapshot_hash_table);
vfree(pe); vfree(pe);
return -EFAULT; return -EFAULT;
} }
new_lv->lv_current_pe = pe; new_lv->u.lv_current_pe = pe;
/* reduce allocation counters on PV(s) */ /* reduce allocation counters on PV(s) */
for (l = 0; l < old_lv->lv_allocated_le; l++) { for (l = 0; l < old_lv->u.lv_allocated_le; l++) {
vg_ptr->pe_allocated--; vg_ptr->pe_allocated--;
for (p = 0; p < vg_ptr->pv_cur; p++) { for (p = 0; p < vg_ptr->pv_cur; p++) {
if (kdev_same(vg_ptr->pv[p]->pv_dev, if (kdev_same(vg_ptr->pv[p]->pv_dev,
old_lv->lv_current_pe[l].dev)) { old_lv->u.lv_current_pe[l].dev)) {
vg_ptr->pv[p]->pe_allocated--; vg_ptr->pv[p]->pe_allocated--;
break; break;
} }
...@@ -2267,11 +2270,11 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2267,11 +2270,11 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
} }
/* extend the PE count in PVs */ /* extend the PE count in PVs */
for (l = 0; l < new_lv->lv_allocated_le; l++) { for (l = 0; l < new_lv->u.lv_allocated_le; l++) {
vg_ptr->pe_allocated++; vg_ptr->pe_allocated++;
for (p = 0; p < vg_ptr->pv_cur; p++) { for (p = 0; p < vg_ptr->pv_cur; p++) {
if (kdev_same(vg_ptr->pv[p]->pv_dev, if (kdev_same(vg_ptr->pv[p]->pv_dev,
new_lv->lv_current_pe[l].dev)) { new_lv->u.lv_current_pe[l].dev)) {
vg_ptr->pv[p]->pe_allocated++; vg_ptr->pv[p]->pe_allocated++;
break; break;
} }
...@@ -2279,30 +2282,30 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2279,30 +2282,30 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
} }
/* save availiable i/o statistic data */ /* save availiable i/o statistic data */
if (old_lv->lv_stripes < 2) { /* linear logical volume */ if (old_lv->u.lv_stripes < 2) { /* linear logical volume */
end = min(old_lv->lv_current_le, new_lv->lv_current_le); end = min(old_lv->u.lv_current_le, new_lv->u.lv_current_le);
for (l = 0; l < end; l++) { for (l = 0; l < end; l++) {
new_lv->lv_current_pe[l].reads += new_lv->u.lv_current_pe[l].reads +=
old_lv->lv_current_pe[l].reads; old_lv->u.lv_current_pe[l].reads;
new_lv->lv_current_pe[l].writes += new_lv->u.lv_current_pe[l].writes +=
old_lv->lv_current_pe[l].writes; old_lv->u.lv_current_pe[l].writes;
} }
} else { /* striped logical volume */ } else { /* striped logical volume */
uint i, j, source, dest, end, old_stripe_size, new_stripe_size; uint i, j, source, dest, end, old_stripe_size, new_stripe_size;
old_stripe_size = old_lv->lv_allocated_le / old_lv->lv_stripes; old_stripe_size = old_lv->u.lv_allocated_le / old_lv->u.lv_stripes;
new_stripe_size = new_lv->lv_allocated_le / new_lv->lv_stripes; new_stripe_size = new_lv->u.lv_allocated_le / new_lv->u.lv_stripes;
end = min(old_stripe_size, new_stripe_size); end = min(old_stripe_size, new_stripe_size);
for (i = source = dest = 0; for (i = source = dest = 0;
i < new_lv->lv_stripes; i++) { i < new_lv->u.lv_stripes; i++) {
for (j = 0; j < end; j++) { for (j = 0; j < end; j++) {
new_lv->lv_current_pe[dest + j].reads += new_lv->u.lv_current_pe[dest + j].reads +=
old_lv->lv_current_pe[source + j].reads; old_lv->u.lv_current_pe[source + j].reads;
new_lv->lv_current_pe[dest + j].writes += new_lv->u.lv_current_pe[dest + j].writes +=
old_lv->lv_current_pe[source + j].writes; old_lv->u.lv_current_pe[source + j].writes;
} }
source += old_stripe_size; source += old_stripe_size;
dest += new_stripe_size; dest += new_stripe_size;
...@@ -2312,19 +2315,29 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) { ...@@ -2312,19 +2315,29 @@ static int __extend_reduce(vg_t *vg_ptr, lv_t *old_lv, lv_t *new_lv) {
return 0; return 0;
} }
static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv) static int lvm_do_lv_extend_reduce(int minor, char *lv_name, userlv_t *ulv)
{ {
int r; int r;
ulong l, e, size; ulong l, e, size;
vg_t *vg_ptr = vg[VG_CHR(minor)]; vg_t *vg_ptr = vg[VG_CHR(minor)];
lv_t *old_lv; lv_t *old_lv;
lv_t *new_lv;
pe_t *pe; pe_t *pe;
if ((pe = new_lv->lv_current_pe) == NULL) if((new_lv = kmalloc(sizeof(lv_t),GFP_KERNEL)) == NULL){
printk(KERN_CRIT
"%s -- LV_EXTEND/REDUCE: kmallor error LV at line %d\n",
lvm_name,__LINE__);
return -ENOMEM;
}
memset(new_lv,0,sizeof(lv_t));
memcpy(&new_lv->u,ulv,sizeof(userlv_t));
if ((pe = new_lv->u.lv_current_pe) == NULL)
return -EINVAL; return -EINVAL;
for (l = 0; l < vg_ptr->lv_max; l++) for (l = 0; l < vg_ptr->lv_max; l++)
if (vg_ptr->lv[l] && !strcmp(vg_ptr->lv[l]->lv_name, lv_name)) if (vg_ptr->lv[l] && !strcmp(vg_ptr->lv[l]->u.lv_name, lv_name))
break; break;
if (l == vg_ptr->lv_max) if (l == vg_ptr->lv_max)
...@@ -2332,9 +2345,9 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv) ...@@ -2332,9 +2345,9 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
old_lv = vg_ptr->lv[l]; old_lv = vg_ptr->lv[l];
if (old_lv->lv_access & LV_SNAPSHOT) { if (old_lv->u.lv_access & LV_SNAPSHOT) {
/* only perform this operation on active snapshots */ /* only perform this operation on active snapshots */
if (old_lv->lv_status & LV_ACTIVE) if (old_lv->u.lv_status & LV_ACTIVE)
r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv); r = __extend_reduce_snapshot(vg_ptr, old_lv, new_lv);
else else
r = -EPERM; r = -EPERM;
...@@ -2348,15 +2361,15 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv) ...@@ -2348,15 +2361,15 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
/* copy relevent fields */ /* copy relevent fields */
down_write(&old_lv->lv_lock); down_write(&old_lv->lv_lock);
if(new_lv->lv_access & LV_SNAPSHOT) { if(new_lv->u.lv_access & LV_SNAPSHOT) {
size = (new_lv->lv_remap_end > old_lv->lv_remap_end) ? size = (new_lv->u.lv_remap_end > old_lv->u.lv_remap_end) ?
old_lv->lv_remap_ptr : new_lv->lv_remap_end; old_lv->u.lv_remap_ptr : new_lv->u.lv_remap_end;
size *= sizeof(lv_block_exception_t); size *= sizeof(lv_block_exception_t);
memcpy(new_lv->lv_block_exception, memcpy(new_lv->u.lv_block_exception,
old_lv->lv_block_exception, size); old_lv->u.lv_block_exception, size);
old_lv->lv_remap_end = new_lv->lv_remap_end; old_lv->u.lv_remap_end = new_lv->u.lv_remap_end;
old_lv->lv_block_exception = new_lv->lv_block_exception; old_lv->u.lv_block_exception = new_lv->u.lv_block_exception;
old_lv->lv_snapshot_hash_table = old_lv->lv_snapshot_hash_table =
new_lv->lv_snapshot_hash_table; new_lv->lv_snapshot_hash_table;
old_lv->lv_snapshot_hash_table_size = old_lv->lv_snapshot_hash_table_size =
...@@ -2364,40 +2377,40 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv) ...@@ -2364,40 +2377,40 @@ static int lvm_do_lv_extend_reduce(int minor, char *lv_name, lv_t *new_lv)
old_lv->lv_snapshot_hash_mask = old_lv->lv_snapshot_hash_mask =
new_lv->lv_snapshot_hash_mask; new_lv->lv_snapshot_hash_mask;
for (e = 0; e < new_lv->lv_remap_ptr; e++) for (e = 0; e < new_lv->u.lv_remap_ptr; e++)
lvm_hash_link(new_lv->lv_block_exception + e, lvm_hash_link(new_lv->u.lv_block_exception + e,
new_lv->lv_block_exception[e].rdev_org, new_lv->u.lv_block_exception[e].rdev_org,
new_lv->lv_block_exception[e].rsector_org, new_lv->u.lv_block_exception[e].rsector_org,
new_lv); new_lv);
} else { } else {
vfree(old_lv->lv_current_pe); vfree(old_lv->u.lv_current_pe);
vfree(old_lv->lv_snapshot_hash_table); vfree(old_lv->lv_snapshot_hash_table);
old_lv->lv_size = new_lv->lv_size; old_lv->u.lv_size = new_lv->u.lv_size;
old_lv->lv_allocated_le = new_lv->lv_allocated_le; old_lv->u.lv_allocated_le = new_lv->u.lv_allocated_le;
old_lv->lv_current_le = new_lv->lv_current_le; old_lv->u.lv_current_le = new_lv->u.lv_current_le;
old_lv->lv_current_pe = new_lv->lv_current_pe; old_lv->u.lv_current_pe = new_lv->u.lv_current_pe;
lvm_gendisk.part[minor(old_lv->lv_dev)].nr_sects = lvm_gendisk.part[minor(old_lv->u.lv_dev)].nr_sects =
old_lv->lv_size; old_lv->u.lv_size;
lvm_size[minor(old_lv->lv_dev)] = old_lv->lv_size >> 1; lvm_size[minor(old_lv->u.lv_dev)] = old_lv->u.lv_size >> 1;
if (old_lv->lv_access & LV_SNAPSHOT_ORG) { if (old_lv->u.lv_access & LV_SNAPSHOT_ORG) {
lv_t *snap; lv_t *snap;
for(snap = old_lv->lv_snapshot_next; snap; for(snap = old_lv->u.lv_snapshot_next; snap;
snap = snap->lv_snapshot_next) { snap = snap->u.lv_snapshot_next) {
down_write(&snap->lv_lock); down_write(&snap->lv_lock);
snap->lv_current_pe = old_lv->lv_current_pe; snap->u.lv_current_pe = old_lv->u.lv_current_pe;
snap->lv_allocated_le = snap->u.lv_allocated_le =
old_lv->lv_allocated_le; old_lv->u.lv_allocated_le;
snap->lv_current_le = old_lv->lv_current_le; snap->u.lv_current_le = old_lv->u.lv_current_le;
snap->lv_size = old_lv->lv_size; snap->u.lv_size = old_lv->u.lv_size;
lvm_gendisk.part[minor(snap->lv_dev)].nr_sects lvm_gendisk.part[minor(snap->u.lv_dev)].nr_sects
= old_lv->lv_size; = old_lv->u.lv_size;
lvm_size[minor(snap->lv_dev)] = lvm_size[minor(snap->u.lv_dev)] =
old_lv->lv_size >> 1; old_lv->u.lv_size >> 1;
__update_hardsectsize(snap); __update_hardsectsize(snap);
up_write(&snap->lv_lock); up_write(&snap->lv_lock);
} }
...@@ -2431,27 +2444,27 @@ static int lvm_do_lv_status_byname(vg_t *vg_ptr, void *arg) ...@@ -2431,27 +2444,27 @@ static int lvm_do_lv_status_byname(vg_t *vg_ptr, void *arg)
for (l = 0; l < vg_ptr->lv_max; l++) { for (l = 0; l < vg_ptr->lv_max; l++) {
if ((lv_ptr = vg_ptr->lv[l]) != NULL && if ((lv_ptr = vg_ptr->lv[l]) != NULL &&
strcmp(lv_ptr->lv_name, strcmp(lv_ptr->u.lv_name,
lv_status_byname_req.lv_name) == 0) { lv_status_byname_req.lv_name) == 0) {
/* Save usermode pointers */ /* Save usermode pointers */
if (copy_from_user(&saved_ptr1, &lv_status_byname_req.lv->lv_current_pe, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr1, &lv_status_byname_req.lv->u.lv_current_pe, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_from_user(&saved_ptr2, &lv_status_byname_req.lv->lv_block_exception, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr2, &lv_status_byname_req.lv->u.lv_block_exception, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_to_user(lv_status_byname_req.lv, if (copy_to_user(lv_status_byname_req.lv,
lv_ptr, lv_ptr,
sizeof(lv_t)) != 0) sizeof(userlv_t)) != 0)
return -EFAULT; return -EFAULT;
if (saved_ptr1 != NULL) { if (saved_ptr1 != NULL) {
if (copy_to_user(saved_ptr1, if (copy_to_user(saved_ptr1,
lv_ptr->lv_current_pe, lv_ptr->u.lv_current_pe,
lv_ptr->lv_allocated_le * lv_ptr->u.lv_allocated_le *
sizeof(pe_t)) != 0) sizeof(pe_t)) != 0)
return -EFAULT; return -EFAULT;
} }
/* Restore usermode pointers */ /* Restore usermode pointers */
if (copy_to_user(&lv_status_byname_req.lv->lv_current_pe, &saved_ptr1, sizeof(void*)) != 0) if (copy_to_user(&lv_status_byname_req.lv->u.lv_current_pe, &saved_ptr1, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
...@@ -2484,23 +2497,23 @@ static int lvm_do_lv_status_byindex(vg_t *vg_ptr,void *arg) ...@@ -2484,23 +2497,23 @@ static int lvm_do_lv_status_byindex(vg_t *vg_ptr,void *arg)
return -ENXIO; return -ENXIO;
/* Save usermode pointers */ /* Save usermode pointers */
if (copy_from_user(&saved_ptr1, &lv_status_byindex_req.lv->lv_current_pe, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr1, &lv_status_byindex_req.lv->u.lv_current_pe, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_from_user(&saved_ptr2, &lv_status_byindex_req.lv->lv_block_exception, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr2, &lv_status_byindex_req.lv->u.lv_block_exception, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_to_user(lv_status_byindex_req.lv, lv_ptr, sizeof(lv_t)) != 0) if (copy_to_user(lv_status_byindex_req.lv, lv_ptr, sizeof(userlv_t)) != 0)
return -EFAULT; return -EFAULT;
if (saved_ptr1 != NULL) { if (saved_ptr1 != NULL) {
if (copy_to_user(saved_ptr1, if (copy_to_user(saved_ptr1,
lv_ptr->lv_current_pe, lv_ptr->u.lv_current_pe,
lv_ptr->lv_allocated_le * lv_ptr->u.lv_allocated_le *
sizeof(pe_t)) != 0) sizeof(pe_t)) != 0)
return -EFAULT; return -EFAULT;
} }
/* Restore usermode pointers */ /* Restore usermode pointers */
if (copy_to_user(&lv_status_byindex_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0) if (copy_to_user(&lv_status_byindex_req.lv->u.lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -2524,7 +2537,7 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) { ...@@ -2524,7 +2537,7 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
for ( l = 0; l < vg_ptr->lv_max; l++) { for ( l = 0; l < vg_ptr->lv_max; l++) {
if ( vg_ptr->lv[l] == NULL) continue; if ( vg_ptr->lv[l] == NULL) continue;
if ( kdev_same(vg_ptr->lv[l]->lv_dev, if ( kdev_same(vg_ptr->lv[l]->u.lv_dev,
to_kdev_t(lv_status_bydev_req.dev))) to_kdev_t(lv_status_bydev_req.dev)))
break; break;
} }
...@@ -2533,22 +2546,22 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) { ...@@ -2533,22 +2546,22 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
lv_ptr = vg_ptr->lv[l]; lv_ptr = vg_ptr->lv[l];
/* Save usermode pointers */ /* Save usermode pointers */
if (copy_from_user(&saved_ptr1, &lv_status_bydev_req.lv->lv_current_pe, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr1, &lv_status_bydev_req.lv->u.lv_current_pe, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_from_user(&saved_ptr2, &lv_status_bydev_req.lv->lv_block_exception, sizeof(void*)) != 0) if (copy_from_user(&saved_ptr2, &lv_status_bydev_req.lv->u.lv_block_exception, sizeof(void*)) != 0)
return -EFAULT; return -EFAULT;
if (copy_to_user(lv_status_bydev_req.lv, lv_ptr, sizeof(lv_t)) != 0) if (copy_to_user(lv_status_bydev_req.lv, lv_ptr, sizeof(lv_t)) != 0)
return -EFAULT; return -EFAULT;
if (saved_ptr1 != NULL) { if (saved_ptr1 != NULL) {
if (copy_to_user(saved_ptr1, if (copy_to_user(saved_ptr1,
lv_ptr->lv_current_pe, lv_ptr->u.lv_current_pe,
lv_ptr->lv_allocated_le * lv_ptr->u.lv_allocated_le *
sizeof(pe_t)) != 0) sizeof(pe_t)) != 0)
return -EFAULT; return -EFAULT;
} }
/* Restore usermode pointers */ /* Restore usermode pointers */
if (copy_to_user(&lv_status_bydev_req.lv->lv_current_pe, &saved_ptr1, sizeof(void *)) != 0) if (copy_to_user(&lv_status_bydev_req.lv->u.lv_current_pe, &saved_ptr1, sizeof(void *)) != 0)
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -2558,7 +2571,7 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) { ...@@ -2558,7 +2571,7 @@ static int lvm_do_lv_status_bydev(vg_t * vg_ptr, void * arg) {
/* /*
* character device support function rename a logical volume * character device support function rename a logical volume
*/ */
static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv) static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, userlv_t *ulv)
{ {
int l = 0; int l = 0;
int ret = 0; int ret = 0;
...@@ -2567,10 +2580,10 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv) ...@@ -2567,10 +2580,10 @@ static int lvm_do_lv_rename(vg_t *vg_ptr, lv_req_t *lv_req, lv_t *lv)
for (l = 0; l < vg_ptr->lv_max; l++) for (l = 0; l < vg_ptr->lv_max; l++)
{ {
if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue; if ( (lv_ptr = vg_ptr->lv[l]) == NULL) continue;
if (kdev_same(lv_ptr->lv_dev, lv->lv_dev)) if (kdev_same(lv_ptr->u.lv_dev, ulv->lv_dev))
{ {
lvm_fs_remove_lv(vg_ptr, lv_ptr); lvm_fs_remove_lv(vg_ptr, lv_ptr);
strncpy(lv_ptr->lv_name, strncpy(lv_ptr->u.lv_name,
lv_req->lv_name, lv_req->lv_name,
NAME_LEN); NAME_LEN);
lvm_fs_create_lv(vg_ptr, lv_ptr); lvm_fs_create_lv(vg_ptr, lv_ptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment