1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2000 Stelias Computing, Inc.
5 * Copyright (C) 2000 Red Hat, Inc.
6 * Copyright (C) 2000 Tacitus Systems
7 * Copyright (C) 2000 Peter J. Braam
9 * This file is part of InterMezzo, http://www.inter-mezzo.org.
11 * InterMezzo is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * InterMezzo is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with InterMezzo; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <asm/bitops.h>
26 #include <asm/termios.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
30 #include <linux/errno.h>
32 #include <linux/namei.h>
33 #include <linux/ext2_fs.h>
34 #include <linux/slab.h>
35 #include <linux/vmalloc.h>
36 #include <linux/sched.h>
37 #include <linux/stat.h>
38 #include <linux/string.h>
39 #include <linux/blkdev.h>
40 #include <linux/init.h>
41 #include <linux/module.h>
43 #include "intermezzo_fs.h"
44 #include "intermezzo_psdev.h"
46 static inline void presto_relock_sem(struct inode *dir)
48 /* the lock from sys_mkdir / lookup_create */
50 /* the rest is done by the do_{create,mkdir, ...} */
53 static inline void presto_relock_other(struct inode *dir)
56 // down(&dir->i_zombie);
60 static inline void presto_fulllock(struct inode *dir)
62 /* the lock from sys_mkdir / lookup_create */
65 // down(&dir->i_zombie);
69 static inline void presto_unlock(struct inode *dir)
73 // up(&dir->i_zombie);
74 /* the lock from sys_mkdir / lookup_create */
80 * these are initialized in super.c
82 extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
83 static int izo_authorized_uid;
85 int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id,
86 unsigned int *generation)
92 /* prefix is 7 characters: '...ino:' */
93 if ( dentry->d_name.len < 7 || dentry->d_name.len > 64 ||
94 memcmp(dentry->d_name.name, PRESTO_ILOOKUP_MAGIC, 7) != 0 ) {
99 memcpy(tmpname, dentry->d_name.name + 7, dentry->d_name.len - 7);
100 *(tmpname + dentry->d_name.len - 7) = '\0';
102 /* name is of the form ...ino:<inode number>:<generation> */
103 *id = simple_strtoul(tmpname, &next, 16);
104 if ( *next == PRESTO_ILOOKUP_SEP ) {
105 *generation = simple_strtoul(next + 1, 0, 16);
106 CDEBUG(D_INODE, "ino string: %s, Id = %lx (%lu), "
107 "generation %x (%d)\n",
108 tmpname, *id, *id, *generation, *generation);
117 struct dentry *presto_tmpfs_ilookup(struct inode *dir,
118 struct dentry *dentry,
120 unsigned int generation)
126 inline int presto_can_ilookup(void)
128 return (current->euid == izo_authorized_uid ||
129 capable(CAP_DAC_READ_SEARCH));
132 struct dentry *presto_iget_ilookup(struct inode *dir,
133 struct dentry *dentry,
135 unsigned int generation)
142 if ( !presto_can_ilookup() ) {
143 CERROR("ilookup denied: euid %u, authorized_uid %u\n",
144 current->euid, izo_authorized_uid);
145 return ERR_PTR(-EPERM);
148 inode = iget(dir->i_sb, ino);
150 CERROR("fatal: NULL inode ino %lu\n", ino);
153 if (is_bad_inode(inode) || inode->i_nlink == 0) {
154 CERROR("fatal: bad inode ino %lu, links %d\n", ino, inode->i_nlink);
157 if (inode->i_generation != generation) {
158 CERROR("fatal: bad generation %u (want %u)\n",
159 inode->i_generation, generation);
163 d_instantiate(dentry, inode);
164 dentry->d_flags |= DCACHE_DISCONNECTED; /* NFS hack */
172 return ERR_PTR(error);
175 struct dentry *presto_add_ilookup_dentry(struct dentry *parent,
178 struct inode *inode = real->d_inode;
182 struct dentry *inodir;
183 struct presto_dentry_data *dd;
185 inodir = lookup_one_len("..iopen..", parent, strlen("..iopen.."));
186 if (!inodir || IS_ERR(inodir) || !inodir->d_inode ) {
187 CERROR("%s: bad ..iopen.. lookup\n", __FUNCTION__);
190 inodir->d_inode->i_op = &presto_dir_iops;
192 snprintf(ptr, 32, "...ino:%lx:%x", inode->i_ino, inode->i_generation);
194 de = lookup_one_len(ptr, inodir, strlen(ptr));
195 if (!de || IS_ERR(de)) {
196 CERROR("%s: bad ...ino lookup %ld\n",
197 __FUNCTION__, PTR_ERR(de));
202 dd = presto_d2d(real);
210 if (de->d_inode != inode ) {
211 CERROR("XX de->d_inode %ld, inode %ld\n",
212 de->d_inode->i_ino, inode->i_ino);
215 if (dd->dd_inodentry) {
216 CERROR("inodentry exists %ld \n", inode->i_ino);
227 atomic_inc(&inode->i_count);
228 de->d_op = &presto_dentry_ops;
231 CERROR("DD: no ops dentry %p, dd %p\n", de, dd);
232 dd->dd_inodentry = de;
240 struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
244 struct presto_cache *cache;
247 unsigned int generation;
248 struct inode_operations *iops;
252 cache = presto_get_cache(dir);
254 CERROR("InterMezzo BUG: no cache in presto_lookup "
255 "(dir ino: %ld)!\n", dir->i_ino);
259 minor = presto_c2m(cache);
261 iops = filter_c2cdiops(cache->cache_filter);
262 if (!iops || !iops->lookup) {
263 CERROR("InterMezzo BUG: filesystem has no lookup\n");
269 CDEBUG(D_CACHE, "dentry %p, dir ino: %ld, name: %*s, islento: %d\n",
270 dentry, dir->i_ino, dentry->d_name.len, dentry->d_name.name,
273 if (dentry->d_fsdata)
274 CERROR("DD -- BAD dentry %p has data\n", dentry);
276 dentry->d_fsdata = NULL;
278 if (ext2_check_for_iopen(dir, dentry))
282 if ( izo_dentry_is_ilookup(dentry, &ino, &generation) ) {
283 de = cache->cache_filter->o_trops->tr_ilookup
284 (dir, dentry, ino, generation);
287 de = iops->lookup(dir, dentry, nd);
293 CERROR("dentry lookup error %ld\n", PTR_ERR(de));
297 /* some file systems have no read_inode: set methods here */
299 presto_set_ops(dentry->d_inode, cache->cache_filter);
301 filter_setup_dentry_ops(cache->cache_filter,
302 dentry->d_op, &presto_dentry_ops);
303 dentry->d_op = filter_c2udops(cache->cache_filter);
305 /* In lookup we will tolerate EROFS return codes from presto_set_dd
306 * to placate NFS. EROFS indicates that a fileset was not found but
307 * we should still be able to continue through a lookup.
308 * Anything else is a hard error and must be returned to VFS. */
310 rc = presto_set_dd(dentry);
311 if (rc && rc != -EROFS) {
312 CERROR("presto_set_dd failed (dir %ld, name %*s): %d\n",
313 dir->i_ino, dentry->d_name.len, dentry->d_name.name, rc);
321 static inline int presto_check_set_fsdata (struct dentry *de)
323 if (presto_d2d(de) == NULL) {
325 CERROR("dentry without fsdata: %p: %*s\n", de,
326 de->d_name.len, de->d_name.name);
329 return presto_set_dd (de);
335 int presto_setattr(struct dentry *de, struct iattr *iattr)
338 struct presto_cache *cache;
339 struct presto_file_set *fset;
340 struct lento_vfs_context info = { 0, {0}, 0 };
344 error = presto_prep(de, &cache, &fset);
350 if (!iattr->ia_valid)
351 CDEBUG(D_INODE, "presto_setattr: iattr is not valid\n");
353 CDEBUG(D_INODE, "valid %#x, mode %#o, uid %u, gid %u, size %Lu, "
354 "atime %lu mtime %lu ctime %lu flags %d\n",
355 iattr->ia_valid, iattr->ia_mode, iattr->ia_uid, iattr->ia_gid,
356 iattr->ia_size, iattr->ia_atime.tv_sec, iattr->ia_mtime.tv_sec,
357 iattr->ia_ctime.tv_sec, iattr->ia_attr_flags);
359 if ( presto_get_permit(de->d_inode) < 0 ) {
364 if (!ISLENTO(presto_c2m(cache)))
365 info.flags = LENTO_FL_KML;
366 info.flags |= LENTO_FL_IGNORE_TIME;
367 error = presto_do_setattr(fset, de, iattr, &info);
368 presto_put_permit(de->d_inode);
373 * Now the meat: the fs operations that require journaling
376 * XXX: some of these need modifications for hierarchical filesets
379 int presto_prep(struct dentry *dentry, struct presto_cache **cache,
380 struct presto_file_set **fset)
384 /* NFS might pass us dentries which have not gone through lookup.
385 * Test and set d_fsdata for such dentries
387 rc = presto_check_set_fsdata (dentry);
390 *fset = presto_fset(dentry);
391 if ( *fset == NULL ) {
392 CERROR("No file set for dentry at %p: %*s\n", dentry,
393 dentry->d_name.len, dentry->d_name.name);
397 *cache = (*fset)->fset_cache;
398 if ( *cache == NULL ) {
399 CERROR("PRESTO: BAD, BAD: cannot find cache\n");
403 CDEBUG(D_PIOCTL, "---> cache flags %x, fset flags %x\n",
404 (*cache)->cache_flags, (*fset)->fset_flags);
405 if( presto_is_read_only(*fset) ) {
406 CERROR("PRESTO: cannot modify read-only fileset, minor %d.\n",
413 static int presto_create(struct inode * dir, struct dentry * dentry, int mode,
414 struct nameidata *nd)
417 struct presto_cache *cache;
418 struct dentry *parent = dentry->d_parent;
419 struct lento_vfs_context info;
420 struct presto_file_set *fset;
423 error = presto_check_set_fsdata(dentry);
429 error = presto_prep(dentry->d_parent, &cache, &fset);
436 /* Does blocking and non-blocking behavious need to be
437 checked for. Without blocking (return 1), the permit
438 was acquired without reintegration
440 if ( presto_get_permit(dir) < 0 ) {
442 presto_fulllock(dir);
446 presto_relock_sem(dir);
447 parent = dentry->d_parent;
448 memset(&info, 0, sizeof(info));
449 if (!ISLENTO(presto_c2m(cache)))
450 info.flags = LENTO_FL_KML;
451 info.flags |= LENTO_FL_IGNORE_TIME;
452 error = presto_do_create(fset, parent, dentry, mode, &info);
454 presto_relock_other(dir);
455 presto_put_permit(dir);
460 static int presto_link(struct dentry *old_dentry, struct inode *dir,
461 struct dentry *new_dentry)
464 struct presto_cache *cache, *new_cache;
465 struct presto_file_set *fset, *new_fset;
466 struct dentry *parent = new_dentry->d_parent;
467 struct lento_vfs_context info;
470 error = presto_prep(old_dentry, &cache, &fset);
476 error = presto_check_set_fsdata(new_dentry);
482 error = presto_prep(new_dentry->d_parent, &new_cache, &new_fset);
488 if (fset != new_fset) {
494 if ( presto_get_permit(old_dentry->d_inode) < 0 ) {
496 presto_fulllock(dir);
500 if ( presto_get_permit(dir) < 0 ) {
502 presto_fulllock(dir);
506 presto_relock_sem(dir);
507 parent = new_dentry->d_parent;
509 memset(&info, 0, sizeof(info));
510 if (!ISLENTO(presto_c2m(cache)))
511 info.flags = LENTO_FL_KML;
512 info.flags |= LENTO_FL_IGNORE_TIME;
513 error = presto_do_link(fset, old_dentry, parent,
517 /* XXX for links this is not right */
518 if (cache->cache_filter->o_trops->tr_add_ilookup ) {
520 d = cache->cache_filter->o_trops->tr_add_ilookup
521 (dir->i_sb->s_root, new_dentry, 1);
525 presto_relock_other(dir);
526 presto_put_permit(dir);
527 presto_put_permit(old_dentry->d_inode);
531 static int presto_mkdir(struct inode * dir, struct dentry * dentry, int mode)
534 struct presto_file_set *fset;
535 struct presto_cache *cache;
536 struct dentry *parent = dentry->d_parent;
537 struct lento_vfs_context info;
541 error = presto_check_set_fsdata(dentry);
547 error = presto_prep(dentry->d_parent, &cache, &fset);
555 if ( presto_get_permit(dir) < 0 ) {
557 presto_fulllock(dir);
561 memset(&info, 0, sizeof(info));
562 if (!ISLENTO(presto_c2m(cache)))
563 info.flags = LENTO_FL_KML;
564 info.flags |= LENTO_FL_IGNORE_TIME;
566 presto_relock_sem(dir);
567 parent = dentry->d_parent;
568 error = presto_do_mkdir(fset, parent, dentry, mode, &info);
569 presto_relock_other(dir);
570 presto_put_permit(dir);
576 static int presto_symlink(struct inode *dir, struct dentry *dentry,
580 struct presto_cache *cache;
581 struct presto_file_set *fset;
582 struct dentry *parent = dentry->d_parent;
583 struct lento_vfs_context info;
586 error = presto_check_set_fsdata(dentry);
592 error = presto_prep(dentry->d_parent, &cache, &fset);
599 if ( presto_get_permit(dir) < 0 ) {
601 presto_fulllock(dir);
605 presto_relock_sem(dir);
606 parent = dentry->d_parent;
607 memset(&info, 0, sizeof(info));
608 if (!ISLENTO(presto_c2m(cache)))
609 info.flags = LENTO_FL_KML;
610 info.flags |= LENTO_FL_IGNORE_TIME;
611 error = presto_do_symlink(fset, parent, dentry, name, &info);
612 presto_relock_other(dir);
613 presto_put_permit(dir);
617 int presto_unlink(struct inode *dir, struct dentry *dentry)
620 struct presto_cache *cache;
621 struct presto_file_set *fset;
622 struct dentry *parent = dentry->d_parent;
623 struct lento_vfs_context info;
626 error = presto_check_set_fsdata(dentry);
632 error = presto_prep(dentry->d_parent, &cache, &fset);
639 if ( presto_get_permit(dir) < 0 ) {
641 presto_fulllock(dir);
645 presto_relock_sem(dir);
646 parent = dentry->d_parent;
647 memset(&info, 0, sizeof(info));
648 if (!ISLENTO(presto_c2m(cache)))
649 info.flags = LENTO_FL_KML;
650 info.flags |= LENTO_FL_IGNORE_TIME;
652 error = presto_do_unlink(fset, parent, dentry, &info);
654 presto_relock_other(dir);
655 presto_put_permit(dir);
659 static int presto_rmdir(struct inode *dir, struct dentry *dentry)
662 struct presto_cache *cache;
663 struct presto_file_set *fset;
664 struct dentry *parent = dentry->d_parent;
665 struct lento_vfs_context info;
668 CDEBUG(D_FILE, "prepping presto\n");
669 error = presto_check_set_fsdata(dentry);
676 error = presto_prep(dentry->d_parent, &cache, &fset);
682 CDEBUG(D_FILE, "unlocking\n");
683 /* We need to dget() before the dput in double_unlock, to ensure we
684 * still have dentry references. double_lock doesn't do dget for us.
686 if (d_unhashed(dentry))
688 // double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
689 up(&dentry->d_inode->i_sem);
692 CDEBUG(D_FILE, "getting permit\n");
693 if ( presto_get_permit(parent->d_inode) < 0 ) {
696 down(&dentry->d_inode->i_sem);
697 // double_down(&dir->i_sem, &dentry->d_inode->i_sem);
698 // double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
703 CDEBUG(D_FILE, "locking\n");
706 down(&dentry->d_inode->i_sem);
707 parent = dentry->d_parent;
708 memset(&info, 0, sizeof(info));
709 if (!ISLENTO(presto_c2m(cache)))
710 info.flags = LENTO_FL_KML;
711 info.flags |= LENTO_FL_IGNORE_TIME;
712 error = presto_do_rmdir(fset, parent, dentry, &info);
713 presto_put_permit(parent->d_inode);
719 static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev)
722 struct presto_cache *cache;
723 struct presto_file_set *fset;
724 struct dentry *parent = dentry->d_parent;
725 struct lento_vfs_context info;
727 if (!old_valid_dev(rdev))
731 error = presto_check_set_fsdata(dentry);
737 error = presto_prep(dentry->d_parent, &cache, &fset);
744 if ( presto_get_permit(dir) < 0 ) {
746 presto_fulllock(dir);
750 presto_relock_sem(dir);
751 parent = dentry->d_parent;
752 memset(&info, 0, sizeof(info));
753 if (!ISLENTO(presto_c2m(cache)))
754 info.flags = LENTO_FL_KML;
755 info.flags |= LENTO_FL_IGNORE_TIME;
756 error = presto_do_mknod(fset, parent, dentry, mode, rdev, &info);
757 presto_relock_other(dir);
758 presto_put_permit(dir);
765 // XXX this can be optimized: renamtes across filesets only require
766 // multiple KML records, but can locally be executed normally.
767 int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
768 struct inode *new_dir, struct dentry *new_dentry)
771 struct presto_cache *cache, *new_cache;
772 struct presto_file_set *fset, *new_fset;
773 struct lento_vfs_context info;
774 struct dentry *old_parent = old_dentry->d_parent;
775 struct dentry *new_parent = new_dentry->d_parent;
779 error = presto_prep(old_dentry, &cache, &fset);
784 error = presto_prep(new_parent, &new_cache, &new_fset);
790 if ( fset != new_fset ) {
795 /* We need to do dget before the dput in double_unlock, to ensure we
796 * still have dentry references. double_lock doesn't do dget for us.
799 triple = (S_ISDIR(old_dentry->d_inode->i_mode) && new_dentry->d_inode)?
802 unlock_rename(new_dentry->d_parent, old_dentry->d_parent);
804 if ( presto_get_permit(old_dir) < 0 ) {
808 if ( presto_get_permit(new_dir) < 0 ) {
813 lock_rename(new_dentry->d_parent, old_dentry->d_parent);
814 memset(&info, 0, sizeof(info));
815 if (!ISLENTO(presto_c2m(cache)))
816 info.flags = LENTO_FL_KML;
817 info.flags |= LENTO_FL_IGNORE_TIME;
818 error = do_rename(fset, old_parent, old_dentry, new_parent,
821 presto_put_permit(new_dir);
822 presto_put_permit(old_dir);
826 /* basically this allows the ilookup processes access to all files for
827 * reading, while not making ilookup totally insecure. This could all
828 * go away if we could set the CAP_DAC_READ_SEARCH capability for the client.
830 /* If posix acls are available, the underlying cache fs will export the
831 * appropriate permission function. Thus we do not worry here about ACLs
834 int presto_permission(struct inode *inode, int mask, struct nameidata *nd)
836 unsigned short mode = inode->i_mode;
837 struct presto_cache *cache;
841 if ( presto_can_ilookup() && !(mask & S_IWOTH)) {
842 CDEBUG(D_CACHE, "ilookup on %ld OK\n", inode->i_ino);
847 cache = presto_get_cache(inode);
850 /* we only override the file/dir permission operations */
851 struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);
852 struct inode_operations *diops = filter_c2cdiops(cache->cache_filter);
854 if ( S_ISREG(mode) && fiops && fiops->permission ) {
856 return fiops->permission(inode, mask, nd);
858 if ( S_ISDIR(mode) && diops && diops->permission ) {
860 return diops->permission(inode, mask, nd);
864 /* The cache filesystem doesn't have its own permission function,
865 * so we call the default one.
867 rc = vfs_permission(inode, mask);
874 int presto_ioctl(struct inode *inode, struct file *file,
875 unsigned int cmd, unsigned long arg)
878 struct izo_ioctl_data *data = NULL;
879 struct presto_dentry_data *dd;
884 /* Try the filesystem's ioctl first, and return if it succeeded. */
885 dd = presto_d2d(file->f_dentry);
886 if (dd && dd->dd_fset) {
887 int (*cache_ioctl)(struct inode *, struct file *, unsigned int, unsigned long ) = filter_c2cdfops(dd->dd_fset->fset_cache->cache_filter)->ioctl;
890 rc = cache_ioctl(inode, file, cmd, arg);
897 if (current->euid != 0 && current->euid != izo_authorized_uid) {
902 memset(buf, 0, sizeof(buf));
904 if (izo_ioctl_getdata(buf, buf + 1024, (void *)arg)) {
905 CERROR("intermezzo ioctl: data error\n");
908 data = (struct izo_ioctl_data *)buf;
911 case IZO_IOC_REINTKML: {
914 rc = kml_reint_rec(file, data);
917 cperr = copy_to_user((char *)arg, data, sizeof(*data));
919 CERROR("WARNING: cperr %d\n", cperr);
925 case IZO_IOC_GET_RCVD: {
926 struct izo_rcvd_rec rec;
927 struct presto_file_set *fset;
930 fset = presto_fset(file->f_dentry);
935 rc = izo_rcvd_get(&rec, fset, data->ioc_uuid);
942 return copy_to_user((char *)arg, &rec, sizeof(rec))? -EFAULT : 0;
945 case IZO_IOC_REPSTATUS: {
946 __u64 client_kmlsize;
947 struct izo_rcvd_rec *lr_client;
948 struct izo_rcvd_rec rec;
949 struct presto_file_set *fset;
953 fset = presto_fset(file->f_dentry);
958 minor = presto_f2m(fset);
960 client_kmlsize = data->ioc_kmlsize;
961 lr_client = (struct izo_rcvd_rec *) data->ioc_pbuf1;
963 rc = izo_repstatus(fset, client_kmlsize,
971 return copy_to_user((char *)arg, &rec, sizeof(rec))? -EFAULT : 0;
974 case IZO_IOC_GET_CHANNEL: {
975 struct presto_file_set *fset;
977 fset = presto_fset(file->f_dentry);
983 data->ioc_dev = fset->fset_cache->cache_psdev->uc_minor;
984 CDEBUG(D_PSDEV, "CHANNEL %d\n", data->ioc_dev);
986 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
989 case IZO_IOC_SET_IOCTL_UID:
990 izo_authorized_uid = data->ioc_uid;
994 case IZO_IOC_SET_PID:
995 rc = izo_psdev_setpid(data->ioc_dev);
999 case IZO_IOC_SET_CHANNEL:
1000 rc = izo_psdev_setchannel(file, data->ioc_dev);
1004 case IZO_IOC_GET_KML_SIZE: {
1005 struct presto_file_set *fset;
1008 fset = presto_fset(file->f_dentry);
1014 kmlsize = presto_kml_offset(fset) + fset->fset_kml_logical_off;
1017 return copy_to_user((char *)arg, &kmlsize, sizeof(kmlsize))?-EFAULT : 0;
1020 case IZO_IOC_PURGE_FILE_DATA: {
1021 struct presto_file_set *fset;
1023 fset = presto_fset(file->f_dentry);
1029 rc = izo_purge_file(fset, data->ioc_inlbuf1);
1034 case IZO_IOC_GET_FILEID: {
1035 rc = izo_get_fileid(file, data);
1039 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
1042 case IZO_IOC_SET_FILEID: {
1043 rc = izo_set_fileid(file, data);
1047 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
1050 case IZO_IOC_ADJUST_LML: {
1051 struct lento_vfs_context *info;
1052 info = (struct lento_vfs_context *)data->ioc_inlbuf1;
1053 rc = presto_adjust_lml(file, info);
1058 case IZO_IOC_CONNECT: {
1059 struct presto_file_set *fset;
1062 fset = presto_fset(file->f_dentry);
1067 minor = presto_f2m(fset);
1069 rc = izo_upc_connect(minor, data->ioc_ino,
1070 data->ioc_generation, data->ioc_uuid,
1076 case IZO_IOC_GO_FETCH_KML: {
1077 struct presto_file_set *fset;
1080 fset = presto_fset(file->f_dentry);
1085 minor = presto_f2m(fset);
1087 rc = izo_upc_go_fetch_kml(minor, fset->fset_name,
1088 data->ioc_uuid, data->ioc_kmlsize);
1093 case IZO_IOC_REVOKE_PERMIT:
1094 if (data->ioc_flags)
1095 rc = izo_revoke_permit(file->f_dentry, data->ioc_uuid);
1097 rc = izo_revoke_permit(file->f_dentry, NULL);
1101 case IZO_IOC_CLEAR_FSET:
1102 rc = izo_clear_fsetroot(file->f_dentry);
1106 case IZO_IOC_CLEAR_ALL_FSETS: {
1107 struct presto_file_set *fset;
1109 fset = presto_fset(file->f_dentry);
1115 rc = izo_clear_all_fsetroots(fset->fset_cache);
1120 case IZO_IOC_SET_FSET:
1122 * Mark this dentry as being a fileset root.
1124 rc = presto_set_fsetroot_from_ioc(file->f_dentry,
1131 case IZO_IOC_MARK: {
1132 int res = 0; /* resulting flags - returned to user */
1135 CDEBUG(D_DOWNCALL, "mark inode: %ld, and: %x, or: %x, what %d\n",
1136 file->f_dentry->d_inode->i_ino, data->ioc_and_flag,
1137 data->ioc_or_flag, data->ioc_mark_what);
1139 switch (data->ioc_mark_what) {
1141 error = izo_mark_dentry(file->f_dentry,
1143 data->ioc_or_flag, &res);
1146 error = izo_mark_fset(file->f_dentry,
1148 data->ioc_or_flag, &res);
1151 error = izo_mark_cache(file->f_dentry,
1153 data->ioc_or_flag, &res);
1157 data->ioc_and_flag = 0xffffffff;
1158 data->ioc_or_flag = 0;
1159 error = izo_mark_dentry(file->f_dentry,
1161 data->ioc_or_flag, &res);
1164 error = izo_mark_fset(file->f_dentry,
1166 data->ioc_or_flag, &fflags);
1169 error = izo_mark_cache(file->f_dentry,
1176 data->ioc_and_flag = fflags;
1177 data->ioc_or_flag = cflags;
1188 data->ioc_mark_what = res;
1189 CDEBUG(D_DOWNCALL, "mark inode: %ld, and: %x, or: %x, what %x\n",
1190 file->f_dentry->d_inode->i_ino, data->ioc_and_flag,
1191 data->ioc_or_flag, data->ioc_mark_what);
1194 return copy_to_user((char *)arg, data, sizeof(*data))? -EFAULT : 0;
1197 case IZO_IOC_CLIENT_MAKE_BRANCH: {
1198 struct presto_file_set *fset;
1201 fset = presto_fset(file->f_dentry);
1206 minor = presto_f2m(fset);
1208 rc = izo_upc_client_make_branch(minor, fset->fset_name,
1215 case IZO_IOC_SERVER_MAKE_BRANCH: {
1216 struct presto_file_set *fset;
1219 fset = presto_fset(file->f_dentry);
1224 minor = presto_f2m(fset);
1226 izo_upc_server_make_branch(minor, data->ioc_inlbuf1);
1230 case IZO_IOC_SET_KMLSIZE: {
1231 struct presto_file_set *fset;
1233 struct izo_rcvd_rec rec;
1235 fset = presto_fset(file->f_dentry);
1240 minor = presto_f2m(fset);
1242 rc = izo_upc_set_kmlsize(minor, fset->fset_name, data->ioc_uuid,
1250 rc = izo_rcvd_get(&rec, fset, data->ioc_uuid);
1251 if (rc == -EINVAL) {
1252 /* We don't know anything about this uuid yet; no
1254 memset(&rec, 0, sizeof(rec));
1255 } else if (rc <= 0) {
1256 CERROR("InterMezzo: error reading last_rcvd: %d\n", rc);
1260 rec.lr_remote_offset = data->ioc_kmlsize;
1261 rc = izo_rcvd_write(fset, &rec);
1263 CERROR("InterMezzo: error writing last_rcvd: %d\n", rc);
1270 case IZO_IOC_BRANCH_UNDO: {
1271 struct presto_file_set *fset;
1274 fset = presto_fset(file->f_dentry);
1279 minor = presto_f2m(fset);
1281 rc = izo_upc_branch_undo(minor, fset->fset_name,
1286 case IZO_IOC_BRANCH_REDO: {
1287 struct presto_file_set *fset;
1290 fset = presto_fset(file->f_dentry);
1295 minor = presto_f2m(fset);
1297 rc = izo_upc_branch_redo(minor, fset->fset_name,
1312 struct file_operations presto_dir_fops = {
1313 .ioctl = presto_ioctl
1316 struct inode_operations presto_dir_iops = {
1317 .create = presto_create,
1318 .lookup = presto_lookup,
1319 .link = presto_link,
1320 .unlink = presto_unlink,
1321 .symlink = presto_symlink,
1322 .mkdir = presto_mkdir,
1323 .rmdir = presto_rmdir,
1324 .mknod = presto_mknod,
1325 .rename = presto_rename,
1326 .permission = presto_permission,
1327 .setattr = presto_setattr,
1328 #ifdef CONFIG_FS_EXT_ATTR
1329 .set_ext_attr = presto_set_ext_attr,