📄 lvm.c
字号:
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); vg_ptr = NULL; return -EPERM; } /* get the physical volume structures */ vg_ptr->pv_act = vg_ptr->pv_cur = 0; for (p = 0; p < vg_ptr->pv_max; p++) { /* 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++) { /* user space address */ if ((lvp = vg_ptr->lv[l]) != NULL) { if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) { 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++) { 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; } }#ifdef CONFIG_DEVFS_FS vg_devfs_handle[vg_ptr->vg_number] = devfs_mk_dir(0, vg_ptr->vg_name, NULL); ch_devfs_handle[vg_ptr->vg_number] = devfs_register( vg_devfs_handle[vg_ptr->vg_number] , "group", DEVFS_FL_DEFAULT, LVM_CHAR_MAJOR, vg_ptr->vg_number, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &lvm_chr_fops, NULL);#endif#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr);#endif 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); lvm_do_create_proc_entry_of_pv ( vg_ptr, pv_ptr); if ( ret != 0) return ret; /* We don't need the PE list in kernel space like LVs pe_t list */ pv_ptr->pe = NULL; vg_ptr->pv_cur++; vg_ptr->pv_act++; vg_ptr->pe_total += pv_ptr->pe_total;#ifdef LVM_GET_INODE /* insert a dummy inode for fs_may_mount */ pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);#endif 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; vg_ptr->pe_total -= pv_ptr->pe_total; vg_ptr->pv_cur--; vg_ptr->pv_act--; 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 (copy_from_user(vg_name, arg, sizeof(vg_name)) != 0) return -EFAULT;#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr);#endif 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); }#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_create_proc_entry_of_vg ( vg_ptr);#endif 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; /* 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) {#ifdef DEBUG_KFREE printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif lvm_do_pv_remove(vg_ptr, i); } }#ifdef CONFIG_DEVFS_FS devfs_unregister (ch_devfs_handle[vg_ptr->vg_number]); devfs_unregister (vg_devfs_handle[vg_ptr->vg_number]);#endif#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_vg ( vg_ptr);#endif#ifdef DEBUG_KFREE printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif 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_ptr = NULL; pv_ptr = vg_ptr->pv[p] = kmalloc(sizeof(pv_t),GFP_KERNEL); if (pv_ptr == NULL) { printk(KERN_CRIT "%s -- VG_CREATE: kmalloc error PV at line %d\n", lvm_name, __LINE__); return -ENOMEM; } if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) { return -EFAULT; } /* We don't need the PE list in kernel space as with LVs pe_t list (see below) */ pv_ptr->pe = NULL; pv_ptr->pe_allocated = 0; pv_ptr->pv_status = PV_ACTIVE; vg_ptr->pv_act++; vg_ptr->pv_cur++;#ifdef LVM_GET_INODE /* insert a dummy inode for fs_may_mount */ pv_ptr->inode = lvm_get_inode(pv_ptr->pv_dev);#endif return 0;} /* lvm_do_pv_create() *//* * character device support function physical volume create */static int lvm_do_pv_remove(vg_t *vg_ptr, ulong p) { pv_t *pv_ptr = vg_ptr->pv[p];#if defined CONFIG_LVM_PROC_FS && defined CONFIG_PROC_FS lvm_do_remove_proc_entry_of_pv ( vg_ptr, pv_ptr);#endif vg_ptr->pe_total -= pv_ptr->pe_total; vg_ptr->pv_cur--; vg_ptr->pv_act--;#ifdef LVM_GET_INODE lvm_clear_inode(pv_ptr->inode);#endif kfree(pv_ptr); vg_ptr->pv[p] = NULL; return 0;}/* * 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; 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; if ((pep = lv->lv_current_pe) == NULL) return -EINVAL; if (lv->lv_chunk_size > LVM_SNAPSHOT_MAX_CHUNK) return -EINVAL; for (l = 0; l < vg_ptr->lv_max; 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; lv_ptr->lv_status &= ~LV_ACTIVE; lv_ptr->lv_snapshot_org = \ lv_ptr->lv_snapshot_prev = \ lv_ptr->lv_snapshot_next = NULL; lv_ptr->lv_block_exception = NULL; lv_ptr->lv_iobuf = NULL; lv_ptr->lv_snapshot_hash_table = NULL; lv_ptr->lv_snapshot_hash_table_size = 0; lv_ptr->lv_snapshot_hash_mask = 0; lv_ptr->lv_COW_table_page = NULL; init_MUTEX(&lv_ptr->lv_snapshot_sem); lv_ptr->lv_snapshot_use_rate = 0; vg_ptr->lv[l] = lv_ptr; /* get the PE structures from user space if this is no snapshot logical volume */ if (!(lv_ptr->lv_access & LV_SNAPSHOT)) { size = lv_ptr->lv_allocated_le * sizeof(pe_t); if ((lv_ptr->lv_current_pe = vmalloc(size)) == NULL) { printk(KERN_CRIT "%s -- LV_CREATE: vmalloc error LV_CURRENT_PE of %d Byte " "at line %d\n", lvm_name, size, __LINE__);#ifdef DEBUG_KFREE printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif kfree(lv_ptr); vg[VG_CHR(minor)]->lv[l] = NULL; return -ENOMEM; } if (copy_from_user(lv_ptr->lv_current_pe, pep, size)) { vfree(lv_ptr->lv_current_pe); kfree(lv_ptr); vg_ptr->lv[l] = NULL; return -EFAULT; } /* correct the PE count in PVs */ for (le = 0; le < lv_ptr->lv_allocated_le; le++) { vg_ptr->pe_allocated++; for (p = 0; p < vg_ptr->pv_cur; p++) { if (vg_ptr->pv[p]->pv_dev == lv_ptr->lv_current_pe[le].dev) vg_ptr->pv[p]->pe_allocated++; } } } else { /* Get snapshot exception data and block list */ if (lvbe != NULL) { lv_ptr->lv_snapshot_org = vg_ptr->lv[LV_BLK(lv_ptr->lv_snapshot_minor)]; if (lv_ptr->lv_snapshot_org != NULL) { size = lv_ptr->lv_remap_end * sizeof(lv_block_exception_t); if ((lv_ptr->lv_block_exception = vmalloc(size)) == NULL) { printk(KERN_CRIT "%s -- lvm_do_lv_create: vmalloc error LV_BLOCK_EXCEPTION " "of %d byte at line %d\n", lvm_name, size, __LINE__);#ifdef DEBUG_KFREE printk(KERN_DEBUG "%s -- kfree %d\n", lvm_name, __LINE__);#endif kfree(lv_ptr); vg_ptr->lv[l] = NULL; return -ENOMEM; } if (copy_from_user(lv_ptr->lv_block_exception, lvbe, size)) { vfree(lv_ptr->lv_block_exception); kfree(lv_ptr); vg[VG_CHR(minor)]->lv[l] = NULL; return -EFAULT; } /* point to the original logical volume */ lv_ptr = lv_ptr->lv_snapshot_org; lv_ptr->lv_snapshot_minor = 0; lv_ptr->lv_snapshot_org = lv_ptr; lv_ptr->lv_snapshot_prev = NULL; /* walk thrugh the snapshot list */ while (lv_ptr->lv_snapshot_next != NULL) lv_ptr = lv_ptr->lv_snapshot_next; /* now lv_ptr points to the last existing snapshot in the chain */ vg_ptr->lv[l]->lv_snapshot_prev = lv_ptr; /* our new one now back points to the previous last in the chain which can be the original logical volume */ lv_ptr = vg_ptr->lv[l]; /* now lv_ptr points to our new last snapshot logical volume */ lv_ptr->lv_snapshot_org = lv_ptr->lv_snapshot_prev->lv_snapshot_org; lv_ptr->lv_snapshot_next = NULL; lv_ptr->l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -