Commit d03480a1 authored by Linus Torvalds's avatar Linus Torvalds

Remove intermezzo, per instructions from Peter Braam.

parent b188bcda
#
# Makefile 1.00 Peter Braam <braam@clusterfs.com>
#
obj-$(CONFIG_INTERMEZZO_FS) += intermezzo.o
intermezzo-objs := cache.o dcache.o dir.o ext_attr.o file.o fileset.o \
inode.o journal.o journal_ext2.o journal_ext3.o \
journal_obdfs.o journal_reiserfs.o journal_tmpfs.o journal_xfs.o \
kml_reint.o kml_unpack.o methods.o presto.o psdev.o replicator.o \
super.o sysctl.o upcall.o vfs.o
/* -*- 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 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.
*/
#include <linux/module.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include "intermezzo_fs.h"
#include "intermezzo_psdev.h"
/*
This file contains the routines associated with managing a
cache of files for InterMezzo. These caches have two reqs:
- need to be found fast so they are hashed by the device,
with an attempt to have collision chains of length 1.
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 */
#define CACHES_BITS 8
#define CACHES_SIZE (1 << CACHES_BITS)
#define CACHES_MASK CACHES_SIZE - 1
static struct list_head presto_caches[CACHES_SIZE];
static inline int presto_cache_hash(struct super_block *s)
{
return (CACHES_MASK) & ((unsigned long)s >> L1_CACHE_SHIFT);
}
inline void presto_cache_add(struct presto_cache *cache)
{
list_add(&cache->cache_chain,
&presto_caches[presto_cache_hash(cache->cache_sb)]);
}
inline void presto_cache_init_hash(void)
{
int i;
for ( i = 0; i < CACHES_SIZE; i++ ) {
INIT_LIST_HEAD(&presto_caches[i]);
}
}
int izo_ioctl_packlen(struct izo_ioctl_data *data)
{
int len = sizeof(struct izo_ioctl_data);
len += size_round(data->ioc_inllen1);
len += size_round(data->ioc_inllen2);
return len;
}
/* map a device to a cache */
struct presto_cache *presto_cache_find(struct super_block *s)
{
struct presto_cache *cache;
struct list_head *lh, *tmp;
lh = tmp = &(presto_caches[presto_cache_hash(s)]);
while ( (tmp = lh->next) != lh ) {
cache = list_entry(tmp, struct presto_cache, cache_chain);
if (cache->cache_sb == s)
return cache;
}
return NULL;
}
/* map an inode to a cache */
struct presto_cache *presto_get_cache(struct inode *inode)
{
struct presto_cache *cache;
ENTRY;
/* find the correct presto_cache here, based on the device */
cache = presto_cache_find(inode->i_sb);
if ( !cache ) {
CERROR("WARNING: no presto cache for %s, ino %ld\n",
inode->i_sb->s_id, inode->i_ino);
EXIT;
return NULL;
}
EXIT;
return cache;
}
/* another debugging routine: check fs is InterMezzo fs */
int presto_ispresto(struct inode *inode)
{
struct presto_cache *cache;
if ( !inode )
return 0;
cache = presto_get_cache(inode);
if ( !cache )
return 0;
return inode->i_sb == cache->cache_sb;
}
/* setup a cache structure when we need one */
struct presto_cache *presto_cache_init(void)
{
struct presto_cache *cache;
PRESTO_ALLOC(cache, sizeof(struct presto_cache));
if ( cache ) {
memset(cache, 0, sizeof(struct presto_cache));
INIT_LIST_HEAD(&cache->cache_chain);
INIT_LIST_HEAD(&cache->cache_fset_list);
cache->cache_lock = SPIN_LOCK_UNLOCKED;
cache->cache_reserved = 0;
}
return cache;
}
/* free a cache structure and all of the memory it is pointing to */
inline void presto_free_cache(struct presto_cache *cache)
{
if (!cache)
return;
list_del(&cache->cache_chain);
if (cache->cache_sb && cache->cache_sb->s_root &&
presto_d2d(cache->cache_sb->s_root)) {
kmem_cache_free(presto_dentry_slab,
presto_d2d(cache->cache_sb->s_root));
cache->cache_sb->s_root->d_fsdata = NULL;
}
PRESTO_FREE(cache, sizeof(struct presto_cache));
}
int presto_reserve_space(struct presto_cache *cache, loff_t req)
{
struct filter_fs *filter;
loff_t avail;
struct super_block *sb = cache->cache_sb;
filter = cache->cache_filter;
if (!filter ) {
EXIT;
return 0;
}
if (!filter->o_trops ) {
EXIT;
return 0;
}
if (!filter->o_trops->tr_avail ) {
EXIT;
return 0;
}
spin_lock(&cache->cache_lock);
avail = filter->o_trops->tr_avail(cache, sb);
CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
(long) (cache->cache_reserved + req));
CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
if (req + cache->cache_reserved > avail) {
spin_unlock(&cache->cache_lock);
EXIT;
return -ENOSPC;
}
cache->cache_reserved += req;
spin_unlock(&cache->cache_lock);
EXIT;
return 0;
}
void presto_release_space(struct presto_cache *cache, loff_t req)
{
CDEBUG(D_SUPER, "ESC::%ld ---> %ld \n", (long) cache->cache_reserved,
(long) (cache->cache_reserved - req));
spin_lock(&cache->cache_lock);
cache->cache_reserved -= req;
spin_unlock(&cache->cache_lock);
}
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 Tacit Networks, Inc.
* Author: Shirish H. Phatak <shirish@tacitnetworks.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.
*
* Extended attribute handling for presto.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/segment.h>
#include "intermezzo_fs.h"
#include "intermezzo_psdev.h"
#ifdef CONFIG_FS_EXT_ATTR
#include <linux/ext_attr.h>
extern inline void presto_debug_fail_blkdev(struct presto_file_set *fset,
unsigned long value);
/* VFS interface */
/* XXX! Fixme test for user defined attributes */
int presto_set_ext_attr(struct inode *inode,
const char *name, void *buffer,
size_t buffer_len, int flags)
{
int error;
struct presto_cache *cache;
struct presto_file_set *fset;
struct lento_vfs_context info;
struct dentry *dentry;
int minor = presto_i2m(inode);
char *buf = NULL;
ENTRY;
if (minor < 0) {
EXIT;
return -1;
}
if ( ISLENTO(minor) ) {
EXIT;
return -EINVAL;
}
/* BAD...vfs should really pass down the dentry to use, especially
* since every other operation in iops does. But for now
* we do a reverse mapping from inode to the first dentry
*/
if (list_empty(&inode->i_dentry)) {
CERROR("No alias for inode %d\n", (int) inode->i_ino);
EXIT;
return -EINVAL;
}
dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
error = presto_prep(dentry, &cache, &fset);
if ( error ) {
EXIT;
return error;
}
if ((buffer != NULL) && (buffer_len != 0)) {
/* If buffer is a user space pointer copy it to kernel space
* and reset the flag. We do this since the journal functions need
* access to the contents of the buffer, and the file system
* does not care. When we actually invoke the function, we remove
* the EXT_ATTR_FLAG_USER flag.
*
* XXX:Check if the "fs does not care" assertion is always true -SHP
* (works for ext3)
*/
if (flags & EXT_ATTR_FLAG_USER) {
PRESTO_ALLOC(buf, buffer_len);
if (!buf) {
CERROR("InterMezzo: out of memory!!!\n");
return -ENOMEM;
}
error = copy_from_user(buf, buffer, buffer_len);
if (error)
return -EFAULT;
} else
buf = buffer;
} else
buf = buffer;
if ( presto_get_permit(inode) < 0 ) {
EXIT;
if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
PRESTO_FREE(buf, buffer_len);
return -EROFS;
}
/* Simulate presto_setup_info */
memset(&info, 0, sizeof(info));
/* For now redundant..but we keep it around just in case */
info.flags = LENTO_FL_IGNORE_TIME;
if (!ISLENTO(cache->cache_psdev->uc_minor))
info.flags |= LENTO_FL_KML;
/* We pass in the kernel space pointer and reset the
* EXT_ATTR_FLAG_USER flag.
* See comments above.
*/
/* Note that mode is already set by VFS so we send in a NULL */
error = presto_do_set_ext_attr(fset, dentry, name, buf,
buffer_len, flags & ~EXT_ATTR_FLAG_USER,
NULL, &info);
presto_put_permit(inode);
if (buffer_len && (flags & EXT_ATTR_FLAG_USER))
PRESTO_FREE(buf, buffer_len);
EXIT;
return error;
}
/* Lento Interface */
/* XXX: ignore flags? We should be forcing these operations through? -SHP*/
int lento_set_ext_attr(const char *path, const char *name,
void *buffer, size_t buffer_len, int flags, mode_t mode,
struct lento_vfs_context *info)
{
int error;
char * pathname;
struct nameidata nd;
struct dentry *dentry;
struct presto_file_set *fset;
ENTRY;
lock_kernel();
pathname=getname(path);
error = PTR_ERR(pathname);
if (IS_ERR(pathname)) {
EXIT;
goto exit;
}
/* Note that ext_attrs apply to both files and directories..*/
error=presto_walk(pathname,&nd);
if (error)
goto exit;
dentry = nd.dentry;
fset = presto_fset(dentry);
error = -EINVAL;
if ( !fset ) {
CERROR("No fileset!\n");
EXIT;
goto exit_dentry;
}
if (buffer==NULL) buffer_len=0;
error = presto_do_set_ext_attr(fset, dentry, name, buffer,
buffer_len, flags, &mode, info);
exit_dentry:
path_release(&nd);
exit_path:
putname(pathname);
exit:
unlock_kernel();
return error;
}
#endif /*CONFIG_FS_EXT_ATTR*/
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) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
* Michael Callahan <callahan@maths.ox.ac.uk>
* Copyright (C) 1999 Carnegie Mellon University
* Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu>
*
* 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
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/segment.h>
#include "intermezzo_fs.h"
#include "intermezzo_psdev.h"
extern void presto_free_cache(struct presto_cache *);
void presto_set_ops(struct inode *inode, struct filter_fs *filter)
{
ENTRY;
if (!inode || is_bad_inode(inode))
return;
if (S_ISREG(inode->i_mode)) {
if ( !filter_c2cfiops(filter) ) {
filter_setup_file_ops(filter,
inode, &presto_file_iops,
&presto_file_fops);
}
inode->i_op = filter_c2ufiops(filter);
inode->i_fop = filter_c2uffops(filter);
CDEBUG(D_INODE, "set file methods for %ld to %p\n",
inode->i_ino, inode->i_op);
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = filter_c2udiops(filter);
inode->i_fop = filter_c2udfops(filter);
CDEBUG(D_INODE, "set dir methods for %ld to %p ioctl %p\n",
inode->i_ino, inode->i_op, inode->i_fop->ioctl);
} else if (S_ISLNK(inode->i_mode)) {
if ( !filter_c2csiops(filter)) {
filter_setup_symlink_ops(filter,
inode,
&presto_sym_iops,
&presto_sym_fops);
}
inode->i_op = filter_c2usiops(filter);
inode->i_fop = filter_c2usfops(filter);
CDEBUG(D_INODE, "set link methods for %ld to %p\n",
inode->i_ino, inode->i_op);
}
EXIT;
}
void presto_read_inode(struct inode *inode)
{
struct presto_cache *cache;
cache = presto_get_cache(inode);
if ( !cache ) {
CERROR("PRESTO: BAD, BAD: cannot find cache\n");
make_bad_inode(inode);
return ;
}
filter_c2csops(cache->cache_filter)->read_inode(inode);
CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n",
inode->i_ino, inode->i_gid);
presto_set_ops(inode, cache->cache_filter);
/* XXX handle special inodes here or not - probably not? */
}
static void presto_put_super(struct super_block *sb)
{
struct presto_cache *cache;
struct upc_channel *channel;
struct super_operations *sops;
struct list_head *lh;
int err;
ENTRY;
cache = presto_cache_find(sb);
if (!cache) {
EXIT;
goto exit;
}
channel = &izo_channels[presto_c2m(cache)];
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)
sops->put_super(sb);
/* free any remaining async upcalls when the filesystem is unmounted */
spin_lock(&channel->uc_lock);
lh = channel->uc_pending.next;
while ( lh != &channel->uc_pending) {
struct upc_req *req;
req = list_entry(lh, struct upc_req, rq_chain);
/* assignment must be here: we are about to free &lh */
lh = lh->next;
if ( ! (req->rq_flags & REQ_ASYNC) )
continue;
list_del(&(req->rq_chain));
PRESTO_FREE(req->rq_data, req->rq_bufsize);
PRESTO_FREE(req, sizeof(struct upc_req));
}
list_del(&cache->cache_channel_list);
spin_unlock(&channel->uc_lock);
presto_free_cache(cache);
exit:
CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
presto_kmemory, presto_vmemory);
return ;
}
struct super_operations presto_super_ops = {
.read_inode = presto_read_inode,
.put_super = presto_put_super,
};
/* symlinks can be chowned */
struct inode_operations presto_sym_iops = {
.setattr = presto_setattr
};
/* NULL for now */
struct file_operations presto_sym_fops;
This diff is collapsed.
This diff is collapsed.
#ifndef __PRESTO_JOURNAL_H
#define __PRESTO_JOURNAL_H
struct journal_prefix {
int len;
u32 version;
int pid;
int uid;
int fsuid;
int fsgid;
int opcode;
u32 ngroups;
u32 groups[0];
};
struct journal_suffix {
unsigned long prevrec; /* offset of previous record for dentry */
int recno;
int time;
int len;
};
#endif
#ifndef __INTERMEZZO_KML_H
#define __INTERMEZZO_KML_H
#include "intermezzo_psdev.h"
#include <linux/fs.h>
#include "intermezzo_journal.h"
#define PRESTO_KML_MAJOR_VERSION 0x00010000
#define PRESTO_KML_MINOR_VERSION 0x00002001
#define PRESTO_OP_NOOP 0
#define PRESTO_OP_CREATE 1
#define PRESTO_OP_MKDIR 2
#define PRESTO_OP_UNLINK 3
#define PRESTO_OP_RMDIR 4
#define PRESTO_OP_CLOSE 5
#define PRESTO_OP_SYMLINK 6
#define PRESTO_OP_RENAME 7
#define PRESTO_OP_SETATTR 8
#define PRESTO_OP_LINK 9
#define PRESTO_OP_OPEN 10
#define PRESTO_OP_MKNOD 11
#define PRESTO_OP_WRITE 12
#define PRESTO_OP_RELEASE 13
#define PRESTO_OP_TRUNC 14
#define PRESTO_OP_SETEXTATTR 15
#define PRESTO_OP_DELEXTATTR 16
#define PRESTO_LML_DONE 1 /* flag to get first write to do LML */
#define KML_KOP_MARK 0xffff
struct presto_lml_data {
loff_t rec_offset;
};
struct big_journal_prefix {
u32 len;
u32 version;
u32 pid;
u32 uid;
u32 fsuid;
u32 fsgid;
u32 opcode;
u32 ngroups;
u32 groups[NGROUPS_SMALL];
};
enum kml_opcode {
KML_CREATE = 1,
KML_MKDIR,
KML_UNLINK,
KML_RMDIR,
KML_CLOSE,
KML_SYMLINK,
KML_RENAME,
KML_SETATTR,
KML_LINK,
KML_OPEN,
KML_MKNOD,
KML_ENDMARK = 0xff
};
struct kml_create {
char *path;
struct presto_version new_objectv,
old_parentv,
new_parentv;
int mode;
int uid;
int gid;
};
struct kml_open {
};
struct kml_mkdir {
char *path;
struct presto_version new_objectv,
old_parentv,
new_parentv;
int mode;
int uid;
int gid;
};
struct kml_unlink {
char *path,
*name;
struct presto_version old_tgtv,
old_parentv,
new_parentv;
};
struct kml_rmdir {
char *path,
*name;
struct presto_version old_tgtv,
old_parentv,
new_parentv;
};
struct kml_close {
int open_mode,
open_uid,
open_gid;
char *path;
struct presto_version new_objectv;
__u64 ino;
int generation;
};
struct kml_symlink {
char *sourcepath,
*targetpath;
struct presto_version new_objectv,
old_parentv,
new_parentv;
int uid;
int gid;
};
struct kml_rename {
char *sourcepath,
*targetpath;
struct presto_version old_objectv,
new_objectv,
old_tgtv,
new_tgtv;
};
struct kml_setattr {
char *path;
struct presto_version old_objectv;
struct iattr iattr;
};
struct kml_link {
char *sourcepath,
*targetpath;
struct presto_version new_objectv,
old_parentv,
new_parentv;
};
struct kml_mknod {
char *path;
struct presto_version new_objectv,
old_parentv,
new_parentv;
int mode;
int uid;
int gid;
int major;
int minor;
};
/* kml record items for optimizing */
struct kml_kop_node
{
u32 kml_recno;
u32 kml_flag;
u32 kml_op;
nlink_t i_nlink;
u32 i_ino;
};
struct kml_kop_lnode
{
struct list_head chains;
struct kml_kop_node node;
};
struct kml_endmark {
u32 total;
struct kml_kop_node *kop;
};
/* kml_flag */
#define KML_REC_DELETE 1
#define KML_REC_EXIST 0
struct kml_optimize {
struct list_head kml_chains;
u32 kml_flag;
u32 kml_op;
nlink_t i_nlink;
u32 i_ino;
};
struct kml_rec {
/* attribute of this record */
int rec_size;
int rec_kml_offset;
struct big_journal_prefix rec_head;
union {
struct kml_create create;
struct kml_open open;
struct kml_mkdir mkdir;
struct kml_unlink unlink;
struct kml_rmdir rmdir;
struct kml_close close;
struct kml_symlink symlink;
struct kml_rename rename;
struct kml_setattr setattr;
struct kml_mknod mknod;
struct kml_link link;
struct kml_endmark endmark;
} rec_kml;
struct journal_suffix rec_tail;
/* for kml optimize only */
struct kml_optimize kml_optimize;
};
/* kml record items for optimizing */
extern void kml_kop_init (struct presto_file_set *fset);
extern void kml_kop_addrec (struct presto_file_set *fset,
struct inode *ino, u32 op, u32 flag);
extern int kml_kop_flush (struct presto_file_set *fset);
/* defined in kml_setup.c */
extern int kml_init (struct presto_file_set *fset);
extern int kml_cleanup (struct presto_file_set *fset);
/* defined in kml.c */
extern int begin_kml_reint (struct file *file, unsigned long arg);
extern int do_kml_reint (struct file *file, unsigned long arg);
extern int end_kml_reint (struct file *file, unsigned long arg);
/* kml_utils.c */
extern char *dlogit (void *tbuf, const void *sbuf, int size);
extern char * bdup_printf (char *format, ...);
/* defined in kml_decode.c */
/* printop */
#define PRINT_KML_PREFIX 0x1
#define PRINT_KML_SUFFIX 0x2
#define PRINT_KML_REC 0x4
#define PRINT_KML_OPTIMIZE 0x8
#define PRINT_KML_EXIST 0x10
#define PRINT_KML_DELETE 0x20
extern void kml_printrec (struct kml_rec *rec, int printop);
extern int print_allkmlrec (struct list_head *head, int printop);
extern int delete_kmlrec (struct list_head *head);
extern int kml_decoderec (char *buf, int pos, int buflen, int *size,
struct kml_rec **newrec);
extern int decode_kmlrec (struct list_head *head, char *kml_buf, int buflen);
extern void kml_freerec (struct kml_rec *rec);
/* defined in kml_reint.c */
#define KML_CLOSE_BACKFETCH 1
extern int kml_reintbuf (struct kml_fsdata *kml_fsdata,
char *mtpt, struct kml_rec **rec);
/* defined in kml_setup.c */
extern int kml_init (struct presto_file_set *fset);
extern int kml_cleanup (struct presto_file_set *fset);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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