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/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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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--) {
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user