1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
|
/* -*- 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;
};
static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data);
#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 struct file_system_type presto_fs_type;
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);
inline 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);
inline 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);
inline 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);
inline 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 inline void presto_cache_add(struct presto_cache *cache, kdev_t dev);
extern inline 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
__inline__ 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 *);
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);
/* 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;
tmp = kmalloc(strlen(str) + 1, GFP_KERNEL);
if (tmp)
memcpy(tmp, str, strlen(str) + 1);
return tmp;
}
/* 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 int izo_ioctl_packlen(struct izo_ioctl_data *data);
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";
}
static inline 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;
}
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;
}
/* 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
|