Commit 173d4827 authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-driverfs-rewrite
parents 59ece965 d4a3557e
...@@ -106,13 +106,17 @@ static void fill_devpath(struct device * dev, char * path, int length) ...@@ -106,13 +106,17 @@ static void fill_devpath(struct device * dev, char * path, int length)
static int create_symlink(struct driver_dir_entry * parent, char * name, char * path) static int create_symlink(struct driver_dir_entry * parent, char * name, char * path)
{ {
struct driver_file_entry * entry; struct driver_file_entry * entry;
int error;
entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL); entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL);
if (!entry) if (!entry)
return -ENOMEM; return -ENOMEM;
entry->name = name; entry->name = name;
entry->mode = S_IRUGO; entry->mode = S_IRUGO;
return driverfs_create_symlink(parent,entry,path); error = driverfs_create_symlink(parent,entry,path);
if (error)
kfree(entry);
return error;
} }
int device_bus_link(struct device * dev) int device_bus_link(struct device * dev)
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -51,7 +50,6 @@ ...@@ -51,7 +50,6 @@
static struct super_operations driverfs_ops; static struct super_operations driverfs_ops;
static struct file_operations driverfs_file_operations; static struct file_operations driverfs_file_operations;
static struct inode_operations driverfs_dir_inode_operations; static struct inode_operations driverfs_dir_inode_operations;
static struct dentry_operations driverfs_dentry_dir_ops;
static struct dentry_operations driverfs_dentry_file_ops; static struct dentry_operations driverfs_dentry_file_ops;
static struct address_space_operations driverfs_aops; static struct address_space_operations driverfs_aops;
...@@ -136,6 +134,9 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in ...@@ -136,6 +134,9 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in
struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev); struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev);
int error = -EPERM; int error = -EPERM;
if (dentry->d_inode)
return -EEXIST;
/* only allow create if ->d_fsdata is not NULL (so we can assume it /* only allow create if ->d_fsdata is not NULL (so we can assume it
* comes from the driverfs API below. */ * comes from the driverfs API below. */
if (dentry->d_fsdata && inode) { if (dentry->d_fsdata && inode) {
...@@ -149,22 +150,19 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in ...@@ -149,22 +150,19 @@ static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, in
static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{ {
int res; int res;
lock_kernel(); mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
dentry->d_op = &driverfs_dentry_dir_ops; res = driverfs_mknod(dir, dentry, mode, 0);
res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!res) if (!res)
dir->i_nlink++; dir->i_nlink++;
unlock_kernel();
return res; return res;
} }
static int driverfs_create(struct inode *dir, struct dentry *dentry, int mode) static int driverfs_create(struct inode *dir, struct dentry *dentry, int mode)
{ {
int res; int res;
lock_kernel(); mode = (mode & S_IALLUGO) | S_IFREG;
dentry->d_op = &driverfs_dentry_file_ops; dentry->d_op = &driverfs_dentry_file_ops;
res = driverfs_mknod(dir, dentry, mode | S_IFREG, 0); res = driverfs_mknod(dir, dentry, mode, 0);
unlock_kernel();
return res; return res;
} }
...@@ -173,6 +171,9 @@ static int driverfs_symlink(struct inode * dir, struct dentry *dentry, const cha ...@@ -173,6 +171,9 @@ static int driverfs_symlink(struct inode * dir, struct dentry *dentry, const cha
struct inode *inode; struct inode *inode;
int error = -ENOSPC; int error = -ENOSPC;
if (dentry->d_inode)
return -EEXIST;
inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
if (inode) { if (inode) {
int l = strlen(symname)+1; int l = strlen(symname)+1;
...@@ -212,24 +213,49 @@ static int driverfs_empty(struct dentry *dentry) ...@@ -212,24 +213,49 @@ static int driverfs_empty(struct dentry *dentry)
static int driverfs_unlink(struct inode *dir, struct dentry *dentry) static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
down(&inode->i_sem);
lock_kernel(); dentry->d_inode->i_nlink--;
inode->i_nlink--;
unlock_kernel();
dput(dentry); dput(dentry);
up(&inode->i_sem);
d_delete(dentry);
return 0; return 0;
} }
static void d_unhash(struct dentry *dentry)
{
dget(dentry);
spin_lock(&dcache_lock);
switch (atomic_read(&dentry->d_count)) {
default:
spin_unlock(&dcache_lock);
shrink_dcache_parent(dentry);
spin_lock(&dcache_lock);
if (atomic_read(&dentry->d_count) != 2)
break;
case 2:
list_del_init(&dentry->d_hash);
}
spin_unlock(&dcache_lock);
}
static int driverfs_rmdir(struct inode *dir, struct dentry *dentry) static int driverfs_rmdir(struct inode *dir, struct dentry *dentry)
{ {
int error = -ENOTEMPTY; int error = -ENOTEMPTY;
struct inode * inode = dentry->d_inode;
down(&inode->i_sem);
d_unhash(dentry);
if (driverfs_empty(dentry)) { if (driverfs_empty(dentry)) {
dentry->d_inode->i_nlink--; dentry->d_inode->i_nlink -= 2;
driverfs_unlink(dir, dentry); dput(dentry);
inode->i_flags |= S_DEAD;
dir->i_nlink--; dir->i_nlink--;
error = 0; error = 0;
} }
up(&inode->i_sem);
if (!error)
d_delete(dentry);
dput(dentry);
return error; return error;
} }
...@@ -365,7 +391,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig) ...@@ -365,7 +391,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
{ {
loff_t retval = -EINVAL; loff_t retval = -EINVAL;
lock_kernel(); down(&file->f_dentry->d_inode->i_sem);
switch(orig) { switch(orig) {
case 0: case 0:
if (offset > 0) { if (offset > 0) {
...@@ -382,7 +408,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig) ...@@ -382,7 +408,7 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
default: default:
break; break;
} }
unlock_kernel(); up(&file->f_dentry->d_inode->i_sem);
return retval; return retval;
} }
...@@ -424,36 +450,31 @@ static int driverfs_d_delete_file (struct dentry * dentry) ...@@ -424,36 +450,31 @@ static int driverfs_d_delete_file (struct dentry * dentry)
} }
static struct file_operations driverfs_file_operations = { static struct file_operations driverfs_file_operations = {
read: driverfs_read_file, .read = driverfs_read_file,
write: driverfs_write_file, .write = driverfs_write_file,
llseek: driverfs_file_lseek, .llseek = driverfs_file_lseek,
open: driverfs_open_file, .open = driverfs_open_file,
release: driverfs_release, .release = driverfs_release,
}; };
static struct inode_operations driverfs_dir_inode_operations = { static struct inode_operations driverfs_dir_inode_operations = {
create: driverfs_create, .lookup = simple_lookup,
lookup: simple_lookup,
unlink: driverfs_unlink,
symlink: driverfs_symlink,
mkdir: driverfs_mkdir,
rmdir: driverfs_rmdir,
}; };
static struct address_space_operations driverfs_aops = { static struct address_space_operations driverfs_aops = {
readpage: driverfs_readpage, .readpage = driverfs_readpage,
writepage: fail_writepage, .writepage = fail_writepage,
prepare_write: driverfs_prepare_write, .prepare_write = driverfs_prepare_write,
commit_write: driverfs_commit_write .commit_write = driverfs_commit_write
}; };
static struct dentry_operations driverfs_dentry_file_ops = { static struct dentry_operations driverfs_dentry_file_ops = {
d_delete: driverfs_d_delete_file, .d_delete = driverfs_d_delete_file,
}; };
static struct super_operations driverfs_ops = { static struct super_operations driverfs_ops = {
statfs: simple_statfs, .statfs = simple_statfs,
drop_inode: generic_delete_inode, .drop_inode = generic_delete_inode,
}; };
static int driverfs_fill_super(struct super_block *sb, void *data, int silent) static int driverfs_fill_super(struct super_block *sb, void *data, int silent)
...@@ -489,10 +510,10 @@ static struct super_block *driverfs_get_sb(struct file_system_type *fs_type, ...@@ -489,10 +510,10 @@ static struct super_block *driverfs_get_sb(struct file_system_type *fs_type,
} }
static struct file_system_type driverfs_fs_type = { static struct file_system_type driverfs_fs_type = {
owner: THIS_MODULE, .owner = THIS_MODULE,
name: "driverfs", .name = "driverfs",
get_sb: driverfs_get_sb, .get_sb = driverfs_get_sb,
kill_sb: kill_litter_super, .kill_sb = kill_litter_super,
}; };
static int get_mount(void) static int get_mount(void)
...@@ -589,7 +610,7 @@ driverfs_create_dir(struct driver_dir_entry * entry, ...@@ -589,7 +610,7 @@ driverfs_create_dir(struct driver_dir_entry * entry,
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *) entry; dentry->d_fsdata = (void *) entry;
entry->dentry = dentry; entry->dentry = dentry;
error = vfs_mkdir(parent_dentry->d_inode,dentry,entry->mode); error = driverfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
} else } else
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
up(&parent_dentry->d_inode->i_sem); up(&parent_dentry->d_inode->i_sem);
...@@ -630,7 +651,7 @@ driverfs_create_file(struct driver_file_entry * entry, ...@@ -630,7 +651,7 @@ driverfs_create_file(struct driver_file_entry * entry,
dentry = lookup_hash(&qstr,parent->dentry); dentry = lookup_hash(&qstr,parent->dentry);
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)entry; dentry->d_fsdata = (void *)entry;
error = vfs_create(parent->dentry->d_inode,dentry,entry->mode); error = driverfs_create(parent->dentry->d_inode,dentry,entry->mode);
/* Still good? Ok, then fill in the blanks: */ /* Still good? Ok, then fill in the blanks: */
if (!error) { if (!error) {
...@@ -678,7 +699,7 @@ int driverfs_create_symlink(struct driver_dir_entry * parent, ...@@ -678,7 +699,7 @@ int driverfs_create_symlink(struct driver_dir_entry * parent,
dentry = lookup_hash(&qstr,parent->dentry); dentry = lookup_hash(&qstr,parent->dentry);
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
dentry->d_fsdata = (void *)entry; dentry->d_fsdata = (void *)entry;
error = vfs_symlink(parent->dentry->d_inode,dentry,target); error = driverfs_symlink(parent->dentry->d_inode,dentry,target);
if (!error) { if (!error) {
dentry->d_inode->u.generic_ip = (void *)entry; dentry->d_inode->u.generic_ip = (void *)entry;
entry->dentry = dentry; entry->dentry = dentry;
...@@ -717,7 +738,7 @@ void driverfs_remove_file(struct driver_dir_entry * dir, const char * name) ...@@ -717,7 +738,7 @@ void driverfs_remove_file(struct driver_dir_entry * dir, const char * name)
entry = list_entry(node,struct driver_file_entry,node); entry = list_entry(node,struct driver_file_entry,node);
if (!strcmp(entry->name,name)) { if (!strcmp(entry->name,name)) {
list_del_init(node); list_del_init(node);
vfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry); driverfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry);
dput(entry->dentry); dput(entry->dentry);
put_mount(); put_mount();
break; break;
...@@ -752,14 +773,14 @@ void driverfs_remove_dir(struct driver_dir_entry * dir) ...@@ -752,14 +773,14 @@ void driverfs_remove_dir(struct driver_dir_entry * dir)
entry = list_entry(node,struct driver_file_entry,node); entry = list_entry(node,struct driver_file_entry,node);
list_del_init(node); list_del_init(node);
vfs_unlink(dentry->d_inode,entry->dentry); driverfs_unlink(dentry->d_inode,entry->dentry);
dput(entry->dentry); dput(entry->dentry);
put_mount(); put_mount();
node = dir->files.next; node = dir->files.next;
} }
up(&dentry->d_inode->i_sem); up(&dentry->d_inode->i_sem);
vfs_rmdir(dentry->d_parent->d_inode,dentry); driverfs_rmdir(dentry->d_parent->d_inode,dentry);
up(&dentry->d_parent->d_inode->i_sem); up(&dentry->d_parent->d_inode->i_sem);
dput(dentry); dput(dentry);
done: done:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment