patch-2.4.20 linux-2.4.20/fs/intermezzo/vfs.c

Next file: linux-2.4.20/fs/iobuf.c
Previous file: linux-2.4.20/fs/intermezzo/upcall.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/fs/intermezzo/vfs.c linux-2.4.20/fs/intermezzo/vfs.c
@@ -1,4 +1,25 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ *  Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ *  Copyright (C) 2000 Stelias Computing, Inc.
+ *  Copyright (C) 2000 Red Hat, Inc.
+ *
+ *   This file is part of InterMezzo, http://www.inter-mezzo.org.
+ *
+ *   InterMezzo is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License as published by the Free Software Foundation.
+ *
+ *   InterMezzo is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with InterMezzo; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
  * vfs.c
  *
  * This file implements kernel downcalls from lento.
@@ -48,20 +69,50 @@
 #include <linux/blk.h>
 
 #include <linux/intermezzo_fs.h>
-#include <linux/intermezzo_upcall.h>
 #include <linux/intermezzo_psdev.h>
-#include <linux/intermezzo_kml.h>
 
 #ifdef CONFIG_FS_EXT_ATTR
-#include <linux/ext_attr.h>
+# include <linux/ext_attr.h>
 
-#ifdef CONFIG_FS_POSIX_ACL
-#include <linux/posix_acl.h>
-#endif
+# ifdef CONFIG_FS_POSIX_ACL
+#  include <linux/posix_acl.h>
+# endif
 #endif
 
 extern struct inode_operations presto_sym_iops;
 
+/* Write the last_rcvd values to the last_rcvd file.  We don't know what the
+ * UUID or last_ctime values are, so we have to read from the file first
+ * (sigh). 
+ * exported for branch_reinter in kml_reint.c*/
+int presto_write_last_rcvd(struct rec_info *recinfo,
+                           struct presto_file_set *fset,
+                           struct lento_vfs_context *info)
+{
+        int rc;
+        struct izo_rcvd_rec rcvd_rec;
+
+        ENTRY;
+
+        memset(&rcvd_rec, 0, sizeof(rcvd_rec));
+        memcpy(rcvd_rec.lr_uuid, info->uuid, sizeof(rcvd_rec.lr_uuid));
+        rcvd_rec.lr_remote_recno = HTON__u64(info->recno);
+        rcvd_rec.lr_remote_offset = HTON__u64(info->kml_offset);
+        rcvd_rec.lr_local_recno = HTON__u64(recinfo->recno);
+        rcvd_rec.lr_local_offset = HTON__u64(recinfo->offset + recinfo->size);
+
+        rc = izo_rcvd_write(fset, &rcvd_rec);
+        if (rc < 0) {
+                /* izo_rcvd_write returns negative errors and non-negative
+                 * offsets */
+                CERROR("InterMezzo: izo_rcvd_write failed: %d\n", rc);
+                EXIT;
+                return rc;
+        }
+        EXIT;
+        return 0;
+}
+
 /*
  * It's inline, so penalty for filesystems that don't use sticky bit is
  * minimal.
@@ -130,13 +181,13 @@
                                      unsigned long value)
 {
         int minor = presto_f2m(fset);
-        int errorval = upc_comms[minor].uc_errorval;
-        kdev_t dev = fset->fset_mtpt->d_inode->i_dev;
+        int errorval = izo_channels[minor].uc_errorval;
+        kdev_t dev = fset->fset_dentry->d_inode->i_dev;
 
         if (errorval && errorval == (long)value && !is_read_only(dev)) {
                 CDEBUG(D_SUPER, "setting device %s read only\n", kdevname(dev));
                 BLKDEV_FAIL(dev, 1);
-                upc_comms[minor].uc_errorval = -dev;
+                izo_channels[minor].uc_errorval = -dev;
         }
 }
 #else
@@ -144,20 +195,22 @@
 #endif
 
 
-static inline int presto_do_kml(struct lento_vfs_context *info, struct inode* inode)
+static inline int presto_do_kml(struct lento_vfs_context *info,
+                                struct dentry *dentry)
 {
-        if ( ! (info->flags & LENTO_FL_KML) ) 
+        if ( ! (info->flags & LENTO_FL_KML) )
                 return 0;
-        if ( inode->i_gid == presto_excluded_gid ) 
+        if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
                 return 0;
         return 1;
 }
 
-static inline int presto_do_expect(struct lento_vfs_context *info, struct inode *inode)
+static inline int presto_do_rcvd(struct lento_vfs_context *info,
+                                 struct dentry *dentry)
 {
         if ( ! (info->flags & LENTO_FL_EXPECT) ) 
                 return 0;
-        if ( inode->i_gid == presto_excluded_gid ) 
+        if ( presto_chk(dentry, PRESTO_DONT_JOURNAL) )
                 return 0;
         return 1;
 }
@@ -166,12 +219,15 @@
 /* XXX fixme: this should not fail, all these dentries are in memory
    when _we_ call this */
 int presto_settime(struct presto_file_set *fset, 
-                   struct dentry *dentry, 
+                   struct dentry *newobj,
+                   struct dentry *parent,
+                   struct dentry *target,
                    struct lento_vfs_context *ctx, 
                    int valid)
 {
-        int error; 
-        struct inode *inode = dentry->d_inode;
+        int error = 0;
+        struct dentry *dentry;
+        struct inode *inode;
         struct inode_operations *iops;
         struct iattr iattr;
 
@@ -180,39 +236,128 @@
                 EXIT;
                 return 0;
         }
+
         iattr.ia_ctime = ctx->updated_time;
         iattr.ia_mtime = ctx->updated_time;
         iattr.ia_valid = valid;
 
-        error = -EROFS;
-        if (IS_RDONLY(inode)) {
-                EXIT;
-                return -EROFS;
+        while (1) {
+                if (parent && ctx->flags & LENTO_FL_TOUCH_PARENT) {
+                        dentry = parent;
+                        parent = NULL;
+                } else if (newobj && ctx->flags & LENTO_FL_TOUCH_NEWOBJ) {
+                        dentry = newobj;
+                        newobj = NULL;
+                } else if (target) {
+                        dentry = target;
+                        target = NULL;
+                } else
+                        break;
+
+                inode = dentry->d_inode;
+
+                error = -EROFS;
+                if (IS_RDONLY(inode)) {
+                        EXIT;
+                        return -EROFS;
+                }
+
+                if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+                        EXIT;
+                        return -EPERM;
+                }
+
+                error = -EPERM;
+                iops = filter_c2cdiops(fset->fset_cache->cache_filter); 
+                if (!iops) { 
+                        EXIT;
+                        return error;
+                }
+
+                if (iops->setattr != NULL)
+                        error = iops->setattr(dentry, &iattr);
+                else {
+                        error = 0;
+                        inode_setattr(dentry->d_inode, &iattr);
+                }
         }
+        EXIT;
+        return error;
+}
 
-        if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
+void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb)
+{
+        rb->rb_mode = (__u32)inode->i_mode;
+        rb->rb_rdev = (__u32)inode->i_rdev;
+        rb->rb_uid  = (__u64)inode->i_uid;
+        rb->rb_gid  = (__u64)inode->i_gid;
+}
+
+
+int presto_do_close(struct presto_file_set *fset, struct file *file)
+{
+        struct rec_info rec;
+        int rc = -ENOSPC; 
+        void *handle;
+        struct inode *inode = file->f_dentry->d_inode;
+        struct presto_file_data *fdata = 
+                (struct presto_file_data *)file->private_data;
+
+        ENTRY;
+        presto_getversion(&fdata->fd_info.remote_version, inode);
+
+        rc = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
+        if (rc) { 
                 EXIT;
-                return -EPERM;
+                return rc;
         }
 
-        error = -EPERM;
-        iops = filter_c2cdiops(fset->fset_cache->cache_filter); 
-        if (!iops) {
-                EXIT;
-                return error;
+        handle = presto_trans_start(fset, file->f_dentry->d_inode, 
+                                            KML_OPCODE_RELEASE);
+        if ( IS_ERR(handle) ) {
+                CERROR("presto_release: no space for transaction\n");
+                return rc;
         }
 
-        if (iops->setattr != NULL)
-                error = iops->setattr(dentry, &iattr);
-        else {
-		error = 0;
-                inode_setattr(dentry->d_inode, &iattr);
-	}
+        if (fdata->fd_info.flags & LENTO_FL_KML) 
+                rc = presto_journal_close(&rec, fset, file, file->f_dentry,
+                                          &fdata->fd_version, 
+                                          &fdata->fd_info.remote_version);
+        if (rc) { 
+                CERROR("presto_close: cannot journal close\n");
+                goto out;
+        }
+
+        if (fdata->fd_info.flags & LENTO_FL_EXPECT) 
+                rc = presto_write_last_rcvd(&rec, fset, &fdata->fd_info);
+
+        if (rc) { 
+                CERROR("presto_close: cannot journal last_rcvd\n");
+                goto out;
+        }
+        presto_trans_commit(fset, handle); 
+        
+        /* cancel the LML record */ 
+        handle = presto_trans_start(fset, inode, KML_OPCODE_WRITE);
+        if ( IS_ERR(handle) ) {
+                CERROR("presto_release: no space for clear\n");
+                return -ENOSPC;
+        }
+
+        rc = presto_clear_lml_close(fset, fdata->fd_lml_offset); 
+        if (rc < 0 ) { 
+                CERROR("presto_close: cannot journal close\n");
+                goto out;
+        }
+        presto_truncate_lml(fset);
+
+ out:
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+        presto_trans_commit(fset, handle); 
         EXIT;
-        return error;
+        return rc;
 }
 
-
 int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,
                       struct iattr *iattr, struct lento_vfs_context *info)
 {
@@ -221,8 +366,9 @@
         struct inode_operations *iops;
         int error;
         struct presto_version old_ver, new_ver;
+        struct izo_rollback_data rb;
         void *handle;
-	off_t old_size=inode->i_size;
+        loff_t old_size=inode->i_size;
 
         ENTRY;
         error = -EROFS;
@@ -237,33 +383,34 @@
         }
 
         presto_getversion(&old_ver, dentry->d_inode);
+        izo_get_rollback_data(dentry->d_inode, &rb);
         error = -EPERM;
         iops = filter_c2cdiops(fset->fset_cache->cache_filter); 
-        if (!iops &&
-            !iops->setattr) {
+
+        error = presto_reserve_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
+        if (error) {
                 EXIT;
                 return error;
         }
 
-	error = presto_reserve_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
-	if (error) {
-		EXIT;
-		return error;
-	}
-
-	if  (iattr->ia_valid & ATTR_SIZE) { 
-		handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_TRUNC);
-	} else {
-		handle = presto_trans_start(fset, dentry->d_inode, PRESTO_OP_SETATTR);
-	}
+        if  (iattr->ia_valid & ATTR_SIZE) {
+                if (izo_mark_dentry(dentry, ~PRESTO_DATA, 0, NULL) != 0)
+                        CERROR("izo_mark_dentry(inode %ld, ~PRESTO_DATA) "
+                               "failed\n", dentry->d_inode->i_ino);
+                handle = presto_trans_start(fset, dentry->d_inode,
+                                            KML_OPCODE_TRUNC);
+        } else {
+                handle = presto_trans_start(fset, dentry->d_inode,
+                                            KML_OPCODE_SETATTR);
+        }
 
         if ( IS_ERR(handle) ) {
-                printk("presto_do_setattr: no space for transaction\n");
-		presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
+                CERROR("presto_do_setattr: no space for transaction\n");
+                presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
                 return -ENOSPC;
         }
 
-        if (dentry->d_inode && iops->setattr) {
+        if (dentry->d_inode && iops && iops->setattr) {
                 error = iops->setattr(dentry, iattr);
         } else {
                 error = inode_change_ok(dentry->d_inode, iattr);
@@ -271,41 +418,43 @@
                         inode_setattr(inode, iattr);
         }
 
-	if (!error && (iattr->ia_valid & ATTR_SIZE))
-		vmtruncate(inode, iattr->ia_size);
+        if (!error && (iattr->ia_valid & ATTR_SIZE))
+                vmtruncate(inode, iattr->ia_size);
 
         if (error) {
                 EXIT;
                 goto exit;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x10);
 
-        if ( presto_do_kml(info, dentry->d_inode) ) {
+        if ( presto_do_kml(info, dentry) ) {
                 if ((iattr->ia_valid & ATTR_SIZE) && (old_size != inode->i_size)) {
-                	struct file file;
-                	/* Journal a close whenever we see a potential truncate
-                 	* At the receiving end, lento should explicitly remove
-                 	* ATTR_SIZE from the list of valid attributes */
-                	presto_getversion(&new_ver, inode);
-                	file.private_data = NULL;
-                	file.f_dentry = dentry;
-                	error=presto_journal_close(&rec, fset, &file, dentry, &new_ver);
-            	}
+                        struct file file;
+                        /* Journal a close whenever we see a potential truncate
+                        * At the receiving end, lento should explicitly remove
+                        * ATTR_SIZE from the list of valid attributes */
+                        presto_getversion(&new_ver, inode);
+                        file.private_data = NULL;
+                        file.f_dentry = dentry;
+                        error = presto_journal_close(&rec, fset, &file, dentry,
+                                                     &old_ver, &new_ver);
+                }
 
-		if (!error)
-                	error = presto_journal_setattr(&rec, fset, dentry, &old_ver, iattr);
+                if (!error)
+                        error = presto_journal_setattr(&rec, fset, dentry,
+                                                       &old_ver, &rb, iattr);
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x20);
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETATTR | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETATTR | 0x30);
 
         EXIT;
 exit:
-	presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
+        presto_release_space(fset->fset_cache, 2*PRESTO_REQHIGH); 
         presto_trans_commit(fset, handle);
         return error;
 }
@@ -342,7 +491,7 @@
         fset = presto_fset(dentry);
         error = -EINVAL;
         if ( !fset ) {
-                printk("No fileset!\n");
+                CERROR("No fileset!\n");
                 EXIT;
                 goto exit_lock;
         }
@@ -378,6 +527,14 @@
 
         error = presto_do_setattr(fset, dentry, iattr, info);
 
+        if (info->flags & LENTO_FL_SET_DDFILEID) {
+                struct presto_dentry_data *dd = presto_d2d(dentry);
+                if (dd) {
+                        dd->remote_ino = info->remote_ino;
+                        dd->remote_generation = info->remote_generation;
+                }
+        }
+
 #ifdef CONFIG_FS_POSIX_ACL
         /* restore the inode_operations if we changed them*/
         if (iattr->ia_valid & ATTR_MODE) 
@@ -408,12 +565,12 @@
         mode |= S_IFREG;
 
         down(&dir->d_inode->i_zombie);
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
-	if (error) {
-		EXIT;
-        	up(&dir->d_inode->i_zombie);
-		return error;
-	}
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
+        if (error) {
+                EXIT;
+                up(&dir->d_inode->i_zombie);
+                return error;
+        }
 
         error = may_create(dir->d_inode, dentry);
         if (error) {
@@ -429,13 +586,13 @@
         }
 
         presto_getversion(&tgt_dir_ver, dir->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_CREATE);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_CREATE);
         if ( IS_ERR(handle) ) {
                 EXIT;
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
-                printk("presto_do_create: no space for transaction\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+                CERROR("presto_do_create: no space for transaction\n");
                 error=-ENOSPC;
-		goto exit_pre_lock;
+                goto exit_pre_lock;
         }
         DQUOT_INIT(dir->d_inode);
         lock_kernel();
@@ -445,21 +602,11 @@
                 goto exit_lock;
         }
 
-        if (dentry->d_inode && 
-            dentry->d_inode->i_gid != presto_excluded_gid) {
+        if (dentry->d_inode) {
                 struct presto_cache *cache = fset->fset_cache;
                 /* was this already done? */
-                if ( !filter_c2cfiops(cache->cache_filter) )
-                        filter_setup_file_ops(cache->cache_filter, 
-                                              dentry->d_inode,
-                                              &presto_file_iops,
-                                              &presto_file_fops);
-
-                /* make the new inode ours */
-                dentry->d_inode->i_op = 
-                        filter_c2ufiops(cache->cache_filter);
-                dentry->d_inode->i_fop = 
-                        filter_c2uffops(cache->cache_filter);
+                presto_set_ops(dentry->d_inode, cache->cache_filter);
+
                 filter_setup_dentry_ops(cache->cache_filter, 
                                         dentry->d_op, 
                                         &presto_dentry_ops);
@@ -473,37 +620,44 @@
                 }
         }
 
-        error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);
-        if (error) { 
-                EXIT;
-                goto exit_lock;
-        }
-        error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);
+        info->flags |= LENTO_FL_TOUCH_PARENT;
+        error = presto_settime(fset, NULL, dir, dentry,
+                               info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
                 goto exit_lock;
         }
 
+        presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x10);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x10);
-        presto_getversion(&new_file_ver, dentry->d_inode);
-        if ( presto_do_kml(info, dentry->d_inode) )
+        if ( presto_do_kml(info, dentry) ) { 
+                presto_getversion(&new_file_ver, dentry->d_inode);
                 error = presto_journal_create(&rec, fset, dentry, &tgt_dir_ver,
-                                              &new_file_ver,
+                                              &new_file_ver, 
                                               dentry->d_inode->i_mode);
+        }
+
+        presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x20);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) )
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_CREATE | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_CREATE | 0x30);
+
+        /* add inode dentry */
+        if (fset->fset_cache->cache_filter->o_trops->tr_add_ilookup ) { 
+                struct dentry *d;
+                d = fset->fset_cache->cache_filter->o_trops->tr_add_ilookup
+                        (dir->d_inode->i_sb->s_root, dentry);
+        }
+
         EXIT;
 
  exit_lock:
         unlock_kernel();
         presto_trans_commit(fset, handle);
  exit_pre_lock:
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
         up(&dir->d_inode->i_zombie);
         return error;
 }
@@ -551,9 +705,9 @@
         if (path_init(pathname,  LOOKUP_PARENT, &nd))
                 error = path_walk(pathname, &nd);
         if (error) {
-		EXIT;
+                EXIT;
                 goto exit;
-	}
+        }
         dentry = lookup_create(&nd, 0);
         error = PTR_ERR(dentry);
         if (IS_ERR(dentry)) {
@@ -564,7 +718,7 @@
         fset = presto_fset(dentry);
         error = -EINVAL;
         if ( !fset ) {
-                printk("No fileset!\n");
+                CERROR("No fileset!\n");
                 EXIT;
                 goto exit_lock;
         }
@@ -575,7 +729,7 @@
 
  exit_lock:
         path_release (&nd);
-	dput(dentry); 
+        dput(dentry); 
         up(&dentry->d_parent->d_inode->i_sem);
         putname(pathname);
 exit:
@@ -595,12 +749,12 @@
         void *handle;
 
         down(&dir->d_inode->i_zombie);
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
-	if (error) {
-		EXIT;
-        	up(&dir->d_inode->i_zombie);
-		return error;
-	}
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
+        if (error) {
+                EXIT;
+                up(&dir->d_inode->i_zombie);
+                return error;
+        }
         error = -ENOENT;
         inode = old_dentry->d_inode;
         if (!inode)
@@ -631,10 +785,10 @@
 
 
         presto_getversion(&tgt_dir_ver, dir->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_LINK);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_LINK);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
-                printk("presto_do_link: no space for transaction\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+                CERROR("presto_do_link: no space for transaction\n");
                 return -ENOSPC;
         }
 
@@ -647,32 +801,37 @@
                 goto exit_lock;
         }
 
-        error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);
-        if (error) { 
-                EXIT;
-                goto exit_lock;
-        }
-        error = presto_settime(fset, new_dentry, info, ATTR_CTIME);
+        /* link dd data to that of existing dentry */
+        old_dentry->d_op->d_release(new_dentry); 
+        if (!presto_d2d(old_dentry)) 
+                BUG();
+        presto_d2d(old_dentry)->dd_count++;
+
+        new_dentry->d_fsdata = presto_d2d(old_dentry);
+
+        info->flags |= LENTO_FL_TOUCH_PARENT;
+        error = presto_settime(fset, NULL, dir, new_dentry,
+                               info, ATTR_CTIME);
         if (error) { 
                 EXIT;
                 goto exit_lock;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x10);
         presto_getversion(&new_link_ver, new_dentry->d_inode);
-        if ( presto_do_kml(info, old_dentry->d_inode) )
+        if ( presto_do_kml(info, old_dentry) )
                 error = presto_journal_link(&rec, fset, old_dentry, new_dentry,
                                             &tgt_dir_ver, &new_link_ver);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x20);
-        if ( presto_do_expect(info, old_dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x20);
+        if ( presto_do_rcvd(info, old_dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_LINK | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_LINK | 0x30);
         EXIT;
         presto_trans_commit(fset, handle);
 exit_lock:
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
         up(&dir->d_inode->i_zombie);
         return error;
 }
@@ -714,7 +873,7 @@
                         fset = presto_fset(new_dentry);
                         error = -EINVAL;
                         if ( !fset ) {
-                                printk("No fileset!\n");
+                                CERROR("No fileset!\n");
                                 EXIT;
                                 goto out2;
                         }
@@ -736,17 +895,17 @@
         return error;
 }
 
-
 int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,
                      struct dentry *dentry, struct lento_vfs_context *info)
 {
         struct rec_info rec;
-        int error;
         struct inode_operations *iops;
         struct presto_version tgt_dir_ver, old_file_ver;
+        struct izo_rollback_data rb;
         void *handle;
-        int do_kml = 0, do_expect =0;
-	int linkno = 0;
+        int do_kml = 0, do_rcvd = 0, linkno = 0, error, old_targetlen = 0;
+        char *old_target = NULL;
+
         ENTRY;
         down(&dir->d_inode->i_zombie);
         error = may_delete(dir->d_inode, dentry, 0);
@@ -764,19 +923,34 @@
                 return error;
         }
 
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW); 
-	if (error) {
-		EXIT;
-        	up(&dir->d_inode->i_zombie);
-		return error;
-	}
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQLOW); 
+        if (error) {
+                EXIT;
+                up(&dir->d_inode->i_zombie);
+                return error;
+        }
+
+
+        if (presto_d2d(dentry)) { 
+                struct presto_dentry_data *dd = presto_d2d(dentry); 
+                struct dentry *de = dd->dd_inodentry;
+                if (de && dentry->d_inode->i_nlink == 1) { 
+                        dd->dd_count--;
+                        dd->dd_inodentry = NULL; 
+                        de->d_fsdata = NULL; 
+                        atomic_dec(&de->d_inode->i_count); 
+                        de->d_inode = NULL;
+                        dput(de); 
+                }
+        }
 
         presto_getversion(&tgt_dir_ver, dir->d_inode);
         presto_getversion(&old_file_ver, dentry->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_UNLINK);
+        izo_get_rollback_data(dentry->d_inode, &rb);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_UNLINK);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQLOW); 
-                printk("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQLOW); 
+                CERROR("ERROR: presto_do_unlink: no space for transaction. Tell Peter.\n");
                 up(&dir->d_inode->i_zombie);
                 return -ENOSPC;
         }
@@ -785,12 +959,45 @@
                 error = -EBUSY;
         else {
                 lock_kernel();
-		linkno = dentry->d_inode->i_nlink;
-		if (linkno > 1) {
-			dget(dentry);
-		}
-                do_kml = presto_do_kml(info, dir->d_inode);
-                do_expect = presto_do_expect(info, dir->d_inode);
+                linkno = dentry->d_inode->i_nlink;
+                if (linkno > 1) {
+                        dget(dentry);
+                }
+
+                if (S_ISLNK(dentry->d_inode->i_mode)) {
+                        mm_segment_t old_fs;
+                        struct inode_operations *riops;
+                        riops = filter_c2csiops(fset->fset_cache->cache_filter);
+
+                        PRESTO_ALLOC(old_target, PATH_MAX);
+                        if (old_target == NULL) {
+                                error = -ENOMEM;
+                                EXIT;
+                                goto exit;
+                        }
+
+                        old_fs = get_fs();
+                        set_fs(get_ds());
+
+                        if (riops->readlink == NULL)
+                                CERROR("InterMezzo %s: no readlink iops.\n",
+                                       __FUNCTION__);
+                        else
+                                old_targetlen =
+                                        riops->readlink(dentry, old_target,
+                                                        PATH_MAX);
+                        if (old_targetlen < 0) {
+                                CERROR("InterMezzo: readlink failed: %ld\n",
+                                       PTR_ERR(old_target));
+                                PRESTO_FREE(old_target, PATH_MAX);
+                                old_target = NULL;
+                                old_targetlen = 0;
+                        }
+                        set_fs(old_fs);
+                }
+
+                do_kml = presto_do_kml(info, dir);
+                do_rcvd = presto_do_rcvd(info, dir);
                 error = iops->unlink(dir->d_inode, dentry);
                 unlock_kernel();
                 if (!error)
@@ -798,7 +1005,9 @@
         }
 
         if (linkno > 1) { 
-                error = presto_settime(fset, dentry, info, ATTR_CTIME);
+                /* FIXME: Combine this with the next call? */
+                error = presto_settime(fset, NULL, NULL, dentry,
+                                       info, ATTR_CTIME);
                 dput(dentry); 
                 if (error) { 
                         EXIT;
@@ -806,7 +1015,8 @@
                 }
         }
 
-        error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);
+        error = presto_settime(fset, NULL, NULL, dir,
+                               info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
                 goto exit;
@@ -818,22 +1028,22 @@
                 goto exit;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x10);
-        if ( do_kml ) { 
+        presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x10);
+        if ( do_kml )
                 error = presto_journal_unlink(&rec, fset, dir, &tgt_dir_ver,
-                                              &old_file_ver,
-                                              dentry->d_name.len,
-                                              dentry->d_name.name);
-	}
-        presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x20);
-        if ( do_expect ) { 
+                                              &old_file_ver, &rb, dentry,
+                                              old_target, old_targetlen);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x20);
+        if ( do_rcvd ) { 
                 error = presto_write_last_rcvd(&rec, fset, info);
-	}
-        presto_debug_fail_blkdev(fset, PRESTO_OP_UNLINK | 0x30);
+        }
+        presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x30);
         EXIT;
 exit:
-	presto_release_space(fset->fset_cache, PRESTO_REQLOW); 
+        presto_release_space(fset->fset_cache, PRESTO_REQLOW); 
         presto_trans_commit(fset, handle);
+        if (old_target != NULL)
+                PRESTO_FREE(old_target, PATH_MAX);
         return error;
 }
 
@@ -866,7 +1076,7 @@
                 fset = presto_fset(dentry);
                 error = -EINVAL;
                 if ( !fset ) {
-                        printk("No fileset!\n");
+                        CERROR("No fileset!\n");
                         EXIT;
                         goto exit2;
                 }
@@ -904,13 +1114,13 @@
 
         ENTRY;
         down(&dir->d_inode->i_zombie);
-	/* record + max path len + space to free */ 
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
-	if (error) {
-		EXIT;
-        	up(&dir->d_inode->i_zombie);
-		return error;
-	}
+        /* record + max path len + space to free */ 
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+        if (error) {
+                EXIT;
+                up(&dir->d_inode->i_zombie);
+                return error;
+        }
 
         error = may_create(dir->d_inode, dentry);
         if (error) {
@@ -926,11 +1136,12 @@
         }
 
         presto_getversion(&tgt_dir_ver, dir->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_SYMLINK);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_SYMLINK);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
-                printk("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n"); 
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+                CERROR("ERROR: presto_do_symlink: no space for transaction. Tell Peter.\n"); 
                 EXIT;
+                up(&dir->d_inode->i_zombie);
                 return -ENOSPC;
         }
         DQUOT_INIT(dir->d_inode);
@@ -941,19 +1152,11 @@
                 goto exit;
         }
 
-        if (dentry->d_inode &&
-            dentry->d_inode->i_gid != presto_excluded_gid) {
+        if (dentry->d_inode) {
                 struct presto_cache *cache = fset->fset_cache;
                 
-                /* was this already done? */
-                if ( !filter_c2csiops(cache->cache_filter) )
-                        filter_setup_symlink_ops(cache->cache_filter, 
-                                                 dentry->d_inode,
-                                                 &presto_sym_iops,
-                                                 NULL);
+                presto_set_ops(dentry->d_inode, cache->cache_filter);
 
-                /* make the new inode ours */
-                dentry->d_inode->i_op = filter_c2usiops(cache->cache_filter);
                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, 
                                         &presto_dentry_ops);
                 dentry->d_op = filter_c2udops(cache->cache_filter);
@@ -965,34 +1168,31 @@
                 }
         }
 
-        error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);
-        if (error) { 
-                EXIT;
-                goto exit;
-        }
-        error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);
+        info->flags |= LENTO_FL_TOUCH_PARENT;
+        error = presto_settime(fset, NULL, dir, dentry,
+                               info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
                 goto exit;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x10);
         presto_getversion(&new_link_ver, dentry->d_inode);
-        if ( presto_do_kml(info, dentry->d_inode) )
+        if ( presto_do_kml(info, dentry) )
                 error = presto_journal_symlink(&rec, fset, dentry, oldname,
                                                &tgt_dir_ver, &new_link_ver);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x20);
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SYMLINK | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SYMLINK | 0x30);
         EXIT;
 exit:
         unlock_kernel();
         presto_trans_commit(fset, handle);
  exit_lock:
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
         up(&dir->d_inode->i_zombie);
         return error;
 }
@@ -1033,7 +1233,7 @@
         dentry = lookup_create(&nd, 0);
         error = PTR_ERR(dentry);
         if (IS_ERR(dentry)) {
-        	path_release(&nd);
+                path_release(&nd);
                 EXIT;
                 goto exit_to;
         }
@@ -1041,8 +1241,8 @@
         fset = presto_fset(dentry);
         error = -EINVAL;
         if ( !fset ) {
-                printk("No fileset!\n");
-        	path_release(&nd);
+                CERROR("No fileset!\n");
+                path_release(&nd);
                 EXIT;
                 goto exit_lock;
         }
@@ -1073,11 +1273,12 @@
 
         ENTRY;
         down(&dir->d_inode->i_zombie);
-	/* one journal record + directory block + room for removals*/ 
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
-	if (error) { 
+
+        /* one journal record + directory block + room for removals*/ 
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+        if (error) { 
                 EXIT;
-        	up(&dir->d_inode->i_zombie);
+                up(&dir->d_inode->i_zombie);
                 return error;
         }
 
@@ -1095,10 +1296,10 @@
 
         error = -ENOSPC;
         presto_getversion(&tgt_dir_ver, dir->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKDIR);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKDIR);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
-                printk("presto_do_mkdir: no space for transaction\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+                CERROR("presto_do_mkdir: no space for transaction\n");
                 goto exit_lock;
         }
 
@@ -1111,11 +1312,11 @@
                 goto exit;
         }
 
-        if ( dentry->d_inode && !error && 
-             dentry->d_inode->i_gid != presto_excluded_gid) {
+        if ( dentry->d_inode && !error) {
                 struct presto_cache *cache = fset->fset_cache;
-                /* make it ours */
-                dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
+
+                presto_set_ops(dentry->d_inode, cache->cache_filter);
+
                 filter_setup_dentry_ops(cache->cache_filter, 
                                         dentry->d_op, 
                                         &presto_dentry_ops);
@@ -1128,35 +1329,32 @@
                 }
         }
 
-        error = presto_settime(fset, dir, info, ATTR_CTIME | ATTR_MTIME);
-        if (error) { 
-                EXIT;
-                goto exit;
-        }
-        error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);
+        info->flags |= LENTO_FL_TOUCH_PARENT;
+        error = presto_settime(fset, NULL, dir, dentry,
+                             info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
                 goto exit;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x10);
         presto_getversion(&new_dir_ver, dentry->d_inode);
-        if ( presto_do_kml(info, dentry->d_inode) )
+        if ( presto_do_kml(info, dir) )
                 error = presto_journal_mkdir(&rec, fset, dentry, &tgt_dir_ver,
-                                             &new_dir_ver,
+                                             &new_dir_ver, 
                                              dentry->d_inode->i_mode);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x20);
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKDIR | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKDIR | 0x30);
         EXIT;
 exit:
         unlock_kernel();
         presto_trans_commit(fset, handle);
  exit_lock:
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH + 4096); 
         up(&dir->d_inode->i_zombie);
         return error;
 }
@@ -1193,8 +1391,8 @@
         if (!IS_ERR(dentry)) {
                 fset = presto_fset(dentry);
                 error = -EINVAL;
-                if ( !fset ) {
-                        printk("No fileset!\n");
+                if (!fset) {
+                        CERROR("No fileset!\n");
                         EXIT;
                         goto out_dput;
                 }
@@ -1202,14 +1400,14 @@
                 error = presto_do_mkdir(fset, nd.dentry, dentry, 
                                         mode & S_IALLUGO, info);
 out_dput:
-		dput(dentry);
+                dput(dentry);
         }
-	up(&nd.dentry->d_inode->i_sem);
-	path_release(&nd);
+        up(&nd.dentry->d_inode->i_sem);
+        path_release(&nd);
 out_name:
         EXIT;
         putname(pathname);
-	CDEBUG(D_PIOCTL, "error: %d\n", error);
+        CDEBUG(D_PIOCTL, "error: %d\n", error);
         return error;
 }
 
@@ -1232,10 +1430,11 @@
         struct rec_info rec;
         int error;
         struct presto_version tgt_dir_ver, old_dir_ver;
+        struct izo_rollback_data rb;
         struct inode_operations *iops;
         void *handle;
-        int do_kml, do_expect;
-	int size;
+        int do_kml, do_rcvd;
+        int size;
 
         ENTRY;
         error = may_delete(dir->d_inode, dentry, 1);
@@ -1249,64 +1448,67 @@
                 return error;
         }
 
-	size = PRESTO_REQHIGH - dentry->d_inode->i_size; 
-	error = presto_reserve_space(fset->fset_cache, size); 
-	if (error) { 
-		EXIT;
-		return error;
-	}
+        size = PRESTO_REQHIGH - dentry->d_inode->i_size; 
+        error = presto_reserve_space(fset->fset_cache, size); 
+        if (error) { 
+                EXIT;
+                return error;
+        }
 
         presto_getversion(&tgt_dir_ver, dir->d_inode);
         presto_getversion(&old_dir_ver, dentry->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_RMDIR);
+        izo_get_rollback_data(dentry->d_inode, &rb);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_RMDIR);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, size); 
-                printk("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");
+                presto_release_space(fset->fset_cache, size); 
+                CERROR("ERROR: presto_do_rmdir: no space for transaction. Tell Peter.\n");
                 return -ENOSPC;
         }
 
         DQUOT_INIT(dir->d_inode);
 
-        do_kml = presto_do_kml(info, dir->d_inode);
-        do_expect = presto_do_expect(info, dir->d_inode);
+        do_kml = presto_do_kml(info, dir);
+        do_rcvd = presto_do_rcvd(info, dir);
 
         double_down(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
         d_unhash(dentry);
         if (IS_DEADDIR(dir->d_inode))
                 error = -ENOENT;
-        else if (d_mountpoint(dentry))
+        else if (d_mountpoint(dentry)) {
+                CERROR("foo: d_mountpoint(dentry): ino %ld\n",
+                       dentry->d_inode->i_ino);
                 error = -EBUSY;
-        else {
+        } else {
                 lock_kernel();
                 error = iops->rmdir(dir->d_inode, dentry);
                 unlock_kernel();
                 if (!error) {
                         dentry->d_inode->i_flags |= S_DEAD;
-			error = presto_settime(fset, dir, info, 
-					       ATTR_CTIME | ATTR_MTIME);
-		}
+                        error = presto_settime(fset, NULL, NULL, dir, info,
+                                               ATTR_CTIME | ATTR_MTIME);
+                }
         }
         double_up(&dir->d_inode->i_zombie, &dentry->d_inode->i_zombie);
         if (!error)
                 d_delete(dentry);
         dput(dentry);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x10);
         if ( !error && do_kml )
                 error = presto_journal_rmdir(&rec, fset, dir, &tgt_dir_ver,
-                                             &old_dir_ver,
+                                             &old_dir_ver, &rb,
                                              dentry->d_name.len,
                                              dentry->d_name.name);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x20);
-        if ( !error && do_expect ) 
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x20);
+        if ( !error && do_rcvd ) 
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RMDIR | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RMDIR | 0x30);
         EXIT;
 
         presto_trans_commit(fset, handle);
-	presto_release_space(fset->fset_cache, size); 
+        presto_release_space(fset->fset_cache, size); 
         return error;
 }
 
@@ -1320,21 +1522,27 @@
 
         ENTRY;
         name = getname(pathname);
-        if(IS_ERR(name))
+        if(IS_ERR(name)) {
+                EXIT;
                 return PTR_ERR(name);
+        }
 
         if (path_init(name, LOOKUP_PARENT, &nd))
                 error = path_walk(name, &nd);
-        if (error)
+        if (error) {
+                EXIT;
                 goto exit;
-
+        }
         switch(nd.last_type) {
-                case LAST_DOTDOT:
-                        error = -ENOTEMPTY;
-                        goto exit1;
-                case LAST_ROOT: case LAST_DOT:
-                        error = -EBUSY;
-                        goto exit1;
+        case LAST_DOTDOT:
+                error = -ENOTEMPTY;
+                EXIT;
+                goto exit1;
+        case LAST_ROOT:
+        case LAST_DOT:
+                error = -EBUSY;
+                EXIT;
+                goto exit1;
         }
         down(&nd.dentry->d_inode->i_sem);
         dentry = lookup_hash(&nd.last, nd.dentry);
@@ -1343,7 +1551,7 @@
                 fset = presto_fset(dentry);
                 error = -EINVAL;
                 if ( !fset ) {
-                        printk("No fileset!\n");
+                        CERROR("No fileset!\n");
                         EXIT;
                         goto exit_put;
                 }
@@ -1353,11 +1561,10 @@
         }
         up(&nd.dentry->d_inode->i_sem);
 exit1:
-        EXIT;
         path_release(&nd);
 exit:
-        EXIT;
         putname(name);
+        EXIT;
         return error;
 }
 
@@ -1374,13 +1581,13 @@
         ENTRY;
 
         down(&dir->d_inode->i_zombie);
-	/* one KML entry */ 
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
-	if (error) {
-		EXIT;
-        	up(&dir->d_inode->i_zombie);
-		return error;
-	}
+        /* one KML entry */ 
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
+        if (error) {
+                EXIT;
+                up(&dir->d_inode->i_zombie);
+                return error;
+        }
 
         if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) {
                 EXIT;
@@ -1405,10 +1612,10 @@
         
         error = -ENOSPC;
         presto_getversion(&tgt_dir_ver, dir->d_inode);
-        handle = presto_trans_start(fset, dir->d_inode, PRESTO_OP_MKNOD);
+        handle = presto_trans_start(fset, dir->d_inode, KML_OPCODE_MKNOD);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
-                printk("presto_do_mknod: no space for transaction\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+                CERROR("presto_do_mknod: no space for transaction\n");
                 goto exit_lock2;
         }
 
@@ -1417,11 +1624,11 @@
                 EXIT;
                 goto exit_commit;
         }
-        if ( dentry->d_inode &&
-             dentry->d_inode->i_gid != presto_excluded_gid) {
+        if ( dentry->d_inode) {
                 struct presto_cache *cache = fset->fset_cache;
-                /* make it ours */
-                dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
+
+                presto_set_ops(dentry->d_inode, cache->cache_filter);
+
                 filter_setup_dentry_ops(cache->cache_filter, dentry->d_op, 
                                         &presto_dentry_ops);
                 dentry->d_op = filter_c2udops(cache->cache_filter);
@@ -1434,35 +1641,37 @@
                 }
         }
 
-        error = presto_settime(fset, dir, info, ATTR_MTIME);
+        error = presto_settime(fset, NULL, NULL, dir,
+                               info, ATTR_MTIME);
         if (error) { 
                 EXIT;
         }
-        error = presto_settime(fset, dentry, info, ATTR_CTIME | ATTR_MTIME);
+        error = presto_settime(fset, NULL, NULL, dentry,
+                               info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
         }
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x10);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x10);
         presto_getversion(&new_node_ver, dentry->d_inode);
-        if ( presto_do_kml(info, dentry->d_inode) )
+        if ( presto_do_kml(info, dentry) )
                 error = presto_journal_mknod(&rec, fset, dentry, &tgt_dir_ver,
-                                             &new_node_ver,
+                                             &new_node_ver, 
                                              dentry->d_inode->i_mode,
                                              MAJOR(dev), MINOR(dev) );
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) ) 
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x20);
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_MKNOD | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_MKNOD | 0x30);
         EXIT;
  exit_commit:
         presto_trans_commit(fset, handle);
  exit_lock2:
         unlock_kernel();
  exit_lock:
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
         up(&dir->d_inode->i_zombie);
         return error;
 }
@@ -1494,7 +1703,7 @@
                 fset = presto_fset(dentry);
                 error = -EINVAL;
                 if ( !fset ) {
-                        printk("No fileset!\n");
+                        CERROR("No fileset!\n");
                         EXIT;
                         goto exit_put;
                 }
@@ -1523,7 +1732,7 @@
         return error;
 }
 
-static int do_rename(struct presto_file_set *fset,
+int do_rename(struct presto_file_set *fset,
                      struct dentry *old_parent, struct dentry *old_dentry,
                      struct dentry *new_parent, struct dentry *new_dentry,
                      struct lento_vfs_context *info)
@@ -1533,7 +1742,7 @@
         struct inode_operations *iops;
         struct presto_version src_dir_ver, tgt_dir_ver;
         void *handle;
-	int new_inode_unlink = 0;
+        int new_inode_unlink = 0;
         struct inode *old_dir = old_parent->d_inode;
         struct inode *new_dir = new_parent->d_inode;
 
@@ -1548,15 +1757,15 @@
                 return error;
         }
 
-	error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
-	if (error) {
-		EXIT;
-		return error;
-	}
-        handle = presto_trans_start(fset, old_dir, PRESTO_OP_RENAME);
+        error = presto_reserve_space(fset->fset_cache, PRESTO_REQHIGH); 
+        if (error) {
+                EXIT;
+                return error;
+        }
+        handle = presto_trans_start(fset, old_dir, KML_OPCODE_RENAME);
         if ( IS_ERR(handle) ) {
-		presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
-                printk("presto_do_rename: no space for transaction\n");
+                presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+                CERROR("presto_do_rename: no space for transaction\n");
                 return -ENOSPC;
         }
         if (new_dentry->d_inode && new_dentry->d_inode->i_nlink > 1) { 
@@ -1572,19 +1781,17 @@
         }
 
         if (new_inode_unlink) { 
-                error = presto_settime(fset, old_dentry, info, ATTR_CTIME);
+                error = presto_settime(fset, NULL, NULL, old_dentry,
+                                       info, ATTR_CTIME);
                 dput(old_dentry); 
                 if (error) { 
                         EXIT;
                         goto exit;
                 }
         }
-        error = presto_settime(fset, old_parent, info, ATTR_CTIME | ATTR_MTIME);
-        if (error) { 
-                EXIT;
-                goto exit;
-        }
-        error = presto_settime(fset, new_parent, info, ATTR_CTIME | ATTR_MTIME);
+        info->flags |= LENTO_FL_TOUCH_PARENT;
+        error = presto_settime(fset, NULL, new_parent, old_parent,
+                               info, ATTR_CTIME | ATTR_MTIME);
         if (error) { 
                 EXIT;
                 goto exit;
@@ -1593,21 +1800,22 @@
         /* XXX make a distinction between cross file set
          * and intra file set renames here
          */
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x10);
-        if ( presto_do_kml(info, old_dir) )
-                error = presto_journal_rename(&rec, fset, old_dentry, new_dentry,
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x10);
+        if ( presto_do_kml(info, old_dentry) )
+                error = presto_journal_rename(&rec, fset, old_dentry,
+                                              new_dentry,
                                               &src_dir_ver, &tgt_dir_ver);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x20);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x20);
 
-        if ( presto_do_expect(info, new_dir) ) 
+        if ( presto_do_rcvd(info, old_dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_RENAME | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_RENAME | 0x30);
         EXIT;
 exit:
         presto_trans_commit(fset, handle);
-	presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
+        presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
         return error;
 }
 
@@ -1729,7 +1937,7 @@
                 error = -EBUSY;
         else
                 error = do_rename(fset, old_parent, old_dentry,
-                                         new_parent, new_dentry, info);
+                                  new_parent, new_dentry, info);
         double_up(&old_dir->i_zombie, &new_dir->i_zombie);
         if (error)
                 return error;
@@ -1802,7 +2010,7 @@
         fset = presto_fset(old_dentry);
         error = -EINVAL;
         if ( !fset ) {
-                printk("No fileset!\n");
+                CERROR("No fileset!\n");
                 EXIT;
                 goto exit4;
         }
@@ -1852,7 +2060,7 @@
         if (!IS_ERR(to)) {
                 error = lento_do_rename(from,to, info);
                 putname(to);
-        }
+        } 
         putname(from);
         return error;
 }
@@ -1879,7 +2087,7 @@
         fset = presto_fset(dentry);
         error = -EINVAL;
         if (!fset) {
-                printk("No fileset for %*s!\n",
+                CERROR("No fileset for %*s!\n",
                        dentry->d_name.len, dentry->d_name.name);
                 EXIT;
                 dput(dentry);
@@ -1890,7 +2098,7 @@
         sprintf(name, "%s%#lx%c%#x",
                 PRESTO_ILOOKUP_MAGIC, ino, PRESTO_ILOOKUP_SEP, generation);
         CDEBUG(D_PIOCTL, "opening %ld by number (as %s)\n", ino, name);
-        return lookup_one_len(name, fset->fset_mtpt, strlen(name));
+        return lookup_one_len(name, fset->fset_dentry, strlen(name));
 }
 
 static struct file *presto_filp_dopen(struct dentry *dentry, int flags)
@@ -1914,8 +2122,7 @@
                 error = get_write_access(inode);
                 if (error) {
                         CDEBUG(D_PIOCTL, "error getting write access\n");
-                        EXIT;
-                        goto cleanup_file;
+                        EXIT;                        goto cleanup_file;
                 }
         }
 
@@ -1969,8 +2176,8 @@
          * just turn off the flag and ignore it.
          */
         if (flags & O_CREAT) {
-                printk(KERN_WARNING "%s: create file by inode number (%ld) not allowed\n",
-                	__FUNCTION__, ino);
+                CERROR("%s: create file by inode number (%ld) not allowed\n",
+                       __FUNCTION__, ino);
                 EXIT;
                 return -EACCES;
         }
@@ -1986,6 +2193,7 @@
         error = presto_walk(tmp, &nd);
         if ( error && error != -ENOENT ) {
                 EXIT;
+                unlock_kernel();
                 return error;
         } 
         if (error == -ENOENT)
@@ -2000,7 +2208,7 @@
                 slash = strrchr(tmp, '/');
                 if (slash && slash != tmp) {
                         *slash = '\0';
-			path_release(&nd);
+                        path_release(&nd);
                         goto again;
                 }
                 /* we should never get here... */
@@ -2052,7 +2260,7 @@
         EXIT;
 exit:
         unlock_kernel();
-	path_release(&nd);
+        path_release(&nd);
         putname(tmp);
         return fd;
 
@@ -2061,72 +2269,6 @@
         goto exit;
 }
 
-int lento_close(unsigned int fd, struct lento_vfs_context *info)
-{
-        struct rec_info rec;
-        int error;
-        struct file * filp;
-        struct dentry *dentry;
-        int do_kml, do_expect;
-
-        ENTRY;
-        lock_kernel();
-
-        error = -EBADF;
-        filp = fcheck(fd);
-        if (filp) {
-
-                struct files_struct * files = current->files;
-                dentry = filp->f_dentry;
-                dget(dentry);
-                do_kml = presto_do_kml(info, dentry->d_inode);
-                do_expect = presto_do_expect(info, dentry->d_inode);
-                files->fd[fd] = NULL;
-                put_unused_fd(fd);
-                FD_CLR(fd, files->close_on_exec);
-                error = filp_close(filp, files);
-        } else {
-                EXIT;
-                return error;
-        }
-
-        if (error) {
-                EXIT;
-                goto exit;
-        }
-
-        if ( do_kml ) { 
-                struct presto_file_set *fset;
-                struct presto_version new_file_ver;
-
-                fset = presto_fset(dentry);
-                error = -EINVAL;
-                if (!fset) {
-                        printk("No fileset for %*s!\n",
-                               dentry->d_name.len, dentry->d_name.name);
-                        EXIT;
-                        goto exit;
-                }
-                presto_getversion(&new_file_ver, dentry->d_inode);
-                error = presto_journal_close(&rec, fset, filp, dentry, 
-					     &new_file_ver);
-                if ( error ) {
-                        printk("presto: close error %d!\n", error);
-                        EXIT;
-                        goto exit;
-                }
-                if ( do_expect ) 
-
-                        error = presto_write_last_rcvd(&rec, fset, info);
-        }
-
-        EXIT;
-exit:
-        dput(dentry);
-        unlock_kernel();
-        return error;
-}
-
 #ifdef CONFIG_FS_EXT_ATTR
 
 #ifdef CONFIG_FS_POSIX_ACL
@@ -2254,9 +2396,9 @@
         }
 
         
-        handle = presto_trans_start(fset,dentry->d_inode,PRESTO_OP_SETEXTATTR);
+        handle = presto_trans_start(fset,dentry->d_inode,KML_OPCODE_SETEXTATTR);
         if ( IS_ERR(handle) ) {
-                printk("presto_do_set_ext_attr: no space for transaction\n");
+                CERROR("presto_do_set_ext_attr: no space for transaction\n");
                 presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 
                 return -ENOSPC;
         }
@@ -2285,15 +2427,15 @@
 #endif
 
         /* Reset ctime. Only inode change time (ctime) is affected */
-        error = presto_settime(fset, dentry, info, ATTR_CTIME);
+        error = presto_settime(fset, NULL, NULL, dentry, info, ATTR_CTIME);
         if (error) { 
                 EXIT;
                 goto exit;
         }
 
         if (flags & EXT_ATTR_FLAG_USER) {
-                printk(" USER flag passed to presto_do_set_ext_attr!\n");
-                *(int *)0 = 1;
+                CERROR(" USER flag passed to presto_do_set_ext_attr!\n");
+                BUG();
         }
 
         /* We are here, so set_ext_attr succeeded. We no longer need to keep
@@ -2302,17 +2444,17 @@
          */
         flags &= ~(EXT_ATTR_FLAG_EXISTS | EXT_ATTR_FLAG_CREATE);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x10);
-        if ( presto_do_kml(info, dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x10);
+        if ( presto_do_kml(info, dentry) )
                 error = presto_journal_set_ext_attr
                         (&rec, fset, dentry, &ver, name, buffer, 
                          buffer_len, flags);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x20);
-        if ( presto_do_expect(info, dentry->d_inode) )
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x20);
+        if ( presto_do_rcvd(info, dentry) )
                 error = presto_write_last_rcvd(&rec, fset, info);
 
-        presto_debug_fail_blkdev(fset, PRESTO_OP_SETEXTATTR | 0x30);
+        presto_debug_fail_blkdev(fset, KML_OPCODE_SETEXTATTR | 0x30);
         EXIT;
 exit:
         presto_release_space(fset->fset_cache, PRESTO_REQHIGH); 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)