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
- Lines: 890
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/fs/intermezzo/kml_reint.c
- Orig date:
Sun Nov 11 10:20:21 2001
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)