diff --git a/driver/device-mapper/dmfs-error.c b/driver/device-mapper/dmfs-error.c index 510e9f448..011426ca1 100644 --- a/driver/device-mapper/dmfs-error.c +++ b/driver/device-mapper/dmfs-error.c @@ -22,6 +22,19 @@ #include #include +#include "dm.h" + +void dmfs_add_error(struct dm_table *t, unsigned num, char *str) +{ + +} + +/* + * Assuming that we allow modules to call this rather than passing the message + * back. Not sure which approach to take yet. + */ +EXPORT_SYMBOL(dmfs_add_error); + static ssize_t dmfs_error_read(struct file *file, char *buf, size_t size, loff_t *pos) { struct dmfs_i *dmi = DMFS_I(file->f_dentry->d_parent->d_inode); @@ -31,6 +44,11 @@ static ssize_t dmfs_error_read(struct file *file, char *buf, size_t size, loff_t if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; + down(&dmi->sem); + if (dmi->table) { + + } + up(&dmi->sem); return copied; } diff --git a/driver/device-mapper/dmfs-lv.c b/driver/device-mapper/dmfs-lv.c index fe6f771e9..8e681deb8 100644 --- a/driver/device-mapper/dmfs-lv.c +++ b/driver/device-mapper/dmfs-lv.c @@ -25,6 +25,8 @@ #include #include +#include "dm.h" + extern struct dmfs_address_space_operations; struct dentry *dmfs_verify_name(struct inode *dir, char *name) @@ -73,8 +75,10 @@ struct inode *dmfs_create_symlink(struct inode *dir, int mode) return inode; } -static int dmfs_lv_unlink(struct inode *inode, struct dentry *dentry) +static int dmfs_lv_unlink(struct inode *dir, struct dentry *dentry) { + struct inode *inode = dentry->d_inode; + if (!(inode->i_mode & S_IFLNK)) return -EINVAL; @@ -229,16 +233,9 @@ static struct dm_root_inode_operations = { struct inode *dmfs_create_lv(struct super_block *sb, int mode) { - struct inode *inode = new_inode(sb); + struct inode *inode = dmfs_new_inode(sb, mode | S_IFDIR); if (inode) { - inode->i_mode = mode | S_IFDIR; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_rdev = NODEV; - inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_fop = &dmfs_lv_file_operations; inode->i_op = &dmfs_lv_dir_operations; } diff --git a/driver/device-mapper/dmfs-root.c b/driver/device-mapper/dmfs-root.c index 7fd7e94db..4930d2a69 100644 --- a/driver/device-mapper/dmfs-root.c +++ b/driver/device-mapper/dmfs-root.c @@ -25,6 +25,8 @@ #include #include +#include "dm.h" + static int is_identifier(const char *str, int len) { while(len--) { diff --git a/driver/device-mapper/dmfs-status.c b/driver/device-mapper/dmfs-status.c index 300db35f6..91788e78f 100644 --- a/driver/device-mapper/dmfs-status.c +++ b/driver/device-mapper/dmfs-status.c @@ -24,7 +24,7 @@ static ssize_t dmfs_status_read(struct file *file, char *buf, size_t size, loff_t *pos) { - return size; + return 0; } static int dmfs_status_sync(struct file *file, struct dentry *dentry, int datasync) diff --git a/driver/device-mapper/dmfs-super.c b/driver/device-mapper/dmfs-super.c index 055c235c7..ad9b41c61 100644 --- a/driver/device-mapper/dmfs-super.c +++ b/driver/device-mapper/dmfs-super.c @@ -22,6 +22,8 @@ #include #include +#include "dm.h" + #define DMFS_MAGIC 0x444D4653 extern struct inode *dmfs_create_root(struct super_block *sb, int); @@ -84,4 +86,28 @@ struct super_block *dmfs_read_super(struct super_block *sb, void *data, int sile return sb; } +struct inode *dmfs_new_inode(struct super_block *sb, int mode) +{ + struct inode *inode = new_inode(sb); + struct dmfs_i *dmi; + if (inode) { + inode->i_mode = mode; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_blksize = PAGE_CACHE_SIZE; + inode->i_blocks = 0; + inode->i_rdev = NODEV; + inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; + + dmi = kmalloc(sizeof(struct dmfs_i), GFP_KERNEL); + if (dmi == NULL) { + iput(inode); + return NULL; + } + memset(dmi, sizeof(struct dmfs_i), 0); + init_MUTEX(&dmi->sem); + inode->generic_ip = dmi; + } + return inode; +} diff --git a/driver/device-mapper/dmfs-table.c b/driver/device-mapper/dmfs-table.c index 8cabe8ce7..9525db9ba 100644 --- a/driver/device-mapper/dmfs-table.c +++ b/driver/device-mapper/dmfs-table.c @@ -21,9 +21,8 @@ #include #include -#include -#include "dm.h" +#include "dm.h" static inline char *next_token(char **p) { @@ -37,43 +36,65 @@ static inline char *next_token(char **p) return r; } -static int dmfs_parse_line(struct dmfs_table *t, char *str) +static offset_t start_of_next_range(struct dm_table *t) +{ + offset_t n = 0; + if (t->num_targets) { + n = t->highs[t->num_targets - 1] + 1; + } + return n; +} + +static void dmfs_parse_line(struct dmfs_table *t, unsigned num, char *str) { char *p = str; - const char *delim = " \t"; const char *tok; offset_t start, size, high; void *context; struct target_type *ttype; + int rv = 0; + char *msg; + msg = "No start argument"; tok = next_token(&p); if (!tok) - return -1; + goto out; start = simple_strtoul(tok, NULL, 10); + msg = "No size argument"; tok = next_token(&p); if (!tok) - return -1; + goto out; size = simple_strtoul(tok, NULL, 10); + msg = "Gap in table"; + if (start != start_of_next_range(t)) + goto out; + + msg = "No target type"; tok = next_token(&p); if (!tok) - return -1; + goto out; + msg = "Target type unknown"; ttype = dm_get_target_type(tok); if (ttype) { - context = ttype->ctr(t, start, size, p); - if (!IS_ERR(context)) { + msg = "This message should never appear (constructor error)"; + rv = ttype->ctr(t, start, size, p, &context); + if (rv == 0)) { + msg = "Error adding target to table"; high = start + (size - 1); if (dm_table_add_target(t, high, ttype, context) == 0) - return 0; + return; ttype->dtr(t, context); } dm_put_target_type(ttype); } - return -1; +out: + dmfs_add_error(t, num, msg); } + static int dmfs_copy(char *dst, int dstlen, char *src, int srclen, int *flag) { int copied = 0; @@ -95,7 +116,7 @@ end_of_line: goto out; } -static int dmfs_parse_page(struct dm_table *t, char *buf, int len, char *tmp, unsigned long *tmpl) +static int dmfs_parse_page(struct dm_table *t, char *buf, int len, char *tmp, unsigned long *tmpl, int *num) { int copied; @@ -105,15 +126,20 @@ static int dmfs_parse_page(struct dm_table *t, char *buf, int len, char *tmp, un buf += copied; len -= copied; if (*tmpl + copied == PAGE_SIZE - 1) - return -1; + goto line_too_long; *tmpl = copied; if (flag) { - if (dmfs_parse_line(t, tmp)) - return -1; + dmfs_parse_line(t, *num, tmp); + (*num)++; *tmpl = 0; } } while(len > 0); return 0; + +line_too_long: + dmfs_add_error(t, *num, "Line too long"); + /* FIXME: Add code to recover from this */ + return -1; } static struct dm_table *dmfs_parse(struct inode *inode) @@ -126,6 +152,7 @@ static struct dm_table *dmfs_parse(struct inode *inode) unsigned long rem = 0; struct dm_table *t; struct page *pg, **hash; + int num = 0; if (inode->i_size == 0) return NULL; @@ -141,9 +168,8 @@ static struct dm_table *dmfs_parse(struct inode *inode) return NULL; } - down(&inode->i_sem); - end_index = inode->i_size >> PAGE_CACHE_SIZE; - end_offset = inode->i_size & (PAGE_CAHE_SIZE - 1); + end_index = inode->i_size >> PAGE_CACHE_SHIFT; + end_offset = inode->i_size & (PAGE_CACHE_SIZE - 1); do { unsigned long end = (index == end_index) ? end_offset : PAGE_CACHE_SIZE; @@ -156,10 +182,17 @@ static struct dm_table *dmfs_parse(struct inode *inode) spin_unlock(&pagecache_lock); if (pg) { + char *kaddr; + int rv; + if (!Page_Uptodate(pg)) goto broken; - if (dmfs_parse_page(t, pg, end, (char *)page, &rem)) + kaddr = kmap(pg); + rv = dmfs_parse_page(t, kaddr, end, (char *)page, &rem); + kunmap(pg); + + if (rv) goto parse_error; } @@ -167,8 +200,6 @@ static struct dm_table *dmfs_parse(struct inode *inode) index++; } while(index != end_index); - up(&inode->i_sem); - free_page(page); if (dm_table_complete(t) == 0) return t; @@ -177,14 +208,12 @@ static struct dm_table *dmfs_parse(struct inode *inode) return NULL; broken: - up(&inode->i_sem); printk(KERN_ERR "dmfs_parse: Page not uptodate\n"); free_page(page); dm_put_table(t); return NULL; parse_error: - up(&inode->i_sem); printk(KERN_ERR "dmfs_parse: Parse error\n"); free_page(page); dm_put_table(t); @@ -193,17 +222,21 @@ parse_error: static int dmfs_release(struct inode *inode, struct file *f) { + struct dmfs_i *dmi = inode->u.generic_ip; struct dm_table *table; if (!(f->f_mode & S_IWUGO)) return 0; + down(&dmi->sem); table = dmfs_parse(inode); if (table) { - dm_put_table((struct dm_table *)inode->u.generic_ip); - inode->u.generic_ip = table; + if (dmi->table) + dm_put_table(dmi->table); + dmi->table = table; } + up(&dmi->sem); return 0; } @@ -290,7 +323,7 @@ struct dmfs_address_space_operations = { static struct dmfs_table_file_operations = { llseek: generic_file_llseek, read: generic_file_read, - write: generic_file_write, + write: generic_file_write, /* FIXME: Needs to hold dmi->sem */ open: dmfs_table_open, release: dmfs_table_release, fsync: dmfs_table_sync, @@ -315,6 +348,7 @@ int dmfs_create_table(struct inode *dir, int mode) inode->i_mapping->a_ops = &dmfs_address_space_operations; inode->i_fop = &dmfs_table_file_operations; inode->i_op = &dmfs_table_inode_operations; + inode->i_mapping = dir->i_mapping; } return inode; diff --git a/driver/device-mapper/dmfs-tdir.c b/driver/device-mapper/dmfs-tdir.c index 634744ee9..d412d73cc 100644 --- a/driver/device-mapper/dmfs-tdir.c +++ b/driver/device-mapper/dmfs-tdir.c @@ -24,6 +24,8 @@ #include #include +#include "dm.h" + extern struct inode *dmfs_create_error(struct inode *, int); extern struct inode *dmfs_create_table(struct inode *, int); extern struct inode *dmfs_create_status(struct inode *, int); @@ -45,6 +47,9 @@ void dm_unlock_tdir(struct dentry *dentry) static int dmfs_tdir_unlink(struct inode *dir, struct dentry *dentry) { + struct inode *inode = dentry->d_inode; + + inode->i_mapping = &inode->i_data; inode->i_nlink--; dput(dentry); return 0; @@ -131,16 +136,9 @@ static struct dmfs_tdir_inode_operations = { struct inode *dmfs_create_tdir(struct inode *dir, struct dentry *dentry, int mode) { - struct inode *inode = new_inode(sb); + struct inode *inode = dmfs_new_inode(sb, mode | S_IFDIR); if (inode) { - inode->i_mode = mode | S_IFDIR; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_blocks = 0; - inode->i_rdev = NODEV; - inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_fop = &dmfs_tdir_file_operations; inode->i_op = &dmfs_tdir_dir_operations; }