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 +