mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
o Kill write funcs for error/status files
o Redo write logic for table file o Relax rules for symlink content by removing the rewriting function Well I probably won't get a chance to work on this tomorrow, so this is my changeset to date.
This commit is contained in:
parent
2f1a7a61fc
commit
ac4fc0b84d
@ -28,13 +28,6 @@ static ssize_t dmfs_error_read(struct file *file, char *buf, size_t size, loff_t
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t dmfs_error_write(struct file *file, const char *buf, size_t size, loff_t *pos)
|
|
||||||
{
|
|
||||||
struct inode *inode = file->f_dentry->d_inode;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dmfs_error_sync(struct file *file, struct dentry *dentry, int datasync)
|
static int dmfs_error_sync(struct file *file, struct dentry *dentry, int datasync)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -42,7 +35,6 @@ static int dmfs_error_sync(struct file *file, struct dentry *dentry, int datasyn
|
|||||||
|
|
||||||
static struct dm_table_file_operations = {
|
static struct dm_table_file_operations = {
|
||||||
read: dmfs_error_read,
|
read: dmfs_error_read,
|
||||||
write: dmfs_error_write,
|
|
||||||
fsync: dmfs_error_sync,
|
fsync: dmfs_error_sync,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,38 +33,25 @@ struct dentry *dmfs_verify_name(struct inode *dir, char *name)
|
|||||||
int err = -ENOENT;
|
int err = -ENOENT;
|
||||||
|
|
||||||
if (path_init(name, LOOKUP_FOLLOW, &nd))
|
if (path_init(name, LOOKUP_FOLLOW, &nd))
|
||||||
err = path_walk(path, &nd);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
err = path_walk(path, &nd);
|
||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
goto err_out;
|
||||||
|
|
||||||
|
err = -EINVAL;
|
||||||
if (nd.mnt->mnt->sb != dir->i_sb)
|
if (nd.mnt->mnt->sb != dir->i_sb)
|
||||||
goto err;
|
goto err_out;
|
||||||
|
|
||||||
if (nd.dentry->d_parent != dir)
|
if (nd.dentry->d_parent != dir)
|
||||||
goto err;
|
goto err_out;
|
||||||
|
|
||||||
dget(nd.dentry);
|
dget(nd.dentry);
|
||||||
path_release(nd);
|
path_release(nd);
|
||||||
return nd.dentry;
|
return nd.dentry;
|
||||||
err:
|
err_out:
|
||||||
path_release(nd);
|
path_release(nd);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(err);
|
||||||
}
|
|
||||||
|
|
||||||
char *dmfs_translate_name(struct dentry *de)
|
|
||||||
{
|
|
||||||
int len = de->d_name.len + 3;
|
|
||||||
char *n = kmalloc(len);
|
|
||||||
if (n) {
|
|
||||||
char *p = n;
|
|
||||||
*p++ = '.';
|
|
||||||
*p++ = '/';
|
|
||||||
memcmp(p, de->d_name.name, de->d_name.len);
|
|
||||||
p += de->d_name.len
|
|
||||||
*p = 0;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct inode *dmfs_create_symlink(struct inode *dir, int mode)
|
struct inode *dmfs_create_symlink(struct inode *dir, int mode)
|
||||||
@ -91,7 +78,6 @@ static int dmfs_lv_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
{
|
{
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct dentry *de;
|
struct dentry *de;
|
||||||
char *realname;
|
|
||||||
int rv;
|
int rv;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
@ -99,11 +85,6 @@ static int dmfs_lv_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
if (IS_ERR(de))
|
if (IS_ERR(de))
|
||||||
return PTR_ERR(de);
|
return PTR_ERR(de);
|
||||||
|
|
||||||
realname = dmfs_translate_name(de);
|
|
||||||
dput(de);
|
|
||||||
if (realname == NULL);
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
inode = dmfs_create_symlink(dir, S_IRWXUGO);
|
inode = dmfs_create_symlink(dir, S_IRWXUGO);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
kfree(realname);
|
kfree(realname);
|
||||||
@ -113,12 +94,11 @@ static int dmfs_lv_symlink(struct inode *dir, struct dentry *dentry,
|
|||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
dget(dentry);
|
dget(dentry);
|
||||||
|
|
||||||
l = strlen(realname) + 1;
|
l = strlen(symname) + 1;
|
||||||
rv = block_symlink(inode, realname, l);
|
rv = block_symlink(inode, symname, l);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
}
|
}
|
||||||
kfree(realname);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -218,16 +198,6 @@ static struct dentry *dmfs_lv_lookup(struct inode *dir, struct dentry *dentry)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dmfs_lv_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|
||||||
struct inode *new_dir, struct dentry *new_dentry)
|
|
||||||
{
|
|
||||||
/* Can only rename - not move between directories! */
|
|
||||||
if (old_dir != new_dir)
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
return -EINVAL; /* FIXME: a change of LV name here */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dmfs_lv_sync(struct file *file, struct dentry *dentry, int datasync)
|
static int dmfs_lv_sync(struct file *file, struct dentry *dentry, int datasync)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -245,7 +215,6 @@ static struct dm_root_inode_operations = {
|
|||||||
symlink: dmfs_lv_symlink,
|
symlink: dmfs_lv_symlink,
|
||||||
mkdir: dmfs_lv_mkdir,
|
mkdir: dmfs_lv_mkdir,
|
||||||
rmdir: dmfs_lv_rmdir,
|
rmdir: dmfs_lv_rmdir,
|
||||||
rename: dmfs_lv_rename,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inode *dmfs_create_lv(struct super_block *sb, int mode)
|
struct inode *dmfs_create_lv(struct super_block *sb, int mode)
|
||||||
|
@ -27,11 +27,6 @@ static ssize_t dmfs_status_read(struct file *file, char *buf, size_t size, loff_
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t dmfs_status_write(struct file *file, const char *buf, size_t size, loff_t *pos)
|
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -39,7 +34,6 @@ static int dmfs_status_sync(struct file *file, struct dentry *dentry, int datasy
|
|||||||
|
|
||||||
static struct dm_table_file_operations = {
|
static struct dm_table_file_operations = {
|
||||||
read: dmfs_status_read,
|
read: dmfs_status_read,
|
||||||
write: dmfs_status_write,
|
|
||||||
fsync: dmfs_status_sync,
|
fsync: dmfs_status_sync,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,6 +252,29 @@ static int dmfs_commit_write(struct file *file, struct page *page,
|
|||||||
return 0;
|
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))
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dmfs_table_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
if (file->f_mode & FMODE_WRITE) {
|
||||||
|
struct dentry *dentry = file->f_dentry;
|
||||||
|
struct inode *inode = dentry->d_parent->d_inode;
|
||||||
|
|
||||||
|
put_write_access(inode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int dmfs_table_sync(struct file *file, struct dentry *dentry, int datasync)
|
static int dmfs_table_sync(struct file *file, struct dentry *dentry, int datasync)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -268,6 +291,8 @@ 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,
|
||||||
|
open: dmfs_table_open,
|
||||||
|
release: dmfs_table_release,
|
||||||
fsync: dmfs_table_sync,
|
fsync: dmfs_table_sync,
|
||||||
release: dmfs_release,
|
release: dmfs_release,
|
||||||
};
|
};
|
||||||
|
@ -29,89 +29,18 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
static inline positive(struct dentry *dentry)
|
int dm_lock_tdir(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return dentry->d_inode && !d_unhashed(dentry);
|
struct file file = { f_dentry: dentry };
|
||||||
}
|
|
||||||
|
|
||||||
static int dm_deny_write_access(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
struct file file { f_dentry: &dentry };
|
|
||||||
|
|
||||||
return deny_write_access(&file);
|
return deny_write_access(&file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dm_allow_dentry_list(struct dentry *list[], int i)
|
void dm_unlock_tdir(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
int x;
|
struct file file = { f_dentry: dentry };
|
||||||
for(x = 0; x < i; x++)
|
|
||||||
atomic_inc(&list[x]->d_inode->i_writecount);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dm_deny_dentry_list(struct dentry *list[], int i)
|
allow_write_access(&file);
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
for(x = 0; x < i; x++) {
|
|
||||||
rv = dm_deny_write_access(list[x]);
|
|
||||||
if (rv)
|
|
||||||
goto error:
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
error:
|
|
||||||
if (x > 0) {
|
|
||||||
dm_allow_dentry_list(list, x - 1);
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dm_child_list(struct dentry *de_list[], struct dentry *dentry)
|
|
||||||
{
|
|
||||||
struct list_head *list;
|
|
||||||
int i = 0;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
spin_lock(&dcache_lock);
|
|
||||||
list = dentry->d_subdirs.next;
|
|
||||||
|
|
||||||
while(list != &dentry->d_subdirs) {
|
|
||||||
struct dentry *de = list_entry(list, struct dentry, d_child);
|
|
||||||
|
|
||||||
if (positive(de))
|
|
||||||
de_list[i++] = dget(de);
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
spin_unlock(&dcache_lock);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dm_lock_tdir(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
struct dentry de_list[4];
|
|
||||||
int n, rv;
|
|
||||||
|
|
||||||
rv = n = dm_child_list(de_list, dentry);
|
|
||||||
if (n) {
|
|
||||||
rv = deny_dentry_list(de_list, n);
|
|
||||||
dput_list(de_list, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dm_unlock_tdir(struct dentry *dentry)
|
|
||||||
{
|
|
||||||
struct dentry de_list[4];
|
|
||||||
|
|
||||||
rv = dm_child_list(de_list, dentry);
|
|
||||||
if (rv) {
|
|
||||||
dm_allow_dentry_list(de_list, rv);
|
|
||||||
dput_list(de_list, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dmfs_tdir_unlink(struct inode *dir, struct dentry *dentry)
|
static int dmfs_tdir_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
|
Loading…
Reference in New Issue
Block a user