Commit 54165329 authored by Robert Read's avatar Robert Read Committed by David S. Miller

[PATCH] InterMezzo for 2.5

This is the initial port of InterMezzo for 2.5.  It now compiles,
mounts, and completes I/Os successfully, but we are aware that more
needs to be done and we will do it as quickly as possible.
parent f8d0366a
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
obj-$(CONFIG_INTERMEZZO_FS) += intermezzo.o obj-$(CONFIG_INTERMEZZO_FS) += intermezzo.o
intermezzo-objs := journal_reiserfs.o cache.o journal.o presto.o vfs.o \ intermezzo-objs := cache.o dcache.o dir.o ext_attr.o file.o fileset.o \
psdev.o upcall.o methods.o sysctl.o dcache.o dir.o \ inode.o io_daemon.o journal.o journal_ext2.o journal_ext3.o \
super.o journal_ext2.o journal_ext3.o journal_xfs.o \ journal_obdfs.o journal_reiserfs.o journal_tmpfs.o journal_xfs.o \
inode.o file.o journal_obdfs.o kml_reint.o kml_unpack.o methods.o presto.o psdev.o replicator.o \
super.o sysctl.o upcall.o vfs.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
/* /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* * vim:expandtab:shiftwidth=8:tabstop=8:
* *
* Copyright (C) 2000 Stelias Computing, Inc. * Copyright (C) 2000 Stelias Computing, Inc.
* Copyright (C) 2000 Red Hat, 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.
*/ */
#define __NO_VERSION__ #define __NO_VERSION__
...@@ -19,14 +32,14 @@ ...@@ -19,14 +32,14 @@
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
/* /*
...@@ -37,24 +50,27 @@ ...@@ -37,24 +50,27 @@
The methods for the cache are set up in methods. The methods for the cache are set up in methods.
*/ */
extern kmem_cache_t * presto_dentry_slab;
/* the intent of this hash is to have collision chains of length 1 */ /* the intent of this hash is to have collision chains of length 1 */
#define CACHES_BITS 8 #define CACHES_BITS 8
#define CACHES_SIZE (1 << CACHES_BITS) #define CACHES_SIZE (1 << CACHES_BITS)
#define CACHES_MASK CACHES_SIZE - 1 #define CACHES_MASK CACHES_SIZE - 1
static struct list_head presto_caches[CACHES_SIZE]; static struct list_head presto_caches[CACHES_SIZE];
static inline int presto_cache_hash(struct super_block *sb) static inline int presto_cache_hash(kdev_t dev)
{ {
return (CACHES_MASK) & ((unsigned long)sb / L1_CACHE_BYTES); return (CACHES_MASK) & ((0x000F & (major(dev)) << 8) + (0x000F & minor(dev)));
} }
inline void presto_cache_add(struct presto_cache *cache, struct super_block *sb) inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
{ {
list_add(&cache->cache_chain, list_add(&cache->cache_chain,
&presto_caches[presto_cache_hash(sb)]); &presto_caches[presto_cache_hash(dev)]);
cache->cache_dev = dev;
} }
inline void presto_init_cache_hash(void) inline void presto_cache_init_hash(void)
{ {
int i; int i;
for ( i = 0; i < CACHES_SIZE; i++ ) { for ( i = 0; i < CACHES_SIZE; i++ ) {
...@@ -63,17 +79,18 @@ inline void presto_init_cache_hash(void) ...@@ -63,17 +79,18 @@ inline void presto_init_cache_hash(void)
} }
/* map a device to a cache */ /* map a device to a cache */
struct presto_cache *presto_find_cache(struct super_block *sb) struct presto_cache *presto_cache_find(kdev_t dev)
{ {
struct presto_cache *cache; struct presto_cache *cache;
struct list_head *lh, *tmp; struct list_head *lh, *tmp;
lh = tmp = &(presto_caches[presto_cache_hash(sb)]); lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
while ( (tmp = lh->next) != lh ) { while ( (tmp = lh->next) != lh ) {
cache = list_entry(tmp, struct presto_cache, cache_chain); cache = list_entry(tmp, struct presto_cache, cache_chain);
if (cache->cache_sb == sb) if ( kdev_same(cache->cache_dev, dev) ) {
return cache; return cache;
} }
}
return NULL; return NULL;
} }
...@@ -82,85 +99,19 @@ struct presto_cache *presto_find_cache(struct super_block *sb) ...@@ -82,85 +99,19 @@ struct presto_cache *presto_find_cache(struct super_block *sb)
struct presto_cache *presto_get_cache(struct inode *inode) struct presto_cache *presto_get_cache(struct inode *inode)
{ {
struct presto_cache *cache; struct presto_cache *cache;
ENTRY;
/* find the correct presto_cache here, based on the device */ /* find the correct presto_cache here, based on the device */
cache = presto_find_cache(inode->i_sb); cache = presto_cache_find(to_kdev_t(inode->i_dev));
if ( !cache ) { if ( !cache ) {
printk("WARNING: no presto cache for dev %s, ino %ld\n", CERROR("WARNING: no presto cache for dev %x, ino %ld\n",
inode->i_sb->s_id, inode->i_ino); inode->i_dev, inode->i_ino);
EXIT; EXIT;
return NULL; return NULL;
} }
EXIT;
return cache; return cache;
} }
/* list cache mount points for ioctl's or /proc/fs/intermezzo/mounts */
int presto_sprint_mounts(char *buf, int buflen, int minor)
{
int len = 0;
int i;
struct list_head *head, *tmp;
struct presto_cache *cache;
buf[0] = '\0';
for (i=0 ; i<CACHES_SIZE ; i++) {
head = tmp = &presto_caches[i];
while ( (tmp = tmp->next) != head ) {
cache = list_entry(tmp, struct presto_cache,
cache_chain);
if ( !cache->cache_root_fileset || !cache->cache_mtpt)
continue;
if ((minor != -1) &&
(cache->cache_psdev->uc_minor != minor))
continue;
if ( strlen(cache->cache_root_fileset) +
strlen(cache->cache_mtpt) +
strlen(cache->cache_psdev->uc_devname) +
4 > buflen - len)
break;
len += sprintf(buf + len, "%s %s %s\n",
cache->cache_root_fileset,
cache->cache_mtpt,
cache->cache_psdev->uc_devname);
}
}
buf[buflen-1] = '\0';
CDEBUG(D_SUPER, "%s\n", buf);
return len;
}
#ifdef CONFIG_KREINT
/* get mount point by volname
Arthur Ma, 2000.12.25
*/
int presto_get_mount (char *buf, int buflen, char *volname)
{
int i;
struct list_head *head, *tmp;
struct presto_cache *cache = NULL;
char *path = "";
buf[0] = '\0';
for (i=0 ; i<CACHES_SIZE ; i++) {
head = tmp = &presto_caches[i];
while ( (tmp = tmp->next) != head ) {
cache = list_entry(tmp, struct presto_cache,
cache_chain);
if ( !cache->cache_root_fileset || !cache->cache_mtpt)
continue;
if ( strcmp(cache->cache_root_fileset, volname) == 0)
break;
}
}
if (cache != NULL)
path = cache->cache_mtpt;
strncpy (buf, path, buflen);
return strlen (buf);
}
#endif
/* another debugging routine: check fs is InterMezzo fs */ /* another debugging routine: check fs is InterMezzo fs */
int presto_ispresto(struct inode *inode) int presto_ispresto(struct inode *inode)
{ {
...@@ -171,27 +122,25 @@ int presto_ispresto(struct inode *inode) ...@@ -171,27 +122,25 @@ int presto_ispresto(struct inode *inode)
cache = presto_get_cache(inode); cache = presto_get_cache(inode);
if ( !cache ) if ( !cache )
return 0; return 0;
return (inode->i_sb == cache->cache_sb); return kdev_same(to_kdev_t(inode->i_dev), cache->cache_dev);
} }
/* setup a cache structure when we need one */ /* setup a cache structure when we need one */
struct presto_cache *presto_init_cache(void) struct presto_cache *presto_cache_init(void)
{ {
struct presto_cache *cache; struct presto_cache *cache;
/* make a presto_cache structure for the hash */ PRESTO_ALLOC(cache, sizeof(struct presto_cache));
PRESTO_ALLOC(cache, struct presto_cache *, sizeof(struct presto_cache));
if ( cache ) { if ( cache ) {
memset(cache, 0, sizeof(struct presto_cache)); memset(cache, 0, sizeof(struct presto_cache));
INIT_LIST_HEAD(&cache->cache_chain); INIT_LIST_HEAD(&cache->cache_chain);
INIT_LIST_HEAD(&cache->cache_fset_list); INIT_LIST_HEAD(&cache->cache_fset_list);
}
cache->cache_lock = SPIN_LOCK_UNLOCKED; cache->cache_lock = SPIN_LOCK_UNLOCKED;
cache->cache_reserved = 0; cache->cache_reserved = 0;
}
return cache; return cache;
} }
/* free a cache structure and all of the memory it is pointing to */ /* free a cache structure and all of the memory it is pointing to */
inline void presto_free_cache(struct presto_cache *cache) inline void presto_free_cache(struct presto_cache *cache)
{ {
...@@ -199,12 +148,12 @@ inline void presto_free_cache(struct presto_cache *cache) ...@@ -199,12 +148,12 @@ inline void presto_free_cache(struct presto_cache *cache)
return; return;
list_del(&cache->cache_chain); list_del(&cache->cache_chain);
if (cache->cache_mtpt) if (cache->cache_sb && cache->cache_sb->s_root &&
PRESTO_FREE(cache->cache_mtpt, strlen(cache->cache_mtpt) + 1); presto_d2d(cache->cache_sb->s_root)) {
if (cache->cache_type) kmem_cache_free(presto_dentry_slab,
PRESTO_FREE(cache->cache_type, strlen(cache->cache_type) + 1); presto_d2d(cache->cache_sb->s_root));
if (cache->cache_root_fileset) cache->cache_sb->s_root->d_fsdata = NULL;
PRESTO_FREE(cache->cache_root_fileset, strlen(cache->cache_root_fileset) + 1); }
PRESTO_FREE(cache, sizeof(struct presto_cache)); PRESTO_FREE(cache, sizeof(struct presto_cache));
} }
...@@ -227,11 +176,12 @@ int presto_reserve_space(struct presto_cache *cache, loff_t req) ...@@ -227,11 +176,12 @@ int presto_reserve_space(struct presto_cache *cache, loff_t req)
EXIT; EXIT;
return 0; return 0;
} }
spin_lock(&cache->cache_lock);
avail = filter->o_trops->tr_avail(cache, sb); avail = filter->o_trops->tr_avail(cache, sb);
CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved, CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
(long) (cache->cache_reserved + req)); (long) (cache->cache_reserved + req));
CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail); CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
spin_lock(&cache->cache_lock);
if (req + cache->cache_reserved > avail) { if (req + cache->cache_reserved > avail) {
spin_unlock(&cache->cache_lock); spin_unlock(&cache->cache_lock);
EXIT; EXIT;
...@@ -240,6 +190,7 @@ int presto_reserve_space(struct presto_cache *cache, loff_t req) ...@@ -240,6 +190,7 @@ int presto_reserve_space(struct presto_cache *cache, loff_t req)
cache->cache_reserved += req; cache->cache_reserved += req;
spin_unlock(&cache->cache_lock); spin_unlock(&cache->cache_lock);
EXIT;
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
/* /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* Extended attribute handling for presto. * vim:expandtab:shiftwidth=8:tabstop=8:
*
* Copyright (C) 2001 Tacit Networks, Inc.
* Author: Shirish H. Phatak <shirish@tacitnetworks.com>
*
* This file is part of InterMezzo, http://www.inter-mezzo.org.
* *
* Copyright (C) 2001. All rights reserved. * InterMezzo is free software; you can redistribute it and/or
* Shirish H. Phatak * modify it under the terms of version 2 of the GNU General Public
* Tacit Networks, Inc. * 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.
*
* Extended attribute handling for presto.
*/ */
#define __NO_VERSION__ #define __NO_VERSION__
...@@ -14,6 +29,7 @@ ...@@ -14,6 +29,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -22,18 +38,16 @@ ...@@ -22,18 +38,16 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/locks.h> #include <linux/smp_lock.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/segment.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#ifdef CONFIG_FS_EXT_ATTR #ifdef CONFIG_FS_EXT_ATTR
#include <linux/ext_attr.h> #include <linux/ext_attr.h>
...@@ -41,9 +55,6 @@ ...@@ -41,9 +55,6 @@
extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset, extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
unsigned long value); unsigned long value);
extern int presto_prep(struct dentry *, struct presto_cache **,
struct presto_file_set **);
/* VFS interface */ /* VFS interface */
/* XXX! Fixme test for user defined attributes */ /* XXX! Fixme test for user defined attributes */
...@@ -75,7 +86,7 @@ int presto_set_ext_attr(struct inode *inode, ...@@ -75,7 +86,7 @@ int presto_set_ext_attr(struct inode *inode,
* we do a reverse mapping from inode to the first dentry * we do a reverse mapping from inode to the first dentry
*/ */
if (list_empty(&inode->i_dentry)) { if (list_empty(&inode->i_dentry)) {
printk("No alias for inode %d\n", (int) inode->i_ino); CERROR("No alias for inode %d\n", (int) inode->i_ino);
EXIT; EXIT;
return -EINVAL; return -EINVAL;
} }
...@@ -99,12 +110,13 @@ int presto_set_ext_attr(struct inode *inode, ...@@ -99,12 +110,13 @@ int presto_set_ext_attr(struct inode *inode,
* (works for ext3) * (works for ext3)
*/ */
if (flags & EXT_ATTR_FLAG_USER) { if (flags & EXT_ATTR_FLAG_USER) {
PRESTO_ALLOC(buf, char *, buffer_len); PRESTO_ALLOC(buf, buffer_len);
if (!buf) { if (!buf) {
printk("InterMezzo: out of memory!!!\n"); CERROR("InterMezzo: out of memory!!!\n");
return -ENOMEM; return -ENOMEM;
} }
if (copy_from_user(buf, buffer, buffer_len)) error = copy_from_user(buf, buffer, buffer_len);
if (error)
return -EFAULT; return -EFAULT;
} else } else
buf = buffer; buf = buffer;
...@@ -172,7 +184,7 @@ int lento_set_ext_attr(const char *path, const char *name, ...@@ -172,7 +184,7 @@ int lento_set_ext_attr(const char *path, const char *name,
fset = presto_fset(dentry); fset = presto_fset(dentry);
error = -EINVAL; error = -EINVAL;
if ( !fset ) { if ( !fset ) {
printk("No fileset!\n"); CERROR("No fileset!\n");
EXIT; EXIT;
goto exit_dentry; goto exit_dentry;
} }
......
This diff is collapsed.
This diff is collapsed.
/* /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* Super block/filesystem wide operations * vim:expandtab:shiftwidth=8:tabstop=8:
* *
* Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
* Michael Callahan <callahan@maths.ox.ac.uk> * Michael Callahan <callahan@maths.ox.ac.uk>
* * Copyright (C) 1999 Carnegie Mellon University
* Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu> * Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu>
* Copyright (C) Carnegie Mellon University *
* 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.
*
* Super block/filesystem wide operations
*/ */
#define __NO_VERSION__ #define __NO_VERSION__
...@@ -15,6 +31,7 @@ ...@@ -15,6 +31,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -23,33 +40,25 @@ ...@@ -23,33 +40,25 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/segment.h>
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
extern int presto_remount(struct super_block *, int *, char *);
int presto_excluded_gid = PRESTO_EXCL_GID;
extern int presto_prep(struct dentry *, struct presto_cache **,
struct presto_file_set **);
extern void presto_free_cache(struct presto_cache *); extern void presto_free_cache(struct presto_cache *);
void presto_set_ops(struct inode *inode, struct filter_fs *filter) void presto_set_ops(struct inode *inode, struct filter_fs *filter)
{ {
ENTRY; ENTRY;
if (inode->i_gid == presto_excluded_gid ) {
EXIT; if (!inode || is_bad_inode(inode))
CDEBUG(D_INODE, "excluded methods for %ld at %p, %p\n",
inode->i_ino, inode->i_op, inode->i_fop);
return; return;
}
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
if ( !filter_c2cfiops(filter) ) { if ( !filter_c2cfiops(filter) ) {
filter_setup_file_ops(filter, filter_setup_file_ops(filter,
...@@ -63,8 +72,8 @@ void presto_set_ops(struct inode *inode, struct filter_fs *filter) ...@@ -63,8 +72,8 @@ void presto_set_ops(struct inode *inode, struct filter_fs *filter)
} else if (S_ISDIR(inode->i_mode)) { } else if (S_ISDIR(inode->i_mode)) {
inode->i_op = filter_c2udiops(filter); inode->i_op = filter_c2udiops(filter);
inode->i_fop = filter_c2udfops(filter); inode->i_fop = filter_c2udfops(filter);
CDEBUG(D_INODE, "set dir methods for %ld to %p lookup %p\n", CDEBUG(D_INODE, "set dir methods for %ld to %p ioctl %p\n",
inode->i_ino, inode->i_op, inode->i_op->lookup); inode->i_ino, inode->i_op, inode->i_fop->ioctl);
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
if ( !filter_c2csiops(filter)) { if ( !filter_c2csiops(filter)) {
filter_setup_symlink_ops(filter, filter_setup_symlink_ops(filter,
...@@ -86,7 +95,7 @@ void presto_read_inode(struct inode *inode) ...@@ -86,7 +95,7 @@ void presto_read_inode(struct inode *inode)
cache = presto_get_cache(inode); cache = presto_get_cache(inode);
if ( !cache ) { if ( !cache ) {
printk("PRESTO: BAD, BAD: cannot find cache\n"); CERROR("PRESTO: BAD, BAD: cannot find cache\n");
make_bad_inode(inode); make_bad_inode(inode);
return ; return ;
} }
...@@ -96,35 +105,50 @@ void presto_read_inode(struct inode *inode) ...@@ -96,35 +105,50 @@ void presto_read_inode(struct inode *inode)
CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n", CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n",
inode->i_ino, inode->i_gid); inode->i_ino, inode->i_gid);
// if (inode->i_gid == presto_excluded_gid)
// return;
presto_set_ops(inode, cache->cache_filter); presto_set_ops(inode, cache->cache_filter);
/* XXX handle special inodes here or not - probably not? */ /* XXX handle special inodes here or not - probably not? */
} }
void presto_put_super(struct super_block *sb) static void presto_put_super(struct super_block *sb)
{ {
struct presto_cache *cache; struct presto_cache *cache;
struct upc_comm *psdev; struct upc_channel *channel;
struct super_operations *sops; struct super_operations *sops;
struct list_head *lh; struct list_head *lh;
int err;
ENTRY; ENTRY;
cache = presto_find_cache(sb); cache = presto_cache_find(to_kdev_t(sb->s_dev));
if (!cache) { if (!cache) {
EXIT; EXIT;
goto exit; goto exit;
} }
psdev = &upc_comms[presto_c2m(cache)]; channel = &izo_channels[presto_c2m(cache)];
sops = filter_c2csops(cache->cache_filter); sops = filter_c2csops(cache->cache_filter);
err = izo_clear_all_fsetroots(cache);
if (err) {
CERROR("%s: err %d\n", __FUNCTION__, err);
}
PRESTO_FREE(cache->cache_vfsmount, sizeof(struct vfsmount));
/* look at kill_super - fsync_super is not exported GRRR but
probably not needed */
unlock_super(sb);
shrink_dcache_parent(cache->cache_root);
dput(cache->cache_root);
//fsync_super(sb);
lock_super(sb);
if (sops->write_super)
sops->write_super(sb);
if (sops->put_super) if (sops->put_super)
sops->put_super(sb); sops->put_super(sb);
/* free any remaining async upcalls when the filesystem is unmounted */ /* free any remaining async upcalls when the filesystem is unmounted */
lh = psdev->uc_pending.next; spin_lock(&channel->uc_lock);
while ( lh != &psdev->uc_pending) { lh = channel->uc_pending.next;
while ( lh != &channel->uc_pending) {
struct upc_req *req; struct upc_req *req;
req = list_entry(lh, struct upc_req, rq_chain); req = list_entry(lh, struct upc_req, rq_chain);
...@@ -136,6 +160,8 @@ void presto_put_super(struct super_block *sb) ...@@ -136,6 +160,8 @@ void presto_put_super(struct super_block *sb)
PRESTO_FREE(req->rq_data, req->rq_bufsize); PRESTO_FREE(req->rq_data, req->rq_bufsize);
PRESTO_FREE(req, sizeof(struct upc_req)); PRESTO_FREE(req, sizeof(struct upc_req));
} }
list_del(&cache->cache_channel_list);
spin_unlock(&channel->uc_lock);
presto_free_cache(cache); presto_free_cache(cache);
...@@ -146,18 +172,16 @@ void presto_put_super(struct super_block *sb) ...@@ -146,18 +172,16 @@ void presto_put_super(struct super_block *sb)
return ; return ;
} }
struct super_operations presto_super_ops = {
.read_inode = presto_read_inode,
.put_super = presto_put_super,
};
/* symlinks can be chowned */ /* symlinks can be chowned */
struct inode_operations presto_sym_iops = { struct inode_operations presto_sym_iops = {
setattr: presto_setattr .setattr = presto_setattr
}; };
/* NULL for now */ /* NULL for now */
struct file_operations presto_sym_fops; struct file_operations presto_sym_fops;
struct super_operations presto_super_ops = {
read_inode: presto_read_inode,
put_super: presto_put_super,
remount_fs: presto_remount
};
MODULE_LICENSE("GPL");
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* * vim:expandtab:shiftwidth=8:tabstop=8:
* Intermezzo. (C) 1998 Peter J. Braam *
* Copyright (C) 1998 Peter J. Braam <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.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#if defined(CONFIG_EXT2_FS) #if defined(CONFIG_EXT2_FS)
...@@ -46,7 +62,7 @@ static void *presto_e2_trans_start(struct presto_file_set *fset, struct inode *i ...@@ -46,7 +62,7 @@ static void *presto_e2_trans_start(struct presto_file_set *fset, struct inode *i
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }
if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR) if ( (op != KML_OPCODE_UNLINK && op != KML_OPCODE_RMDIR)
&& avail_kmlblocks < 6 ) { && avail_kmlblocks < 6 ) {
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }
...@@ -58,7 +74,14 @@ static void presto_e2_trans_commit(struct presto_file_set *fset, void *handle) ...@@ -58,7 +74,14 @@ static void presto_e2_trans_commit(struct presto_file_set *fset, void *handle)
do {} while (0); do {} while (0);
} }
static int presto_e2_has_all_data(struct inode *inode)
{
BUG();
return 0;
}
struct journal_ops presto_ext2_journal_ops = { struct journal_ops presto_ext2_journal_ops = {
tr_all_data: presto_e2_has_all_data,
tr_avail: presto_e2_freespace, tr_avail: presto_e2_freespace,
tr_start: presto_e2_trans_start, tr_start: presto_e2_trans_start,
tr_commit: presto_e2_trans_commit, tr_commit: presto_e2_trans_commit,
......
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* * vim:expandtab:shiftwidth=8:tabstop=8:
* Intermezzo. (C) 1998 Peter J. Braam *
* Intermezzo. (C) 2000 Red Hat, Inc. * Copyright (C) 1998 Peter J. Braam <braam@clusterfs.com>
* Intermezzo. (C) 2000 Los Alamos National Laboratory * Copyright (C) 2000 Red Hat, Inc.
* Intermezzo. (C) 2000 TurboLinux, Inc. * Copyright (C) 2000 Los Alamos National Laboratory
* Intermezzo. (C) 2001 Mountain View Data, Inc. * Copyright (C) 2000 TurboLinux, Inc.
* Copyright (C) 2001 Mountain View Data, Inc.
* Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
*
* 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.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
...@@ -26,9 +45,7 @@ ...@@ -26,9 +45,7 @@
#endif #endif
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE) #if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
...@@ -52,9 +69,9 @@ ...@@ -52,9 +69,9 @@
static loff_t presto_e3_freespace(struct presto_cache *cache, static loff_t presto_e3_freespace(struct presto_cache *cache,
struct super_block *sb) struct super_block *sb)
{ {
loff_t freebl = le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count); loff_t freebl = le32_to_cpu(EXT3_SB(sb)->s_es->s_free_blocks_count);
loff_t avail = freebl - loff_t avail = freebl -
le32_to_cpu(sb->u.ext3_sb.s_es->s_r_blocks_count); le32_to_cpu(EXT3_SB(sb)->s_es->s_r_blocks_count);
return (avail << EXT3_BLOCK_SIZE_BITS(sb)); return (avail << EXT3_BLOCK_SIZE_BITS(sb));
} }
...@@ -77,13 +94,13 @@ static void *presto_e3_trans_start(struct presto_file_set *fset, ...@@ -77,13 +94,13 @@ static void *presto_e3_trans_start(struct presto_file_set *fset,
return NULL; return NULL;
} }
avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count; avail_kmlblocks = EXT3_SB(inode->i_sb)->s_es->s_free_blocks_count;
if ( avail_kmlblocks < 3 ) { if ( avail_kmlblocks < 3 ) {
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }
if ( (op != PRESTO_OP_UNLINK && op != PRESTO_OP_RMDIR) if ( (op != KML_OPCODE_UNLINK && op != KML_OPCODE_RMDIR)
&& avail_kmlblocks < 6 ) { && avail_kmlblocks < 6 ) {
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }
...@@ -105,52 +122,71 @@ static void *presto_e3_trans_start(struct presto_file_set *fset, ...@@ -105,52 +122,71 @@ static void *presto_e3_trans_start(struct presto_file_set *fset,
and operations involving the LML records and operations involving the LML records
*/ */
switch (op) { switch (op) {
case PRESTO_OP_TRUNC: case KML_OPCODE_TRUNC:
jblocks = one_path_blks + extra_name_blks + trunc_blks jblocks = one_path_blks + extra_name_blks + trunc_blks
+ EXT3_DELETE_TRANS_BLOCKS; + EXT3_DELETE_TRANS_BLOCKS;
break; break;
case PRESTO_OP_RELEASE: case KML_OPCODE_KML_TRUNC:
/* Hopefully this is a little better, but I'm still mostly
* guessing here. */
/* unlink 1 */
jblocks = extra_name_blks + trunc_blks +
EXT3_DELETE_TRANS_BLOCKS + 2;
/* unlink 2 */
jblocks += extra_name_blks + trunc_blks +
EXT3_DELETE_TRANS_BLOCKS + 2;
/* rename 1 */
jblocks += 2 * extra_path_blks + trunc_blks +
2 * EXT3_DATA_TRANS_BLOCKS + 2 + 3;
/* rename 2 */
jblocks += 2 * extra_path_blks + trunc_blks +
2 * EXT3_DATA_TRANS_BLOCKS + 2 + 3;
break;
case KML_OPCODE_RELEASE:
/* /*
jblocks = one_path_blks + lml_blks + 2*trunc_blks; jblocks = one_path_blks + lml_blks + 2*trunc_blks;
*/ */
jblocks = one_path_blks; jblocks = one_path_blks;
break; break;
case PRESTO_OP_SETATTR: case KML_OPCODE_SETATTR:
jblocks = one_path_blks + trunc_blks + 1 ; jblocks = one_path_blks + trunc_blks + 1 ;
break; break;
case PRESTO_OP_CREATE: case KML_OPCODE_CREATE:
jblocks = one_path_blks + trunc_blks jblocks = one_path_blks + trunc_blks
+ EXT3_DATA_TRANS_BLOCKS + 3 + 2; + EXT3_DATA_TRANS_BLOCKS + 3 + 2;
break; break;
case PRESTO_OP_LINK: case KML_OPCODE_LINK:
jblocks = one_path_blks + trunc_blks jblocks = one_path_blks + trunc_blks
+ EXT3_DATA_TRANS_BLOCKS + 2; + EXT3_DATA_TRANS_BLOCKS + 2;
break; break;
case PRESTO_OP_UNLINK: case KML_OPCODE_UNLINK:
jblocks = one_path_blks + extra_name_blks + trunc_blks jblocks = one_path_blks + extra_name_blks + trunc_blks
+ EXT3_DELETE_TRANS_BLOCKS + 2; + EXT3_DELETE_TRANS_BLOCKS + 2;
break; break;
case PRESTO_OP_SYMLINK: case KML_OPCODE_SYMLINK:
jblocks = one_path_blks + extra_path_blks + trunc_blks jblocks = one_path_blks + extra_path_blks + trunc_blks
+ EXT3_DATA_TRANS_BLOCKS + 5; + EXT3_DATA_TRANS_BLOCKS + 5;
break; break;
case PRESTO_OP_MKDIR: case KML_OPCODE_MKDIR:
jblocks = one_path_blks + trunc_blks jblocks = one_path_blks + trunc_blks
+ EXT3_DATA_TRANS_BLOCKS + 4 + 2; + EXT3_DATA_TRANS_BLOCKS + 4 + 2;
break; break;
case PRESTO_OP_RMDIR: case KML_OPCODE_RMDIR:
jblocks = one_path_blks + extra_name_blks + trunc_blks jblocks = one_path_blks + extra_name_blks + trunc_blks
+ EXT3_DELETE_TRANS_BLOCKS + 1; + EXT3_DELETE_TRANS_BLOCKS + 1;
break; break;
case PRESTO_OP_MKNOD: case KML_OPCODE_MKNOD:
jblocks = one_path_blks + trunc_blks + jblocks = one_path_blks + trunc_blks +
EXT3_DATA_TRANS_BLOCKS + 3 + 2; EXT3_DATA_TRANS_BLOCKS + 3 + 2;
break; break;
case PRESTO_OP_RENAME: case KML_OPCODE_RENAME:
jblocks = one_path_blks + extra_path_blks + trunc_blks + jblocks = one_path_blks + extra_path_blks + trunc_blks +
2 * EXT3_DATA_TRANS_BLOCKS + 2 + 3; 2 * EXT3_DATA_TRANS_BLOCKS + 2 + 3;
break; break;
case PRESTO_OP_WRITE: case KML_OPCODE_WRITE:
jblocks = one_path_blks; jblocks = one_path_blks;
/* add this when we can wrap our transaction with /* add this when we can wrap our transaction with
that of ext3_file_write (ordered writes) that of ext3_file_write (ordered writes)
...@@ -162,7 +198,8 @@ static void *presto_e3_trans_start(struct presto_file_set *fset, ...@@ -162,7 +198,8 @@ static void *presto_e3_trans_start(struct presto_file_set *fset,
return NULL; return NULL;
} }
CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks); CDEBUG(D_JOURNAL, "creating journal handle (%d blocks) for op %d\n",
jblocks, op);
/* journal_start/stop does not do its own locking while updating /* journal_start/stop does not do its own locking while updating
* the handle/transaction information. Hence we create our own * the handle/transaction information. Hence we create our own
* critical section to protect these calls. -SHP * critical section to protect these calls. -SHP
...@@ -173,7 +210,7 @@ static void *presto_e3_trans_start(struct presto_file_set *fset, ...@@ -173,7 +210,7 @@ static void *presto_e3_trans_start(struct presto_file_set *fset,
return handle; return handle;
} }
void presto_e3_trans_commit(struct presto_file_set *fset, void *handle) static void presto_e3_trans_commit(struct presto_file_set *fset, void *handle)
{ {
if ( presto_no_journal(fset) || !handle) if ( presto_no_journal(fset) || !handle)
return; return;
...@@ -184,7 +221,7 @@ void presto_e3_trans_commit(struct presto_file_set *fset, void *handle) ...@@ -184,7 +221,7 @@ void presto_e3_trans_commit(struct presto_file_set *fset, void *handle)
unlock_kernel(); unlock_kernel();
} }
void presto_e3_journal_file_data(struct inode *inode) static void presto_e3_journal_file_data(struct inode *inode)
{ {
#ifdef EXT3_JOURNAL_DATA_FL #ifdef EXT3_JOURNAL_DATA_FL
EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL; EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
...@@ -193,11 +230,56 @@ void presto_e3_journal_file_data(struct inode *inode) ...@@ -193,11 +230,56 @@ void presto_e3_journal_file_data(struct inode *inode)
#endif #endif
} }
/* The logic here is a slightly modified version of ext3/inode.c:block_to_path
*/
static int presto_e3_has_all_data(struct inode *inode)
{
int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb);
int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb);
const long direct_blocks = EXT3_NDIR_BLOCKS,
indirect_blocks = ptrs,
double_blocks = (1 << (ptrs_bits * 2));
long block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
inode->i_sb->s_blocksize_bits;
ENTRY;
if (inode->i_size == 0) {
EXIT;
return 1;
}
if (block < direct_blocks) {
/* No indirect blocks, no problem. */
} else if (block < indirect_blocks + direct_blocks) {
block++;
} else if (block < double_blocks + indirect_blocks + direct_blocks) {
block += 2;
} else if (((block - double_blocks - indirect_blocks - direct_blocks)
>> (ptrs_bits * 2)) < ptrs) {
block += 3;
}
block *= (inode->i_sb->s_blocksize / 512);
CDEBUG(D_CACHE, "Need %ld blocks, have %ld.\n", block, inode->i_blocks);
if (block > inode->i_blocks) {
EXIT;
return 0;
}
EXIT;
return 1;
}
struct journal_ops presto_ext3_journal_ops = { struct journal_ops presto_ext3_journal_ops = {
tr_avail: presto_e3_freespace, .tr_all_data = presto_e3_has_all_data,
tr_start: presto_e3_trans_start, .tr_avail = presto_e3_freespace,
tr_commit: presto_e3_trans_commit, .tr_start = presto_e3_trans_start,
tr_journal_data: presto_e3_journal_file_data .tr_commit = presto_e3_trans_commit,
.tr_journal_data = presto_e3_journal_file_data,
.tr_ilookup = presto_iget_ilookup
}; };
#endif /* CONFIG_EXT3_FS */ #endif /* CONFIG_EXT3_FS */
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* * vim:expandtab:shiftwidth=8:tabstop=8:
* Intermezzo. (C) 1998 Peter J. Braam *
* Intermezzo. (C) 2000 Red Hat, Inc. * Copyright (C) 1998 Peter J. Braam <braam@clusterfs.com>
* Intermezzo. (C) 2000 Los Alamos National Laboratory * Copyright (C) 2000 Red Hat, Inc.
* Intermezzo. (C) 2000 TurboLinux, Inc. * Copyright (C) 2000 Los Alamos National Laboratory
* Intermezzo. (C) 2001 Mountain View Data, Inc. * Copyright (C) 2000 TurboLinux, Inc.
* Copyright (C) 2001 Mountain View Data, 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.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/string.h> #include <linux/string.h>
#ifdef CONFIG_OBDFS_FS #ifdef CONFIG_OBDFS_FS
...@@ -23,9 +41,7 @@ ...@@ -23,9 +41,7 @@
#endif #endif
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#ifdef CONFIG_OBDFS_FS #ifdef CONFIG_OBDFS_FS
...@@ -162,17 +178,17 @@ void presto_obdfs_trans_commit(struct presto_file_set *fset, void *handle) ...@@ -162,17 +178,17 @@ void presto_obdfs_trans_commit(struct presto_file_set *fset, void *handle)
void presto_obdfs_journal_file_data(struct inode *inode) void presto_obdfs_journal_file_data(struct inode *inode)
{ {
#ifdef EXT3_JOURNAL_DATA_FL #ifdef EXT3_JOURNAL_DATA_FL
EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL; inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
#else #else
#warning You must have a facility to enable journaled writes for recovery! #warning You must have a facility to enable journaled writes for recovery!
#endif #endif
} }
struct journal_ops presto_obdfs_journal_ops = { struct journal_ops presto_obdfs_journal_ops = {
tr_avail: presto_obdfs_freespace, .tr_avail = presto_obdfs_freespace,
tr_start: presto_obdfs_trans_start, .tr_start = presto_obdfs_trans_start,
tr_commit: presto_obdfs_trans_commit, .tr_commit = presto_obdfs_trans_commit,
tr_journal_data: presto_obdfs_journal_file_data .tr_journal_data = presto_obdfs_journal_file_data
}; };
#endif #endif
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* * vim:expandtab:shiftwidth=8:tabstop=8:
* Intermezzo. (C) 1998 Peter J. Braam *
* Intermezzo. (C) 2000 Red Hat, Inc. * Copyright (C) 1998 Peter J. Braam <braam@clusterfs.com>
* Intermezzo. (C) 2000 Los Alamos National Laboratory * Copyright (C) 2000 Red Hat, Inc.
* Intermezzo. (C) 2000 TurboLinux, Inc. * Copyright (C) 2000 Los Alamos National Laboratory
* Intermezzo. (C) 2001 Mountain View Data, Inc. * Copyright (C) 2000 TurboLinux, Inc.
* Copyright (C) 2001 Mountain View Data, 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.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/string.h> #include <linux/string.h>
#if 0 #if 0
...@@ -26,9 +44,8 @@ ...@@ -26,9 +44,8 @@
#endif #endif
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE) #if defined(CONFIG_REISERFS_FS) || defined(CONFIG_REISERFS_FS_MODULE)
...@@ -52,9 +69,9 @@ static void *presto_reiserfs_trans_start(struct presto_file_set *fset, ...@@ -52,9 +69,9 @@ static void *presto_reiserfs_trans_start(struct presto_file_set *fset,
__u32 avail_kmlblocks; __u32 avail_kmlblocks;
struct reiserfs_transaction_handle *th ; struct reiserfs_transaction_handle *th ;
PRESTO_ALLOC(th, struct reiserfs_transaction_handle *, sizeof(*th)); PRESTO_ALLOC(th, sizeof(*th));
if (!th) { if (!th) {
printk("presto: No memory for trans handle\n"); CERROR("presto: No memory for trans handle\n");
return NULL; return NULL;
} }
...@@ -81,36 +98,44 @@ static void *presto_reiserfs_trans_start(struct presto_file_set *fset, ...@@ -81,36 +98,44 @@ static void *presto_reiserfs_trans_start(struct presto_file_set *fset,
CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks); CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
lock_kernel(); lock_kernel();
//journal_begin(th, inode->i_sb, jblocks); journal_begin(th, inode->i_sb, jblocks);
unlock_kernel(); unlock_kernel();
return th; return th;
} }
void presto_reiserfs_trans_commit(struct presto_file_set *fset, void *handle) static void presto_reiserfs_trans_commit(struct presto_file_set *fset,
void *handle)
{ {
int jblocks; int jblocks;
jblocks = 3 + JOURNAL_PER_BALANCE_CNT * 4; jblocks = 3 + JOURNAL_PER_BALANCE_CNT * 4;
lock_kernel(); lock_kernel();
//journal_end(handle, fset->fset_cache->cache_sb, jblocks); journal_end(handle, fset->fset_cache->cache_sb, jblocks);
unlock_kernel(); unlock_kernel();
PRESTO_FREE(handle, sizeof(struct reiserfs_transaction_handle)); PRESTO_FREE(handle, sizeof(struct reiserfs_transaction_handle));
} }
void presto_reiserfs_journal_file_data(struct inode *inode) static void presto_reiserfs_journal_file_data(struct inode *inode)
{ {
#ifdef EXT3_JOURNAL_DATA_FL #ifdef EXT3_JOURNAL_DATA_FL
EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL; inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
#else #else
#warning You must have a facility to enable journaled writes for recovery! #warning You must have a facility to enable journaled writes for recovery!
#endif #endif
} }
static int presto_reiserfs_has_all_data(struct inode *inode)
{
BUG();
return 0;
}
struct journal_ops presto_reiserfs_journal_ops = { struct journal_ops presto_reiserfs_journal_ops = {
tr_avail: presto_reiserfs_freespace, .tr_all_data = presto_reiserfs_has_all_data,
tr_start: presto_reiserfs_trans_start, .tr_avail = presto_reiserfs_freespace,
tr_commit: presto_reiserfs_trans_commit, .tr_start = presto_reiserfs_trans_start,
tr_journal_data: presto_reiserfs_journal_file_data .tr_commit = presto_reiserfs_trans_commit,
.tr_journal_data = presto_reiserfs_journal_file_data
}; };
#endif #endif
......
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
* Copyright (C) 1998 Peter J. Braam <braam@clusterfs.com>
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2000 Los Alamos National Laboratory
* Copyright (C) 2000 TurboLinux, Inc.
* Copyright (C) 2001 Mountain View Data, Inc.
* Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
*
* 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.
*/
#include <linux/types.h>
#include <linux/param.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#if defined(CONFIG_TMPFS)
#include <linux/jbd.h>
#if defined(CONFIG_EXT3)
#include <linux/ext3_fs.h>
#include <linux/ext3_jbd.h>
#endif
#endif
#include <linux/intermezzo_fs.h>
#include <linux/intermezzo_psdev.h>
#if defined(CONFIG_TMPFS)
/* space requirements:
presto_do_truncate:
used to truncate the KML forward to next fset->chunksize boundary
- zero partial block
- update inode
presto_write_record:
write header (< one block)
write one path (< MAX_PATHLEN)
possibly write another path (< MAX_PATHLEN)
write suffix (< one block)
presto_update_last_rcvd
write one block
*/
static loff_t presto_tmpfs_freespace(struct presto_cache *cache,
struct super_block *sb)
{
return (1<<30);
}
/* start the filesystem journal operations */
static void *presto_tmpfs_trans_start(struct presto_file_set *fset,
struct inode *inode,
int op)
{
return (void *)1;
}
static void presto_tmpfs_trans_commit(struct presto_file_set *fset, void *handle)
{
return;
}
static void presto_tmpfs_journal_file_data(struct inode *inode)
{
return;
}
/* The logic here is a slightly modified version of ext3/inode.c:block_to_path
*/
static int presto_tmpfs_has_all_data(struct inode *inode)
{
return 0;
}
struct journal_ops presto_tmpfs_journal_ops = {
tr_all_data: presto_tmpfs_has_all_data,
tr_avail: presto_tmpfs_freespace,
tr_start: presto_tmpfs_trans_start,
tr_commit: presto_tmpfs_trans_commit,
tr_journal_data: presto_tmpfs_journal_file_data,
tr_ilookup: presto_tmpfs_ilookup,
tr_add_ilookup: presto_add_ilookup_dentry
};
#endif /* CONFIG_EXT3_FS */
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* * vim:expandtab:shiftwidth=8:tabstop=8:
* * Intermezzo. (C) 1998 Peter J. Braam *
* */ * Copyright (C) 1998 Peter J. Braam <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.
*/
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp_lock.h>
#include <asm/segment.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/string.h> #include <linux/string.h>
#if 0
/* XFS Support not there yet */
#ifdef CONFIG_FS_XFS #ifdef CONFIG_FS_XFS
#include <linux/xfs_fs.h> #include <linux/xfs_fs.h>
#endif #endif
#include <linux/intermezzo_fs.h> #include <linux/intermezzo_fs.h>
#include <linux/intermezzo_upcall.h>
#include <linux/intermezzo_psdev.h> #include <linux/intermezzo_psdev.h>
#include <linux/intermezzo_kml.h>
#include <linux/intermezzo_journal.h> #include <linux/intermezzo_journal.h>
#if 0 #if 0
...@@ -118,18 +136,27 @@ static void presto_xfs_trans_commit(struct presto_file_set *fset, void *handle) ...@@ -118,18 +136,27 @@ static void presto_xfs_trans_commit(struct presto_file_set *fset, void *handle)
xfs_trans_stop(handle); xfs_trans_stop(handle);
} }
void presto_xfs_journal_file_data(struct inode *inode) static void presto_xfs_journal_file_data(struct inode *inode)
{ {
return; return;
} }
static int presto_xfs_has_all_data(struct inode *inode)
{
BUG();
return 0;
}
struct journal_ops presto_xfs_journal_ops = { struct journal_ops presto_xfs_journal_ops = {
tr_avail: presto_xfs_freespace, .tr_all_data = presto_xfs_has_all_data,
tr_start: presto_xfs_trans_start, .tr_avail = presto_xfs_freespace,
tr_commit: presto_xfs_trans_commit, .tr_start = presto_xfs_trans_start,
tr_journal_data: presto_xfs_journal_file_data .tr_commit = presto_xfs_trans_commit,
.tr_journal_data = presto_xfs_journal_file_data
}; };
#endif /* CONFIG_XFS_FS */ #endif
#endif /* CONFIG_XFS_FS */
This diff is collapsed.
This diff is collapsed.
/* /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* * vim:expandtab:shiftwidth=8:tabstop=8:
* *
* Copyright (C) 2000 Stelias Computing, Inc. * Copyright (C) 2000 Stelias Computing, Inc.
* Copyright (C) 2000 Red Hat, Inc. * Copyright (C) 2000 Red Hat, Inc.
...@@ -7,6 +7,22 @@ ...@@ -7,6 +7,22 @@
* *
* Extended Attribute Support * Extended Attribute Support
* Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, Inc. * Copyright (C) 2001 Shirish H. Phatak, Tacit Networks, 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.
*
*/ */
#include <stdarg.h> #include <stdarg.h>
...@@ -20,9 +36,10 @@ ...@@ -20,9 +36,10 @@
#include <linux/ext2_fs.h> #include <linux/ext2_fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/time.h> #include <linux/sched.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/init.h> #include <linux/init.h>
#define __NO_VERSION__ #define __NO_VERSION__
...@@ -149,6 +166,16 @@ void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type) ...@@ -149,6 +166,16 @@ void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type)
FDEBUG(D_SUPER, "ops at %p\n", ops); FDEBUG(D_SUPER, "ops at %p\n", ops);
} }
if ( strlen(cache_type) == strlen("tmpfs") &&
memcmp(cache_type, "tmpfs", strlen("tmpfs")) == 0 ) {
#if defined(CONFIG_TMPFS)
ops->o_trops = &presto_tmpfs_journal_ops;
#else
ops->o_trops = NULL;
#endif
FDEBUG(D_SUPER, "ops at %p\n", ops);
}
if ( strlen(cache_type) == strlen("reiserfs") && if ( strlen(cache_type) == strlen("reiserfs") &&
memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) { memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
#if 0 #if 0
...@@ -163,7 +190,7 @@ void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type) ...@@ -163,7 +190,7 @@ void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type)
if ( strlen(cache_type) == strlen("xfs") && if ( strlen(cache_type) == strlen("xfs") &&
memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) { memcmp(cache_type, "xfs", strlen("xfs")) == 0 ) {
#if 0 #if 0
//#if defined(CONFIG_XFS_FS) || defined (CONFIG_XFS_FS_MODULE) /*#if defined(CONFIG_XFS_FS) || defined (CONFIG_XFS_FS_MODULE) */
ops->o_trops = &presto_xfs_journal_ops; ops->o_trops = &presto_xfs_journal_ops;
#else #else
ops->o_trops = NULL; ops->o_trops = NULL;
...@@ -206,6 +233,13 @@ struct filter_fs *filter_get_filter_fs(const char *cache_type) ...@@ -206,6 +233,13 @@ struct filter_fs *filter_get_filter_fs(const char *cache_type)
ops = &filter_oppar[FILTER_FS_EXT3]; ops = &filter_oppar[FILTER_FS_EXT3];
FDEBUG(D_SUPER, "ops at %p\n", ops); FDEBUG(D_SUPER, "ops at %p\n", ops);
} }
if ( strlen(cache_type) == strlen("tmpfs") &&
memcmp(cache_type, "tmpfs", strlen("tmpfs")) == 0 ) {
ops = &filter_oppar[FILTER_FS_TMPFS];
FDEBUG(D_SUPER, "ops at %p\n", ops);
}
if ( strlen(cache_type) == strlen("reiserfs") && if ( strlen(cache_type) == strlen("reiserfs") &&
memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) { memcmp(cache_type, "reiserfs", strlen("reiserfs")) == 0 ) {
ops = &filter_oppar[FILTER_FS_REISERFS]; ops = &filter_oppar[FILTER_FS_REISERFS];
...@@ -218,7 +252,7 @@ struct filter_fs *filter_get_filter_fs(const char *cache_type) ...@@ -218,7 +252,7 @@ struct filter_fs *filter_get_filter_fs(const char *cache_type)
} }
if (ops == NULL) { if (ops == NULL) {
printk("prepare to die: unrecognized cache type for Filter\n"); CERROR("prepare to die: unrecognized cache type for Filter\n");
} }
return ops; return ops;
FEXIT; FEXIT;
...@@ -342,7 +376,7 @@ void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct i ...@@ -342,7 +376,7 @@ void filter_setup_dir_ops(struct filter_fs *cache, struct inode *inode, struct i
memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops)); memcpy(filter_c2udfops(cache), cache_fops, sizeof(*cache_fops));
/* unconditional filtering operations */ /* unconditional filtering operations */
filter_c2udfops(cache)->open = filter_fops->open; filter_c2udfops(cache)->ioctl = filter_fops->ioctl;
FEXIT; FEXIT;
} }
...@@ -373,7 +407,7 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct ...@@ -373,7 +407,7 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct
memcpy(pr_iops, cache_iops, sizeof(*cache_iops)); memcpy(pr_iops, cache_iops, sizeof(*cache_iops));
/* copy dir fops */ /* copy dir fops */
printk("*** cache file ops at %p\n", cache_fops); CERROR("*** cache file ops at %p\n", cache_fops);
memcpy(filter_c2uffops(cache), cache_fops, sizeof(*cache_fops)); memcpy(filter_c2uffops(cache), cache_fops, sizeof(*cache_fops));
/* assign */ /* assign */
...@@ -382,6 +416,8 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct ...@@ -382,6 +416,8 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct
pr_iops->setattr = filter_iops->setattr; pr_iops->setattr = filter_iops->setattr;
if (cache_iops->getattr) if (cache_iops->getattr)
pr_iops->getattr = filter_iops->getattr; pr_iops->getattr = filter_iops->getattr;
/* XXX Should this be conditional rmr ? */
pr_iops->permission = filter_iops->permission;
#ifdef CONFIG_FS_EXT_ATTR #ifdef CONFIG_FS_EXT_ATTR
/* For now we assume that posix acls are handled through extended /* For now we assume that posix acls are handled through extended
* attributes. If this is not the case, we must explicitly trap and * attributes. If this is not the case, we must explicitly trap and
...@@ -396,6 +432,7 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct ...@@ -396,6 +432,7 @@ void filter_setup_file_ops(struct filter_fs *cache, struct inode *inode, struct
filter_c2uffops(cache)->open = filter_fops->open; filter_c2uffops(cache)->open = filter_fops->open;
filter_c2uffops(cache)->release = filter_fops->release; filter_c2uffops(cache)->release = filter_fops->release;
filter_c2uffops(cache)->write = filter_fops->write; filter_c2uffops(cache)->write = filter_fops->write;
filter_c2uffops(cache)->ioctl = filter_fops->ioctl;
FEXIT; FEXIT;
} }
...@@ -454,7 +491,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache, ...@@ -454,7 +491,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache,
filter_dop, sizeof(*filter_dop)); filter_dop, sizeof(*filter_dop));
if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){ if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
printk("WARNING: filter overriding revalidation!\n"); CERROR("WARNING: filter overriding revalidation!\n");
} }
return; return;
} }
This diff is collapsed.
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
* Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
* Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
*
* 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.
*
* Manage RCVD records for clients in the kernel
*
*/
#define __NO_VERSION__
#include <linux/module.h>
#include <stdarg.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/intermezzo_fs.h>
/*
* this file contains a hash table of replicators/clients for a
* fileset. It allows fast lookup and update of reintegration status
*/
struct izo_offset_rec {
struct list_head or_list;
char or_uuid[16];
loff_t or_offset;
};
#define RCACHE_BITS 8
#define RCACHE_SIZE (1 << RCACHE_BITS)
#define RCACHE_MASK (RCACHE_SIZE - 1)
static struct list_head *
izo_rep_cache(void)
{
int i;
struct list_head *cache;
PRESTO_ALLOC(cache, sizeof(struct list_head) * RCACHE_SIZE);
if (cache == NULL) {
CERROR("intermezzo-fatal: no memory for replicator cache\n");
return NULL;
}
memset(cache, 0, sizeof(struct list_head) * RCACHE_SIZE);
for (i = 0; i < RCACHE_SIZE; i++)
INIT_LIST_HEAD(&cache[i]);
return cache;
}
static struct list_head *
izo_rep_hash(struct list_head *cache, char *uuid)
{
return &cache[(RCACHE_MASK & uuid[1])];
}
static void
izo_rep_cache_clean(struct presto_file_set *fset)
{
int i;
struct list_head *bucket;
struct list_head *tmp;
if (fset->fset_clients == NULL)
return;
for (i = 0; i < RCACHE_SIZE; i++) {
tmp = bucket = &fset->fset_clients[i];
tmp = tmp->next;
while (tmp != bucket) {
struct izo_offset_rec *offrec;
tmp = tmp->next;
list_del(tmp);
offrec = list_entry(tmp, struct izo_offset_rec,
or_list);
PRESTO_FREE(offrec, sizeof(struct izo_offset_rec));
}
}
}
struct izo_offset_rec *
izo_rep_cache_find(struct presto_file_set *fset, char *uuid)
{
struct list_head *buck = izo_rep_hash(fset->fset_clients, uuid);
struct list_head *tmp = buck;
struct izo_offset_rec *rec = NULL;
while ( (tmp = tmp->next) != buck ) {
rec = list_entry(tmp, struct izo_offset_rec, or_list);
if ( memcmp(rec->or_uuid, uuid, sizeof(rec->or_uuid)) == 0 )
return rec;
}
return NULL;
}
static int
izo_rep_cache_add(struct presto_file_set *fset, struct izo_rcvd_rec *rec,
loff_t offset)
{
struct izo_offset_rec *offrec;
if (izo_rep_cache_find(fset, rec->lr_uuid)) {
CERROR("izo: duplicate client entry %s off %Ld\n",
fset->fset_name, offset);
return -EINVAL;
}
PRESTO_ALLOC(offrec, sizeof(*offrec));
if (offrec == NULL) {
CERROR("izo: cannot allocate offrec\n");
return -ENOMEM;
}
memcpy(offrec->or_uuid, rec->lr_uuid, sizeof(rec->lr_uuid));
offrec->or_offset = offset;
list_add(&offrec->or_list,
izo_rep_hash(fset->fset_clients, rec->lr_uuid));
return 0;
}
int
izo_rep_cache_init(struct presto_file_set *fset)
{
struct izo_rcvd_rec rec;
loff_t offset = 0, last_offset = 0;
fset->fset_clients = izo_rep_cache();
if (fset->fset_clients == NULL) {
CERROR("Error initializing client cache\n");
return -ENOMEM;
}
while ( presto_fread(fset->fset_rcvd.fd_file, (char *)&rec,
sizeof(rec), &offset) == sizeof(rec) ) {
int rc;
if ((rc = izo_rep_cache_add(fset, &rec, last_offset)) < 0) {
izo_rep_cache_clean(fset);
return rc;
}
last_offset = offset;
}
return 0;
}
/*
* Return local last_rcvd record for the client. Update or create
* if necessary.
*
* XXX: After this call, any -EINVAL from izo_rcvd_get is a real error.
*/
int
izo_repstatus(struct presto_file_set *fset, __u64 client_kmlsize,
struct izo_rcvd_rec *lr_client, struct izo_rcvd_rec *lr_server)
{
int rc;
rc = izo_rcvd_get(lr_server, fset, lr_client->lr_uuid);
if (rc < 0 && rc != -EINVAL) {
return rc;
}
/* client is new or has been reset. */
if (rc < 0 || (client_kmlsize == 0 && lr_client->lr_remote_offset == 0)) {
memset(lr_server, 0, sizeof(*lr_server));
memcpy(lr_server->lr_uuid, lr_client->lr_uuid, sizeof(lr_server->lr_uuid));
rc = izo_rcvd_write(fset, lr_server);
if (rc < 0)
return rc;
}
/* update intersync */
rc = izo_upc_repstatus(presto_f2m(fset), fset->fset_name, lr_server);
return rc;
}
loff_t
izo_rcvd_get(struct izo_rcvd_rec *rec, struct presto_file_set *fset, char *uuid)
{
struct izo_offset_rec *offrec;
struct izo_rcvd_rec tmprec;
loff_t offset;
offrec = izo_rep_cache_find(fset, uuid);
if (offrec == NULL) {
CDEBUG(D_SPECIAL, "izo_get_rcvd: uuid not in hash.\n");
return -EINVAL;
}
offset = offrec->or_offset;
if (rec == NULL)
return offset;
if (presto_fread(fset->fset_rcvd.fd_file, (char *)&tmprec,
sizeof(tmprec), &offset) != sizeof(tmprec)) {
CERROR("izo_get_rcvd: Unable to read from last_rcvd file offset "
"%Lu\n", offset);
return -EIO;
}
memcpy(rec->lr_uuid, tmprec.lr_uuid, sizeof(tmprec.lr_uuid));
rec->lr_remote_recno = le64_to_cpu(tmprec.lr_remote_recno);
rec->lr_remote_offset = le64_to_cpu(tmprec.lr_remote_offset);
rec->lr_local_recno = le64_to_cpu(tmprec.lr_local_recno);
rec->lr_local_offset = le64_to_cpu(tmprec.lr_local_offset);
rec->lr_last_ctime = le64_to_cpu(tmprec.lr_last_ctime);
return offrec->or_offset;
}
/* Try to lookup the UUID in the hash. Insert it if it isn't found. Write the
* data to the file.
*
* Returns the offset of the beginning of the record in the last_rcvd file. */
loff_t
izo_rcvd_write(struct presto_file_set *fset, struct izo_rcvd_rec *rec)
{
struct izo_offset_rec *offrec;
loff_t offset, rc;
ENTRY;
offrec = izo_rep_cache_find(fset, rec->lr_uuid);
if (offrec == NULL) {
/* I don't think it should be possible for an entry to be not in
* the hash table without also having an invalid offset, but we
* handle it gracefully regardless. */
write_lock(&fset->fset_rcvd.fd_lock);
offset = fset->fset_rcvd.fd_offset;
fset->fset_rcvd.fd_offset += sizeof(*rec);
write_unlock(&fset->fset_rcvd.fd_lock);
rc = izo_rep_cache_add(fset, rec, offset);
if (rc < 0) {
EXIT;
return rc;
}
} else
offset = offrec->or_offset;
rc = presto_fwrite(fset->fset_rcvd.fd_file, (char *)rec, sizeof(*rec),
&offset);
if (rc == sizeof(*rec))
/* presto_fwrite() advances 'offset' */
rc = offset - sizeof(*rec);
EXIT;
return rc;
}
loff_t
izo_rcvd_upd_remote(struct presto_file_set *fset, char * uuid, __u64 remote_recno,
__u64 remote_offset)
{
struct izo_rcvd_rec rec;
loff_t rc;
ENTRY;
rc = izo_rcvd_get(&rec, fset, uuid);
if (rc < 0)
return rc;
rec.lr_remote_recno = remote_recno;
rec.lr_remote_offset = remote_offset;
rc = izo_rcvd_write(fset, &rec);
EXIT;
if (rc < 0)
return rc;
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
#ifndef __FILTER_H_ #ifndef __FILTER_H_
#define __FILTER_H_ 1 #define __FILTER_H_ 1
...@@ -59,12 +63,13 @@ struct filter_fs { ...@@ -59,12 +63,13 @@ struct filter_fs {
struct snapshot_ops *o_snops; struct snapshot_ops *o_snops;
}; };
#define FILTER_FS_TYPES 5 #define FILTER_FS_TYPES 6
#define FILTER_FS_EXT2 0 #define FILTER_FS_EXT2 0
#define FILTER_FS_EXT3 1 #define FILTER_FS_EXT3 1
#define FILTER_FS_REISERFS 2 #define FILTER_FS_REISERFS 2
#define FILTER_FS_XFS 3 #define FILTER_FS_XFS 3
#define FILTER_FS_OBDFS 4 #define FILTER_FS_OBDFS 4
#define FILTER_FS_TMPFS 5
extern struct filter_fs filter_oppar[FILTER_FS_TYPES]; extern struct filter_fs filter_oppar[FILTER_FS_TYPES];
struct filter_fs *filter_get_filter_fs(const char *cache_type); struct filter_fs *filter_get_filter_fs(const char *cache_type);
...@@ -96,7 +101,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache, struct dentry_operations * ...@@ -96,7 +101,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache, struct dentry_operations *
#define PRESTO_DEBUG #define PRESTO_DEBUG
#ifdef PRESTO_DEBUG #ifdef PRESTO_DEBUG
/* debugging masks */ /* debugging masks */
#define D_SUPER 1 /* print results returned by Venus */ #define D_SUPER 1
#define D_INODE 2 /* print entry and exit into procedure */ #define D_INODE 2 /* print entry and exit into procedure */
#define D_FILE 4 #define D_FILE 4
#define D_CACHE 8 /* cache debugging */ #define D_CACHE 8 /* cache debugging */
......
This diff is collapsed.
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
#ifndef __PRESTO_PSDEV_H #ifndef __PRESTO_PSDEV_H
#define __PRESTO_PSDEV_H #define __PRESTO_PSDEV_H
#ifdef PRESTO_DEVEL #define MAX_CHANNEL 16
# define PRESTO_FS_NAME "izofs" #define PROCNAME_SIZE 32
# define PRESTO_PSDEV_NAME "/dev/izo" #include <linux/smp_lock.h>
# define PRESTO_PSDEV_MAJOR 186 #include <linux/smp_lock.h>
#else
# define PRESTO_FS_NAME "InterMezzo"
# define PRESTO_PSDEV_NAME "/dev/intermezzo"
# define PRESTO_PSDEV_MAJOR 185
#endif
#define MAX_PRESTODEV 16
#include <linux/version.h> #include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) /* represents state of an instance reached with /dev/intermezzo */
#define wait_queue_head_t struct wait_queue *
#define DECLARE_WAITQUEUE(name,task) \
struct wait_queue name = { task, NULL }
#define init_waitqueue_head(arg)
#else
#ifndef __initfunc
#define __initfunc(arg) arg
#endif
#endif
/* represents state of a /dev/presto */
/* communication pending & processing queues */ /* communication pending & processing queues */
struct upc_comm { struct upc_channel {
unsigned int uc_seq; unsigned int uc_seq;
wait_queue_head_t uc_waitq; /* Lento wait queue */ wait_queue_head_t uc_waitq; /* Lento wait queue */
struct list_head uc_pending; struct list_head uc_pending;
struct list_head uc_processing; struct list_head uc_processing;
spinlock_t uc_lock;
int uc_pid; /* Lento's pid */ int uc_pid; /* Lento's pid */
int uc_hard; /* allows signals during upcalls */ int uc_hard; /* allows signals during upcalls */
int uc_no_filter; int uc_no_filter;
...@@ -43,15 +28,15 @@ struct upc_comm { ...@@ -43,15 +28,15 @@ struct upc_comm {
long uc_errorval; /* for testing I/O failures */ long uc_errorval; /* for testing I/O failures */
struct list_head uc_cache_list; struct list_head uc_cache_list;
int uc_minor; int uc_minor;
char * uc_devname;
}; };
#define ISLENTO(minor) (current->pid == upc_comms[minor].uc_pid \ #define ISLENTO(minor) (current->pid == izo_channels[minor].uc_pid \
|| current->parent->pid == upc_comms[minor].uc_pid) || current->real_parent->pid == izo_channels[minor].uc_pid \
|| current->real_parent->real_parent->pid == izo_channels[minor].uc_pid)
extern struct upc_comm upc_comms[MAX_PRESTODEV]; extern struct upc_channel izo_channels[MAX_CHANNEL];
/* messages between presto filesystem in kernel and Venus */ /* message types between presto filesystem in kernel */
#define REQ_READ 1 #define REQ_READ 1
#define REQ_WRITE 2 #define REQ_WRITE 2
#define REQ_ASYNC 4 #define REQ_ASYNC 4
...@@ -60,10 +45,10 @@ extern struct upc_comm upc_comms[MAX_PRESTODEV]; ...@@ -60,10 +45,10 @@ extern struct upc_comm upc_comms[MAX_PRESTODEV];
struct upc_req { struct upc_req {
struct list_head rq_chain; struct list_head rq_chain;
caddr_t rq_data; caddr_t rq_data;
u_short rq_flags; int rq_flags;
u_short rq_bufsize; int rq_bufsize;
u_short rq_rep_size; int rq_rep_size;
u_short rq_opcode; /* copied from data to save lookup */ int rq_opcode; /* copied from data to save lookup */
int rq_unique; int rq_unique;
wait_queue_head_t rq_sleep; /* process' wait queue */ wait_queue_head_t rq_sleep; /* process' wait queue */
unsigned long rq_posttime; unsigned long rq_posttime;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment