diff --git a/driver/device-mapper/dm-fs.c b/driver/device-mapper/dm-fs.c index a99c06089..3ad17acfb 100644 --- a/driver/device-mapper/dm-fs.c +++ b/driver/device-mapper/dm-fs.c @@ -39,107 +39,115 @@ */ const char *_fs_dir = "device-mapper"; +const char *_control_name = "control"; static struct proc_dir_entry *_proc_dir; +static struct proc_dir_entry *_control; static devfs_handle_t _dev_dir; -static devfs_handle_t _dev_control; + +static int _line_splitter(struct file *file, const char *buffer, + unsigned long *count, void *data) + +typedef int (process_fn)(const char *b, const char *e); + +struct pf_data { + process_fn data; + int minor; +}; int dm_init_fs() { - /* create /dev/device-manager */ + struct pf_data *pfd = kmalloc(sizeof(*pfd), GFP_KERNEL); + + if (!pfd) + return 0; + _dev_dir = devfs_mk_dir(0, _fs_dir, NULL); - /* and put the control device in it */ - _dev_control = devfs_register(0 , "device-mapper", 0, DM_CHAR_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &dm_ctl_fops, NULL); + if (!(_proc_dir = create_proc_entry(_fs_dir, S_IFDIR, &proc_root))) + goto fail; - if (!(_proc_dir = create_proc_entry(_fs_dir, S_IFDIR, &proc_root))) { - devfs_unregister(_dm_control); - _dm_control = 0; - return 0; - } + if (!(_control = create_proc_entry(_control_name, 0, _proc_dir))) + goto fail; + + _control->write_proc = _line_splitter; + + pfd->fn = _process_control; + pfd->minor = -1; + _control->data = pfd; return 1; + + fail: + dm_fin_fs(); + return 0; } void dm_fin_fs(void) { - /* FIXME: unregister all devices and proc interfaces */ + if (_control) { + remove_proc_entry(_control_name, _proc_dir); + _control = 0; + } - devfs_unregister(_dev_control); - devfs_unregister(_dev_dir); + if (_proc_dir) { + remove_proc_entry(_fs_dir, &proc_root); + _proc_dir = 0; + } - remove_proc_entry(_fs_dir, &proc_root); + if (_dev_dir) + devfs_unregister(_dev_dir); } -int dm_add(const char *name) +int _process_control(const char *b, const char *e, int minor) { + const char *wb, *we; + char *name[64]; + long minor = -1; + int create = 0; -} + /* + * create [minor] + * remove + */ + if (!_get_word(b, e, &wb, &we)) + return -EINVAL; + b = we; -int dm_remove(const char *name) -{ + if (!_tok_cmp("create", wb, we)) + create = 1; -} + else if (_tok_cmp("remove", wb, we)) + return -EINVAL; + if (!_get_word(b, e, &wb, &we)) + return -EINVAL; + b = we; -static int _setup_targets(struct mapped_device *md, struct device_table *t) -{ - int i; - offset_t low = 0; + _tok_cpy(name, sizeof(buffer), wb, we); - md->num_targets = t->count; - md->targets = __aligned(sizeof(*md->targets) * md->num_targets, - NODE_SIZE); + if (create) { + if (_get_word(b, e, &wb, &we)) { + minor = simple_strtol(wb, &we, 10); - for (i = 0; i < md->num_targets; i++) { - struct mapper *m = _find_mapper(t->map[i].type); - if (!m) - return 0; - - if (!m->ctr(low, t->map[i].high + 1, - t->map[i].context, md->contexts + i)) { - WARN("contructor for '%s' failed", m->name); - return 0; + if (we == wb) + return -EINVAL; } + _create_dm(name, minor); - md->targets[i] = m->map; + } else { + if (!_get_word(b, e, &wb, &we)) + return -EINVAL; + + _tok_cpy(name, sizeof(buffer), wb, we); + _remove_dm(name, minor); } - return 1; + return -EINVAL; } -static const char *_eat_white(const char *b, const char *e) -{ - while(b != e && isspace((int) *b)) - b++; - - return b; -} - -static int _get_line(const char *b, const char *e, - const char **lb, const char **le) -{ - b = _eat_white(b, e); - if (b == e) - return 0; - - lb = b; - while((b != e) && *b != '\n') - b++; - - if (b == e) { - /* FIXME: handle partial lines */ - return 0; - } - - *le = b; - return 1; -} - -static int _process_line(const char *b, const char *e) +static int _process_table(const char *b, const char *e, int minor) { struct target *t; const char *wb, *we; @@ -161,47 +169,131 @@ static int _process_line(const char *b, const char *e) /* FIXME: add module loading here */ return -EPARAM; } - - } -static int _write_proc(struct file *file, const char *buffer, - unsigned long *count, void *data) +static int _process_table(const char *b, const char *e, int minor) { - const char *b, *e, *lb, *le; - int minor = (int) data; + const char *wb, *we; struct mapped_device *md = dm_get_dev(minor); if (!md) return -ENXIO; - b = buffer; - e = buffer + e; + if (!_get_word(b, e, &wb, &we)) + return -EINVAL; - if (!is_loading(md)) { - if (!_get_line(b, e, &lb, &le)) - return -EPARAM; + if (!_tok_cmp("begin", b, e)) { + /* suspend the device if it's active */ + dm_suspend(md); - if (tokcmp("begin\n", lb, le)) - return -EPARAM; + /* start loading a table */ + dm_start_table(md); - start_loading(md); - b = le; + } else if (!_tok_cmp("end", b, e)) { + /* activate the device ... ... */ + dm_complete_table(md); + dm_activate(md); + + } else { + /* add the new entry */ + int len = we - wb; + char high_s[64], *ptr; + char target[64]; + struct target *t; + offset_t high; + + if (len > sizeof(high_s)) + return 0; + + strncpy(high_s, wb, we - wb); + high_s[len] = '\0'; + + high = strtol(high_s, &ptr, 10); + if (ptr == high_s) + return 0; + + b = we; + if (!_get_word(b, e, &wb, &we)) + return 0; + + len = we - wb; + if (len > sizeof(target)) + return 0; + + strncpy(target, wb, len); + target[len] = '\0'; + + if (!(t = dm_get_target(target))) + return 0; + + dm_add_entry(md, high, t, context); } - while(_get_line(b, e, &lb, &le)) { - if (!tokcmp("end\n", wb, we)) { - /* FIXME: finish */ - } - - ret = _process_line(lb, le); - if (ret < 0) - goto fail; - - b = le; - } - - fail: - /* stop the table load */ - + return 1; +} + +static const char *_eat_space(const char *b, const char *e) +{ + while(b != e && isspace((int) *b)) + b++; + + return b; +} + +static int _get_word(const char *b, const char *e, + const char **wb, const char *we) +{ + b = _eat_space(b, e); + + if (b == e) + return 0; + + *wb = b; + while(b != e && !isspace((int) b)) + b++; + *we = e; + return 1; +} + +static int _line_splitter(struct file *file, const char *buffer, + unsigned long *count, void *data) +{ + const char *b = buffer, *e = buffer + count, *lb; + struct pf_data *pfd = (struct pf_data *) data; + + while(b < e) { + b = _eat_space(b, e); + if (b == e) + return 0; + + lb = b; + while((b != e) && *b != '\n') + b++; + + if (!pfd->fn(lb, b, pfd->minor)) + return lb - buffer; + } + + return count; +} + +static int _tok_cmp(const char *str, const char *b, const char *e) +{ + while (*str && b != e) { + if (*str < *b) + return -1; + + if (*str > *b) + return 1; + + str++, b++; + } + + if (!*str && b == e) + return 0; + + if (*str) + return 1; + + return -1; } diff --git a/driver/device-mapper/dm-table.c b/driver/device-mapper/dm-table.c index d3e8565f0..d1fa420d6 100644 --- a/driver/device-mapper/dm-table.c +++ b/driver/device-mapper/dm-table.c @@ -107,6 +107,45 @@ void dm_free_btree(struct mapped_device *md) __free_aligned(md->contexts); } +static int _setup_targets(struct mapped_device *md, struct device_table *t) +{ + int i; + offset_t low = 0; + md->num_targets = t->count; + md->targets = __aligned(sizeof(*md->targets) * md->num_targets, + NODE_SIZE); + for (i = 0; i < md->num_targets; i++) { + struct mapper *m = _find_mapper(t->map[i].type); + if (!m) + return 0; + + if (!m->ctr(low, t->map[i].high + 1, + t->map[i].context, md->contexts + i)) { + WARN("contructor for '%s' failed", m->name); + return 0; + } + + md->targets[i] = m->map; + } + + return 1; +} + +int dm_start_table(struct mapped_device *md) +{ + /* if this is active, suspend it */ +} + +int dm_add_entry(struct mapped_device *md, offset_t high, + dm_map_fn target, void *context) +{ + +} + +int dm_activate_table(struct mapped_device *md) +{ + +} diff --git a/driver/device-mapper/dm.c b/driver/device-mapper/dm.c index d7230f882..b3df9969e 100644 --- a/driver/device-mapper/dm.c +++ b/driver/device-mapper/dm.c @@ -132,7 +132,7 @@ const char *_name = "device-mapper"; int _version[3] = {1, 0, 0}; -spinlock_t _dev_lock; +struct rw_semaphore _dev_lock; static int _dev_count = 0; static struct mapped_device *_devs[MAX_DEVICES]; @@ -171,9 +171,9 @@ static int _request_fn(request_queue_t *q, int rw, struct buffer_head *bh); */ static int _init(void) { - _init_mds(); + init_rwsem(&_dev_lock); - if (!_register_std_targets()) + if (!dm_std_targets()) return -EIO; /* FIXME: better error value */ /* set up the arrays */ @@ -219,50 +219,6 @@ static void _fin(void) _version[0], _version[1], _version[2]); } -/* - * character device fns - */ -static int _ctl_open(struct inode *inode, struct file *file) -{ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - MOD_INC_USE_COUNT; - return 0; -} - -static int _ctl_close(struct inode *inode, struct file *file) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static int _ctl_ioctl(struct inode *inode, struct file *file, - uint command, ulong a) -{ - struct dm_request req; - - if (copy_from_user(&req, (void *) a, sizeof(req))) - return -EFAULT; - - switch (command) { - case MAPPED_DEVICE_CREATE: - return _create_dev(req.minor, req.name); - break; - - case MAPPED_DEVICE_DESTROY: - return _destroy_dev(req.minor); - break; - - default: - WARN("_ctl_ioctl: unknown command 0x%x", command); - return -EINVAL; - } - - return 0; -} - - /* * block device functions */ @@ -370,10 +326,14 @@ static int _request_fn(request_queue_t *q, int rw, struct buffer_head *bh) if (minor >= MAX_DEVICES) return -ENXIO; + down_read(&_dev_lock); md = _devs[minor]; - if (MINOR(md->dev != minor)) + up_read(&_dev_lock); + + if (!md) return -ENXIO; + down_read(&md->lock); for (l = 0; l < md->depth; l++) { next_node = ((KEYS_PER_NODE + 1) * next_node) + i; node = md->index[l] + (next_node * KEYS_PER_NODE); @@ -393,6 +353,8 @@ static int _request_fn(request_queue_t *q, int rw, struct buffer_head *bh) } else buffer_IO_error(bh); + + up_read(&md->lock); return ret; } @@ -426,12 +388,12 @@ static struct mapped_device *_alloc_dev(int minor) int i; struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL); - spin_lock(&_dev_lock); + down_write(&_dev_lock); minor = (minor < 0) ? __any_old_dev() : __specific_dev(minor); if (minor < 0) { WARN("no free devices available"); - spin_unlock(&_dev_lock); + up_write(&_dev_lock); kfree(md); return 0; } @@ -441,7 +403,7 @@ static struct mapped_device *_alloc_dev(int minor) clear_bit(md->status, DM_CREATED); _devs[minor] = md; - spin_unlock(&_dev_lock); + up_write(&_dev_lock); return *d; } @@ -450,60 +412,75 @@ static void _free_dev(struct mapped_device *md) { int i, minor = MINOR(md->dev); - spin_lock(&_dev_lock); + down_write(&_dev_lock); _devs[i] = 0; - spin_unlock(&_dev_lock); + up_write(&_dev_lock); kfree(md); } -static struct mapped_device *__find_dev(const char *name) +static inline struct mapped_device *__find_dev(const char *name) { int i; + return 0; +} + +struct mapped_device *dm_find_name(const char *name) +{ + int i; + struct mapped_device *md; + + down_read(&_dev_lock); for (i = 0; i < MAX_DEVICES; i++) if (_devs[i] && !strcmp(_devs[i]->name, name)) return _devs[i]; - return 0; + up_read(&_dev_lock); } -static int _create_dev(int minor, const char *name) +struct mapped_device *dm_find_minor(int minor) +{ + +} + +static int dm_create(int minor, const char *name) { struct mapped_device *md = _alloc_dev(minor); if (!md) return -ENXIO; - spin_lock(&_dev_lock); + down_write(&_dev_lock); if (__find_dev(name)) { WARN("device with that name already exists"); - spin_unlock(&_dev_lock); + up_write(&_dev_lock); _free_dev(md); return -EINVAL; } strcpy(md->name, name); - spin_unlock(&_dev_lock); - - dm_fs_add_lv(md); + up_write(&_dev_lock); } -static int _destroy_dev(int minor) +static int dm_remove(const char *name, int minor) { struct mapped_device *md; + int minor; - spin_lock(&_dev_lock); - md = _devs[minor]; + down_write(&_dev_lock); + if (!(md = __find_dev(name))) { + up_write(&_dev_lock); + return -ENXIO; + } + + minor = MINOR(md->dev); clear_bit(md->status, CREATED); - spin_unlock(&_dev_lock); dm_clear_table(md); - spin_lock(&_dev_lock); _free_dev(md); - spin_unlock(&_dev_lock); - - dm_fs_remove_lv(md); + _devs[minor] = 0; + up_write(&_dev_lock); return 0; } diff --git a/driver/device-mapper/dm.h b/driver/device-mapper/dm.h index d7d35d97f..60bcffc3a 100644 --- a/driver/device-mapper/dm.h +++ b/driver/device-mapper/dm.h @@ -36,11 +36,12 @@ enum { DM_LOADING, - DM_CREATED, DM_ACTIVE, }; struct mapped_device { + struct rw_semaphore lock; + kdev_t dev; char name[DM_NAME_LEN]; @@ -59,8 +60,6 @@ struct mapped_device { /* used by dm-fs.c */ devfs_handle_t devfs_entry; - char incomplete_input[64]; - }; /* dm-target.c */ @@ -76,11 +75,20 @@ struct target { struct target *dm_get_target(const char *name); int dm_std_targets(void); -/* dm.c */ +/* dm.c */ +struct mapped_device *dm_find_name(const char *name); +struct mapped_device *dm_find_minor(int minor); + +void dm_suspend(struct mapped_device *md); +void dm_activate(struct mapped_device *md); /* dm-table.c */ -int dm_build_btree(struct mapped_device *md); +int dm_start_table(struct mapped_device *md); +int dm_add_entry(struct mapped_device *md, offset_t high, + dm_map_fn target, void *context); +int dm_complete_table(struct mapped_device *md); + /* dm-fs.c */ int dm_init_fs(void);