3 * Copyright (C) 2002 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>
27 #include <linux/slab.h>
28 #include <linux/ctype.h>
29 #include <linux/socket.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
34 #include <linux/smp_lock.h>
40 extern struct inode* lu_iget(struct super_block*, struct lufs_fattr*);
41 extern int lufs_notify_change(struct dentry*, struct iattr*);
43 static int lu_readdir(struct file*, void*, filldir_t);
45 static struct dentry *lu_lookup(struct inode*, struct dentry*);
46 static int lu_mkdir(struct inode*, struct dentry*, int);
47 static int lu_create(struct inode*, struct dentry*, int);
48 static int lu_rmdir(struct inode*, struct dentry*);
49 static int lu_rename(struct inode*, struct dentry*, struct inode*, struct dentry*);
50 static int lu_unlink(struct inode*, struct dentry*);
51 static int lu_link(struct dentry*, struct inode*, struct dentry*);
52 static int lu_symlink(struct inode*, struct dentry*, const char*);
54 struct file_operations lu_dir_operations = {
55 .read = generic_read_dir,
56 .readdir = lu_readdir,
59 struct inode_operations lu_dir_inode_operations = {
64 .symlink = lu_symlink,
68 .setattr = lufs_notify_change,
71 static int lu_lookup_validate(struct dentry *dentry, int flags)
73 struct inode *inode = dentry->d_inode;
74 unsigned long age = jiffies - dentry->d_time;
79 res = (age <= LU_MAXAGE);
80 TRACE("age: %lu, valid: %d\n", age, res);
83 res = (lu_revalidate_inode(dentry) == 0);
89 if(is_bad_inode(inode))
93 TRACE("no inode?!\n");
95 TRACE("out(res=%d)\n", res);
100 static int lu_delete_dentry(struct dentry *dentry)
104 if(dentry->d_inode && is_bad_inode(dentry->d_inode)){
105 WARN("bad inode, unhashing \n");
113 struct dentry_operations lufs_dentry_operations = {
114 .d_revalidate = lu_lookup_validate,
115 .d_delete = lu_delete_dentry,
118 static int lu_readdir(struct file *f, void *dirent, filldir_t filldir)
124 struct iovec siov[2], riov;
125 struct server_slot *slot;
126 unsigned short offset;
130 if((slot = lu_getslot(GET_INFO(f->f_dentry->d_sb))) == NULL)
133 if(lu_getname(f->f_dentry, slot->s_buf, LU_MAXDATA) < 0){
134 WARN("lu_getname failed!\n");
138 TRACE("reading %s, offset %u...\n", slot->s_buf, (unsigned)f->f_pos);
141 switch((unsigned int)f->f_pos){
144 if(filldir(dirent, ".", 1, 0, f->f_dentry->d_inode->i_ino, DT_DIR) < 0)
149 if(filldir(dirent, "..", 2, 1, f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
155 siov[0].iov_base = &offset;
156 siov[0].iov_len = sizeof(unsigned short);
157 siov[1].iov_base = slot->s_buf;
158 siov[1].iov_len = strlen(slot->s_buf) + 1;
159 riov.iov_base = slot->s_buf;
160 riov.iov_len = LU_MAXDATA;
162 if((res = lu_execute(GET_INFO(f->f_dentry->d_inode->i_sb), slot, PTYPE_READDIR, siov, 2, &riov, 1)) < 0){
163 WARN("could not read directory content!\n");
164 if(res == -ERESTARTSYS)
169 WARN("server failure!\n");
173 for(qname.name = slot->s_buf, c = strchr(slot->s_buf, '\n'); c != NULL; qname.name = c+1, c = strchr(c+1, '\n')){
175 TRACE("direntry: %s.\n", qname.name);
176 qname.len = strlen(qname.name);
177 if((ino = find_inode_number(f->f_dentry, &qname)) == 0)
178 ino = iunique(f->f_dentry->d_sb, 2);
179 if(filldir(dirent, qname.name, qname.len, f->f_pos, ino, DT_UNKNOWN) < 0)
191 static struct dentry* lu_lookup(struct inode *dir, struct dentry *dentry)
194 struct lufs_fattr fattr;
195 struct iovec siov, riov;
197 struct server_slot *slot;
201 if((slot = lu_getslot(GET_INFO(dir->i_sb))) == NULL)
202 return ERR_PTR(-ERESTARTSYS);
204 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
205 WARN("lu_getname failed!\n");
209 TRACE("looking up %s\n", slot->s_buf);
211 siov.iov_base = slot->s_buf;
212 siov.iov_len = strlen(slot->s_buf) + 1;
213 riov.iov_base = &fattr;
214 riov.iov_len = sizeof(struct lufs_fattr);
216 if((res = lu_execute(GET_INFO(dir->i_sb), slot, PTYPE_STAT, &siov, 1, &riov, 1)) < 0)
220 TRACE("File not found...\n");
221 dentry->d_op = &lufs_dentry_operations;
222 dentry->d_time = jiffies;
228 lu_fixattrs(GET_INFO(dir->i_sb), &fattr);
230 if(dentry == dentry->d_parent)
233 fattr.f_ino = iunique(dentry->d_sb, 2);
235 if((inode = lu_iget(dir->i_sb, &fattr))){
236 dentry->d_op = &lufs_dentry_operations;
237 dentry->d_time = jiffies;
238 d_add(dentry, inode);
249 static int lu_instantiate(struct dentry *dentry, char *name, struct server_slot *slot)
252 struct lufs_fattr fattr;
253 struct iovec siov, riov;
258 TRACE("instantiating %s\n", name);
260 siov.iov_base = name;
261 siov.iov_len = strlen(name) + 1;
262 riov.iov_base = &fattr;
263 riov.iov_len = sizeof(struct lufs_fattr);
265 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_STAT, &siov, 1, &riov, 1)) < 0)
269 TRACE("File not found...\n");
274 lu_fixattrs(GET_INFO(dentry->d_sb), &fattr);
276 fattr.f_ino = iunique(dentry->d_sb, 2);
277 inode = lu_iget(dentry->d_sb, &fattr);
284 d_instantiate(dentry, inode);
292 static int lu_mkdir(struct inode *dir, struct dentry *dentry, int mode)
295 struct server_slot *slot;
300 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
303 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
304 WARN("lu_getname failed!\n");
308 iov[0].iov_base = &mode;
309 iov[0].iov_len = sizeof(mode);
310 iov[1].iov_base = slot->s_buf;
311 iov[1].iov_len = strlen(slot->s_buf) + 1;
313 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_MKDIR, iov, 2, NULL, 0)) < 0)
317 TRACE("Could not create directory.\n");
322 res = lu_instantiate(dentry, slot->s_buf, slot);
331 static int lu_create(struct inode *dir, struct dentry *dentry, int mode)
334 struct server_slot *slot;
339 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
342 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
343 WARN("lu_getname failed!\n");
347 iov[0].iov_base = &mode;
348 iov[0].iov_len = sizeof(mode);
349 iov[1].iov_base = slot->s_buf;
350 iov[1].iov_len = strlen(slot->s_buf) + 1;
352 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_CREATE, iov, 2, NULL, 0)) < 0)
356 TRACE("Could not create file.\n");
361 res = lu_instantiate(dentry, slot->s_buf, slot);
370 static int lu_rmdir(struct inode *dir, struct dentry *dentry)
373 struct server_slot *slot;
376 if(!d_unhashed(dentry))
381 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
384 if((res = lu_getname(dentry, slot->s_buf, LU_MAXDATA)) < 0){
385 WARN("lu_getname failed!");
389 iov.iov_base = slot->s_buf;
390 iov.iov_len = strlen(slot->s_buf) + 1;
392 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_RMDIR, &iov, 1, NULL, 0)) < 0)
396 TRACE("rmdir failed!\n");
409 static int lu_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
411 struct server_slot *slot;
417 if((slot = lu_getslot(GET_INFO(old_dentry->d_sb))) == NULL)
420 if((res = lu_getname(old_dentry, slot->s_buf, LU_MAXPATHLEN)) < 0 ||
421 (res = lu_getname(new_dentry, &(slot->s_buf[LU_MAXPATHLEN]), LU_MAXPATHLEN)) < 0){
422 WARN("lu_getname failed!\n");
426 iov[0].iov_base = slot->s_buf;
427 iov[0].iov_len = strlen(slot->s_buf) + 1;
428 iov[1].iov_base = &(slot->s_buf[LU_MAXPATHLEN]);
429 iov[1].iov_len = strlen(&(slot->s_buf[LU_MAXPATHLEN])) + 1;
431 if((res = lu_execute(GET_INFO(old_dentry->d_sb), slot, PTYPE_RENAME, iov, 2, NULL, 0)) < 0)
435 TRACE("rename failed!\n");
448 static int lu_unlink(struct inode *dir, struct dentry *dentry)
451 struct server_slot *slot;
456 if((slot = lu_getslot(GET_INFO(dentry->d_sb))) == NULL)
459 if((res = lu_getname(dentry, slot->s_buf, LU_MAXPATHLEN)) < 0){
460 WARN("lu_getname failed!");
464 iov.iov_base = slot->s_buf;
465 iov.iov_len = strlen(slot->s_buf) + 1;
467 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_UNLINK, &iov, 1, NULL, 0)) < 0)
471 TRACE("unlink failed!\n");
485 static int lu_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
488 struct server_slot *slot;
493 if(S_ISDIR(old_dentry->d_inode->i_mode))
496 if(!(slot = lu_getslot(GET_INFO(old_dentry->d_sb))))
499 if((res = lu_getname(old_dentry, slot->s_buf, LU_MAXPATHLEN)) < 0){
500 WARN("lu_getname failed!\n");
504 if((res = lu_getname(dentry, &slot->s_buf[LU_MAXPATHLEN], LU_MAXPATHLEN)) < 0){
505 WARN("lu_getname failed!\n");
509 iov[0].iov_base = slot->s_buf;
510 iov[0].iov_len = strlen(slot->s_buf) + 1;
511 iov[1].iov_base = &slot->s_buf[LU_MAXPATHLEN];
512 iov[1].iov_len = strlen(&slot->s_buf[LU_MAXPATHLEN]) + 1;
516 if((res = lu_execute(GET_INFO(old_dentry->d_sb), slot, PTYPE_LINK, iov, 2, NULL, 0)) < 0)
520 TRACE("link failed!\n");
533 static int lu_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
536 struct server_slot *slot;
540 TRACE("symlink: %s\n", symname);
542 if(strlen(symname) > LU_MAXPATHLEN - 1)
543 return -ENAMETOOLONG;
545 if(!(slot = lu_getslot(GET_INFO(dentry->d_sb))))
548 if((res = lu_getname(dentry, slot->s_buf, LU_MAXPATHLEN)) < 0){
549 WARN("lu_getname failed!\n");
553 TRACE("fname: %s\n", slot->s_buf);
555 strcpy(&slot->s_buf[LU_MAXPATHLEN], symname);
557 iov[0].iov_base = slot->s_buf;
558 iov[0].iov_len = strlen(slot->s_buf) + 1;
559 iov[1].iov_base = &slot->s_buf[LU_MAXPATHLEN];
560 iov[1].iov_len = strlen(&slot->s_buf[LU_MAXPATHLEN]) + 1;
564 if((res = lu_execute(GET_INFO(dentry->d_sb), slot, PTYPE_SYMLINK, iov, 2, NULL, 0)) < 0)
568 TRACE("symlink failed!\n");