blob: d4d573aba06c7bb6184f3669b92edf7054c82b0c [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 Szeredibc22e7b2001-10-23 19:26:04 +000011#include <linux/sched.h>
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000012#include <linux/slab.h>
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000013#include <linux/file.h>
14
15#define FUSE_SUPER_MAGIC 0x65735546
16
17static void fuse_read_inode(struct inode *inode)
18{
Miklos Szeredi90d8bef2001-10-26 14:55:42 +000019 /* No op */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000020}
21
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000022static void fuse_clear_inode(struct inode *inode)
23{
Miklos Szeredi5e183482001-10-31 14:52:35 +000024 struct fuse_conn *fc = INO_FC(inode);
Miklos Szeredia181e612001-11-06 12:03:23 +000025 struct fuse_in in = FUSE_IN_INIT;
26 struct fuse_forget_in arg;
27
28 arg.version = inode->i_version;
29
30 in.h.opcode = FUSE_FORGET;
31 in.h.ino = inode->i_ino;
32 in.argsize = sizeof(arg);
33 in.arg = &arg;
34
35 request_send(fc, &in, NULL);
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000036}
37
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000038static void fuse_put_super(struct super_block *sb)
39{
40 struct fuse_conn *fc = sb->u.generic_sbp;
41
Miklos Szeredi79b52f62001-10-24 14:37:13 +000042 spin_lock(&fuse_lock);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000043 fc->sb = NULL;
44 fuse_release_conn(fc);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000045 spin_unlock(&fuse_lock);
46
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000047}
48
49static struct super_operations fuse_super_operations = {
50 read_inode: fuse_read_inode,
Miklos Szeredi85c74fc2001-10-28 19:44:14 +000051 clear_inode: fuse_clear_inode,
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000052 put_super: fuse_put_super,
53};
54
55
56static struct fuse_conn *get_conn(struct fuse_mount_data *d)
57{
58 struct fuse_conn *fc = NULL;
59 struct file *file;
60 struct inode *ino;
61
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000062 if(d == NULL) {
63 printk("fuse_read_super: Bad mount data\n");
64 return NULL;
65 }
66
Miklos Szeredi2df1c042001-11-06 15:07:17 +000067 if(d->version != FUSE_KERNEL_VERSION) {
68 printk("fuse_read_super: Bad version: %i\n", d->version);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000069 return NULL;
70 }
71
72 file = fget(d->fd);
73 ino = NULL;
74 if(file)
75 ino = file->f_dentry->d_inode;
76
77 if(!ino || ino->u.generic_ip != proc_fuse_dev) {
78 printk("fuse_read_super: Bad file: %i\n", d->fd);
79 goto out;
80 }
81
82 fc = file->private_data;
83
84 out:
85 fput(file);
86 return fc;
87
88}
89
Miklos Szeredi2df1c042001-11-06 15:07:17 +000090static struct inode *get_root_inode(struct super_block *sb, unsigned int mode)
Miklos Szeredi79b52f62001-10-24 14:37:13 +000091{
Miklos Szeredi5e183482001-10-31 14:52:35 +000092 struct fuse_attr attr;
93 memset(&attr, 0, sizeof(attr));
Miklos Szeredi79b52f62001-10-24 14:37:13 +000094
Miklos Szeredi2df1c042001-11-06 15:07:17 +000095 attr.mode = mode;
Miklos Szeredia181e612001-11-06 12:03:23 +000096 return fuse_iget(sb, 1, &attr, 0);
Miklos Szeredi79b52f62001-10-24 14:37:13 +000097}
98
Miklos Szeredibc22e7b2001-10-23 19:26:04 +000099static struct super_block *fuse_read_super(struct super_block *sb,
100 void *data, int silent)
101{
102 struct fuse_conn *fc;
103 struct inode *root;
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000104 struct fuse_mount_data *d = data;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000105
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000106 sb->s_blocksize = 1024;
107 sb->s_blocksize_bits = 10;
108 sb->s_magic = FUSE_SUPER_MAGIC;
109 sb->s_op = &fuse_super_operations;
110
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000111 root = get_root_inode(sb, d->rootmode);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000112 if(root == NULL) {
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000113 printk("fuse_read_super: failed to get root inode\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000114 return NULL;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000115 }
116
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000117 spin_lock(&fuse_lock);
Miklos Szeredi2df1c042001-11-06 15:07:17 +0000118 fc = get_conn(d);
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000119 if(fc == NULL)
120 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000121
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000122 if(fc->sb != NULL) {
Miklos Szeredia181e612001-11-06 12:03:23 +0000123 printk("fuse_read_super: connection already mounted\n");
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000124 goto err;
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000125 }
126
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000127 sb->u.generic_sbp = fc;
128 sb->s_root = d_alloc_root(root);
Miklos Szeredi19dff1b2001-10-30 15:06:52 +0000129 if(!sb->s_root)
130 goto err;
131
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000132 fc->sb = sb;
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000133 spin_unlock(&fuse_lock);
134
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000135 return sb;
136
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000137 err:
Miklos Szeredi79b52f62001-10-24 14:37:13 +0000138 spin_unlock(&fuse_lock);
139 iput(root);
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000140 return NULL;
141}
142
143
144static DECLARE_FSTYPE(fuse_fs_type, "fuse", fuse_read_super, 0);
145
146int fuse_fs_init()
147{
148 int res;
149
150 res = register_filesystem(&fuse_fs_type);
151 if(res)
152 printk("fuse: failed to register filesystem\n");
153
154 return res;
155}
156
157void fuse_fs_cleanup()
158{
159 unregister_filesystem(&fuse_fs_type);
160}
161
162/*
163 * Local Variables:
164 * indent-tabs-mode: t
165 * c-basic-offset: 8
Miklos Szeredia181e612001-11-06 12:03:23 +0000166 * End: */
Miklos Szeredibc22e7b2001-10-23 19:26:04 +0000167