This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / relayfs / inode.c
1 /*
2  * VFS-related code for RelayFS, a high-speed data relay filesystem.
3  *
4  * Copyright (C) 2003 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
5  * Copyright (C) 2003 - Karim Yaghmour <karim@opersys.com>
6  *
7  * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
8  *
9  * This file is released under the GPL.
10  */
11
12 #include <linux/module.h>
13 #include <linux/fs.h>
14 #include <linux/mount.h>
15 #include <linux/pagemap.h>
16 #include <linux/highmem.h>
17 #include <linux/init.h>
18 #include <linux/string.h>
19 #include <linux/smp_lock.h>
20 #include <linux/backing-dev.h>
21 #include <linux/namei.h>
22 #include <linux/poll.h>
23 #include <asm/uaccess.h>
24 #include <asm/relay.h>
25
26 #define RELAYFS_MAGIC                   0x26F82121
27
28 static struct super_operations          relayfs_ops;
29 static struct address_space_operations  relayfs_aops;
30 static struct inode_operations          relayfs_file_inode_operations;
31 static struct file_operations           relayfs_file_operations;
32 static struct inode_operations          relayfs_dir_inode_operations;
33
34 static struct vfsmount *                relayfs_mount;
35 static int                              relayfs_mount_count;
36
37 static struct backing_dev_info          relayfs_backing_dev_info = {
38         .ra_pages       = 0,    /* No readahead */
39         .memory_backed  = 1,    /* Does not contribute to dirty memory */
40 };
41
42 static struct inode *
43 relayfs_get_inode(struct super_block *sb, int mode, dev_t dev)
44 {
45         struct inode * inode;
46         
47         inode = new_inode(sb);
48
49         if (inode) {
50                 inode->i_mode = mode;
51                 inode->i_uid = current->fsuid;
52                 inode->i_gid = current->fsgid;
53                 inode->i_blksize = PAGE_CACHE_SIZE;
54                 inode->i_blocks = 0;
55                 inode->i_mapping->a_ops = &relayfs_aops;
56                 inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
57                 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
58                 switch (mode & S_IFMT) {
59                 default:
60                         init_special_inode(inode, mode, dev);
61                         break;
62                 case S_IFREG:
63                         inode->i_op = &relayfs_file_inode_operations;
64                         inode->i_fop = &relayfs_file_operations;
65                         break;
66                 case S_IFDIR:
67                         inode->i_op = &relayfs_dir_inode_operations;
68                         inode->i_fop = &simple_dir_operations;
69
70                         /* directory inodes start off with i_nlink == 2 (for "." entry) */
71                         inode->i_nlink++;
72                         break;
73                 case S_IFLNK:
74                         inode->i_op = &page_symlink_inode_operations;
75                         break;
76                 }
77         }
78         return inode;
79 }
80
81 /*
82  * File creation. Allocate an inode, and we're done..
83  */
84 /* SMP-safe */
85 static int 
86 relayfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
87 {
88         struct inode * inode;
89         int error = -ENOSPC;
90
91         inode = relayfs_get_inode(dir->i_sb, mode, dev);
92
93         if (inode) {
94                 d_instantiate(dentry, inode);
95                 dget(dentry);   /* Extra count - pin the dentry in core */
96                 error = 0;
97         }
98         return error;
99 }
100
101 static int 
102 relayfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
103 {
104         int retval;
105
106         retval = relayfs_mknod(dir, dentry, mode | S_IFDIR, 0);
107
108         if (!retval)
109                 dir->i_nlink++;
110         return retval;
111 }
112
113 static int 
114 relayfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
115 {
116         return relayfs_mknod(dir, dentry, mode | S_IFREG, 0);
117 }
118
119 static int 
120 relayfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
121 {
122         struct inode *inode;
123         int error = -ENOSPC;
124
125         inode = relayfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
126
127         if (inode) {
128                 int l = strlen(symname)+1;
129                 error = page_symlink(inode, symname, l);
130                 if (!error) {
131                         d_instantiate(dentry, inode);
132                         dget(dentry);
133                 } else
134                         iput(inode);
135         }
136         return error;
137 }
138
139 /**
140  *      relayfs_create_entry - create a relayfs directory or file
141  *      @name: the name of the file to create
142  *      @parent: parent directory
143  *      @dentry: result dentry
144  *      @entry_type: type of file to create (S_IFREG, S_IFDIR)
145  *      @mode: mode
146  *      @data: data to associate with the file
147  *
148  *      Creates a file or directory with the specifed permissions.
149  */
150 static int 
151 relayfs_create_entry(const char * name, struct dentry * parent, struct dentry **dentry, int entry_type, int mode, void * data)
152 {
153         struct qstr qname;
154         struct dentry * d;
155         
156         int error = 0;
157
158         error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count);
159         if (error) {
160                 printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error);
161                 return error;
162         }
163
164         qname.name = name;
165         qname.len = strlen(name);
166         qname.hash = full_name_hash(name, qname.len);
167
168         if (parent == NULL)
169                 if (relayfs_mount && relayfs_mount->mnt_sb)
170                         parent = relayfs_mount->mnt_sb->s_root;
171
172         if (parent == NULL) {
173                 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
174                 return -EINVAL;
175         }
176
177         parent = dget(parent);
178         down(&parent->d_inode->i_sem);
179         d = lookup_hash(&qname, parent);
180         if (IS_ERR(d)) {
181                 error = PTR_ERR(d);
182                 goto release_mount;
183         }
184         
185         if (d->d_inode) {
186                 error = -EEXIST;
187                 goto release_mount;
188         }
189
190         if (entry_type == S_IFREG)
191                 error = relayfs_create(parent->d_inode, d, entry_type | mode, NULL);
192         else
193                 error = relayfs_mkdir(parent->d_inode, d, entry_type | mode);
194         if (error)
195                 goto release_mount;
196
197         if ((entry_type == S_IFREG) && data) {
198                 d->d_inode->u.generic_ip = data;
199                 goto exit; /* don't release mount for regular files */
200         }
201
202 release_mount:
203         simple_release_fs(&relayfs_mount, &relayfs_mount_count);
204 exit:   
205         *dentry = d;
206         up(&parent->d_inode->i_sem);
207         dput(parent);
208
209         return error;
210 }
211
212 /**
213  *      relayfs_create_file - create a file in the relay filesystem
214  *      @name: the name of the file to create
215  *      @parent: parent directory
216  *      @dentry: result dentry
217  *      @data: data to associate with the file
218  *      @mode: mode, if not specied the default perms are used
219  *
220  *      The file will be created user rw on behalf of current user.
221  */
222 int 
223 relayfs_create_file(const char * name, struct dentry * parent, struct dentry **dentry, void * data, int mode)
224 {
225         if (!mode)
226                 mode = S_IRUSR | S_IWUSR;
227         
228         return relayfs_create_entry(name, parent, dentry, S_IFREG,
229                                     mode, data);
230 }
231
232 /**
233  *      relayfs_create_dir - create a directory in the relay filesystem
234  *      @name: the name of the directory to create
235  *      @parent: parent directory
236  *      @dentry: result dentry
237  *
238  *      The directory will be created world rwx on behalf of current user.
239  */
240 int 
241 relayfs_create_dir(const char * name, struct dentry * parent, struct dentry **dentry)
242 {
243         return relayfs_create_entry(name, parent, dentry, S_IFDIR,
244                                     S_IRWXU | S_IRUGO | S_IXUGO, NULL);
245 }
246
247 /**
248  *      relayfs_remove_file - remove a file in the relay filesystem
249  *      @dentry: file dentry
250  *
251  *      Remove a file previously created by relayfs_create_file.
252  */
253 int 
254 relayfs_remove_file(struct dentry *dentry)
255 {
256         struct dentry *parent;
257         int is_reg;
258         
259         parent = dentry->d_parent;
260         if (parent == NULL)
261                 return -EINVAL;
262
263         is_reg = S_ISREG(dentry->d_inode->i_mode);
264
265         parent = dget(parent);
266         down(&parent->d_inode->i_sem);
267         if (dentry->d_inode) {
268                 simple_unlink(parent->d_inode, dentry);
269                 d_delete(dentry);
270         }
271         dput(dentry);
272         up(&parent->d_inode->i_sem);
273         dput(parent);
274
275         if(is_reg)
276                 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
277
278         return 0;
279 }
280
281 /**
282  *      relayfs_open - open file op for relayfs files
283  *      @inode: the inode
284  *      @filp: the file
285  *
286  *      Associates the channel with the file, and increments the
287  *      channel refcount.  Reads will be 'auto-consuming'.
288  */
289 int
290 relayfs_open(struct inode *inode, struct file *filp)
291 {
292         struct rchan *rchan;
293         struct rchan_reader *reader;
294         int retval = 0;
295
296         if (inode->u.generic_ip) {
297                 rchan = (struct rchan *)inode->u.generic_ip;
298                 if (rchan == NULL)
299                         return -EACCES;
300                 reader = __add_rchan_reader(rchan, filp, 1, 0);
301                 if (reader == NULL)
302                         return -ENOMEM;
303                 filp->private_data = reader;
304                 retval = rchan->callbacks->fileop_notify(rchan->id, filp,
305                                                          RELAY_FILE_OPEN);
306                 if (retval == 0)
307                         /* Inc relay channel refcount for file */
308                         rchan_get(rchan->id);
309                 else {
310                         __remove_rchan_reader(reader);
311                         retval = -EPERM;
312                 }
313         }
314
315         return retval;
316 }
317
318 /**
319  *      relayfs_mmap - mmap file op for relayfs files
320  *      @filp: the file
321  *      @vma: the vma describing what to map
322  *
323  *      Calls upon relay_mmap_buffer to map the file into user space.
324  */
325 int 
326 relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
327 {
328         struct rchan *rchan;
329         
330         rchan = ((struct rchan_reader *)filp->private_data)->rchan;
331
332         return __relay_mmap_buffer(rchan, vma);
333 }
334
335 /**
336  *      relayfs_file_read - read file op for relayfs files
337  *      @filp: the file
338  *      @buf: user buf to read into
339  *      @count: bytes requested
340  *      @offset: offset into file
341  *
342  *      Reads count bytes from the channel, or as much as is available within
343  *      the sub-buffer currently being read.  Reads are 'auto-consuming'.
344  *      See relay_read() for details.
345  *
346  *      Returns bytes read on success, 0 or -EAGAIN if nothing available,
347  *      negative otherwise.
348  */
349 ssize_t 
350 relayfs_file_read(struct file *filp, char * buf, size_t count, loff_t *offset)
351 {
352         size_t read_count;
353         struct rchan_reader *reader;
354         u32 dummy; /* all VFS readers are auto-consuming */
355
356         if (offset != &filp->f_pos) /* pread, seeking not supported */
357                 return -ESPIPE;
358
359         if (count == 0)
360                 return 0;
361
362         reader = (struct rchan_reader *)filp->private_data;
363         read_count = relay_read(reader, buf, count,
364                 filp->f_flags & (O_NDELAY | O_NONBLOCK) ? 0 : 1, &dummy);
365
366         return read_count;
367 }
368
369 /**
370  *      relayfs_file_write - write file op for relayfs files
371  *      @filp: the file
372  *      @buf: user buf to write from
373  *      @count: bytes to write
374  *      @offset: offset into file
375  *
376  *      Reserves a slot in the relay buffer and writes count bytes
377  *      into it.  The current limit for a single write is 2 pages
378  *      worth.  The user_deliver() channel callback will be invoked on
379  *      
380  *      Returns bytes written on success, 0 or -EAGAIN if nothing available,
381  *      negative otherwise.
382  */
383 ssize_t 
384 relayfs_file_write(struct file *filp, const char *buf, size_t count, loff_t *offset)
385 {
386         int write_count;
387         char * write_buf;
388         struct rchan *rchan;
389         int err = 0;
390         void *wrote_pos;
391         struct rchan_reader *reader;
392
393         reader = (struct rchan_reader *)filp->private_data;
394         if (reader == NULL)
395                 return -EPERM;
396
397         rchan = reader->rchan;
398         if (rchan == NULL)
399                 return -EPERM;
400
401         if (count == 0)
402                 return 0;
403
404         /* Change this if need to write more than 2 pages at once */
405         if (count > 2 * PAGE_SIZE)
406                 return -EINVAL;
407         
408         write_buf = (char *)__get_free_pages(GFP_KERNEL, 1);
409         if (write_buf == NULL)
410                 return -ENOMEM;
411
412         if (copy_from_user(write_buf, buf, count))
413                 return -EFAULT;
414
415         if (filp->f_flags & (O_NDELAY | O_NONBLOCK)) {
416                 write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos);
417                 if (write_count == 0)
418                         return -EAGAIN;
419         } else {
420                 err = wait_event_interruptible(rchan->write_wait,
421                  (write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos)));
422                 if (err)
423                         return err;
424         }
425         
426         free_pages((unsigned long)write_buf, 1);
427         
428         rchan->callbacks->user_deliver(rchan->id, wrote_pos, write_count);
429
430         return write_count;
431 }
432
433 /**
434  *      relayfs_ioctl - ioctl file op for relayfs files
435  *      @inode: the inode
436  *      @filp: the file
437  *      @cmd: the command
438  *      @arg: command arg
439  *
440  *      Passes the specified cmd/arg to the kernel client.  arg may be a 
441  *      pointer to user-space data, in which case the kernel client is 
442  *      responsible for copying the data to/from user space appropriately.
443  *      The kernel client is also responsible for returning a meaningful
444  *      return value for ioctl calls.
445  *      
446  *      Returns result of relay channel callback, -EPERM if unsuccessful.
447  */
448 int
449 relayfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
450 {
451         struct rchan *rchan;
452         struct rchan_reader *reader;
453
454         reader = (struct rchan_reader *)filp->private_data;
455         if (reader == NULL)
456                 return -EPERM;
457
458         rchan = reader->rchan;
459         if (rchan == NULL)
460                 return -EPERM;
461
462         return rchan->callbacks->ioctl(rchan->id, cmd, arg);
463 }
464
465 /**
466  *      relayfs_poll - poll file op for relayfs files
467  *      @filp: the file
468  *      @wait: poll table
469  *
470  *      Poll implemention.
471  */
472 static unsigned int
473 relayfs_poll(struct file *filp, poll_table *wait)
474 {
475         struct rchan_reader *reader;
476         unsigned int mask = 0;
477         
478         reader = (struct rchan_reader *)filp->private_data;
479
480         if (reader->rchan->finalized)
481                 return POLLERR;
482
483         if (filp->f_mode & FMODE_READ) {
484                 poll_wait(filp, &reader->rchan->read_wait, wait);
485                 if (!rchan_empty(reader))
486                         mask |= POLLIN | POLLRDNORM;
487         }
488         
489         if (filp->f_mode & FMODE_WRITE) {
490                 poll_wait(filp, &reader->rchan->write_wait, wait);
491                 if (!rchan_full(reader))
492                         mask |= POLLOUT | POLLWRNORM;
493         }
494         
495         return mask;
496 }
497
498 /**
499  *      relayfs_release - release file op for relayfs files
500  *      @inode: the inode
501  *      @filp: the file
502  *
503  *      Decrements the channel refcount, as the filesystem is
504  *      no longer using it.
505  */
506 int
507 relayfs_release(struct inode *inode, struct file *filp)
508 {
509         struct rchan_reader *reader;
510         struct rchan *rchan;
511
512         reader = (struct rchan_reader *)filp->private_data;
513         if (reader == NULL || reader->rchan == NULL)
514                 return 0;
515         rchan = reader->rchan;
516         
517         rchan->callbacks->fileop_notify(reader->rchan->id, filp,
518                                         RELAY_FILE_CLOSE);
519         __remove_rchan_reader(reader);
520         /* The channel is no longer in use as far as this file is concerned */
521         rchan_put(rchan);
522
523         return 0;
524 }
525
526 static struct address_space_operations relayfs_aops = {
527         .readpage       = simple_readpage,
528         .prepare_write  = simple_prepare_write,
529         .commit_write   = simple_commit_write
530 };
531
532 static struct file_operations relayfs_file_operations = {
533         .open           = relayfs_open,
534         .read           = relayfs_file_read,
535         .write          = relayfs_file_write,
536         .ioctl          = relayfs_ioctl,
537         .poll           = relayfs_poll,
538         .mmap           = relayfs_mmap,
539         .fsync          = simple_sync_file,
540         .release        = relayfs_release,
541 };
542
543 static struct inode_operations relayfs_file_inode_operations = {
544         .getattr        = simple_getattr,
545 };
546
547 static struct inode_operations relayfs_dir_inode_operations = {
548         .create         = relayfs_create,
549         .lookup         = simple_lookup,
550         .link           = simple_link,
551         .unlink         = simple_unlink,
552         .symlink        = relayfs_symlink,
553         .mkdir          = relayfs_mkdir,
554         .rmdir          = simple_rmdir,
555         .mknod          = relayfs_mknod,
556         .rename         = simple_rename,
557 };
558
559 static struct super_operations relayfs_ops = {
560         .statfs         = simple_statfs,
561         .drop_inode     = generic_delete_inode,
562 };
563
564 static int 
565 relayfs_fill_super(struct super_block * sb, void * data, int silent)
566 {
567         struct inode * inode;
568         struct dentry * root;
569
570         sb->s_blocksize = PAGE_CACHE_SIZE;
571         sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
572         sb->s_magic = RELAYFS_MAGIC;
573         sb->s_op = &relayfs_ops;
574         inode = relayfs_get_inode(sb, S_IFDIR | 0755, 0);
575
576         if (!inode)
577                 return -ENOMEM;
578
579         root = d_alloc_root(inode);
580         if (!root) {
581                 iput(inode);
582                 return -ENOMEM;
583         }
584         sb->s_root = root;
585
586         return 0;
587 }
588
589 static struct super_block *
590 relayfs_get_sb(struct file_system_type *fs_type,
591         int flags, const char *dev_name, void *data)
592 {
593         return get_sb_single(fs_type, flags, data, relayfs_fill_super);
594 }
595
596 static struct file_system_type relayfs_fs_type = {
597         .owner          = THIS_MODULE,
598         .name           = "relayfs",
599         .get_sb         = relayfs_get_sb,
600         .kill_sb        = kill_litter_super,
601 };
602
603 static int __init 
604 init_relayfs_fs(void)
605 {
606         int err = register_filesystem(&relayfs_fs_type);
607 #ifdef CONFIG_KLOG_CHANNEL
608         if (!err)
609                 create_klog_channel();
610 #endif
611         return err;
612 }
613
614 static void __exit 
615 exit_relayfs_fs(void)
616 {
617 #ifdef CONFIG_KLOG_CHANNEL
618         remove_klog_channel();
619 #endif
620         unregister_filesystem(&relayfs_fs_type);
621 }
622
623 module_init(init_relayfs_fs)
624 module_exit(exit_relayfs_fs)
625
626 MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
627 MODULE_DESCRIPTION("Relay Filesystem");
628 MODULE_LICENSE("GPL");
629