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

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

diff -urN linux-2.4.19/fs/intermezzo/kml_reint.c linux-2.4.20/fs/intermezzo/kml_reint.c
@@ -1,9 +1,25 @@
-/*
- * KML REINT
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
  *
- * Copryright (C) 1996 Arthur Ma <arthur.ma@mountainviewdata.com>
+ *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
+ *
+ *   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.
+ *
+ * Reintegration of KML records
  *
- * Copyright (C) 2000 Mountainview Data, Inc.
  */
 
 #define __NO_VERSION__
@@ -19,393 +35,596 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <linux/intermezzo_fs.h>
-#include <linux/intermezzo_kml.h>
 #include <linux/intermezzo_psdev.h>
-#include <linux/intermezzo_upcall.h>
-
-static void kmlreint_pre_secure (struct kml_rec *rec);
-static void kmlreint_post_secure (struct kml_rec *rec);
 
-static void kmlreint_pre_secure (struct kml_rec *rec)
+static void kmlreint_pre_secure(struct kml_rec *rec, struct file *dir,
+                                struct run_ctxt *saved)
 {
-        if (current->fsuid != current->uid)
-                CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsuid\n");
-        if (current->fsgid != current->gid)
-                CDEBUG (D_KML, "reint_kmlreint_pre_secure: cannot setfsgid\n");
-        current->fsuid = rec->rec_head.uid;
-        current->fsgid = rec->rec_head.fsgid;
+        struct run_ctxt ctxt; 
+        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
+        int i;
+
+        ctxt.fsuid = rec->prefix.hdr->fsuid;
+        ctxt.fsgid = rec->prefix.hdr->fsgid;
+        ctxt.fs = KERNEL_DS; 
+        ctxt.pwd = dd->dd_fset->fset_dentry;
+        ctxt.pwdmnt = dd->dd_fset->fset_mnt;
+
+        ctxt.root = ctxt.pwd;
+        ctxt.rootmnt = ctxt.pwdmnt;
+        if (rec->prefix.hdr->ngroups > 0) {
+                ctxt.ngroups = rec->prefix.hdr->ngroups;
+                for (i = 0; i< ctxt.ngroups; i++) 
+                        ctxt.groups[i] = rec->prefix.groups[i];
+        } else
+                ctxt.ngroups = 0;
+
+        push_ctxt(saved, &ctxt);
+}
+
+
+/* Append two strings in a less-retarded fashion. */
+static char * path_join(char *p1, int p1len, char *p2, int p2len)
+{
+        int size = p1len + p2len + 2; /* possibly one extra /, one NULL */
+        char *path;
+
+        path = kmalloc(size, GFP_KERNEL);
+        if (path == NULL)
+                return NULL;
+
+        memcpy(path, p1, p1len);
+        if (path[p1len - 1] != '/') {
+                path[p1len] = '/';
+                p1len++;
+        }
+        memcpy(path + p1len, p2, p2len);
+        path[p1len + p2len] = '\0';
+
+        return path;
 }
 
-static void kmlreint_post_secure (struct kml_rec *rec)
+static inline int kml_recno_equal(struct kml_rec *rec,
+                                  struct presto_file_set *fset)
 {
-        current->fsuid = current->uid; 
-        current->fsgid = current->gid;
-        /* current->egid = current->gid; */ 
-        /* ????????????? */
+        return (rec->suffix->recno == fset->fset_lento_recno + 1);
 }
 
-static int reint_create (int slot_offset, struct kml_rec *rec)
+static inline int version_equal(struct presto_version *a, struct inode *inode)
 {
-        struct  lento_vfs_context info;
-        struct  kml_create *create = &rec->rec_kml.create;
-        mm_segment_t old_fs;
-        int     error;
+        if (a == NULL)
+                return 1;
+
+        if (inode == NULL) {
+                CERROR("InterMezzo: NULL inode in version_equal()\n");
+                return 0;
+        }
+
+        if (inode->i_mtime == a->pv_mtime &&
+            (S_ISDIR(inode->i_mode) || inode->i_size == a->pv_size))
+                return 1;
 
+        return 0;
+}
+
+static int reint_close(struct kml_rec *rec, struct file *file,
+                       struct lento_vfs_context *given_info)
+{
+        struct run_ctxt saved_ctxt;
+        int error;
+        struct presto_file_set *fset;
+        struct lento_vfs_context info; 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0; 
+        memcpy(&info, given_info, sizeof(*given_info));
 
-        CDEBUG (D_KML, "=====REINT_CREATE::%s\n", create->path);
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_create(create->path, create->mode, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
+
+        CDEBUG (D_KML, "=====REINT_CLOSE::%s\n", rec->path);
+
+        fset = presto_fset(file->f_dentry);
+        if (fset->fset_flags & FSET_DATA_ON_DEMAND) {
+                struct iattr iattr;
+
+                iattr.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_SIZE;
+                iattr.ia_mtime = (time_t)rec->new_objectv->pv_mtime;
+                iattr.ia_ctime = (time_t)rec->new_objectv->pv_ctime;
+                iattr.ia_size = (time_t)rec->new_objectv->pv_size;
+
+                /* no kml record, but update last rcvd */
+                /* save fileid in dentry for later backfetch */
+                info.flags |= LENTO_FL_EXPECT | LENTO_FL_SET_DDFILEID;
+                info.remote_ino = rec->ino;
+                info.remote_generation = rec->generation;
+                info.flags &= ~LENTO_FL_KML;
+                kmlreint_pre_secure(rec, file, &saved_ctxt);
+                error = lento_setattr(rec->path, &iattr, &info);
+                pop_ctxt(&saved_ctxt);
+
+                presto_d2d(file->f_dentry)->dd_flags &= ~PRESTO_DATA;
+        } else {
+                int minor = presto_f2m(fset);
+
+                info.updated_time = rec->new_objectv->pv_mtime;
+                memcpy(&info.remote_version, rec->old_objectv, 
+                       sizeof(*rec->old_objectv));
+                info.remote_ino = rec->ino;
+                info.remote_generation = rec->generation;
+                error = izo_upc_backfetch(minor, rec->path, fset->fset_name,
+                                          &info);
+                if (error) {
+                        CERROR("backfetch error %d\n", error);
+                        /* if file doesn't exist anymore,  then ignore the CLOSE
+                         * and just update the last_rcvd.
+                         */
+                        if (error == ENOENT) {
+                                CDEBUG(D_KML, "manually updating remote offset uuid %s"
+                                       "recno %d offset %Lu\n", info.uuid, info.recno, info.kml_offset);
+                                error = izo_rcvd_upd_remote(fset, info.uuid, info.recno, info.kml_offset);
+                                if(error)
+                                        CERROR("izo_rcvd_upd_remote error %d\n", error);
+
+                        } 
+                }
+                        
+                /* propagate error to avoid further reint */
+        }
 
         EXIT;
         return error;
 }
 
-static int reint_open (int slot_offset, struct kml_rec *rec)
+static int reint_create(struct kml_rec *rec, struct file *dir,
+                        struct lento_vfs_context *info)
 {
-        return 0;
+        struct run_ctxt saved_ctxt;
+        int     error;        ENTRY;
+
+        CDEBUG (D_KML, "=====REINT_CREATE::%s\n", rec->path);
+        info->updated_time = rec->new_objectv->pv_ctime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_create(rec->path, rec->mode, info);
+        pop_ctxt(&saved_ctxt); 
+
+        EXIT;
+        return error;
 }
 
-static int reint_mkdir (int slot_offset, struct kml_rec *rec)
+static int reint_link(struct kml_rec *rec, struct file *dir,
+                      struct lento_vfs_context *info)
 {
-        struct  lento_vfs_context info;
-        struct  kml_mkdir *mkdir = &rec->rec_kml.mkdir;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
         int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0; 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_mkdir (mkdir->path, mkdir->mode, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
+        CDEBUG (D_KML, "=====REINT_LINK::%s -> %s\n", rec->path, rec->target);
+        info->updated_time = rec->new_objectv->pv_mtime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_link(rec->path, rec->target, info);
+        pop_ctxt(&saved_ctxt); 
 
         EXIT;
         return error;
 }
 
-static int reint_rmdir (int slot_offset, struct kml_rec *rec)
+static int reint_mkdir(struct kml_rec *rec, struct file *dir,
+                       struct lento_vfs_context *info)
 {
-        struct  kml_rmdir  *rmdir = &rec->rec_kml.rmdir;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
-        char *name;
-        int error;
+        struct run_ctxt saved_ctxt;
+        int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
-        name = bdup_printf ("%s/%s", rmdir->path, rmdir->name);
-        if (name == NULL)
-        {
-                kmlreint_post_secure (rec);
-                EXIT;
-                return -ENOMEM;
-        }
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0;
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_rmdir (name, &info);
-        set_fs (old_fs);
+        CDEBUG (D_KML, "=====REINT_MKDIR::%s\n", rec->path);
+        info->updated_time = rec->new_objectv->pv_ctime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_mkdir(rec->path, rec->mode, info);
+        pop_ctxt(&saved_ctxt); 
+
+        EXIT;
+        return error;
+}
+
+static int reint_mknod(struct kml_rec *rec, struct file *dir,
+                       struct lento_vfs_context *info)
+{
+        struct run_ctxt saved_ctxt;
+        int     error, dev;
+
+        ENTRY;
+
+        CDEBUG (D_KML, "=====REINT_MKNOD::%s\n", rec->path);
+        info->updated_time = rec->new_objectv->pv_ctime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+
+        dev = rec->rdev ?: MKDEV(rec->major, rec->minor);
+
+        error = lento_mknod(rec->path, rec->mode, dev, info);
+        pop_ctxt(&saved_ctxt); 
 
-        PRESTO_FREE (name, strlen (name) + 1);
-        kmlreint_post_secure (rec);
         EXIT;
         return error;
 }
 
-static int reint_link (int slot_offset, struct kml_rec *rec)
+
+static int reint_noop(struct kml_rec *rec, struct file *dir,
+                      struct lento_vfs_context *info)
+{
+        return 0;
+}
+
+static int reint_rename(struct kml_rec *rec, struct file *dir,
+                        struct lento_vfs_context *info)
 {
-        struct  kml_link *link = &rec->rec_kml.link;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
         int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0; 
+        CDEBUG (D_KML, "=====REINT_RENAME::%s -> %s\n", rec->path, rec->target);
+        info->updated_time = rec->new_objectv->pv_mtime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_rename(rec->path, rec->target, info);
+        pop_ctxt(&saved_ctxt); 
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_link (link->sourcepath, link->targetpath, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
         EXIT;
         return error;
 }
 
-static int reint_unlink (int slot_offset, struct kml_rec *rec)
+static int reint_rmdir(struct kml_rec *rec, struct file *dir,
+                       struct lento_vfs_context *info)
 {
-        struct  kml_unlink *unlink = &rec->rec_kml.unlink;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
         int     error;
-        char   *name;
+        char *path;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
-        name = bdup_printf ("%s/%s", unlink->path, unlink->name);
-        if (name == NULL)
-        {
-                kmlreint_post_secure (rec);
+
+        path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
+        if (path == NULL) {
                 EXIT;
                 return -ENOMEM;
         }
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0;
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_unlink (name, &info);
-        set_fs (old_fs);
-        PRESTO_FREE (name, strlen (name));
-        kmlreint_post_secure (rec);
+        CDEBUG (D_KML, "=====REINT_RMDIR::%s\n", path);
+        info->updated_time = rec->new_parentv->pv_mtime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_rmdir(path, info);
+        pop_ctxt(&saved_ctxt); 
 
+        kfree(path);
         EXIT;
         return error;
 }
 
-static int reint_symlink (int slot_offset, struct kml_rec *rec)
+static int reint_setattr(struct kml_rec *rec, struct file *dir,
+                         struct lento_vfs_context *info)
 {
-        struct  kml_symlink *symlink = &rec->rec_kml.symlink;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
+        struct iattr iattr;
         int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0; 
+        iattr.ia_valid = rec->valid;
+        iattr.ia_mode  = (umode_t)rec->mode;
+        iattr.ia_uid   = (uid_t)rec->uid;
+        iattr.ia_gid   = (gid_t)rec->gid;
+        iattr.ia_size  = (off_t)rec->size;
+        iattr.ia_ctime = (time_t)rec->ctime;
+        iattr.ia_mtime = (time_t)rec->mtime;
+        iattr.ia_atime = iattr.ia_mtime; /* We don't track atimes. */
+        iattr.ia_attr_flags = rec->flags;
+
+        CDEBUG (D_KML, "=====REINT_SETATTR::%s (%d)\n", rec->path, rec->valid);
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_setattr(rec->path, &iattr, info);
+        pop_ctxt(&saved_ctxt); 
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_symlink (symlink->targetpath, 
-                        symlink->sourcepath, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
         EXIT;
         return error;
 }
 
-static int reint_rename (int slot_offset, struct kml_rec *rec)
+static int reint_symlink(struct kml_rec *rec, struct file *dir,
+                         struct lento_vfs_context *info)
 {
-        struct  kml_rename *rename = &rec->rec_kml.rename;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
         int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0;
-
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_rename (rename->sourcepath, rename->targetpath, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
+        CDEBUG (D_KML, "=====REINT_SYMLINK::%s -> %s\n", rec->path, rec->target);
+        info->updated_time = rec->new_objectv->pv_ctime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_symlink(rec->target, rec->path, info);
+        pop_ctxt(&saved_ctxt); 
 
         EXIT;
         return error;
 }
 
-static int reint_setattr (int slot_offset, struct kml_rec *rec)
+static int reint_unlink(struct kml_rec *rec, struct file *dir,
+                        struct lento_vfs_context *info)
 {
-        struct  kml_setattr *setattr = &rec->rec_kml.setattr;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
+        struct run_ctxt saved_ctxt;
         int     error;
+        char *path;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = setattr->iattr.ia_attr_flags;
+        path = path_join(rec->path, rec->pathlen - 1, rec->target, rec->targetlen);
+        if (path == NULL) {
+                EXIT;
+                return -ENOMEM;
+        }
+
+        CDEBUG (D_KML, "=====REINT_UNLINK::%s\n", path);
+        info->updated_time = rec->new_parentv->pv_mtime;
+        kmlreint_pre_secure(rec, dir, &saved_ctxt);
+        error = lento_unlink(path, info);
+        pop_ctxt(&saved_ctxt); 
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_setattr (setattr->path, &setattr->iattr, &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
+        kfree(path);
         EXIT;
         return error;
 }
 
-static int reint_mknod (int slot_offset, struct kml_rec *rec)
+static int branch_reint_rename(struct presto_file_set *fset, struct kml_rec *rec, 
+                   struct file *dir, struct lento_vfs_context *info,
+                   char * kml_data, __u64 kml_size)
 {
-        struct  kml_mknod *mknod = &rec->rec_kml.mknod;
-        struct  lento_vfs_context info;
-        mm_segment_t old_fs;
         int     error;
 
         ENTRY;
-        kmlreint_pre_secure (rec);
 
-        info.slot_offset = slot_offset;
-        info.recno = rec->rec_tail.recno;
-        info.kml_offset = rec->rec_kml_offset;
-        info.flags = 0;
+        error = reint_rename(rec, dir, info);
+        if (error == -ENOENT) {
+                /* normal reint failed because path was not found */
+                struct rec_info rec;
+                
+                CDEBUG(D_KML, "saving branch rename kml\n");
+                rec.is_kml = 1;
+                rec.size = kml_size;
+                error = presto_log(fset, &rec, kml_data, kml_size,
+                           NULL, 0, NULL, 0,  NULL, 0);
+                if (error == 0)
+                        error = presto_write_last_rcvd(&rec, fset, info);
+        }
 
-        old_fs = get_fs();
-        set_fs (get_ds());
-        error = lento_mknod (mknod->path, mknod->mode, 
-                MKDEV(mknod->major, mknod->minor), &info);
-        set_fs (old_fs);
-        kmlreint_post_secure (rec);
         EXIT;
         return error;
 }
 
-int kml_reint (char *mtpt, int slot_offset, struct kml_rec *rec)
+int branch_reinter(struct presto_file_set *fset, struct kml_rec *rec, 
+                   struct file *dir, struct lento_vfs_context *info,
+                   char * kml_data, __u64 kml_size)
 {
         int error = 0;
-        switch (rec->rec_head.opcode)
-        {
-                case KML_CREATE:
-                        error = reint_create (slot_offset, rec);
-                        break;
-                case KML_OPEN:
-                        error = reint_open (slot_offset, rec);
-                        break;
-                case KML_CLOSE:
-                        /* error = reint_close (slot_offset, rec);
-                           force the system to return to lento */
-                        error = KML_CLOSE_BACKFETCH;
-                        break;
-                case KML_MKDIR:
-                        error = reint_mkdir (slot_offset, rec);
-                        break;
-                case KML_RMDIR:
-                        error = reint_rmdir (slot_offset, rec);
-                        break;
-                case KML_UNLINK:
-                        error = reint_unlink (slot_offset, rec);
-                        break;
-                case KML_LINK:
-                        error =  reint_link (slot_offset, rec);
-                        break;
-                case KML_SYMLINK:
-                        error = reint_symlink (slot_offset, rec);
-                        break;
-                case KML_RENAME:
-                        error = reint_rename (slot_offset, rec);
-                        break;
-                case KML_SETATTR:
-                        error =  reint_setattr (slot_offset, rec);
-                        break;
-                case KML_MKNOD:
-                        error = reint_mknod (slot_offset, rec);
-                        break;
-                default:
-                        CDEBUG (D_KML, "wrong opcode::%d\n", rec->rec_head.opcode);
-                        return -EBADF;
-        }
-        if (error != 0 && error != KML_CLOSE_BACKFETCH)
-                CDEBUG (D_KML, "KML_ERROR::error = %d\n", error);
+        int op = rec->prefix.hdr->opcode;
+
+        if (op == KML_OPCODE_CLOSE) {
+                /* regular close and backfetch */
+                error = reint_close(rec, dir, info);
+        } else if  (op == KML_OPCODE_RENAME) {
+                /* rename only if name already exists  */
+                error = branch_reint_rename(fset, rec, dir, info,
+                                            kml_data, kml_size);
+        } else {
+                /* just rewrite kml into branch/kml and update last_rcvd */
+                struct rec_info rec;
+                
+                CDEBUG(D_KML, "Saving branch kml\n");
+                rec.is_kml = 1;
+                rec.size = kml_size;
+                error = presto_log(fset, &rec, kml_data, kml_size,
+                           NULL, 0, NULL, 0,  NULL, 0);
+                if (error == 0)
+                        error = presto_write_last_rcvd(&rec, fset, info);
+        }
+                
         return error;
 }
 
-/* return the old mtpt */
-/*
-struct fs_struct {
-        atomic_t count;
-        int umask;
-        struct dentry * root, * pwd;
+typedef int (*reinter_t)(struct kml_rec *rec, struct file *basedir,
+                         struct lento_vfs_context *info);
+
+static reinter_t presto_reinters[KML_OPCODE_NUM] =
+{
+        [KML_OPCODE_CLOSE] = reint_close,
+        [KML_OPCODE_CREATE] = reint_create,
+        [KML_OPCODE_LINK] = reint_link,
+        [KML_OPCODE_MKDIR] = reint_mkdir,
+        [KML_OPCODE_MKNOD] = reint_mknod,
+        [KML_OPCODE_NOOP] = reint_noop,
+        [KML_OPCODE_RENAME] = reint_rename,
+        [KML_OPCODE_RMDIR] = reint_rmdir,
+        [KML_OPCODE_SETATTR] = reint_setattr,
+        [KML_OPCODE_SYMLINK] = reint_symlink,
+        [KML_OPCODE_UNLINK] = reint_unlink,
 };
-*/
-static int do_set_fs_root (struct dentry *newroot, 
-                                        struct dentry **old_root)
-{
-        struct dentry *de = current->fs->root;
-        current->fs->root = newroot;
-	if (old_root != (struct dentry **) NULL)
-        	*old_root = de;
-        return 0;
+
+static inline reinter_t get_reinter(int op)
+{
+        if (op < 0 || op >= sizeof(presto_reinters) / sizeof(reinter_t)) 
+                return NULL; 
+        else 
+                return  presto_reinters[op];
 }
 
-static int set_system_mtpt (char *mtpt, struct dentry **old_root)
+int kml_reint_rec(struct file *dir, struct izo_ioctl_data *data)
 {
-	struct nameidata nd;
-        struct dentry *dentry;
-	int error;
-
-	if (path_init(pathname, LOOKUP_PARENT, &nd))
-		error = path_walk(mtpt, &nd);
-        if (error) {
-                CDEBUG (D_KML, "Yean!!!!::Can't find mtpt::%s\n", mtpt);
+        char *ptr;
+        char *end;
+        struct kml_rec rec;
+        int error = 0;
+        struct lento_vfs_context info;
+        struct presto_cache *cache;
+        struct presto_file_set *fset;
+        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
+        int op;
+        reinter_t reinter;
+
+        struct izo_rcvd_rec lr_rec;
+        int off;
+
+        ENTRY;
+
+        error = presto_prep(dir->f_dentry, &cache, &fset);
+        if ( error  ) {
+                CERROR("intermezzo: Reintegration on invalid file\n");
                 return error;
-	}
+        }
+
+        if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) { 
+                CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
+                       dir->f_dentry->d_inode->i_ino);
+                    
+                return -EINVAL;
+        }
+
+        if (data->ioc_plen1 > 64 * 1024) {
+                EXIT;
+                return -ENOSPC;
+        }
+
+        ptr = fset->fset_reint_buf;
+        end = ptr + data->ioc_plen1;
+
+        if (copy_from_user(ptr, data->ioc_pbuf1, data->ioc_plen1)) { 
+                EXIT;
+                error = -EFAULT;
+                goto out;
+        }
+
+        error = kml_unpack(&rec, &ptr, end);
+        if (error) { 
+                EXIT;
+                error = -EFAULT;
+                goto out;
+        }
+
+        off = izo_rcvd_get(&lr_rec, fset, data->ioc_uuid);
+        if (off < 0) {
+                CERROR("No last_rcvd record, setting to 0\n");
+                memset(&lr_rec, 0, sizeof(lr_rec));
+        }
+ 
+        data->ioc_kmlsize = ptr - fset->fset_reint_buf;
 
-        dentry = nd.dentry;
-        error = do_set_fs_root (dentry, old_root);
-        path_release (&nd);
+        if (rec.suffix->recno != lr_rec.lr_remote_recno + 1) {
+                CERROR("KML record number %Lu expected, not %d\n",
+                       lr_rec.lr_remote_recno + 1,
+                       rec.suffix->recno);
+
+#if 0
+                if (!version_check(&rec, dd->dd_fset, &info)) {
+                        /* FIXME: do an upcall to resolve conflicts */
+                        CERROR("intermezzo: would be a conflict!\n");
+                        error = -EINVAL;
+                        EXIT;
+                        goto out;
+                }
+#endif
+        }
+
+        op = rec.prefix.hdr->opcode;
+
+        reinter = get_reinter(op);
+        if (!reinter) { 
+                CERROR("%s: Unrecognized KML opcode %d\n", __FUNCTION__, op);
+                error = -EINVAL;
+                EXIT;
+                goto out;
+        }
+
+        info.kml_offset = data->ioc_offset + data->ioc_kmlsize;
+        info.recno = rec.suffix->recno;
+        info.flags = LENTO_FL_EXPECT;
+        if (data->ioc_flags)
+                info.flags |= LENTO_FL_KML;
+
+        memcpy(info.uuid, data->ioc_uuid, sizeof(info.uuid));
+
+        if (fset->fset_flags & FSET_IS_BRANCH && data->ioc_flags)
+                error = branch_reinter(fset, &rec, dir, &info, fset->fset_reint_buf,
+                                       data->ioc_kmlsize);
+        else 
+                error = reinter(&rec, dir, &info);
+ out: 
+        EXIT;
         return error;
 }
 
-int kml_reintbuf (struct  kml_fsdata *kml_fsdata,
-                  char *mtpt, struct kml_rec **close_rec)
+int izo_get_fileid(struct file *dir, struct izo_ioctl_data *data)
 {
-        struct kml_rec *rec = NULL;
-        struct list_head *head, *tmp;
-        struct dentry *old_root;
-        int    error = 0;
-
-        head = &kml_fsdata->kml_reint_cache;
-        if (list_empty(head))
-                return 0;
+        char *buf = NULL; 
+        char *ptr;
+        char *end;
+        struct kml_rec rec;
+        struct file *file;
+        struct presto_cache *cache;
+        struct presto_file_set *fset;
+        struct presto_dentry_data *dd = presto_d2d(dir->f_dentry);
+        struct run_ctxt saved_ctxt;
+        int     error;
 
-        if (kml_fsdata->kml_reint_current == NULL ||
-            kml_fsdata->kml_reint_current == head->next)
-                return 0;
+        ENTRY;
 
-        error = set_system_mtpt (mtpt, &old_root);
-        if (error)
+        error = presto_prep(dir->f_dentry, &cache, &fset);
+        if ( error  ) {
+                CERROR("intermezzo: Reintegration on invalid file\n");
                 return error;
+        }
+
+        if (!dd || !dd->dd_fset || dd->dd_fset->fset_dentry != dir->f_dentry) { 
+                CERROR("intermezzo: reintegration on non-fset root (ino %ld)\n",
+                       dir->f_dentry->d_inode->i_ino);
+                    
+                return -EINVAL;
+        }
+
+
+        PRESTO_ALLOC(buf, data->ioc_plen1);
+        if (!buf) { 
+                EXIT;
+                return -ENOMEM;
+        }
+        ptr = buf;
+        end = buf + data->ioc_plen1;
+
+        if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) { 
+                EXIT;
+                PRESTO_FREE(buf, data->ioc_plen1);
+                return -EFAULT;
+        }
 
-        tmp = head->next;
-        while (error == 0 &&  tmp != head ) {
-                rec = list_entry(tmp, struct kml_rec, kml_optimize.kml_chains);
-                error = kml_reint (mtpt, rec->rec_kml_offset, rec);
-                tmp = tmp->next;
+        error = kml_unpack(&rec, &ptr, end);
+        if (error) { 
+                EXIT;
+                PRESTO_FREE(buf, data->ioc_plen1);
+                return -EFAULT;
         }
 
-        do_set_fs_root (old_root, NULL);
-
-        if (error == KML_CLOSE_BACKFETCH)
-                *close_rec = rec;
-        kml_fsdata->kml_reint_current = tmp;
+        kmlreint_pre_secure(&rec, dir, &saved_ctxt);
+
+        file = filp_open(rec.path, O_RDONLY, 0);
+        if (!file || IS_ERR(file)) { 
+                error = PTR_ERR(file);
+                goto out;
+        }
+        data->ioc_ino = file->f_dentry->d_inode->i_ino;
+        data->ioc_generation = file->f_dentry->d_inode->i_generation; 
+        filp_close(file, 0); 
+
+        CDEBUG(D_FILE, "%s ino %Lx, gen %Lx\n", rec.path, 
+               data->ioc_ino, data->ioc_generation);
+
+ out:
+        if (buf) 
+                PRESTO_FREE(buf, data->ioc_plen1);
+        pop_ctxt(&saved_ctxt); 
+        EXIT;
         return error;
 }
 
+

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