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:
parent
dcca4d2081
commit
161720b500
@ -22,6 +22,19 @@
|
||||
#include <linux/config.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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "dm.h"
|
||||
|
||||
static int is_identifier(const char *str, int len)
|
||||
{
|
||||
while(len--) {
|
||||
|
@ -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)
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <linux/config.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -21,9 +21,8 @@
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/parser.h>
|
||||
#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;
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <linux/config.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user