blob: 36819b732c0a6bfa0580c98e0ed8caa7dcc094f3 [file] [log] [blame]
Miklos Szeredibc22e7b2001-10-23 19:26:04 +00001/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu)
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
Miklos Szeredibc22e7b2001-10-23 19:26:04 +00009#include "fuse_i.h"
10
Miklos Szeredi05033042001-11-13 16:11:35 +000011#include <linux/pagemap.h>
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000012#include <linux/sched.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000013#include <linux/slab.h>
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000014#include <linux/file.h>
15
16#define FUSE_SUPER_MAGIC 0x65735546
17
18static void fuse_read_inode(struct inode *inode)
19{
Miklos Szeredi90d8bef2001-10-26 14:55:42 +000020 /* No op */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000021}
22
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000023static void fuse_clear_inode(struct inode *inode)
24{
Miklos Szeredi5e183482001-10-31 14:52:35 +000025 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia181e612001-11-06 12:03:23 +000026 struct fuse_in in = FUSE_IN_INIT;
27 struct fuse_forget_in arg;
28
29 arg.version = inode->i_version;
30
31 in.h.opcode = FUSE_FORGET;
32 in.h.ino = inode->i_ino;
33 in.argsize = sizeof(arg);
34 in.arg = &arg;
35
36 request_send(fc, &in, NULL);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000037}
38
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000039static void fuse_put_super(struct super_block *sb)
40{
41 struct fuse_conn *fc = sb->u.generic_sbp;
42
Miklos Szeredi79b52f62001-10-24 14:37:13 +000043 spin_lock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000044 fc->sb = NULL;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +000045 fc->uid = 0;
46 fc->flags = 0;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000047 fuse_release_conn(fc);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000048 spin_unlock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000049}
50
51static struct super_operations fuse_super_operations = {
52 read_inode: fuse_read_inode,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000053 clear_inode: fuse_clear_inode,
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000054 put_super: fuse_put_super,
55};
56
57
58static struct fuse_conn *get_conn(struct fuse_mount_data *d)
59{
60 struct fuse_conn *fc = NULL;
61 struct file *file;
62 struct inode *ino;
63
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000064 if(d == NULL) {
65 printk("fuse_read_super: Bad mount data\n");
66 return NULL;
67 }
68
Miklos Szeredi2df1c042001-11-06 15:07:17 +000069 if(d->version != FUSE_KERNEL_VERSION) {
70 printk("fuse_read_super: Bad version: %i\n", d->version);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000071 return NULL;
72 }
73
74 file = fget(d->fd);
75 ino = NULL;
76 if(file)
77 ino = file->f_dentry->d_inode;
78
79 if(!ino || ino->u.generic_ip != proc_fuse_dev) {
80 printk("fuse_read_super: Bad file: %i\n", d->fd);
81 goto out;
82 }
83
84 fc = file->private_data;
85
86 out:
87 fput(file);
88 return fc;
89
90}
91
Miklos Szeredi2df1c042001-11-06 15:07:17 +000092static struct inode *get_root_inode(struct super_block *sb, unsigned int mode)
Miklos Szeredi79b52f62001-10-24 14:37:13 +000093{
Miklos Szeredi5e183482001-10-31 14:52:35 +000094 struct fuse_attr attr;
95 memset(&attr, 0, sizeof(attr));
Miklos Szeredi79b52f62001-10-24 14:37:13 +000096
Miklos Szeredi2df1c042001-11-06 15:07:17 +000097 attr.mode = mode;
Miklos Szeredia181e612001-11-06 12:03:23 +000098 return fuse_iget(sb, 1, &attr, 0);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000099}
100
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000101static struct super_block *fuse_read_super(struct super_block *sb,
102 void *data, int silent)
103{
104 struct fuse_conn *fc;
105 struct inode *root;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000106 struct fuse_mount_data *d = data;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000107
Miklos Szeredi05033042001-11-13 16:11:35 +0000108 sb->s_blocksize = PAGE_CACHE_SIZE;
109 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000110 sb->s_magic = FUSE_SUPER_MAGIC;
111 sb->s_op = &fuse_super_operations;
112
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000113 root = get_root_inode(sb, d->rootmode);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000114 if(root == NULL) {
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000115 printk("fuse_read_super: failed to get root inode\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000116 return NULL;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000117 }
118
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000119 spin_lock(&fuse_lock);
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000120 fc = get_conn(d);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000121 if(fc == NULL)
122 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000123
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000124 if(fc->sb != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000125 printk("fuse_read_super: connection already mounted\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000126 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000127 }
128
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000129 sb->u.generic_sbp = fc;
130 sb->s_root = d_alloc_root(root);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000131 if(!sb->s_root)
132 goto err;
133
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000134 fc->sb = sb;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000135 fc->flags = d->flags;
136 fc->uid = d->uid;
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000137 spin_unlock(&fuse_lock);
138
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000139 return sb;
140
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000141 err:
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000142 spin_unlock(&fuse_lock);
143 iput(root);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000144 return NULL;
145}
146
147
148static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
149
150int fuse_fs_init()
151{
152 int res;
153
154 res = register_filesystem(&fuse_fs_type);
155 if(res)
156 printk("fuse: failed to register filesystem\n");
157
158 return res;
159}
160
161void fuse_fs_cleanup()
162{
163 unregister_filesystem(&fuse_fs_type);
164}
165
166/*
167 * Local Variables:
168 * indent-tabs-mode: t
169 * c-basic-offset: 8
Miklos Szeredia181e612001-11-06 12:03:23 +0000170 * End: */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000171