📄 ioctl32.c
字号:
uint32_t pv_cur; uint32_t pv_act; uint32_t dummy; uint32_t vgda; uint32_t pe_size; uint32_t pe_total; uint32_t pe_allocated; uint32_t pvg_total; u32 proc; u32 pv[ABS_MAX_PV + 1]; u32 lv[ABS_MAX_LV + 1]; uint8_t vg_uuid[UUID_LEN+1]; /* volume group UUID */ uint8_t dummy1[200];} vg32_t;typedef struct { uint8_t id[2]; uint16_t version; lvm_disk_data_t pv_on_disk; lvm_disk_data_t vg_on_disk; lvm_disk_data_t pv_namelist_on_disk; lvm_disk_data_t lv_on_disk; lvm_disk_data_t pe_on_disk; uint8_t pv_name[NAME_LEN]; uint8_t vg_name[NAME_LEN]; uint8_t system_id[NAME_LEN]; kdev_t pv_dev; uint32_t pv_number; uint32_t pv_status; uint32_t pv_allocatable; uint32_t pv_size; uint32_t lv_cur; uint32_t pe_size; uint32_t pe_total; uint32_t pe_allocated; uint32_t pe_stale; u32 pe; u32 inode; uint8_t pv_uuid[UUID_LEN+1];} pv32_t;typedef struct { char lv_name[NAME_LEN]; u32 lv;} lv_req32_t;typedef struct { u32 lv_index; u32 lv; /* Transfer size because user space and kernel space differ */ uint16_t size;} lv_status_byindex_req32_t;typedef struct { __kernel_dev_t32 dev; u32 lv;} lv_status_bydev_req32_t;typedef struct { uint8_t lv_name[NAME_LEN]; kdev_t old_dev; kdev_t new_dev; u32 old_pe; u32 new_pe;} le_remap_req32_t;typedef struct { char pv_name[NAME_LEN]; u32 pv;} pv_status_req32_t;typedef struct { uint8_t lv_name[NAME_LEN]; uint8_t vg_name[NAME_LEN]; uint32_t lv_access; uint32_t lv_status; uint32_t lv_open; kdev_t lv_dev; uint32_t lv_number; uint32_t lv_mirror_copies; uint32_t lv_recovery; uint32_t lv_schedule; uint32_t lv_size; u32 lv_current_pe; uint32_t lv_current_le; uint32_t lv_allocated_le; uint32_t lv_stripes; uint32_t lv_stripesize; uint32_t lv_badblock; uint32_t lv_allocation; uint32_t lv_io_timeout; uint32_t lv_read_ahead; /* delta to version 1 starts here */ u32 lv_snapshot_org; u32 lv_snapshot_prev; u32 lv_snapshot_next; u32 lv_block_exception; uint32_t lv_remap_ptr; uint32_t lv_remap_end; uint32_t lv_chunk_size; uint32_t lv_snapshot_minor; char dummy[200];} lv32_t;typedef struct { u32 hash[2]; u32 rsector_org; kdev_t rdev_org; u32 rsector_new; kdev_t rdev_new;} lv_block_exception32_t;static void put_lv_t(lv_t *l){ if (l->lv_current_pe) vfree(l->lv_current_pe); if (l->lv_block_exception) vfree(l->lv_block_exception); kfree(l);}static lv_t *get_lv_t(u32 p, int *errp){ int err, i; u32 ptr1, ptr2; size_t size; lv_block_exception32_t *lbe32; lv_block_exception_t *lbe; lv32_t *ul = (lv32_t *)A(p); lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL); if (!l) { *errp = -ENOMEM; return NULL; } memset(l, 0, sizeof(lv_t)); err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe); err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le, ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr, ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); err |= __get_user(ptr1, &ul->lv_current_pe); err |= __get_user(ptr2, &ul->lv_block_exception); if (err) { kfree(l); *errp = -EFAULT; return NULL; } if (ptr1) { size = l->lv_allocated_le * sizeof(pe_t); l->lv_current_pe = vmalloc(size); if (l->lv_current_pe) err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size); } if (!err && ptr2) { size = l->lv_remap_end * sizeof(lv_block_exception_t); l->lv_block_exception = lbe = vmalloc(size); if (l->lv_block_exception) { lbe32 = (lv_block_exception32_t *)A(ptr2); memset(lbe, 0, size); for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) { err |= get_user(lbe->rsector_org, &lbe32->rsector_org); err |= __get_user(lbe->rdev_org, &lbe32->rdev_org); err |= __get_user(lbe->rsector_new, &lbe32->rsector_new); err |= __get_user(lbe->rdev_new, &lbe32->rdev_new); } } } if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) { if (!err) *errp = -ENOMEM; else *errp = -EFAULT; put_lv_t(l); return NULL; } return l;}static int copy_lv_t(u32 ptr, lv_t *l){ int err; lv32_t *ul = (lv32_t *)A(ptr); u32 ptr1; size_t size; err = get_user(ptr1, &ul->lv_current_pe); if (err) return -EFAULT; err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe); err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le, ((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le)); err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr, ((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr)); size = l->lv_allocated_le * sizeof(pe_t); if (ptr1) err |= __copy_to_user((void *)A(ptr1), l->lv_current_pe, size); return err ? -EFAULT : 0;}static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ vg_t *v = NULL; union { lv_req_t lv_req; le_remap_req_t le_remap; lv_status_byindex_req_t lv_byindex; lv_status_bydev_req_t lv_bydev; pv_status_req_t pv_status; } u; pv_t p; int err; u32 ptr = 0; int i; mm_segment_t old_fs; void *karg = &u; switch (cmd) { case VG_STATUS: v = kmalloc(sizeof(vg_t), GFP_KERNEL); if (!v) return -ENOMEM; karg = v; break; case VG_CREATE_OLD: case VG_CREATE: v = kmalloc(sizeof(vg_t), GFP_KERNEL); if (!v) return -ENOMEM; if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) { kfree(v); return -EFAULT; } /* 'proc' field is unused, just NULL it out. */ v->proc = NULL; if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) { kfree(v); return -EFAULT; } karg = v; memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv)); if (v->pv_max > ABS_MAX_PV || v->lv_max > ABS_MAX_LV) return -EPERM; for (i = 0; i < v->pv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->pv[i]); if (err) break; if (ptr) { v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL); if (!v->pv[i]) { err = -ENOMEM; break; } err = copy_from_user(v->pv[i], (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) { err = -EFAULT; break; } err = copy_from_user(v->pv[i]->pv_uuid, ((pv32_t *)A(ptr))->pv_uuid, UUID_LEN+1); if (err) { err = -EFAULT; break; } v->pv[i]->pe = NULL; v->pv[i]->bd = NULL; } } if (!err) { for (i = 0; i < v->lv_max; i++) { err = __get_user(ptr, &((vg32_t *)arg)->lv[i]); if (err) break; if (ptr) { v->lv[i] = get_lv_t(ptr, &err); if (err) break; } } } break; case LV_CREATE: case LV_EXTEND: case LV_REDUCE: case LV_REMOVE: case LV_RENAME: case LV_STATUS_BYNAME: err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name)); if (err) return -EFAULT; if (cmd != LV_REMOVE) { err = __get_user(ptr, &((lv_req32_t *)arg)->lv); if (err) return err; u.lv_req.lv = get_lv_t(ptr, &err); } else u.lv_req.lv = NULL; break; case LV_STATUS_BYINDEX: err = get_user(u.lv_byindex.lv_index, &((lv_status_byindex_req32_t *)arg)->lv_index); err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv); if (err) return err; u.lv_byindex.lv = get_lv_t(ptr, &err); break; case LV_STATUS_BYDEV: err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev); err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv); if (err) return err; u.lv_bydev.lv = get_lv_t(ptr, &err); break; case VG_EXTEND: err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) return -EFAULT; err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1); if (err) return -EFAULT; p.pe = NULL; p.bd = NULL; karg = &p; break; case PV_CHANGE: case PV_STATUS: err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name)); if (err) return -EFAULT; err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv); if (err) return err; u.pv_status.pv = &p; if (cmd == PV_CHANGE) { err = copy_from_user(&p, (void *)A(ptr), sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) return -EFAULT; p.pe = NULL; p.bd = NULL; } break; }; old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); switch (cmd) { case VG_STATUS: if (!err) { if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) || clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc)) err = -EFAULT; } if (copy_to_user(((vg32_t *)arg)->vg_uuid, v->vg_uuid, UUID_LEN+1)) { err = -EFAULT; } kfree(v); break; case VG_CREATE_OLD: case VG_CREATE: for (i = 0; i < v->pv_max; i++) { if (v->pv[i]) kfree(v->pv[i]); } for (i = 0; i < v->lv_max; i++) { if (v->lv[i]) put_lv_t(v->lv[i]); } kfree(v); break; case LV_STATUS_BYNAME: if (!err && u.lv_req.lv) err = copy_lv_t(ptr, u.lv_req.lv); /* Fall through */ case LV_CREATE: case LV_EXTEND: case LV_REDUCE: if (u.lv_req.lv) put_lv_t(u.lv_req.lv); break; case LV_STATUS_BYINDEX: if (u.lv_byindex.lv) { if (!err) err = copy_lv_t(ptr, u.lv_byindex.lv); put_lv_t(u.lv_byindex.lv); } break; case LV_STATUS_BYDEV: if (u.lv_bydev.lv) { if (!err) err = copy_lv_t(ptr, u.lv_bydev.lv); put_lv_t(u.lv_byindex.lv); } break; case PV_STATUS: if (!err) { err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1); if (err) return -EFAULT; err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1); if (err) return -EFAULT; } break; }; return err;}#endif#ifdef CONFIG_GENRTC#endif#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)/* This really belongs in include/linux/drm.h -DaveM */#include "../../../drivers/char/drm/drm.h"typedef struct drm32_version { int version_major; /* Major version */ int version_minor; /* Minor version */ int version_patchlevel;/* Patch level */ int name_len; /* Length of name buffer */ u32 name; /* Name of driver */ int date_len; /* Length of date buffer */ u32 date; /* User-space buffer to hold date */ int desc_len; /* Length of desc buffer */ u32 desc; /* User-space buffer to hold desc */} drm32_version_t;#define DRM32_IOCTL_VERSION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -