glendix

view netfs/net.c @ 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
children 092b922b74ce
line source
1 /*
2 * Copyright 2009 Rahul Murmuria <rahul@murmuria.in>
3 * This file may be redistributed under the terms of the GNU GPL.
4 * Most of this program has been adapted from the design of lwnfs
5 * from http://lwn.net which is a sample implementation over libfs.
6 */
8 #include <linux/slab.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/pagemap.h> /* PAGE_CACHE_SIZE */
13 #include <linux/fs.h> /* This is where libfs stuff is declared */
14 #include <asm/atomic.h>
15 #include <asm/uaccess.h> /* copy_to_user */
17 MODULE_LICENSE("GPL");
18 MODULE_AUTHOR("Rahul Murmuria");
20 #define NET_MAGIC 0x19980122
22 static inline unsigned int blksize_bits(unsigned int size)
23 {
24 unsigned int bits = 8;
25 do {
26 bits++;
27 size >>= 1;
28 } while (size > 256);
29 return bits;
30 }
32 static char *buffer;
34 #define TMPSIZE 128
36 static struct inode *slashnet_make_inode(struct super_block *sb, int mode)
37 {
38 struct inode *ret = new_inode(sb);
40 if (ret) {
41 ret->i_mode = mode;
42 ret->i_uid = ret->i_gid = 0;
43 ret->i_blkbits = blksize_bits(PAGE_CACHE_SIZE);
44 ret->i_blocks = 0;
45 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
46 }
47 return ret;
48 }
51 /*
52 * The operations on our "files".
53 */
55 /*
56 * Open a file.
57 */
58 static int slashnet_open(struct inode *inode, struct file *filp)
59 {
60 inode->i_private = kmalloc(TMPSIZE, GFP_KERNEL);
61 filp->private_data = inode->i_private;
62 return 0;
63 }
65 /*
66 * Read a file.
67 */
68 static ssize_t slashnet_read_file(struct file *filp, char *dnsquery,
69 size_t count, loff_t *offset)
70 {
71 char tmp[TMPSIZE];
72 int len;
73 memcpy (tmp, buffer, sizeof(tmp));
74 len = sizeof(buffer);
75 if (*offset > len)
76 return 0;
77 if (count > len - *offset)
78 count = len - *offset;
79 if (copy_to_user(dnsquery, tmp + *offset, count))
80 return -EFAULT;
82 *offset += count;
83 return count;
84 }
86 /*
87 * Write a file.
88 */
89 static ssize_t slashnet_write_file(struct file *filp, const char *dnsquery,
90 size_t count, loff_t *offset)
91 {
92 char tmp[TMPSIZE];
93 buffer = (char *)(filp->private_data);
95 if (*offset != 0)
96 return -EINVAL;
98 memset(tmp, 0, TMPSIZE);
99 if(copy_from_user(tmp, dnsquery, count))
100 return -EFAULT;
101 memcpy (buffer, tmp, count-1);
102 printk("*** value buffer has in write_file: %s ***\n", (char *) filp->private_data);
103 /* Although private_data has required info here, it doesnot retain
104 * its value by the time we reach slashnet_read_file. Hence we are
105 * currently using a static global variable, buffer. */
107 return count;
108 }
111 /*
112 * Now we can put together our file operations structure.
113 */
114 static struct file_operations slashnet_file_ops = {
115 .open = slashnet_open,
116 .read = slashnet_read_file,
117 .write = slashnet_write_file,
118 };
121 /*
122 * Create a file.
123 */
124 static struct dentry *slashnet_create_file (struct super_block *sb,
125 struct dentry *dir, const char *name, char *initval)
126 {
127 struct dentry *dentry;
128 struct inode *inode;
129 struct qstr qname;
130 /*
131 * Make a hashed version of the name to go with the dentry.
132 */
133 qname.name = name;
134 qname.len = strlen (name);
135 qname.hash = full_name_hash(name, qname.len);
136 /*
137 * Now we can create our dentry and the inode to go with it.
138 */
139 dentry = d_alloc(dir, &qname);
140 if (! dentry)
141 goto out;
142 inode = slashnet_make_inode(sb, S_IFREG | 0644);
143 if (! inode)
144 goto out_dput;
145 inode->i_fop = &slashnet_file_ops;
146 inode->i_private = initval;
147 /* debug */
148 printk("*** %s: initial val is %s ***\n", name, initval);
150 /*
151 * Put it all into the dentry cache and we're done.
152 */
153 d_add(dentry, inode);
154 return dentry;
155 /*
156 * Then again, maybe it didn't work.
157 */
158 out_dput:
159 dput(dentry);
160 out:
161 return 0;
162 }
165 /*
166 * Create a directory which can be used to hold files. This code is
167 * almost identical to the "create file" logic, except that we create
168 * the inode with a different mode, and use the libfs "simple" operations.
169 */
170 static struct dentry *slashnet_create_dir (struct super_block *sb,
171 struct dentry *parent, const char *name)
172 {
173 struct dentry *dentry;
174 struct inode *inode;
175 struct qstr qname;
177 qname.name = name;
178 qname.len = strlen (name);
179 qname.hash = full_name_hash(name, qname.len);
180 dentry = d_alloc(parent, &qname);
181 if (! dentry)
182 goto out;
184 inode = slashnet_make_inode(sb, S_IFDIR | 0644);
185 if (! inode)
186 goto out_dput;
187 inode->i_op = &simple_dir_inode_operations;
188 inode->i_fop = &simple_dir_operations;
190 d_add(dentry, inode);
191 return dentry;
193 out_dput:
194 dput(dentry);
195 out:
196 return 0;
197 }
201 /*
202 * Create the files that we export.
203 */
205 static void slashnet_create_files (struct super_block *sb, struct dentry *root)
206 {
207 buffer = kmalloc(TMPSIZE, GFP_KERNEL);
208 memset (buffer, 0, TMPSIZE);
209 slashnet_create_file(sb, root, "cs", buffer);
210 slashnet_create_dir(sb, root, "tcp");
211 }
215 /*
216 * Superblock stuff. This is all boilerplate to give the vfs something
217 * that looks like a filesystem to work with.
218 */
220 /*
221 * Our superblock operations, both of which are generic kernel ops
222 * that we don't have to write ourselves.
223 */
224 static struct super_operations slashnet_s_ops = {
225 .statfs = simple_statfs,
226 .drop_inode = generic_delete_inode,
227 };
229 /*
230 * "Fill" a superblock with mundane stuff.
231 */
232 static int slashnet_fill_super (struct super_block *sb, void *data, int silent)
233 {
234 struct inode *root;
235 struct dentry *root_dentry;
236 /*
237 * Basic parameters.
238 */
239 sb->s_blocksize = PAGE_CACHE_SIZE;
240 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
241 sb->s_magic = NET_MAGIC;
242 sb->s_op = &slashnet_s_ops;
243 /*
244 * We need to conjure up an inode to represent the root directory
245 * of this filesystem. Its operations all come from libfs, so we
246 * don't have to mess with actually *doing* things inside this
247 * directory.
248 */
249 root = slashnet_make_inode (sb, S_IFDIR | 0755);
250 if (! root)
251 goto out;
252 root->i_op = &simple_dir_inode_operations;
253 root->i_fop = &simple_dir_operations;
254 /*
255 * Get a dentry to represent the directory in core.
256 */
257 root_dentry = d_alloc_root(root);
258 if (! root_dentry)
259 goto out_iput;
260 sb->s_root = root_dentry;
261 /*
262 * Make up the files which will be in this filesystem, and we're done.
263 */
264 slashnet_create_files (sb, root_dentry);
265 return 0;
267 out_iput:
268 iput(root);
269 out:
270 return -ENOMEM;
271 }
274 /*
275 * Stuff to pass in when registering the filesystem.
276 */
277 static int slashnet_get_super(struct file_system_type *fst,
278 int flags, const char *devname, void *data,
279 struct vfsmount *mnt)
280 {
281 return get_sb_single(fst, flags, data, slashnet_fill_super, mnt);
282 }
284 static struct file_system_type slashnet_type = {
285 .owner = THIS_MODULE,
286 .name = "net",
287 .get_sb = slashnet_get_super,
288 .kill_sb = kill_litter_super,
289 };
294 /*
295 * Get things set up.
296 */
297 static int __init slashnet_init(void)
298 {
299 return register_filesystem(&slashnet_type);
300 }
302 static void __exit slashnet_exit(void)
303 {
304 unregister_filesystem(&slashnet_type);
305 }
307 module_init(slashnet_init);
308 module_exit(slashnet_exit);