1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

o Everybody needs dm.h

o Fixed to work with highmem
 o Added dmfs private inode struct for lv and table directories
 o Fixed a number of errors/typos
 o Status file read returns 0 so we can leave this until we've actually got
   something to report in this now.
 o New locking on tables.... still some issues to be worked out here but
   closer now I think.
 o Now use mapping of table directory to hold pages rather than mapping of
   table file inode. Need to write a note to myself to fix issues with the
   file length at the same time....

Well thats enough for tonight I think. The error file will be part of
tomorrows work.
This commit is contained in:
Steven Whitehouse 2001-10-10 21:49:21 +00:00
parent dcca4d2081
commit 161720b500
7 changed files with 119 additions and 44 deletions

View File

@ -22,6 +22,19 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#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) 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); 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)) if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT; return -EFAULT;
down(&dmi->sem);
if (dmi->table) {
}
up(&dmi->sem);
return copied; return copied;
} }

View File

@ -25,6 +25,8 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "dm.h"
extern struct dmfs_address_space_operations; extern struct dmfs_address_space_operations;
struct dentry *dmfs_verify_name(struct inode *dir, char *name) 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; 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)) if (!(inode->i_mode & S_IFLNK))
return -EINVAL; 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 *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) { 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_fop = &dmfs_lv_file_operations;
inode->i_op = &dmfs_lv_dir_operations; inode->i_op = &dmfs_lv_dir_operations;
} }

View File

@ -25,6 +25,8 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "dm.h"
static int is_identifier(const char *str, int len) static int is_identifier(const char *str, int len)
{ {
while(len--) { while(len--) {

View File

@ -24,7 +24,7 @@
static ssize_t dmfs_status_read(struct file *file, char *buf, size_t size, loff_t *pos) 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) static int dmfs_status_sync(struct file *file, struct dentry *dentry, int datasync)

View File

@ -22,6 +22,8 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "dm.h"
#define DMFS_MAGIC 0x444D4653 #define DMFS_MAGIC 0x444D4653
extern struct inode *dmfs_create_root(struct super_block *sb, int); 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; 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;
}

View File

@ -21,9 +21,8 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/parser.h>
#include "dm.h"
#include "dm.h"
static inline char *next_token(char **p) static inline char *next_token(char **p)
{ {
@ -37,43 +36,65 @@ static inline char *next_token(char **p)
return r; 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; char *p = str;
const char *delim = " \t";
const char *tok; const char *tok;
offset_t start, size, high; offset_t start, size, high;
void *context; void *context;
struct target_type *ttype; struct target_type *ttype;
int rv = 0;
char *msg;
msg = "No start argument";
tok = next_token(&p); tok = next_token(&p);
if (!tok) if (!tok)
return -1; goto out;
start = simple_strtoul(tok, NULL, 10); start = simple_strtoul(tok, NULL, 10);
msg = "No size argument";
tok = next_token(&p); tok = next_token(&p);
if (!tok) if (!tok)
return -1; goto out;
size = simple_strtoul(tok, NULL, 10); 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); tok = next_token(&p);
if (!tok) if (!tok)
return -1; goto out;
msg = "Target type unknown";
ttype = dm_get_target_type(tok); ttype = dm_get_target_type(tok);
if (ttype) { if (ttype) {
context = ttype->ctr(t, start, size, p); msg = "This message should never appear (constructor error)";
if (!IS_ERR(context)) { rv = ttype->ctr(t, start, size, p, &context);
if (rv == 0)) {
msg = "Error adding target to table";
high = start + (size - 1); high = start + (size - 1);
if (dm_table_add_target(t, high, ttype, context) == 0) if (dm_table_add_target(t, high, ttype, context) == 0)
return 0; return;
ttype->dtr(t, context); ttype->dtr(t, context);
} }
dm_put_target_type(ttype); 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) static int dmfs_copy(char *dst, int dstlen, char *src, int srclen, int *flag)
{ {
int copied = 0; int copied = 0;
@ -95,7 +116,7 @@ end_of_line:
goto out; 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; int copied;
@ -105,15 +126,20 @@ static int dmfs_parse_page(struct dm_table *t, char *buf, int len, char *tmp, un
buf += copied; buf += copied;
len -= copied; len -= copied;
if (*tmpl + copied == PAGE_SIZE - 1) if (*tmpl + copied == PAGE_SIZE - 1)
return -1; goto line_too_long;
*tmpl = copied; *tmpl = copied;
if (flag) { if (flag) {
if (dmfs_parse_line(t, tmp)) dmfs_parse_line(t, *num, tmp);
return -1; (*num)++;
*tmpl = 0; *tmpl = 0;
} }
} while(len > 0); } while(len > 0);
return 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) 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; unsigned long rem = 0;
struct dm_table *t; struct dm_table *t;
struct page *pg, **hash; struct page *pg, **hash;
int num = 0;
if (inode->i_size == 0) if (inode->i_size == 0)
return NULL; return NULL;
@ -141,9 +168,8 @@ static struct dm_table *dmfs_parse(struct inode *inode)
return NULL; return NULL;
} }
down(&inode->i_sem); end_index = inode->i_size >> PAGE_CACHE_SHIFT;
end_index = inode->i_size >> PAGE_CACHE_SIZE; end_offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
end_offset = inode->i_size & (PAGE_CAHE_SIZE - 1);
do { do {
unsigned long end = (index == end_index) ? end_offset : PAGE_CACHE_SIZE; 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); spin_unlock(&pagecache_lock);
if (pg) { if (pg) {
char *kaddr;
int rv;
if (!Page_Uptodate(pg)) if (!Page_Uptodate(pg))
goto broken; 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; goto parse_error;
} }
@ -167,8 +200,6 @@ static struct dm_table *dmfs_parse(struct inode *inode)
index++; index++;
} while(index != end_index); } while(index != end_index);
up(&inode->i_sem);
free_page(page); free_page(page);
if (dm_table_complete(t) == 0) if (dm_table_complete(t) == 0)
return t; return t;
@ -177,14 +208,12 @@ static struct dm_table *dmfs_parse(struct inode *inode)
return NULL; return NULL;
broken: broken:
up(&inode->i_sem);
printk(KERN_ERR "dmfs_parse: Page not uptodate\n"); printk(KERN_ERR "dmfs_parse: Page not uptodate\n");
free_page(page); free_page(page);
dm_put_table(t); dm_put_table(t);
return NULL; return NULL;
parse_error: parse_error:
up(&inode->i_sem);
printk(KERN_ERR "dmfs_parse: Parse error\n"); printk(KERN_ERR "dmfs_parse: Parse error\n");
free_page(page); free_page(page);
dm_put_table(t); dm_put_table(t);
@ -193,17 +222,21 @@ parse_error:
static int dmfs_release(struct inode *inode, struct file *f) static int dmfs_release(struct inode *inode, struct file *f)
{ {
struct dmfs_i *dmi = inode->u.generic_ip;
struct dm_table *table; struct dm_table *table;
if (!(f->f_mode & S_IWUGO)) if (!(f->f_mode & S_IWUGO))
return 0; return 0;
down(&dmi->sem);
table = dmfs_parse(inode); table = dmfs_parse(inode);
if (table) { if (table) {
dm_put_table((struct dm_table *)inode->u.generic_ip); if (dmi->table)
inode->u.generic_ip = table; dm_put_table(dmi->table);
dmi->table = table;
} }
up(&dmi->sem);
return 0; return 0;
} }
@ -290,7 +323,7 @@ struct dmfs_address_space_operations = {
static struct dmfs_table_file_operations = { static struct dmfs_table_file_operations = {
llseek: generic_file_llseek, llseek: generic_file_llseek,
read: generic_file_read, read: generic_file_read,
write: generic_file_write, write: generic_file_write, /* FIXME: Needs to hold dmi->sem */
open: dmfs_table_open, open: dmfs_table_open,
release: dmfs_table_release, release: dmfs_table_release,
fsync: dmfs_table_sync, 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_mapping->a_ops = &dmfs_address_space_operations;
inode->i_fop = &dmfs_table_file_operations; inode->i_fop = &dmfs_table_file_operations;
inode->i_op = &dmfs_table_inode_operations; inode->i_op = &dmfs_table_inode_operations;
inode->i_mapping = dir->i_mapping;
} }
return inode; return inode;

View File

@ -24,6 +24,8 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fs.h> #include <linux/fs.h>
#include "dm.h"
extern struct inode *dmfs_create_error(struct inode *, int); extern struct inode *dmfs_create_error(struct inode *, int);
extern struct inode *dmfs_create_table(struct inode *, int); extern struct inode *dmfs_create_table(struct inode *, int);
extern struct inode *dmfs_create_status(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) 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--; inode->i_nlink--;
dput(dentry); dput(dentry);
return 0; 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 *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) { 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_fop = &dmfs_tdir_file_operations;
inode->i_op = &dmfs_tdir_dir_operations; inode->i_op = &dmfs_tdir_dir_operations;
} }