blob: 7d211cbd426bc7685129927a4b1134728b198388 [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 Szeredi43696432001-11-18 19:15:05 +000026 struct fuse_in *in = NULL;
27 struct fuse_forget_in *inarg = NULL;
Miklos Szeredia181e612001-11-06 12:03:23 +000028
Miklos Szeredi43696432001-11-18 19:15:05 +000029 if(fc == NULL)
30 return;
31
32 in = kmalloc(sizeof(struct fuse_in), GFP_NOFS);
33 if(!in)
34 return;
35
36 inarg = kmalloc(sizeof(struct fuse_forget_in), GFP_NOFS);
37 if(!inarg)
38 goto out_free;
Miklos Szeredia181e612001-11-06 12:03:23 +000039
Miklos Szeredi43696432001-11-18 19:15:05 +000040 memset(inarg, 0, sizeof(struct fuse_forget_in));
41 inarg->version = inode->i_version;
42
43 in->h.opcode = FUSE_FORGET;
44 in->h.ino = inode->i_ino;
45 in->numargs = 1;
46 in->args[0].size = sizeof(struct fuse_forget_in);
47 in->args[0].value = inarg;
48
49 if(!request_send_noreply(fc, in))
50 return;
51
52 out_free:
53 kfree(inarg);
54 kfree(in);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000055}
56
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000057static void fuse_put_super(struct super_block *sb)
58{
59 struct fuse_conn *fc = sb->u.generic_sbp;
60
Miklos Szeredi79b52f62001-10-24 14:37:13 +000061 spin_lock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000062 fc->sb = NULL;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +000063 fc->uid = 0;
64 fc->flags = 0;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000065 fuse_release_conn(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +000066 sb->u.generic_sbp = NULL;
Miklos Szeredi96249982001-11-21 12:21:19 +000067 /* Flush all readers on this fs */
68 wake_up_all(&fc->waitq);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000069 spin_unlock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000070}
71
72static struct super_operations fuse_super_operations = {
73 read_inode: fuse_read_inode,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000074 clear_inode: fuse_clear_inode,
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000075 put_super: fuse_put_super,
76};
77
78
79static struct fuse_conn *get_conn(struct fuse_mount_data *d)
80{
81 struct fuse_conn *fc = NULL;
82 struct file *file;
83 struct inode *ino;
84
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000085 if(d == NULL) {
86 printk("fuse_read_super: Bad mount data\n");
87 return NULL;
88 }
89
Miklos Szeredi2df1c042001-11-06 15:07:17 +000090 if(d->version != FUSE_KERNEL_VERSION) {
91 printk("fuse_read_super: Bad version: %i\n", d->version);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000092 return NULL;
93 }
94
95 file = fget(d->fd);
96 ino = NULL;
97 if(file)
98 ino = file->f_dentry->d_inode;
99
100 if(!ino || ino->u.generic_ip != proc_fuse_dev) {
101 printk("fuse_read_super: Bad file: %i\n", d->fd);
102 goto out;
103 }
104
105 fc = file->private_data;
106
107 out:
108 fput(file);
109 return fc;
110
111}
112
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000113static struct inode *get_root_inode(struct super_block *sb, unsigned int mode)
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000114{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000115 struct fuse_attr attr;
116 memset(&attr, 0, sizeof(attr));
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000117
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000118 attr.mode = mode;
Miklos Szeredia181e612001-11-06 12:03:23 +0000119 return fuse_iget(sb, 1, &attr, 0);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000120}
121
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000122static struct super_block *fuse_read_super(struct super_block *sb,
123 void *data, int silent)
124{
125 struct fuse_conn *fc;
126 struct inode *root;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000127 struct fuse_mount_data *d = data;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000128
Miklos Szeredi05033042001-11-13 16:11:35 +0000129 sb->s_blocksize = PAGE_CACHE_SIZE;
130 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000131 sb->s_magic = FUSE_SUPER_MAGIC;
132 sb->s_op = &fuse_super_operations;
133
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000134 root = get_root_inode(sb, d->rootmode);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000135 if(root == NULL) {
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000136 printk("fuse_read_super: failed to get root inode\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000137 return NULL;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000138 }
139
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000140 spin_lock(&fuse_lock);
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000141 fc = get_conn(d);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000142 if(fc == NULL)
143 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000144
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000145 if(fc->sb != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000146 printk("fuse_read_super: connection already mounted\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000147 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000148 }
149
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000150 sb->u.generic_sbp = fc;
151 sb->s_root = d_alloc_root(root);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000152 if(!sb->s_root)
153 goto err;
154
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000155 fc->sb = sb;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000156 fc->flags = d->flags;
157 fc->uid = d->uid;
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000158 spin_unlock(&fuse_lock);
159
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000160 return sb;
161
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000162 err:
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000163 spin_unlock(&fuse_lock);
164 iput(root);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000165 return NULL;
166}
167
168
169static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
170
171int fuse_fs_init()
172{
173 int res;
174
175 res = register_filesystem(&fuse_fs_type);
176 if(res)
177 printk("fuse: failed to register filesystem\n");
178
179 return res;
180}
181
182void fuse_fs_cleanup()
183{
184 unregister_filesystem(&fuse_fs_type);
185}
186
187/*
188 * Local Variables:
189 * indent-tabs-mode: t
190 * c-basic-offset: 8
Miklos Szeredi63a63bc2001-12-02 20:37:53 +0000191 * End:
192 */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000193