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 kstatfs*);
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 kstatfs *attr)
390 struct server_slot *slot;
391 struct lufs_sbattr sbattr;
395 if((slot = lu_getslot(GET_INFO(sb))) == NULL)
398 riov.iov_base = &sbattr;
399 riov.iov_len = sizeof(sbattr);
401 if((res = lu_execute(GET_INFO(sb), slot, PTYPE_STATFS, NULL, 0, &riov, 1)) < 0)
405 WARN("statfs failed\n");
410 attr->f_type = LU_MAGIC;
411 attr->f_bsize = LU_BLOCKSIZE;
412 attr->f_blocks = sbattr.sb_bytes / LU_BLOCKSIZE;
413 attr->f_bfree = sbattr.sb_bytes_free / LU_BLOCKSIZE;
414 attr->f_bavail = sbattr.sb_bytes_available / LU_BLOCKSIZE;
415 attr->f_files = sbattr.sb_files;
416 attr->f_ffree = sbattr.sb_ffree;
417 attr->f_namelen = 0xFF;
427 static void lu_put_super(struct super_block *sb)
433 info.si_signo = SIGUSR1;
435 info.si_code = SI_USER;
436 info.si_pid = current->pid;
437 info.si_uid = current->uid;
439 /* notify the daemon that we're going bye-bye */
440 kill_proc_info(SIGUSR1, &info, GET_INFO(sb)->server_pid);
442 lu_empty_slots(GET_INFO(sb));
447 static void lu_delete_inode(struct inode *in)
454 static int lu_fill_super(struct super_block *sb, void *opts, int silent)
456 struct lufs_sb_info *info;
457 struct server_slot *slot;
458 struct lufs_fattr root_attr;
459 struct inode *root_inode;
466 ERROR("need some options here!\n");
470 if((info = (struct lufs_sb_info*)kmalloc(sizeof(struct lufs_sb_info), GFP_KERNEL)) == NULL){
471 ERROR("kmalloc error!\n");
474 memset(info, 0, sizeof(struct lufs_sb_info));
475 info->lock = RW_LOCK_UNLOCKED;
476 INIT_LIST_HEAD(&info->slots);
478 info->config.uid = current->uid;
479 info->config.gid = current->gid;
480 info->config.channels = LU_NRSLOTS;
482 parse_options(info, opts);
484 if(!info->server_socket[0]){
485 ERROR("no server_socket specified!\n");
489 for(i = 0; i < info->config.channels; i++){
490 if((slot = kmalloc(sizeof(struct server_slot), GFP_KERNEL)) == NULL){
491 ERROR("kmalloc error!\n");
494 memset(slot, 0, sizeof(struct server_slot));
495 init_MUTEX(&slot->s_lock);
496 if((slot->s_buf = kmalloc(LU_MAXDATA, GFP_KERNEL)) == NULL){
497 ERROR("kmalloc error!\n");
500 list_add(&slot->s_list, &info->slots);
503 sb->s_fs_info = info;
504 sb->s_blocksize = LU_BLOCKSIZE;
505 sb->s_blocksize_bits = LU_BLOCKSIZEBITS;
506 sb->s_magic = LU_MAGIC;
509 sb->s_maxbytes = ((((long long)1) << 32) << LU_BLOCKSIZEBITS) - 1;
510 TRACE("sb->s_maxbytes=%Ld\n",sb->s_maxbytes);
512 lu_lookup_root(info, &root_attr);
513 root_inode = lu_iget(sb, &root_attr);
516 sb->s_root = d_alloc_root(root_inode);
520 sb->s_root->d_op = &lufs_dentry_operations;
521 sb->s_root->d_time = jiffies;
523 TRACE("mount succeded: %s\n", info->server_socket);
527 lu_empty_slots(info);
531 ERROR("mount failed!\n");
535 static struct super_block *lu_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
537 return get_sb_nodev(fs_type, flags, data, lu_fill_super);
540 static struct file_system_type lu_fs_type = {
541 .owner = THIS_MODULE,
544 .kill_sb = kill_anon_super,
547 static int __init lu_init(void)
549 VERBOSE("UserLand File System\n");
550 VERBOSE("Copyright (c) 2002, Florin Malita\n");
551 return register_filesystem(&lu_fs_type);
554 static void __exit lu_release(void)
556 VERBOSE("Unregistering lufs...\n");
557 unregister_filesystem(&lu_fs_type);
560 module_init(lu_init);
561 module_exit(lu_release);