blob: 7fc5cfef20ab8f463369fd89de5d27836779bd9a [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;
Miklos Szeredife25def2001-12-20 15:38:05 +000035 memset(in, 0, sizeof(struct fuse_in));
Miklos Szeredi43696432001-11-18 19:15:05 +000036
37 inarg = kmalloc(sizeof(struct fuse_forget_in), GFP_NOFS);
38 if(!inarg)
39 goto out_free;
Miklos Szeredia181e612001-11-06 12:03:23 +000040
Miklos Szeredi43696432001-11-18 19:15:05 +000041 memset(inarg, 0, sizeof(struct fuse_forget_in));
42 inarg->version = inode->i_version;
43
44 in->h.opcode = FUSE_FORGET;
45 in->h.ino = inode->i_ino;
46 in->numargs = 1;
47 in->args[0].size = sizeof(struct fuse_forget_in);
48 in->args[0].value = inarg;
49
50 if(!request_send_noreply(fc, in))
51 return;
52
53 out_free:
54 kfree(inarg);
55 kfree(in);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000056}
57
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000058static void fuse_put_super(struct super_block *sb)
59{
60 struct fuse_conn *fc = sb->u.generic_sbp;
61
Miklos Szeredi79b52f62001-10-24 14:37:13 +000062 spin_lock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000063 fc->sb = NULL;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +000064 fc->uid = 0;
65 fc->flags = 0;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000066 fuse_release_conn(fc);
Miklos Szeredi43696432001-11-18 19:15:05 +000067 sb->u.generic_sbp = NULL;
Miklos Szeredi96249982001-11-21 12:21:19 +000068 /* Flush all readers on this fs */
69 wake_up_all(&fc->waitq);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000070 spin_unlock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000071}
72
73static struct super_operations fuse_super_operations = {
74 read_inode: fuse_read_inode,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000075 clear_inode: fuse_clear_inode,
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000076 put_super: fuse_put_super,
77};
78
79
80static struct fuse_conn *get_conn(struct fuse_mount_data *d)
81{
82 struct fuse_conn *fc = NULL;
83 struct file *file;
84 struct inode *ino;
85
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000086 if(d == NULL) {
87 printk("fuse_read_super: Bad mount data\n");
88 return NULL;
89 }
90
Miklos Szeredi2df1c042001-11-06 15:07:17 +000091 if(d->version != FUSE_KERNEL_VERSION) {
92 printk("fuse_read_super: Bad version: %i\n", d->version);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000093 return NULL;
94 }
95
96 file = fget(d->fd);
97 ino = NULL;
98 if(file)
99 ino = file->f_dentry->d_inode;
100
101 if(!ino || ino->u.generic_ip != proc_fuse_dev) {
102 printk("fuse_read_super: Bad file: %i\n", d->fd);
103 goto out;
104 }
105
106 fc = file->private_data;
107
108 out:
109 fput(file);
110 return fc;
111
112}
113
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000114static struct inode *get_root_inode(struct super_block *sb, unsigned int mode)
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000115{
Miklos Szeredi5e183482001-10-31 14:52:35 +0000116 struct fuse_attr attr;
117 memset(&attr, 0, sizeof(attr));
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000118
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000119 attr.mode = mode;
Miklos Szeredia181e612001-11-06 12:03:23 +0000120 return fuse_iget(sb, 1, &attr, 0);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000121}
122
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000123static struct super_block *fuse_read_super(struct super_block *sb,
124 void *data, int silent)
125{
126 struct fuse_conn *fc;
127 struct inode *root;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000128 struct fuse_mount_data *d = data;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000129
Miklos Szeredi05033042001-11-13 16:11:35 +0000130 sb->s_blocksize = PAGE_CACHE_SIZE;
131 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000132 sb->s_magic = FUSE_SUPER_MAGIC;
133 sb->s_op = &fuse_super_operations;
134
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000135 root = get_root_inode(sb, d->rootmode);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000136 if(root == NULL) {
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000137 printk("fuse_read_super: failed to get root inode\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000138 return NULL;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000139 }
140
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000141 spin_lock(&fuse_lock);
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000142 fc = get_conn(d);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000143 if(fc == NULL)
144 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000145
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000146 if(fc->sb != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000147 printk("fuse_read_super: connection already mounted\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000148 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000149 }
150
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000151 sb->u.generic_sbp = fc;
152 sb->s_root = d_alloc_root(root);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000153 if(!sb->s_root)
154 goto err;
155
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000156 fc->sb = sb;
Miklos Szeredi8cffdb92001-11-09 14:49:18 +0000157 fc->flags = d->flags;
158 fc->uid = d->uid;
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000159 spin_unlock(&fuse_lock);
160
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000161 return sb;
162
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000163 err:
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000164 spin_unlock(&fuse_lock);
165 iput(root);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000166 return NULL;
167}
168
169
170static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
171
172int fuse_fs_init()
173{
174 int res;
175
176 res = register_filesystem(&fuse_fs_type);
177 if(res)
178 printk("fuse: failed to register filesystem\n");
179
180 return res;
181}
182
183void fuse_fs_cleanup()
184{
185 unregister_filesystem(&fuse_fs_type);
186}
187
188/*
189 * Local Variables:
190 * indent-tabs-mode: t
191 * c-basic-offset: 8
Miklos Szeredi63a63bc2001-12-02 20:37:53 +0000192 * End:
193 */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000194