📄 lvm.c
字号:
if (copy_from_user(&le_remap_req, arg, sizeof(le_remap_req_t)) != 0) return -EFAULT; for (l = 0; l < vg_ptr->lv_max; l++) { lv_ptr = vg_ptr->lv[l]; if (lv_ptr != NULL && strcmp(lv_ptr->lv_name, le_remap_req.lv_name) == 0) { for (le = 0; le < lv_ptr->lv_allocated_le; le++) { if (lv_ptr->lv_current_pe[le].dev == le_remap_req.old_dev && lv_ptr->lv_current_pe[le].pe == le_remap_req.old_pe) { lv_ptr->lv_current_pe[le].dev = le_remap_req.new_dev; lv_ptr->lv_current_pe[le].pe = le_remap_req.new_pe; __update_hardsectsize(lv_ptr); return 0; } } return -EINVAL; } } return -ENXIO;} /* lvm_do_le_remap() *//* * character device support function VGDA create */static int lvm_do_vg_create(void *arg, int minor){ int ret = 0; ulong l, ls = 0, p, size; lv_t lv; vg_t *vg_ptr; lv_t **snap_lv_ptr; if ((vg_ptr = kmalloc(sizeof(vg_t),GFP_KERNEL)) == NULL) { printk(KERN_CRIT "%s -- VG_CREATE: kmalloc error VG at line %d\n", lvm_name, __LINE__); return -ENOMEM; } /* get the volume group structure */ if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) { P_IOCTL("lvm_do_vg_create ERROR: copy VG ptr %p (%d bytes)\n", arg, sizeof(vg_t)); kfree(vg_ptr); return -EFAULT; } /* VG_CREATE now uses minor number in VG structure */ if (minor == -1) minor = vg_ptr->vg_number; /* Validate it */ if (vg[VG_CHR(minor)] != NULL) { P_IOCTL("lvm_do_vg_create ERROR: VG %d in use\n", minor); kfree(vg_ptr); return -EPERM; } /* we are not that active so far... */ vg_ptr->vg_status &= ~VG_ACTIVE; vg_ptr->pe_allocated = 0; if (vg_ptr->pv_max > ABS_MAX_PV) { printk(KERN_WARNING "%s -- Can't activate VG: ABS_MAX_PV too small\n", lvm_name); kfree(vg_ptr); return -EPERM; } if (vg_ptr->lv_max > ABS_MAX_LV) { printk(KERN_WARNING "%s -- Can't activate VG: ABS_MAX_LV too small for %u\n", lvm_name, vg_ptr->lv_max); kfree(vg_ptr); return -EPERM; } /* create devfs and procfs entries */ lvm_fs_create_vg(vg_ptr); vg[VG_CHR(minor)] = vg_ptr; /* get the physical volume structures */ vg_ptr->pv_act = vg_ptr->pv_cur = 0; for (p = 0; p < vg_ptr->pv_max; p++) { pv_t *pvp; /* user space address */ if ((pvp = vg_ptr->pv[p]) != NULL) { ret = lvm_do_pv_create(pvp, vg_ptr, p); if ( ret != 0) { lvm_do_vg_remove(minor); return ret; } } } size = vg_ptr->lv_max * sizeof(lv_t *); if ((snap_lv_ptr = vmalloc ( size)) == NULL) { printk(KERN_CRIT "%s -- VG_CREATE: vmalloc error snapshot LVs at line %d\n", lvm_name, __LINE__); lvm_do_vg_remove(minor); return -EFAULT; } memset(snap_lv_ptr, 0, size); /* get the logical volume structures */ vg_ptr->lv_cur = 0; for (l = 0; l < vg_ptr->lv_max; l++) { lv_t *lvp; /* user space address */ if ((lvp = vg_ptr->lv[l]) != NULL) { if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) { P_IOCTL("ERROR: copying LV ptr %p (%d bytes)\n", lvp, sizeof(lv_t)); lvm_do_vg_remove(minor); return -EFAULT; } if ( lv.lv_access & LV_SNAPSHOT) { snap_lv_ptr[ls] = lvp; vg_ptr->lv[l] = NULL; ls++; continue; } vg_ptr->lv[l] = NULL; /* only create original logical volumes for now */ if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) { lvm_do_vg_remove(minor); return -EFAULT; } } } /* Second path to correct snapshot logical volumes which are not in place during first path above */ for (l = 0; l < ls; l++) { lv_t *lvp = snap_lv_ptr[l]; if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) { lvm_do_vg_remove(minor); return -EFAULT; } if (lvm_do_lv_create(minor, lv.lv_name, &lv) != 0) { lvm_do_vg_remove(minor); return -EFAULT; } } vfree(snap_lv_ptr); vg_count++; MOD_INC_USE_COUNT; /* let's go active */ vg_ptr->vg_status |= VG_ACTIVE; return 0;} /* lvm_do_vg_create() *//* * character device support function VGDA extend */static int lvm_do_vg_extend(vg_t *vg_ptr, void *arg){ int ret = 0; uint p; pv_t *pv_ptr; if (vg_ptr == NULL) return -ENXIO; if (vg_ptr->pv_cur < vg_ptr->pv_max) { for (p = 0; p < vg_ptr->pv_max; p++) { if ( ( pv_ptr = vg_ptr->pv[p]) == NULL) { ret = lvm_do_pv_create(arg, vg_ptr, p); if ( ret != 0) return ret; pv_ptr = vg_ptr->pv[p]; vg_ptr->pe_total += pv_ptr->pe_total; return 0; } } } return -EPERM;} /* lvm_do_vg_extend() *//* * character device support function VGDA reduce */static int lvm_do_vg_reduce(vg_t *vg_ptr, void *arg) { uint p; pv_t *pv_ptr; if (vg_ptr == NULL) return -ENXIO; if (copy_from_user(pv_name, arg, sizeof(pv_name)) != 0) return -EFAULT; for (p = 0; p < vg_ptr->pv_max; p++) { pv_ptr = vg_ptr->pv[p]; if (pv_ptr != NULL && strcmp(pv_ptr->pv_name, pv_name) == 0) { if (pv_ptr->lv_cur > 0) return -EPERM; lvm_do_pv_remove(vg_ptr, p); /* Make PV pointer array contiguous */ for (; p < vg_ptr->pv_max - 1; p++) vg_ptr->pv[p] = vg_ptr->pv[p + 1]; vg_ptr->pv[p + 1] = NULL; return 0; } } return -ENXIO;} /* lvm_do_vg_reduce *//* * character device support function VG rename */static int lvm_do_vg_rename(vg_t *vg_ptr, void *arg){ int l = 0, p = 0, len = 0; char vg_name[NAME_LEN] = { 0,}; char lv_name[NAME_LEN] = { 0,}; char *ptr = NULL; lv_t *lv_ptr = NULL; pv_t *pv_ptr = NULL; if (vg_ptr == NULL) return -ENXIO; if (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0) return -EFAULT; lvm_fs_remove_vg(vg_ptr); strncpy ( vg_ptr->vg_name, vg_name, sizeof ( vg_name)-1); for ( l = 0; l < vg_ptr->lv_max; l++) { if ((lv_ptr = vg_ptr->lv[l]) == NULL) continue; strncpy(lv_ptr->vg_name, vg_name, sizeof ( vg_name)); ptr = strrchr(lv_ptr->lv_name, '/'); if (ptr == NULL) ptr = lv_ptr->lv_name; strncpy(lv_name, ptr, sizeof ( lv_name)); len = sizeof(LVM_DIR_PREFIX); strcpy(lv_ptr->lv_name, LVM_DIR_PREFIX); strncat(lv_ptr->lv_name, vg_name, NAME_LEN - len); len += strlen ( vg_name); strncat(lv_ptr->lv_name, lv_name, NAME_LEN - len); } for ( p = 0; p < vg_ptr->pv_max; p++) { if ( (pv_ptr = vg_ptr->pv[p]) == NULL) continue; strncpy(pv_ptr->vg_name, vg_name, NAME_LEN); } lvm_fs_create_vg(vg_ptr); return 0;} /* lvm_do_vg_rename *//* * character device support function VGDA remove */static int lvm_do_vg_remove(int minor){ int i; vg_t *vg_ptr = vg[VG_CHR(minor)]; pv_t *pv_ptr; if (vg_ptr == NULL) return -ENXIO;#ifdef LVM_TOTAL_RESET if (vg_ptr->lv_open > 0 && lvm_reset_spindown == 0)#else if (vg_ptr->lv_open > 0)#endif return -EPERM; /* let's go inactive */ vg_ptr->vg_status &= ~VG_ACTIVE; /* remove from procfs and devfs */ lvm_fs_remove_vg(vg_ptr); /* free LVs */ /* first free snapshot logical volumes */ for (i = 0; i < vg_ptr->lv_max; i++) { if (vg_ptr->lv[i] != NULL && vg_ptr->lv[i]->lv_access & LV_SNAPSHOT) { lvm_do_lv_remove(minor, NULL, i); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(1); } } /* then free the rest of the LVs */ for (i = 0; i < vg_ptr->lv_max; i++) { if (vg_ptr->lv[i] != NULL) { lvm_do_lv_remove(minor, NULL, i); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(1); } } /* free PVs */ for (i = 0; i < vg_ptr->pv_max; i++) { if ((pv_ptr = vg_ptr->pv[i]) != NULL) { P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); lvm_do_pv_remove(vg_ptr, i); } } P_KFREE("%s -- kfree %d\n", lvm_name, __LINE__); kfree(vg_ptr); vg[VG_CHR(minor)] = NULL; vg_count--; MOD_DEC_USE_COUNT; return 0;} /* lvm_do_vg_remove() *//* * character device support function physical volume create */static int lvm_do_pv_create(pv_t *pvp, vg_t *vg_ptr, ulong p) { pv_t *pv; int err; pv = kmalloc(sizeof(pv_t),GFP_KERNEL); if (pv == NULL) { printk(KERN_CRIT "%s -- PV_CREATE: kmalloc error PV at line %d\n", lvm_name, __LINE__); return -ENOMEM; } memset(pv, 0, sizeof(*pv)); if (copy_from_user(pv, pvp, sizeof(pv_t)) != 0) { P_IOCTL("lvm_do_pv_create ERROR: copy PV ptr %p (%d bytes)\n", pvp, sizeof(pv_t)); kfree(pv); return -EFAULT; } if ((err = _open_pv(pv))) { kfree(pv); return err; } /* We don't need the PE list in kernel space as with LVs pe_t list (see below) */ pv->pe = NULL; pv->pe_allocated = 0; pv->pv_status = PV_ACTIVE; vg_ptr->pv_act++; vg_ptr->pv_cur++; lvm_fs_create_pv(vg_ptr, pv); vg_ptr->pv[p] = pv; return 0;} /* lvm_do_pv_create() *//* * character device support function physical volume remove */static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) { pv_t *pv = vg_ptr->pv[p]; lvm_fs_remove_pv(vg_ptr, pv); vg_ptr->pe_total -= pv->pe_total; vg_ptr->pv_cur--; vg_ptr->pv_act--; _close_pv(pv); kfree(pv); vg_ptr->pv[p] = NULL; return 0;}static void __update_hardsectsize(lv_t *lv) { int le, e; int max_hardsectsize = 0, hardsectsize; for (le = 0; le < lv->lv_allocated_le; le++) { hardsectsize = get_hardsect_size(lv->lv_current_pe[le].dev); if (hardsectsize == 0) hardsectsize = 512; if (hardsectsize > max_hardsectsize) max_hardsectsize = hardsectsize; } /* only perform this operation on active snapshots */ if ((lv->lv_access & LV_SNAPSHOT) && (lv->lv_status & LV_ACTIVE)) { for (e = 0; e < lv->lv_remap_end; e++) { hardsectsize = get_hardsect_size( lv->lv_block_exception[e].rdev_new); if (hardsectsize == 0) hardsectsize = 512; if (hardsectsize > max_hardsectsize) max_hardsectsize = hardsectsize; } } lvm_hardsectsizes[MINOR(lv->lv_dev)] = max_hardsectsize;}/* * character device support function logical volume create */static int lvm_do_lv_create(int minor, char *lv_name, lv_t *lv){ int e, ret, l, le, l_new, p, size, activate = 1; ulong lv_status_save; lv_block_exception_t *lvbe = lv->lv_block_exception; vg_t *vg_ptr = vg[VG_CHR(minor)]; lv_t *lv_ptr = NULL; pe_t *pep; if (!(pep = lv->lv_current_pe)) return -EINVAL; if (_sectors_to_k(lv->lv_chunk_size) > LVM_SNAPSHOT_MAX_CHUNK) return -EINVAL; for (l = 0; l < vg_ptr->lv_cur; l++) { if (vg_ptr->lv[l] != NULL && strcmp(vg_ptr->lv[l]->lv_name, lv_name) == 0) return -EEXIST; } /* in case of lv_remove(), lv_create() pair */ l_new = -1; if (vg_ptr->lv[lv->lv_number] == NULL) l_new = lv->lv_number; else { for (l = 0; l < vg_ptr->lv_max; l++) { if (vg_ptr->lv[l] == NULL) if (l_new == -1) l_new = l; } } if (l_new == -1) return -EPERM; else l = l_new; if ((lv_ptr = kmalloc(sizeof(lv_t),GFP_KERNEL)) == NULL) {; printk(KERN_CRIT "%s -- LV_CREATE: kmalloc error LV at line %d\n", lvm_name, __LINE__); return -ENOMEM; } /* copy preloaded LV */ memcpy((char *) lv_ptr, (char *) lv, sizeof(lv_t)); lv_status_save = lv_ptr->lv_status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -