3 * Copyright (C) 2002-2003 Florin Malita <mali@go.ro>
5 * This file is part of LUFS, a free userspace filesystem implementation.
6 * See http://lufs.sourceforge.net/ for updates.
8 * LUFS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * LUFS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/version.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/init.h>
28 #include <linux/slab.h>
29 #include <linux/list.h>
30 #include <linux/smp_lock.h>
31 #include <linux/signal.h>
32 #include <linux/sched.h>
33 #include <linux/socket.h>
34 #include <linux/string.h>
35 #include <linux/vfs.h>
37 #include <asm/system.h>
38 #include <asm/uaccess.h>
43 MODULE_AUTHOR("Florin Malita <mali@go.ro>");
44 MODULE_DESCRIPTION("Linux Userland Filesystem");
46 MODULE_LICENSE("GPL");
49 extern struct file_operations lu_dir_operations, lu_file_operations;
50 extern struct inode_operations lu_dir_inode_operations, lu_file_inode_operations, lu_symlink_inode_operations;
51 extern struct address_space_operations lu_file_aops;
52 extern struct dentry_operations lufs_dentry_operations;
54 static void lu_delete_inode(struct inode*);
55 static void lu_put_super(struct super_block*);
56 static int lu_statfs(struct super_block*, struct statfs*);
58 static struct super_operations lu_sops = {
59 .drop_inode = generic_delete_inode,
60 .delete_inode = lu_delete_inode,
61 .put_super = lu_put_super,
67 * Ignore unknown options, they're probably for the userspace daemon.
69 static void parse_options(struct lufs_sb_info *server, char *opts)
79 while((p = strsep(&opts, ","))){
80 if(strncmp(p, "server_socket=", 14) == 0){
81 if(strlen(p+14) > UNIX_PATH_MAX)
83 strcpy(server->server_socket, p+14);
84 TRACE("server_socket: %s\n", server->server_socket);
86 if(strncmp(p, "uid=", 4) == 0){
88 ERROR("only root can use uid option!\n");
93 server->config.uid = simple_strtoul(q, &q, 0);
94 TRACE("uid: %d\n", server->config.uid);
97 if(strncmp(p, "gid=", 4) == 0){
99 ERROR("only root can use gid option!\n");
104 server->config.gid = simple_strtoul(q, &q, 0);
105 TRACE("gid: %d\n", server->config.gid);
108 if(strncmp(p, "fmask=", 6) == 0){
109 if(strlen(p + 6) > 3)
112 server->config.fmode = (((q[0] - '0') << 6) + ((q[1] - '0') << 3) + (q[2] - '0')) & (S_IRWXU | S_IRWXG | S_IRWXO);
113 TRACE("fmode: %d\n", server->config.fmode);
115 if(strncmp(p, "dmask=", 6) == 0){
116 if(strlen(p + 6) > 3)
119 server->config.dmode = (((q[0] - '0') << 6) + ((q[1] - '0') << 3) + (q[2] - '0')) & (S_IRWXU | S_IRWXG | S_IRWXO);
120 TRACE("dmode: %d\n", server->config.dmode);
122 if(strncmp(p, "root=", 5) == 0){
123 if(strlen(p+5) >= UNIX_PATH_MAX - 1)
125 strcpy(server->root, p+5);
126 server->rootlen = strlen(server->root);
128 if(server->root[server->rootlen - 1] == '/'){
129 server->root[server->rootlen - 1] = 0;
133 TRACE("remote root: %s, len: %u\n", server->root, server->rootlen);
135 if(strncmp(p, "channels=", 9) == 0){
139 server->config.channels = simple_strtoul(q, &q, 0);
141 TRACE("channels: %u\n", server->config.channels);
143 if(strncmp(p, "own_fs", 6) == 0){
144 server->config.own_fs = 1;
145 TRACE("forcing ownership\n");
147 if(strncmp(p, "server_pid=", 11) == 0){
151 server->server_pid = simple_strtoul(q, &q, 0);
153 TRACE("server_pid: %u\n", server->server_pid);
160 WARN("evil options!\n");
164 * Fill in inode attributes.
165 * Ivalidate the page_cache pages if the inode has been modified.
167 static void set_inode_attr(struct inode *inode, struct lufs_fattr *fattr)
169 time_t last_time = inode->i_mtime.tv_sec;
170 loff_t last_sz = inode->i_size;
174 inode->i_mode = fattr->f_mode;
175 inode->i_nlink = fattr->f_nlink;
176 inode->i_uid = fattr->f_uid;
177 inode->i_gid = fattr->f_gid;
178 inode->i_ctime.tv_sec = fattr->f_ctime;
179 inode->i_mtime.tv_sec = fattr->f_mtime;
180 inode->i_atime.tv_sec = fattr->f_atime;
181 inode->i_blksize = fattr->f_blksize;
182 inode->i_blocks = fattr->f_blocks;
183 inode->i_size = fattr->f_size;
185 if(inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz){
186 TRACE("inode changed...\n");
187 if(!S_ISDIR(inode->i_mode))
188 invalidate_inode_pages(inode->i_mapping);
194 static int lu_do_stat(struct dentry *dentry, struct lufs_fattr *fattr)
196 struct server_slot *slot;
197 struct iovec siov, riov;
202 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
205 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
206 WARN("lu_getname failed!\n");
210 TRACE("stating %s...\n", slot->s_buf);
212 siov.iov_base = slot->s_buf;
213 siov.iov_len = strlen(slot->s_buf) + 1;
214 riov.iov_base = fattr;
215 riov.iov_len = sizeof(struct lufs_fattr);
217 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_STAT, &siov, 1, &riov, 1)) < 0)
221 WARN("stat failed!\n");
226 lu_fixattrs(GET_INFO(dentry->d_sb), fattr);
237 * Reload inode attributes.
239 static int lu_refresh_inode(struct dentry *dentry)
241 struct inode *inode = dentry->d_inode;
242 struct lufs_fattr fattr;
247 if((res = lu_do_stat(dentry, &fattr)) < 0)
250 dentry->d_time = jiffies;
255 if((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT))
256 set_inode_attr(inode, &fattr);
258 WARN("inode changed mode, %x to %x\n", inode->i_mode, (unsigned int)fattr.f_mode);
261 fattr.f_mode = inode->i_mode;
262 make_bad_inode(inode);
263 inode->i_mode = fattr.f_mode;
265 if(!S_ISDIR(inode->i_mode))
266 invalidate_inode_pages(inode->i_mapping);
275 int lu_revalidate_inode(struct dentry *dentry)
283 if(time_before(jiffies, dentry->d_time + LU_MAXAGE))
286 res = lu_refresh_inode(dentry);
294 int lufs_notify_change(struct dentry *dentry, struct iattr *iattr)
296 struct server_slot *slot;
298 struct lufs_fattr fattr;
303 if((res = lu_do_stat(dentry, &fattr)) < 0)
306 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
309 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
310 WARN("lu_getname failed!\n");
314 if(iattr->ia_valid & ATTR_MODE)
315 fattr.f_mode = iattr->ia_mode;
316 if(iattr->ia_valid & ATTR_UID)
317 fattr.f_uid = iattr->ia_uid;
318 if(iattr->ia_valid & ATTR_GID)
319 fattr.f_gid = iattr->ia_gid;
320 if(iattr->ia_valid & ATTR_SIZE)
321 fattr.f_size = iattr->ia_size;
322 if(iattr->ia_valid & ATTR_ATIME)
323 fattr.f_atime= iattr->ia_atime.tv_sec;
324 if(iattr->ia_valid & ATTR_MTIME)
325 fattr.f_mtime= iattr->ia_mtime.tv_sec;
326 if(iattr->ia_valid & ATTR_CTIME)
327 fattr.f_ctime= iattr->ia_ctime.tv_sec;
329 iov[0].iov_base = &fattr;
330 iov[0].iov_len = sizeof(struct lufs_fattr);
331 iov[1].iov_base = slot->s_buf;
332 iov[1].iov_len = strlen(slot->s_buf) + 1;
334 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_SETATTR, iov, 2, NULL, 0)) < 0)
338 WARN("setattr failed!\n");
345 lu_refresh_inode(dentry);
354 * We always create a new inode here.
356 struct inode* lu_iget(struct super_block *sb, struct lufs_fattr *fattr)
365 res->i_ino = fattr->f_ino;
366 set_inode_attr(res, fattr);
368 if(S_ISDIR(res->i_mode)){
369 TRACE("it's a dir.\n");
370 res->i_op = &lu_dir_inode_operations;
371 res->i_fop = &lu_dir_operations;
372 }else if(S_ISLNK(res->i_mode)){
373 TRACE("it's a link.\n");
374 res->i_op = &lu_symlink_inode_operations;
376 TRACE("it's a file.\n");
377 res->i_op = &lu_file_inode_operations;
378 res->i_fop = &lu_file_operations;
379 res->i_data.a_ops = &lu_file_aops;
382 insert_inode_hash(res);
386 static int lu_statfs(struct super_block *sb, struct statfs *attr)
390 attr->f_type = LU_MAGIC;
391 attr->f_bsize = LU_BLOCKSIZE;
393 attr->f_namelen = LU_MAXPATHLEN;
401 static void lu_put_super(struct super_block *sb)
407 info.si_signo = SIGUSR1;
409 info.si_code = SI_USER;
410 info.si_pid = current->pid;
411 info.si_uid = current->uid;
413 /* notify the daemon that we're going bye-bye */
414 kill_proc_info(SIGUSR1, &info, GET_INFO(sb)->server_pid);
416 lu_empty_slots(GET_INFO(sb));
421 static void lu_delete_inode(struct inode *in)
428 static int lu_fill_super(struct super_block *sb, void *opts, int silent)
430 struct lufs_sb_info *info;
431 struct server_slot *slot;
432 struct lufs_fattr root_attr;
433 struct inode *root_inode;
440 ERROR("need some options here!\n");
444 if((info = (struct lufs_sb_info*)kmalloc(sizeof(struct lufs_sb_info), GFP_KERNEL)) == NULL){
445 ERROR("kmalloc error!\n");
448 memset(info, 0, sizeof(struct lufs_sb_info));
449 info->lock = RW_LOCK_UNLOCKED;
450 INIT_LIST_HEAD(&info->slots);
452 info->config.uid = current->uid;
453 info->config.gid = current->gid;
454 info->config.channels = LU_NRSLOTS;
456 parse_options(info, opts);
458 if(!info->server_socket[0]){
459 ERROR("no server_socket specified!\n");
463 for(i = 0; i < info->config.channels; i++){
464 if((slot = kmalloc(sizeof(struct server_slot), GFP_KERNEL)) == NULL){
465 ERROR("kmalloc error!\n");
468 memset(slot, 0, sizeof(struct server_slot));
469 init_MUTEX(&slot->s_lock);
470 if((slot->s_buf = kmalloc(LU_MAXDATA, GFP_KERNEL)) == NULL){
471 ERROR("kmalloc error!\n");
474 list_add(&slot->s_list, &info->slots);
477 sb->s_fs_info = info;
478 sb->s_blocksize = LU_BLOCKSIZE;
479 sb->s_blocksize_bits = LU_BLOCKSIZEBITS;
480 sb->s_magic = LU_MAGIC;
483 sb->s_maxbytes = ((((long long)1) << 32) << LU_BLOCKSIZEBITS) - 1;
484 TRACE("sb->s_maxbytes=%Ld\n",sb->s_maxbytes);
486 lu_lookup_root(info, &root_attr);
487 root_inode = lu_iget(sb, &root_attr);
490 sb->s_root = d_alloc_root(root_inode);
494 sb->s_root->d_op = &lufs_dentry_operations;
495 sb->s_root->d_time = jiffies;
497 TRACE("mount succeded: %s\n", info->server_socket);
501 lu_empty_slots(info);
505 ERROR("mount failed!\n");
509 static struct super_block *lu_get_sb(struct file_system_type *fs_type, int flags, char *dev_name, void *data)
511 return get_sb_nodev(fs_type, flags, data, lu_fill_super);
514 static struct file_system_type lu_fs_type = {
515 .owner = THIS_MODULE,
518 .kill_sb = kill_anon_super,
521 static int __init lu_init(void)
523 VERBOSE("UserLand File System\n");
524 VERBOSE("Copyright (c) 2002, Florin Malita\n");
525 return register_filesystem(&lu_fs_type);
528 static void __exit lu_release(void)
530 VERBOSE("Unregistering lufs...\n");
531 unregister_filesystem(&lu_fs_type);
534 module_init(lu_init);
535 module_exit(lu_release);