[Envfs-commits] CVS: envfs/fs/envfs dir.c,1.1,1.2 file.c,1.4,1.5 inode.c,1.1,1.2 super.c,1.2,1.3
Status: Pre-Alpha
Brought to you by:
lethal
From: Paul M. <le...@us...> - 2001-09-23 04:28:13
|
Update of /cvsroot/envfs/envfs/fs/envfs In directory usw-pr-cvs1:/tmp/cvs-serv21374/fs/envfs Modified Files: dir.c file.c inode.c super.c Log Message: Changes and stuff. Index: dir.c =================================================================== RCS file: /cvsroot/envfs/envfs/fs/envfs/dir.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- dir.c 2001/09/19 03:01:45 1.1 +++ dir.c 2001/09/23 04:28:10 1.2 @@ -12,6 +12,8 @@ static struct dentry *envfs_lookup(struct inode *dir, struct dentry *dentry) { + char *tmp; + envfs_debug("entering\n"); if (!dentry) @@ -19,11 +21,15 @@ if (!dentry->d_name.name) goto out; - envfs_debug("dir->i_ino == %d\n", dir->i_ino); + tmp = envfs_getenv(dentry->d_name.name); + + envfs_debug("dir->i_ino == %ld\n", dir->i_ino); envfs_debug("dentry->d_name.name == %s\n", dentry->d_name.name); dentry->d_inode = envfs_get_inode(dir->i_sb, + strlen(tmp), 0644 | S_IFREG, dir->i_dev); + kfree(tmp); out: envfs_debug("leaving\n"); return NULL; @@ -32,16 +38,16 @@ static int envfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) { - struct inode *inode = envfs_get_inode(dir->i_sb, mode, dev); + struct inode *inode = envfs_get_inode(dir->i_sb, 0, mode, dev); envfs_debug("entering\n"); if (!inode) return -ENOSPC; dentry->d_inode = inode; - envfs_debug("inode == %d\n", dentry->d_inode->i_ino); - dentry->d_inode = inode; + envfs_debug("inode == %ld\n", dentry->d_inode->i_ino); + dget(dentry); envfs_debug("leaving\n"); @@ -51,7 +57,7 @@ static int envfs_create(struct inode *dir, struct dentry *dentry, int mode) { envfs_debug("entering\n"); - envfs_debug("dir->i_ino == %d\n", dir->i_ino); + envfs_debug("dir->i_ino == %ld\n", dir->i_ino); envfs_debug("leaving\n"); return envfs_mknod(dir, dentry, mode | S_IFREG, 0); } @@ -103,7 +109,7 @@ envfs_debug("entering\n"); - envfs_debug("filp->f_pos == %d\n", filp->f_pos); + envfs_debug("filp->f_pos == %ld\n", filp->f_pos); if (!dentry) goto out; @@ -140,6 +146,7 @@ struct file_operations envfs_dops = { read: generic_read_dir, readdir: envfs_readdir, + ioctl: envfs_ioctl, }; struct inode_operations envfs_diops = { Index: file.c =================================================================== RCS file: /cvsroot/envfs/envfs/fs/envfs/file.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- file.c 2001/09/19 03:26:16 1.4 +++ file.c 2001/09/23 04:28:10 1.5 @@ -12,11 +12,140 @@ #include <linux/envfs_fs.h> #include <asm/uaccess.h> +/* + * Dump the envp + */ +int envfs_dump_vars(void) +{ + int res, len, pos; + char *buf; + + envfs_debug("entering\n"); + + len = current->mm->env_end - current->mm->env_start; + buf = kmalloc(len, GFP_KERNEL); + + if (!buf) { + printk(KERN_ERR "Can't allocate memory for envp\n"); + envfs_debug("leaving\n"); + return -ENOMEM; + } + + task_lock(current); + + if (!current->mm) { + printk(KERN_ERR "No current->mm ?!\n"); + task_unlock(current); + envfs_debug("leaving\n"); + return -EINVAL; + } + + atomic_inc(&(current->mm->mm_users)); + task_unlock(current); + + res = access_process_vm(current, current->mm->env_start, buf, len, 0); + + /* + * Each key:value pair ends with a '\0', which causes things like + * printk() to fail printing out the whole envp. Because of this, we + * translate each '\0' to '|' on everything but the end of the envp. + * + * The other option is calling access_process_vm() lots of times with + * the length of the key:value pair as the offset within the envp + * space, though this is slower than just doing translation and + * splitting up the string. + */ + for (pos = strlen(buf); pos != res; pos = strlen(buf)) + if (!buf[pos] || buf[pos] == '\0') + buf[pos] = '|'; + + buf[pos - 1] = '\0'; + + printk(KERN_INFO "envfs: envp: %s\n", buf); + envfs_debug("len: %d, pos: %d, res: %d, strlen(buf): %d\n", + len, pos, res, strlen(buf)); + + mmput(current->mm); + + kfree(buf); + + envfs_debug("leaving\n"); + + return 0; +} + +/** + * envfs_ll_purge - Purge dentry from list + * + * @dentry: envfs dentry to search for + * + * Searches through the envfs_dentry_list looking for an existing entry of + * @dentry (by key). If it's found, the inode and dentry are cleaned up so + * they can be reused later, and the entry is purged from the list. + */ +static int envfs_ll_purge(struct envfs_dentry *dentry) +{ + struct envfs_dentry *list_dentry; + struct list_head *list; + + envfs_debug("entering\n"); + + /* + * No use spinning an emtpy list + */ + if (list_empty(envfs_dentry_list)) { + envfs_debug("list is empty\n"); + goto out; + } + + /* + * Spin list looking for matching key + * + * FIXME: Should utilize the envfs dentry position here for faster + * lookups. Use hashes and have the position reference the hash + * location in the hash table maybe? + */ + list_for_each(list, envfs_dentry_list) { + list_dentry = list_entry(list, struct envfs_dentry, node); + + if (!list_dentry) + continue; + + /* + * Found it + */ + if (strcmp(list_dentry->key, dentry->key) == 0) { + /* + * Clean up after the dentry and inode + */ + if (list_dentry->f_dentry->d_inode) { + vfs_unlink(list_dentry->f_dentry->d_inode, + list_dentry->f_dentry); + envfs_delete_inode(list_dentry->f_dentry->d_inode); + dput(list_dentry->f_dentry); + } + + /* + * Clean up after the list entry + */ + list_del(&(list_dentry->node)); + kfree(list_dentry); + + break; + } + } + +out: + envfs_debug("leaving\n"); + + return 0; +} + char *envfs_getenv_vars(struct file *filp, void *dirent, filldir_t filldir) { + struct envfs_dentry *e_dentry; unsigned long currkey; - struct dentry *dentry; - char *buf, *opt; + char *buf; int i = 0; envfs_debug("entering\n"); @@ -25,6 +154,19 @@ current->mm->env_start, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Can't allocate memory\n"); + goto out_nomem; + } + + e_dentry = kmalloc(sizeof(struct envfs_dentry *), GFP_KERNEL); + + if (!e_dentry) { + printk(KERN_ERR "Can't allocate memory\n"); + kfree(buf); + goto out_nomem; + } + for (currkey = current->mm->env_start; currkey < current->mm->env_end; currkey++) { @@ -34,24 +176,43 @@ i++; } + /* Seek to current position */ for (i = 0; i < filp->f_pos - 2; i++) { strsep(&buf, "|"); } - opt = strsep(&buf, "="); + /* + * Setup the envfs dentry list entry + */ + INIT_LIST_HEAD(&e_dentry->node); + e_dentry->key = strsep(&buf, "="); + //e_dentry->val = strsep(&buf, "="); + e_dentry->pos = filp->f_pos - 2; - if (!*opt) + if (!*(e_dentry->key)) goto out; - if (envfs_create_by_name(opt, 0755 | S_IFREG, NULL, &dentry) == -EINVAL) + //if (!*(e_dentry->val)) + // goto out; + + envfs_ll_purge(e_dentry); + + if (envfs_create_by_name(e_dentry->key, 0755 | S_IFREG, NULL, + &(e_dentry->f_dentry)) == -EINVAL) goto out; - if (filldir(dirent, dentry->d_name.name, dentry->d_name.len, - filp->f_pos, dentry->d_inode->i_ino, DT_UNKNOWN) < 0) + if (filldir(dirent, e_dentry->f_dentry->d_name.name, + e_dentry->f_dentry->d_name.len, filp->f_pos, + e_dentry->f_dentry->d_inode->i_ino, DT_UNKNOWN) < 0) goto out; + /* + * Add it to the list + */ + list_add(&e_dentry->node, envfs_dentry_list); filp->f_pos++; out: kfree(buf); +out_nomem: envfs_debug("leaving\n"); return NULL; } @@ -142,8 +303,29 @@ return count; } +int envfs_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned int arg) +{ + envfs_debug("entering\n"); + + envfs_debug("cmd: %d\n", cmd); + + switch (cmd) { + case 0x9cfe123: + envfs_dump_vars(); + break; + default: + envfs_debug("leaving: no cmd\n"); + return -ENOTTY; + } + + envfs_debug("leaving\n"); + return 0; +} + struct file_operations envfs_fops = { read: envfs_read_file, + ioctl: envfs_ioctl, mmap: generic_file_mmap, llseek: generic_file_llseek, }; Index: inode.c =================================================================== RCS file: /cvsroot/envfs/envfs/fs/envfs/inode.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- inode.c 2001/09/19 03:01:45 1.1 +++ inode.c 2001/09/23 04:28:10 1.2 @@ -11,27 +11,56 @@ #include <linux/locks.h> #include <linux/envfs_fs.h> +void envfs_delete_inode(struct inode *inode) +{ + envfs_debug("entering\n"); + + lock_kernel(); + + envfs_debug("unlinking inode: %ld\n", inode->i_ino); + + if (inode->i_flags & S_IMMUTABLE) + inode->i_flags &= ~S_IMMUTABLE; + + inode->i_size = 0; + inode->i_blocks = 0; + inode->i_nlink--; + + clear_inode(inode); + + unlock_kernel(); + + envfs_debug("leaving\n"); +} + void envfs_read_inode(struct inode *inode) { + envfs_debug("entering\n"); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + envfs_debug("leaving\n"); } -struct inode *envfs_get_inode(struct super_block *sb, int mode, int dev) +struct inode *envfs_get_inode(struct super_block *sb, loff_t inode_size, int mode, int dev) { struct inode *inode = new_inode(sb); envfs_debug("entering\n"); + if (!inode) return NULL; - + if (inode_size) + inode_size--; + 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_size = inode_size; + inode->i_mapping->a_ops = &envfs_aops; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + envfs_read_inode(inode); /* * FIXME: This is a hack to force everything into a read-only state. Index: super.c =================================================================== RCS file: /cvsroot/envfs/envfs/fs/envfs/super.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- super.c 2001/09/19 03:30:26 1.2 +++ super.c 2001/09/23 04:28:10 1.3 @@ -15,9 +15,15 @@ static struct vfsmount *envfs_mnt; +spinlock_t envfs_lock = SPIN_LOCK_UNLOCKED; +struct list_head *envfs_dentry_list; + +extern int envfs_dump_vars(void); + static int envfs_statfs(struct super_block *sb, struct statfs *buf) { envfs_debug("entering\n"); + envfs_dump_vars(); buf->f_type = ENVFS_SUPER_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; buf->f_namelen = NAME_MAX; @@ -48,6 +54,7 @@ statfs: envfs_statfs, put_inode: force_delete, read_inode: envfs_read_inode, + delete_inode: envfs_delete_inode, }; static struct super_block *envfs_read_super(struct super_block *sb, @@ -61,7 +68,7 @@ sb->s_magic = ENVFS_SUPER_MAGIC; sb->s_op = &envfs_sops; - root_inode = envfs_get_inode(sb, S_IFDIR | 0755, 0); + root_inode = envfs_get_inode(sb, 0, S_IFDIR | 0755, 0); if (!root_inode) return NULL; @@ -73,6 +80,16 @@ return NULL; } + envfs_dentry_list = kmalloc(sizeof(struct list_head *), GFP_KERNEL); + + if (!envfs_dentry_list) { + printk(KERN_ERR "Can't allocate memory for list\n"); + iput(root_inode); + return NULL; + } + + INIT_LIST_HEAD(envfs_dentry_list); + envfs_debug("leaving\n"); return sb; } @@ -105,7 +122,7 @@ MODULE_AUTHOR("Paul Mundt <le...@ch...>"); MODULE_DESCRIPTION("/env file system"); -MODULE_LICENSE("GPL"); +//MODULE_LICENSE("GPL"); module_init(init_envfs_fs); module_exit(exit_envfs_fs); |