blob: 98800d0b213d557fa46a295e51b3207901d98749 [file] [log] [blame]
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
* Copyright (C) 2001, 2002 Cluster File Systems, Inc.
* Copyright (C) 2001 Tacitus Systems, Inc.
* Copyright (C) 2000 Stelias Computing, Inc.
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2000 TurboLinux, Inc.
* Copyright (C) 2000 Los Alamos National Laboratory.
*
* 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.
*/
#ifndef __INTERMEZZO_FS_H_
#define __INTERMEZZO_FS_H_ 1
#include <linux/intermezzo_lib.h>
#include <linux/intermezzo_idl.h>
#ifdef __KERNEL__
typedef __u8 uuid_t[16];
#else
# include <uuid/uuid.h>
#endif
struct lento_vfs_context {
__u64 kml_offset;
__u64 updated_time;
__u64 remote_ino;
__u64 remote_generation;
__u32 slot_offset;
__u32 recno;
__u32 flags;
uuid_t uuid;
struct presto_version remote_version;
};
#ifdef __KERNEL__
# include <linux/smp.h>
# include <linux/fsfilter.h>
# include <linux/slab.h>
# include <linux/vmalloc.h>
# include <linux/smp_lock.h>
/* fixups for fs.h */
# ifndef fs_down
# define fs_down(sem) down(sem)
# endif
# ifndef fs_up
# define fs_up(sem) up(sem)
# endif
# define KML_IDLE 0
# define KML_DECODE 1
# define KML_OPTIMIZE 2
# define KML_REINT 3
# define KML_OPEN_REINT 0x0100
# define KML_REINT_BEGIN 0x0200
# define KML_BACKFETCH 0x0400
# define KML_REINT_END 0x0800
# define KML_CLOSE_REINT 0x1000
# define KML_REINT_MAXBUF (64 * 1024)
# define CACHE_CLIENT_RO 0x4
# define CACHE_LENTO_RO 0x8
/* global variables */
extern int presto_debug;
extern int presto_print_entry;
extern long presto_kmemory;
extern long presto_vmemory;
# define PRESTO_DEBUG
# ifdef PRESTO_DEBUG
/* debugging masks */
# define D_SUPER 1
# define D_INODE 2
# define D_FILE 4
# define D_CACHE 8 /* cache debugging */
# define D_MALLOC 16 /* print malloc, de-alloc information */
# define D_JOURNAL 32
# define D_UPCALL 64 /* up and downcall debugging */
# define D_PSDEV 128
# define D_PIOCTL 256
# define D_SPECIAL 512
# define D_TIMING 1024
# define D_DOWNCALL 2048
# define D_KML 4096
# define D_FSDATA 8192
# define CDEBUG(mask, format, a...) \
do { \
if (presto_debug & mask) { \
printk("(%s:%s,l. %d %d): " format, __FILE__, \
__FUNCTION__, __LINE__, current->pid \
, ## a); \
} \
} while (0)
#define CERROR(format, a...) \
do { \
printk("(%s:%s,l. %d %d): " format, __FILE__, __FUNCTION__, \
__LINE__, current->pid , ## a); \
} while (0)
# define ENTRY \
if (presto_print_entry) \
printk("Process %d entered %s\n", current->pid, __FUNCTION__)
# define EXIT \
if (presto_print_entry) \
printk("Process %d leaving %s at %d\n", current->pid, \
__FUNCTION__, __LINE__)
# define presto_kmem_inc(ptr, size) presto_kmemory += (size)
# define presto_kmem_dec(ptr, size) presto_kmemory -= (size)
# define presto_vmem_inc(ptr, size) presto_vmemory += (size)
# define presto_vmem_dec(ptr, size) presto_vmemory -= (size)
# else /* !PRESTO_DEBUG */
# define CDEBUG(mask, format, a...) do {} while (0)
# define ENTRY do {} while (0)
# define EXIT do {} while (0)
# define presto_kmem_inc(ptr, size) do {} while (0)
# define presto_kmem_dec(ptr, size) do {} while (0)
# define presto_vmem_inc(ptr, size) do {} while (0)
# define presto_vmem_dec(ptr, size) do {} while (0)
# endif /* PRESTO_DEBUG */
struct run_ctxt {
struct vfsmount *pwdmnt;
struct dentry *pwd;
struct vfsmount *rootmnt;
struct dentry *root;
uid_t fsuid;
gid_t fsgid;
mm_segment_t fs;
int ngroups;
gid_t groups[NGROUPS];
};
static inline void push_ctxt(struct run_ctxt *save, struct run_ctxt *new)
{
int i;
save->fs = get_fs();
save->pwd = dget(current->fs->pwd);
save->pwdmnt = mntget(current->fs->pwdmnt);
save->fsgid = current->fsgid;
save->fsuid = current->fsuid;
save->root = current->fs->root;
save->rootmnt = current->fs->rootmnt;
save->ngroups = current->ngroups;
for (i = 0; i< current->ngroups; i++)
save->groups[i] = current->groups[i];
set_fs(new->fs);
lock_kernel();
set_fs_pwd(current->fs, new->pwdmnt, new->pwd);
if (new->root)
set_fs_root(current->fs, new->rootmnt, new->root);
unlock_kernel();
current->fsuid = new->fsuid;
current->fsgid = new->fsgid;
if (new->ngroups > 0) {
current->ngroups = new->ngroups;
for (i = 0; i< new->ngroups; i++)
current->groups[i] = new->groups[i];
}
}
static inline void pop_ctxt(struct run_ctxt *saved)
{
int i;
set_fs(saved->fs);
lock_kernel();
set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
if (saved->root)
set_fs_root(current->fs, saved->rootmnt, saved->root);
unlock_kernel();
current->fsuid = saved->fsuid;
current->fsgid = saved->fsgid;
current->ngroups = saved->ngroups;
for (i = 0; i< saved->ngroups; i++)
current->groups[i] = saved->groups[i];
mntput(saved->pwdmnt);
dput(saved->pwd);
}
static inline struct presto_dentry_data *presto_d2d(struct dentry *dentry)
{
return (struct presto_dentry_data *)(dentry->d_fsdata);
}
struct presto_cache {
spinlock_t cache_lock;
loff_t cache_reserved;
struct vfsmount *cache_vfsmount;
struct super_block *cache_sb;
struct dentry *cache_root;
struct list_head cache_chain; /* for the dev/cache hash */
int cache_flags;
kdev_t cache_dev; /* underlying block device */
char *cache_type; /* filesystem type of cache */
struct filter_fs *cache_filter;
struct upc_channel *cache_psdev; /* points to channel used */
struct list_head cache_channel_list;
struct list_head cache_fset_list; /* filesets mounted in cache */
};
struct presto_log_fd {
rwlock_t fd_lock;
loff_t fd_offset; /* offset where next record should go */
struct file *fd_file;
int fd_truncating;
unsigned int fd_recno; /* last recno written */
struct list_head fd_reservations;
};
/* file sets */
# define CHUNK_BITS 16
struct presto_file_set {
struct list_head fset_list;
struct presto_log_fd fset_kml;
struct presto_log_fd fset_lml;
struct presto_log_fd fset_rcvd;
struct list_head *fset_clients; /* cache of clients */
struct dentry *fset_dentry;
struct vfsmount *fset_mnt;
struct presto_cache *fset_cache;
unsigned int fset_lento_recno; /* last recno mentioned to lento */
loff_t fset_lento_off; /* last offset mentioned to lento */
loff_t fset_kml_logical_off; /* logical offset of kml file byte 0 */
char * fset_name;
int fset_flags;
int fset_chunkbits;
char *fset_reint_buf; /* temporary buffer holds kml during reint */
spinlock_t fset_permit_lock;
int fset_permit_count;
int fset_permit_upcall_count;
/* This queue is used both for processes waiting for the kernel to give
* up the permit as well as processes waiting for the kernel to be given
* the permit, depending on the state of FSET_HASPERMIT. */
wait_queue_head_t fset_permit_queue;
loff_t fset_file_maxio; /* writing more than this causes a close */
unsigned long int kml_truncate_size;
};
/* This is the default number of bytes written before a close is recorded*/
#define FSET_DEFAULT_MAX_FILEIO (1024<<10)
struct dentry *presto_tmpfs_ilookup(struct inode *dir, struct dentry *dentry,
ino_t ino, unsigned int generation);
struct dentry *presto_iget_ilookup(struct inode *dir, struct dentry *dentry,
ino_t ino, unsigned int generation);
struct dentry *presto_add_ilookup_dentry(struct dentry *parent,
struct dentry *real);
struct journal_ops {
int (*tr_all_data)(struct inode *);
loff_t (*tr_avail)(struct presto_cache *fset, struct super_block *);
void *(*tr_start)(struct presto_file_set *, struct inode *, int op);
void (*tr_commit)(struct presto_file_set *, void *handle);
void (*tr_journal_data)(struct inode *);
struct dentry *(*tr_ilookup)(struct inode *dir, struct dentry *dentry, ino_t ino, unsigned int generation);
struct dentry *(*tr_add_ilookup)(struct dentry *parent, struct dentry *real);
};
extern struct journal_ops presto_ext2_journal_ops;
extern struct journal_ops presto_ext3_journal_ops;
extern struct journal_ops presto_tmpfs_journal_ops;
extern struct journal_ops presto_xfs_journal_ops;
extern struct journal_ops presto_reiserfs_journal_ops;
extern struct journal_ops presto_obdfs_journal_ops;
# define LENTO_FL_KML 0x0001
# define LENTO_FL_EXPECT 0x0002
# define LENTO_FL_VFSCHECK 0x0004
# define LENTO_FL_JUSTLOG 0x0008
# define LENTO_FL_WRITE_KML 0x0010
# define LENTO_FL_CANCEL_LML 0x0020
# define LENTO_FL_WRITE_EXPECT 0x0040
# define LENTO_FL_IGNORE_TIME 0x0080
# define LENTO_FL_TOUCH_PARENT 0x0100
# define LENTO_FL_TOUCH_NEWOBJ 0x0200
# define LENTO_FL_SET_DDFILEID 0x0400
struct presto_cache *presto_get_cache(struct inode *inode);
int presto_sprint_mounts(char *buf, int buflen, int minor);
struct presto_file_set *presto_fset(struct dentry *de);
int presto_journal(struct dentry *dentry, char *buf, size_t size);
int presto_fwrite(struct file *file, const char *str, int len, loff_t *off);
int presto_ispresto(struct inode *);
/* super.c */
extern int init_intermezzo_fs(void);
/* fileset.c */
extern int izo_prepare_fileset(struct dentry *root, char *fsetname);
char * izo_make_path(struct presto_file_set *fset, char *name);
struct file *izo_fset_open(struct presto_file_set *fset, char *name, int flags, int mode);
/* psdev.c */
int izo_psdev_get_free_channel(void);
int presto_psdev_init(void);
int izo_psdev_setpid(int minor);
extern void presto_psdev_cleanup(void);
int presto_lento_up(int minor);
int izo_psdev_setchannel(struct file *file, int fd);
/* inode.c */
extern struct super_operations presto_super_ops;
void presto_set_ops(struct inode *inode, struct filter_fs *filter);
/* dcache.c */
void presto_frob_dop(struct dentry *de);
char *presto_path(struct dentry *dentry, struct dentry *root,
char *buffer, int buflen);
struct presto_dentry_data *izo_alloc_ddata(void);
int presto_set_dd(struct dentry *);
int presto_init_ddata_cache(void);
void presto_cleanup_ddata_cache(void);
extern struct dentry_operations presto_dentry_ops;
/* dir.c */
extern struct inode_operations presto_dir_iops;
extern struct inode_operations presto_file_iops;
extern struct inode_operations presto_sym_iops;
extern struct file_operations presto_dir_fops;
extern struct file_operations presto_file_fops;
extern struct file_operations presto_sym_fops;
int presto_setattr(struct dentry *de, struct iattr *iattr);
int presto_settime(struct presto_file_set *fset, struct dentry *newobj,
struct dentry *parent, struct dentry *target,
struct lento_vfs_context *ctx, int valid);
int presto_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
extern int presto_ilookup_uid;
# define PRESTO_ILOOKUP_MAGIC "...ino:"
# define PRESTO_ILOOKUP_SEP ':'
int izo_dentry_is_ilookup(struct dentry *, ino_t *id, unsigned int *generation);
struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry);
struct presto_dentry_data {
int dd_count; /* how mnay dentries are using this dentry */
struct presto_file_set *dd_fset;
struct dentry *dd_inodentry;
loff_t dd_kml_offset;
int dd_flags;
__u64 remote_ino;
__u64 remote_generation;
};
struct presto_file_data {
int fd_do_lml;
loff_t fd_lml_offset;
size_t fd_bytes_written;
/* authorization related data of file at open time */
uid_t fd_uid;
gid_t fd_gid;
mode_t fd_mode;
/* identification data of calling process */
uid_t fd_fsuid;
gid_t fd_fsgid;
int fd_ngroups;
gid_t fd_groups[NGROUPS_MAX];
/* information how to complete the close operation */
struct lento_vfs_context fd_info;
struct presto_version fd_version;
};
/* presto.c and Lento::Downcall */
int presto_walk(const char *name, struct nameidata *nd);
int izo_clear_fsetroot(struct dentry *dentry);
int izo_clear_all_fsetroots(struct presto_cache *cache);
int presto_get_kmlsize(char *path, __u64 *size);
int presto_get_lastrecno(char *path, off_t *size);
int presto_set_fsetroot(struct dentry *dentry, char *fsetname,
unsigned int flags);
int presto_set_fsetroot_from_ioc(struct dentry *dentry, char *fsetname,
unsigned int flags);
int presto_is_read_only(struct presto_file_set *);
int presto_truncate_lml(struct presto_file_set *fset);
int lento_write_lml(char *path,
__u64 remote_ino,
__u32 remote_generation,
__u32 remote_version,
struct presto_version *remote_file_version);
int lento_complete_closes(char *path);
int presto_f2m(struct presto_file_set *fset);
int presto_prep(struct dentry *, struct presto_cache **,
struct presto_file_set **);
/* cache.c */
extern struct presto_cache *presto_cache_init(void);
extern void presto_cache_add(struct presto_cache *cache, kdev_t dev);
extern void presto_cache_init_hash(void);
struct presto_cache *presto_cache_find(kdev_t dev);
#define PRESTO_REQLOW (3 * 4096)
#define PRESTO_REQHIGH (6 * 4096)
void presto_release_space(struct presto_cache *cache, loff_t req);
int presto_reserve_space(struct presto_cache *cache, loff_t req);
#define PRESTO_DATA 0x00000002 /* cached data is valid */
#define PRESTO_ATTR 0x00000004 /* attributes cached */
#define PRESTO_DONT_JOURNAL 0x00000008 /* things like .intermezzo/ */
struct presto_file_set *presto_path2fileset(const char *name);
int izo_revoke_permit(struct dentry *, uuid_t uuid);
int presto_chk(struct dentry *dentry, int flag);
void presto_set(struct dentry *dentry, int flag);
int presto_get_permit(struct inode *inode);
int presto_put_permit(struct inode *inode);
int presto_set_max_kml_size(const char *path, unsigned long max_size);
int izo_mark_dentry(struct dentry *dentry, int and, int or, int *res);
int izo_mark_cache(struct dentry *dentry, int and_bits, int or_bits, int *);
int izo_mark_fset(struct dentry *dentry, int and_bits, int or_bits, int *);
void presto_getversion(struct presto_version *pv, struct inode *inode);
int presto_i2m(struct inode *inode);
int presto_c2m(struct presto_cache *cache);
/* file.c */
int izo_purge_file(struct presto_file_set *fset, char *file);
int presto_adjust_lml(struct file *file, struct lento_vfs_context *info);
/* journal.c */
struct rec_info {
loff_t offset;
int size;
int recno;
int is_kml;
};
void presto_trans_commit(struct presto_file_set *fset, void *handle);
void *presto_trans_start(struct presto_file_set *fset, struct inode *inode,
int op);
int presto_fread(struct file *file, char *str, int len, loff_t *off);
int presto_clear_lml_close(struct presto_file_set *fset,
loff_t lml_offset);
int presto_complete_lml(struct presto_file_set *fset);
int presto_read_kml_logical_offset(struct rec_info *recinfo,
struct presto_file_set *fset);
int presto_write_kml_logical_offset(struct presto_file_set *fset);
struct file *presto_copy_kml_tail(struct presto_file_set *fset,
unsigned long int start);
int presto_finish_kml_truncate(struct presto_file_set *fset,
unsigned long int offset);
int izo_lookup_file(struct presto_file_set *fset, char *path,
struct nameidata *nd);
int izo_do_truncate(struct presto_file_set *fset, struct dentry *dentry,
loff_t length, loff_t size_check);
int izo_log_close(struct presto_log_fd *logfd);
struct file *izo_log_open(struct presto_file_set *fset, char *name, int flags);
int izo_init_kml_file(struct presto_file_set *, struct presto_log_fd *);
int izo_init_lml_file(struct presto_file_set *, struct presto_log_fd *);
int izo_init_last_rcvd_file(struct presto_file_set *, struct presto_log_fd *);
/* vfs.c */
/* Extra data needed in the KML for rollback operations; this structure is
* passed around during the KML-writing process. */
struct izo_rollback_data {
__u32 rb_mode;
__u32 rb_rdev;
__u64 rb_uid;
__u64 rb_gid;
};
int presto_write_last_rcvd(struct rec_info *recinfo,
struct presto_file_set *fset,
struct lento_vfs_context *info);
void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb);
int presto_do_close(struct presto_file_set *fset, struct file *file);
int presto_do_setattr(struct presto_file_set *fset, struct dentry *dentry,
struct iattr *iattr, struct lento_vfs_context *info);
int presto_do_create(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, int mode,
struct lento_vfs_context *info);
int presto_do_link(struct presto_file_set *fset, struct dentry *dir,
struct dentry *old_dentry, struct dentry *new_dentry,
struct lento_vfs_context *info);
int presto_do_unlink(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, struct lento_vfs_context *info);
int presto_do_symlink(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, const char *name,
struct lento_vfs_context *info);
int presto_do_mkdir(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, int mode,
struct lento_vfs_context *info);
int presto_do_rmdir(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, struct lento_vfs_context *info);
int presto_do_mknod(struct presto_file_set *fset, struct dentry *dir,
struct dentry *dentry, int mode, dev_t dev,
struct lento_vfs_context *info);
int do_rename(struct presto_file_set *fset, struct dentry *old_dir,
struct dentry *old_dentry, struct dentry *new_dir,
struct dentry *new_dentry, struct lento_vfs_context *info);
int presto_do_statfs (struct presto_file_set *fset,
struct statfs * buf);
int lento_setattr(const char *name, struct iattr *iattr,
struct lento_vfs_context *info);
int lento_create(const char *name, int mode, struct lento_vfs_context *info);
int lento_link(const char *oldname, const char *newname,
struct lento_vfs_context *info);
int lento_unlink(const char *name, struct lento_vfs_context *info);
int lento_symlink(const char *oldname,const char *newname,
struct lento_vfs_context *info);
int lento_mkdir(const char *name, int mode, struct lento_vfs_context *info);
int lento_rmdir(const char *name, struct lento_vfs_context *info);
int lento_mknod(const char *name, int mode, dev_t dev,
struct lento_vfs_context *info);
int lento_rename(const char *oldname, const char *newname,
struct lento_vfs_context *info);
int lento_iopen(const char *name, ino_t ino, unsigned int generation,int flags);
/* journal.c */
#define JOURNAL_PAGE_SZ PAGE_SIZE
int presto_no_journal(struct presto_file_set *fset);
int journal_fetch(int minor);
int presto_log(struct presto_file_set *fset, struct rec_info *rec,
const char *buf, size_t size,
const char *string1, int len1,
const char *string2, int len2,
const char *string3, int len3);
int presto_get_fileid(int minor, struct presto_file_set *fset,
struct dentry *dentry);
int presto_journal_setattr(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry, struct presto_version *old_ver,
struct izo_rollback_data *, struct iattr *iattr);
int presto_journal_create(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry,
struct presto_version *tgt_dir_ver,
struct presto_version *new_file_ver, int mode);
int presto_journal_link(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *src, struct dentry *tgt,
struct presto_version *tgt_dir_ver,
struct presto_version *new_link_ver);
int presto_journal_unlink(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dir,
struct presto_version *tgt_dir_ver,
struct presto_version *old_file_ver,
struct izo_rollback_data *, struct dentry *dentry,
char *old_target, int old_targetlen);
int presto_journal_symlink(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry, const char *target,
struct presto_version *tgt_dir_ver,
struct presto_version *new_link_ver);
int presto_journal_mkdir(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry,
struct presto_version *tgt_dir_ver,
struct presto_version *new_dir_ver, int mode);
int presto_journal_rmdir(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry,
struct presto_version *tgt_dir_ver,
struct presto_version *old_dir_ver,
struct izo_rollback_data *, int len, const char *name);
int presto_journal_mknod(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *dentry,
struct presto_version *tgt_dir_ver,
struct presto_version *new_node_ver, int mode,
int dmajor, int dminor);
int presto_journal_rename(struct rec_info *rec, struct presto_file_set *fset,
struct dentry *src, struct dentry *tgt,
struct presto_version *src_dir_ver,
struct presto_version *tgt_dir_ver);
int presto_journal_open(struct rec_info *, struct presto_file_set *,
struct dentry *, struct presto_version *old_ver);
int presto_journal_close(struct rec_info *rec, struct presto_file_set *,
struct file *, struct dentry *,
struct presto_version *old_file_ver,
struct presto_version *new_file_ver);
int presto_write_lml_close(struct rec_info *rec,
struct presto_file_set *fset,
struct file *file,
__u64 remote_ino,
__u64 remote_generation,
struct presto_version *remote_version,
struct presto_version *new_file_ver);
void presto_log_op(void *data, int len);
loff_t presto_kml_offset(struct presto_file_set *fset);
/* upcall.c */
#define SYNCHRONOUS 0
#define ASYNCHRONOUS 1
/* asynchronous calls */
int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length,
__u32 last_recno, char *fsetname);
int izo_upc_kml_truncate(int minor, __u64 length, __u32 last_recno,
char *fsetname);
int izo_upc_go_fetch_kml(int minor, char *fsetname, uuid_t uuid, __u64 kmlsize);
int izo_upc_backfetch(int minor, char *path, char *fileset,
struct lento_vfs_context *);
/* synchronous calls */
int izo_upc_get_fileid(int minor, __u32 reclen, char *rec,
__u32 pathlen, char *path, char *fsetname);
int izo_upc_permit(int minor, struct dentry *, __u32 pathlen, char *path,
char *fset);
int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname,
struct lento_vfs_context *info);
int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
int client_flag);
int izo_upc_revoke_permit(int minor, char *fsetname, uuid_t uuid);
int izo_upc_set_kmlsize(int minor, char *fsetname, uuid_t uuid, __u64 kmlsize);
int izo_upc_client_make_branch(int minor, char *fsetname);
int izo_upc_server_make_branch(int minor, char *fsetname);
int izo_upc_branch_undo(int minor, char *fsetname, char *branchname);
int izo_upc_branch_redo(int minor, char *fsetname, char *branchname);
int izo_upc_repstatus(int minor, char * fsetname, struct izo_rcvd_rec *lr_server);
/* general mechanism */
int izo_upc_upcall(int minor, int *size, struct izo_upcall_hdr *, int async);
/* replicator.c */
int izo_repstatus(struct presto_file_set *fset, __u64 client_kmlsize,
struct izo_rcvd_rec *lr_client, struct izo_rcvd_rec *lr_server);
int izo_rep_cache_init(struct presto_file_set *);
void izo_rep_cache_clean(struct presto_file_set *fset);
loff_t izo_rcvd_get(struct izo_rcvd_rec *, struct presto_file_set *, char *uuid);
loff_t izo_rcvd_write(struct presto_file_set *, struct izo_rcvd_rec *);
loff_t izo_rcvd_upd_remote(struct presto_file_set *fset, char * uuid, __u64 remote_recno,
__u64 remote_offset);
int izo_ioctl_packlen(struct izo_ioctl_data *data);
/* sysctl.c */
int init_intermezzo_sysctl(void);
void cleanup_intermezzo_sysctl(void);
/* ext_attr.c */
/* We will be more tolerant than the default ea patch with attr name sizes and
* the size of value. If these come via VFS from the default ea patches, the
* corresponding character strings will be truncated anyway. During journalling- * we journal length for both name and value. See journal_set_ext_attr.
*/
#define PRESTO_EXT_ATTR_NAME_MAX 128
#define PRESTO_EXT_ATTR_VALUE_MAX 8192
#define PRESTO_ALLOC(ptr, size) \
do { \
long s = (size); \
(ptr) = kmalloc(s, GFP_KERNEL); \
if ((ptr) == NULL) \
CERROR("IZO: out of memory at %s:%d (trying to " \
"allocate %ld)\n", __FILE__, __LINE__, s); \
else { \
presto_kmem_inc((ptr), s); \
memset((ptr), 0, s); \
} \
CDEBUG(D_MALLOC, "kmalloced: %ld at %p (tot %ld).\n", \
s, (ptr), presto_kmemory); \
} while (0)
#define PRESTO_FREE(ptr, size) \
do { \
long s = (size); \
if ((ptr) == NULL) { \
CERROR("IZO: free NULL pointer (%ld bytes) at " \
"%s:%d\n", s, __FILE__, __LINE__); \
break; \
} \
kfree(ptr); \
CDEBUG(D_MALLOC, "kfreed: %ld at %p (tot %ld).\n", \
s, (ptr), presto_kmemory); \
presto_kmem_dec((ptr), s); \
} while (0)
static inline int dentry_name_cmp(struct dentry *dentry, char *name)
{
return (strlen(name) == dentry->d_name.len &&
memcmp(name, dentry->d_name.name, dentry->d_name.len) == 0);
}
static inline char *strdup(char *str)
{
char *tmp;
long int s;
s=strlen(str) + 1;
tmp = kmalloc(s, GFP_KERNEL);
if (tmp){
memcpy(tmp, str, s);
presto_kmem_inc(tmp, s);
}
CDEBUG(D_MALLOC, "kmalloced: %ld at %p (tot %ld).\n",
s, tmp, presto_kmemory);
return tmp;
}
static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data)
{
if (data->ioc_len > (1<<30)) {
CERROR("IZO ioctl: ioc_len larger than 1<<30\n");
return 1;
}
if (data->ioc_inllen1 > (1<<30)) {
CERROR("IZO ioctl: ioc_inllen1 larger than 1<<30\n");
return 1;
}
if (data->ioc_inllen2 > (1<<30)) {
CERROR("IZO ioctl: ioc_inllen2 larger than 1<<30\n");
return 1;
}
if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
CERROR("IZO ioctl: inlbuf1 pointer but 0 length\n");
return 1;
}
if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
CERROR("IZO ioctl: inlbuf2 pointer but 0 length\n");
return 1;
}
if (data->ioc_pbuf1 && !data->ioc_plen1) {
CERROR("IZO ioctl: pbuf1 pointer but 0 length\n");
return 1;
}
if (data->ioc_pbuf2 && !data->ioc_plen2) {
CERROR("IZO ioctl: pbuf2 pointer but 0 length\n");
return 1;
}
if (izo_ioctl_packlen(data) != data->ioc_len ) {
CERROR("IZO ioctl: packlen exceeds ioc_len\n");
return 1;
}
if (data->ioc_inllen1 &&
data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
CERROR("IZO ioctl: inlbuf1 not 0 terminated\n");
return 1;
}
if (data->ioc_inllen2 &&
data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2
- 1] != '\0') {
CERROR("IZO ioctl: inlbuf2 not 0 terminated\n");
return 1;
}
return 0;
}
/* buffer MUST be at least the size of izo_ioctl_hdr */
static inline int izo_ioctl_getdata(char *buf, char *end, void *arg)
{
struct izo_ioctl_hdr *hdr;
struct izo_ioctl_data *data;
int err;
ENTRY;
hdr = (struct izo_ioctl_hdr *)buf;
data = (struct izo_ioctl_data *)buf;
err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
if ( err ) {
EXIT;
return err;
}
if (hdr->ioc_version != IZO_IOCTL_VERSION) {
CERROR("IZO: version mismatch kernel vs application\n");
return -EINVAL;
}
if (hdr->ioc_len + buf >= end) {
CERROR("IZO: user buffer exceeds kernel buffer\n");
return -EINVAL;
}
if (hdr->ioc_len < sizeof(struct izo_ioctl_data)) {
CERROR("IZO: user buffer too small for ioctl\n");
return -EINVAL;
}
err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
if ( err ) {
EXIT;
return err;
}
if (izo_ioctl_is_invalid(data)) {
CERROR("IZO: ioctl not correctly formatted\n");
return -EINVAL;
}
if (data->ioc_inllen1) {
data->ioc_inlbuf1 = &data->ioc_bulk[0];
}
if (data->ioc_inllen2) {
data->ioc_inlbuf2 = &data->ioc_bulk[0] +
size_round(data->ioc_inllen1);
}
EXIT;
return 0;
}
# define MYPATHLEN(buffer, path) ((buffer) + PAGE_SIZE - (path))
# define free kfree
# define malloc(a) kmalloc(a, GFP_KERNEL)
# define printf printk
int kml_reint_rec(struct file *dir, struct izo_ioctl_data *data);
int izo_get_fileid(struct file *dir, struct izo_ioctl_data *data);
int izo_set_fileid(struct file *dir, struct izo_ioctl_data *data);
#else /* __KERNEL__ */
# include <stdlib.h>
# include <stdio.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <string.h>
# define printk printf
# ifndef CERROR
# define CERROR printf
# endif
# define kmalloc(a,b) malloc(a)
void init_fsreintdata (void);
int kml_fsreint(struct kml_rec *rec, char *basedir);
int kml_iocreint(__u32 size, char *ptr, __u32 offset, int dird,
uuid_t uuid, __u32 generate_kml);
static inline void izo_ioctl_init(struct izo_ioctl_data *data)
{
memset(data, 0, sizeof(*data));
data->ioc_len = sizeof(*data);
data->ioc_version = IZO_IOCTL_VERSION;
}
static inline int
izo_ioctl_pack(struct izo_ioctl_data *data, char **pbuf, int max)
{
char *ptr;
struct izo_ioctl_data *overlay;
data->ioc_len = izo_ioctl_packlen(data);
data->ioc_version = IZO_IOCTL_VERSION;
if (*pbuf && izo_ioctl_packlen(data) > max)
return 1;
if (*pbuf == NULL)
*pbuf = malloc(data->ioc_len);
if (*pbuf == NULL)
return 1;
overlay = (struct izo_ioctl_data *)*pbuf;
memcpy(*pbuf, data, sizeof(*data));
ptr = overlay->ioc_bulk;
if (data->ioc_inlbuf1)
LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
if (data->ioc_inlbuf2)
LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
if (izo_ioctl_is_invalid(overlay))
return 1;
return 0;
}
#endif /* __KERNEL__*/
#define IZO_ERROR_NAME 1
#define IZO_ERROR_UPDATE 2
#define IZO_ERROR_DELETE 3
#define IZO_ERROR_RENAME 4
static inline char *izo_error(int err)
{
#ifndef __KERNEL__
if (err <= 0)
return strerror(-err);
#endif
switch (err) {
case IZO_ERROR_NAME:
return "InterMezzo name/name conflict";
case IZO_ERROR_UPDATE:
return "InterMezzo update/update conflict";
case IZO_ERROR_DELETE:
return "InterMezzo update/delete conflict";
case IZO_ERROR_RENAME:
return "InterMezzo rename/rename conflict";
}
return "Unknown InterMezzo error";
}
/* kml_unpack.c */
char *kml_print_rec(struct kml_rec *rec, int brief);
int kml_unpack(struct kml_rec *rec, char **buf, char *end);
#endif