glendix
changeset 53:92dc24ff2dce
Initial check-in of netfs - currently working on /net/cs
| author | Rahul Murmuria <rahul@murmuria.in> |
|---|---|
| date | Mon Feb 23 17:52:27 2009 -0500 (2009-02-23) |
| parents | eb3d33f7401a |
| children | fe5e31ca4730 |
| files | netfs/Makefile netfs/net.c |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netfs/Makefile Mon Feb 23 17:52:27 2009 -0500 1.3 @@ -0,0 +1,9 @@ 1.4 +ifneq ($(KERNELRELEASE),) 1.5 +obj-m := net.o 1.6 +else 1.7 +KDIR := /lib/modules/$(shell uname -r)/build 1.8 +PWD := $(shell pwd) 1.9 +default: 1.10 + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules 1.11 +endif 1.12 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/netfs/net.c Mon Feb 23 17:52:27 2009 -0500 2.3 @@ -0,0 +1,309 @@ 2.4 +/* 2.5 + * Copyright 2009 Rahul Murmuria <rahul@murmuria.in> 2.6 + * This file may be redistributed under the terms of the GNU GPL. 2.7 + * Most of this program has been adapted from the design of lwnfs 2.8 + * from http://lwn.net which is a sample implementation over libfs. 2.9 + */ 2.10 + 2.11 +#include <linux/slab.h> 2.12 +#include <linux/kernel.h> 2.13 +#include <linux/init.h> 2.14 +#include <linux/module.h> 2.15 +#include <linux/pagemap.h> /* PAGE_CACHE_SIZE */ 2.16 +#include <linux/fs.h> /* This is where libfs stuff is declared */ 2.17 +#include <asm/atomic.h> 2.18 +#include <asm/uaccess.h> /* copy_to_user */ 2.19 + 2.20 +MODULE_LICENSE("GPL"); 2.21 +MODULE_AUTHOR("Rahul Murmuria"); 2.22 + 2.23 +#define NET_MAGIC 0x19980122 2.24 + 2.25 +static inline unsigned int blksize_bits(unsigned int size) 2.26 +{ 2.27 + unsigned int bits = 8; 2.28 + do { 2.29 + bits++; 2.30 + size >>= 1; 2.31 + } while (size > 256); 2.32 + return bits; 2.33 +} 2.34 + 2.35 +static char *buffer; 2.36 + 2.37 +#define TMPSIZE 128 2.38 + 2.39 +static struct inode *slashnet_make_inode(struct super_block *sb, int mode) 2.40 +{ 2.41 + struct inode *ret = new_inode(sb); 2.42 + 2.43 + if (ret) { 2.44 + ret->i_mode = mode; 2.45 + ret->i_uid = ret->i_gid = 0; 2.46 + ret->i_blkbits = blksize_bits(PAGE_CACHE_SIZE); 2.47 + ret->i_blocks = 0; 2.48 + ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; 2.49 + } 2.50 + return ret; 2.51 +} 2.52 + 2.53 + 2.54 +/* 2.55 + * The operations on our "files". 2.56 + */ 2.57 + 2.58 +/* 2.59 + * Open a file. 2.60 + */ 2.61 +static int slashnet_open(struct inode *inode, struct file *filp) 2.62 +{ 2.63 + inode->i_private = kmalloc(TMPSIZE, GFP_KERNEL); 2.64 + filp->private_data = inode->i_private; 2.65 + return 0; 2.66 +} 2.67 + 2.68 +/* 2.69 + * Read a file. 2.70 + */ 2.71 +static ssize_t slashnet_read_file(struct file *filp, char *dnsquery, 2.72 + size_t count, loff_t *offset) 2.73 +{ 2.74 + char tmp[TMPSIZE]; 2.75 + int len; 2.76 + memcpy (tmp, buffer, sizeof(tmp)); 2.77 + len = sizeof(buffer); 2.78 + if (*offset > len) 2.79 + return 0; 2.80 + if (count > len - *offset) 2.81 + count = len - *offset; 2.82 + if (copy_to_user(dnsquery, tmp + *offset, count)) 2.83 + return -EFAULT; 2.84 + 2.85 + *offset += count; 2.86 + return count; 2.87 +} 2.88 + 2.89 +/* 2.90 + * Write a file. 2.91 + */ 2.92 +static ssize_t slashnet_write_file(struct file *filp, const char *dnsquery, 2.93 + size_t count, loff_t *offset) 2.94 +{ 2.95 + char tmp[TMPSIZE]; 2.96 + buffer = (char *)(filp->private_data); 2.97 + 2.98 + if (*offset != 0) 2.99 + return -EINVAL; 2.100 + 2.101 + memset(tmp, 0, TMPSIZE); 2.102 + if(copy_from_user(tmp, dnsquery, count)) 2.103 + return -EFAULT; 2.104 + memcpy (buffer, tmp, count-1); 2.105 + printk("*** value buffer has in write_file: %s ***\n", (char *) filp->private_data); 2.106 + /* Although private_data has required info here, it doesnot retain 2.107 + * its value by the time we reach slashnet_read_file. Hence we are 2.108 + * currently using a static global variable, buffer. */ 2.109 + 2.110 + return count; 2.111 +} 2.112 + 2.113 + 2.114 +/* 2.115 + * Now we can put together our file operations structure. 2.116 + */ 2.117 +static struct file_operations slashnet_file_ops = { 2.118 + .open = slashnet_open, 2.119 + .read = slashnet_read_file, 2.120 + .write = slashnet_write_file, 2.121 +}; 2.122 + 2.123 + 2.124 +/* 2.125 + * Create a file. 2.126 + */ 2.127 +static struct dentry *slashnet_create_file (struct super_block *sb, 2.128 + struct dentry *dir, const char *name, char *initval) 2.129 +{ 2.130 + struct dentry *dentry; 2.131 + struct inode *inode; 2.132 + struct qstr qname; 2.133 +/* 2.134 + * Make a hashed version of the name to go with the dentry. 2.135 + */ 2.136 + qname.name = name; 2.137 + qname.len = strlen (name); 2.138 + qname.hash = full_name_hash(name, qname.len); 2.139 +/* 2.140 + * Now we can create our dentry and the inode to go with it. 2.141 + */ 2.142 + dentry = d_alloc(dir, &qname); 2.143 + if (! dentry) 2.144 + goto out; 2.145 + inode = slashnet_make_inode(sb, S_IFREG | 0644); 2.146 + if (! inode) 2.147 + goto out_dput; 2.148 + inode->i_fop = &slashnet_file_ops; 2.149 + inode->i_private = initval; 2.150 + /* debug */ 2.151 + printk("*** %s: initial val is %s ***\n", name, initval); 2.152 + 2.153 +/* 2.154 + * Put it all into the dentry cache and we're done. 2.155 + */ 2.156 + d_add(dentry, inode); 2.157 + return dentry; 2.158 +/* 2.159 + * Then again, maybe it didn't work. 2.160 + */ 2.161 + out_dput: 2.162 + dput(dentry); 2.163 + out: 2.164 + return 0; 2.165 +} 2.166 + 2.167 + 2.168 +/* 2.169 + * Create a directory which can be used to hold files. This code is 2.170 + * almost identical to the "create file" logic, except that we create 2.171 + * the inode with a different mode, and use the libfs "simple" operations. 2.172 + */ 2.173 +static struct dentry *slashnet_create_dir (struct super_block *sb, 2.174 + struct dentry *parent, const char *name) 2.175 +{ 2.176 + struct dentry *dentry; 2.177 + struct inode *inode; 2.178 + struct qstr qname; 2.179 + 2.180 + qname.name = name; 2.181 + qname.len = strlen (name); 2.182 + qname.hash = full_name_hash(name, qname.len); 2.183 + dentry = d_alloc(parent, &qname); 2.184 + if (! dentry) 2.185 + goto out; 2.186 + 2.187 + inode = slashnet_make_inode(sb, S_IFDIR | 0644); 2.188 + if (! inode) 2.189 + goto out_dput; 2.190 + inode->i_op = &simple_dir_inode_operations; 2.191 + inode->i_fop = &simple_dir_operations; 2.192 + 2.193 + d_add(dentry, inode); 2.194 + return dentry; 2.195 + 2.196 + out_dput: 2.197 + dput(dentry); 2.198 + out: 2.199 + return 0; 2.200 +} 2.201 + 2.202 + 2.203 + 2.204 +/* 2.205 + * Create the files that we export. 2.206 + */ 2.207 + 2.208 +static void slashnet_create_files (struct super_block *sb, struct dentry *root) 2.209 +{ 2.210 + buffer = kmalloc(TMPSIZE, GFP_KERNEL); 2.211 + memset (buffer, 0, TMPSIZE); 2.212 + slashnet_create_file(sb, root, "cs", buffer); 2.213 + slashnet_create_dir(sb, root, "tcp"); 2.214 +} 2.215 + 2.216 + 2.217 + 2.218 +/* 2.219 + * Superblock stuff. This is all boilerplate to give the vfs something 2.220 + * that looks like a filesystem to work with. 2.221 + */ 2.222 + 2.223 +/* 2.224 + * Our superblock operations, both of which are generic kernel ops 2.225 + * that we don't have to write ourselves. 2.226 + */ 2.227 +static struct super_operations slashnet_s_ops = { 2.228 + .statfs = simple_statfs, 2.229 + .drop_inode = generic_delete_inode, 2.230 +}; 2.231 + 2.232 +/* 2.233 + * "Fill" a superblock with mundane stuff. 2.234 + */ 2.235 +static int slashnet_fill_super (struct super_block *sb, void *data, int silent) 2.236 +{ 2.237 + struct inode *root; 2.238 + struct dentry *root_dentry; 2.239 +/* 2.240 + * Basic parameters. 2.241 + */ 2.242 + sb->s_blocksize = PAGE_CACHE_SIZE; 2.243 + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 2.244 + sb->s_magic = NET_MAGIC; 2.245 + sb->s_op = &slashnet_s_ops; 2.246 +/* 2.247 + * We need to conjure up an inode to represent the root directory 2.248 + * of this filesystem. Its operations all come from libfs, so we 2.249 + * don't have to mess with actually *doing* things inside this 2.250 + * directory. 2.251 + */ 2.252 + root = slashnet_make_inode (sb, S_IFDIR | 0755); 2.253 + if (! root) 2.254 + goto out; 2.255 + root->i_op = &simple_dir_inode_operations; 2.256 + root->i_fop = &simple_dir_operations; 2.257 +/* 2.258 + * Get a dentry to represent the directory in core. 2.259 + */ 2.260 + root_dentry = d_alloc_root(root); 2.261 + if (! root_dentry) 2.262 + goto out_iput; 2.263 + sb->s_root = root_dentry; 2.264 +/* 2.265 + * Make up the files which will be in this filesystem, and we're done. 2.266 + */ 2.267 + slashnet_create_files (sb, root_dentry); 2.268 + return 0; 2.269 + 2.270 + out_iput: 2.271 + iput(root); 2.272 + out: 2.273 + return -ENOMEM; 2.274 +} 2.275 + 2.276 + 2.277 +/* 2.278 + * Stuff to pass in when registering the filesystem. 2.279 + */ 2.280 +static int slashnet_get_super(struct file_system_type *fst, 2.281 + int flags, const char *devname, void *data, 2.282 + struct vfsmount *mnt) 2.283 +{ 2.284 + return get_sb_single(fst, flags, data, slashnet_fill_super, mnt); 2.285 +} 2.286 + 2.287 +static struct file_system_type slashnet_type = { 2.288 + .owner = THIS_MODULE, 2.289 + .name = "net", 2.290 + .get_sb = slashnet_get_super, 2.291 + .kill_sb = kill_litter_super, 2.292 +}; 2.293 + 2.294 + 2.295 + 2.296 + 2.297 +/* 2.298 + * Get things set up. 2.299 + */ 2.300 +static int __init slashnet_init(void) 2.301 +{ 2.302 + return register_filesystem(&slashnet_type); 2.303 +} 2.304 + 2.305 +static void __exit slashnet_exit(void) 2.306 +{ 2.307 + unregister_filesystem(&slashnet_type); 2.308 +} 2.309 + 2.310 +module_init(slashnet_init); 2.311 +module_exit(slashnet_exit); 2.312 +
