1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-27 18:55:19 +03:00

Some more sync ups

o Error file routines (initial idea)
 o Various fixes for bugs
 o Tidy a few things
 o Added a bit of debugging code ready for when this gets tested
 o get_exclusive_write_access() function which will get moved into namei.c
   I hope (and rewritten accordingly), should this become the final version
   used.

Still a few more areas need thinking about, but in general much closer now I
think. Last area to sort out before testing is the symlink code which is
pretty close now... just a few more checks needed and the actual calls to
the core code.
This commit is contained in:
Steven Whitehouse 2001-10-11 20:29:00 +00:00
parent 7f64636f5f
commit c4bf9638e3
4 changed files with 121 additions and 32 deletions

View File

@ -20,33 +20,102 @@
*/
#include <linux/config.h>
#include <linux/list.h>
#include <linux/fs.h>
#include "dm.h"
struct dmfs_error {
struct list_head list;
unsigned len;
char *msg;
};
void dmfs_add_error(struct dm_table *t, unsigned num, char *str)
{
int len = strlen(str) + sizeof(dmfs_error) + 12;
struct dmfs_error *e = kmalloc(len, GFP_KERNEL);
if (e) {
e->msg = (char *)(e + 1);
e->len = sprintf(e->msg, "%8u: %s\n", num, str);
list_add(&e->list, &t->errors);
}
}
/*
* 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);
void dmfs_zap_errors(struct dm_table *t)
{
struct dmfs_error *e;
while(!list_empty(&t->errors)) {
e = list_entry(t->errors.next, struct dmfs_error, list);
kfree(e);
}
}
static struct dmfs_error find_initial_message(struct dn_table *t, loff_t *pos)
{
struct dmfs_error *e;
struct list_head *tmp, *head;
tmp = head = &t->errors;
for(;;) {
tmp = tmp->next;
if (tmp == head)
break;
e = list_entry(tmp, struct dmfs_error, list);
if (*pos < e->len)
return e;
(*pos) -= e->len;
}
return NULL;
}
static int copy_sequence(struct dm_table *t, struct dmfs_error *e, char *buf,
size_t size, loff_t offset)
{
char *from;
int amount;
int copied = 0;
do {
from = e->msg + offset;
amount = e->len - offset;
if (copy_to_user(buf, from, amount))
return -EFAULT;
buf += amount;
copied += amount;
size -= amount;
offset = 0;
if (e->list.next == &t->errors)
break;
e = list_entry(e->list.next, struct dmfs_error, list);
} while(size > 0);
return amount;
}
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 dm_table *t = dmi->table;
int copied = 0;
loff_t offset = *pos;
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
down(&dmi->sem);
if (dmi->table) {
struct dmfs_error *e = find_initial_message(t, &offset);
if (e) {
copied = copy_sequence(t, e, buf, size, offset);
if (copied > 0)
(*pos) += copied;
}
}
up(&dmi->sem);
return copied;

View File

@ -95,13 +95,17 @@ static int dmfs_lv_symlink(struct inode *dir, struct dentry *dentry,
int rv;
int l;
if (dentry->d_name.len != 6 || memcmp(dentry->d_name, "ACTIVE", 6) != 0)
return -EINVAL;
de = dmfs_verify_name(dir, symname);
if (IS_ERR(de))
return PTR_ERR(de);
dput(de);
inode = dmfs_create_symlink(dir, S_IRWXUGO);
if (IS_ERR(inode)) {
kfree(realname);
return PTR_ERR(inode);
}
@ -145,18 +149,11 @@ static int dmfs_lv_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (dentry->d_name[0] == '.')
return -EINVAL;
inode = dmfs_create_lv(dir, dentry, mode);
inode = dmfs_create_tdir(dir, mode);
if (!IS_ERR(inode)) {
md = dm_create(name, -1);
if (!IS_ERR(md)) {
inode->u.generic_ip = md;
md->inode = inode;
d_instantiate(dentry, inode);
dget(dentry);
return 0;
}
iput(inode);
return PTR_ERR(md);
d_instantiate(dentry, inode);
dget(dentry);
return 0;
}
return PTR_ERR(inode);
}
@ -231,13 +228,21 @@ static struct dm_root_inode_operations = {
rmdir: dmfs_lv_rmdir,
};
struct inode *dmfs_create_lv(struct super_block *sb, int mode)
struct inode *dmfs_create_lv(struct super_block *sb, int mode, struct dentry *dentry)
{
struct inode *inode = dmfs_new_inode(sb, mode | S_IFDIR);
struct mapped_device *md;
char *name = dentry->d_name.name;
if (inode) {
inode->i_fop = &dmfs_lv_file_operations;
inode->i_op = &dmfs_lv_dir_operations;
md = dm_create(name, -1);
if (md == NULL) {
iput(inode);
return NULL;
}
DMFS_I(inode)->md = md;
}
return inode;

View File

@ -52,18 +52,11 @@ static int dmfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (dentry->d_name[0] == '.')
return -EINVAL;
inode = dmfs_create_lv(dir, dentry, mode);
inode = dmfs_create_lv(dir, mode, dentry);
if (!IS_ERR(inode)) {
md = dm_create(name, -1);
if (!IS_ERR(md)) {
inode->u.generic_ip = md;
md->inode = inode;
d_instantiate(dentry, inode);
dget(dentry);
return 0;
}
iput(inode);
return PTR_ERR(md);
d_instantiate(dentry, inode);
dget(dentry);
return 0;
}
return PTR_ERR(inode);
}

View File

@ -81,7 +81,11 @@ static void dmfs_parse_line(struct dmfs_table *t, unsigned num, char *str)
if (ttype) {
msg = "This message should never appear (constructor error)";
rv = ttype->ctr(t, start, size, p, &context);
msg = context;
if (rv == 0)) {
printk(KERN_DEBUG "%ul %ul %s %s", start, size,
ttype->name,
ttype->print(context));
msg = "Error adding target to table";
high = start + (size - 1);
if (dm_table_add_target(t, high, ttype, context) == 0)
@ -285,13 +289,31 @@ static int dmfs_commit_write(struct file *file, struct page *page,
return 0;
}
/*
* There is a small race here in that two processes might call this at
* the same time and both fail. So its a fail safe race :-) This should
* move into namei.c (and thus use the spinlock and do this properly)
* at some stage if we continue to use this set of functions for ensuring
* exclusive write access to the file
*/
static int get_exclusive_write_access(struct inode *inode)
{
if (get_write_access(inode))
return -1;
if (atomic_read(&inode->i_writecount) != 1) {
put_write_access(inode);
return -1;
}
return 0;
}
static int dmfs_table_open(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_parent->d_inode;
if (file->f_mode & FMODE_WRITE) {
if (get_write_access(inode))
if (get_exclusive_write_access(inode))
return -EPERM;
}