I'll send a separate mail to eng, but BE CAREFUL WHEN MERGING.
Merging into b1_2 or b_cray is fine, but be careful when you merge
into HEAD! If you want my help, please ask.
subdir-m += obdfilter
subdir-m += ost
subdir-m += llite
-subdir-m += cobd
-
-ifeq ($(PATCHLEVEL),4)
-subdir-m += ptlbd
-endif # PATCHLEVEL = 4
-
-@SNAPFS_TRUE@subdir-m += snapfs
-@SMFS_TRUE@subdir-m += smfs
@INCLUDE_RULES@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = include ldiskfs lvfs obdclass lov ldlm ptlrpc \
- obdecho osc mdc mds obdfilter ost llite cobd ptlbd snapfs smfs \
+ obdecho osc mdc mds obdfilter ost llite \
liblustre doc utils tests conf scripts autoconf
EXTRA_DIST = BUGS FDL kernel_patches
])
#
-# LC_CONFIG_SNAPFS
-#
-# Whether snapfs is desired
-#
-AC_DEFUN([LC_CONFIG_SNAPFS],
-[# snap compilation
-AC_MSG_CHECKING([whether to enable snapfs support])
-AC_ARG_ENABLE([snapfs],
- AC_HELP_STRING([--enable-snapfs],
- [build snapfs]),
- [],[enable_snapfs='no'])
-AC_MSG_RESULT([$enable_snapfs])
-])
-
-#
-# LC_CONFIG_SMFS
-#
-# whether smfs is desired
-#
-AC_DEFUN([LC_CONFIG_SMFS],
-[AC_MSG_CHECKING([whether to enable smfs support])
-AC_ARG_ENABLE([smfs],
- AC_HELP_STRING([--enable-smfs],
- [build smfs]),
- [],[enable_smfs='no'])
-AC_MSG_RESULT([$enable_smfs])
-])
-
-#
# LC_PROG_LINUX
#
# Lustre linux kernel checks
AM_CONDITIONAL(LDISKFS, test x$enable_ldiskfs = xyes)
AM_CONDITIONAL(USE_QUILT, test x$QUILT != xno)
AM_CONDITIONAL(MPITESTS, test x$enable_mpitests = xyes, Build MPI Tests)
-AM_CONDITIONAL(SNAPFS, test x$enable_snapfs = xyes)
-AM_CONDITIONAL(SMFS, test x$enable_smfs = xyes)
AM_CONDITIONAL(LIBLUSTRE, test x$enable_liblustre = xyes)
AM_CONDITIONAL(MPITESTS, test x$enable_mpitests = xyes, Build MPI Tests)
])
lustre/Makefile
lustre/autoMakefile
lustre/autoconf/Makefile
-lustre/cobd/Makefile
-lustre/cobd/autoMakefile
lustre/conf/Makefile
lustre/doc/Makefile
lustre/include/Makefile
lustre/osc/autoMakefile
lustre/ost/Makefile
lustre/ost/autoMakefile
-lustre/ptlbd/Makefile
-lustre/ptlbd/autoMakefile
lustre/ptlrpc/Makefile
lustre/ptlrpc/autoMakefile
lustre/scripts/Makefile
lustre/scripts/version_tag.pl
-lustre/smfs/Makefile
-lustre/smfs/autoMakefile
-lustre/snapfs/Makefile
-lustre/snapfs/autoMakefile
-lustre/snapfs/utils/Makefile
lustre/tests/Makefile
lustre/utils/Lustre/Makefile
lustre/utils/Makefile
+++ /dev/null
-.deps
-Makefile
-autoMakefile.in
-autoMakefile
-*.ko
-*.mod.c
-.*.cmd
-.*.flags
-.tmp_versions
-.depend
+++ /dev/null
-MODULES := cobd
-cobd-objs := cache_obd.o lproc_cache.o
-
-@INCLUDE_RULES@
+++ /dev/null
-# Copyright (C) 2002 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-if MODULES
-modulefs_DATA := cobd$(KMODEXT)
-endif
-
-DIST_SOURCES = $(cobd-objs:.o=.c)
-MOSTLYCLEANFILES = *.o *.ko *.mod.c
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
- * Copyright (c) 2003 Hewlett-Packard Development Company, LP.
- * Developed under the sponsorship of the US Government under
- * Subcontract No. B514193
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_COBD
-
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_idl.h>
-#include <linux/obd_class.h>
-#include <linux/obd_cache.h>
-
-static int cobd_setup (struct obd_device *obd, obd_count len, void *buf)
-{
- struct lustre_cfg *lcfg = (struct lustre_cfg *)buf;
- struct cache_obd *cobd = &obd->u.cobd;
- struct obd_device *target;
- struct obd_device *cache;
- struct obd_uuid target_uuid;
- struct obd_uuid cache_uuid;
- struct lustre_handle target_conn = {0,}, cache_conn = {0,};
- struct lprocfs_static_vars lvars;
- int rc;
-
- if (lcfg->lcfg_inlbuf1 == NULL || lcfg->lcfg_inlbuf2 == NULL)
- return (-EINVAL);
-
- obd_str2uuid(&target_uuid, lcfg->lcfg_inlbuf1);
- target = class_uuid2obd (&target_uuid);
-
- obd_str2uuid(&cache_uuid, lcfg->lcfg_inlbuf2);
- cache = class_uuid2obd (&cache_uuid);
- if (target == NULL ||
- cache == NULL)
- return (-EINVAL);
-
- /* don't bother checking attached/setup;
- * obd_connect() should, and it can change underneath us */
- rc = obd_connect(&target_conn, target, &target_uuid);
- if (rc != 0)
- return (rc);
- cobd->cobd_target_exp = class_conn2export(&target_conn);
-
- rc = obd_connect(&cache_conn, cache, &cache_uuid);
- if (rc != 0) {
- obd_disconnect(cobd->cobd_target_exp, 0);
- return rc;
- }
- cobd->cobd_cache_exp = class_conn2export(&cache_conn);
-
- lprocfs_init_vars(cobd, &lvars);
- lprocfs_obd_setup(obd, lvars.obd_vars);
-
- return 0;
-}
-
-static int cobd_cleanup(struct obd_device *obd, int flags)
-{
- struct cache_obd *cobd = &obd->u.cobd;
- int rc;
-
- if (!list_empty(&obd->obd_exports))
- return (-EBUSY);
-
- lprocfs_obd_cleanup(obd);
-
- rc = obd_disconnect(cobd->cobd_cache_exp, flags);
- if (rc != 0)
- CERROR("error %d disconnecting cache\n", rc);
-
- rc = obd_disconnect(cobd->cobd_target_exp, flags);
- if (rc != 0)
- CERROR("error %d disconnecting target\n", rc);
-
- return (0);
-}
-
-static int
-cobd_connect (struct lustre_handle *conn, struct obd_device *obd,
- struct obd_uuid *cluuid)
-{
- int rc = class_connect (conn, obd, cluuid);
-
- CERROR ("rc %d\n", rc);
- return (rc);
-}
-
-static int cobd_disconnect(struct obd_export *exp, int flags)
-{
- int rc = class_disconnect(exp, flags);
-
- CERROR ("rc %d\n", rc);
- return (rc);
-}
-
-static int cobd_get_info(struct obd_export *exp, obd_count keylen,
- void *key, __u32 *vallen, void *val)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client cookie "LPX64"\n",
- exp->exp_handle.h_cookie);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
-
- /* intercept cache utilisation info? */
-
- return obd_get_info(cobd->cobd_target_exp, keylen, key, vallen, val);
-}
-
-static int cobd_statfs(struct obd_device *obd, struct obd_statfs *osfs,
- unsigned long max_age)
-{
- return obd_statfs(class_exp2obd(obd->u.cobd.cobd_target_exp), osfs,
- max_age);
-}
-
-static int cobd_getattr(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client cookie "LPX64"\n",
- exp->exp_handle.h_cookie);
- return -EINVAL;
- }
-
- cobd = &obd->u.cobd;
- return obd_getattr(cobd->cobd_target_exp, oa, lsm);
-}
-
-static int cobd_preprw(int cmd, struct obd_export *exp, struct obdo *oa,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *nb,
- struct niobuf_local *res, struct obd_trans_info *oti)
-{
- struct obd_export *cobd_exp;
- int rc;
-
- if (exp->exp_obd == NULL)
- return -EINVAL;
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd_exp = exp->exp_obd->u.cobd.cobd_target_exp;
- rc = obd_preprw(cmd, cobd_exp, oa, objcount, obj, niocount, nb, res,
- oti);
-
- return rc;
-}
-
-static int cobd_commitrw(int cmd, struct obd_export *exp, struct obdo *oa,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_local *local,
- struct obd_trans_info *oti, int rc)
-{
- struct obd_export *cobd_exp;
-
- if (exp->exp_obd == NULL)
- return -EINVAL;
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd_exp = exp->exp_obd->u.cobd.cobd_target_exp;
- rc = obd_commitrw(cmd, cobd_exp, oa, objcount, obj, niocount, local,
- oti, rc);
- return rc;
-}
-
-static int cobd_brw(int cmd, struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md *lsm, obd_count oa_bufs,
- struct brw_page *pga, struct obd_trans_info *oti)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client cookie "LPX64"\n",
- exp->exp_handle.h_cookie);
- return -EINVAL;
- }
-
- if ((cmd & OBD_BRW_WRITE) != 0)
- return -EOPNOTSUPP;
-
- cobd = &obd->u.cobd;
- return obd_brw(cmd, cobd->cobd_target_exp, oa, lsm, oa_bufs, pga, oti);
-}
-
-static int cobd_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obd = class_exp2obd(exp);
- struct cache_obd *cobd;
-
- if (obd == NULL) {
- CERROR("invalid client cookie "LPX64"\n",
- exp->exp_handle.h_cookie);
- return -EINVAL;
- }
-
- /* intercept? */
-
- cobd = &obd->u.cobd;
- return obd_iocontrol(cmd, cobd->cobd_target_exp, len, karg, uarg);
-}
-
-static struct obd_ops cobd_ops = {
- .o_owner = THIS_MODULE,
-
- .o_setup = cobd_setup,
- .o_cleanup = cobd_cleanup,
-
- .o_connect = cobd_connect,
- .o_disconnect = cobd_disconnect,
-
- .o_get_info = cobd_get_info,
- .o_statfs = cobd_statfs,
-
- .o_getattr = cobd_getattr,
- .o_preprw = cobd_preprw,
- .o_commitrw = cobd_commitrw,
- .o_brw = cobd_brw,
- .o_iocontrol = cobd_iocontrol,
-};
-
-static int __init cobd_init(void)
-{
- struct lprocfs_static_vars lvars;
- ENTRY;
-
- printk(KERN_INFO "Lustre: Caching OBD driver; info@clusterfs.com\n");
-
- lprocfs_init_vars(cobd, &lvars);
- RETURN(class_register_type(&cobd_ops, lvars.module_vars,
- OBD_CACHE_DEVICENAME));
-}
-
-static void /*__exit*/ cobd_exit(void)
-{
- class_unregister_type(OBD_CACHE_DEVICENAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Caching OBD driver");
-MODULE_LICENSE("GPL");
-
-module_init(cobd_init);
-module_exit(cobd_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/obd_class.h>
-#include <linux/lprocfs_status.h>
-
-#ifndef LPROCFS
-static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
-static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
-#else
-/* Common STATUS namespace */
-static int cobd_rd_target(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device *cobd = (struct obd_device *)data;
- int rc;
-
- LASSERT(cobd != NULL);
-
- if (!cobd->obd_set_up) {
- rc = snprintf(page, count, "not set up\n");
- } else {
- struct obd_device *tgt =
- class_exp2obd(cobd->u.cobd.cobd_target_exp);
- LASSERT(tgt != NULL);
- rc = snprintf(page, count, "%s\n", tgt->obd_uuid.uuid);
- }
- return rc;
-}
-
-static int cobd_rd_cache(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct obd_device *cobd = (struct obd_device*)data;
- int rc;
-
- LASSERT(cobd != NULL);
-
- if (!cobd->obd_set_up) {
- rc = snprintf(page, count, "not set up\n");
- } else {
- struct obd_device *cache =
- class_exp2obd(cobd->u.cobd.cobd_cache_exp);
- LASSERT(cache != NULL);
- rc = snprintf(page, count, "%s\n", cache->obd_uuid.uuid);
- }
- return rc;
-}
-
-static struct lprocfs_vars lprocfs_obd_vars[] = {
- { "uuid", lprocfs_rd_uuid, 0, 0 },
- { "target_uuid", cobd_rd_target, 0, 0 },
- { "cache_uuid", cobd_rd_cache, 0, 0 },
- { 0 }
-};
-
-struct lprocfs_vars lprocfs_module_vars[] = {
- { "num_refs", lprocfs_rd_numrefs, 0, 0 },
- { 0 }
-};
-#endif /* LPROCFS */
-
-LPROCFS_INIT_VARS(cobd, lprocfs_module_vars, lprocfs_obd_vars)
AC_MSG_RESULT([$enable_mpitests])
AM_CONDITIONAL(MPITESTS, test x$enable_mpitests = xyes, Build MPI Tests)
-# snap compilation
-AC_MSG_CHECKING([whether to enable snapfs support])
-AC_ARG_ENABLE([snapfs],
- AC_HELP_STRING([--enable-snapfs],
- [build snapfs]),
- [],[enable_snapfs='no'])
-AC_MSG_RESULT([$enable_snapfs])
-AM_CONDITIONAL(SNAPFS, test x$enable_snapfs = xyes)
-
-# smfs compilation
-AC_MSG_CHECKING([whether to enable smfs support])
-AC_ARG_ENABLE([smfs],
- AC_HELP_STRING([--enable-smfs],
- [build smfs]),
- [],[enable_smfs='no'])
-AC_MSG_RESULT([$enable_smfs])
-AM_CONDITIONAL(SMFS, test x$enable_smfs = xyes)
-
sinclude(portals/build.m4)
sinclude(portals/archdep.m4)
Makefile
Rules
autoMakefile
-cobd/Makefile
-cobd/autoMakefile
conf/Makefile
doc/Makefile
include/Makefile
portals/tests/autoMakefile
portals/unals/Makefile
portals/utils/Makefile
-ptlbd/Makefile
-ptlbd/autoMakefile
ptlrpc/Makefile
ptlrpc/autoMakefile
scripts/Makefile
scripts/lustre.spec
scripts/version_tag.pl
-smfs/Makefile
-smfs/autoMakefile
-snapfs/Makefile
-snapfs/autoMakefile
-snapfs/utils/Makefile
tests/Makefile
utils/Lustre/Makefile
utils/Makefile
+++ /dev/null
-.deps
-Makefile
-autoMakefile.in
-autoMakefile
-*.ko
-*.mod.c
-.*.flags
-.tmp_versions
-.depend
+++ /dev/null
-MODULES := ptlbd
-ptlbd-objs := blk.o client.o main.o rpc.o server.o
-
-@INCLUDE_RULES@
+++ /dev/null
-# Copyright (C) 2002 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-if MODULES
-if !LINUX25
-modulefs_DATA = ptlbd$(KMODEXT)
-endif
-endif
-
-MOSTLYCLEANFILES = *.o *.ko *.mod.c
-DIST_SOURCES = $(ptlbd-objs:%.o=%.c)
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- * Author: Zach Brown <zab@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/module.h>
-#include <linux/major.h>
-#include <linux/smp.h>
-#include <linux/hdreg.h>
-
-#define DEBUG_SUBSYSTEM S_PTLBD
-
-#include <linux/lustre_ha.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_idl.h>
-#include <linux/obd_ptlbd.h>
-
-/*
- * todo:
- * assign proper major number
- * allow more minors
- * discover actual block sizes?
- * allow more than one sector per io
- * think about vary-io
- * restrict single ops to sequential block io
- * ddn target addresses need to be 32 bit
- * cant get to addresses after 0xFFFF0000
- */
-
-#define PTLBD_MAJOR 253
-#define PTLBD_MAX_MINOR 1
-
-#define MAJOR_NR PTLBD_MAJOR
-#define LOCAL_END_REQUEST
-#include <linux/blk.h>
-#include <linux/blkdev.h>
-#include <linux/blkpg.h>
-#include <linux/devfs_fs_kernel.h>
-
-static int ptlbd_size_size[PTLBD_MAX_MINOR];
-static int ptlbd_size[PTLBD_MAX_MINOR];
-static int ptlbd_hardsect_size[PTLBD_MAX_MINOR];
-static int ptlbd_max_sectors[PTLBD_MAX_MINOR];
-//RHism static char ptlbd_dev_varyio[PTLBD_MAX_MINOR];
-
-/*
- * per minor state, indexed by minor.
- */
-
-static struct ptlbd_obd *one_for_now;
-
-void ptlbd_blk_register(struct ptlbd_obd *ptlbd)
-{
- ENTRY;
- one_for_now = ptlbd;
- EXIT;
-}
-
-static struct ptlbd_obd * ptlbd_get_minor(int minor)
-{
- ENTRY;
- if ( minor >= PTLBD_MAX_MINOR )
- RETURN( ERR_PTR(-ENODEV) );
- RETURN(one_for_now);
-}
-
-static struct ptlbd_obd * ptlbd_get_inode(struct inode *inode)
-{
- ENTRY;
-
- if ( inode == NULL ) /* can this really happen? */
- RETURN( ERR_PTR(-EINVAL) );
-
- return ptlbd_get_minor(MINOR(inode->i_rdev));
-}
-
-static int ptlbd_open(struct inode *inode, struct file *file)
-{
- struct ptlbd_obd *ptlbd = ptlbd_get_inode(inode);
- ENTRY;
-
-
- if ( IS_ERR(ptlbd) )
- RETURN(PTR_ERR(ptlbd));
-
- if (! ptlbd->bd_import->imp_remote_handle.cookie)
- if (ptlbd_do_connect(ptlbd))
- RETURN(-ENOTCONN);
-
- ptlbd->refcount++;
- RETURN(0);
-}
-
-
-static int ptlbd_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct ptlbd_obd *ptlbd;
- int ret;
- __u16 major, minor, dev;
- struct hd_geometry geo;
-
- if ( ! capable(CAP_SYS_ADMIN) )
- RETURN(-EPERM);
-
- ptlbd = ptlbd_get_inode(inode);
- if ( IS_ERR(ptlbd) )
- RETURN( PTR_ERR(ptlbd) );
-
- major = MAJOR(inode->i_rdev);
- minor = MINOR(inode->i_rdev);
- dev = inode->i_rdev;
-
- switch(cmd) {
- case HDIO_GETGEO:
- geo.heads = 64;
- geo.sectors = 32;
- geo.start = 4;
- geo.cylinders = blk_size[major][minor]/
- (geo.heads * geo.sectors);
- if (copy_to_user((void *) arg, &geo, sizeof(geo)))
- ret = -EFAULT;
- else
- ret = 0;
- break;
-
- case BLKSECTGET:
- ret = copy_to_user((void *) arg,
- & max_sectors[major][minor], sizeof(arg));
- break;
-
- case BLKFLSBUF:
- ret = blk_ioctl(dev, cmd, arg);
- ptlbd_send_flush_req(ptlbd, PTLBD_FLUSH);
- break;
-
- case BLKGETSIZE:
- case BLKGETSIZE64:
- case BLKROSET:
- case BLKROGET:
- case BLKRASET:
- case BLKRAGET:
- case BLKSSZGET:
- case BLKELVGET:
- case BLKELVSET:
- default:
- ret = blk_ioctl(dev, cmd, arg);
- break;
-
- case BLKSECTSET: /* don't allow setting of max_sectors */
-
- case BLKRRPART: /* not a partitionable device */
- case BLKPG: /* "" */
- ret = -EINVAL;
- break;
- }
-
- RETURN(ret);
-}
-
-static int ptlbd_release(struct inode *inode, struct file *file)
-{
- struct ptlbd_obd *ptlbd = ptlbd_get_inode(inode);
- ENTRY;
-
- if ( IS_ERR(ptlbd) )
- RETURN( PTR_ERR(ptlbd) );
-
- if (--ptlbd->refcount == 0)
- ptlbd_do_disconnect(ptlbd);
-
- RETURN(0);
-}
-
-static void ptlbd_end_request_havelock(struct request *req)
-{
- struct buffer_head *bh;
- int uptodate = 1;
-
- if ( req->errors )
- uptodate = 0;
-
- while( (bh = req->bh) != NULL ) {
- blk_finished_io(bh->b_size >> 9);
- req->bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
- bh->b_end_io(bh, uptodate);
- }
- blkdev_release_request(req);
-}
-
-#if 0
-static void ptlbd_end_request_getlock(struct request *req)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock, flags);
- ptlbd_end_request_havelock(req);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-#endif
-
-static void ptlbd_request(request_queue_t *q)
-{
- struct ptlbd_obd *ptlbd;
- struct request *req;
- ptlbd_cmd_t cmd;
- int errors = 0;
- ENTRY;
-
- while ( !QUEUE_EMPTY ) {
- req = CURRENT;
- ptlbd = ptlbd_get_minor(MINOR(req->rq_dev));
-
- blkdev_dequeue_request(req);
-
- if ( ptlbd->refcount <= 0 ) {
- req->errors++;
- ptlbd_end_request_havelock(req);
- return;
- }
-
- spin_unlock_irq(&io_request_lock);
-
- if ( req->cmd == READ )
- cmd = PTLBD_READ;
- else
- cmd = PTLBD_WRITE;
-
- errors = ptlbd_send_rw_req(ptlbd, cmd, req->bh);
-
- spin_lock_irq(&io_request_lock);
-
- if (errors)
- req->errors += errors;
-
- ptlbd_end_request_havelock(req);
- }
-}
-
-static struct block_device_operations ptlbd_ops = {
- .owner = THIS_MODULE,
- .open = ptlbd_open,
- .ioctl = ptlbd_ioctl,
- .release = ptlbd_release,
-};
-
-int ptlbd_blk_init(void)
-{
- int ret;
- int i;
- ENTRY;
-
- ret = register_blkdev(PTLBD_MAJOR, "ptlbd", &ptlbd_ops);
- if ( ret < 0 )
- RETURN(ret);
-
- blk_size[PTLBD_MAJOR] = ptlbd_size;
- blksize_size[PTLBD_MAJOR] = ptlbd_size_size;
- hardsect_size[PTLBD_MAJOR] = ptlbd_hardsect_size;
- max_sectors[PTLBD_MAJOR] = ptlbd_max_sectors;
-
- blk_init_queue(BLK_DEFAULT_QUEUE(PTLBD_MAJOR), ptlbd_request);
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
-
- for ( i = 0 ; i < PTLBD_MAX_MINOR ; i++) {
- ptlbd_size_size[i] = 4096;
- /* avoid integer overflow */
- ptlbd_size[i] = (16*1024*((1024*1024) >> BLOCK_SIZE_BITS));
- ptlbd_hardsect_size[i] = 4096;
- ptlbd_max_sectors[i] = PTLRPC_MAX_BRW_PAGES * (4096/512);
- }
-
- return 0;
-}
-
-void ptlbd_blk_exit(void)
-{
- ENTRY;
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(PTLBD_MAJOR));
- unregister_blkdev(PTLBD_MAJOR, "ptlbd");
-}
-
-#undef MAJOR_NR
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- * Author: Zach Brown <zab@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-
-#define DEBUG_SUBSYSTEM S_PTLBD
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_debug.h>
-#include <linux/lprocfs_status.h>
-#include <linux/obd_ptlbd.h>
-
-static int ptlbd_cl_setup(struct obd_device *obd, obd_count len, void *buf)
-{
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- struct lprocfs_static_vars lvars;
- struct obd_import *imp;
- struct lustre_cfg* lcfg = buf;
- ENTRY;
-
- if (ptlbd->bd_import != NULL)
- RETURN(-EALREADY);
-
- if (lcfg->lcfg_inllen1 < 1) {
- CERROR("requires a PTLBD server UUID\n");
- RETURN(-EINVAL);
- }
-
- if (lcfg->lcfg_inllen1 > 37) {
- CERROR("PTLBD server UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- obd_str2uuid(&ptlbd->bd_server_uuid, lcfg->lcfg_inlbuf1);
-
- /*
- * from client_obd_connect.. *shrug*
- */
- imp = ptlbd->bd_import = class_new_import();
- imp->imp_connection = ptlrpc_uuid_to_connection(&ptlbd->bd_server_uuid);
- if (!imp->imp_connection) {
- class_destroy_import(imp);
- class_import_put(imp);
- RETURN(-ENOENT);
- }
- imp->imp_state = LUSTRE_IMP_FULL;
-
- ptlrpc_init_client(PTLBD_REQUEST_PORTAL, PTLBD_REPLY_PORTAL,
- "ptlbd", &ptlbd->bd_client);
- imp->imp_client = &ptlbd->bd_client;
- imp->imp_obd = obd;
- memcpy(imp->imp_target_uuid.uuid, lcfg->lcfg_inlbuf1,
- lcfg->lcfg_inllen1);
- ptlbd_blk_register(ptlbd);
-
- lprocfs_init_vars(ptlbd_cl, &lvars);
- lprocfs_obd_setup(obd, lvars.obd_vars);
-
- RETURN(0);
-}
-
-static int ptlbd_cl_cleanup(struct obd_device *obd, int flags)
-{
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- struct obd_import *imp;
- ENTRY;
-
- if ((!ptlbd) || (!(imp = ptlbd->bd_import)))
- RETURN(-ENOENT);
-
- if (!imp->imp_connection)
- RETURN(-ENOENT);
-
- lprocfs_obd_cleanup(obd);
-
- ptlrpc_cleanup_client(imp);
- ptlrpc_put_connection(imp->imp_connection);
-
- class_destroy_import(imp);
- class_import_put(imp);
-
- RETURN(0);
-}
-
-
-/* modelled after ptlrpc_import_connect() */
-int ptlbd_cl_connect(struct lustre_handle *conn, struct obd_device *obd,
- struct obd_uuid *target_uuid)
-{
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- struct obd_import *imp = ptlbd->bd_import;
- struct obd_export *exp;
- struct ptlrpc_request *request;
- int rc, size[] = {sizeof(imp->imp_target_uuid),
- sizeof(obd->obd_uuid),
- sizeof(*conn)};
- char *tmp[] = {imp->imp_target_uuid.uuid,
- obd->obd_uuid.uuid,
- (char*)conn};
- ENTRY;
-
- if (!conn || !obd || !target_uuid)
- RETURN(-EINVAL);
-
- rc = class_connect(conn, obd, target_uuid);
- if (rc)
- RETURN(rc);
- exp = class_conn2export(conn);
-
- request = ptlrpc_prep_req(imp, PTLBD_CONNECT, 3, size, tmp);
- if (!request)
- GOTO(out_disco, rc = -ENOMEM);
- request->rq_send_state = LUSTRE_IMP_NEW;
- request->rq_replen = lustre_msg_size(0, NULL);
-
- imp->imp_dlm_handle = *conn;
-
- imp->imp_state = LUSTRE_IMP_NEW;
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_req, rc);
-
- exp->exp_connection = ptlrpc_connection_addref(imp->imp_connection);
-
- imp->imp_state = LUSTRE_IMP_FULL;
- imp->imp_remote_handle = request->rq_repmsg->handle;
-
-out_req:
- ptlrpc_req_finished(request);
-out_disco:
- if (rc)
- class_disconnect(exp, 0);
- class_export_put(exp);
- RETURN(rc);
-}
-
-
-/* modelled after ptlrpc_import_disconnect() */
-int ptlbd_cl_disconnect(struct obd_export *exp, int failover)
-{
- struct obd_device *obd = exp->exp_obd;
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- struct obd_import *imp = ptlbd->bd_import;
- struct ptlrpc_request *request;
- int rc, err;
- ENTRY;
-
- if (!obd)
- RETURN(-EINVAL);
-
- request = ptlrpc_prep_req(imp, PTLBD_DISCONNECT, 0, NULL, NULL);
- if (!request)
- GOTO(out_req, rc = -ENOMEM);
-
- request->rq_replen = lustre_msg_size(0, NULL);
- request->rq_send_state = LUSTRE_IMP_FULL;
-
- rc = ptlrpc_queue_wait(request);
-
-out_req:
- if (request)
- ptlrpc_req_finished(request);
- err = class_disconnect(exp, 0);
- memset(&imp->imp_remote_handle, 0, sizeof(imp->imp_remote_handle));
- if (!rc && err)
- rc = err;
- RETURN(rc);
-}
-
-
-static struct obd_ops ptlbd_cl_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = ptlbd_cl_setup,
- .o_cleanup = ptlbd_cl_cleanup,
- .o_connect = ptlbd_cl_connect,
- .o_disconnect = ptlbd_cl_disconnect,
-};
-
-static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
-static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
-LPROCFS_INIT_VARS(ptlbd_cl, lprocfs_module_vars, lprocfs_obd_vars)
-
-int ptlbd_cl_init(void)
-{
- struct lprocfs_static_vars lvars;
-
- lprocfs_init_vars(ptlbd_cl,&lvars);
- return class_register_type(&ptlbd_cl_obd_ops, lvars.module_vars,
- OBD_PTLBD_CL_DEVICENAME);
-}
-
-void ptlbd_cl_exit(void)
-{
- class_unregister_type(OBD_PTLBD_CL_DEVICENAME);
-}
-
-
-
-int ptlbd_do_connect(struct ptlbd_obd *ptlbd)
-{
- int rc;
- struct obd_device *obd = ptlbd->bd_import->imp_obd;
- struct lustre_handle conn;
- ENTRY;
-
- memset(&conn, 0, sizeof(conn));
- rc = obd_connect(&conn, obd, &ptlbd->bd_server_uuid);
- if (rc < 0)
- RETURN(rc);
- ptlbd->bd_exp = class_conn2export(&conn);
- RETURN(rc);
-}
-
-
-int ptlbd_do_disconnect(struct ptlbd_obd *ptlbd)
-{
- int rc;
- ENTRY;
-
- rc = obd_disconnect(ptlbd->bd_exp, 0);
- RETURN(rc);
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/smp.h>
-
-#define DEBUG_SUBSYSTEM S_PTLBD
-
-#include <linux/lustre_ha.h>
-#include <linux/obd_support.h>
-
-#include <linux/obd_ptlbd.h>
-
-static int __init ptlbd_init(void)
-{
- int ret;
- ENTRY;
-
- ret = ptlbd_cl_init();
- if ( ret < 0 )
- RETURN(ret);
-
- ret = ptlbd_sv_init();
- if ( ret < 0 )
- GOTO(out_cl, ret);
-
- ret = ptlbd_blk_init();
- if ( ret < 0 )
- GOTO(out_sv, ret);
-
- RETURN(0);
-
-out_sv:
- ptlbd_sv_exit();
-out_cl:
- ptlbd_cl_exit();
- RETURN(ret);
-}
-
-static void /*__exit*/ ptlbd_exit(void)
-{
- ENTRY;
- ptlbd_cl_exit();
- ptlbd_sv_exit();
- ptlbd_blk_exit();
- EXIT;
-}
-
-module_init(ptlbd_init);
-module_exit(ptlbd_exit);
-MODULE_LICENSE("GPL");
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- * Author: Zach Brown <zab@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-
-#define DEBUG_SUBSYSTEM S_PTLBD
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_debug.h>
-#include <linux/lprocfs_status.h>
-#include <linux/obd_ptlbd.h>
-
-int ptlbd_send_rw_req(struct ptlbd_obd *ptlbd, ptlbd_cmd_t cmd,
- struct buffer_head *first_bh)
-{
- struct obd_import *imp = ptlbd->bd_import;
- struct ptlbd_op *op;
- struct ptlbd_niob *niob, *niobs;
- struct ptlbd_rsp *rsp;
- struct ptlrpc_request *req;
- struct ptlrpc_bulk_desc *desc;
- struct buffer_head *bh;
- unsigned int page_count;
- int rc, rep_size, size[2];
- ENTRY;
-
- LASSERT(cmd == PTLBD_READ || cmd == PTLBD_WRITE);
-
- for ( page_count = 0, bh = first_bh ; bh ; bh = bh->b_reqnext )
- page_count++;
-
- size[0] = sizeof(struct ptlbd_op);
- size[1] = page_count * sizeof(struct ptlbd_niob);
-
- req = ptlrpc_prep_req(imp, cmd, 2, size, NULL);
- if (!req)
- RETURN(rc = 1); /* need to return error cnt */
-
- op = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*op));
- niobs = lustre_msg_buf(req->rq_reqmsg, 1, size[1]);
-
- /* XXX pack */
- op->op_cmd = cmd;
- op->op_lun = 0;
- op->op_niob_cnt = page_count;
- op->op__padding = 0;
- op->op_block_cnt = page_count;
-
- if (cmd == PTLBD_READ)
- desc = ptlrpc_prep_bulk_imp (req, page_count,
- BULK_PUT_SINK, PTLBD_BULK_PORTAL);
- else
- desc = ptlrpc_prep_bulk_imp (req, page_count,
- BULK_GET_SOURCE, PTLBD_BULK_PORTAL);
- if ( desc == NULL )
- GOTO(out, rc = 1); /* need to return error cnt */
- /* NB req now owns desc, and frees it when she frees herself */
-
- for ( niob = niobs, bh = first_bh ; bh ; bh = bh->b_reqnext, niob++ ) {
- ptlrpc_prep_bulk_page(desc, bh->b_page,
- bh_offset (bh) & (PAGE_SIZE - 1),
- bh->b_size);
-
- niob->n_block_nr = bh->b_blocknr;
- niob->n_offset = bh_offset(bh);
- niob->n_length = bh->b_size;
- }
-
- rep_size = sizeof(struct ptlbd_rsp);
- req->rq_replen = lustre_msg_size(1, &rep_size);
-
- /* XXX find out how we're really supposed to manage levels */
- req->rq_send_state = imp->imp_state;
- rc = ptlrpc_queue_wait(req);
-
- if ( rc != 0 )
- GOTO(out, rc = 1); /* need to return error count */
-
- rsp = lustre_swab_repbuf(req, 0, sizeof (*rsp),
- lustre_swab_ptlbd_rsp);
- if (rsp == NULL) {
- CERROR ("can't unpack response\n");
- GOTO (out, rc = 1); /* need to return error count */
- }
- else if (rsp->r_status != 0) {
- rc = rsp->r_error_cnt;
- }
-
-out:
- ptlrpc_req_finished(req);
- RETURN(rc);
-}
-
-
-int ptlbd_send_flush_req(struct ptlbd_obd *ptlbd, ptlbd_cmd_t cmd)
-{
- struct obd_import *imp = ptlbd->bd_import;
- struct ptlbd_op *op;
- struct ptlbd_rsp *rsp;
- struct ptlrpc_request *req;
- int rc, rep_size, size[1];
- ENTRY;
-
- LASSERT(cmd == PTLBD_FLUSH);
-
- size[0] = sizeof(struct ptlbd_op);
-
- req = ptlrpc_prep_req(imp, cmd, 1, size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- op = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*op));
-
- /* XXX pack */
- op->op_cmd = cmd;
- op->op_lun = 0;
- op->op_niob_cnt = 0;
- op->op__padding = 0;
- op->op_block_cnt = 0;
-
- rep_size = sizeof(struct ptlbd_rsp);
- req->rq_replen = lustre_msg_size(1, &rep_size);
-
- /* XXX find out how we're really supposed to manage levels */
- req->rq_send_state = imp->imp_state;
-
- rc = ptlrpc_queue_wait(req);
- if ( rc != 0 )
- GOTO(out_req, rc = 1);
- rsp = lustre_swab_repbuf(req, 0, sizeof (*rsp),
- lustre_swab_ptlbd_rsp);
- if (rsp->r_status != 0)
- rc = rsp->r_status;
-
-out_req:
- ptlrpc_req_finished(req);
- RETURN(rc);
-}
-
-
-int ptlbd_do_filp(struct file *filp, int op, struct ptlbd_niob *niobs,
- int page_count, struct list_head *page_list)
-{
- mm_segment_t old_fs;
- struct list_head *pos;
- int status = 0;
- ENTRY;
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- list_for_each(pos, page_list) {
- ssize_t ret;
- struct page *page = list_entry(pos, struct page, list);
- loff_t offset = (niobs->n_block_nr << PAGE_SHIFT) +
- niobs->n_offset;
- if ( op == PTLBD_READ )
- ret = filp->f_op->read(filp, page_address(page),
- niobs->n_length, &offset);
- else
- ret = filp->f_op->write(filp, page_address(page),
- niobs->n_length, &offset);
- if (ret != niobs->n_length) {
- status = ret;
- break;
- }
- niobs++;
- }
- set_fs(old_fs);
- RETURN(status);
-}
-
-
-int ptlbd_srv_rw_req(ptlbd_cmd_t cmd, __u16 index,
- struct ptlrpc_request *req, int swab)
-{
- struct ptlbd_niob *niob, *niobs;
- struct ptlbd_rsp *rsp;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct file *filp = req->rq_export->exp_obd->u.ptlbd.filp;
- struct l_wait_info lwi;
- int size[1], i, page_count, rc = 0, error_cnt = 0;
- struct list_head *pos, *n;
- struct page *page;
- LIST_HEAD(tmp_pages);
- ENTRY;
-
- niobs = lustre_swab_reqbuf (req, 1, sizeof (*niobs),
- lustre_swab_ptlbd_niob);
- if (niobs == NULL)
- GOTO (out, rc = -EFAULT);
-
- size[0] = sizeof(struct ptlbd_rsp);
- rc = lustre_pack_reply(req, 1, size, NULL);
- if ( rc )
- GOTO(out, rc);
-
- rsp = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rsp));
- if ( rsp == NULL )
- GOTO (out, rc = -EFAULT);
-
- /* FIXME: assumes each niobuf fits in 1 page */
- page_count = req->rq_reqmsg->buflens[1] / sizeof(struct ptlbd_niob);
- if (swab) { /* swab remaining niobs */
- for (i = 1; i < page_count; i++)
- lustre_swab_ptlbd_niob(&niobs[i]);
- }
- if (req->rq_export == NULL) {
- error_cnt++;
- GOTO(out_reply, rc = -EFAULT);
- }
-
- if (cmd == PTLBD_READ)
- desc = ptlrpc_prep_bulk_exp (req, page_count,
- BULK_PUT_SOURCE, PTLBD_BULK_PORTAL);
- else
- desc = ptlrpc_prep_bulk_exp (req, page_count,
- BULK_GET_SINK, PTLBD_BULK_PORTAL);
- if (desc == NULL) {
- error_cnt++;
- GOTO(out_reply, rc = -ENOMEM);
- }
- desc->bd_portal = PTLBD_BULK_PORTAL;
- LASSERT (page_count > 0);
-
- for ( i = 0, niob = niobs ; i < page_count; niob++, i++) {
- page = alloc_page(GFP_KERNEL);
- if (page == NULL) {
- error_cnt++;
- GOTO(out_reply, rc = -ENOMEM);
- }
- list_add_tail(&page->list, &tmp_pages);
-
- ptlrpc_prep_bulk_page(desc, page,
- niob->n_offset & (PAGE_SIZE - 1),
- niob->n_length);
- }
-
- if ( cmd == PTLBD_READ ) {
- rc = ptlbd_do_filp(filp, PTLBD_READ, niobs,
- page_count, &tmp_pages);
- if (rc < 0) {
- error_cnt++;
- GOTO(out_reply, rc);
- }
- }
- rc = ptlrpc_start_bulk_transfer(desc);
-
- if ( rc ) {
- error_cnt++;
- GOTO(out_reply, rc);
- }
-
- lwi = LWI_TIMEOUT(obd_timeout * HZ / 4, NULL, desc);
- rc = l_wait_event(desc->bd_waitq, !ptlrpc_bulk_active(desc), &lwi);
- if (rc != 0) {
- LASSERT(rc == -ETIMEDOUT);
- ptlrpc_abort_bulk(desc);
- error_cnt++;
- GOTO(out_reply, rc);
- }
-
- /* XXX do some error handling */
- LASSERT(desc->bd_success && desc->bd_nob_transferred == desc->bd_nob);
-
- if ( cmd == PTLBD_WRITE ) {
- if ((rc = ptlbd_do_filp(filp, PTLBD_WRITE, niobs,
- page_count, &tmp_pages)) < 0) {
- error_cnt++;
- }
- }
-
-out_reply:
- rsp->r_error_cnt = error_cnt;
- rsp->r_status = rc;
- req->rq_status = rc;
-
- ptlrpc_reply(req);
-
- list_for_each_safe(pos, n, &tmp_pages) {
- struct page *page = list_entry(pos, struct page, list);
- list_del(&page->list);
- __free_page(page);
- }
- if (desc)
- ptlrpc_free_bulk(desc);
-out:
- RETURN(rc);
-}
-
-
-int ptlbd_srv_flush_req(ptlbd_cmd_t cmd, __u16 index,
- struct ptlrpc_request *req)
-{
- struct ptlbd_rsp *rsp;
- struct file *filp = req->rq_export->exp_obd->u.ptlbd.filp;
- int size[1], rc, status;
- ENTRY;
-
- size[0] = sizeof(struct ptlbd_rsp);
- rc = lustre_pack_reply(req, 1, size, NULL);
- if ( rc )
- RETURN(rc);
-
- rsp = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rsp));
- if ( rsp == NULL )
- RETURN(-EINVAL);
-
- if (! (filp) && (filp->f_op) && (filp->f_op->fsync) &&
- (filp->f_dentry))
- GOTO(out_reply, status = -EINVAL);
-
- status = filp->f_op->fsync(filp, filp->f_dentry, 1);
-
-out_reply:
- rsp->r_error_cnt = 0;
- rsp->r_status = status;
- req->rq_status = 0;
-
- ptlrpc_reply(req);
- RETURN(0);
-}
-
-
-int ptlbd_handle(struct ptlrpc_request *req)
-{
- struct ptlbd_op *op;
- int swab;
- int rc;
- ENTRY;
-
- swab = lustre_msg_swabbed (req->rq_reqmsg);
-
- if (req->rq_reqmsg->opc == PTLBD_CONNECT) {
- rc = target_handle_connect(req, ptlbd_handle);
- target_send_reply(req, rc, OBD_FAIL_PTLRPC);
- RETURN(0);
- }
- if (req->rq_reqmsg->opc == PTLBD_DISCONNECT) {
- rc = target_handle_disconnect(req);
- target_send_reply(req, rc, OBD_FAIL_PTLRPC);
- RETURN(0);
- }
- op = lustre_swab_reqbuf (req, 0, sizeof (*op),
- lustre_swab_ptlbd_op);
- if (op == NULL)
- RETURN(-EFAULT);
-
- switch (op->op_cmd) {
- case PTLBD_READ:
- case PTLBD_WRITE:
- rc = ptlbd_srv_rw_req(op->op_cmd, op->op_lun, req,
- swab);
- break;
-
- case PTLBD_FLUSH:
- rc = ptlbd_srv_flush_req(op->op_cmd, op->op_lun, req);
- break;
- default:
- rc = -EINVAL;
- }
-
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
- * Author: Zach Brown <zab@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-
-#define DEBUG_SUBSYSTEM S_PTLBD
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_debug.h>
-#include <linux/lprocfs_status.h>
-#include <linux/obd_ptlbd.h>
-
-#define BACKING_FILE "/tmp/ptlbd-backing-file-la-la-la"
-
-static int ptlbd_sv_already_setup = 1;
-
-static int ptlbd_sv_setup(struct obd_device *obd, obd_count len, void *buf)
-{
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- struct lprocfs_static_vars lvars;
- int rc;
- ENTRY;
-
- ptlbd->filp = filp_open(BACKING_FILE,
- O_RDWR|O_CREAT|O_LARGEFILE, 0600);
-
- if ( IS_ERR(ptlbd->filp) )
- RETURN(PTR_ERR(ptlbd->filp));
-
- lprocfs_init_vars(ptlbd_sv, &lvars);
- lprocfs_obd_setup(obd, lvars.obd_vars);
-
- ptlbd->ptlbd_service =
- ptlrpc_init_svc(PTLBD_NBUFS, PTLBD_BUFSIZE, PTLBD_MAXREQSIZE,
- PTLBD_REQUEST_PORTAL, PTLBD_REPLY_PORTAL, 30000,
- ptlbd_handle, "ptlbd_sv",
- obd->obd_proc_entry, NULL);
-
- if (ptlbd->ptlbd_service == NULL)
- GOTO(out_filp, rc = -ENOMEM);
-
- rc = ptlrpc_start_n_threads(obd, ptlbd->ptlbd_service, 1, "ptldb");
- if (rc != 0)
- GOTO(out_thread, rc);
-
- ptlbd_sv_already_setup = 1;
-
- RETURN(0);
-
-out_thread:
- ptlrpc_unregister_service(ptlbd->ptlbd_service);
-out_filp:
- filp_close(ptlbd->filp, NULL);
- lprocfs_obd_cleanup(obd);
-
- RETURN(rc);
-}
-
-static int ptlbd_sv_cleanup(struct obd_device *obd, int flags)
-{
- struct ptlbd_obd *ptlbd = &obd->u.ptlbd;
- ENTRY;
-
- /* XXX check for state */
-
- ptlrpc_unregister_service(ptlbd->ptlbd_service);
- if ( ! IS_ERR(ptlbd->filp) )
- filp_close(ptlbd->filp, NULL);
-
- ptlbd_sv_already_setup = 0;
-
- lprocfs_obd_cleanup(obd);
-
- RETURN(0);
-}
-
-static struct obd_ops ptlbd_sv_obd_ops = {
- .o_owner = THIS_MODULE,
- .o_setup = ptlbd_sv_setup,
- .o_cleanup = ptlbd_sv_cleanup,
- .o_connect = class_connect,
- .o_disconnect = class_disconnect,
-};
-
-static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
-static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
-LPROCFS_INIT_VARS(ptlbd_sv, lprocfs_module_vars, lprocfs_obd_vars)
-
-int ptlbd_sv_init(void)
-{
- struct lprocfs_static_vars lvars;
-
- lprocfs_init_vars(ptlbd_sv,&lvars);
- return class_register_type(&ptlbd_sv_obd_ops, lvars.module_vars,
- OBD_PTLBD_SV_DEVICENAME);
-}
-
-void ptlbd_sv_exit(void)
-{
- class_unregister_type(OBD_PTLBD_SV_DEVICENAME);
-}
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-.deps
-TAGS
-.*.cmd
-autoMakefile.in
-autoMakefile
-*.ko
-*.mod.c
-.*.flags
-.tmp_versions
+++ /dev/null
-MODULES := smfs
-smfs-objs := super.o options.o inode.o cache.o dir.o sysctl.o file.o
-smfs-objs += symlink.o sm_fs.o kml.o reint.o journal.o journal_ext3.o
-smfs-objs += smfs_llog.o
-
-@INCLUDE_RULES@
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-if MODULES
-if SMFS
-modulefs_DATA = smfs$(KMODEXT)
-endif
-endif
-
-MOSTLYCLEANFILES = *.o *.ko *.mod.c
-DIST_SOURCES = $(smfs-objs:%.o=%.c) kml_idl.h smfs_internal.h smfs_support.h
+++ /dev/null
-/*
- * snapfs/cache.c
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/lustre_idl.h>
-#include <portals/list.h>
-
-#include "smfs_internal.h"
-struct sm_ops smfs_operations;
-
-extern struct inode_operations smfs_file_iops;
-extern struct file_operations smfs_file_fops;
-extern struct inode_operations smfs_sym_iops;
-extern struct file_operations smfs_sym_fops;
-extern struct super_operations smfs_super_ops;
-extern struct journal_operations smfs_journal_ops;
-
-
-inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sb_ops;
-}
-
-inline struct inode_operations *cache_diops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_dir_iops;
-}
-
-inline struct inode_operations *cache_fiops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_file_iops;
-}
-
-inline struct inode_operations *cache_siops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sym_iops;
-}
-
-inline struct file_operations *cache_dfops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_dir_fops;
-}
-
-inline struct file_operations *cache_ffops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_file_fops;
-}
-
-inline struct file_operations *cache_sfops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sym_fops;
-}
-
-inline struct dentry_operations *cache_dops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_dentry_ops;
-}
-
-inline struct journal_operations *journal_ops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_journal_ops;
-}
-
-void init_smfs_cache()
-{
- memset(&smfs_operations, 0, sizeof(struct sm_ops));
-}
-void cleanup_smfs_cache()
-{
- return;
-}
-
-static void setup_iops(struct inode *cache_inode,
- struct inode_operations *iops,
- struct inode_operations *cache_iops)
-{
-
- if (cache_inode->i_op && cache_iops && iops) {
- if (cache_inode->i_op->create)
- iops->create = cache_iops->create;
- if (cache_inode->i_op->create_it)
- iops->create_it = cache_iops->create_it;
- if (cache_inode->i_op->lookup)
- iops->lookup = cache_iops->lookup;
- if (cache_inode->i_op->lookup_raw)
- iops->lookup_raw = cache_iops->lookup_raw;
- if (cache_inode->i_op->lookup_it)
- iops->lookup_it = cache_iops->lookup_it;
- if (cache_inode->i_op->link)
- iops->link = cache_iops->link;
- if (cache_inode->i_op->link_raw)
- iops->link_raw = cache_iops->link_raw;
- if (cache_inode->i_op->unlink)
- iops->unlink = cache_iops->unlink;
- if (cache_inode->i_op->unlink_raw)
- iops->unlink_raw = cache_iops->unlink_raw;
- if (cache_inode->i_op->symlink)
- iops->symlink = cache_iops->symlink;
- if (cache_inode->i_op->symlink_raw)
- iops->symlink_raw = cache_iops->symlink_raw;
- if (cache_inode->i_op->mkdir)
- iops->mkdir = cache_iops->mkdir;
- if (cache_inode->i_op->mkdir_raw)
- iops->mkdir_raw = cache_iops->mkdir_raw;
- if (cache_inode->i_op->rmdir)
- iops->rmdir = cache_iops->rmdir;
- if (cache_inode->i_op->rmdir_raw)
- iops->rmdir_raw = cache_iops->rmdir_raw;
- if (cache_inode->i_op->mknod)
- iops->mknod = cache_iops->mknod;
- if (cache_inode->i_op->mknod_raw)
- iops->mknod_raw = cache_iops->mknod_raw;
- if (cache_inode->i_op->rename)
- iops->rename = cache_iops->rename;
- if (cache_inode->i_op->rename_raw)
- iops->rename_raw = cache_iops->rename_raw;
- if (cache_inode->i_op->readlink)
- iops->readlink = cache_iops->readlink;
- if (cache_inode->i_op->follow_link)
- iops->follow_link = cache_iops->follow_link;
- if (cache_inode->i_op->truncate)
- iops->truncate = cache_iops->truncate;
- if (cache_inode->i_op->permission)
- iops->permission = cache_iops->permission;
- if (cache_inode->i_op->revalidate)
- iops->revalidate = cache_iops->revalidate;
- if (cache_inode->i_op->revalidate_it)
- iops->revalidate_it = cache_iops->revalidate_it;
- if (cache_inode->i_op->setattr)
- iops->setattr = cache_iops->setattr;
- if (cache_inode->i_op->setattr_raw)
- iops->setattr_raw = cache_iops->setattr_raw;
- if (cache_inode->i_op->getattr)
- iops->getattr = cache_iops->getattr;
- if (cache_inode->i_op->setxattr)
- iops->setxattr = cache_iops->setxattr;
- if (cache_inode->i_op->getxattr)
- iops->getxattr = cache_iops->getxattr;
- if (cache_inode->i_op->listxattr)
- iops->listxattr = cache_iops->listxattr;
- if (cache_inode->i_op->removexattr)
- iops->removexattr = cache_iops->removexattr;
- }
-}
-static void setup_fops(struct inode *cache_inode,
- struct file_operations *fops,
- struct file_operations *cache_fops)
-{
- if (cache_inode->i_fop && cache_fops && fops) {
- if (cache_inode->i_fop->llseek)
- fops->llseek = cache_fops->llseek;
- if (cache_inode->i_fop->read)
- fops->read = cache_fops->read;
- if (cache_inode->i_fop->write)
- fops->write = cache_fops->write;
- if (cache_inode->i_fop->readdir)
- fops->readdir = cache_fops->readdir;
- if (cache_inode->i_fop->poll)
- fops->poll = cache_fops->poll;
- if (cache_inode->i_fop->ioctl)
- fops->ioctl = cache_fops->ioctl;
- if (cache_inode->i_fop->mmap)
- fops->mmap = cache_fops->mmap;
- if (cache_inode->i_fop->open)
- fops->open = cache_fops->open;
- if (cache_inode->i_fop->flush)
- fops->flush = cache_fops->flush;
- if (cache_inode->i_fop->release)
- fops->release = cache_fops->release;
- if (cache_inode->i_fop->fsync)
- fops->fsync = cache_fops->fsync;
- if (cache_inode->i_fop->fasync)
- fops->fasync = cache_fops->fasync;
- if (cache_inode->i_fop->lock)
- fops->lock = cache_fops->lock;
- if (cache_inode->i_fop->readv)
- fops->readv = cache_fops->readv;
- if (cache_inode->i_fop->writev)
- fops->writev = cache_fops->writev;
- if (cache_inode->i_fop->sendpage)
- fops->sendpage = cache_fops->sendpage;
- if (cache_inode->i_fop->get_unmapped_area)
- fops->get_unmapped_area = cache_fops->get_unmapped_area;
- }
-}
-static void setup_sm_file_ops(struct inode *cache_inode,
- struct inode *inode,
- struct inode_operations *cache_iops,
- struct file_operations *cache_fops)
-{
- struct smfs_super_info *smb;
- struct inode_operations *iops;
- struct file_operations *fops;
-
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & FILE_OPS_CHECK)
- return;
- smb->ops_check |= FILE_OPS_CHECK;
-
- iops = cache_fiops(&smfs_operations);
- fops = cache_ffops(&smfs_operations);
-
- memset(iops , 0 , sizeof (struct inode_operations));
- memset(fops , 0 , sizeof (struct file_operations));
-
- setup_iops(cache_inode, iops, cache_iops);
- setup_fops(cache_inode, fops, cache_fops);
-
- return;
-}
-
-static void setup_sm_dir_ops(struct inode *cache_inode,
- struct inode *inode,
- struct inode_operations *cache_dir_iops,
- struct file_operations *cache_dir_fops)
-{
- struct smfs_super_info *smb;
- struct inode_operations *iops;
- struct file_operations *fops;
-
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & DIR_OPS_CHECK)
- return;
- smb->ops_check |= DIR_OPS_CHECK;
-
- iops = cache_diops(&smfs_operations);
- fops = cache_dfops(&smfs_operations);
-
- memset(iops, 0, sizeof (struct inode_operations));
- memset(fops, 0, sizeof (struct file_operations));
-
- setup_iops(cache_inode, iops, cache_dir_iops);
- setup_fops(cache_inode, fops, cache_dir_fops);
-
- return;
-}
-
-static void setup_sm_symlink_ops(struct inode *cache_inode,
- struct inode *inode,
- struct inode_operations *cache_sym_iops,
- struct file_operations *cache_sym_fops)
-{
- struct smfs_super_info *smb;
- struct inode_operations *iops;
- struct file_operations *fops;
-
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & SYMLINK_OPS_CHECK)
- return;
- smb->ops_check |= SYMLINK_OPS_CHECK;
-
- iops = cache_siops(&smfs_operations);
- fops = cache_sfops(&smfs_operations);
-
- memset(iops , 0 , sizeof (struct inode_operations));
- memset(fops , 0 , sizeof (struct file_operations));
-
- setup_iops(cache_inode, iops, cache_sym_iops);
- setup_fops(cache_inode, fops, cache_sym_fops);
-
- return;
-}
-
-static void setup_sm_sb_ops(struct super_block *cache_sb,
- struct super_block *sb,
- struct super_operations *smfs_sops)
-{
- struct smfs_super_info *smb;
- struct super_operations *sops;
-
- ENTRY;
-
- smb = S2SMI(sb);
-
- if (smb->ops_check & SB_OPS_CHECK)
- return;
- smb->ops_check |= SB_OPS_CHECK;
- sops = cache_sops(&smfs_operations);
- memset(sops, 0, sizeof (struct super_operations));
-
- if (cache_sb->s_op) {
- if (cache_sb->s_op->read_inode)
- sops->read_inode = smfs_sops->read_inode;
- if (cache_sb->s_op->read_inode2)
- sops->read_inode2 = smfs_sops->read_inode2;
- if (cache_sb->s_op->dirty_inode)
- sops->dirty_inode = smfs_sops->dirty_inode;
- if (cache_sb->s_op->write_inode)
- sops->write_inode = smfs_sops->write_inode;
- if (cache_sb->s_op->put_inode)
- sops->put_inode = smfs_sops->put_inode;
- if (cache_sb->s_op->delete_inode)
- sops->delete_inode = smfs_sops->delete_inode;
- if (cache_sb->s_op->put_super)
- sops->put_super = smfs_sops->put_super;
- if (cache_sb->s_op->write_super)
- sops->write_super = smfs_sops->write_super;
- if (cache_sb->s_op->write_super_lockfs)
- sops->write_super_lockfs = smfs_sops->write_super_lockfs;
- if (cache_sb->s_op->unlockfs)
- sops->unlockfs = smfs_sops->unlockfs;
- if (cache_sb->s_op->statfs)
- sops->statfs = smfs_sops->statfs;
- if (cache_sb->s_op->remount_fs)
- sops->remount_fs = smfs_sops->remount_fs;
- if (cache_sb->s_op->umount_begin)
- sops->umount_begin = smfs_sops->umount_begin;
- if (cache_sb->s_op->fh_to_dentry)
- sops->fh_to_dentry = smfs_sops->fh_to_dentry;
- if (cache_sb->s_op->dentry_to_fh)
- sops->dentry_to_fh = smfs_sops->dentry_to_fh;
- if (cache_sb->s_op->show_options)
- sops->show_options = smfs_sops->show_options;
- /*FIXME we need this method to clear the cache inode */
- sops->clear_inode = smfs_sops->clear_inode;
- }
-
- return;
-}
-void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode)
-{
- /* XXX now set the correct snap_{file,dir,sym}_iops */
- if (S_ISDIR(inode->i_mode)) {
- setup_sm_dir_ops(cache_inode, inode,
- &smfs_dir_iops,
- &smfs_dir_fops);
- inode->i_op = cache_diops(&smfs_operations);
- inode->i_fop = cache_dfops(&smfs_operations);
- } else if (S_ISREG(inode->i_mode)) {
- setup_sm_file_ops(cache_inode, inode,
- &smfs_file_iops,
- &smfs_file_fops);
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- inode->i_fop = cache_ffops(&smfs_operations);
- inode->i_op = cache_fiops(&smfs_operations);
-
- } else if (S_ISLNK(inode->i_mode)) {
- setup_sm_symlink_ops(cache_inode, inode,
- &smfs_sym_iops,
- &smfs_sym_fops);
- inode->i_op = cache_siops(&smfs_operations);
- inode->i_fop = cache_sfops(&smfs_operations);
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- }
-}
-void sm_set_sb_ops (struct super_block *cache_sb,
- struct super_block *sb)
-{
- struct smfs_super_info *smb;
-
- smb = S2SMI(sb);
-
- setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops);
-
- sb->s_op = cache_sops(&smfs_operations);
- return;
-}
-
-void setup_sm_journal_ops(char *cache_type)
-{
- struct journal_operations *jops;
-
- jops = journal_ops(&smfs_operations);
-
- if (strlen(cache_type) == strlen("ext3") &&
- memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
-#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
- memcpy(jops, &smfs_ext3_journal_ops,
- sizeof(struct journal_operations));
-#else
- memset(jops, 0, sizeof(journal_operations));
-#endif
- CDEBUG(D_SUPER, "ops at %p\n", jops);
- }
-}
-
+++ /dev/null
-/*
- * dir.c
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/lustre_idl.h>
-#include <linux/smp_lock.h>
-
-#include "smfs_internal.h"
-#include "kml_idl.h"
-
-#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
-
-void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
-{
- atomic_set(&dentry->d_count, 1);
- dentry->d_vfs_flags = 0;
- dentry->d_flags = 0;
- dentry->d_inode = inode;
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
- INIT_LIST_HEAD(&dentry->d_alias);
-}
-
-void d_unalloc(struct dentry *dentry)
-{
-
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
- dput(dentry); /* this will free the dentry memory */
-}
-
-static int smfs_create(struct inode *dir,
- struct dentry *dentry,
- int mode)
-{
- struct inode *cache_dir;
- struct inode *cache_inode = NULL, *inode;
- struct dentry parent;
- struct dentry *cache_dentry = NULL;
- int rc;
-
- ENTRY;
-
- cache_dir = I2CI(dir);
- if (!cache_dir)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- if (!cache_dentry) {
- RETURN(-ENOMEM);
- }
-
- if (cache_dir && cache_dir->i_op->create)
- rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode);
-
- if (rc)
- GOTO(exit, rc);
-
- cache_inode = igrab(cache_dentry->d_inode);
-
- inode = iget(dir->i_sb, cache_inode->i_ino);
-
- if (!inode)
- GOTO(exit, rc = -ENOMEM);
-
- d_instantiate(dentry, inode);
-
- sm_set_inode_ops(cache_inode, inode);
-exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-
-static struct dentry *smfs_lookup(struct inode *dir,
- struct dentry *dentry)
-{
- struct inode *cache_dir;
- struct inode *cache_inode = NULL, *inode;
- struct dentry parent;
- struct dentry *cache_dentry = NULL;
- struct dentry *rc = NULL;
-
- ENTRY;
-
- cache_dir = I2CI(dir);
- if (!cache_dir)
- RETURN(ERR_PTR(-ENOENT));
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- if(cache_dir && cache_dir->i_op->lookup)
- rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
-
- if (rc || !cache_dentry->d_inode ||
- is_bad_inode(cache_dentry->d_inode) ||
- IS_ERR(cache_dentry->d_inode)) {
- GOTO(exit, rc);
- }
-
- cache_inode = igrab(cache_dentry->d_inode);
-
- inode = iget(dir->i_sb, cache_inode->i_ino);
-
- d_add(dentry, inode);
-exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-
-static int smfs_lookup_raw(struct inode *dir, const char *name,
- int len, ino_t *data)
-{
- struct inode *cache_dir;
- int rc = 0;
-
- cache_dir = I2CI(dir);
-
- if (!cache_dir)
- RETURN(-ENOENT);
-
- if (cache_dir->i_op->lookup_raw)
- rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);
-
- RETURN(rc);
-}
-
-static int smfs_link(struct dentry * old_dentry,
- struct inode * dir, struct dentry *dentry)
-{
- struct inode *cache_old_inode = NULL;
- struct inode *cache_dir = I2CI(dir);
- struct inode *inode = NULL;
- struct dentry *cache_dentry;
- struct dentry *cache_old_dentry;
- struct dentry parent;
- struct dentry parent_old;
- int rc = 0;
-
- inode = old_dentry->d_inode;
-
- cache_old_inode = I2CI(inode);
-
- if (!cache_old_inode || !cache_dir)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- prepare_parent_dentry(&parent_old, cache_dir);
- cache_old_dentry = d_alloc(&parent_old, &dentry->d_name);
- d_add(cache_old_dentry, cache_old_inode);
- pre_smfs_inode(inode, cache_old_dentry->d_inode);
-
- if (cache_dir->i_op->link)
- rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry);
-
- if (rc)
- GOTO(exit, rc);
-
- atomic_inc(&inode->i_count);
- post_smfs_inode(inode, cache_old_dentry->d_inode);
- d_instantiate(dentry, inode);
-
-exit:
- if (cache_dentry->d_inode)
- igrab(cache_dentry->d_inode);
- if (cache_old_dentry->d_inode)
- igrab(cache_old_dentry->d_inode);
-
- d_unalloc(cache_dentry);
- d_unalloc(cache_old_dentry);
-
- RETURN(rc);
-}
-
-static int smfs_unlink(struct inode * dir,
- struct dentry *dentry)
-{
- struct inode *cache_dir = I2CI(dir);
- struct inode *cache_inode = I2CI(dentry->d_inode);
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
-
- if (!cache_dir || !cache_inode)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
- d_add(cache_dentry, cache_inode);
-
- if (cache_dir->i_op->unlink)
- rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
-
-
- post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
- post_smfs_inode(dir, cache_dir);
-
- igrab(cache_dentry->d_inode);
-
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-
-static int smfs_symlink (struct inode * dir,
- struct dentry *dentry,
- const char * symname)
-{
- struct inode *cache_dir = I2CI(dir);
- struct inode *cache_inode = NULL;
- struct inode *inode = NULL;
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
-
- if (!cache_dir)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- if (cache_dir->i_op->symlink)
- rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
-
- cache_inode = igrab(cache_dentry->d_inode);
-
- inode = iget(dir->i_sb, cache_inode->i_ino);
-
- if (inode)
- d_instantiate(dentry, inode);
- else
- rc = -ENOENT;
-
- d_unalloc(cache_dentry);
-
- RETURN(rc);
-}
-
-static int smfs_mkdir(struct inode * dir,
- struct dentry * dentry,
- int mode)
-{
- struct inode *cache_dir = I2CI(dir);
- struct inode *cache_inode = NULL;
- struct inode *inode = NULL;
- struct dentry *cache_dentry;
- struct dentry parent;
- void *handle;
- int rc = 0;
-
- if (!cache_dir)
- RETURN(-ENOENT);
-
- handle = smfs_trans_start(cache_dir, KML_OPCODE_MKDIR);
- if (IS_ERR(handle) ) {
- CERROR("smfs_do_mkdir: no space for transaction\n");
- RETURN(-ENOSPC);
- }
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- pre_smfs_inode(dir, cache_dir);
- lock_kernel();
- if (cache_dir->i_op->mkdir)
- rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
-
- cache_inode = igrab(cache_dentry->d_inode);
-
- inode = iget(dir->i_sb, cache_inode->i_ino);
-
- if (!inode)
- GOTO(exit, rc = -ENOENT);
-
- d_instantiate(dentry, inode);
- /*Do KML post hook*/
- if (smfs_do_kml(dir)) {
- rc = post_kml_mkdir(dir, dentry);
- GOTO(exit, rc);
- }
- post_smfs_inode(dir, cache_dir);
-exit:
- unlock_kernel();
- smfs_trans_commit(handle);
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-
-static int smfs_rmdir(struct inode * dir,
- struct dentry *dentry)
-{
- struct inode *cache_dir = I2CI(dir);
- struct inode *cache_inode = I2CI(dentry->d_inode);
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
-
- if (!cache_dir)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
- d_add(cache_dentry, cache_inode);
- igrab(cache_inode);
-
- pre_smfs_inode(dir, cache_dir);
- pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
-
-
- if (cache_dir->i_op->rmdir)
- rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
-
- post_smfs_inode(dir, cache_dir);
- post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-
-static int smfs_mknod(struct inode * dir, struct dentry *dentry,
- int mode, int rdev)
-{
- struct inode *cache_dir = I2CI(dir);
- struct inode *inode = NULL;
- struct inode *cache_inode = NULL;
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
-
- if (!cache_dir)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent, cache_dir);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- pre_smfs_inode(dir, cache_dir);
- pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
-
- if (cache_dir->i_op->mknod)
- rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
-
- if (cache_dentry->d_inode)
- cache_inode = igrab(cache_dentry->d_inode);
- if (rc)
- GOTO(exit, rc);
-
- inode = iget(dir->i_sb, cache_inode->i_ino);
- d_instantiate(dentry, inode);
- post_smfs_inode(dir, cache_dir);
- post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
-exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
-static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
- struct inode * new_dir,struct dentry *new_dentry)
-{
- struct inode *cache_old_dir = I2CI(old_dir);
- struct inode *cache_new_dir = I2CI(new_dir);
- struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
- struct dentry *cache_old_dentry;
- struct dentry *cache_new_dentry;
- struct dentry parent_new;
- struct dentry parent_old;
- int rc = 0;
-
- if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
- RETURN(-ENOENT);
-
- prepare_parent_dentry(&parent_old, cache_old_dir);
- cache_old_dentry = d_alloc(&parent_old, &old_dentry->d_name);
- d_add(cache_old_dentry, cache_old_inode);
- igrab(cache_old_inode);
-
- prepare_parent_dentry(&parent_new, cache_new_dir);
- cache_new_dentry = d_alloc(&parent_new, &new_dentry->d_name);
-
- pre_smfs_inode(old_dir, cache_old_dir) ;
- pre_smfs_inode(new_dir, cache_new_dir);
-
- if (cache_old_dir->i_op->rename)
- rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
- cache_new_dir, cache_new_dentry);
-
- post_smfs_inode(old_dir, cache_old_dir) ;
- post_smfs_inode(new_dir, cache_new_dir);
- if (cache_new_dentry->d_inode) {
- igrab(cache_new_dentry->d_inode);
- }
- d_unalloc(cache_old_dentry);
- d_unalloc(cache_new_dentry);
- RETURN(rc);
-}
-
-struct inode_operations smfs_dir_iops = {
- create: smfs_create,
- lookup: smfs_lookup,
- lookup_raw: smfs_lookup_raw, /* BKL held */
- link: smfs_link, /* BKL held */
- unlink: smfs_unlink, /* BKL held */
- symlink: smfs_symlink, /* BKL held */
- mkdir: smfs_mkdir, /* BKL held */
- rmdir: smfs_rmdir, /* BKL held */
- mknod: smfs_mknod, /* BKL held */
- rename: smfs_rename, /* BKL held */
- setxattr: smfs_setxattr, /* BKL held */
- getxattr: smfs_getxattr, /* BKL held */
- listxattr: smfs_listxattr, /* BKL held */
- removexattr: smfs_removexattr, /* BKL held */
-};
-
-static ssize_t smfs_read_dir(struct file *filp, char *buf,
- size_t size, loff_t *ppos)
-{
- struct dentry *dentry = filp->f_dentry;
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-EINVAL);
-
- smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode,
- &open_file, &open_dentry);
-
- if (cache_inode->i_fop->read)
- rc = cache_inode->i_fop->read(&open_file, buf, size, ppos);
-
- smfs_update_file(filp, &open_file);
- RETURN(rc);
-}
-
-static int smfs_readdir(struct file * filp,
- void * dirent,
- filldir_t filldir)
-{
- struct dentry *dentry = filp->f_dentry;
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-EINVAL);
-
- smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode,
- &open_file, &open_dentry);
-
- if (cache_inode->i_fop->readdir)
- rc = cache_inode->i_fop->readdir(&open_file, dirent, filldir);
-
- smfs_update_file(filp, &open_file);
- RETURN(rc);
-}
-
-struct file_operations smfs_dir_fops = {
- read: smfs_read_dir,
- readdir: smfs_readdir, /* BKL held */
- ioctl: smfs_ioctl, /* BKL held */
- fsync: smfs_fsync, /* BKL held */
-};
+++ /dev/null
-/*
- * file.c
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/pagemap.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-/* instantiate a file handle to the cache file */
-void smfs_prepare_cachefile(struct inode *inode,
- struct file *file,
- struct inode *cache_inode,
- struct file *cache_file,
- struct dentry *cache_dentry)
-{
- ENTRY;
- cache_file->f_pos = file->f_pos;
- cache_file->f_mode = file->f_mode;
- cache_file->f_flags = file->f_flags;
- cache_file->f_count = file->f_count;
- cache_file->f_owner = file->f_owner;
- cache_file->f_error = file->f_error;
- cache_file->f_op = inode->i_fop;
- cache_file->f_dentry = cache_dentry;
- cache_file->f_dentry->d_inode = cache_inode;
- cache_file->f_vfsmnt = file->f_vfsmnt;
- cache_file->private_data = file->private_data;
- cache_file->f_it = file->f_it;
- cache_file->f_reada = file->f_reada;
- cache_file->f_ramax = file->f_ramax;
- cache_file->f_raend = file->f_raend;
- cache_file->f_ralen = file->f_ralen;
- cache_file->f_rawin = file->f_rawin;
- EXIT;
-}
-/* update file structs*/
-void smfs_update_file(struct file *file,
- struct file *cache_file)
-{
- ENTRY;
- file->f_pos = cache_file->f_pos;
- file->f_mode = cache_file->f_mode;
- file->f_flags = cache_file->f_flags;
- file->f_count = cache_file->f_count;
- file->f_owner = cache_file->f_owner;
- file->f_reada = cache_file->f_reada;
- file->f_ramax = cache_file->f_ramax;
- file->f_raend = cache_file->f_raend;
- file->f_ralen = cache_file->f_ralen;
- file->f_rawin = cache_file->f_rawin;
- EXIT;
-}
-
-static ssize_t smfs_write (struct file *filp, const char *buf,
- size_t count, loff_t *ppos)
-{
- struct inode *cache_inode;
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct file open_file;
- struct dentry open_dentry;
- loff_t tmp_ppos;
- loff_t *cache_ppos;
- int rc = 0;
-
- ENTRY;
-
- cache_inode = I2CI(inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
-
- if (ppos != &(filp->f_pos)) {
- cache_ppos = &tmp_ppos;
- } else {
- cache_ppos = &open_file.f_pos;
- }
- *cache_ppos = *ppos;
-
- smfs_prepare_cachefile(inode, filp, cache_inode,
- &open_file, &open_dentry);
- pre_smfs_inode(inode, cache_inode);
-
- if (cache_inode->i_fop->write)
- rc = cache_inode->i_fop->write(&open_file, buf, count, cache_ppos);
-
- *ppos = *cache_ppos;
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(filp, &open_file);
-
- RETURN(rc);
-}
-
-int smfs_ioctl(struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- struct inode *cache_inode;
- struct dentry *dentry = filp->f_dentry;
- struct file open_file;
- struct dentry open_dentry;
- ssize_t rc = 0;
-
- ENTRY;
-
- cache_inode = I2CI(dentry->d_inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(inode, filp, cache_inode,
- &open_file, &open_dentry);
-
- if (cache_inode->i_fop->ioctl)
- rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
-
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(filp, &open_file);
- RETURN(rc);
-}
-
-static ssize_t smfs_read (struct file *filp, char *buf,
- size_t count, loff_t *ppos)
-{
- struct inode *cache_inode;
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct file open_file;
- struct dentry open_dentry;
- loff_t tmp_ppos;
- loff_t *cache_ppos;
- ssize_t rc = 0;
-
- ENTRY;
-
- cache_inode = I2CI(dentry->d_inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- if (ppos != &(filp->f_pos)) {
- cache_ppos = &tmp_ppos;
- } else {
- cache_ppos = &open_file.f_pos;
- }
- *cache_ppos = *ppos;
-
-
- smfs_prepare_cachefile(inode, filp, cache_inode,
- &open_file, &open_dentry);
-
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_inode->i_fop->read)
- rc = cache_inode->i_fop->read(&open_file, buf, count, cache_ppos);
-
- *ppos = *cache_ppos;
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(filp, &open_file);
- RETURN(rc);
-}
-
-static loff_t smfs_llseek(struct file *file,
- loff_t offset,
- int origin)
-{
- struct inode *cache_inode;
- struct dentry *dentry = file->f_dentry;
- struct file open_file;
- struct dentry open_dentry;
- ssize_t rc = 0;
-
- ENTRY;
-
- cache_inode = I2CI(dentry->d_inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(dentry->d_inode, file, cache_inode,
- &open_file, &open_dentry);
-
- pre_smfs_inode(dentry->d_inode, cache_inode);
- if (cache_inode->i_fop->llseek)
- rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
- smfs_update_file(file, &open_file);
-
- RETURN(rc);
-}
-
-static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
-{
- struct inode *inode = file->f_dentry->d_inode;
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(inode, file, cache_inode,
- &open_file, &open_dentry);
-
- if (cache_inode->i_mapping == &cache_inode->i_data)
- inode->i_mapping = cache_inode->i_mapping;
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_inode->i_fop->mmap)
- rc = cache_inode->i_fop->mmap(&open_file, vma);
-
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(file, &open_file);
-
- RETURN(rc);
-}
-
-static int smfs_open(struct inode * inode, struct file * filp)
-{
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(inode, filp, cache_inode,
- &open_file, &open_dentry);
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_inode->i_fop->open)
- rc = cache_inode->i_fop->open(cache_inode, &open_file);
-
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(filp, &open_file);
-
- RETURN(rc);
-
-}
-static int smfs_release(struct inode * inode, struct file * filp)
-{
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(inode, filp, cache_inode,
- &open_file, &open_dentry);
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_inode->i_fop->release)
- rc = cache_inode->i_fop->release(cache_inode, &open_file);
-
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(filp, &open_file);
-
- RETURN(rc);
-}
-int smfs_fsync(struct file * file,
- struct dentry *dentry,
- int datasync)
-{
- struct inode *inode = dentry->d_inode;
- struct inode *cache_inode;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(inode);
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cachefile(inode, file, cache_inode,
- &open_file, &open_dentry);
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_inode->i_fop->fsync)
- rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
-
- post_smfs_inode(inode, cache_inode);
- smfs_update_file(file, &open_file);
-
- RETURN(rc);
-}
-
-struct file_operations smfs_file_fops = {
- llseek: smfs_llseek,
- read: smfs_read,
- write: smfs_write,
- ioctl: smfs_ioctl,
- mmap: smfs_mmap,
- open: smfs_open,
- release: smfs_release,
- fsync: smfs_fsync,
-};
-
-static void smfs_prepare_cache_dentry(struct dentry *dentry, struct inode *inode)
-{
- atomic_set(&dentry->d_count, 1);
- dentry->d_vfs_flags = 0;
- dentry->d_flags = 0;
- dentry->d_inode = inode;
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
- INIT_LIST_HEAD(&dentry->d_alias);
-}
-
-static void smfs_truncate(struct inode * inode)
-{
- struct inode *cache_inode;
-
- cache_inode = I2CI(inode);
-
- if (!cache_inode)
- return;
-
- if (cache_inode->i_op->truncate)
- cache_inode->i_op->truncate(cache_inode);
-
- post_smfs_inode(inode, cache_inode);
-
- return;
-}
-
-int smfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
- struct inode *cache_inode;
- struct dentry open_dentry;
-
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
- smfs_prepare_cache_dentry(&open_dentry, cache_inode);
-
- pre_smfs_inode(dentry->d_inode, cache_inode);
- if (cache_inode->i_op->setattr)
- rc = cache_inode->i_op->setattr(&open_dentry, attr);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
-
- RETURN(rc);
-}
-
-int smfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
- struct inode *cache_inode;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
-
- pre_smfs_inode(dentry->d_inode, cache_inode);
- smfs_prepare_cache_dentry(&open_dentry, cache_inode);
-
- if (cache_inode->i_op->setattr)
- rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
-}
-
-int smfs_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
-{
- struct inode *cache_inode;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cache_dentry(&open_dentry, cache_inode);
- pre_smfs_inode(dentry->d_inode, cache_inode);
-
- if (cache_inode->i_op->setattr)
- rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
-}
-
-ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
- struct inode *cache_inode;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cache_dentry(&open_dentry, cache_inode);
- pre_smfs_inode(dentry->d_inode, cache_inode);
-
- if (cache_inode->i_op->listxattr)
- rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
-}
-
-int smfs_removexattr(struct dentry *dentry, const char *name)
-{
- struct inode *cache_inode;
- struct dentry open_dentry;
- int rc = 0;
-
- cache_inode = I2CI(dentry->d_inode);
-
- if (!cache_inode)
- RETURN(-ENOENT);
-
- smfs_prepare_cache_dentry(&open_dentry, cache_inode);
- pre_smfs_inode(dentry->d_inode, cache_inode);
-
- if (cache_inode->i_op->removexattr)
- rc = cache_inode->i_op->removexattr(&open_dentry, name);
-
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
-}
-
-struct inode_operations smfs_file_iops = {
- truncate: smfs_truncate, /* BKL held */
- setattr: smfs_setattr, /* BKL held */
- setxattr: smfs_setxattr, /* BKL held */
- getxattr: smfs_getxattr, /* BKL held */
- listxattr: smfs_listxattr, /* BKL held */
- removexattr: smfs_removexattr, /* BKL held */
-};
-
+++ /dev/null
-/*
- * smfs/inode.c
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-static void duplicate_inode(struct inode *dst_inode,
- struct inode *src_inode)
-{
- dst_inode->i_mode = src_inode->i_mode;
- dst_inode->i_uid = src_inode->i_uid;
- dst_inode->i_gid = src_inode->i_gid;
- dst_inode->i_nlink = src_inode->i_nlink;
- dst_inode->i_size = src_inode->i_size;
- dst_inode->i_atime = src_inode->i_atime;
- dst_inode->i_ctime = src_inode->i_ctime;
- dst_inode->i_mtime = src_inode->i_mtime;
- dst_inode->i_blksize = src_inode->i_blksize;
- dst_inode->i_blocks = src_inode->i_blocks;
- dst_inode->i_version = src_inode->i_version;
- dst_inode->i_state = src_inode->i_state;
-}
-
-void post_smfs_inode(struct inode *inode,
- struct inode *cache_inode)
-{
- if (inode && cache_inode) {
- duplicate_inode(inode, cache_inode);
- /*Here we must release the cache_inode,
- *Otherwise we will have no chance to
- *do it
- */
- cache_inode->i_state &=~I_LOCK;
- }
-}
-void pre_smfs_inode(struct inode *inode,
- struct inode *cache_inode)
-{
- if (inode && cache_inode) {
- duplicate_inode(cache_inode, inode);
- }
-}
-
-static void smfs_read_inode(struct inode *inode)
-{
- struct super_block *cache_sb;
- struct inode *cache_inode;
- ENTRY;
-
- if (!inode)
- return;
-
- CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
- cache_sb = S2CSB(inode->i_sb);
-
- cache_inode = iget(cache_sb, inode->i_ino);
- I2CI(inode) = cache_inode;
-
- if(cache_sb && cache_sb->s_op->read_inode)
- cache_sb->s_op->read_inode(cache_inode);
-
- post_smfs_inode(inode, cache_inode);
- sm_set_inode_ops(cache_inode, inode);
-
- CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
- inode->i_ino, atomic_read(&inode->i_count));
-
- iput(cache_inode);
- return;
-}
-
-/* Although some filesystem(such as ext3) do not have
- * clear_inode method, but we need it to free the
- * cache inode
- */
-static void smfs_clear_inode(struct inode *inode)
-{
- struct super_block *cache_sb;
- struct inode *cache_inode;
-
- ENTRY;
-
- if (!inode) return;
-
- cache_sb = S2CSB(inode->i_sb);
- cache_inode = I2CI(inode);
-
- /*FIXME: because i_count of cache_inode may not
- * be 0 or 1 in before smfs_delete inode, So we
- * need to dec it to 1 before we call delete_inode
- * of the bellow cache filesystem Check again latter*/
-
- if (atomic_read(&cache_inode->i_count) < 1)
- BUG();
-
- while (atomic_read(&cache_inode->i_count) != 1) {
- atomic_dec(&cache_inode->i_count);
- }
- iput(cache_inode);
-
- I2CI(inode) = NULL;
- return;
-}
-static void smfs_delete_inode(struct inode *inode)
-{
- struct inode *cache_inode;
- struct super_block *cache_sb;
-
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
-
- if (!cache_inode || !cache_sb)
- return;
-
- /*FIXME: because i_count of cache_inode may not
- * be 0 or 1 in before smfs_delete inode, So we
- * need to dec it to 1 before we call delete_inode
- * of the bellow cache filesystem Check again latter*/
-
- if (atomic_read(&cache_inode->i_count) < 1)
- BUG();
-
- while (atomic_read(&cache_inode->i_count) != 1) {
- atomic_dec(&cache_inode->i_count);
- }
-
- pre_smfs_inode(inode, cache_inode);
-
- list_del(&cache_inode->i_hash);
- INIT_LIST_HEAD(&cache_inode->i_hash);
- list_del(&cache_inode->i_list);
- INIT_LIST_HEAD(&cache_inode->i_list);
-
- if (cache_inode->i_data.nrpages)
- truncate_inode_pages(&cache_inode->i_data, 0);
-
- if (cache_sb->s_op->delete_inode)
- cache_sb->s_op->delete_inode(cache_inode);
-
- post_smfs_inode(inode, cache_inode);
-
- I2CI(inode) = NULL;
- return;
-}
-static void smfs_write_inode(struct inode *inode, int wait)
-{
- struct inode *cache_inode;
- struct super_block *cache_sb;
-
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
-
- if (!cache_inode || !cache_sb)
- return;
-
- pre_smfs_inode(inode, cache_inode);
-
- if (cache_sb->s_op->write_inode)
- cache_sb->s_op->write_inode(cache_inode, wait);
-
- post_smfs_inode(inode, cache_inode);
-
- return;
-}
-static void smfs_dirty_inode(struct inode *inode)
-{
- struct inode *cache_inode;
- struct super_block *cache_sb;
-
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
-
- if (!cache_inode || !cache_sb)
- return;
-
- pre_smfs_inode(inode, cache_inode);
- if (cache_sb->s_op->dirty_inode)
- cache_sb->s_op->dirty_inode(cache_inode);
-
- post_smfs_inode(inode, cache_inode);
- return;
-}
-
-static void smfs_put_inode(struct inode *inode)
-{
- struct inode *cache_inode;
- struct super_block *cache_sb;
-
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
-
- if (!cache_inode || !cache_sb)
- return;
- if (cache_sb->s_op->put_inode)
- cache_sb->s_op->put_inode(cache_inode);
-
- return;
-}
-
-static void smfs_write_super(struct super_block *sb)
-{
- struct super_block *cache_sb;
-
- ENTRY;
- cache_sb = S2CSB(sb);
-
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->write_super)
- cache_sb->s_op->write_super(cache_sb);
-
- duplicate_sb(cache_sb, sb);
- return;
-}
-
-static void smfs_write_super_lockfs(struct super_block *sb)
-{
- struct super_block *cache_sb;
-
- ENTRY;
- cache_sb = S2CSB(sb);
-
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->write_super_lockfs)
- cache_sb->s_op->write_super_lockfs(cache_sb);
-
- duplicate_sb(cache_sb, sb);
- return;
-}
-
-static void smfs_unlockfs(struct super_block *sb)
-{
- struct super_block *cache_sb;
-
- ENTRY;
- cache_sb = S2CSB(sb);
-
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->unlockfs)
- cache_sb->s_op->unlockfs(cache_sb);
-
- duplicate_sb(cache_sb, sb);
- return;
-}
-static int smfs_statfs(struct super_block * sb, struct statfs * buf)
-{
- struct super_block *cache_sb;
- int rc = 0;
-
- ENTRY;
- cache_sb = S2CSB(sb);
-
- if (!cache_sb)
- RETURN(-EINVAL);
-
- if (cache_sb->s_op->statfs)
- rc = cache_sb->s_op->statfs(cache_sb, buf);
-
- duplicate_sb(cache_sb, sb);
-
- return rc;
-}
-static int smfs_remount(struct super_block * sb, int * flags, char * data)
-{
- struct super_block *cache_sb;
- int rc = 0;
-
- ENTRY;
- cache_sb = S2CSB(sb);
-
- if (!cache_sb)
- RETURN(-EINVAL);
-
- if (cache_sb->s_op->remount_fs)
- rc = cache_sb->s_op->remount_fs(cache_sb, flags, data);
-
- duplicate_sb(cache_sb, sb);
- RETURN(rc);
-}
-struct super_operations smfs_super_ops = {
- read_inode: smfs_read_inode,
- clear_inode: smfs_clear_inode,
- put_super: smfs_put_super,
- delete_inode: smfs_delete_inode,
- write_inode: smfs_write_inode,
- dirty_inode: smfs_dirty_inode, /* BKL not held. We take it */
- put_inode: smfs_put_inode, /* BKL not held. Don't need */
-
- write_super: smfs_write_super, /* BKL held */
- write_super_lockfs: smfs_write_super_lockfs, /* BKL not held. Take it */
- unlockfs: smfs_unlockfs, /* BKL not held. We take it */
- statfs: smfs_statfs, /* BKL held */
- remount_fs: smfs_remount, /* BKL held */
-
-};
-
-
-
-
-
+++ /dev/null
-/*
- * smfs/inode.c
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/lustre_idl.h>
-#include "kml_idl.h"
-#include "smfs_internal.h"
-extern struct sm_ops smfs_operations;
-
-#define size_round(x) (((x)+3) & ~0x3)
-
-void *smfs_trans_start(struct inode *inode, int op)
-{
-
- CDEBUG(D_INODE, "trans start %p\n",
- smfs_operations.sm_journal_ops.tr_start);
- if (smfs_operations.sm_journal_ops.tr_start) {
- return smfs_operations.sm_journal_ops.tr_start(inode, op);
- }
- return NULL;
-}
-
-void smfs_trans_commit(void *handle)
-{
- if (smfs_operations.sm_journal_ops.tr_commit) {
- smfs_operations.sm_journal_ops.tr_commit(handle);
- }
- CDEBUG(D_SM, "trans commit %p\n",
- smfs_operations.sm_journal_ops.tr_commit);
-}
-/*The following function are gotten from intermezzo
- * smfs_path
- * logit
- * journal_log_prefix_with_groups_and_ids
- * journal_log_prefix
-*/
-static char* smfs_path(struct dentry *dentry, struct dentry *root,
- char *buffer, int buflen)
-{
- char * end = buffer+buflen;
- char * retval;
-
- *--end = '\0';
- buflen--;
- if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
- buflen -= 10;
- end -= 10;
- memcpy(end, " (deleted)", 10);
- }
-
- /* Get '/' right */
- retval = end-1;
- *retval = '/';
-
- for (;;) {
- struct dentry * parent;
- int namelen;
-
- if (dentry == root)
- break;
- parent = dentry->d_parent;
- if (dentry == parent)
- break;
- namelen = dentry->d_name.len;
- buflen -= namelen + 1;
- if (buflen < 0)
- break;
- end -= namelen;
- memcpy(end, dentry->d_name.name, namelen);
- *--end = '/';
- retval = end;
- dentry = parent;
- }
- return retval;
-}
-
-static inline char *logit(char *buf, const void *value, int size)
-{
- char *ptr = (char *)value;
-
- memcpy(buf, ptr, size);
- buf += size;
- return buf;
-}
-static inline char *
-journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
- __u32 ngroups, gid_t *groups,
- __u32 fsuid, __u32 fsgid)
-{
- struct kml_prefix_hdr p;
- u32 loggroups[NGROUPS_MAX];
-
- int i;
-
- p.version = KML_MAJOR_VERSION | KML_MINOR_VERSION;
- p.pid = cpu_to_le32(current->pid);
- p.auid = cpu_to_le32(current->uid);
- p.fsuid = cpu_to_le32(fsuid);
- p.fsgid = cpu_to_le32(fsgid);
- p.ngroups = cpu_to_le32(ngroups);
- p.opcode = cpu_to_le32(opcode);
- for (i=0 ; i < ngroups ; i++)
- loggroups[i] = cpu_to_le32((__u32) groups[i]);
-
- buf = logit(buf, &p, sizeof(struct kml_prefix_hdr));
- buf = logit(buf, &loggroups, sizeof(__u32) * ngroups);
- return buf;
-}
-
-static inline char *
-journal_log_prefix(char *buf, int opcode)
-{
- __u32 groups[NGROUPS_MAX];
- int i;
-
- /* convert 16 bit gid's to 32 bit gid's */
- for (i=0; i<current->ngroups; i++)
- groups[i] = (__u32) current->groups[i];
-
- return journal_log_prefix_with_groups_and_ids(buf, opcode,
- (__u32)current->ngroups,
- groups,
- (__u32)current->fsuid,
- (__u32)current->fsgid);
-}
-
-static inline char *
-journal_log_prefix_with_groups(char *buf, int opcode,
- __u32 ngroups, gid_t *groups)
-{
- return journal_log_prefix_with_groups_and_ids(buf, opcode,
- ngroups, groups,
- (__u32)current->fsuid,
- (__u32)current->fsgid);
-}
-
-static inline char *log_dentry_version(char *buf, struct dentry *dentry)
-{
- struct smfs_version version;
-
- smfs_getversion(&version, dentry->d_inode);
-
- version.sm_mtime = HTON__u64(version.sm_mtime);
- version.sm_ctime = HTON__u64(version.sm_ctime);
- version.sm_size = HTON__u64(version.sm_size);
-
- return logit(buf, &version, sizeof(version));
-}
-
-static inline char *log_version(char *buf, struct smfs_version *pv)
-{
- struct smfs_version version;
-
- memcpy(&version, pv, sizeof(version));
-
- version.sm_mtime = HTON__u64(version.sm_mtime);
- version.sm_ctime = HTON__u64(version.sm_ctime);
- version.sm_size = HTON__u64(version.sm_size);
-
- return logit(buf, &version, sizeof(version));
-}
-static inline char *journal_log_suffix(char *buf, char *log,
- struct dentry *dentry)
-{
- struct kml_suffix s;
- struct kml_prefix_hdr *p = (struct kml_prefix_hdr *)log;
-
- s.prevrec = 0;
-
- /* record number needs to be filled in after reservation
- s.recno = cpu_to_le32(rec->recno); */
- s.time = cpu_to_le32(CURRENT_TIME);
- s.len = p->len;
- return logit(buf, &s, sizeof(s));
-}
-
-int smfs_kml_log(struct smfs_super_info *smfs_info,
- const char *buf, size_t size,
- const char *string1, int len1,
- const char *string2, int len2,
- const char *string3, int len3)
-{
- int rc = 0;
- /*should pack the record and dispatch it
- *create llog handle write to the log*/
- return rc;
-}
-
-int smfs_journal_mkdir(struct dentry *dentry,
- struct smfs_version *tgt_dir_ver,
- struct smfs_version *new_dir_ver,
- int mode)
-{
- int opcode = KML_OPCODE_MKDIR;
- char *buffer, *path, *logrecord, record[292];
- struct dentry *root;
- __u32 uid, gid, lmode, pathlen;
- struct smfs_super_info *smfs_info;
- struct super_block* sb;
- int error, size;
-
- ENTRY;
-
- sb = dentry->d_inode->i_sb;
- root = sb->s_root;
- smfs_info = S2SMI(sb);
-
- uid = cpu_to_le32(dentry->d_inode->i_uid);
- gid = cpu_to_le32(dentry->d_inode->i_gid);
- lmode = cpu_to_le32(mode);
-
- SM_ALLOC(buffer, PAGE_SIZE);
- path = smfs_path(dentry, root, buffer, PAGE_SIZE);
- pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
- size = sizeof(__u32) * current->ngroups +
- sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
- sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
- sizeof(struct kml_suffix);
-
- if ( size > sizeof(record) )
- CERROR("InterMezzo: BUFFER OVERFLOW in %s!\n", __FUNCTION__);
-
- logrecord = journal_log_prefix(record, opcode);
-
- logrecord = log_version(logrecord, tgt_dir_ver);
- logrecord = log_dentry_version(logrecord, dentry->d_parent);
- logrecord = log_version(logrecord, new_dir_ver);
- logrecord = logit(logrecord, &lmode, sizeof(lmode));
- logrecord = logit(logrecord, &uid, sizeof(uid));
- logrecord = logit(logrecord, &gid, sizeof(gid));
- logrecord = logit(logrecord, &pathlen, sizeof(pathlen));
- logrecord = journal_log_suffix(logrecord, record, dentry);
-
- error = smfs_kml_log(smfs_info, record, size,
- path, size_round(le32_to_cpu(pathlen)),
- NULL, 0, NULL, 0);
- SM_FREE(buffer, PAGE_SIZE);
- RETURN(error);
-}
+++ /dev/null
-/*
- * smfs/journal_ext3.c
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/smp_lock.h>
-#include <linux/lustre_idl.h>
-#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/ext3_jbd.h>
-#endif
-
-#include "smfs_internal.h"
-#include "kml_idl.h"
-
-#if defined(CONFIG_EXT3_FS) || defined (CONFIG_EXT3_FS_MODULE)
-
-#define MAX_PATH_BLOCKS(inode) (PATH_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
-#define MAX_NAME_BLOCKS(inode) (NAME_MAX >> EXT3_BLOCK_SIZE_BITS((inode)->i_sb))
-
-static void *smfs_e3_trans_start(struct inode *inode,
- int op)
-{
-
- int trunc_blks, one_path_blks, extra_path_blks;
- int extra_name_blks, lml_blks, jblocks;
- __u32 avail_kmlblocks;
- handle_t *handle;
-
- avail_kmlblocks = inode->i_sb->u.ext3_sb.s_es->s_free_blocks_count;
-
- if ( avail_kmlblocks < 3 ) {
- return ERR_PTR(-ENOSPC);
- }
-
- if ((op != KML_OPCODE_UNLINK && op != KML_OPCODE_RMDIR)
- && avail_kmlblocks < 6 ) {
- return ERR_PTR(-ENOSPC);
- }
- /* Need journal space for:
- at least three writes to KML (two one block writes, one a path)
- possibly a second name (unlink, rmdir)
- possibly a second path (symlink, rename)
- a one block write to the last rcvd file
- */
-
- trunc_blks = EXT3_DATA_TRANS_BLOCKS + 1;
- one_path_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 3;
- lml_blks = 4*EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode) + 2;
- extra_path_blks = EXT3_DATA_TRANS_BLOCKS + MAX_PATH_BLOCKS(inode);
- extra_name_blks = EXT3_DATA_TRANS_BLOCKS + MAX_NAME_BLOCKS(inode);
-
- /* additional blocks appear for "two pathname" operations
- and operations involving the LML records
- */
-
- switch (op) {
- case KML_OPCODE_MKDIR:
- jblocks = one_path_blks + trunc_blks
- + EXT3_DATA_TRANS_BLOCKS + 4 + 2;
- break;
- default:
- CDEBUG(D_INODE, "invalid operation %d for journal\n", op);
- return NULL;
- }
-
- CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks);
-
- lock_kernel();
- handle = journal_start(EXT3_JOURNAL(inode), jblocks);
- unlock_kernel();
-
- return handle;
-}
-
-static void smfs_e3_trans_commit(void *handle)
-{
- lock_kernel();
- journal_stop(handle);
- unlock_kernel();
-}
-
-struct journal_operations smfs_ext3_journal_ops = {
- .tr_start = smfs_e3_trans_start,
- .tr_commit = smfs_e3_trans_commit,
-};
-#endif
-
+++ /dev/null
-/*
- * smfs/kml.c
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-#include "kml_idl.h"
-
-/*FIXME there should be more conditions in this check*/
-int smfs_do_kml(struct inode *dir)
-{
- struct smfs_super_info *smfs_info = S2SMI(dir->i_sb);
-
- if (smfs_info->flags & SM_DO_KML) {
- return 1;
- }
- return 0;
-}
-void smfs_getversion(struct smfs_version * smfs_version,
- struct inode * inode)
-{
- smfs_version->sm_mtime = (__u64)inode->i_mtime;
- smfs_version->sm_ctime = (__u64)inode->i_ctime;
- smfs_version->sm_size = (__u64)inode->i_size;
-}
-
-int smfs_kml_init(struct super_block *sb)
-{
- struct smfs_super_info *smfs_info = S2SMI(sb);
- int rc = 0;
- smfs_info->flags |= SM_DO_KML;
-
- rc = smfs_llog_setup(&smfs_info->kml_llog);
-
- RETURN(rc);
-}
-
-int post_kml_mkdir(struct inode *dir, struct dentry *dentry)
-{
- struct smfs_version tgt_dir_ver, new_dir_ver;
- int error;
-
- smfs_getversion(&tgt_dir_ver, dir);
-
- smfs_getversion(&new_dir_ver, dentry->d_inode);
-
- error = smfs_journal_mkdir(dentry, &tgt_dir_ver,
- &new_dir_ver,
- dentry->d_inode->i_mode);
- return error;
-}
-
+++ /dev/null
-/*
- * smfs/kml_idl.h
- */
-
-# define MYPATHLEN(buffer, path) ((buffer) + PAGE_SIZE - (path))
-/*Got these defines from intermezzo*/
-struct kml_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;
-};
-
-#define KML_MAJOR_VERSION 0x00010000
-#define KML_MINOR_VERSION 0x00000002
-#define KML_OPCODE_NOOP 0
-#define KML_OPCODE_CREATE 1
-#define KML_OPCODE_MKDIR 2
-#define KML_OPCODE_UNLINK 3
-#define KML_OPCODE_RMDIR 4
-#define KML_OPCODE_CLOSE 5
-#define KML_OPCODE_SYMLINK 6
-#define KML_OPCODE_RENAME 7
-#define KML_OPCODE_SETATTR 8
-#define KML_OPCODE_LINK 9
-#define KML_OPCODE_OPEN 10
-#define KML_OPCODE_MKNOD 11
-#define KML_OPCODE_WRITE 12
-#define KML_OPCODE_RELEASE 13
-#define KML_OPCODE_TRUNC 14
-#define KML_OPCODE_SETEXTATTR 15
-#define KML_OPCODE_DELEXTATTR 16
-#define KML_OPCODE_KML_TRUNC 17
-#define KML_OPCODE_GET_FILEID 18
-#define KML_OPCODE_NUM 19
-
-#ifdef __KERNEL__
-# define NTOH__u32(var) le32_to_cpu(var)
-# define NTOH__u64(var) le64_to_cpu(var)
-# define HTON__u32(var) cpu_to_le32(var)
-# define HTON__u64(var) cpu_to_le64(var)
-#else
-# include <glib.h>
-# define NTOH__u32(var) GUINT32_FROM_LE(var)
-# define NTOH__u64(var) GUINT64_FROM_LE(var)
-# define HTON__u32(var) GUINT32_TO_LE(var)
-# define HTON__u64(var) GUINT64_TO_LE(var)
-#endif
-
-
+++ /dev/null
-/*
- * snapfs/options.c
- */
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-
-static struct list_head option_list;
-char *options = NULL;
-char *opt_left = NULL;
-
-int init_option(char *data)
-{
- INIT_LIST_HEAD(&option_list);
- SM_ALLOC(options, strlen(data) + 1);
- if (!options) {
- CERROR("Can not allocate memory \n");
- return -ENOMEM;
- }
- memcpy(options, data, strlen(data));
- opt_left = options;
- return 0;
-}
-/*cleanup options*/
-void cleanup_option(void)
-{
- struct option *option;
- while (!list_empty(&option_list)) {
- option = list_entry(option_list.next, struct option, list);
- list_del(&option->list);
- SM_FREE(option->opt, strlen(option->opt) + 1);
- if (option->value)
- SM_FREE(option->value, strlen(option->value) + 1);
- SM_FREE(option, sizeof(struct option));
- }
- SM_FREE(options, strlen(options) + 1);
-}
-int get_opt(struct option **option, char **pos)
-{
- char *name, *value, *left, *tmp;
- struct option *tmp_opt;
- int length = 0;
-
- *pos = opt_left;
-
- if (! *opt_left)
- return -ENODATA;
- left = strchr(opt_left, ',');
- if (left == opt_left)
- return -EINVAL;
- if (!left){
- left = opt_left + strlen(opt_left);
- }
-
- SM_ALLOC(tmp_opt, sizeof(struct option));
- tmp_opt->opt = NULL;
- tmp_opt->value = NULL;
-
- tmp = opt_left;
- while(tmp != left && *tmp != '=') {
- length++;
- tmp++;
- }
- SM_ALLOC(name, length + 1);
- tmp_opt->opt = name;
- memset(name, 0, length + 1);
- while (opt_left != tmp) *name++ = *opt_left++;
-
- if (*tmp == '=') {
- /*this option has value*/
- opt_left ++; /*after '='*/
- if (left == opt_left) {
- SM_FREE(tmp_opt->opt, length);
- SM_FREE(tmp_opt, sizeof(struct option));
- opt_left = *pos;
- return -EINVAL;
- }
- length = left - opt_left + 1;
- SM_ALLOC(value, length);
- tmp_opt->value = value;
- memset(value, 0, length);
- while (opt_left != left) *value++ = *opt_left++;
- }
- list_add(&tmp_opt->list, &option_list);
- if (*opt_left == ',') opt_left ++; /*after ','*/
- *option = tmp_opt;
- return 0;
-}
+++ /dev/null
-/*
- * smfs/kml.c
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
+++ /dev/null
-/*
- * fs/smfs/sm_fs.c
- *
- * A storage management file system.
- *
- */
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/miscdevice.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-int sm_stack = 0;
-long sm_kmemory = 0;
-
-
-MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
-MODULE_DESCRIPTION("Smfs file system filters v0.01");
-
-extern int init_smfs(void);
-extern int cleanup_smfs(void);
-extern int init_snap_sysctl(void);
-
-static int __init smfs_init(void)
-{
- int err;
-
- if ( (err = init_smfs()) ) {
- printk("Error initializing snapfs, %d\n", err);
- return -EINVAL;
- }
-
- if ( (err = init_smfs_proc_sys()) ) {
- printk("Error initializing snapfs proc sys, %d\n", err);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void __exit smfs_cleanup(void)
-{
- cleanup_smfs();
-}
-module_init(smfs_init);
-module_exit(smfs_cleanup);
-
+++ /dev/null
-#ifndef __LINUX_SMFS_H
-#define __LINUX_SMFS_H
-
-struct smfs_inode_info {
- struct inode *smi_inode;
-};
-
-struct smfs_super_info {
- struct super_block *smsi_sb;
- struct vfsmount *smsi_mnt; /* mount the cache kern with kern_do_mount (like MDS) */
- __u32 flags; /* flags*/
- struct llog_ctxt *kml_llog; /*smfs kml llog*/
- int ops_check;
-};
-
-#define I2SMI(inode) ((struct smfs_inode_info *) (&(inode->u.generic_ip)))
-#define S2SMI(sb) ((struct smfs_super_info *) (&(sb->u.generic_sbp)))
-#define S2CSB(sb) (((struct smfs_super_info *) (&(sb->u.generic_sbp)))->smsi_sb)
-#define I2CI(inode) (((struct smfs_inode_info*) (&(inode->u.generic_ip)))->smi_inode)
-
-#define SB_OPS_CHECK 0x1
-#define INODE_OPS_CHECK 0x2
-#define FILE_OPS_CHECK 0x4
-#define DENTRY_OPS_CHECK 0x8
-#define DEV_OPS_CHECK 0x10
-#define SYMLINK_OPS_CHECK 0x20
-#define DIR_OPS_CHECK 0x40
-
-#define SM_DO_KML 0x1
-
-#include "smfs_support.h"
-
-struct journal_operations {
- void *(*tr_start)(struct inode *, int op);
- void (*tr_commit)(void *handle);
-};
-
-struct sm_ops {
- /* operations on the file store */
- struct super_operations sm_sb_ops;
-
- struct inode_operations sm_dir_iops;
- struct inode_operations sm_file_iops;
- struct inode_operations sm_sym_iops;
-
- struct file_operations sm_dir_fops;
- struct file_operations sm_file_fops;
- struct file_operations sm_sym_fops;
-
- struct dentry_operations sm_dentry_ops;
- struct journal_operations sm_journal_ops;
-
-};
-struct option {
- char *opt;
- char *value;
- struct list_head list;
-};
-
-extern int init_smfs_proc_sys(void);
-/*options.c*/
-extern int get_opt(struct option **option, char **pos);
-extern void cleanup_option(void);
-extern int init_option(char *data);
-/*cache.c*/
-void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode);
-void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb);
-void init_smfs_cache(void);
-void cleanup_smfs_cache(void);
-void setup_sm_journal_ops(char * cache_type);
-/*super.c*/
-extern int init_smfs(void);
-extern int cleanup_smfs(void);
-extern void smfs_put_super(struct super_block *sb);
-extern void duplicate_sb(struct super_block *csb, struct super_block *sb);
-/*sysctl.c*/
-extern int sm_debug_level;
-extern int sm_inodes;
-extern long sm_kmemory;
-extern int sm_stack;
-/*dir.c*/
-extern struct inode_operations smfs_dir_iops;
-extern struct file_operations smfs_dir_fops;
-
-extern void d_unalloc(struct dentry *dentry);
-/*inode.c*/
-extern void duplicate_inode(struct inode *cache_inode, struct inode *inode);
-/*file.c*/
-extern void smfs_prepare_cachefile(struct inode *inode,
- struct file *file,
- struct inode *cache_inode,
- struct file *cache_file,
- struct dentry *cache_dentry);
-extern int smfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
- unsigned long arg);
-extern int smfs_fsync(struct file * file, struct dentry *dentry, int datasync);
-extern int smfs_setattr(struct dentry *dentry, struct iattr *attr);
-extern int smfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
-extern int smfs_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size);
-extern ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-extern int smfs_removexattr(struct dentry *dentry, const char *name);
-extern void smfs_update_file(struct file *file, struct file *cache_file);
-/*journal.c */
-extern void *smfs_trans_start(struct inode *inode, int op);
-extern void smfs_trans_commit(void *handle);
-extern int smfs_journal_mkdir(struct dentry *dentry,
- struct smfs_version *tgt_dir_ver,
- struct smfs_version *new_dir_ver,
- int mode);
-/*journal_ext3.c*/
-extern struct journal_operations smfs_ext3_journal_ops;
-/*kml.c*/
-extern int smfs_kml_init(struct super_block *sb);
-extern int smfs_do_kml(struct inode *dir);
-extern void smfs_getversion(struct smfs_version * smfs_version, struct inode * inode);
-extern int post_kml_mkdir(struct inode *dir, struct dentry *dentry);
-/*smfs_llog.c*/
-extern int smfs_llog_setup(struct llog_ctxt **ctxt);
-#endif /* __LINUX_SMFS_H */
+++ /dev/null
-/*
- * llog.c
- */
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/lustre_idl.h>
-
-#include "smfs_internal.h"
-
-int smfs_llog_setup(struct llog_ctxt **p_ctxt)
-{
- int rc = 0;
-
- RETURN(rc);
-}
-
-
-
-
-
-
+++ /dev/null
-#ifndef __LINUX_SMFS_SUPPORT_H
-#define __LINUX_SMFS_SUPPORT_H
-/*Got these defination from lustre. Put here temporaryly*/
-
-#define D_TRACE (1 << 0) /* ENTRY/EXIT markers */
-#define D_INODE (1 << 1)
-#define D_SUPER (1 << 2)
-#define D_EXT2 (1 << 3) /* anything from ext2_debug */
-#define D_MALLOC (1 << 4) /* print malloc, free information */
-#define D_CACHE (1 << 5) /* cache-related items */
-#define D_INFO (1 << 6) /* general information */
-#define D_IOCTL (1 << 7) /* ioctl related information */
-#define D_BLOCKS (1 << 8) /* ext2 block allocation */
-#define D_NET (1 << 9) /* network communications */
-#define D_WARNING (1 << 10) /* CWARN(...) == CDEBUG (D_WARNING, ...) */
-#define D_BUFFS (1 << 11)
-#define D_OTHER (1 << 12)
-#define D_DENTRY (1 << 13)
-#define D_PAGE (1 << 15) /* bulk page handling */
-#define D_DLMTRACE (1 << 16)
-#define D_ERROR (1 << 17) /* CERROR(...) == CDEBUG (D_ERROR, ...) */
-#define D_EMERG (1 << 18) /* CEMERG(...) == CDEBUG (D_EMERG, ...) */
-#define D_HA (1 << 19) /* recovery and failover */
-#define D_RPCTRACE (1 << 20) /* for distributed debugging */
-#define D_VFSTRACE (1 << 21)
-#define D_SM (1 << 22)
-
-
-#ifdef __KERNEL__
-# include <linux/sched.h> /* THREAD_SIZE */
-#else
-# ifndef THREAD_SIZE /* x86_64 has THREAD_SIZE in userspace */
-# define THREAD_SIZE 8192
-# endif
-#endif
-# include <linux/vmalloc.h>
-# define sm_debug_msg(mask, file, fn, line, stack, format, a...) \
- printk("%02x (@%lu %s:%s,l. %d %d %lu): " format, \
- (mask), (long)time(0), file, fn, line, \
- getpid() , stack, ## a);
-
-#define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5)
-
-#ifdef __KERNEL__
-# ifdef __ia64__
-# define CDEBUG_STACK (THREAD_SIZE - \
- ((unsigned long)__builtin_dwarf_cfa() & \
- (THREAD_SIZE - 1)))
-# else
-# define CDEBUG_STACK (THREAD_SIZE - \
- ((unsigned long)__builtin_frame_address(0) & \
- (THREAD_SIZE - 1)))
-# endif
-
-#define CHECK_STACK(stack) \
- do { \
- if ((stack) > 3*THREAD_SIZE/4 && (stack) > sm_stack) { \
- printk( "maximum lustre stack %u\n", \
- sm_stack = (stack)); \
- } \
- } while (0)
-#else /* __KERNEL__ */
-#define CHECK_STACK(stack) do { } while(0)
-#define CDEBUG_STACK (0L)
-#endif /* __KERNEL__ */
-
-#if 1
-#define CDEBUG(mask, format, a...) \
-do { \
- CHECK_STACK(CDEBUG_STACK); \
- if (!(mask) || ((mask) & (D_ERROR | D_EMERG | D_WARNING)) || \
- (sm_debug_level & (mask))) { \
- printk("SM_DEBUG: (%s %d):", __FILE__, __LINE__); \
- printk(format, ## a); \
- } \
-} while (0)
-
-#define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a)
-#define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a)
-#define CEMERG(format, a...) CDEBUG(D_EMERG, format, ## a)
-
-#define GOTO(label, rc) \
-do { \
- long GOTO__ret = (long)(rc); \
- CDEBUG(D_TRACE,"SM_DEBUG: (%s %d):Process leaving via %s (rc=%lu : %ld : %lx)\n", \
- __FILE__, __LINE__, #label, (unsigned long)GOTO__ret, \
- (signed long)GOTO__ret, \
- (signed long)GOTO__ret); \
- goto label; \
-} while (0)
-
-#define RETURN(rc) \
-do { \
- typeof(rc) RETURN__ret = (rc); \
- CDEBUG(D_TRACE, "Process %d leaving %s (rc=%lu : %ld : %lx)\n", \
- current->pid, __FUNCTION__, (long)RETURN__ret, \
- (long)RETURN__ret, (long)RETURN__ret); \
- return RETURN__ret; \
-} while (0)
-
-#define ENTRY \
-do { \
- CDEBUG(D_TRACE, "SM_DEBUG: (%s %d): Process %d enter %s\n", \
- __FILE__, __LINE__, current->pid, __FUNCTION__); \
-} while (0)
-
-#define EXIT \
-do { \
- CDEBUG(D_TRACE, "SM_DEBUG: (%s %d): Process %d leaving %s \n", \
- __FILE__, __LINE__, current->pid, __FUNCTION__); \
-} while(0)
-#else
-#define CDEBUG(mask, format, a...) do { } while (0)
-#define CWARN(format, a...) do { } while (0)
-#define CERROR(format, a...) printk("<3>" format, ## a)
-#define CEMERG(format, a...) printk("<0>" format, ## a)
-#define GOTO(label, rc) do { (void)(rc); goto label; } while (0)
-#define RETURN(rc) return (rc)
-#define ENTRY do { } while (0)
-#define EXIT do { } while (0)
-#endif
-
-#define SM_ALLOC(ptr, size) \
-do { \
- if (size <= 4096) { \
- ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
- CDEBUG(D_MALLOC, "Proc %d %s:%d kmalloced: %d at %x.\n",\
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- } else { \
- ptr = vmalloc((unsigned long) size); \
- CDEBUG(D_MALLOC, "Proc %d %s:%d vmalloced: %d at %x.\n",\
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- } \
- if (ptr == 0) { \
- printk("kernel malloc returns 0 at %s:%d\n", \
- __FILE__, __LINE__); \
- } else { \
- memset(ptr, 0, size); \
- sm_kmemory += size; \
- } \
-} while (0)
-
-#define SM_FREE(ptr,size) \
-do { \
- sm_kmemory -= size; \
- if (size <= 4096) { \
- CDEBUG(D_MALLOC, "Proc %d %s:%d kfreed: %d at %x.\n", \
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- kfree((ptr)); \
- } else { \
- CDEBUG(D_MALLOC, "Proc %d %s:%d vfreed: %d at %x.\n", \
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- vfree((ptr)); \
- } \
-} while (0)
-
-#endif /*__LINUX_SMFS_SUPPORT_H */
+++ /dev/null
-/*
- * Copyright (c) 2003-2004 Cluster File Systems, Inc.
- *
- */
-#define DEBUG_SUBSYSTEM S_SM
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/utime.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/loop.h>
-#include <linux/errno.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-/* Find the options for the clone. These consist of a cache device
- and an index in the snaptable associated with that device.
-*/
-static char *smfs_options(char *options, char **devstr, char **namestr, int *kml)
-{
- struct option *opt_value = NULL;
- char *pos;
-
- while (!(get_opt(&opt_value, &pos))) {
- if (!strcmp(opt_value->opt, "dev")) {
- if (devstr != NULL)
- *devstr = opt_value->value;
- } else if (!strcmp(opt_value->opt, "type")) {
- if (namestr != NULL)
- *namestr = opt_value->value;
- } else if (!strcmp(opt_value->opt, "kml")) {
- *kml = 1;
- } else {
- break;
- }
- }
- return pos;
-}
-
-static int set_loop_fd(char *dev_path, char *loop_dev)
-{
- struct loop_info loopinfo;
- struct nameidata nd;
- struct dentry *dentry;
- struct block_device_operations *bd_ops;
- struct file *filp;
- int fd = 0, error = 0;
-
- fd = get_unused_fd();
-
- if (!fd) RETURN(-EINVAL);
-
- filp = filp_open(dev_path, FMODE_WRITE, 0);
- if (!filp || !S_ISREG(filp->f_dentry->d_inode->i_mode))
- RETURN(-EINVAL);
-
- fd_install(fd, filp);
-
- if (path_init(loop_dev, LOOKUP_FOLLOW, &nd)) {
- error = path_walk(loop_dev, &nd);
- if (error) {
- path_release(&nd);
- filp_close(filp, current->files);
- RETURN(-EINVAL);
- }
- } else {
- path_release(&nd);
- filp_close(filp, current->files);
- RETURN(-EINVAL);
- }
- dentry = nd.dentry;
- bd_ops = get_blkfops(LOOP_MAJOR);
-
- error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_FD,
- (unsigned long)fd);
- if (error) {
- path_release(&nd);
- filp_close(filp, current->files);
- RETURN(-EINVAL);
- }
- memset(&loopinfo, 0, sizeof(struct loop_info));
-
- error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_STATUS,
- (unsigned long)(&loopinfo));
- path_release(&nd);
- RETURN(error);
-}
-
-#define SIZE(a) (sizeof(a)/sizeof(a[0]))
-static char *find_unused_and_set_loop_device(char *dev_path)
-{
- char *loop_formats[] = { "/dev/loop/%d", "/dev/loop%d"};
- struct loop_info loopinfo;
- struct nameidata nd;
- struct dentry *dentry;
- char *dev = NULL;
- int i, j, error;
-
- for (j = 0; j < SIZE(loop_formats); j++) {
- SM_ALLOC(dev, strlen(loop_formats[i]) + 1);
- for(i = 0; i < 256; i++) {
- struct block_device_operations *bd_ops;
-
- sprintf(dev, loop_formats[j], i);
-
- if (path_init(dev, LOOKUP_FOLLOW, &nd)) {
- error = path_walk(dev, &nd);
- if (error && error != -ENOENT) {
- path_release(&nd);
- SM_FREE(dev, strlen(loop_formats[i]) + 1);
- RETURN(NULL);
- }
- } else {
- SM_FREE(dev, strlen(loop_formats[i]) + 1);
- RETURN(NULL);
- }
- dentry = nd.dentry;
- bd_ops = get_blkfops(LOOP_MAJOR);
- error = bd_ops->ioctl(dentry->d_inode, NULL, LOOP_GET_STATUS,
- (unsigned long)&loopinfo);
- path_release(&nd);
-
- if (error == -ENXIO) {
- /*find unused loop and set dev_path to loopdev*/
- error = set_loop_fd(dev_path, dev);
- if (error) {
- SM_FREE(dev, strlen(loop_formats[i]) + 1);
- dev = NULL;
- }
- return dev;/* probably free */
- }
- }
- SM_FREE(dev, strlen(loop_formats[i]) + 1);
- }
- RETURN(NULL);
-}
-
-#define MAX_LOOP_DEVICES 256
-static char *parse_path2dev(struct super_block *sb, char *dev_path)
-{
- struct dentry *dentry;
- struct nameidata nd;
- char *name = NULL;
- int error = 0;
-
- if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
- error = path_walk(dev_path, &nd);
- if (error) {
- path_release(&nd);
- RETURN(NULL);
- }
- } else {
- RETURN(NULL);
- }
- dentry = nd.dentry;
-
- if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
- (!S_ISBLK(dentry->d_inode->i_mode) &&
- !S_ISREG(dentry->d_inode->i_mode))){
- path_release(&nd);
- RETURN(NULL);
- }
-
- if (S_ISREG(dentry->d_inode->i_mode)) {
- name = find_unused_and_set_loop_device(dev_path);
- path_release(&nd);
- RETURN(name);
- }
- SM_ALLOC(name, strlen(dev_path) + 1);
- memcpy(name, dev_path, strlen(dev_path) + 1);
- RETURN(name);
-}
-void duplicate_sb(struct super_block *csb,
- struct super_block *sb)
-{
- sb->s_blocksize = csb->s_blocksize;
- sb->s_magic = csb->s_magic;
- sb->s_blocksize_bits = csb->s_blocksize_bits;
- sb->s_maxbytes = csb->s_maxbytes;
-}
-extern struct super_operations smfs_super_ops;
-
-static int sm_mount_cache(struct super_block *sb,
- char *devstr,
- char *typestr)
-{
- struct vfsmount *mnt;
- struct smfs_super_info *smb;
- char *dev_name = NULL;
- unsigned long page;
- int err = 0;
-
- dev_name = parse_path2dev(sb, devstr);
- if (!dev_name) {
- GOTO(err_out, err = -ENOMEM);
- }
- if (!(page = __get_free_page(GFP_KERNEL))) {
- GOTO(err_out, err = -ENOMEM);
- }
- memset((void *)page, 0, PAGE_SIZE);
- sprintf((char *)page, "iopen_nopriv");
-
- mnt = do_kern_mount(typestr, 0, dev_name, (void *)page);
- free_page(page);
-
- if (IS_ERR(mnt)) {
- CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
- GOTO(err_out, err = PTR_ERR(mnt));
- }
- smb = S2SMI(sb);
- smb->smsi_sb = mnt->mnt_sb;
- smb->smsi_mnt = mnt;
-
- duplicate_sb(mnt->mnt_sb, sb);
- sm_set_sb_ops(mnt->mnt_sb, sb);
-err_out:
- if (dev_name)
- SM_FREE(dev_name, strlen(dev_name) + 2);
-
- return err;
-}
-static int sm_umount_cache(struct super_block *sb)
-{
- struct smfs_super_info *smb = S2SMI(sb);
-
- mntput(smb->smsi_mnt);
-
- return 0;
-}
-void smfs_put_super(struct super_block *sb)
-{
- if (sb)
- sm_umount_cache(sb);
- return;
-}
-
-struct super_block *
-smfs_read_super(
- struct super_block *sb,
- void *data,
- int silent)
-{
- struct inode *root_inode = NULL;
- char *devstr = NULL, *typestr = NULL;
- char *cache_data;
- ino_t root_ino;
- int err = 0, kml = 0;
-
- ENTRY;
-
- CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
-
- init_option(data);
- /* read and validate options */
- cache_data = smfs_options(data, &devstr, &typestr, &kml);
- if (*cache_data) {
- CERROR("invalid mount option %s\n", (char*)data);
- GOTO(out_err, err=-EINVAL);
- }
- if (!typestr || !devstr) {
- CERROR("mount options name and dev mandatory\n");
- GOTO(out_err, err=-EINVAL);
- }
-
- err = sm_mount_cache(sb, devstr, typestr);
- if (err) {
- CERROR("Can not mount %s as %s\n", devstr, typestr);
- GOTO(out_err, 0);
- }
-
- if (kml) smfs_kml_init(sb);
-
- setup_sm_journal_ops(typestr);
-
- dget(S2CSB(sb)->s_root);
- root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
- root_inode = iget(sb, root_ino);
-
- CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
- sb->s_op->read_inode, root_ino, root_inode);
-
- sb->s_root = d_alloc_root(root_inode);
-
- if (!sb->s_root) {
- GOTO(out_err, err=-EINVAL);
- }
-
- CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
- (ulong) sb, (ulong) &sb->u.generic_sbp);
-
-out_err:
- cleanup_option();
- if (err)
- return NULL;
- return sb;
-}
-
-static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
-
-int init_smfs(void)
-{
- int err = 0;
-
- err = register_filesystem(&smfs_type);
- if (err) {
- CERROR("smfs: failed in register Storage Management filesystem!\n");
- }
- init_smfs_cache();
- return err;
-}
-
-int cleanup_smfs(void)
-{
- int err = 0;
-
- ENTRY;
- err = unregister_filesystem(&smfs_type);
- if (err) {
- CERROR("smfs: failed to unregister Storage Management filesystem!\n");
- }
- cleanup_smfs_cache();
- return 0;
-}
+++ /dev/null
-/*
- * smfs/symlink.c
- *
- *
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/lustre_idl.h>
-
-#include "smfs_internal.h"
-
-static int smfs_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *cache_inode = I2CI(dentry->d_inode);
- struct inode *cache_dir = NULL;
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
-
- if (!cache_inode)
- RETURN(-ENOENT);
- if (dentry->d_parent && dentry->d_parent->d_inode){
- cache_dir = I2CI(dentry->d_parent->d_inode);
- prepare_parent_dentry(&parent, cache_dir);
- }
- cache_dentry = d_alloc(&parent, &dentry->d_name);
- d_add(cache_dentry, cache_inode);
- igrab(cache_inode);
-
- if (cache_inode->i_op && cache_inode->i_op->readlink)
- rc = cache_inode->i_op->readlink(cache_dentry, buffer, buflen);
-
- d_unalloc(cache_dentry);
- return rc;
-}
-
-static int smfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct inode *cache_inode = I2CI(dentry->d_inode);
- struct inode *cache_dir = NULL;
- struct dentry *cache_dentry;
- struct dentry parent;
- int rc = 0;
- if (!cache_inode)
- RETURN(-ENOENT);
-
- if (dentry->d_parent && dentry->d_parent->d_inode){
- cache_dir = I2CI(dentry->d_parent->d_inode);
- prepare_parent_dentry(&parent, cache_dir);
- }
-
- cache_dentry = d_alloc(&parent, &dentry->d_name);
-
- d_add(cache_dentry, cache_inode);
- igrab(cache_inode);
-
- if (cache_inode->i_op && cache_inode->i_op->follow_link)
- rc = cache_inode->i_op->follow_link(cache_dentry, nd);
-
- d_unalloc(cache_dentry);
- return rc;
-}
-struct inode_operations smfs_sym_iops = {
- readlink: smfs_readlink,
- follow_link: smfs_follow_link,
- setxattr: smfs_setxattr, /* BKL held */
- getxattr: smfs_getxattr, /* BKL held */
- listxattr: smfs_listxattr, /* BKL held */
- removexattr: smfs_removexattr, /* BKL held */
-};
-
-struct file_operations smfs_sym_fops = {
-};
+++ /dev/null
-/*
- * Sysctrl entries for Snapfs
- */
-
-/* /proc entries */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_smfs_root;
-#endif
-
-
-/* SYSCTL below */
-
-static struct ctl_table_header *smfs_table_header = NULL;
-/* 0x100 to avoid any chance of collisions at any point in the tree with
- * non-directories
- */
-#define PSDEV_SMFS (0x130)
-
-#define PSDEV_DEBUG 1 /* control debugging */
-#define PSDEV_TRACE 2 /* control enter/leave pattern */
-
-/* These are global control options */
-#define ENTRY_CNT 3
-
-int sm_print_entry = 1;
-int sm_debug_level = 0;
-
-/* XXX - doesn't seem to be working in 2.2.15 */
-static struct ctl_table smfs_ctltable[] =
-{
- {PSDEV_DEBUG, "debug", &sm_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
- {PSDEV_TRACE, "trace", &sm_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
- {0}
-};
-
-static ctl_table smfs_table[2] = {
- {PSDEV_SMFS, "smfs", NULL, 0, 0555, smfs_ctltable},
- {0}
-};
-
-
-int __init init_smfs_proc_sys(void)
-{
-#ifdef CONFIG_PROC_FS
- proc_smfs_root = proc_mkdir("smfs", proc_root_fs);
- if (!proc_smfs_root) {
- printk(KERN_ERR "SMFS: error registering /proc/fs/smfs\n");
- RETURN(-ENOMEM);
- }
- proc_smfs_root->owner = THIS_MODULE;
-#endif
-
-#ifdef CONFIG_SYSCTL
- if ( !smfs_table_header )
- smfs_table_header =
- register_sysctl_table(smfs_table, 0);
-#endif
- return 0;
-}
-
-void cleanup_smfs_proc_sys(void)
-{
-#ifdef CONFIG_SYSCTL
- if ( smfs_table_header )
- unregister_sysctl_table(smfs_table_header);
- smfs_table_header = NULL;
-#endif
-#if CONFIG_PROC_FS
- remove_proc_entry("smfs", proc_root_fs);
-#endif
-}
-
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-.deps
-TAGS
-.*.cmd
-autoMakefile.in
-autoMakefile
-*.ko
-*.mod.c
-.*.flags
-.tmp_versions
+++ /dev/null
-MODULES := snapfs
-snapfs-objs := cache.o clonefs.o dcache.o dir.o dotsnap.o file.o
-snapfs-objs += filter.o inode.o journal_ext3.o psdev.o
-snapfs-objs += snap.o snaptable.o super.o symlink.o sysctl.o options.o
-
-@INCLUDE_RULES@
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-SUBDIRS = . utils
-
-if MODULES
-if SNAPFS
-modulefs_DATA = snapfs$(KMODEXT)
-endif
-endif
-
-MOSTLYCLEANFILES = *.o *.ko *.mod.c
-DIST_SOURCES = $(snapfs-objs:%.o=%.c) snapfs_internal.h snapfs_support.h
-
+++ /dev/null
-/*
- * snapfs/cache.c
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-#include <portals/list.h>
-#include "snapfs_internal.h"
-/*
- * XXX - Not sure for snapfs that the cache functions are even needed.
- * Can't all lookups be done by an inode->superblock->u.generic_sbp
- * lookup?
- */
-
-extern struct snap_table snap_tables[SNAP_MAX_TABLES];
-
-/* 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 snap_caches[CACHES_SIZE];
-
-
-static inline int snap_cache_hash(kdev_t dev)
-{
- return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
-}
-
-inline void snap_cache_add(struct snap_cache *cache, kdev_t dev)
-{
- list_add(&cache->cache_chain,
- &snap_caches[snap_cache_hash(dev)]);
- cache->cache_dev = dev;
-}
-
-inline void snap_init_cache_hash(void)
-{
- int i;
- for ( i = 0; i < CACHES_SIZE; i++ ) {
- INIT_LIST_HEAD(&snap_caches[i]);
- }
-}
-
-/* map a device to a cache */
-struct snap_cache *snap_find_cache(kdev_t dev)
-{
- struct snap_cache *cache;
- struct list_head *lh;
-
- lh = &(snap_caches[snap_cache_hash(dev)]);
- list_for_each_entry(cache, lh, cache_chain) {
- if (cache->cache_dev == dev)
- return cache;
- }
- return NULL;
-}
-
-/* setup a cache structure when we need one */
-struct snap_cache *snap_init_cache(void)
-{
- struct snap_cache *cache;
-
- /* make a snap_cache structure for the hash */
- SNAP_ALLOC(cache, sizeof(struct snap_cache));
- if ( cache ) {
- memset(cache, 0, sizeof(struct snap_cache));
- INIT_LIST_HEAD(&cache->cache_chain);
- INIT_LIST_HEAD(&cache->cache_clone_list);
- }
- return cache;
-}
-/*walk through the cache structure*/
-int snap_cache_process(snap_cache_cb_t cb, void* in, unsigned long* out)
-{
- int i = 0;
-
- for (i = 0; i < CACHES_SIZE; i++) {
- struct snap_cache *cache;
- struct list_head *lh = &(snap_caches[i]);
- list_for_each_entry(cache, lh, cache_chain) {
- if (cb(cache, in, out))
- goto exit;
- }
- }
-exit:
- return 0;
-}
-
-
-/* free a cache structure and all of the memory it is pointing to */
-inline void snap_free_cache(struct snap_cache *cache)
-{
- if (!cache)
- return;
- SNAP_FREE(cache, sizeof(struct snap_cache));
-}
-
+++ /dev/null
-/*
- * Super block/filesystem wide operations
- *
- * Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
- * Michael Callahan <callahan@maths.ox.ac.uk>
- *
- * Rewritten for Linux 2.1. Peter Braam <braam@cs.cmu.edu>
- * Copyright (C) Carnegie Mellon University
- *
- * Copyright (C) 2000, Mountain View Data, Inc, authors
- * Peter Braam <braam@mountainviewdata.com>,
- * Harrison Xing <harrisonx@mountainviewdata.com>
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-#include "snapfs_internal.h"
-
-
-/* Clone is a simple file system, read only that just follows redirectors
- we have placed the entire implementation except clone_read_super in
- this file
- */
-
-struct inode_operations clonefs_dir_inode_ops;
-struct inode_operations clonefs_file_inode_ops;
-struct inode_operations clonefs_symlink_inode_ops;
-//struct inode_operations clonefs_special_inode_operations;
-struct file_operations clonefs_dir_file_ops;
-struct file_operations clonefs_file_file_ops;
-//struct file_operations clonefs_special_file_operations;
-struct address_space_operations clonefs_file_address_ops;
-
-/* support routines for following redirectors */
-
-/* Parameter is clonefs inode, 'inode', and typically this may be
- called before read_inode has completed on this clonefs inode,
- i.e. we may only assume that i_ino is valid.
-
- We return an underlying (likely disk) fs inode. This involved
- handling any redirector inodes found along the way.
-
- This function is used by all clone fs interface functions to get an
- underlying fs inode.
-*/
-
-struct inode *clonefs_get_inode(struct inode *inode)
-{
- struct snap_clone_info *clone_sb;
- struct inode *cache_inode, *redirected_inode;
-
- ENTRY;
-
- /* this only works if snapfs_current does NOT overwrite read_inode */
- clone_sb = (struct snap_clone_info *) &inode->i_sb->u.generic_sbp;
-
- /* basic invariant: clone and current ino's are equal */
- cache_inode = iget(clone_sb->clone_cache->cache_sb, inode->i_ino);
-
- redirected_inode = snap_redirect(cache_inode, inode->i_sb);
-
- CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
- (unsigned long) redirected_inode, (unsigned long) cache_inode);
-
- CDEBUG(D_SNAP, "cache_inode: %lx, ino %ld, sb %lx, count %d\n",
- (unsigned long) cache_inode, cache_inode->i_ino,
- (unsigned long) cache_inode->i_sb, atomic_read(&cache_inode->i_count));
-
- iput(cache_inode);
-
- return redirected_inode;
-}
-
-
-/* super operations */
-static void clonefs_read_inode(struct inode *inode)
-{
- struct inode *cache_inode;
-
- ENTRY;
-
- CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n",
- (unsigned long)inode, inode->i_ino, (long) inode->i_sb,
- atomic_read(&inode->i_count));
-
- /* redirecting inode in the cache */
- cache_inode = clonefs_get_inode(inode);
- if (!cache_inode) {
- make_bad_inode(inode);
- return;
- }
- /* copy attrs of that inode to our clone inode */
- snapfs_cpy_attrs(inode, cache_inode);
-
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &clonefs_file_inode_ops;
- if (inode->i_mapping)
- inode->i_mapping->a_ops = &clonefs_file_address_ops;
- inode->i_fop = &clonefs_file_file_ops;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &clonefs_dir_inode_ops;
- inode->i_fop = &clonefs_dir_file_ops;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &clonefs_symlink_inode_ops;
- } else {
- /* init special inode
- * FIXME whether we should replace special inode ops*/
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
- init_special_inode(inode, inode->i_mode,
- kdev_t_to_nr(inode->i_rdev));
-#else
- init_special_inode(inode, inode->i_mode, inode->i_rdev);
-#endif
- }
- iput(cache_inode);
-
- CDEBUG(D_SNAP, "cache_inode: %lx ino %ld, sb %lx, count %d\n",
- (unsigned long) cache_inode, cache_inode->i_ino,
- (unsigned long) cache_inode->i_sb,
- atomic_read(&cache_inode->i_count));
- EXIT;
-}
-
-
-static void clonefs_put_super(struct super_block *sb)
-{
- struct snap_clone_info *clone_sb;
-
- ENTRY;
- CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
- (unsigned long) sb, (unsigned long) &sb->u.generic_sbp);
- clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
- dput(clone_sb->clone_cache->cache_sb->s_root);
- list_del(&clone_sb->clone_list_entry);
-
- put_snap_current_mnt(clone_sb->clone_cache->cache_sb);
-
- EXIT;
-}
-
-static int clonefs_statfs(struct super_block *sb, struct statfs *buf)
-{
- struct snap_clone_info *clone_sb;
- struct snap_cache *cache;
-
- ENTRY;
- clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
-
- cache = clone_sb->clone_cache;
- if (!cache) {
- CERROR("clone_statfs: no cache\n");
- RETURN(-EINVAL);
- }
-
- return cache->cache_filter->o_caops.cache_sops->statfs
- (cache->cache_sb, buf);
-}
-
-struct super_operations clone_super_ops =
-{
- read_inode: clonefs_read_inode, /* read_inode */
- put_super: clonefs_put_super, /* put_super */
- statfs: clonefs_statfs, /* statfs */
-};
-
-
-/* ***************** end of clonefs super ops ******************* */
-/* ***************** begin clonefs dir ops ******************* */
-
-static void d_unalloc(struct dentry *dentry)
-{
-
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
- dput(dentry); /* this will free the dentry memory */
-}
-
-static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
-{
- atomic_set(&dentry->d_count, 1);
- dentry->d_vfs_flags = 0;
- dentry->d_flags = 0;
- dentry->d_inode = inode;
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
- INIT_LIST_HEAD(&dentry->d_alias);
-}
-/*
- * Return the underlying fs dentry with name in 'dentry' that points
- * to the right inode. 'dir' is the clone fs directory to search for
- * the 'dentry'.
- */
-struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry)
-{
- struct inode *cache_dir = NULL;
- struct dentry *cache_dentry = NULL;
- struct inode *cache_inode;
- struct dentry *result;
- struct dentry tmp;
- struct inode *inode;
- struct snap_clone_info *clone_sb;
-
- ENTRY;
-
- cache_dir = clonefs_get_inode(dir);
- if (!cache_dir)
- RETURN(ERR_PTR(-ENOENT));
- /*FIXME later, we make parent dentry here
- *there may some problems in lookup
- */
- prepare_parent_dentry(&tmp, cache_dir);
- cache_dentry = d_alloc(&tmp, &dentry->d_name);
-
- if (!cache_dentry) {
- iput(cache_dir);
- RETURN(ERR_PTR(-ENOENT));
- }
-
- /* Lock cache directory inode. */
- down(&cache_dir->i_sem);
- /*
- * Call underlying fs lookup function to set the 'd_inode' pointer
- * to the corresponding directory inode.
- *
- * Note: If the lookup function does not return NULL, return
- * from 'clone_lookup' with an error.
- */
- result = cache_dir->i_op->lookup(cache_dir, cache_dentry);
- if (result) {
- dput(cache_dentry);
- up(&cache_dir->i_sem);
- iput(cache_dir);
- dentry->d_inode = NULL;
- RETURN(ERR_PTR(-ENOENT));
- }
- /* Unlock cache directory inode. */
- up(&cache_dir->i_sem);
-
- /*
- * If there is no inode pointer in the underlying fs 'cache_dentry'
- * then the directory doesn't have an entry with this name. In fs/ext2
- * we see that we return 0 and put dentry->d_inode = NULL;
- */
- cache_inode = cache_dentry->d_inode;
- if ( cache_inode == NULL ) {
- inode = NULL;
- } else {
- clone_sb = (struct snap_clone_info *) &dir->i_sb->u.generic_sbp;
- /* note, iget below will follow a redirector, since
- it calls into clone_read_inode
- */
- inode = iget(dir->i_sb, cache_inode->i_ino);
- }
-
- /* dput(cache_dentry) will not put the dentry away
- * immediately, unless we first arrange that its hash list is
- * empty.
- */
-
- if ( cache_inode != NULL ) {
- CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n",
- cache_inode->i_ino, atomic_read(&cache_inode->i_count),
- cache_dir->i_ino, atomic_read(&cache_dir->i_count));
- }
-
- d_unalloc(cache_dentry);
- iput(cache_dir);
-
- /*
- * Add 'inode' to the directory entry 'dentry'.
- */
- d_add(dentry, inode);
-
- RETURN(NULL);
-}
-
-
-/* instantiate a file handle to the cache file */
-static void clonefs_prepare_snapfile(struct inode *i,
- struct file *clone_file,
- struct inode *cache_inode,
- struct file *cache_file,
- struct dentry *cache_dentry)
-{
- ENTRY;
-
- cache_file->f_pos = clone_file->f_pos;
- cache_file->f_mode = clone_file->f_mode;
- cache_file->f_flags = clone_file->f_flags;
- cache_file->f_count = clone_file->f_count;
- cache_file->f_owner = clone_file->f_owner;
- cache_file->f_op = cache_inode->i_fop;
- cache_file->f_dentry = cache_dentry;
- cache_file->f_dentry->d_inode = cache_inode;
-
- EXIT;
-}
-
-/* update the clonefs file struct after IO in cache file */
-static void clonefs_restore_snapfile(struct inode *cache_inode,
- struct file *cache_file,
- struct inode *clone_inode,
- struct file *clone_file)
-{
- ENTRY;
-
- cache_file->f_pos = clone_file->f_pos;
- cache_inode->i_size = clone_inode->i_size;
-
- EXIT;
-}
-
-static int clonefs_readdir(struct file *file, void *dirent,
- filldir_t filldir)
-{
- int result;
- struct inode *cache_inode;
- struct file open_file;
- struct dentry open_dentry;
- struct inode *inode = file->f_dentry->d_inode;
-
- ENTRY;
-
- if(!inode) {
- RETURN(-EINVAL);
- }
- cache_inode = clonefs_get_inode(inode);
-
- if (!cache_inode) {
- make_bad_inode(inode);
- RETURN(-ENOMEM);
- }
-
- CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
-
- clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
- &open_dentry);
- /* potemkin case: we are handed a directory inode */
- result = -ENOENT;
- if (open_file.f_op->readdir) {
- down(&cache_inode->i_sem);
- result = open_file.f_op->readdir(&open_file, dirent, filldir);
- up(&cache_inode->i_sem);
- }
- clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
- iput(cache_inode);
- RETURN(result);
-}
-
-struct file_operations clonefs_dir_file_ops = {
- readdir: clonefs_readdir, /* readdir */
-};
-
-struct inode_operations clonefs_dir_inode_ops = {
- lookup: clonefs_lookup, /* lookup */
-};
-
-
-/* ***************** end of clonefs dir ops ******************* */
-/* ***************** begin clonefs file ops ******************* */
-
-static int clonefs_readpage(struct file *file, struct page *page)
-{
- int result = 0;
- struct inode *cache_inode;
- struct file open_file;
- struct dentry open_dentry;
- struct inode *inode;
-
- ENTRY;
-
- inode = file->f_dentry->d_inode;
- cache_inode = clonefs_get_inode(file->f_dentry->d_inode);
- if (!cache_inode) {
- make_bad_inode(file->f_dentry->d_inode);
- RETURN(-ENOMEM);
- }
-
- clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
- &open_dentry);
- /* tell currentfs_readpage the primary inode number */
- open_dentry.d_fsdata = (void*)inode->i_ino;
- page->mapping->host = cache_inode;
- /* potemkin case: we are handed a directory inode */
- down(&cache_inode->i_sem);
- /* XXX - readpage NULL on directories... */
- result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
-
- up(&cache_inode->i_sem);
- page->mapping->host = inode;
- clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
- iput(cache_inode);
- RETURN(result);
-}
-
-struct file_operations clonefs_file_file_ops = {
- read: generic_file_read, /* read -- bad */
- mmap: generic_file_mmap, /* mmap */
-};
-
-struct address_space_operations clonefs_file_address_ops = {
- readpage: clonefs_readpage
-};
-
-
-/* ***************** end of clonefs file ops ******************* */
-/* ***************** begin clonefs symlink ops ******************* */
-
-static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
-{
- struct inode * cache_inode;
- struct inode * old_inode;
- int rc = -ENOENT;
-
- ENTRY;
-
- cache_inode = clonefs_get_inode(dentry->d_inode);
-
- if (!cache_inode) {
- CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(rc);
- }
-
- /* XXX: shall we allocate a new dentry ?
- The following is safe for ext3, etc. because ext2_readlink only
- use the inode info */
-
- /* save the old dentry inode */
- old_inode = dentry->d_inode;
- /* set dentry inode to cache inode */
- dentry->d_inode = cache_inode;
-
- if (cache_inode->i_op->readlink) {
- rc = cache_inode->i_op->readlink(dentry, buf, len);
- }else {
- CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
- }
-
- /* restore the old inode */
- dentry->d_inode = old_inode;
-
- iput(cache_inode);
-
- RETURN(rc);
-}
-
-static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
-{
- struct inode * cache_inode;
- struct inode * old_inode;
- int rc = -ENOENT;
-
- ENTRY;
-
- cache_inode = clonefs_get_inode(dentry->d_inode);
- if (!cache_inode) {
- CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(rc);
- }
-
- /* XXX: shall we allocate a new dentry ?
- The following is safe for ext2, etc. because ext2_follow_link
- only use the inode info */
-
- /* save the old dentry inode */
- old_inode = dentry->d_inode;
- /* set dentry inode to cache inode */
- dentry->d_inode = cache_inode;
-
- if (cache_inode->i_op->follow_link) {
- rc = cache_inode->i_op->follow_link(dentry, nd);
- }
-
- /* restore the old inode */
- dentry->d_inode = old_inode;
-
- iput(cache_inode);
-
- RETURN(rc);
-}
-static ssize_t
-clonefs_getxattr(struct dentry *dentry, const char *name,
- void *buffer, size_t size)
-{
- struct inode * cache_inode;
- struct inode * old_inode;
- int rc = -ENOENT;
-
- ENTRY;
-
- cache_inode = clonefs_get_inode(dentry->d_inode);
- if (!cache_inode) {
- CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(rc);
- }
-
- /* XXX: shall we allocate a new dentry ?
- The following is safe for ext2, etc. because ext2_follow_link
- only use the inode info */
-
- /* save the old dentry inode */
- old_inode = dentry->d_inode;
- /* set dentry inode to cache inode */
- dentry->d_inode = cache_inode;
-
- if (cache_inode->i_op->getxattr) {
- rc = cache_inode->i_op->getxattr(dentry, name, buffer, size);
- }
-
- /* restore the old inode */
- dentry->d_inode = old_inode;
-
- iput(cache_inode);
-
- RETURN(rc);
-}
-static ssize_t
-clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
- struct inode * cache_inode;
- struct inode * old_inode;
- int rc = -ENOENT;
-
- ENTRY;
-
- cache_inode = clonefs_get_inode(dentry->d_inode);
- if (!cache_inode) {
- CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(rc);
- }
-
- /* XXX: shall we allocate a new dentry ?
- The following is safe for ext2, etc. because ext2_follow_link
- only use the inode info */
-
- /* save the old dentry inode */
- old_inode = dentry->d_inode;
- /* set dentry inode to cache inode */
- dentry->d_inode = cache_inode;
-
- if (cache_inode->i_op->listxattr) {
- rc = cache_inode->i_op->listxattr(dentry, buffer, size);
- }
-
- /* restore the old inode */
- dentry->d_inode = old_inode;
-
- iput(cache_inode);
-
- RETURN(rc);
-
-}
-struct inode_operations clonefs_symlink_inode_ops =
-{
- /*FIXME later getxattr, listxattr,
- * other method need to be replaced too
- * */
- readlink: clonefs_readlink, /* readlink */
- follow_link: clonefs_follow_link, /* follow_link */
- getxattr: clonefs_getxattr, /* get xattr */
- listxattr: clonefs_listxattr, /* list xattr */
-};
-
-
-int clonefs_mounted(struct snap_cache *cache, int index)
-{
- struct snap_clone_info *clone_sb;
- struct list_head *list, *end;
-
- end = list = &cache->cache_clone_list;
-
- list_for_each_entry(clone_sb, list, clone_list_entry) {
- if (clone_sb->clone_index == index)
- return 1;
- }
- return 0;
-}
-
+++ /dev/null
-/*
- * Directory operations for SnapFS filesystem
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-/* called when a cache lookup succeeds */
-
-/* XXX PJB: the intent here is to make sure that inodes which are
- currently primary inodes under .snap directories are dropped when
- they are COWED. It seems hard to me to get semantics that are equally
- good as for mounted snap_clone file systems, but we should try to get
- close
-*/
-static int currentfs_dentry_revalidate(struct dentry *de, int flag)
-{
-// struct inode *inode = de->d_inode;
- ENTRY;
-
- /* unless an ancestor is a .snap directory there is nothing to do */
-#if 0
- if ( !currentfs_is_under_dotsnap(dentry) ) {
- EXIT;
- return 1;
- }
- /* XXX PJB get this to work guys! */
- if ( de->d_parent == "dotsnap inode" &&
- inode_is_newer_than(find_time_by_name(de->d_parent->d_name.name))){
- 1. drop this dentry
- 2. make sure the VFS does a new lookup
- 3. probably all you need to do is
- return 0;
- }
-#else
- RETURN(1);
-#endif
-}
-
-struct dentry_operations currentfs_dentry_ops =
-{
- d_revalidate: currentfs_dentry_revalidate
-};
-
+++ /dev/null
-/*
- * dir.c
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-static ino_t get_parent_ino(struct inode * inode)
-{
- ino_t ino = 0;
- struct dentry * dentry;
-
- if (list_empty(&inode->i_dentry)) {
- CERROR("No dentry for ino %lu\n", inode->i_ino);
- return 0;
- }
-
- dentry = dget(list_entry(inode->i_dentry.next, struct dentry, d_alias));
-
- if(dentry->d_parent->d_inode)
- ino = dentry->d_parent->d_inode->i_ino;
-
- dput(dentry);
- return ino;
-
-}
-
-static void d_unadd_iput(struct dentry *dentry)
-{
- spin_lock(&dcache_lock);
- list_del(&dentry->d_alias);
- INIT_LIST_HEAD(&dentry->d_alias);
- list_del(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_hash);
- spin_unlock(&dcache_lock);
-
- iput(dentry->d_inode);
- dentry->d_inode = NULL;
-}
-
-/* XXX check the return values */
-static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
-{
- struct snap_cache *cache;
- struct dentry *rc;
- struct inode_operations *iops;
- struct inode *cache_inode;
- int index;
-
- ENTRY;
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- RETURN(ERR_PTR(-EINVAL));
- }
-
- if ( dentry->d_name.len == strlen(".snap") &&
- (memcmp(dentry->d_name.name, ".snap", strlen(".snap")) == 0) ) {
- struct inode *snap;
- ino_t ino;
-
- /* Don't permit .snap in clonefs */
- if( dentry->d_sb != cache->cache_sb )
- RETURN(ERR_PTR(-ENOENT));
-
- /* Don't permit .snap under .snap */
- if( currentfs_is_under_dotsnap(dentry) )
- RETURN(ERR_PTR(-ENOENT));
-
- ino = 0xF0000000 | dir->i_ino;
- snap = iget(dir->i_sb, ino);
- CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n",
- snap->i_ino, snap->i_mode);
- d_add(dentry, snap);
- RETURN(NULL);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->lookup) {
- RETURN(ERR_PTR(-EINVAL));
- }
-
- rc = iops->lookup(dir, dentry);
- if (rc || !dentry->d_inode ||
- is_bad_inode(dentry->d_inode) ||
- IS_ERR(dentry->d_inode)) {
- RETURN(NULL);
- }
-
- CDEBUG(D_INODE, "cache inode ino %lu, mode %o\n",
- dentry->d_inode->i_ino, dentry->d_inode->i_mode);
- /*
- * If we are under dotsnap, we need save extra data into
- * dentry->d_fsdata: For dir, we only need _this_ snapshot's index;
- * For others, save primary ino, with it we could found index later
- * anyway
- */
- cache_inode = dentry->d_inode;
- if ( (index = currentfs_is_under_dotsnap(dentry)) ) {
- struct snapshot_operations *snapops;
- struct inode *ind_inode;
- ino_t pri_ino, ind_ino;
-
- pri_ino = cache_inode->i_ino;
- snapops = filter_c2csnapops(cache->cache_filter);
- if( !snapops )
- goto err_out;
-
- ind_ino = snapops->get_indirect_ino(cache_inode, index);
- if( ind_ino <=0 && ind_ino != -ENOATTR )
- goto err_out;
- else if( ind_ino != -ENOATTR ){
- ind_inode = iget(cache_inode->i_sb, ind_ino);
- if( !ind_inode ){
- goto err_out;
- }
- list_del(&dentry->d_alias);
- INIT_LIST_HEAD(&dentry->d_alias);
- list_add(&dentry->d_alias, &ind_inode->i_dentry);
- dentry->d_inode = ind_inode;
- iput(cache_inode);
- }
-
- if( S_ISDIR(dentry->d_inode->i_mode) )
- dentry->d_fsdata = (void*)index;
- else
- dentry->d_fsdata = (void*)pri_ino;
- }
-
- RETURN(NULL);
-
-#if 0
- /* XXX: PJB these need to be set up again. See dcache.c */
- printk("set up dentry ops\n");
- CDEBUG(D_CACHE, "\n");
- filter_setup_dentry_ops(cache->cache_filter,
- dentry->d_op, ¤tfs_dentry_ops);
- dentry->d_op = filter_c2udops(cache->cache_filter);
- CDEBUG(D_CACHE, "\n");
-#endif
-
-err_out:
- d_unadd_iput(dentry);
- RETURN(ERR_PTR(-EINVAL));
-}
-
-static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct snap_cache *cache;
- struct inode_operations *iops;
- void *handle = NULL;
- int rc;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(dir->i_dev);
- if (!cache) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
-
- if (snap_needs_cow(dir) != -1) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
- if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
- CERROR("Do cow error\n");
- RETURN(-EINVAL);
- }
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->create) {
- RETURN(-EINVAL);
- }
- snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 2);
- rc = iops->create(dir, dentry, mode);
-
- /* XXX now set the correct snap_{file,dir,sym}_iops */
- if (!dentry->d_inode) {
- CERROR("Error in currentfs_create, dentry->d_inode is NULL\n");
- GOTO(exit, 0);
- }
- set_filter_ops(cache, dentry->d_inode);
- CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3);
- init_filter_data(dentry->d_inode, 0);
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, dir, SNAP_OP_MKDIR);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->mkdir) {
- rc = -EINVAL;
- goto exit;
- }
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 2);
- rc = iops->mkdir(dir, dentry, mode);
-
- if ( rc )
- goto exit;
-
- /* XXX now set the correct snap_{file,dir,sym}_iops */
- if ( dentry->d_inode) {
- dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
- CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
- } else {
- CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
- }
-
- set_filter_ops(cache, dentry->d_inode);
- init_filter_data(dentry->d_inode, 0);
-
- CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3);
-
-
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_link (struct dentry * old_dentry, struct inode * dir,
- struct dentry *dentry)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry))
- RETURN(-EPERM);
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache )
- RETURN(-EINVAL);
-
- handle = snap_trans_start(cache, dir, SNAP_OP_LINK);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
- if ( snap_needs_cow(old_dentry->d_inode) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
- snap_do_cow(old_dentry->d_inode, dir->i_ino, 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
-
- if (!iops || !iops->link)
- GOTO(exit, rc = -EINVAL);
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
- rc = iops->link(old_dentry,dir, dentry);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 3);
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
- const char * symname)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- cache = snap_find_cache(dir->i_dev);
- if (!cache)
- RETURN(-EINVAL);
-
- handle = snap_trans_start(cache, dir, SNAP_OP_SYMLINK);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->symlink)
- GOTO(exit, rc = -EINVAL);
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2);
- rc = iops->symlink(dir, dentry, symname);
-
- set_filter_ops(cache, dentry->d_inode);
- init_filter_data(dentry->d_inode, 0);
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
- int rdev)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, dir, SNAP_OP_MKNOD);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->mknod)
- GOTO(exit, rc = -EINVAL);
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
- rc = iops->mknod(dir, dentry, mode, rdev);
-
- set_filter_ops(cache, dentry->d_inode);
- init_filter_data(dentry->d_inode, 0);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
-
- /* XXX do we need to set the correct snap_{*}_iops */
-
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- struct inode *inode = NULL;
-// time_t i_ctime = 0;
- nlink_t i_nlink = 0;
- off_t i_size = 0;
- ino_t ino = 0;
- int keep_inode = 0;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, dir, SNAP_OP_RMDIR);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->rmdir)
- GOTO(exit, rc = -EINVAL);
-
- /* XXX : there are two cases that we can't remove this inode from disk.
- 1. the inode needs to be cowed.
- 2. the inode is a redirector.
- then we must keep this inode(dir) so that the inode
- will not be deleted after rmdir, will only remove dentry
- */
-
- if (snap_needs_cow(dentry->d_inode) != -1 ||
- snap_is_redirector(dentry->d_inode)) {
- snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2);
- snap_do_cow (dentry->d_inode, get_parent_ino(dentry->d_inode),
- SNAP_CREATE_IND_DEL_PRI);
- keep_inode = 1;
- }
-
- if( keep_inode && dentry->d_inode ) {
- ino = dentry->d_inode->i_ino;
- // i_ctime = dentry->d_inode->i_ctime;
- i_nlink = dentry->d_inode->i_nlink;
- i_size = dentry->d_inode->i_size;
- }
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 4);
- rc = iops->rmdir(dir, dentry);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5);
-
- if( keep_inode && ino) {
- inode = iget (dir->i_sb, ino);
- if( inode) {
-// inode->i_ctime = i_ctime;
- inode->i_nlink = i_nlink;
- inode->i_size = i_size;
- mark_inode_dirty(inode);
- iput( inode);
- /*
- * In Ext3, rmdir() will put this inode into
- * orphan list, we must remove it out. It's ugly!!
- */
- if( cache->cache_type == FILTER_FS_EXT3 )
- ext3_orphan_del(handle, inode);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
- }
- }
-exit:
- snap_trans_commit(cache, handle);
- EXIT;
- return rc;
-}
-
-static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, dir, SNAP_OP_UNLINK);
-
- if ( snap_needs_cow(dir) != -1 ) {
- CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 1);
- snap_do_cow(dir, get_parent_ino(dir), 0);
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->unlink) {
- rc = -EINVAL;
- goto exit;
- }
-
- /* XXX : if nlink for this inode is 1, there are two cases that we
- can't remove this inode from disk.
- 1. the inode needs to be cowed.
- 2. the inode is a redirector.
- then we increament dentry->d_inode->i_nlink so that the inode
- will not be deleted after unlink, will only remove dentry
- */
-
- if( snap_needs_cow (inode) != -1) {
- /* call snap_do_cow with DEL_WITHOUT_IND option */
- snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 2);
- snap_do_cow(inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
- if( inode->i_nlink == 1 )
- inode->i_nlink++;
- } else if (snap_is_redirector (inode) && inode->i_nlink == 1) {
- /* call snap_do_cow with DEL_WITH_IND option
- * just free the blocks of inode, not really delete it
- */
- snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 3);
- snap_do_cow (inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
- inode->i_nlink++;
- }
-
- snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 4);
- rc = iops->unlink(dir, dentry);
- snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 5);
-
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
- struct inode * new_dir, struct dentry *new_dentry)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- void *handle = NULL;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(old_dentry) ||
- currentfs_is_under_dotsnap(new_dentry)) {
- RETURN(-EPERM);
- }
-
- cache = snap_find_cache(old_dir->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- handle = snap_trans_start(cache, old_dir, SNAP_OP_RENAME);
-
- /* Always cow the old dir and old dentry->d_inode */
- if ( snap_needs_cow(old_dir) != -1 ) {
- CDEBUG(D_INODE, "rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
- snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 1);
- snap_do_cow(old_dir, get_parent_ino(old_dir), 0);
- }
- if( snap_needs_cow (old_dentry->d_inode) != -1) {
- CDEBUG(D_INODE, "rename: needs_cow for old_dentry, ino %lu\n",
- old_dentry->d_inode->i_ino);
- snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 2);
- snap_do_cow(old_dentry->d_inode, old_dir->i_ino,0);
- }
-
- /* If it's not in the same dir, whether the new_dentry is NULL or not,
- * we should cow the new_dir. Because rename will use the ino of
- * old_dentry as the ino of the new_dentry in new_dir.
- */
- if(( old_dir != new_dir) ) {
- if( snap_needs_cow(new_dir) !=-1 ){
- CDEBUG(D_INODE, "rename:snap_needs_cow for new_dir %lu\n",
- new_dir->i_ino);
- snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,3);
- snap_do_cow(new_dir, get_parent_ino(new_dir), 0);
- }
- }
-
-#if 0
- if( ( old_dir != new_dir) && ( new_dentry->d_inode )) {
- if(snap_needs_cow(new_dentry->d_inode) !=-1 ){
- printk("rename:needs_cow for new_entry ,ino %lu\n",
- new_dentry->d_inode->i_ino);
- snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 4);
- snap_do_cow (new_dentry->d_inode,
- new_dentry->d_parent->d_inode->i_ino, 0);
- }
- }
-#endif
- /* The inode for the new_dentry will be freed for normal rename option.
- * But we should keep this inode since we need to keep it available
- * for the clone and for snap rollback
- */
- if( new_dentry->d_inode && new_dentry->d_inode->i_nlink == 1 ) {
- if( snap_needs_cow (new_dentry->d_inode) != -1) {
- /* call snap_do_cow with DEL_WITHOUT_IND option */
- snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
- snap_do_cow(new_dentry->d_inode, new_dir->i_ino,
- SNAP_CREATE_IND_DEL_PRI);
- new_dentry->d_inode->i_nlink++;
- }
- else if( snap_is_redirector (new_dentry->d_inode) ) {
- /* call snap_do_cow with DEL_WITH_IND option
- * just free the blocks of inode, not really delete it
- */
- snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
- snap_do_cow (new_dentry->d_inode, new_dir->i_ino,
- SNAP_CREATE_IND_DEL_PRI);
- new_dentry->d_inode->i_nlink++;
- }
- }
-
- iops = filter_c2cdiops(cache->cache_filter);
- if (!iops || !iops->rename) {
- rc = -EINVAL;
- goto exit;
- }
-
- snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 5);
- rc = iops->rename(old_dir, old_dentry, new_dir, new_dentry);
- snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 6);
-
-exit:
- snap_trans_commit(cache, handle);
- RETURN(rc);
-}
-
-static int currentfs_readdir(struct file *filp, void *dirent,
- filldir_t filldir)
-{
- struct snap_cache *cache;
- struct file_operations *fops;
- int rc;
-
- ENTRY;
- if( !filp || !filp->f_dentry || !filp->f_dentry->d_inode ) {
- RETURN(-EINVAL);
- }
-
- cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
- fops = filter_c2cdfops( cache->cache_filter );
- if( !fops ) {
- RETURN(-EINVAL);
- }
-
- /*
- * no action if we are under clonefs or .snap
- */
- if( cache->cache_show_dotsnap &&
- (filp->f_dentry->d_sb == cache->cache_sb) &&
- !currentfs_is_under_dotsnap(filp->f_dentry) ){
- if( filp->f_pos == 0 ){
- if( filldir(dirent, ".snap",
- strlen(".snap")+1, filp->f_pos,
- -1, 0) ){
- return -EINVAL;
- }
- filp->f_pos += strlen(".snap")+1;
- }
- filp->f_pos -= strlen(".snap")+1;
- rc = fops->readdir(filp, dirent, filldir);
- filp->f_pos += strlen(".snap")+1;
- }else
- rc = fops->readdir(filp, dirent, filldir);
-
- RETURN(rc);
-}
-
-struct file_operations currentfs_dir_fops = {
- readdir: currentfs_readdir
-};
-
-struct inode_operations currentfs_dir_iops = {
- create: currentfs_create,
- mkdir: currentfs_mkdir,
- link: currentfs_link,
- symlink: currentfs_symlink,
- mknod: currentfs_mknod,
- rmdir: currentfs_rmdir,
- unlink: currentfs_unlink,
- rename: currentfs_rename,
- lookup: currentfs_lookup,
- removexattr: currentfs_removexattr,
- setattr: currentfs_setattr,
- setxattr: currentfs_setxattr,
-};
+++ /dev/null
-/*
- * dotsnap.c - support for .snap directories
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-struct inode_operations dotsnap_inode_operations;
-struct file_operations dotsnap_file_operations;
-
-int currentfs_is_under_dotsnap(struct dentry *de)
-{
- int index = 0;
-
- while(de && de->d_parent != de) {
- if ( de->d_inode && de->d_inode->i_ino & 0xF0000000 ) {
- EXIT;
- return index;
- }
- index = (int)de->d_fsdata;
- de = de->d_parent;
- }
-
- RETURN(0);
-}
-
-void currentfs_dotsnap_read_inode(struct snap_cache *cache,
- struct inode *inode)
-{
- int tableno = cache->cache_snap_tableno;
- struct snap_table *table;
- ENTRY;
-
- table = &snap_tables[tableno];
-
- inode->i_mode = S_IFDIR | 0755 ;
- inode->i_op = &dotsnap_inode_operations;
- inode->i_size = table->tbl_count - 1;
- /* all except current form a subdirectory and . and .. */
- inode->i_nlink = table->tbl_count -1 + 2;
- inode->i_uid = 0;
- inode->i_gid = 0;
- EXIT;
-}
-
-struct dentry *dotsnap_lookup(struct inode *dir, struct dentry *dentry)
-{
- struct snap_table *table;
- struct snap_cache *cache;
- int i;
- int index;
- int tableno;
- ino_t ino;
- struct inode *inode;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(dir->i_dev);
- if ( !cache ) {
- CERROR("dotsnap_readdir: cannot find cache\n");
- make_bad_inode(dir);
- RETURN(ERR_PTR(-EINVAL));
- }
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->get_indirect_ino) {
- RETURN(ERR_PTR(-EINVAL));
- }
-
- tableno = cache->cache_snap_tableno;
- table = &snap_tables[tableno];
-
- if( table->tbl_count <= 1 )
- RETURN(NULL);
-
- index = table->snap_items[0].index;;
- for ( i = 1 ; i < table->tbl_count ; i++ ) {
- if ( (dentry->d_name.len == strlen(table->snap_items[i].name)) &&
- (memcmp(&dentry->d_name.name[0], &table->snap_items[i].name[0],
- dentry->d_name.len) == 0) ) {
- index = table->snap_items[i].index;
- break;
- }
- }
-
- if( i >= table->tbl_count )
- RETURN(ERR_PTR(-ENOENT));
-
- inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
-
- if ( !inode )
- RETURN(ERR_PTR(-EINVAL));
-
- ino = snapops->get_indirect_ino(inode, index);
- iput(inode);
-
- if ( ino == -ENOATTR || ino == 0 ) {
- ino = dir->i_ino & (~0xF0000000);
- }
-
- if ( ino == -EINVAL ) {
- RETURN(ERR_PTR(-EINVAL));
- }
- CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
-
- inode = iget(dir->i_sb, ino);
- d_add(dentry, inode);
- dentry->d_fsdata = (void*)index;
- inode->i_op = dentry->d_parent->d_parent->d_inode->i_op;
- RETURN(NULL);
-}
-
-
-static int dotsnap_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- unsigned int i;
- int tableno;
- struct snap_cache *cache;
- struct snap_table *table;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
- if ( !cache ) {
- CDEBUG(D_INODE, "dotsnap_readdir: cannot find cache\n");
- make_bad_inode(filp->f_dentry->d_inode);
- RETURN(-EINVAL);
- }
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->get_indirect_ino) {
- RETURN(-EINVAL);
- }
-
- tableno = cache->cache_snap_tableno;
- table = &snap_tables[tableno];
- for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) {
- int index;
- struct inode *inode;
- ino_t ino;
-
-
- inode = filp->f_dentry->d_inode;
- index = table->snap_items[i+1].index;
- ino = snapops->get_indirect_ino
- (filp->f_dentry->d_inode, index);
-
- if ( ino == -ENOATTR || ino == 0 ) {
- ino = filp->f_dentry->d_parent->d_inode->i_ino;
- }
-
- if ( ino == -EINVAL ) {
- return -EINVAL;
- }
-
- CDEBUG(D_INODE, "Listing %s\n", &table->snap_items[i+1].name[0]);
- if (filldir(dirent, &table->snap_items[i+1].name[0],
- strlen(&table->snap_items[i+1].name[0]),
- filp->f_pos, ino, 0) < 0){
- CDEBUG(D_INODE, "\n");
- break;
- }
- filp->f_pos++;
- }
- RETURN(0);
-}
-
-
-struct file_operations dotsnap_file_operations = {
- readdir: dotsnap_readdir, /* readdir */
-};
-
-struct inode_operations dotsnap_inode_operations =
-{
- lookup: dotsnap_lookup
-};
+++ /dev/null
-/*
- * file.c
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/pagemap.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-static int has_pages(struct inode *inode, int index)
-{
- unsigned long offset = index << PAGE_CACHE_SHIFT;
- unsigned long blk_start = offset >> inode->i_sb->s_blocksize_bits;
- unsigned long blk_end = (offset + PAGE_CACHE_SIZE) >>
- inode->i_sb->s_blocksize_bits;
-
- while (blk_start <= blk_end) {
- if (inode->i_mapping && inode->i_mapping->a_ops) {
- if (inode->i_mapping->a_ops->bmap(inode->i_mapping,
- blk_start))
- return 1;
- }
- blk_start++;
- }
- return 0;
-}
-
-static int copy_back_page(struct inode *dst,
- struct inode *src,
- unsigned long start,
- unsigned long end)
-{
- char *kaddr_src, *kaddr_dst;
- struct snap_cache *cache;
- struct address_space_operations *c_aops;
- struct page *src_page = NULL, *dst_page = NULL;
- unsigned long index, offset, bytes;
- int err = 0;
- ENTRY;
-
- offset = (start & (PAGE_CACHE_SIZE -1)); /* Within page */
- bytes = end - start;
- index = start >> PAGE_CACHE_SHIFT;
-
- if (!has_pages(src, index) || bytes > 4096)
- RETURN(0);
-
- cache = snap_find_cache(src->i_dev);
- if (!cache)
- RETURN(-EINVAL);
- c_aops = filter_c2cfaops(cache->cache_filter);
-
- if (!c_aops)
- RETURN(-EINVAL);
-
- src_page = grab_cache_page(src->i_mapping, index);
- if (!src_page) {
- CERROR("copy block %lu from %lu to %lu ENOMEM \n",
- index, src->i_ino, dst->i_ino);
- RETURN(-ENOMEM);
- }
-
- c_aops->readpage(NULL, src_page);
- wait_on_page(src_page);
-
- kaddr_src = kmap(src_page);
- if (!Page_Uptodate(src_page)) {
- CERROR("Can not read page index %lu of inode %lu\n",
- index, src->i_ino);
- err = -EIO;
- goto unlock_src_page;
- }
- dst_page = grab_cache_page(dst->i_mapping, index);
- if (!dst_page) {
- CERROR("copy block %lu from %lu to %lu ENOMEM \n",
- index, src->i_ino, dst->i_ino);
- err = -ENOMEM;
- goto unlock_src_page;
- }
- kaddr_dst = kmap(dst_page);
-
- err = c_aops->prepare_write(NULL, dst_page, offset, offset + bytes);
- if (err)
- goto unlock_dst_page;
- memcpy(kaddr_dst, kaddr_src, PAGE_CACHE_SIZE);
- flush_dcache_page(dst_page);
-
- err = c_aops->commit_write(NULL, dst_page, offset, offset + bytes);
- CDEBUG(D_SNAP, "copy back pages %p index %lu src %lu dst %lu \n",
- dst_page, dst_page->index, src->i_ino, dst->i_ino);
- if (err)
- goto unlock_dst_page;
- err = 1;
-unlock_dst_page:
- kunmap(dst_page);
- UnlockPage(dst_page);
- page_cache_release(dst_page);
-unlock_src_page:
- kunmap(src_page);
- page_cache_release(src_page);
- RETURN(err);
-}
-
-static ssize_t currentfs_write (struct file *filp, const char *buf,
- size_t count, loff_t *ppos)
-{
- struct snap_cache *cache;
- struct inode *inode = filp->f_dentry->d_inode;
- struct file_operations *fops;
- long start[2]={-1,-1}, end[2]={-1,-1};
- struct snap_table *table;
- struct inode *cache_inode = NULL;
- int slot = 0, index = 0, result = 0;
- long i;
- ssize_t rc;
- loff_t pos;
-
- ENTRY;
-
- if (currentfs_is_under_dotsnap(filp->f_dentry))
- RETURN(-ENOSPC);
-
- cache = snap_find_cache(inode->i_dev);
- if ( !cache )
- RETURN(-EINVAL);
-
- down(&inode->i_sem);
-
- if ( snap_needs_cow(inode) != -1 ) {
- CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
- snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0);
- }
-
- fops = filter_c2cffops(cache->cache_filter);
- if (!fops || !fops->write) {
- up(&inode->i_sem);
- RETURN(-EINVAL);
- }
- if (filp->f_flags & O_APPEND)
- pos = inode->i_size;
- else {
- pos = *ppos;
- if (pos != *ppos){
- up(&inode->i_sem);
- RETURN(-EINVAL);
- }
- }
-
- CDEBUG(D_SNAP, "write offset %lld count %u \n", pos, count);
-
- if (pos & (PAGE_CACHE_SIZE - 1)) {
- start[0] = pos & PAGE_CACHE_MASK;
- end[0] = pos;
- }
- pos += count - 1;
- if ((pos+1) & (PAGE_CACHE_SIZE - 1)) {
- start[1] = pos;
- end[1] = PAGE_CACHE_ALIGN(pos);
- }
-
- if (((start[0] >> PAGE_CACHE_SHIFT) == (start[1] >> PAGE_CACHE_SHIFT)) ||
- pos > inode->i_size)
- start[1] = -1;
-
- CDEBUG(D_SNAP, "copy back start[0] %ld end[0] %ld start[1] %ld end[1] %ld \n",
- start[0], end[0], start[1], end[1]);
- for (i = 0; i < 2; i++) {
- if (start[i] == -1)
- continue;
- table = &snap_tables[cache->cache_snap_tableno];
- /*Find the nearest page in snaptable and copy back it*/
- for (slot = table->tbl_count - 1; slot >= 1; slot--) {
- cache_inode = NULL;
- index = table->snap_items[slot].index;
- cache_inode = snap_get_indirect(inode, NULL, index);
-
- if (!cache_inode) continue;
-
- CDEBUG(D_SNAP, "find cache_ino %lu\n", cache_inode->i_ino);
-
- result = copy_back_page(inode, cache_inode, start[i], end[i]);
- if (result == 1) {
- CDEBUG(D_SNAP, "copy page%lu back from ind %lu to %lu\n",
- (start[i] >> PAGE_CACHE_SHIFT),
- cache_inode->i_ino,
- inode->i_ino);
- iput(cache_inode);
- result = 0;
- break;
- }
- if (result < 0) {
- iput(cache_inode);
- rc = result;
- up(&inode->i_sem);
- goto exit;
- }
- iput(cache_inode);
- }
- }
-
- up(&inode->i_sem);
- rc = fops->write(filp, buf, count, ppos);
-exit:
- RETURN(rc);
-}
-
-static int currentfs_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = file->f_dentry->d_inode;
- unsigned long ind_ino = inode->i_ino;
- struct inode *pri_inode = NULL;
- struct inode *cache_inode = NULL;
- struct address_space_operations *c_aops;
- struct snap_cache *cache;
- struct snap_table *table;
- struct page *cache_page = NULL;
- int rc = 0, slot = 0, index = 0, search_older = 0;
- long block;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- c_aops = filter_c2cfaops(cache->cache_filter);
-
- block = (page->index << PAGE_CACHE_SHIFT) >> inode->i_sb->s_blocksize_bits;
-
- /* if there is a block in the cache, return the cache readpage */
- if(c_aops->bmap(inode->i_mapping, block) ) {
- CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n",
- block, inode->i_ino);
- rc = c_aops->readpage(file, page);
- RETURN(rc);
- }
-
- /*
- * clonefs_readpage will fill this with primary ino number
- * we need it to follow the cloned chain of primary inode
- */
- if( file->f_dentry->d_fsdata ){
- pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata);
- if( !pri_inode )
- RETURN(-EINVAL);
- inode = pri_inode;
- search_older = 1;
- }
-
- table = &snap_tables[cache->cache_snap_tableno];
-
- for (slot = table->tbl_count - 1; slot >= 1; slot--) {
- index = table->snap_items[slot].index;
- cache_inode = snap_get_indirect(inode, NULL, index);
-
- if (!cache_inode ) continue;
-
- /* we only want slots between cache_inode to the oldest one */
- if(search_older && cache_inode->i_ino == ind_ino )
- search_older = 0;
-
- if (!search_older && c_aops->bmap(cache_inode->i_mapping, block))
- break;
- iput(cache_inode);
- cache_inode = NULL;
- }
- if (pri_inode) iput(pri_inode);
-
- if (!cache_inode) {
- CDEBUG(D_SNAP, "block %lu is a hole of inode %lu \n",
- block, inode->i_ino);
- memset(kmap(page), 0, PAGE_CACHE_SIZE);
- flush_dcache_page(page);
- GOTO(exit, rc = 0);
- }
- CDEBUG(D_INODE, "readpage ino %lu icount %d \n", cache_inode->i_ino,
- atomic_read(&cache_inode->i_count));
- down(&cache_inode->i_sem);
-
- /*Here we have changed a file to read,
- *So we should rewrite generic file read here
- *FIXME later, the code is ugly
- */
-
- cache_page = grab_cache_page(cache_inode->i_mapping, page->index);
- if (!cache_page)
- GOTO(exit_release, rc = -ENOMEM);
- if ((rc = c_aops->readpage(file, cache_page)))
- GOTO(exit_release, 0);
-
- wait_on_page(cache_page);
-
- if (!Page_Uptodate(cache_page))
- GOTO(exit_release, rc = -EIO);
-
- memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
- flush_dcache_page(page);
-
- kunmap(cache_page);
- page_cache_release(cache_page);
-
- up(&cache_inode->i_sem);
- iput(cache_inode);
-exit:
- kunmap(page);
- SetPageUptodate(page);
- UnlockPage(page);
-
- RETURN(rc);
-
-exit_release:
- if (cache_page)
- page_cache_release(cache_page);
- up(&cache_inode->i_sem);
- iput(cache_inode);
- UnlockPage(page);
- RETURN(rc);
-}
-
-struct address_space_operations currentfs_file_aops = {
- readpage: currentfs_readpage,
-};
-
-struct file_operations currentfs_file_fops = {
- write: currentfs_write,
-};
-
-struct inode_operations currentfs_file_iops = {
- setattr: currentfs_setattr,
- setxattr: currentfs_setxattr,
- removexattr: currentfs_removexattr,
-};
-
+++ /dev/null
-/*
- * filter.c
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-/*
- * The function in this file are responsible for setting up the
- * correct methods layered file systems like InterMezzo and SnapFS
- */
-
-
-static struct filter_fs filter_oppar[FILTER_FS_TYPES];
-
-/* get to the upper methods (intermezzo, snapfs) */
-inline struct super_operations *filter_c2usops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_sops;
-}
-
-inline struct inode_operations *filter_c2udiops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_dir_iops;
-}
-
-inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_file_iops;
-}
-
-inline struct inode_operations *filter_c2usiops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_sym_iops;
-}
-
-inline struct file_operations *filter_c2udfops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_dir_fops;
-}
-
-inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_file_fops;
-}
-
-inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_file_aops;
-}
-
-inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_sym_fops;
-}
-
-inline struct dentry_operations *filter_c2udops(struct filter_fs *cache)
-{
- return &cache->o_fops.filter_dentry_ops;
-}
-
-/* get to the cache (lower) methods */
-inline struct super_operations *filter_c2csops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_sops;
-}
-
-inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_dir_iops;
-}
-
-inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_file_iops;
-}
-
-inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_file_aops;
-}
-
-inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_sym_iops;
-}
-
-inline struct file_operations *filter_c2cdfops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_dir_fops;
-}
-
-inline struct file_operations *filter_c2cffops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_file_fops;
-}
-
-inline struct file_operations *filter_c2csfops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_sym_fops;
-}
-
-inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache)
-{
- return cache->o_caops.cache_dentry_ops;
-}
-/* snapfs: for snapshot operations */
-inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache)
-{
- return cache->o_snapops;
-}
-
-/* find the cache for this FS */
-struct filter_fs *filter_get_filter_fs(const char *cache_type)
-{
- struct filter_fs *ops = NULL;
- ENTRY;
-
- if ((strlen(cache_type) == strlen("ext3") &&
- memcmp(cache_type, "ext3", strlen("ext3")) == 0)) {
- ops = &filter_oppar[FILTER_FS_EXT3];
- CDEBUG(D_SUPER, "ops at %p\n", ops);
- } else if ( strlen(cache_type) == strlen("reiser") &&
- memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) {
- ops = &filter_oppar[FILTER_FS_REISER];
- CDEBUG(D_SUPER, "ops at %p\n", ops);
- } else {
- CERROR("prepare to die: unrecognized cache type for Filter\n");
- }
- EXIT;
- return ops;
-}
-
-/*
- * Frobnicate the InterMezzo/SnapFS operations
- * this establishes the link between the InterMezzo/SnapFS file system
- * and the underlying file system used for the cache.
- */
-
-void filter_setup_super_ops(struct filter_fs *cache,
- struct super_operations *cache_sops,
- struct super_operations *filter_sops)
-{
- /* Get ptr to the shared struct snapfs_ops structure. */
- struct filter_ops *uops = &cache->o_fops;
- /* Get ptr to the shared struct cache_ops structure. */
- struct cache_ops *caops = &cache->o_caops;
-
- ENTRY;
-
- if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_SUPER_OPS;
-
- /* Set the cache superblock operations to point to the
- superblock operations of the underlying file system. */
- caops->cache_sops = cache_sops;
- /*
- * Copy the cache (real fs) superblock ops to the "filter"
- * superblock ops as defaults. Some will be changed below
- */
- memcpy(&uops->filter_sops, cache_sops, sizeof(*cache_sops));
-
- /* now overwrite with filtering ops */
- if (cache_sops->put_super && uops->filter_sops.put_super) {
- uops->filter_sops.put_super = filter_sops->put_super;
- }
- if (cache_sops->read_inode && uops->filter_sops.read_inode) {
- uops->filter_sops.read_inode = filter_sops->read_inode;
- CDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
- cache, cache, uops->filter_sops.read_inode);
- }
- uops->filter_sops.clear_inode = filter_sops->clear_inode;
-
- EXIT;
-}
-
-void filter_setup_dir_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops)
-{
- struct inode_operations *u_iops;
- struct file_operations *u_fops;
-
- ENTRY;
-
- if (cache->o_flags & FILTER_DID_DIR_OPS) {
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_DIR_OPS;
-
- /* steal the old ops */
- cache->o_caops.cache_dir_iops = inode->i_op;
- cache->o_caops.cache_dir_fops = inode->i_fop;
-
- u_iops = filter_c2udiops(cache);
- u_fops = filter_c2udfops(cache);
-
- /* setup our dir iops and fops: copy and modify */
- memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
- memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
-
- /* methods that filter if cache filesystem has these ops */
- if (filter_iops) {
- struct inode_operations *cache_iops = inode->i_op;
-
- if (cache_iops->lookup && filter_iops->lookup)
- u_iops->lookup = filter_iops->lookup;
- if (cache_iops->create && filter_iops->create)
- u_iops->create = filter_iops->create;
- if (cache_iops->link && filter_iops->link)
- u_iops->link = filter_iops->link;
- if (cache_iops->unlink && filter_iops->unlink)
- u_iops->unlink = filter_iops->unlink;
- if (cache_iops->mkdir && filter_iops->mkdir)
- u_iops->mkdir = filter_iops->mkdir;
- if (cache_iops->rmdir && filter_iops->rmdir)
- u_iops->rmdir = filter_iops->rmdir;
- if (cache_iops->symlink && filter_iops->symlink)
- u_iops->symlink = filter_iops->symlink;
- if (cache_iops->rename && filter_iops->rename)
- u_iops->rename = filter_iops->rename;
- if (cache_iops->mknod && filter_iops->mknod)
- u_iops->mknod = filter_iops->mknod;
- if (cache_iops->permission && filter_iops->permission)
- u_iops->permission = filter_iops->permission;
- if (cache_iops->setattr && filter_iops->setattr)
- u_iops->setattr = filter_iops->setattr;
- if (cache_iops->setxattr && filter_iops->setxattr)
- u_iops->setxattr = filter_iops->setxattr;
- if (cache_iops->removexattr && filter_iops->removexattr)
- u_iops->removexattr = filter_iops->removexattr;
-
- }
- /* copy dir fops */
-
- if (filter_fops) {
- struct file_operations *cache_fops = inode->i_fop;
-
- if(cache_fops->readdir && filter_fops->readdir)
- u_fops->readdir = filter_fops->readdir;
- }
- EXIT;
-}
-
-void filter_setup_file_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops,
- struct address_space_operations *filter_aops)
-{
- struct inode_operations *u_iops;
- struct file_operations *u_fops;
- struct address_space_operations *u_aops;
- ENTRY;
-
- if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) {
- EXIT;
- return;
- }
-
- cache->o_flags |= FILTER_DID_FILE_OPS;
-
- /* steal the old ops */
- cache->o_caops.cache_file_iops = inode->i_op;
- cache->o_caops.cache_file_fops = inode->i_fop;
-
- /* abbreviate */
- u_iops = filter_c2ufiops(cache);
- u_fops = filter_c2uffops(cache);
- u_aops = filter_c2ufaops(cache);
-
- /* setup our dir iops: copy and modify */
- memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
- memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
-
- if (inode->i_mapping && inode->i_mapping->a_ops) {
- cache->o_caops.cache_file_aops = inode->i_mapping->a_ops;
- memcpy(u_aops, inode->i_mapping->a_ops,
- sizeof(struct address_space_operations));
- }
- if (filter_iops) {
- if (filter_iops->revalidate)
- u_iops->revalidate = filter_iops->revalidate;
- if (filter_iops->removexattr)
- u_iops->removexattr = filter_iops->removexattr;
- if (filter_iops->setxattr)
- u_iops->setxattr = filter_iops->setxattr;
- if (filter_iops->setattr)
- u_iops->setattr = filter_iops->setattr;
- }
- if (filter_fops) {
- if (filter_fops->read)
- u_fops->read = filter_fops->read;
- if (filter_fops->write)
- u_fops->write = filter_fops->write;
- }
- if (filter_aops) {
- if (filter_aops->readpage)
- u_aops->readpage = filter_aops->readpage;
- }
- EXIT;
-}
-
-void filter_setup_symlink_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops)
-{
- struct inode_operations *u_iops;
- struct file_operations *u_fops;
-
- ENTRY;
-
- if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) {
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_SYMLINK_OPS;
-
- /* steal the old ops */
- cache->o_caops.cache_sym_iops = inode->i_op;
- cache->o_caops.cache_sym_fops = inode->i_fop;
-
- /* abbreviate */
- u_iops = filter_c2usiops(cache);
- u_fops = filter_c2usfops(cache);
-
- /* setup our dir iops: copy and modify */
- memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
- memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
- if (filter_iops) {
- struct inode_operations *cache_iops = inode->i_op;
- if (cache_iops->readlink && filter_iops->readlink)
- u_iops->readlink = filter_iops->readlink;
- if (cache_iops->follow_link && filter_iops->follow_link)
- u_iops->follow_link = filter_iops->follow_link;
- if (cache_iops->getxattr && filter_iops->getxattr)
- u_iops->getxattr = filter_iops->getxattr;
- if (cache_iops->listxattr && filter_iops->listxattr)
- u_iops->listxattr = filter_iops->listxattr;
-
- }
- EXIT;
-}
-
-void filter_setup_dentry_ops(struct filter_fs *cache,
- struct dentry_operations *cache_dop,
- struct dentry_operations *filter_dop)
-{
- if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_DENTRY_OPS;
-
- cache->o_caops.cache_dentry_ops = cache_dop;
- memcpy(&cache->o_fops.filter_dentry_ops,
- filter_dop, sizeof(*filter_dop));
-
- if (cache_dop && cache_dop != filter_dop && cache_dop->d_revalidate){
- CWARN("filter overriding revalidation!\n");
- }
- EXIT;
- return;
-}
-/* snapfs : for snapshot operations */
-void filter_setup_snapshot_ops (struct filter_fs *cache,
- struct snapshot_operations *cache_snapops)
-{
- ENTRY;
-
- if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
-
- cache->o_snapops = cache_snapops;
-
- EXIT;
-}
-
-void filter_setup_journal_ops (struct filter_fs *cache,
- struct journal_ops *cache_journal_ops)
-{
- ENTRY;
-
- if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
- EXIT;
- return;
- }
- cache->o_flags |= FILTER_DID_JOURNAL_OPS;
-
- cache->o_trops = cache_journal_ops;
-
- EXIT;
-}
+++ /dev/null
-/*
- * fs/snap/snap.c
- *
- * A snap shot file system.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/string.h>
-#include <linux/snap.h>
-#include "snapfs_internal.h"
-
-
-extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
-
-/* XXX PJB: this is exactly what we need to put things under
- filters - we don't want the ext2 methods hardcoded, we want them
- in the filter (in read_super) and then call those methods.
- See how InterMezzo gets the journal operations .
-*/
-
-extern void currentfs_dotsnap_read_inode(struct snap_cache *, struct inode *);
-
-static kmem_cache_t *filter_info_cache = NULL;
-
-void cleanup_filter_info_cache()
-{
- kmem_cache_destroy(filter_info_cache);
-}
-
-int init_filter_info_cache()
-{
- filter_info_cache = kmem_cache_create("snapfs_filter_info",
- sizeof(struct filter_inode_info),
- 0, 0, NULL, NULL);
- if (!filter_info_cache) {
- CERROR("unable to create snap_inode info cache\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-
-void init_filter_data(struct inode *inode,
- int flag)
-{
- struct filter_inode_info *i;
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- if (inode->i_filterdata || inode->i_ino & 0xF0000000)
- return;
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CERROR("currentfs_read_inode: cannot find cache\n");
- make_bad_inode(inode);
- return;
- }
- snapops = filter_c2csnapops(cache->cache_filter);
-
- if (inode->i_filterdata) return;
-
- inode->i_filterdata = (struct filter_inode_info *) \
- kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
- i = inode->i_filterdata;
- i -> generation = snapops->get_generation(inode);
- i -> flags = flag;
-}
-
-void set_filter_ops(struct snap_cache *cache, struct inode *inode)
-{
- /* XXX now set the correct snap_{file,dir,sym}_iops */
- if (S_ISDIR(inode->i_mode)) {
- inode->i_op = filter_c2udiops(cache->cache_filter);
- inode->i_fop = filter_c2udfops(cache->cache_filter);
- } else if (S_ISREG(inode->i_mode)) {
- if ( !filter_c2cfiops(cache->cache_filter) ) {
- filter_setup_file_ops(cache->cache_filter, inode,
- ¤tfs_file_iops,
- ¤tfs_file_fops,
- ¤tfs_file_aops);
- }
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- inode->i_fop = filter_c2uffops(cache->cache_filter);
- inode->i_op = filter_c2ufiops(cache->cache_filter);
- if (inode->i_mapping)
- inode->i_mapping->a_ops = filter_c2ufaops(cache->cache_filter);
-
- }
- else if (S_ISLNK(inode->i_mode)) {
- if ( !filter_c2csiops(cache->cache_filter) ) {
- filter_setup_symlink_ops(cache->cache_filter, inode,
- ¤tfs_sym_iops, ¤tfs_sym_fops);
- }
- inode->i_op = filter_c2usiops(cache->cache_filter);
- inode->i_fop = filter_c2usfops(cache->cache_filter);
- CDEBUG(D_INODE, "inode %lu, i_op at %p\n",
- inode->i_ino, inode->i_op);
- }
-}
-int currentfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
-{
- struct snap_cache *cache;
- struct inode *inode = dentry->d_inode;
- struct inode_operations *iops;
- int rc;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CERROR("currentfs_setxattr: cannot find cache\n");
- RETURN(-EINVAL);
- }
-
- iops = filter_c2cfiops(cache->cache_filter);
-
- if (!iops || !iops->setxattr) {
- RETURN(-EINVAL);
- }
- if ( snap_needs_cow(inode) != -1 ) {
- CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
- snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
- }
-
- rc = iops->setxattr(dentry, name, value, size, flags);
-
- RETURN(rc);
-}
-int currentfs_removexattr(struct dentry *dentry, const char *name)
-{
- struct snap_cache *cache;
- struct inode *inode = dentry->d_inode;
- struct inode_operations *iops;
- int rc;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CERROR("currentfs_setxattr: cannot find cache\n");
- RETURN(-EINVAL);
- }
-
- iops = filter_c2cfiops(cache->cache_filter);
-
- if (!iops || !iops->removexattr) {
- RETURN(-EINVAL);
- }
-
- if (snap_needs_cow(inode) != -1) {
- CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
- snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
- }
- rc = iops->removexattr(dentry, name);
-
- RETURN(rc);
-}
-
-int currentfs_setattr(struct dentry *dentry, struct iattr *attr)
-{
- struct snap_cache *cache;
- struct inode *inode = dentry->d_inode;
- struct inode_operations *iops;
- int rc;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CERROR("currentfs_setxattr: cannot find cache\n");
- RETURN(-EINVAL);
- }
-
- iops = filter_c2cfiops(cache->cache_filter);
-
- if (!iops || !iops->setattr) {
- RETURN(-EINVAL);
- }
- if ( snap_needs_cow(inode) != -1 ) {
- CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
- snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
- }
-
- rc = iops->setattr(dentry, attr);
-
- RETURN(rc);
-}
-/* Superblock operations. */
-static void currentfs_read_inode(struct inode *inode)
-{
- struct snap_cache *cache;
- ENTRY;
-
- if( !inode )
- return;
- CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CERROR("currentfs_read_inode: cannot find cache\n");
- make_bad_inode(inode);
- return;
- }
-
- if (inode->i_ino & 0xF0000000) {
- currentfs_dotsnap_read_inode(cache, inode);
- return;
- }
-
- if(filter_c2csops(cache->cache_filter))
- filter_c2csops(cache->cache_filter)->read_inode(inode);
-
- CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
- inode->i_ino, atomic_read(&inode->i_count));
- set_filter_ops(cache, inode);
- /*init filter_data struct
- * FIXME flag should be set future*/
- init_filter_data(inode, 0);
- CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
- inode->i_ino, atomic_read(&inode->i_count));
- return;
-}
-
-static void currentfs_put_super(struct super_block *sb)
-{
-
- struct snap_cache *cache;
- ENTRY;
-
- CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
- (ulong) sb, (ulong) sb->u.generic_sbp);
- cache = snap_find_cache(sb->s_dev);
-
- if (!cache)
- GOTO(exit, 0);
-
- /* handle COMPAT_FEATUREs */
-#ifdef CONFIG_SNAPFS_EXT2
- else if( cache->cache_type == FILTER_FS_EXT2 ){
- if( !EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_SNAPFS) ){
- sb->u.ext2_sb.s_feature_compat &=
- ~EXT2_FEATURE_COMPAT_BLOCKCOW;
- sb->u.ext2_sb.s_es->s_feature_compat &=
- cpu_to_le32(~EXT2_FEATURE_COMPAT_BLOCKCOW);
- }
- }
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
- else if( cache->cache_type == FILTER_FS_EXT3 ){
- if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
- sb->u.ext3_sb.s_es->s_feature_compat &=
- cpu_to_le32(~EXT3_FEATURE_COMPAT_BLOCKCOW);
- }
- }
-#endif
- /*
- * If there is a saved 'put_super' function for the underlying
- * fs then call it.
- */
- if (cache->cache_filter->o_caops.cache_sops->put_super) {
- cache->cache_filter->o_caops.cache_sops->put_super(sb);
- }
-
- if (!list_empty(&cache->cache_clone_list)) {
- CWARN("snap_put_super: clones exist!\n");
- }
-
- list_del(&cache->cache_chain);
- snap_free_cache(cache);
-
- CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
- (ulong) sb, (ulong) sb->u.generic_sbp);
-exit:
- EXIT;
- return;
-}
-static void currentfs_clear_inode(struct inode *inode)
-{
- struct snap_cache *cache;
- struct super_operations *sops;
- ENTRY;
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- CDEBUG(D_INODE, "inode has invalid dev\n");
- return;
- }
-
- if (inode->i_filterdata) {
- kmem_cache_free(filter_info_cache, inode->i_filterdata);
- inode->i_filterdata = NULL;
- }
-
- sops = filter_c2csops(cache->cache_filter);
- if (sops && sops->clear_inode)
- sops->clear_inode(inode);
-}
-
-struct super_operations currentfs_super_ops = {
- read_inode: currentfs_read_inode,
- put_super: currentfs_put_super,
- clear_inode: currentfs_clear_inode,
-};
-
-
-
-
-
+++ /dev/null
-
-/*
- * Snapfs. (C) 2000 Peter J. Braam
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/jbd.h>
-#include <linux/ext3_jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-#define EXT3_EA_TRANS_BLOCKS EXT3_DATA_TRANS_BLOCKS
-
-/*
- * must follow the changes of ext3_create_indirect() in fs/ext3/snap.c
- */
-#define COW_CREDITS (2 * EXT3_EA_TRANS_BLOCKS + 17 + 2 * EXT3_DATA_TRANS_BLOCKS )
-
-/* start the filesystem journal operations */
-static void *snap_e3_trans_start(struct inode *inode, int op)
-{
- int jblocks;
-
- /* XXX needs to be fixed up when we get reiserfs support */
- switch (op) {
- case SNAP_OP_CREATE:
- jblocks = COW_CREDITS + EXT3_DATA_TRANS_BLOCKS + 3;
- break;
- case SNAP_OP_LINK:
- jblocks = COW_CREDITS + EXT3_DATA_TRANS_BLOCKS;
- break;
- case SNAP_OP_UNLINK:
- jblocks = COW_CREDITS + EXT3_DELETE_TRANS_BLOCKS;
- break;
- case SNAP_OP_SYMLINK:
- jblocks = COW_CREDITS + EXT3_DATA_TRANS_BLOCKS + 5;
- break;
- case SNAP_OP_MKDIR:
- jblocks = COW_CREDITS + EXT3_DATA_TRANS_BLOCKS + 4;
- break;
- case SNAP_OP_RMDIR:
- jblocks = 2 * COW_CREDITS + EXT3_DELETE_TRANS_BLOCKS;
- break;
- case SNAP_OP_MKNOD:
- jblocks = COW_CREDITS + EXT3_DATA_TRANS_BLOCKS + 3;
- break;
- case SNAP_OP_RENAME:
- jblocks = 4 * COW_CREDITS + 2 * EXT3_DATA_TRANS_BLOCKS + 2;
- break;
- default:
- CDEBUG(D_INODE, "invalid operation %d for journal\n", op);
- return NULL;
- }
-
- CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks);
- return ext3_journal_start(inode, jblocks);
-}
-
-static void snap_e3_trans_commit(void *handle)
-{
- journal_stop(handle);
-}
-
-struct journal_ops snap_ext3_journal_ops = {
- snap_e3_trans_start,
- snap_e3_trans_commit
-};
-
+++ /dev/null
-/*
- * snapfs/options.c
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-#include <linux/errno.h>
-#include "snapfs_internal.h"
-
-
-static struct list_head option_list;
-char *options = NULL;
-char *opt_left = NULL;
-
-int init_option(char *data)
-{
- INIT_LIST_HEAD(&option_list);
- SNAP_ALLOC(options, strlen(data) + 1);
- if (!options) {
- CERROR("Can not allocate memory \n");
- return -ENOMEM;
- }
- memcpy(options, data, strlen(data));
- opt_left = options;
- return 0;
-}
-/*cleanup options*/
-void cleanup_option()
-{
- struct option *option;
- while (!list_empty(&option_list)) {
- option = list_entry(option_list.next, struct option, list);
- list_del(&option->list);
- SNAP_FREE(option->opt, strlen(option->opt) + 1);
- SNAP_FREE(option->value, strlen(option->value) + 1);
- SNAP_FREE(option, sizeof(struct option));
- }
- SNAP_FREE(options, strlen(options) + 1);
-}
-int get_opt(struct option **option, char **pos)
-{
- char *name, *value, *left;
- struct option *tmp_opt;
- int length;
-
- *pos = opt_left;
-
- if (! *opt_left)
- return -ENODATA;
-
- left = strchr(opt_left, '=');
-
- if (left == opt_left || !left)
- return -EINVAL;
-
- SNAP_ALLOC(tmp_opt, sizeof(struct option));
-
- length = left - opt_left + 1;
- SNAP_ALLOC(name, length);
- tmp_opt->opt = name;
- memset(name, 0, length);
- while (opt_left != left) *name++ = *opt_left++;
-
- opt_left ++; /*after '='*/
-
- left = strchr(opt_left, ',');
- if (left == opt_left) {
- SNAP_FREE(tmp_opt->opt, length);
- SNAP_FREE(tmp_opt, sizeof(struct option));
- opt_left = *pos;
- return -EINVAL;
- }
- if (!left)
- left = opt_left + strlen(opt_left);
- length = left - opt_left + 1;
- SNAP_ALLOC(value, length);
- tmp_opt->value = value;
- memset(value, 0, length);
- while (opt_left != left) *value++ = *opt_left++;
-
- list_add(&tmp_opt->list, &option_list);
-
- if (*opt_left == ',') opt_left ++; /*after ','*/
-
- *option = tmp_opt;
- return 0;
-}
+++ /dev/null
-/*
- * A file system filter driver in the style of InterMezzo
- * to manage file system snapshots
- *
- * Author: Peter J. Braam <braam@mountainviewdata.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define EXPORT_SYMTAB
-
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/unistd.h>
-#include <linux/miscdevice.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-int snap_inodes = 0;
-long snap_kmemory = 0;
-int snap_stack = 0;
-struct snap_control_device snap_dev;
-
-extern int snap_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg);
-
-/* called when opening /dev/device */
-static int snap_psdev_open(struct inode * inode, struct file * file)
-{
- int dev;
- ENTRY;
-
- if (!inode)
- RETURN(-EINVAL);
- dev = MINOR(inode->i_rdev);
- if (dev != SNAP_PSDEV_MINOR)
- RETURN(-ENODEV);
-
- RETURN(0);
-}
-
-/* called when closing /dev/device */
-static int snap_psdev_release(struct inode * inode, struct file * file)
-{
- int dev;
- ENTRY;
-
- if (!inode)
- RETURN(-EINVAL);
- dev = MINOR(inode->i_rdev);
- if (dev != SNAP_PSDEV_MINOR)
- RETURN(-ENODEV);
-
- RETURN(0);
-}
-
-/* XXX need ioctls here to do snap_delete and snap_restore, snap_backup */
-
-
-/* declare character device */
-static struct file_operations snapcontrol_fops = {
- ioctl: snap_ioctl, /* ioctl */
- open: snap_psdev_open, /* open */
- release: snap_psdev_release, /* release */
-};
-
-
-
-#define SNAPFS_MINOR 240
-
-static struct miscdevice snapcontrol_dev = {
- minor: SNAPFS_MINOR,
- name: "snapcontrol",
- fops: &snapcontrol_fops
-};
-
-int init_snap_psdev(void)
-{
- printk(KERN_INFO "SNAP psdev driver v0.01, braam@clusterfs.com\n");
-
- misc_register( &snapcontrol_dev );
-
- return 0;
-}
-
-void snap_cleanup_psdev(void)
-{
- ENTRY;
- misc_deregister(&snapcontrol_dev);
- EXIT;
-}
-
-MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
-MODULE_DESCRIPTION("Snapfs file system filters v0.01");
-
-extern int init_snapfs(void);
-extern int cleanup_snapfs(void);
-extern int init_clonefs(void);
-extern int init_snap_sysctl(void);
-
-static int __init snapfs_init(void)
-{
- int err;
- if ( (err = init_snap_psdev()) ) {
- printk("Error initializing snap_psdev, %d\n", err);
- return -EINVAL;
- }
-
- if ( (err = init_snapfs()) ) {
- printk("Error initializing snapfs, %d\n", err);
- return -EINVAL;
- }
-
- if ( (err = init_snapfs_proc_sys()) ) {
- printk("Error initializing snapfs proc sys, %d\n", err);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void __exit snapfs_cleanup(void)
-{
-
- cleanup_snapfs();
- snap_cleanup_psdev();
-
-}
-module_init(snapfs_init);
-module_exit(snapfs_cleanup);
-
-
+++ /dev/null
-
-/*
- * fs/snap/snap.c
- *
- * A snap shot file system.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/snap.h>
-#include "snapfs_internal.h"
-
-/*
- * Return true if the inode is a redirector inode.
- */
-int snap_is_redirector(struct inode *cache_inode)
-{
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- cache = snap_find_cache(cache_inode->i_dev);
- if (!cache) {
- return 0;
- }
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->is_redirector) {
- return 0;
- }
-
- CDEBUG(D_SNAP, "ino %ld\n", cache_inode->i_ino);
- return snapops->is_redirector(cache_inode);
-}
-
-/*
- * Using a cache inode and clone super block find the real one.
- */
-struct inode *snap_redirect(struct inode *cache_inode,
- struct super_block *clone_sb)
-{
- struct snap_clone_info *clone_info;
- struct snap_table *table;
- struct inode *redirected;
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
- int slot = 0;
- int my_table[SNAP_MAX];
- int clone_slot;
-
- ENTRY;
-
- cache = snap_find_cache(cache_inode->i_dev);
- if (!cache) {
- RETURN(NULL);
- }
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->get_indirect) {
- RETURN(NULL);
- }
-
- CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino);
- clone_info = (struct snap_clone_info *)&clone_sb->u.generic_sbp;
-
- table = &snap_tables[clone_info->clone_cache->cache_snap_tableno];
-
- /* first find if there are indirected at the clone_index */
- redirected = snapops->get_indirect(cache_inode, NULL,
- clone_info->clone_index);
- /* if not found, get the FIRST index after this and before NOW */
- /* XXX fix this later, now use tbl_count, not NOW */
- if (!redirected) {
- int index;
-
- memset(my_table, 0, sizeof(my_table));
- clone_slot = snap_index2slot(table, clone_info->clone_index);
- for (slot = table->tbl_count-1; slot >= clone_slot; slot --) {
- my_table[slot - clone_slot + 1] = table->snap_items[slot].index;
- }
- index = table->tbl_count - clone_slot;
- redirected = snapops->get_indirect(cache_inode, my_table, index);
- }
-
- if (redirected)
- CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
-
- return redirected;
-}
-
-/*
- * Make a copy of the data and plug a redirector in between if there
- * is no redirector yet.
- */
-int snap_do_cow(struct inode *inode, ino_t parent_ino, int del)
-{
- struct snap_cache *cache;
- struct snap snap;
- struct inode *ind = NULL;
- struct snapshot_operations *snapops;
-
- ENTRY;
- CDEBUG(D_SNAP, "snap_do_cow, ino %ld\n", inode->i_ino);
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- RETURN(-EINVAL);
- }
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->create_indirect) {
- RETURN(-EINVAL);
- }
-
- snap_last(cache, &snap);
- ind = snapops->create_indirect(inode, snap.index, snap.gen, parent_ino, del);
- if(!ind)
- RETURN(-EINVAL);
- init_filter_data(ind, 0);
- set_filter_ops(cache, ind);
- iput(ind);
- RETURN(0);
-}
-
-int snap_iterate(struct super_block *sb,
- int (*repeat)(struct inode *inode, void *priv),
- struct inode **start, void *priv, int flag)
-{
- struct inode *inode = sb->s_root->d_inode;
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if (!cache) {
- RETURN(0);
- }
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->iterate) {
- RETURN(0);
- }
-
- return snapops->iterate(sb, repeat, start, priv, flag);
-}
-
-int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind )
-{
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- ENTRY;
- cache = snap_find_cache(pri->i_dev);
- if (!cache)
- RETURN(0);
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->destroy_indirect)
- RETURN(0);
-
- return snapops->destroy_indirect(pri, index, next_ind);
-}
-
-int snap_restore_indirect(struct inode *pri, int index )
-{
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(pri->i_dev);
- if (!cache)
- RETURN(0);
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->restore_indirect)
- RETURN(0);
-
- return snapops->restore_indirect(pri, index);
-}
-
-struct inode *snap_get_indirect(struct inode *pri, int *table, int slot)
-{
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(pri->i_dev);
- if (!cache)
- RETURN(NULL);
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->get_indirect)
- RETURN(NULL);
-
- return snapops->get_indirect(pri, table, slot);
-}
-
-int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino)
-{
- struct snap_cache *cache;
- struct snapshot_operations *snapops;
-
- ENTRY;
-
- cache = snap_find_cache(pri->i_dev);
- if (!cache)
- RETURN(-EINVAL);
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->set_indirect)
- RETURN(-EINVAL);
-
- EXIT;
- return snapops->set_indirect(pri, ind_ino, index, parent_ino);
-}
-
-
+++ /dev/null
-#ifndef __LINUX_SNAPFS_H
-#define __LINUX_SNAPFS_H
-/* maximum number of snapshot tables we maintain in the kernel */
-#define SNAP_MAX 32
-#define SNAP_MAX_TABLES 32
-#define SNAP_MAX_NAMELEN 64
-
-/* ioctls for manipulating snapshots 40 - 60 */
-#define IOC_SNAP_TYPE 'f'
-#define IOC_SNAP_MIN_NR 41
-
-#define IOC_SNAP_SETTABLE _IOWR('f', 41, long)
-#define IOC_SNAP_PRINTTABLE _IOWR('f', 42, long)
-#define IOC_SNAP_GETINDEXFROMNAME _IOWR('f', 43, long)
-#define IOC_SNAP_GET_NEXT_INO _IOWR('f', 44, long)
-#define IOC_SNAP_GET_INO_INFO _IOWR('f', 45, long)
-
-#define IOC_SNAP_ADD _IOWR('f', 46, long)
-#define IOC_SNAP_DELETE _IOWR('f', 47, long)
-#define IOC_SNAP_RESTORE _IOWR('f', 48, long)
-#define IOC_SNAP_DEBUG _IOWR('f', 49, long)
-#define IOC_SNAP_DEVFAIL _IOWR('f', 50, long)
-#define IOC_SNAP_SHOW_DOTSNAP _IOWR('f', 51, long)
-
-#define IOC_SNAP_MAX_NR 51
-
-struct snap {
- time_t time;
- unsigned int index;
- unsigned int gen;
- unsigned int flags;
- char name[SNAP_MAX_NAMELEN];
-};
-
-
-/*FIXME, use ioc_data temporary, will use obd_ioc_data later*/
-struct ioc_data {
- unsigned int ioc_inlen;
- char *ioc_inbuf;
- char ioc_bulk[0];
-};
-
-/* snap ioctl data for table fiddling */
-struct ioc_snap_tbl_data {
- int no; /* which table */
- unsigned long dev;
- unsigned int count; /* how many snaps */
- struct snap snaps[0]; /* sorted times! */
-};
-struct option {
- char *opt;
- char *value;
- struct list_head list;
-};
-/* we have just a single snapshot control device
- it contains a list of all the snap_current info's
-*/
-#define SNAPDEV_NAME "/dev/snapconf"
-#define SNAP_PSDEV_MINOR 240
-#define SNAP_PSDEV_MAJOR 10
-
-#define SNAP_TABLE_OUTBUF_LEN 1020
-
-#ifdef __KERNEL__
-
-#if 0
-#include <linux/lustre_lib.h>
-#else
-#include "snapfs_support.h"
-#endif
-/* What we use to point to IDs in the obdmd data for snapshots. If we use
- * obd_id (8 bytes) instead of ino_t (4 bytes), we halve the number of
- * available snapshot slots (14 in 56 bytes vs. 7 in 56 bytes until we
- * increase the size of OBD_OBDMDSZ).
- */
-typedef ino_t snap_id;
-
-
-/* maximum number of snapshots per device
- must fit in "o_obdmd" area of struct obdo */
-//#define OBD_OBDMDSZ 54
-//#define SNAP_MAX ((OBD_OBDMDSZ - sizeof(uint32_t))/sizeof(snap_id))
-
-
-
-/* if time is 0 this designates the "current" snapshot, i.e.
- the head of the tree
-*/
-
-/* sysctl.c */
-extern int init_snapfs_proc_sys(void);
-extern void cleanup_spapfs_proc_sys(void);
-extern int snap_print_entry;
-extern int snap_debug_level;
-extern int snap_inodes;
-extern long snap_kmemory;
-extern int snap_stack;
-
-/* snap cache information: this morally equals the superblock of a
- snap_current_fs. However, that superblock is the one of the "cache"
- device holding the inodes, hence we store this info in the hash of
- mountpoints hanging of our control device.
-*/
-struct snap_cache {
- struct list_head cache_chain;
-
- kdev_t cache_dev;
- struct super_block *cache_sb; /* the _real_ device */
-
- struct list_head cache_clone_list;
- int cache_snap_tableno;
-
- struct filter_fs *cache_filter;
-
- char cache_type;
- char cache_show_dotsnap;
-};
-
-/* this is the snap_clone_info for the sb of snap_clone_fs */
-struct snap_clone_info {
- struct snap_cache *clone_cache;
- struct list_head clone_list_entry;
- int clone_index;
-};
-
-/*
- * it is important that things like inode, super and file operations
- * for intermezzo are not defined statically. If methods are NULL
- * the VFS takes special action based on that. Given that different
- * cache types have NULL ops at different slots, we must install opeation
- * talbes for InterMezzo with NULL's in the same spot
- */
-
-struct filter_ops {
- /* operations on the file store */
- struct super_operations filter_sops;
-
- struct inode_operations filter_dir_iops;
- struct inode_operations filter_file_iops;
- struct inode_operations filter_sym_iops;
-
- struct file_operations filter_dir_fops;
- struct file_operations filter_file_fops;
- struct file_operations filter_sym_fops;
-
- struct address_space_operations filter_file_aops;
- struct dentry_operations filter_dentry_ops;
-};
-
-
-struct cache_ops {
- /* operations on the file store */
- struct super_operations *cache_sops;
-
- struct inode_operations *cache_dir_iops;
- struct inode_operations *cache_file_iops;
- struct inode_operations *cache_sym_iops;
-
- struct file_operations *cache_dir_fops;
- struct file_operations *cache_file_fops;
- struct file_operations *cache_sym_fops;
-
- struct address_space_operations *cache_file_aops;
- struct dentry_operations *cache_dentry_ops;
-};
-
-
-#define SNAP_OP_NOOP 0
-#define SNAP_OP_CREATE 1
-#define SNAP_OP_MKDIR 2
-#define SNAP_OP_UNLINK 3
-#define SNAP_OP_RMDIR 4
-#define SNAP_OP_CLOSE 5
-#define SNAP_OP_SYMLINK 6
-#define SNAP_OP_RENAME 7
-#define SNAP_OP_SETATTR 8
-#define SNAP_OP_LINK 9
-#define SNAP_OP_OPEN 10
-#define SNAP_OP_MKNOD 11
-#define SNAP_OP_WRITE 12
-#define SNAP_OP_RELEASE 13
-
-struct journal_ops {
- void *(*trans_start)(struct inode *, int op);
- void (*trans_commit)(void *handle);
-};
-
-struct snap_control_device {
- struct list_head snap_dev_list;
-};
-
-#define D_MAXLEN 1024
-
-#define SNAPSHOT_UNUSED_FLAG (1 << 0)
-#define SNAPSHOT_GOOD_FLAG (1 << 1)
-#define SNAPSHOT_DELETING_FLAG (1 << 2)
-#define SNAPSHOT_BAD_FLAG (1 << 3)
-
-struct snap_disk {
- __u64 time;
- __u32 gen;
- __u32 index;
- __u32 flags;
- char name[SNAP_MAX_NAMELEN];
-};
-/* snap ioctl data for attach: current always in first slot of this array */
-struct snap_obd_data {
- int snap_dev; /* which device contains the data */
- unsigned int snap_index;/* which snapshot is ours */
- unsigned int snap_table;/* which table do we use */
-};
-#define DISK_SNAPTABLE_ATTR "Snaptable12"
-#define DISK_SNAP_TABLE_MAGIC 0x1976
-struct snap_disk_table {
- unsigned int magic;
- unsigned int count;
- unsigned int generation;
- struct snap_disk snap_items[SNAP_MAX];
-};
-
-/*Snap Table*/
-struct snap_table {
- struct semaphore tbl_sema;
- spinlock_t tbl_lock;
- unsigned int tbl_count; /* how many snapshots exist in this table*/
- unsigned int generation;
- struct snap snap_items[SNAP_MAX];
-};
-
-struct snap_iterdata {
- kdev_t dev; /* snap current device number */
- int index;
- int tableno;
- time_t time;
-};
-
-struct snap_ioc_data {
- kdev_t dev;
- char name[SNAP_MAX_NAMELEN];
-};
-
-struct snap_ino_list_data{
- kdev_t dev;
- ino_t ino;
-};
-struct filter_inode_info {
- int flags; /* the flags indicated inode type */
- int generation; /*the inode generation*/
-};
-/* dotsnap.c */
-extern int currentfs_is_under_dotsnap(struct dentry *de);
-
-/* cache.c */
-inline void snap_free_cache(struct snap_cache *cache);
-struct snap_cache *snap_find_cache(kdev_t dev);
-typedef int (*snap_cache_cb_t)(struct snap_cache*, void *in, unsigned long *out);
-int snap_cache_process(snap_cache_cb_t cb, void* in, unsigned long* out);
-
-/* snaptable.c */
-extern struct snap_table snap_tables[SNAP_MAX_TABLES];
-void snap_last(struct snap_cache *info, struct snap *snap);
-int snap_index2slot(struct snap_table *snap_table, int snap_index);
-int snap_needs_cow(struct inode *);
-int snapfs_read_snaptable(struct snap_cache *cache, int tableno);
-/* snap.c */
-int snap_is_redirector(struct inode *inode);
-struct inode *snap_redirect(struct inode *inode, struct super_block *clone_sb);
-int snap_do_cow(struct inode *inode, ino_t parent_ino, int del);
-
-int snap_iterate(struct super_block *sb,
- int (*repeat)(struct inode *inode, void *priv),
- struct inode **start, void *priv, int flag);
-
-struct inode *snap_get_indirect(struct inode *pri, int *table, int slot);
-int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind);
-int snap_restore_indirect(struct inode *pri, int index );
-int snap_migrate_data(struct inode *dst, struct inode *src);
-int snap_set_indirect(struct inode *pri, ino_t ind_ino,
- int index, ino_t parent_ino);
-
-/*super.c */
-void put_snap_current_mnt(struct super_block *sb);
-void get_snap_current_mnt(struct super_block *sb);
-/* inode.c */
-extern struct super_operations currentfs_super_ops;
-void cleanup_filter_info_cache(void);
-int init_filter_info_cache(void);
-extern void init_filter_data(struct inode *inode, int flag);
-extern void set_filter_ops(struct snap_cache *cache, struct inode *inode);
-extern int currentfs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags);
-extern int currentfs_removexattr(struct dentry *dentry, const char *name);
-extern int currentfs_setattr(struct dentry *dentry, struct iattr *attr);
-/* dir.c */
-extern struct inode_operations currentfs_dir_iops;
-extern struct file_operations currentfs_dir_fops;
-extern struct address_space_operations currentfs_file_aops;
-
-/* file.c */
-extern struct inode_operations currentfs_file_iops;
-extern struct file_operations currentfs_file_fops;
-
-/* symlink.c */
-extern struct inode_operations currentfs_sym_iops;
-extern struct file_operations currentfs_sym_fops;
-
-extern struct dentry_operations currentfs_dentry_ops;
-
-/* options.c */
-extern int init_option(char *data);
-extern void cleanup_option(void);
-extern int get_opt(struct option **opt, char **pos);
-/* clonefs.c */
-int clonefs_mounted(struct snap_cache *cache, int index);
-
-#define FILTER_DID_SUPER_OPS 0x1
-#define FILTER_DID_INODE_OPS 0x2
-#define FILTER_DID_FILE_OPS 0x4
-#define FILTER_DID_DENTRY_OPS 0x8
-#define FILTER_DID_DEV_OPS 0x10
-#define FILTER_DID_SYMLINK_OPS 0x20
-#define FILTER_DID_DIR_OPS 0x40
-#define FILTER_DID_SNAPSHOT_OPS 0x80
-#define FILTER_DID_JOURNAL_OPS 0x100
-
-struct filter_fs {
- int o_flags;
- struct filter_ops o_fops;
- struct cache_ops o_caops;
- struct journal_ops *o_trops;
- struct snapshot_operations *o_snapops;
-};
-
-#define FILTER_FS_TYPES 3
-#define FILTER_FS_EXT2 0
-#define FILTER_FS_EXT3 1
-#define FILTER_FS_REISER 2
-extern struct filter_fs filter_oppar[FILTER_FS_TYPES];
-struct filter_fs *filter_get_filter_fs(const char *cache_type);
-inline struct super_operations *filter_c2usops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2udiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2usiops(struct filter_fs *cache);
-inline struct super_operations *filter_c2csops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2csiops(struct filter_fs *cache);
-inline struct file_operations *filter_c2udfops(struct filter_fs *cache);
-inline struct file_operations *filter_c2cffops(struct filter_fs *cache);
-inline struct file_operations *filter_c2cdfops(struct filter_fs *cache);
-inline struct file_operations *filter_c2csfops(struct filter_fs *cache);
-inline struct file_operations *filter_c2uffops(struct filter_fs *cache);
-inline struct file_operations *filter_c2usfops(struct filter_fs *cache);
-inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache);
-inline struct dentry_operations *filter_c2udops(struct filter_fs *cache);
-inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache);
-inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache);
-/* for snapfs */
-inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache);
-
-void filter_setup_file_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops,
- struct address_space_operations *filter_aops);
-
-void filter_setup_dir_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops);
-
-void filter_setup_symlink_ops(struct filter_fs *cache,
- struct inode *inode,
- struct inode_operations *filter_iops,
- struct file_operations *filter_fops);
-
-void filter_setup_dentry_ops(struct filter_fs *cache,
- struct dentry_operations *cache_dop,
- struct dentry_operations *filter_dop);
-void filter_setup_super_ops(struct filter_fs *cache,
- struct super_operations *cache_sops,
- struct super_operations *filter_sops);
-/* for snapfs */
-void filter_setup_snapshot_ops(struct filter_fs *cache,
- struct snapshot_operations *cache_snapops);
-void filter_setup_journal_ops(struct filter_fs *cache,
- struct journal_ops *cache_journal_ops);
-
-static inline void* snap_trans_start(struct snap_cache *cache,
- struct inode *inode, int op)
-{
- if( cache->cache_filter->o_trops )
- return cache->cache_filter->o_trops->trans_start(inode, op);
- return NULL;
-};
-static inline void snap_trans_commit(struct snap_cache *cache, void *handle)
-{
- if( cache->cache_filter->o_trops )
- cache->cache_filter->o_trops->trans_commit(handle);
-};
-
-static inline void snapfs_cpy_attrs(struct inode *dst, struct inode *src)
-{
- dst->i_mtime = src->i_mtime;
- dst->i_ctime = src->i_ctime;
- dst->i_atime = src->i_atime;
- dst->i_size = src->i_size;
- dst->i_blksize = src->i_blksize;
- dst->i_blocks = src->i_blocks;
- dst->i_generation = src->i_generation;
- dst->i_uid = src->i_uid;
- dst->i_gid = src->i_gid;
- dst->i_mode = src->i_mode;
-}
-#if 0
-extern unsigned int snap_debug_failcode;
-#ifdef CONFIG_LOOP_DISCARD
-#define BLKDEV_FAIL(dev,fail) loop_discard_io(dev,fail)
-#else
-#define BLKDEV_FAIL(dev,fail) set_device_ro(dev, 1)
-#endif
-
-static inline void snap_debug_device_fail(dev_t dev, unsigned short opcode, unsigned short pos)
-{
- unsigned int failcode = (opcode<<16) | pos;
-
- if( failcode == snap_debug_failcode && !is_read_only(dev)){
- printk(KERN_EMERG "set block device %s into fail mode\n", bdevname(dev));
- BLKDEV_FAIL(dev, 1);
- }
-}
-#else
-#define snap_debug_device_fail(args...) do{}while(0)
-#endif
-
-extern int snap_debug_level;
-extern int snap_print_entry;
-
-#endif /*_KERNEL_*/
-#endif /* __LINUX_SNAPFS_H */
+++ /dev/null
-/*Got these defination from lustre*/
-#define S_SNAP (1 << 0)
-
-#define D_TRACE (1 << 0) /* ENTRY/EXIT markers */
-#define D_INODE (1 << 1)
-#define D_SUPER (1 << 2)
-#define D_EXT2 (1 << 3) /* anything from ext2_debug */
-#define D_MALLOC (1 << 4) /* print malloc, free information */
-#define D_CACHE (1 << 5) /* cache-related items */
-#define D_INFO (1 << 6) /* general information */
-#define D_IOCTL (1 << 7) /* ioctl related information */
-#define D_BLOCKS (1 << 8) /* ext2 block allocation */
-#define D_NET (1 << 9) /* network communications */
-#define D_WARNING (1 << 10) /* CWARN(...) == CDEBUG (D_WARNING, ...) */
-#define D_BUFFS (1 << 11)
-#define D_OTHER (1 << 12)
-#define D_DENTRY (1 << 13)
-#define D_PAGE (1 << 15) /* bulk page handling */
-#define D_DLMTRACE (1 << 16)
-#define D_ERROR (1 << 17) /* CERROR(...) == CDEBUG (D_ERROR, ...) */
-#define D_EMERG (1 << 18) /* CEMERG(...) == CDEBUG (D_EMERG, ...) */
-#define D_HA (1 << 19) /* recovery and failover */
-#define D_RPCTRACE (1 << 20) /* for distributed debugging */
-#define D_VFSTRACE (1 << 21)
-#define D_SNAP (1 << 22)
-
-#ifdef __KERNEL__
-# include <linux/sched.h> /* THREAD_SIZE */
-#else
-# ifndef THREAD_SIZE /* x86_64 has THREAD_SIZE in userspace */
-# define THREAD_SIZE 8192
-# endif
-#endif
-
-# include <linux/vmalloc.h>
-# define snap_debug_msg(mask, file, fn, line, stack, format, a...) \
- printk("%02x (@%lu %s:%s,l. %d %d %lu): " format, \
- (mask), (long)time(0), file, fn, line, \
- getpid() , stack, ## a);
-
-#define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5)
-
-#ifdef __KERNEL__
-# ifdef __ia64__
-# define CDEBUG_STACK (THREAD_SIZE - \
- ((unsigned long)__builtin_dwarf_cfa() & \
- (THREAD_SIZE - 1)))
-# else
-# define CDEBUG_STACK (THREAD_SIZE - \
- ((unsigned long)__builtin_frame_address(0) & \
- (THREAD_SIZE - 1)))
-# endif
-
-#define CHECK_STACK(stack) \
- do { \
- if ((stack) > 3*THREAD_SIZE/4 && (stack) > snap_stack) { \
- printk( "maximum lustre stack %u\n", \
- snap_stack = (stack)); \
- } \
- } while (0)
-#else /* __KERNEL__ */
-#define CHECK_STACK(stack) do { } while(0)
-#define CDEBUG_STACK (0L)
-#endif /* __KERNEL__ */
-
-#if 1
-#define CDEBUG(mask, format, a...) \
-do { \
- CHECK_STACK(CDEBUG_STACK); \
- if (!(mask) || ((mask) & (D_ERROR | D_EMERG | D_WARNING)) || \
- (snap_debug_level & (mask))) \
- printk(format, ## a); \
-} while (0)
-
-#define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a)
-#define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a)
-#define CEMERG(format, a...) CDEBUG(D_EMERG, format, ## a)
-
-#define GOTO(label, rc) \
-do { \
- long GOTO__ret = (long)(rc); \
- CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \
- #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\
- (signed long)GOTO__ret); \
- goto label; \
-} while (0)
-
-#define RETURN(rc) \
-do { \
- typeof(rc) RETURN__ret = (rc); \
- CDEBUG(D_TRACE, "Process %d leaving %s (rc=%lu : %ld : %lx)\n", \
- current->pid, __FUNCTION__, (long)RETURN__ret, \
- (long)RETURN__ret, (long)RETURN__ret); \
- return RETURN__ret; \
-} while (0)
-
-#define ENTRY \
-do { \
- CDEBUG(D_TRACE, "Process %d enter %s\n", \
- current->pid, __FUNCTION__); \
-} while (0)
-
-#define EXIT \
-do { \
- CDEBUG(D_TRACE, "Process %d leaving %s \n", \
- current->pid, __FUNCTION__); \
-} while(0)
-#else
-#define CDEBUG(mask, format, a...) do { } while (0)
-#define CWARN(format, a...) do { } while (0)
-#define CERROR(format, a...) printk("<3>" format, ## a)
-#define CEMERG(format, a...) printk("<0>" format, ## a)
-#define GOTO(label, rc) do { (void)(rc); goto label; } while (0)
-#define RETURN(rc) return (rc)
-#define ENTRY do { } while (0)
-#define EXIT do { } while (0)
-#endif
-
-#define SNAP_ALLOC(ptr, size) \
-do { \
- if (size <= 4096) { \
- ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
- CDEBUG(D_MALLOC, "Proc %d %s:%d kmalloced: %d at %x.\n",\
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- } else { \
- ptr = vmalloc((unsigned long) size); \
- CDEBUG(D_MALLOC, "Proc %d %s:%d vmalloced: %d at %x.\n",\
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- } \
- if (ptr == 0) { \
- printk("kernel malloc returns 0 at %s:%d\n", \
- __FILE__, __LINE__); \
- } else { \
- memset(ptr, 0, size); \
- snap_kmemory += size; \
- } \
-} while (0)
-
-#define SNAP_FREE(ptr,size) \
-do { \
- snap_kmemory -= size; \
- if (size <= 4096) { \
- CDEBUG(D_MALLOC, "Proc %d %s:%d kfreed: %d at %x.\n", \
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- kfree((ptr)); \
- } else { \
- CDEBUG(D_MALLOC, "Proc %d %s:%d vfreed: %d at %x.\n", \
- current->pid, __FUNCTION__, __LINE__, \
- (int) size, (int) ptr); \
- vfree((ptr)); \
- } \
-} while (0)
-
+++ /dev/null
-
-/*
- * snaptable.c
- *
- * Manipulate snapshot tables
- *
- */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/snap.h>
-#include <linux/time.h>
-#include <asm/uaccess.h>
-#include "snapfs_internal.h"
-
-
-struct snap_table snap_tables[SNAP_MAX_TABLES];
-
-int snap_index2slot(struct snap_table *snap_table, int snap_index)
-{
- int slot;
-
- for ( slot=0 ; slot < snap_table->tbl_count ; slot++ )
- if ( snap_table->snap_items[slot].index == snap_index )
- return slot;
- return -1;
-}
-
-
-
-/* latest snap: returns
- - the index of the latest snapshot before NOW
- - hence it returns 0 in case all the volume snapshots lie in the future
- - this is the index where a COW will land (will be created)
-*/
-
-void snap_last(struct snap_cache *info, struct snap *snap)
-{
- int i ;
- time_t now = CURRENT_TIME;
- struct snap_table *table;
- int tableno = info->cache_snap_tableno;
-
- ENTRY;
- if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
- CERROR("invalid table no %d\n", tableno);
- snap->index = -1;
- }
-
- table = &snap_tables[tableno];
-
- /* start at the highest index in the superblock
- snaptime array */
- i = table->tbl_count - 1;
-
- /* NOTE: i>0 is an unnecessary check */
- snap->index = table->snap_items[i].index;
- snap->time = table->snap_items[i].time;
- snap->gen = table->snap_items[i].gen;
- CDEBUG(D_SNAP, "index: %d, time[i]: %ld, now: %ld\n",
- snap->index, snap->time, now);
- return;
-}
-
-/* return -1 if no COW is needed, otherwise the index of the
- clone to COW to is returned
-*/
-
-int snap_needs_cow(struct inode *inode)
-{
- struct snap snap;
- struct snap_cache *cache;
- struct filter_inode_info *filter_info;
- int index = -1;
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if ( !cache ) {
- RETURN(index);
- }
- filter_info = (struct filter_inode_info *) inode->i_filterdata;
- /* here we find the time of the last snap to compare with */
-
- snap_last(cache, &snap);
- /* decision .... if the snapshot is more recent than the object,
- * then any change to the object should cause a COW.
- */
- if (filter_info && filter_info->generation < snap.gen ) {
- index = snap.index;
- }
-
- CDEBUG(D_SNAP, "snap_needs_cow, ino %lu , get index %d\n",
- inode->i_ino, index);
-
- RETURN(index);
-} /* snap_needs_cow */
-
-int snap_print_table(struct ioc_snap_tbl_data *data, char *buf, int *buflen)
-{
- struct snap_table *table;
- struct ioc_snap_tbl_data *stbl_out;
- int tableno = data->no;
- int i, rc = 0, nleft = (*buflen);
-
- char *buf_ptr;
-
- if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
- CERROR("invalid table number %d\n", tableno);
- RETURN(-EINVAL);
- }
-
- table = &snap_tables[tableno];
- stbl_out = (struct ioc_snap_tbl_data *)buf;
- stbl_out->count = table->tbl_count - 1;
- stbl_out->no = tableno;
- buf_ptr = (char*)stbl_out->snaps;
- nleft -= buf_ptr - buf;
- for (i = 1; i < table->tbl_count; i++) {
- memcpy(buf_ptr, &table->snap_items[i], sizeof(struct snap));
-
- nleft -= sizeof(struct snap);
- if(nleft < 0) {
- CERROR("can not get enough space to print snaptable\n");
- rc = -ERANGE;
- goto exit;
- } else {
- buf_ptr += sizeof(struct snap);
- }
- }
-exit:
- if(nleft > 0)
- (*buflen) = (*buflen) - nleft;
- return 0;
-}
-static int inline get_index_of_item(struct snap_table *table, char *name)
-{
- int count = table->tbl_count;
- int i, j;
-
- for (i = 0; i < SNAP_MAX; i++) {
- if (!strcmp(name, table->snap_items[i].name))
- return -EINVAL;
- }
- for (i = 0; i < SNAP_MAX; i++) {
- int found = 0;
- for (j = 0; j < (count + 1); j++) {
- if (table->snap_items[j].index == i) {
- found = 1;
- break;
- }
- }
- if (!found)
- return i;
- }
- return -EINVAL;
-}
-/* This function will write one item(a snapshot) to snaptable
- * and will also write to disk.
- */
-static int snaptable_add_item(struct ioc_snap_tbl_data *data)
-{
- struct snap_table *table;
- struct snap_disk_table *disk_snap_table;
- struct snapshot_operations *snapops;
- struct snap_cache *cache;
- int tableno , index, i, count, rc;
-
- if (!(cache = snap_find_cache((kdev_t)data->dev)))
- RETURN(-ENODEV);
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->set_meta_attr)
- RETURN(-EINVAL);
-
- tableno = data->no;
- if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
- CERROR("invalid table number %d\n", tableno);
- RETURN(-EINVAL);
- }
- table = &snap_tables[tableno];
- count = table->tbl_count;
-
- /* XXX Is down this sema necessary*/
- down_interruptible(&table->tbl_sema);
-
- /*add item in snap_table set generation*/
- table->snap_items[count].gen = table->generation + 1;
- table->snap_items[count].time = CURRENT_TIME;
- /* find table index */
- index = get_index_of_item(table, data->snaps[0].name);
- if (index < 0) {
- CERROR("snaptable full Or Duplicate name in snaptable\n");
- GOTO(exit, rc = -EINVAL);
- }
-
- table->snap_items[count].index = index;
- table->snap_items[count].flags = 0;
- memcpy(&table->snap_items[count].name[0],
- data->snaps[0].name, SNAP_MAX_NAMELEN);
- /* we will write the whole snap_table to disk */
- SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
- if (!disk_snap_table)
- GOTO(exit, rc = -ENOMEM);
- disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
- disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
- disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
- memset(&disk_snap_table->snap_items[0], 0,
- SNAP_MAX * sizeof(struct snap_disk));
-
- for (i = 1; i <= count; i++) {
- struct snap *item = &table->snap_items[i];
- disk_snap_table->snap_items[i-1].time = cpu_to_le64((__u64)item->time);
- disk_snap_table->snap_items[i-1].gen = cpu_to_le32((__u32)item->gen);
- disk_snap_table->snap_items[i-1].flags = cpu_to_le32((__u32)item->flags);
- disk_snap_table->snap_items[i-1].index = cpu_to_le32((__u32)item->index);
- memcpy(&disk_snap_table->snap_items[i-1].name , item->name, SNAP_MAX_NAMELEN);
- }
- rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
- (char*)disk_snap_table, sizeof(struct snap_disk_table));
-
- SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
- table->tbl_count++;
- table->generation++;
-exit:
- up(&table->tbl_sema);
- RETURN(rc);
-}
-
-static int delete_inode(struct inode *primary, void *param)
-{
- struct snap_iterdata * data;
- int tableno = 0;
- int index = 0;
- int rc = 0;
-
- struct inode *redirect;
- ino_t old_ind = 0;
- struct snap_table *table;
- int slot;
- int delete_slot;
- int this_index;
- struct inode *next_ind = NULL;
- int my_table[SNAP_MAX];
-
- ENTRY;
-
- if(!primary) RETURN(0);
-
- data = (struct snap_iterdata*) param;
-
- if (data) {
- index = data->index;
- tableno = data->tableno;
- }
-
- CDEBUG(D_SNAP, "delete_inode ino %lu, index %d\n", primary->i_ino, index);
-
- table = &snap_tables[tableno];
-
- redirect = snap_get_indirect(primary, NULL, index);
-
- if (!redirect) {
- CDEBUG(D_SNAP, "redirect inode index %d not exist \n", index);
- RETURN(0);
- }
- old_ind = redirect->i_ino;
- iput(redirect);
-
- /* In destroy indirect inode, we lock the primary inode here */
- down(&primary->i_sem);
- slot = snap_index2slot(table, index) - 1;
- if (slot > 0) {
- this_index = table->snap_items[slot].index;
- redirect = snap_get_indirect(primary, NULL, this_index);
- if (redirect) {
- iput(redirect);
- } else {
- snap_set_indirect(primary, old_ind, this_index, 0);
- snap_set_indirect(primary, 0, index, 0);
- up(&primary->i_sem);
- RETURN(0);
- }
- }
-
- delete_slot = snap_index2slot(table, index);
- for (slot = table->tbl_count - 1; slot > delete_slot; slot --) {
- my_table[slot - delete_slot] = table->snap_items[slot].index;
- }
-
- this_index = table->tbl_count - delete_slot - 1;
- next_ind = snap_get_indirect(primary, my_table, this_index);
-
- if (next_ind && (next_ind->i_ino == primary->i_ino)) {
- iput(next_ind);
- next_ind = NULL;
- }
- rc = snap_destroy_indirect(primary, index, next_ind);
-
- up(&primary->i_sem);
-
- if (next_ind) iput(next_ind);
-
- if (rc != 0)
- CERROR("snap_destroy_indirect(ino %lu,index %d),ret %d\n",
- primary->i_ino, index, rc);
- RETURN(0);
-}
-
-static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
-{
- CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
- data->dev, data->tableno, data->index, data->time );
-
- snap_iterate(sb, &delete_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
-
- return 0;
-}
-
-/* This function will delete one item(a snapshot) in the snaptable
- * and will also delete the item in the disk.
- * FIXME later, this should be in a transaction.
- */
-int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
-{
- struct snap_table *table;
- struct snap_disk_table *disk_snap_table;
- struct snapshot_operations *snapops;
- struct snap_cache *cache;
- int tableno = data->tableno;
- int index, i, del_slot, rc;
-
- if (!(cache = snap_find_cache((kdev_t)data->dev)))
- RETURN(-ENODEV);
-
- if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
- CERROR("invalid table number %d\n", tableno);
- RETURN(-EINVAL);
- }
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->set_meta_attr)
- RETURN(-EINVAL);
-
- index = data->index;
- if (clonefs_mounted(cache, index)) {
- CERROR("Please first umount this clonefs \n");
- RETURN(-EBUSY);
- }
- /*first delete the snapshot
- * FIXME if snap delete error, how to handle this error*/
- rc = snap_delete(sb, data);
- if (rc)
- RETURN(-EINVAL);
- /*delete item in snaptable */
- table = &snap_tables[tableno];
-
- del_slot = snap_index2slot(table, index);
- if (del_slot < 0)
- RETURN(-EINVAL);
-
- down_interruptible(&table->tbl_sema);
-
- SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
-
- if (!disk_snap_table) {
- up(&table->tbl_sema);
- RETURN(-ENOMEM);
- }
-
- /* we will delete the item snap_table to disk */
-
- index = del_slot;
- /*Move the items after the delete slot forward one step*/
- memset(&table->snap_items[index], 0, sizeof(struct snap));
- while(index < table->tbl_count - 1) {
- struct snap *item = &table->snap_items[index];
-
- item->time = table->snap_items[index + 1].time;
- item->flags = table->snap_items[index + 1].flags;
- item->gen = table->snap_items[index + 1].gen;
- item->index = table->snap_items[index + 1].index;
- memcpy(&item->name[0], &table->snap_items[index + 1].name[0],
- SNAP_MAX_NAMELEN);
- index ++;
- }
-
- table->tbl_count --;
-
- disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
- disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count - 1);
- disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
- memset(&disk_snap_table->snap_items[0], 0,
- SNAP_MAX * sizeof(struct snap_disk));
-
- for (i = 0; i < table->tbl_count - 1; i++) {
- struct snap_disk *disk_item = &disk_snap_table->snap_items[i];
- struct snap *item = &table->snap_items[i+1];
-
- disk_item[i].time = cpu_to_le64((__u64)item->time);
- disk_item[i].gen = cpu_to_le32((__u32)item->gen);
- disk_item[i].flags = cpu_to_le32((__u32)item->flags);
- disk_item[i].index = cpu_to_le32((__u32)item->index);
- memcpy(&disk_item[i].name , item->name, SNAP_MAX_NAMELEN);
- }
-
- rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
- (char*)disk_snap_table, sizeof(struct snap_disk_table));
-
- SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
-
- up(&table->tbl_sema);
- RETURN(rc);
-}
-
-int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
-{
- struct snap_table *table;
- struct snap_disk_table *disk_snap_table;
- struct snapshot_operations *snapops;
- int i, rc;
- int size = 0;
-
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->get_meta_attr)
- RETURN(-EINVAL);
-
- SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
-
- size = sizeof(struct snap_disk_table);
-
-
- table = &snap_tables[tableno];
-
- memset(table, 0, sizeof(struct snap_table));
- init_MUTEX(&table->tbl_sema);
-
- /*Initialized table */
- table->tbl_count = 1;
- rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
- (char*)disk_snap_table, &size);
- if (rc < 0) {
- SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
- RETURN(rc);
- }
-
- if (le32_to_cpu(disk_snap_table->magic) != DISK_SNAP_TABLE_MAGIC) {
- CERROR("On disk snaptable is not right \n");
- RETURN(rc);
- }
- table->generation = le32_to_cpu(disk_snap_table->generation);
- table->tbl_count += le32_to_cpu(disk_snap_table->count);
- for ( i = 0; i < disk_snap_table->count; i++) {
- struct snap *item = &table->snap_items[i + 1];
- item->time = le64_to_cpu(disk_snap_table->snap_items[i].time);
- item->gen = le32_to_cpu(disk_snap_table->snap_items[i].gen);
- item->flags = le32_to_cpu(disk_snap_table->snap_items[i].flags);
- item->index = le32_to_cpu(disk_snap_table->snap_items[i].index);
- memcpy(&item->name[0], &disk_snap_table->snap_items[i].name[0],
- SNAP_MAX_NAMELEN);
- }
- SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
- return 0;
-}
-
-static int getdata(struct ioc_data *input, void **karg)
-{
- void *tmp = NULL;
-
- if (!input->ioc_inlen || !input->ioc_inbuf)
- return 0;
-
- SNAP_ALLOC(tmp, input->ioc_inlen);
- if (!tmp)
- RETURN(-ENOMEM);
-
- CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", input->ioc_inlen, tmp);
-
- memset(tmp, 0, input->ioc_inlen);
- if (copy_from_user(tmp, input->ioc_inbuf, input->ioc_inlen)) {
- CERROR("get inbuf data error \n");
- SNAP_FREE(tmp, input->ioc_inlen);
- RETURN(-EFAULT);
- }
- *karg = tmp;
-
- return 0;
-}
-
-static inline void freedata(void *data, struct ioc_data *input)
-{
- SNAP_FREE(data, input->ioc_inlen);
- CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", input->ioc_inlen, data);
-}
-
-static int get_next_inode(struct inode *pri, void *ino)
-{
- static ino_t prev_ino = -1 ;
- ino_t this_ino = pri->i_ino;
- ino_t find_ino = *(ino_t *)ino;
- ino_t *found = ino;
-
- if( find_ino == 0) {
- (*found) = this_ino;
- return -1;
- }
-
- if( find_ino == prev_ino ) {
- (*found) = this_ino;
- return -1;
- }
- else {
- prev_ino = this_ino;
- }
- return 0;
-}
-
-
-static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino, ino_t *parent_ino)
-{
- kdev_t dev = data->dev;
- ino_t this_ino = data->ino;
-
- struct snap_cache *cache;
-
- struct inode *inode;
- struct dentry * dentry;
-
- ENTRY;
-
- cache = snap_find_cache(dev);
- if ( !cache ) {
- EXIT;
- return -EINVAL;
- }
-
- snap_iterate( cache->cache_sb, &get_next_inode, NULL, &(data->ino),
- SNAP_ITERATE_COWED_INODE);
-
- if( data->ino == this_ino ) {
- data->ino = 0;
- }
-
- *found_ino = data->ino;
-
- if( !(*found_ino) ) return 0;
-
- *parent_ino = 0;
- inode = iget (cache->cache_sb, *found_ino);
- if (list_empty(&inode->i_dentry)) {
- CERROR("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
- iput(inode);
- return 0;
- }
- else {
- dentry = dget(list_entry(inode->i_dentry.next, struct dentry, d_alias));
- }
- if( dentry->d_parent->d_inode)
- *parent_ino = dentry->d_parent->d_inode->i_ino;
- else
- *parent_ino = 0;
-
- dput(dentry);
- iput(inode);
-
- return 0;
-}
-
-static int print_inode(struct inode *pri,void *param)
-{
- CDEBUG(D_SNAP, "cowed inode list: ino %lu \n", pri->i_ino);
- return 0;
-}
-
-static int snap_print(struct super_block *sb, void *data)
-{
- snap_iterate(sb, &print_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
- return 0;
-}
-
-static int delete_new_inode(struct inode *pri, void *param)
-{
- struct snap_iterdata * data;
-
- int index = 1;
- time_t restore_time = 0xFFFFFFFF;
-
- ENTRY;
-
- if(!pri)
- RETURN(0);
-
- if(snap_is_redirector(pri))
- RETURN(0);
-
- data = (struct snap_iterdata*) param;
-
- if(data) {
- index = data->index;
- restore_time = data->time;
- }
-
- CDEBUG(D_SNAP, "ino %lu, index=%d, time=%lu\n",
- pri->i_ino, index, restore_time);
-
-
- if( pri->i_mtime > restore_time || pri->i_ctime > restore_time ) {
- struct list_head *head = &pri->i_dentry, *pos;
-
- CDEBUG(D_SNAP, "snap_restore ino %lu is newer, delete \n",pri->i_ino);
- for( pos = head->next; pos != head; pos = pos->next ){
- d_drop( list_entry(pos, struct dentry, d_alias) );
- }
- pri->i_nlink = 0;
- }
- RETURN(0);
-}
-
-static int restore_inode(struct inode *pri, void *param)
-{
- struct snap_iterdata * data;
- int tableno = 0;
-
- int index = 1;
- time_t restore_time = 0xFFFFFFFF;
-
- struct inode *ind = NULL;
- int slot;
- int restore_slot;
- struct snap_table *table;
- int restore_index;
-
- ENTRY;
-
- if(!pri) RETURN(0);
-
- data = (struct snap_iterdata*) param;
-
- if(data) {
- index = data->index;
- tableno = data->tableno;
- restore_time = data->time;
- }
-
- CDEBUG(D_SNAP, "ino %lu, index=%d, time=%lu, tableno %d\n",
- pri->i_ino, index, restore_time, tableno);
-
- /* XXX: should we have = here? */
- if(pri->i_mtime > restore_time || pri->i_ctime > restore_time) {
- restore_index = index;
- table = &snap_tables[tableno];
- /* first find if there are indirected at the index */
- ind = snap_get_indirect(pri, NULL, index);
- /* if not found, get the FIRST index after this and before NOW*/
- /* XXX fix this later, now use tbl_count, not NOW */
- if(!ind) {
- restore_slot = snap_index2slot(table, index);
- for(slot = restore_slot; slot <= table->tbl_count;
- slot++) {
- ind = snap_get_indirect (pri, NULL,
- table->snap_items[slot].index);
- if(ind) {
- restore_index = table->snap_items[slot].index;
- break;
- }
- }
- }
-
- if(ind) {
- CDEBUG(D_SNAP, "restore ino %lu with index %d\n",
- pri->i_ino, restore_index);
- iput(ind);
- snap_restore_indirect(pri, restore_index);
- /* XXX */
- //delete_inode(pri, param);
- snap_destroy_indirect(pri, restore_index, NULL);
- }
- else {
- CDEBUG(D_SNAP, "ERROR:restore ino %lu\n", pri->i_ino);
- }
- }
- else {
- CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
- }
- RETURN(0);
-}
-
-//int snap_restore(struct super_block *sb, void *data)
-static int snap_restore(struct super_block *sb, struct snap_iterdata *data)
-{
- CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
- data->dev, data->tableno, data->index, data->time );
-
- snap_iterate(sb, &delete_new_inode, NULL, data, SNAP_ITERATE_ALL_INODE);
- snap_iterate(sb, &restore_inode, NULL, data, SNAP_ITERATE_COWED_INODE );
- return 0;
-}
-
-/* return the index number of a name in a table */
-int snap_get_index_from_name(int tableno, char *name)
-{
- struct snap_table *table;
- int slot;
-
- if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
- CERROR("invalid table number %d\n", tableno);
- return -EINVAL;
- }
-
- table = &snap_tables[tableno];
-
- for ( slot = 0 ; slot < table->tbl_count; slot++) {
- if (!strcmp(&table->snap_items[slot].name[0], name)) {
- return table->snap_items[slot].index;
- }
- }
- return -EINVAL;
-}
-
-int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
-{
- struct snapshot_operations *snapops;
- struct snap_iterdata iterate_data;
- struct super_block *sb;
- struct snap_cache *cache;
- struct snap_table *table;
- int index, tableno, slot, rc;
-
- ENTRY;
-
- if (!(cache = snap_find_cache((kdev_t)data->dev)))
- RETURN(-ENODEV);
-
- snapops = filter_c2csnapops(cache->cache_filter);
- if (!snapops || !snapops->set_meta_attr)
- RETURN(-EINVAL);
-
- tableno = data->no;
- if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
- CERROR("invalid table number %d\n", tableno);
- RETURN(-EINVAL);
- }
-
- sb = cache->cache_sb;
- table = &snap_tables[tableno];
-
- index = snap_get_index_from_name(tableno, data->snaps[0].name);
- if (index < 0) {
- CERROR("Could not find %s in snaptable\n",
- data->snaps[0].name);
- RETURN(-EINVAL);
- }
- iterate_data.dev = (kdev_t)data->dev;
- iterate_data.index = index;
- iterate_data.tableno = tableno;
- slot = snap_index2slot (table, index);
- if( slot < 0 )
- RETURN(-EINVAL);
-
- iterate_data.time = table->snap_items[slot].time;
- CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
- iterate_data.dev, iterate_data.tableno,
- iterate_data.index, iterate_data.time);
-
- switch (cmd) {
- case IOC_SNAP_DEBUG:
- rc = snap_print(sb, &iterate_data);
- break;
- case IOC_SNAP_DELETE:
- rc = snaptable_delete_item(sb, &iterate_data);
- break;
- case IOC_SNAP_RESTORE:
- rc = snap_restore(sb, &iterate_data);
- break;
- default:
- CERROR("unrecognized cmd %d \n", cmd);
- rc = -EINVAL;
- break;
- }
- RETURN(rc);
-}
-
-#define BUF_SIZE 1024
-int snap_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- struct ioc_data input;
- void *karg = NULL;
- int rc = 0;
- kdev_t dev;
-
- ENTRY;
-
- dev = MINOR(inode->i_rdev);
- if (dev != SNAP_PSDEV_MINOR)
- RETURN(-ENODEV);
-
- if (!inode) {
- CDEBUG(D_IOCTL, "invalid inode\n");
- RETURN(-EINVAL);
- }
-
- if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE ||
- _IOC_NR(cmd) < IOC_SNAP_MIN_NR ||
- _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) {
- /*FIXME: Sometimes Gettimeof the day will come here
- * still do not know the reason*/
- CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
- _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
- RETURN(0);
- }
-
- /* get data structures */
- rc = copy_from_user(&input, (void *)arg, sizeof(input));
- if (rc) RETURN(rc);
-
- /* get data from the input data*/
- rc = getdata(&input, &karg);
- if (rc) RETURN(rc);
-
- switch (cmd) {
- case IOC_SNAP_ADD: {
- rc = snaptable_add_item(karg);
- break;
- }
- case IOC_SNAP_PRINTTABLE: {
- struct ioc_data *output;
- char *tmp;
-
- SNAP_ALLOC(tmp, BUF_SIZE);
- output=(struct ioc_data*)tmp;
- output->ioc_inbuf = output->ioc_bulk;
- output->ioc_inlen = BUF_SIZE - sizeof(int) - sizeof(unsigned long);
- snap_print_table(karg, output->ioc_inbuf, &(output->ioc_inlen));
-
- rc = copy_to_user((char *)arg, output,
- (output->ioc_inlen + sizeof(int) + sizeof(unsigned long)));
- SNAP_FREE(tmp, BUF_SIZE);
-
- break;
- }
- case IOC_SNAP_GETINDEXFROMNAME: {
- int index = 0;
- char name[SNAP_MAX_NAMELEN];
- int tableno = 0;
- struct snap_cache *cache;
- kdev_t dev;
- int name_len;
-
- struct get_index_struct {
- kdev_t dev;
- char name[SNAP_MAX_NAMELEN];
- };
-
- struct get_index_struct *data = karg;
-
- name_len = input.ioc_inlen - sizeof(kdev_t);
- dev = data->dev;
- memset(name, 0, SNAP_MAX_NAMELEN);
- if(name_len > SNAP_MAX_NAMELEN)
- name_len = SNAP_MAX_NAMELEN;
- if(name_len < 0 )
- name_len = 0;
- /*for(i=0 ; i< name_len; i++) {
- name[i] = data->name[i];
- }
- */
- memcpy(name, data->name, name_len);
- printk("dev %d , len %d, name_len %d, find name is [%s]\n",
- dev, input.ioc_inlen, name_len, name);
- cache = snap_find_cache(dev);
- if ( !cache ) {
- EXIT;
- rc = -EINVAL;
- break;
- }
- tableno = cache->cache_snap_tableno;
-
- index = snap_get_index_from_name(tableno, name);
- rc = copy_to_user((char *)arg, &index, sizeof(index));
- break;
- }
- case IOC_SNAP_GET_NEXT_INO: {
- struct get_ino_struct{
- ino_t found_ino;
- ino_t parent_ino;
- }get_ino;
- get_ino.found_ino = 0;
- get_ino.parent_ino = 0;
- rc = snap_get_next_inode(karg, &get_ino.found_ino, &get_ino.parent_ino);
- rc = copy_to_user((char *)arg, &get_ino, sizeof(get_ino));
- break;
- }
- case IOC_SNAP_GET_INO_INFO: {
- struct ioc_ino_info{
- kdev_t dev;
- ino_t ino;
- int index;
- };
- struct snap_cache *cache;
- struct inode *pri;
- struct inode *ind;
- struct ioc_ino_info *data = karg;
- ino_t ind_ino = 0;
-
- cache = snap_find_cache(data->dev);
- if ( !cache ) {
- EXIT;
- rc = -EINVAL;
- break;
- }
- printk("get_ino_info, dev %d, ino %lu, index %d\n",
- data->dev, data->ino, data->index);
- pri = iget(cache->cache_sb, data->ino);
- ind = snap_get_indirect(pri, NULL, data->index);
- if(ind) {
- ind_ino = ind->i_ino;
- iput(ind);
- }
- iput(pri);
- printk("get_ino_info, get ind %lu\n", ind_ino);
- rc = copy_to_user((char *)arg, &ind_ino, sizeof(ino_t));
- break;
- }
- case IOC_SNAP_DELETE:
- case IOC_SNAP_RESTORE:
- case IOC_SNAP_DEBUG:
- rc = snap_iterate_func(karg, cmd);
- break;
-#ifdef SNAP_DEBUG
- case IOC_SNAP_DEVFAIL:
- snap_debug_failcode = (unsigned int)arg;
- break;
-#endif
- case IOC_SNAP_SHOW_DOTSNAP: {
- struct ioc_show_info{
- kdev_t dev;
- int show;
- };
- struct snap_cache *cache;
- struct ioc_show_info *data = karg;
-
- cache = snap_find_cache(data->dev);
- if( !cache ) {
- EXIT;
- rc = -EINVAL;
- break;
- }
- cache->cache_show_dotsnap = (char)data->show;
- CDEBUG(D_IOCTL, "Set show dotsnap: %s\n",
- data->show ? "Yes" : "No");
-
- break;
- }
- default:
- rc = -EINVAL;
- break;
- }
-
- freedata(karg, &input);
- RETURN(rc);
-}
+++ /dev/null
-/*
- * snap_current
- *
- * Copyright (C) 1998 Peter J. Braam
- * Copyright (C) 2000 Stelias Computing, Inc.
- * Copyright (C) 2000 Red Hat, Inc.
- * Copyright (C) 2000 Mountain View Data, Inc.
- *
- * Author: Peter J. Braam <braam@mountainviewdata.com>
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/loop.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-#include <linux/errno.h>
-#include "snapfs_internal.h"
-
-
-#ifdef SNAP_DEBUG
-unsigned int snap_debug_failcode = 0;
-#endif
-
-extern struct snap_cache *snap_init_cache(void);
-extern inline void snap_cache_add(struct snap_cache *, kdev_t);
-extern inline void snap_init_cache_hash(void);
-
-extern int snap_get_index_from_name (int tableno, char *name);
-
-
-extern struct snapshot_operations ext3_snap_operations;
-extern struct journal_ops snap_ext3_journal_ops;
-
-static void put_filesystem(struct file_system_type *fs)
-{
- if (fs->owner)
- __MOD_DEC_USE_COUNT(fs->owner);
-}
-
-static struct vfsmount* get_vfsmount(struct super_block *sb)
-{
- struct vfsmount *rootmnt, *mnt, *ret = NULL;
- struct list_head *end, *list;
-
- rootmnt = mntget(current->fs->rootmnt);
- end = list = &rootmnt->mnt_list;
- do {
- mnt = list_entry(list, struct vfsmount, mnt_list);
- if (mnt->mnt_sb == sb) {
- ret = mnt;
- break;
- }
- list = list->next;
- } while (end != list);
- mntput(current->fs->rootmnt);
- return ret;
-}
-
-void get_snap_current_mnt(struct super_block *sb)
-{
- struct vfsmount *mnt;
-
- mnt = get_vfsmount(sb);
- if (mnt)
- mntget(mnt);
-}
-void put_snap_current_mnt(struct super_block *sb)
-{
- struct vfsmount *mnt;
-
- mnt = get_vfsmount(sb);
- if (mnt)
- mntput(mnt);
-}
-
-/* In get_opt we get options in opt, value in opt_value
- * we must remember to free opt and opt_value*/
-static char * snapfs_options(char *options, char **cache_type,
- char **cow_type, char **snaptable)
-{
- struct option *opt_value;
- char *pos;
-
- while (!(get_opt(&opt_value, &pos))) {
- if (!strcmp(opt_value->opt, "cache_type")) {
- if (cache_type != NULL)
- *cache_type = opt_value->value;
- } else if (!strcmp(opt_value->opt, "cow_type")) {
- if (cow_type != NULL)
- *cow_type = opt_value->value;
- } else if (!strcmp(opt_value->opt, "snap_table")) {
- if (snaptable != NULL)
- *snaptable = opt_value->value;
- } else {
- break;
- }
- }
- if (!*cache_type && cache_type)
- *cache_type = "ext3";
- if (!*cow_type && cow_type)
- *cow_type = "block";
- if (!*snaptable && snaptable)
- *snaptable = "0";
- return pos;
-}
-int snapfs_remount(struct super_block * sb, int *flags, char *data)
-{
- struct super_operations *sops;
- struct snap_cache *cache = NULL;
- char *snapno = NULL, *pos = NULL;
- char *cache_data = NULL;
- int err = 0;
-
- ENTRY;
- CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
-
- if ((err = init_option(data))) {
- GOTO(out_err, 0);
- }
- cache = snap_find_cache(sb->s_dev);
- if (!cache) {
- CERROR("cannot find cache on remount\n");
- GOTO(out_err, err = -ENODEV);
- }
-
- /* If an option has not yet been set, we allow it to be set on
- * remount. If an option already has a value, we pass NULL for
- * the option pointer, which means that the snapfs option
- * will be parsed but discarded.
- */
- cache_data = snapfs_options(data, NULL, NULL, &snapno);
-
- CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data, cache_data);
- sops = filter_c2csops(cache->cache_filter);
- if (sops->remount_fs)
- err = sops->remount_fs(sb, flags, pos);
-out_err:
- cleanup_option();
- RETURN(err);
-}
-/*
- * snapfs super block read.
- *
- * Allocate a struct snap_cache, determine the underlying fs type,
- * read the underlying fs superblock, save the underlying fs ops,
- * and then replace them with snapfs ops.
- *
- * Remove the snapfs options before passing to underlying fs.
- */
-struct super_block *
-snapfs_read_super (
- struct super_block *sb,
- void *data,
- int silent)
-{
- struct file_system_type *fstype;
- struct snap_cache *cache = NULL;
- char *cache_type = NULL, *cow_type = NULL;
- char *snapno = NULL, *cache_data = NULL;
- int tableno, rc = 0;
-
- ENTRY;
-
- init_option(data);
- cache_data = snapfs_options(data, &cache_type, &cow_type, &snapno);
- /* set up the cache */
- cache = snap_init_cache();
- if ( !cache ) {
- CERROR("snapfs_read_super: failure allocating cache.\n");
- GOTO(out_err, rc = -EINVAL);
- }
- /*get cache and cache filter type */
- fstype = get_fs_type((const char *)cache_type);
-
- if ( !fstype || !fstype->read_super) {
- CERROR("Unrecognized cache type %s \n", cache_type);
- GOTO(out_err, rc = -EINVAL);
- }
- cache->cache_filter = filter_get_filter_fs((const char *)cache_type);
- if (!cache->cache_filter) {
- CERROR("Unrecognized cache type %s \n", cache_type);
- GOTO(out_err, rc = -EINVAL);
- }
-
- /*
- * Read the underlying file system superblock - ext2, ext3, reiser.
- * This performs the underlying mount operation. The snapfs options
- * have been removed from 'cache_data'.
- *
- * Note: It's assumed that sb is always returned.
- */
- if (fstype->read_super(sb, cache_data, silent) != sb) {
- CERROR("snapfs: cache mount failure.\n");
- GOTO(out_err, rc = -EINVAL);
- }
- /*
- * We now know the dev of the cache: hash the cache.
- *
- * 'cache' is the struct snap_cache allocated for this
- * snapfs mount.
- */
- snap_cache_add(cache, sb->s_dev);
-
- tableno = simple_strtoul(snapno, NULL, 0);
- cache->cache_snap_tableno = tableno;
- CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
-
- /*
- * make sure we have our own super operations
- *
- * Initialize or re-initialize the cache->cache_ops shared
- * struct snap_ops structure set based on the underlying
- * file system type.
- */
- filter_setup_super_ops(cache->cache_filter, sb->s_op,
- ¤tfs_super_ops);
- sb->s_op = filter_c2usops(cache->cache_filter);
- /*
- * Save pointers in the snap_cache structure to the
- * snapfs and underlying file system superblocks.
- */
- cache->cache_sb = sb; /* Underlying file system superblock. */
-
- /* set up snapshot ops, handle COMPAT_FEATUREs */
- if( 0 ){
- }
- else if (strcmp (cache_type,"ext3") == 0 || !cache_type){
- cache->cache_type = FILTER_FS_EXT3;
- filter_setup_snapshot_ops(cache->cache_filter,
- &ext3_snap_operations);
- filter_setup_journal_ops(cache->cache_filter,
- &snap_ext3_journal_ops);
- if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
- if( strcmp(cow_type, "block")==0 ){
- sb->u.ext3_sb.s_es->s_feature_compat |=
- cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
- }
- }
- sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
- sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
- }
- /* now get our own directory operations */
- if ( sb->s_root && sb->s_root->d_inode ) {
- filter_setup_dir_ops(cache->cache_filter,
- sb->s_root->d_inode,
- ¤tfs_dir_iops, ¤tfs_dir_fops);
- sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
-
- CDEBUG(D_SUPER, "lookup at %p\n",
- sb->s_root->d_inode->i_op->lookup);
- /* XXX is this needed ?? ext3 do not have dentry operations*/
- filter_setup_dentry_ops(cache->cache_filter,
- sb->s_root->d_op,
- ¤tfs_dentry_ops);
- sb->s_root->d_op = filter_c2udops(cache->cache_filter);
- init_filter_data(sb->s_root->d_inode, 0);
- }
- /*
- * Save a pointer to the snap_cache structure in the
- * "snap_current" superblock.
- */
- (struct snap_cache *) sb->u.generic_sbp = cache;
-
- snapfs_read_snaptable(cache, tableno);
-
- CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
- (ulong) sb, (ulong) sb->u.generic_sbp);
-out_err:
- cleanup_option();
- /* Inc in get_fs_type, Dec in put_fs_type*/
- if (fstype)
- put_filesystem(fstype);
- if (rc)
- return NULL;
- return sb;
-}
-
-static DECLARE_FSTYPE_DEV(snapfs_current_type,
- "snap_current", snapfs_read_super);
-
-/* Find the options for the clone. These consist of a cache device
- and an index in the snaptable associated with that device.
-*/
-static char *clonefs_options(char *options, char **devstr, char **namestr)
-{
- struct option *opt_value = NULL;
- char *pos;
-
- while (!(get_opt(&opt_value, &pos))) {
- if (!strcmp(opt_value->opt, "dev")) {
- if (devstr != NULL)
- *devstr = opt_value->value;
- } else if (!strcmp(opt_value->opt, "name")) {
- if (namestr != NULL)
- *namestr = opt_value->value;
- } else {
- break;
- }
- }
- return pos;
-}
-static int snap_cache_lookup_ino_cb(struct snap_cache *cache, void *in, unsigned long *out)
-{
- ino_t ino = *((unsigned long*)in);
-
- if (cache) {
- struct super_block *sb = cache->cache_sb;
- kdev_t dev = sb->s_dev;
-
- if (MAJOR(dev) != LOOP_MAJOR)
- return 0;
- if (sb->s_bdev->bd_op && sb->s_bdev->bd_op->ioctl) {
- struct inode *inode = sb->s_bdev->bd_inode;
- struct loop_info loop_info;
-
- sb->s_bdev->bd_op->ioctl(inode, NULL, LOOP_GET_INFO,
- (unsigned long)&loop_info);
-
- if(loop_info.lo_inode == ino) {
- *out = sb->s_dev;
- return 1;
- }
- }
- }
- return 0;
-}
-static int snapfs_path2dev(char *dev_path, kdev_t *dev)
-{
- struct dentry *dentry;
- struct nameidata nd;
- int error = 0;
-
- if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
- error = path_walk(dev_path, &nd);
- if (error)
- return error;
- } else
- return -EINVAL;
-
- dentry = nd.dentry;
-
- if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
- (!S_ISBLK(dentry->d_inode->i_mode) &&
- !S_ISREG(dentry->d_inode->i_mode))){
- path_release(&nd);
- return -ENODEV;
- }
- if (S_ISBLK(dentry->d_inode->i_mode)) {
- *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
- } else {
- /*here we must walk through all the snap cache to
- *find the loop device */
- kdev_t tmp;
-
- if (snap_cache_process(snap_cache_lookup_ino_cb,
- &dentry->d_inode->i_ino,
- (unsigned long*)&tmp))
- return -EINVAL;
- *dev = tmp;
- }
- path_release(&nd);
- return 0;
-}
-
-extern struct super_operations clone_super_ops;
-/*
- * We always need to remove the snapfs options before passing
- * to bottom FS.
- */
-struct super_block *
-clone_read_super(
- struct super_block *sb,
- void *data,
- int silent)
-{
- struct snap_clone_info *clone_sb;
- struct snap_cache *snap_cache = NULL;
- struct inode *root_inode = NULL;
- char *devstr = NULL, *namestr = NULL;
- char *cache_data;
- kdev_t dev;
- int index;
- ino_t root_ino;
- int err = 0;
-
- ENTRY;
-
- CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
-
- init_option(data);
- /* read and validate options */
- cache_data = clonefs_options(data, &devstr, &namestr);
- if (*cache_data) {
- CERROR("clonefs: invalid mount option %s\n", (char*)data);
- GOTO(out_err, err=-EINVAL);
- }
- if (!namestr || !devstr) {
- CERROR("snapfs: mount options name and dev mandatory\n");
- GOTO(out_err, err=-EINVAL);
- }
-
- err = snapfs_path2dev(devstr, &dev);
- if ( err ) {
- CERROR("snap: incorrect device option %s\n", devstr);
- GOTO(out_err, err=-EINVAL);
- }
-
- snap_cache = snap_find_cache(dev);
- if ( !snap_cache ) {
- CERROR("snap: incorrect device option %s\n", devstr);
- GOTO(out_err, err=-EINVAL);
- }
-
- index = snap_get_index_from_name (snap_cache->cache_snap_tableno,
- namestr);
- CDEBUG(D_SUPER, "tableno %d, name %s, get index %d\n",
- snap_cache->cache_snap_tableno, namestr, index);
-
- if(index < 0 ) {
- CERROR("No valid index for name %s passed to mount\n",namestr);
- GOTO(out_err, err=-EINVAL);
- }
-
- /*
- * Force clone fs to be read-only.
- *
- * XXX - Is there a way to change the mount options too so
- * the fs is listed as RO by mount?
- */
- sb->s_flags |= MS_RDONLY;
-
- /* set up the super block */
- clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
- list_add(&clone_sb->clone_list_entry, &snap_cache->cache_clone_list);
- clone_sb->clone_cache = snap_cache;
- clone_sb->clone_index = index;
- sb->s_op = &clone_super_ops;
-
- root_ino = snap_cache->cache_sb->s_root->d_inode->i_ino;
- root_inode = iget(sb, root_ino);
-
- CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
- sb->s_op->read_inode, root_ino, root_inode);
-
- sb->s_root = d_alloc_root(root_inode);
-
- if (!sb->s_root) {
- list_del(&clone_sb->clone_list_entry);
- GOTO(out_err, err=-EINVAL);
- }
- dget(snap_cache->cache_sb->s_root);
-
- CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
- (ulong) sb, (ulong) &sb->u.generic_sbp);
-
- get_snap_current_mnt(snap_cache->cache_sb);
- out_err:
- cleanup_option();
- if (err)
- return NULL;
- return sb;
-}
-
-static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
-
-int init_snapfs(void)
-{
- int status;
-
- snap_init_cache_hash();
- init_filter_info_cache();
-
- status = register_filesystem(&snapfs_current_type);
- if (status) {
- CERROR("snapfs: failed in register current filesystem!\n");
- }
-
- status = register_filesystem(&snapfs_clone_type);
- if (status) {
- unregister_filesystem(&snapfs_current_type);
- CERROR("snapfs: failed in register clone filesystem!\n");
- }
-
- return status;
-}
-
-
-
-int cleanup_snapfs(void)
-{
- int err;
-
- ENTRY;
-
- cleanup_filter_info_cache();
- err = unregister_filesystem(&snapfs_clone_type);
- if ( err ) {
- CERROR("snapfs: failed to unregister clone filesystem\n");
- }
- err = unregister_filesystem(&snapfs_current_type);
- if ( err ) {
- CERROR("snapfs: failed to unregister filesystem\n");
- }
- return 0;
-}
+++ /dev/null
-/*
- * fs/snap/snap.c
- *
- * A snap shot file system.
- *
- */
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-static inline int inode_has_ea(struct inode *inode)
-{
- return (inode->u.ext2_i.i_file_acl != 0);
-}
-
-static int currentfs_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct snap_cache *cache;
- int rc;
- struct inode_operations *iops;
- struct inode * inode = dentry->d_inode;
- int bpib = inode->i_sb->s_blocksize >> 9;
- __u32 save_i_blocks;
-
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if ( !cache ) {
- EXIT;
- return -EINVAL;
- }
-
- iops = filter_c2csiops(cache->cache_filter);
- if (!iops ||
- !iops->readlink) {
- rc = -EINVAL;
- goto exit;
- }
-
- save_i_blocks = inode->i_blocks;
- /* If this link has ea and its i_blocks is ea's block,
- * then we should treate it as a fast symlink
- */
- if( inode_has_ea(inode) && inode->i_blocks == bpib ) {
- inode->i_blocks = 0;
- }
- rc = iops->readlink(dentry, buffer, buflen);
-
- if( inode->i_blocks != save_i_blocks ){
- inode->i_blocks = save_i_blocks;
- mark_inode_dirty(inode);
- }
-
-exit:
- EXIT;
- return rc;
-}
-
-static int cat_str_ahead(char *buf, int pos, const char* str)
-{
- int len = strlen(str);
-
- if( pos - len -1 < 0 )
- return pos;
-
- buf[--pos] = '/';
- memcpy(&buf[pos-len], str, len);
- return pos-len;
-}
-
-/*
- * Adjust the following path if we are under dotsnap (skip .snap/clonexx...)
- * in following two case, we just return null and let caller do
- * the normal follow_link:
- * (1) we are not lies in .snap
- * (2) we are already in the root's .snap
- */
-static int dotsnap_follow_link(struct dentry *dentry,
- struct nameidata *nd)
-{
- struct super_block *sb = dentry->d_inode->i_sb;
- struct dentry *de = dentry, *de_save1=NULL, *de_save2=NULL;
- char *buf = NULL;
- int pos = D_MAXLEN, rc;
-
- SNAP_ALLOC(buf, D_MAXLEN);
- if( !buf )
- RETURN(-ENOMEM);
-
- /*
- * iterate upward to construct the path
- */
- do {
- if( de_save2 )
- pos = cat_str_ahead(buf, pos, de_save2->d_name.name);
-
- if ( de->d_inode && de->d_inode->i_ino & 0xF0000000 )
- goto lookup;
-
- de_save2 = de_save1;
- de_save1 = de;
- de = de->d_parent;
- } while (de->d_parent != de);
-
- /* we are not under dotsnap */
- goto exit;
-
-lookup:
- /* See if we already under root's .snap */
- de = de->d_parent;
- if( de == sb->s_root )
- goto exit;
-
- while( (de->d_parent != de) && (de != sb->s_root) ){
- pos = cat_str_ahead(buf, pos, de->d_name.name);
- de = de->d_parent;
- }
- if( de_save1 )
- pos = cat_str_ahead(buf, pos, de_save1->d_name.name);
-
- pos = cat_str_ahead(buf, pos, ".snap");
- buf[D_MAXLEN-1] = 0;
- CDEBUG(D_SNAP, "constructed path: %s\n", &buf[pos]);
-
- /* FIXME lookup_dentry will never return NULL ?? */
-#if 0
- rc = lookup_dentry(&buf[pos], dget(sb->s_root), follow);
- if( !rc ){
- rc = ERR_PTR(-ENOENT);
- CDEBUG(D_SNAP, "lookup_dentry return NULL~!@#$^&*\n");
- }
-#else
- if (path_init(&buf[pos], LOOKUP_FOLLOW, nd)) {
- rc = path_walk(&buf[pos], nd);
- if (rc)
- GOTO(exit, rc);
- }
-#endif
-exit:
- SNAP_FREE(buf, D_MAXLEN);
- return rc;
-}
-
-static int currentfs_follow_link (struct dentry *dentry, struct nameidata *nd)
-{
- struct snap_cache *cache;
- struct inode_operations *iops;
- struct inode * inode = dentry->d_inode;
- int bpib = inode->i_sb->s_blocksize >> 9;
- __u32 save_i_blocks;
- int rc;
- ENTRY;
-
- cache = snap_find_cache(inode->i_dev);
- if ( !cache ) {
- RETURN(-EINVAL);
- }
-
- iops = filter_c2csiops(cache->cache_filter);
- if (!iops ||
- !iops->follow_link) {
- GOTO(exit, rc = -EINVAL);
- }
-
- if( currentfs_is_under_dotsnap(dentry) ){
- rc = dotsnap_follow_link(dentry, nd);
- if( rc )
- goto exit;
- }
-
- save_i_blocks = inode->i_blocks;
- /* If this link has ea and its i_blocks is ea's block,
- * then we should treate it as a fast symlink
- */
- if( inode_has_ea(inode) && inode->i_blocks == bpib ) {
- inode->i_blocks = 0;
- }
- rc = iops->follow_link(dentry, nd);
-
- if( inode->i_blocks != save_i_blocks ){
- inode->i_blocks = save_i_blocks;
- mark_inode_dirty(inode);
- }
-
-exit:
- RETURN(rc);
-}
-
-struct inode_operations currentfs_sym_iops = {
- readlink: currentfs_readlink,
- follow_link: currentfs_follow_link,
-};
-
-struct file_operations currentfs_sym_fops = {
- ioctl: NULL,
-};
+++ /dev/null
-/*
- * Sysctrl entries for Snapfs
- */
-
-/* /proc entries */
-
-#define DEBUG_SUBSYSTEM S_SNAP
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/snap.h>
-
-#include "snapfs_internal.h"
-
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_snapfs_root;
-#endif
-
-
-/* SYSCTL below */
-
-static struct ctl_table_header *snapfs_table_header = NULL;
-/* 0x100 to avoid any chance of collisions at any point in the tree with
- * non-directories
- */
-#define PSDEV_SNAPFS (0x120)
-
-#define PSDEV_DEBUG 1 /* control debugging */
-#define PSDEV_TRACE 2 /* control enter/leave pattern */
-
-/* These are global control options */
-#define ENTRY_CNT 3
-
-int snap_print_entry = 1;
-int snap_debug_level = 0;
-
-/* XXX - doesn't seem to be working in 2.2.15 */
-static struct ctl_table snapfs_ctltable[] =
-{
- {PSDEV_DEBUG, "debug", &snap_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
- {PSDEV_TRACE, "trace", &snap_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
- {0}
-};
-
-static ctl_table snapfs_table[2] = {
- {PSDEV_SNAPFS, "snapfs", NULL, 0, 0555, snapfs_ctltable},
- {0}
-};
-
-
-int __init init_snapfs_proc_sys(void)
-{
-#ifdef CONFIG_PROC_FS
- proc_snapfs_root = proc_mkdir("snapfs", proc_root_fs);
- if (!proc_snapfs_root) {
- printk(KERN_ERR "SNAPFS: error registering /proc/fs/snapfs\n");
- RETURN(-ENOMEM);
- }
- proc_snapfs_root->owner = THIS_MODULE;
-#endif
-
-#ifdef CONFIG_SYSCTL
- if ( !snapfs_table_header )
- snapfs_table_header =
- register_sysctl_table(snapfs_table, 0);
-#endif
- return 0;
-}
-
-void cleanup_snapfs_proc_sys(void)
-{
-#ifdef CONFIG_SYSCTL
- if ( snapfs_table_header )
- unregister_sysctl_table(snapfs_table_header);
- snapfs_table_header = NULL;
-#endif
-#if CONFIG_PROC_FS
- remove_proc_entry("snapfs", proc_root_fs);
-#endif
-
-}
-
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-.*.cmd
+++ /dev/null
-# Administration utilities Makefile
-
-if SNAPFS
-noinst_PROGRAMS = snapconf
-snapconf_LDADD := $(LIBREADLINE) -ltermcap
-endif
-
-snapconf_SOURCES = parser.c snapctl.c snapconf.c parser.h snapctl.h
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre 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.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <assert.h>
-
-#ifdef HAVE_LIBREADLINE
-#define READLINE_LIBRARY
-#include <readline/readline.h>
-
-/* completion_matches() is #if 0-ed out in modern glibc */
-#ifndef completion_matches
-# define completion_matches rl_completion_matches
-#endif
-extern void using_history(void);
-extern void stifle_history(int);
-extern void add_history(char *);
-#endif
-
-#include "parser.h"
-
-static command_t * top_level; /* Top level of commands, initialized by
- * InitParser */
-static char * parser_prompt = NULL;/* Parser prompt, set by InitParser */
-static int done; /* Set to 1 if user types exit or quit */
-static int ignore_errors; /* Normally, the parser will quit when
- an error occurs in non-interacive
- mode. Setting this to non-zero will
- force it to keep buggering on. */
-
-
-/* static functions */
-static char *skipwhitespace(char *s);
-static char *skiptowhitespace(char *s);
-static command_t *find_cmd(char *name, command_t cmds[], char **next);
-static int process(char *s, char **next, command_t *lookup, command_t **result,
- char **prev);
-static void print_commands(char *str, command_t *table);
-
-static char * skipwhitespace(char * s)
-{
- char * t;
- int len;
-
- len = (int)strlen(s);
- for (t = s; t <= s + len && isspace(*t); t++);
- return(t);
-}
-
-
-static char * skiptowhitespace(char * s)
-{
- char * t;
-
- for (t = s; *t && !isspace(*t); t++);
- return(t);
-}
-
-static int line2args(char *line, char **argv, int maxargs)
-{
- char *arg;
- int i = 0;
-
- arg = strtok(line, " \t");
- if ( arg ) {
- argv[i] = arg;
- i++;
- } else
- return 0;
-
- while( (arg = strtok(NULL, " \t")) && (i <= maxargs)) {
- argv[i] = arg;
- i++;
- }
- return i;
-}
-
-/* find a command -- return it if unique otherwise print alternatives */
-static command_t *Parser_findargcmd(char *name, command_t cmds[])
-{
- command_t *cmd;
-
- for (cmd = cmds; cmd->pc_name; cmd++) {
- if (strcmp(name, cmd->pc_name) == 0)
- return cmd;
- }
- return NULL;
-}
-
-void Parser_ignore_errors(int ignore)
-{
- ignore_errors = ignore;
-}
-
-int Parser_execarg(int argc, char **argv, command_t cmds[])
-{
- command_t *cmd;
-
- cmd = Parser_findargcmd(argv[0], cmds);
- if ( cmd ) {
- int rc = (cmd->pc_func)(argc, argv);
- if (rc == CMD_HELP)
- fprintf(stderr, "%s\n", cmd->pc_help);
- return rc;
- } else {
- printf("Try interactive use without arguments or use one of:\n");
- for (cmd = cmds; cmd->pc_name; cmd++)
- printf("\"%s\"\n", cmd->pc_name);
- printf("as argument.\n");
- }
- return -1;
-}
-
-/* returns the command_t * (NULL if not found) corresponding to a
- _partial_ match with the first token in name. It sets *next to
- point to the following token. Does not modify *name. */
-static command_t * find_cmd(char * name, command_t cmds[], char ** next)
-{
- int i, len;
-
- if (!cmds || !name )
- return NULL;
-
- /* This sets name to point to the first non-white space character,
- and next to the first whitespace after name, len to the length: do
- this with strtok*/
- name = skipwhitespace(name);
- *next = skiptowhitespace(name);
- len = *next - name;
- if (len == 0)
- return NULL;
-
- for (i = 0; cmds[i].pc_name; i++) {
- if (strncasecmp(name, cmds[i].pc_name, len) == 0) {
- *next = skipwhitespace(*next);
- return(&cmds[i]);
- }
- }
- return NULL;
-}
-
-/* Recursively process a command line string s and find the command
- corresponding to it. This can be ambiguous, full, incomplete,
- non-existent. */
-static int process(char *s, char ** next, command_t *lookup,
- command_t **result, char **prev)
-{
- *result = find_cmd(s, lookup, next);
- *prev = s;
-
- /* non existent */
- if (!*result)
- return CMD_NONE;
-
- /* found entry: is it ambigous, i.e. not exact command name and
- more than one command in the list matches. Note that find_cmd
- points to the first ambiguous entry */
- if (strncasecmp(s, (*result)->pc_name, strlen((*result)->pc_name))) {
- char *another_next;
- command_t *another_result = find_cmd(s, (*result) + 1,
- &another_next);
- int found_another = 0;
-
- while (another_result) {
- if (strncasecmp(s, another_result->pc_name,
- strlen(another_result->pc_name)) == 0){
- *result = another_result;
- *next = another_next;
- goto got_it;
- }
- another_result = find_cmd(s, another_result + 1,
- &another_next);
- found_another = 1;
- }
- if (found_another)
- return CMD_AMBIG;
- }
-
-got_it:
- /* found a unique command: component or full? */
- if ( (*result)->pc_func ) {
- return CMD_COMPLETE;
- } else {
- if ( *next == '\0' ) {
- return CMD_INCOMPLETE;
- } else {
- return process(*next, next, (*result)->pc_sub_cmd,
- result, prev);
- }
- }
-}
-
-#ifdef HAVE_LIBREADLINE
-static command_t * match_tbl; /* Command completion against this table */
-static char * command_generator(const char * text, int state)
-{
- static int index,
- len;
- char *name;
-
- /* Do we have a match table? */
- if (!match_tbl)
- return NULL;
-
- /* If this is the first time called on this word, state is 0 */
- if (!state) {
- index = 0;
- len = (int)strlen(text);
- }
-
- /* Return next name in the command list that paritally matches test */
- while ( (name = (match_tbl + index)->pc_name) ) {
- index++;
-
- if (strncasecmp(name, text, len) == 0) {
- return(strdup(name));
- }
- }
-
- /* No more matches */
- return NULL;
-}
-
-/* probably called by readline */
-static char **command_completion(char * text, int start, int end)
-{
- command_t * table;
- char * pos;
-
- match_tbl = top_level;
-
- for (table = find_cmd(rl_line_buffer, match_tbl, &pos);
- table; table = find_cmd(pos, match_tbl, &pos))
- {
-
- if (*(pos - 1) == ' ') match_tbl = table->pc_sub_cmd;
- }
-
- return completion_matches(text, command_generator);
-}
-#endif
-
-/* take a string and execute the function or print help */
-int execute_line(char * line)
-{
- command_t *cmd, *ambig;
- char *prev;
- char *next, *tmp;
- char *argv[MAXARGS];
- int i;
- int rc = 0;
-
- switch (process(line, &next, top_level, &cmd, &prev)) {
- case CMD_AMBIG:
- fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
- while( (ambig = find_cmd(prev, cmd, &tmp)) ) {
- fprintf(stderr, "%s ", ambig->pc_name);
- cmd = ambig + 1;
- }
- fprintf(stderr, "\n");
- break;
- case CMD_NONE:
- fprintf(stderr, "No such command, type help\n");
- break;
- case CMD_INCOMPLETE:
- fprintf(stderr,
- "'%s' incomplete command. Use '%s x' where x is one of:\n",
- line, line);
- fprintf(stderr, "\t");
- for (i = 0; cmd->pc_sub_cmd[i].pc_name; i++) {
- fprintf(stderr, "%s ", cmd->pc_sub_cmd[i].pc_name);
- }
- fprintf(stderr, "\n");
- break;
- case CMD_COMPLETE:
- i = line2args(line, argv, MAXARGS);
- rc = (cmd->pc_func)(i, argv);
-
- if (rc == CMD_HELP)
- fprintf(stderr, "%s\n", cmd->pc_help);
-
- break;
- }
-
- return rc;
-}
-
-int
-noop_fn ()
-{
- return (0);
-}
-
-/* just in case you're ever in an airplane and discover you
- forgot to install readline-dev. :) */
-int init_input()
-{
- int interactive = isatty (fileno (stdin));
-
-#ifdef HAVE_LIBREADLINE
- using_history();
- stifle_history(HISTORY);
-
- if (!interactive)
- {
- rl_prep_term_function = (rl_vintfunc_t *)noop_fn;
- rl_deprep_term_function = (rl_voidfunc_t *)noop_fn;
- }
-
- rl_attempted_completion_function = (CPPFunction *)command_completion;
- rl_completion_entry_function = (void *)command_generator;
-#endif
- return interactive;
-}
-
-#ifndef HAVE_LIBREADLINE
-#define add_history(s)
-char * readline(char * prompt)
-{
- char line[2048];
- int n = 0;
- if (prompt)
- printf ("%s", prompt);
- if (fgets(line, sizeof(line), stdin) == NULL)
- return (NULL);
- n = strlen(line);
- if (n && line[n-1] == '\n')
- line[n-1] = '\0';
- return strdup(line);
-}
-#endif
-
-/* this is the command execution machine */
-int Parser_commands(void)
-{
- char *line, *s;
- int rc = 0, save_error = 0;
- int interactive;
-
- interactive = init_input();
-
- while(!done) {
- line = readline(interactive ? parser_prompt : NULL);
-
- if (!line) break;
-
- s = skipwhitespace(line);
-
- if (*s) {
- add_history(s);
- rc = execute_line(s);
- }
- /* stop on error if not-interactive */
- if (rc != 0 && !interactive) {
- if (save_error == 0)
- save_error = rc;
- if (!ignore_errors)
- done = 1;
- }
-
- free(line);
- }
- if (save_error)
- rc = save_error;
- return rc;
-}
-
-
-/* sets the parser prompt */
-void Parser_init(char * prompt, command_t * cmds)
-{
- done = 0;
- top_level = cmds;
- if (parser_prompt) free(parser_prompt);
- parser_prompt = strdup(prompt);
-}
-
-/* frees the parser prompt */
-void Parser_exit(int argc, char *argv[])
-{
- done = 1;
- free(parser_prompt);
- parser_prompt = NULL;
-}
-
-/* convert a string to an integer */
-int Parser_int(char *s, int *val)
-{
- int ret;
-
- if (*s != '0')
- ret = sscanf(s, "%d", val);
- else if (*(s+1) != 'x')
- ret = sscanf(s, "%o", val);
- else {
- s++;
- ret = sscanf(++s, "%x", val);
- }
-
- return(ret);
-}
-
-
-void Parser_qhelp(int argc, char *argv[]) {
-
- printf("Available commands are:\n");
-
- print_commands(NULL, top_level);
- printf("For more help type: help command-name\n");
-}
-
-int Parser_help(int argc, char **argv)
-{
- char line[1024];
- char *next, *prev, *tmp;
- command_t *result, *ambig;
- int i;
-
- if ( argc == 1 ) {
- Parser_qhelp(argc, argv);
- return 0;
- }
-
- line[0]='\0';
- for ( i = 1 ; i < argc ; i++ ) {
- strcat(line, argv[i]);
- }
-
- switch ( process(line, &next, top_level, &result, &prev) ) {
- case CMD_COMPLETE:
- fprintf(stderr, "%s: %s\n",line, result->pc_help);
- break;
- case CMD_NONE:
- fprintf(stderr, "%s: Unknown command.\n", line);
- break;
- case CMD_INCOMPLETE:
- fprintf(stderr,
- "'%s' incomplete command. Use '%s x' where x is one of:\n",
- line, line);
- fprintf(stderr, "\t");
- for (i = 0; result->pc_sub_cmd[i].pc_name; i++) {
- fprintf(stderr, "%s ", result->pc_sub_cmd[i].pc_name);
- }
- fprintf(stderr, "\n");
- break;
- case CMD_AMBIG:
- fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
- while( (ambig = find_cmd(prev, result, &tmp)) ) {
- fprintf(stderr, "%s ", ambig->pc_name);
- result = ambig + 1;
- }
- fprintf(stderr, "\n");
- break;
- }
- return 0;
-}
-
-
-void Parser_printhelp(char *cmd)
-{
- char *argv[] = { "help", cmd };
- Parser_help(2, argv);
-}
-
-
-/*************************************************************************
- * COMMANDS *
- *************************************************************************/
-static void print_commands(char * str, command_t * table) {
- command_t * cmds;
- char buf[80];
-
- for (cmds = table; cmds->pc_name; cmds++) {
- if (cmds->pc_func) {
- if (str) printf("\t%s %s\n", str, cmds->pc_name);
- else printf("\t%s\n", cmds->pc_name);
- }
- if (cmds->pc_sub_cmd) {
- if (str) {
- sprintf(buf, "%s %s", str, cmds->pc_name);
- print_commands(buf, cmds->pc_sub_cmd);
- } else {
- print_commands(cmds->pc_name, cmds->pc_sub_cmd);
- }
- }
- }
-}
-
-char *Parser_getstr(const char *prompt, const char *deft, char *res,
- size_t len)
-{
- char *line = NULL;
- int size = strlen(prompt) + strlen(deft) + 8;
- char *theprompt;
- theprompt = malloc(size);
- assert(theprompt);
-
- sprintf(theprompt, "%s [%s]: ", prompt, deft);
-
- line = readline(theprompt);
- free(theprompt);
-
- if ( line == NULL || *line == '\0' ) {
- strncpy(res, deft, len);
- } else {
- strncpy(res, line, len);
- }
-
- if ( line ) {
- free(line);
- return res;
- } else {
- return NULL;
- }
-}
-
-/* get integer from prompt, loop forever to get it */
-int Parser_getint(const char *prompt, long min, long max, long deft, int base)
-{
- int rc;
- long result;
- char *line;
- int size = strlen(prompt) + 40;
- char *theprompt = malloc(size);
- assert(theprompt);
- sprintf(theprompt,"%s [%ld, (0x%lx)]: ", prompt, deft, deft);
-
- fflush(stdout);
-
- do {
- line = NULL;
- line = readline(theprompt);
- if ( !line ) {
- fprintf(stdout, "Please enter an integer.\n");
- fflush(stdout);
- continue;
- }
- if ( *line == '\0' ) {
- free(line);
- result = deft;
- break;
- }
- rc = Parser_arg2int(line, &result, base);
- free(line);
- if ( rc != 0 ) {
- fprintf(stdout, "Invalid string.\n");
- fflush(stdout);
- } else if ( result > max || result < min ) {
- fprintf(stdout, "Error: response must lie between %ld and %ld.\n",
- min, max);
- fflush(stdout);
- } else {
- break;
- }
- } while ( 1 ) ;
-
- if (theprompt)
- free(theprompt);
- return result;
-
-}
-
-/* get boolean (starting with YyNn; loop forever */
-int Parser_getbool(const char *prompt, int deft)
-{
- int result = 0;
- char *line;
- int size = strlen(prompt) + 8;
- char *theprompt = malloc(size);
- assert(theprompt);
-
- fflush(stdout);
-
- if ( deft != 0 && deft != 1 ) {
- fprintf(stderr, "Error: Parser_getbool given bad default %d\n",
- deft);
- assert ( 0 );
- }
- sprintf(theprompt, "%s [%s]: ", prompt, (deft==0)? "N" : "Y");
-
- do {
- line = NULL;
- line = readline(theprompt);
- if ( line == NULL ) {
- result = deft;
- break;
- }
- if ( *line == '\0' ) {
- result = deft;
- break;
- }
- if ( *line == 'y' || *line == 'Y' ) {
- result = 1;
- break;
- }
- if ( *line == 'n' || *line == 'N' ) {
- result = 0;
- break;
- }
- if ( line )
- free(line);
- fprintf(stdout, "Invalid string. Must start with yY or nN\n");
- fflush(stdout);
- } while ( 1 );
-
- if ( line )
- free(line);
- if ( theprompt )
- free(theprompt);
- return result;
-}
-
-/* parse int out of a string or prompt for it */
-long Parser_intarg(const char *inp, const char *prompt, int deft,
- int min, int max, int base)
-{
- long result;
- int rc;
-
- rc = Parser_arg2int(inp, &result, base);
-
- if ( rc == 0 ) {
- return result;
- } else {
- return Parser_getint(prompt, deft, min, max, base);
- }
-}
-
-/* parse int out of a string or prompt for it */
-char *Parser_strarg(char *inp, const char *prompt, const char *deft,
- char *answer, int len)
-{
- if ( inp == NULL || *inp == '\0' ) {
- return Parser_getstr(prompt, deft, answer, len);
- } else
- return inp;
-}
-
-/* change a string into a number: return 0 on success. No invalid characters
- allowed. The processing of base and validity follows strtol(3)*/
-int Parser_arg2int(const char *inp, long *result, int base)
-{
- char *endptr;
-
- if ( (base !=0) && (base < 2 || base > 36) )
- return 1;
-
- *result = strtol(inp, &endptr, base);
-
- if ( *inp != '\0' && *endptr == '\0' )
- return 0;
- else
- return 1;
-}
-
-/* Convert human readable size string to and int; "1k" -> 1000 */
-int Parser_size (int *sizep, char *str) {
- int size;
- char mod[32];
-
- switch (sscanf (str, "%d%1[gGmMkK]", &size, mod)) {
- default:
- return (-1);
-
- case 1:
- *sizep = size;
- return (0);
-
- case 2:
- switch (*mod) {
- case 'g':
- case 'G':
- *sizep = size << 30;
- return (0);
-
- case 'm':
- case 'M':
- *sizep = size << 20;
- return (0);
-
- case 'k':
- case 'K':
- *sizep = size << 10;
- return (0);
-
- default:
- *sizep = size;
- return (0);
- }
- }
-}
-
-/* Convert a string boolean to an int; "enable" -> 1 */
-int Parser_bool (int *b, char *str) {
- if (!strcasecmp (str, "no") ||
- !strcasecmp (str, "n") ||
- !strcasecmp (str, "off") ||
- !strcasecmp (str, "down") ||
- !strcasecmp (str, "disable"))
- {
- *b = 0;
- return (0);
- }
-
- if (!strcasecmp (str, "yes") ||
- !strcasecmp (str, "y") ||
- !strcasecmp (str, "on") ||
- !strcasecmp (str, "up") ||
- !strcasecmp (str, "enable"))
- {
- *b = 1;
- return (0);
- }
-
- return (-1);
-}
-
-int Parser_quit(int argc, char **argv)
-{
- argc = argc;
- argv = argv;
- done = 1;
- return 0;
-}
+++ /dev/null
-#ifndef _PARSER_H_
-#define _PARSER_H_
-
-#define HISTORY 100 /* Don't let history grow unbounded */
-#define MAXARGS 512
-
-#define CMD_COMPLETE 0
-#define CMD_INCOMPLETE 1
-#define CMD_NONE 2
-#define CMD_AMBIG 3
-#define CMD_HELP 4
-
-typedef struct parser_cmd {
- char *pc_name;
- int (* pc_func)(int, char **);
- struct parser_cmd * pc_sub_cmd;
- char *pc_help;
-} command_t;
-
-typedef struct argcmd {
- char *ac_name;
- int (*ac_func)(int, char **);
- char *ac_help;
-} argcmd_t;
-
-typedef struct network {
- char *type;
- char *server;
- int port;
-} network_t;
-
-int Parser_quit(int argc, char **argv);
-void Parser_init(char *, command_t *); /* Set prompt and load command list */
-int Parser_commands(void); /* Start the command parser */
-void Parser_qhelp(int, char **); /* Quick help routine */
-int Parser_help(int, char **); /* Detailed help routine */
-void Parser_ignore_errors(int ignore); /* Set the ignore errors flag */
-void Parser_printhelp(char *); /* Detailed help routine */
-void Parser_exit(int, char **); /* Shuts down command parser */
-int Parser_execarg(int argc, char **argv, command_t cmds[]);
-int execute_line(char * line);
-
-/* Converts a string to an integer */
-int Parser_int(char *, int *);
-
-/* Prompts for a string, with default values and a maximum length */
-char *Parser_getstr(const char *prompt, const char *deft, char *res,
- size_t len);
-
-/* Prompts for an integer, with minimum, maximum and default values and base */
-int Parser_getint(const char *prompt, long min, long max, long deft,
- int base);
-
-/* Prompts for a yes/no, with default */
-int Parser_getbool(const char *prompt, int deft);
-
-/* Extracts an integer from a string, or prompts if it cannot get one */
-long Parser_intarg(const char *inp, const char *prompt, int deft,
- int min, int max, int base);
-
-/* Extracts a word from the input, or propmts if it cannot get one */
-char *Parser_strarg(char *inp, const char *prompt, const char *deft,
- char *answer, int len);
-
-/* Extracts an integer from a string with a base */
-int Parser_arg2int(const char *inp, long *result, int base);
-
-/* Convert human readable size string to and int; "1k" -> 1000 */
-int Parser_size(int *sizep, char *str);
-
-/* Convert a string boolean to an int; "enable" -> 1 */
-int Parser_bool(int *b, char *str);
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * utils/snapconf.c
- *
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <portals/api-support.h>
-#include <portals/ptlctl.h>
-#include <portals/list.h>
-#include "parser.h"
-#include "snapctl.h"
-
-static int jt_quit(int argc, char **argv) {
- Parser_quit(argc, argv);
- return 0;
-}
-
-static int jt_noop(int argc, char **argv) {
- return 0;
-}
-
-static int jt_opt_ignore_errors(int argc, char **argv) {
- Parser_ignore_errors(1);
- return 0;
-}
-
-command_t cmdlist[] = {
- /* Metacommands */
- {"--ignore_errors", jt_opt_ignore_errors, 0,
- "ignore errors that occur during script processing\n"
- "--ignore_errors"},
- /* snapshot commands*/
- {"device_list", snap_dev_list, 0,
- "device_list list snap available device\n"},
- {"device", snap_dev_open, 0,
- "dev <device> open available snap device\n"},
- {"add", snap_snap_add, 0,
- "add [table_no] <snap_name> add snapshot to the device\n"},
- {"del", snap_snap_del, 0,
- "del [table_no] <snap_name> del snapshot to the device\n"},
- {"snap_list", snap_snap_list, 0,
- "snap_list [table_no] list all the snapshots on the device\n"},
-
- /* User interface commands */
- {"======= control ========", jt_noop, 0, "control commands"},
- {"help", Parser_help, 0, "help"},
- {"exit", jt_quit, 0, "quit"},
- {"quit", jt_quit, 0, "quit"},
- { 0, 0, 0, NULL }
-};
-
-int main(int argc, char **argv)
-{
- int rc;
-
- setlinebuf(stdout);
-
- Parser_init("snapconf > ", cmdlist);
- init_snap_list();
-
- if (argc > 1) {
- rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
- } else {
- rc = Parser_commands();
- }
-
- return rc;
-}
-
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <mntent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <time.h>
-#include <string.h>
-#include <portals/list.h>
-#include "parser.h"
-#include "snapctl.h"
-#include <snapfs_internal.h>
-
-#define IOC_BUF_MAX_LEN 8192
-static char rawbuf[IOC_BUF_MAX_LEN];
-static char *buf = rawbuf;
-/*FIXME add this temporary, will use obd_ioc_data later*/
-#define IOC_INIT(ptr) \
-do{ \
- struct ioc_data* pbuf; \
- memset(buf, 0, sizeof(rawbuf)); \
- pbuf = (struct ioc_data*)buf; \
- pbuf->ioc_inbuf = pbuf->ioc_bulk; \
- ptr = (struct ioc_snap_tbl_data *)pbuf->ioc_bulk; \
-} while(0)
-
-#define IOC_PACK(length) \
-do{ \
- struct ioc_data* pbuf; \
- pbuf = (struct ioc_data*)buf; \
- pbuf->ioc_inlen = length; \
-} while (0)
-
-static struct list_head snap_list;
-struct open_snap_device open_device_table;
-struct snap_device snap_device_list[10];
-
-
-static int get_snaplist()
-{
- FILE *mnt_filp = NULL;
- int error = 0;
-
- /*open mount list*/
- mnt_filp = setmntent("/etc/mtab", "r");
-
- if (!mnt_filp)
- return -EINVAL;
- /*get the mentent and check snap mount*/
- while (!feof(mnt_filp)) {
- struct mntent* entry;
-
- entry = getmntent(mnt_filp);
-
- if (!entry) continue;
-
- if (!strcmp(entry->mnt_type, "snap_current")) {
- /*found a snap_mount structure add to the snaplist*/
- struct snap_mnt *s_mnt;
- char *opt = NULL;
- char dev_name[DEV_NAME_MAX_LEN];
- struct stat statbuf;
-
- s_mnt = (struct snap_mnt *) malloc(sizeof(struct snap_mnt));
- if (!s_mnt) {
- error = ENOMEM;
- goto exit;
- }
- memset(s_mnt, 0, sizeof(struct snap_mnt));
- memcpy(&s_mnt->device.name[0], entry->mnt_fsname, strlen(entry->mnt_fsname));
- memcpy(&s_mnt->device.mntpt[0], entry->mnt_dir, strlen(entry->mnt_dir));
- opt = hasmntopt(entry, "loop");
- memset(dev_name, 0, DEV_NAME_MAX_LEN);
- if (opt) {
- /* Loop device mount find the real dev_name*/
- char *name = opt, *name_dev = dev_name;
-
- while (*name++ != '=');
- while (*name != ',' && *name != ')' && *name ) {
- *name_dev++ = *name++;
- }
-
- } else {
- memcpy(dev_name, entry->mnt_fsname, strlen(entry->mnt_fsname));
- }
-
- if ((error = stat(dev_name, &statbuf)) != 0) {
- fprintf(stderr, "can not stat %s", strerror(errno));
- goto exit;
- }
- s_mnt->device.dev = (unsigned long)statbuf.st_rdev;
- list_add(&s_mnt->snap_mnt_list, &snap_list);
- }
- }
-exit:
- if (mnt_filp)
- endmntent(mnt_filp);
- return error;
-}
-
-static void release_snap_list()
-{
- struct snap_mnt *snaplist;
-
- list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
- list_del(&snaplist->snap_mnt_list);
- free(snaplist);
- }
-}
-
-void init_snap_list()
-{
- int i;
-
- INIT_LIST_HEAD(&snap_list);
- open_device_table.count = 0;
- for(i = 0; i < 10; i++) {
- memset(&open_device_table.device[i].name[0],
- 0, DEV_NAME_MAX_LEN);
- open_device_table.device[i].fd = -1;
- }
-}
-
-static int open_device(char *name, unsigned int dev)
-{
- int index=0, error = 0, i = 0, found = 0;
-
- /*XXX Does these information necessary*/
- for (i = 0; i < open_device_table.count; i++) {
- if (!strcmp(&open_device_table.device[i].name[0], name)) {
- index = i;
- found = 1;
- break;
- }
- }
- if (found == 0) {
- open_device_table.device[index].dev = dev;
- memset(&open_device_table.device[index].name[0],
- 0, DEV_NAME_MAX_LEN);
- memcpy(&open_device_table.device[index].name[0],
- name, strlen(name));
- open_device_table.count ++;
- }
- /*FIXME If there are more than device, how to handle it*/
- if (open_device_table.device[index].fd < 0) {
- /*open device*/
- int fd = open(SNAPDEV_NAME, O_RDWR);
-
- if (fd < 0) {
- if (errno == ENOENT) {
- dev_t snap_dev=makedev(SNAP_PSDEV_MAJOR,SNAP_PSDEV_MINOR);
- /*create snapdevice node*/
- error = mknod(SNAPDEV_NAME, S_IRUSR|S_IWUSR|S_IFCHR, snap_dev);
- if (error) {
- fprintf(stderr, "Can not make node %s :%s \n",
- SNAPDEV_NAME, strerror(errno));
- return (-errno);
- }
- if ((fd = open(SNAPDEV_NAME, O_RDWR)) < 0) {
- fprintf(stderr, "Can not open node %s: %s\n",
- SNAPDEV_NAME, strerror(errno));
- return (-errno);
- }
- } else {
- fprintf(stderr, "Can not open node %s: %s %d \n",
- SNAPDEV_NAME, strerror(errno), errno);
- return(-errno);
- }
- }
- open_device_table.device[index].fd = fd;
- }
- return 0;
-}
-static int open_snap_device(char *name)
-{
- struct snap_mnt *snaplist;
- int rc;
- get_snaplist();
- list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
- if (!strcmp(&snaplist->device.name[0], name)) {
- rc = open_device(&snaplist->device.name[0],
- snaplist->device.dev);
- release_snap_list();
- return rc;
- }
- }
- release_snap_list();
- fprintf(stderr, "%s are not snapdevice\n", name);
- return (-EINVAL);
-}
-int snap_dev_open(int argc, char **argv)
-{
- char *dev_name;
- int rc;
-
- if (argc != 2) {
- fprintf(stderr, "The argument count is not right \n");
- return CMD_HELP;
- }
-
- dev_name = argv[1];
- rc = open_snap_device(dev_name);
- if (rc)
- fprintf(stderr, "%s are not snapdevice\n", dev_name);
- return (rc);
-}
-int snap_dev_list(int argc, char **argv)
-{
- struct snap_mnt *snaplist;
- int index = 0;
-
- if (argc != 1) {
- fprintf(stderr, "The argument count is not right \n");
- return CMD_HELP;
- }
-
- get_snaplist();
- printf("index:\t\tmount_point:\t\tdevice:\n");
- list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
- printf("%d\t\t%s\t\t%s \n", index,
- &snaplist->device.mntpt[0],
- &snaplist->device.name[0]);
- index++;
- }
- release_snap_list();
- return 0;
-}
-static inline void print_snap_table(void * buf)
-{
- struct ioc_snap_tbl_data *ptable;
- int i;
-
- ptable = (struct ioc_snap_tbl_data*)buf;
-
- printf("There are %d snapshot in the system\n", ptable->count);
- printf("index\t\tname\t\t\ttime\t\t\n");
- for (i = 0; i < ptable->count; i++) {
- struct tm* local_time;
- char time[128];
-
- memset (time, 0, sizeof(time));
- local_time = localtime(&ptable->snaps[i].time);
- if (local_time)
- strftime(time, sizeof(time), "%a %b %d %Y %H:%M:%S", local_time);
- printf("%-10d\t%-20s\t%s\n", ptable->snaps[i].index, ptable->snaps[i].name, time);
- }
-}
-int snap_snap_list(int argc, char **argv)
-{
- char *dev_name = NULL;
- int i, rc = 0;
-
- if (argc != 1 && argc != 2) {
- fprintf(stderr, "The argument count is not right\n");
- return CMD_HELP;
- }
- if (open_device_table.count == 0) {
- if (argc == 2) {
- dev_name = argv[1];
- }
- if (dev_name) {
- rc = open_snap_device(dev_name);
- }
- if (!dev_name || rc) {
- fprintf(stderr, "Please open a snapdevice first\n");
- return (-EINVAL);
- }
- }
- for (i = 0; i < open_device_table.count; i++) {
- struct ioc_snap_tbl_data *snap_ioc_data;
-
- IOC_INIT(snap_ioc_data);
-
- if (argc == 2) {
- snap_ioc_data->no = atoi(argv[1]);
- } else {
- snap_ioc_data->no = 0;
- }
-
- IOC_PACK(sizeof(struct ioc_snap_tbl_data));
-
- if ((rc = ioctl(open_device_table.device[i].fd,
- IOC_SNAP_PRINTTABLE, buf))) {
- fprintf(stderr, "can not retrive snaptable on device %s failed %d \n",
- &open_device_table.device[i].name[0], rc);
- return (rc);
- }
- if(((struct ioc_data*)buf)->ioc_bulk)
- print_snap_table(((struct ioc_data*)buf)->ioc_bulk);
- }
- return rc;
-}
-int snap_snap_del(int argc, char **argv)
-{
- char *dev_name = NULL, *snap_name = NULL;
- int rc = 0, i;
-
- if (argc != 3 && argc !=2) {
- fprintf(stderr, "The argument count is not right \n");
- return CMD_HELP;
- }
- if (open_device_table.count == 0) {
- if (argc == 3) {
- dev_name = argv[1];
- } else if (argc == 4) {
- dev_name = argv[2];
- }
- if (dev_name) {
- rc = open_snap_device(dev_name);
- }
- if (!dev_name || rc) {
- fprintf(stderr, "Please open a snapdevice first\n");
- return (-EINVAL);
- }
- }
- for (i = 0; i < open_device_table.count; i++) {
- struct ioc_snap_tbl_data *snap_ioc_data;
-
- IOC_INIT(snap_ioc_data);
-
- snap_ioc_data->count = 1;
- snap_ioc_data->dev = open_device_table.device[i].dev;
-
- if (argc == 3) {
- snap_ioc_data->no = atoi(argv[1]);
- if (!snap_name)
- snap_name = argv[2];
- } else {
- snap_ioc_data->no = 0;
- if (!snap_name)
- snap_name = argv[1];
- }
- memcpy(snap_ioc_data->snaps[0].name,
- snap_name, strlen(snap_name));
-
- snap_ioc_data->snaps[0].time = time(NULL);
-
- IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
-
- if ((rc = ioctl(open_device_table.device[i].fd,
- IOC_SNAP_DELETE, buf))) {
- fprintf(stderr, "del %s failed \n", snap_name);
- } else {
- fprintf(stderr, "del %s success\n", snap_name);
- }
- }
- return rc;
-}
-int snap_snap_add(int argc, char **argv)
-{
- char *dev_name = NULL, *snap_name = NULL;
- int rc = 0, i;
-
- if (argc != 3 && argc !=2 && argc !=4) {
- fprintf(stderr, "The argument count is not right \n");
- return CMD_HELP;
- }
- if (open_device_table.count == 0) {
- if (argc == 3) {
- dev_name = argv[1];
- snap_name = argv[2];
- } else if (argc == 4) {
- dev_name = argv[2];
- snap_name = argv[3];
- }
- if (dev_name) {
- rc = open_snap_device(dev_name);
- }
- if (!dev_name || rc) {
- fprintf(stderr, "Please open a snapdevice first\n");
- return (-EINVAL);
- }
- }
- for (i = 0; i < open_device_table.count; i++) {
- struct ioc_snap_tbl_data *snap_ioc_data;
-
- IOC_INIT(snap_ioc_data);
-
- snap_ioc_data->count = 1;
- snap_ioc_data->dev = open_device_table.device[i].dev;
-
- if (argc == 3) {
- snap_ioc_data->no = atoi(argv[1]);
- if (!snap_name)
- snap_name = argv[2];
- } else {
- snap_ioc_data->no = 0;
- if (!snap_name)
- snap_name = argv[1];
- }
- memcpy(snap_ioc_data->snaps[0].name,
- snap_name, strlen(snap_name));
- snap_ioc_data->snaps[0].time = time(NULL);
-
- IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
-
- if ((rc = ioctl(open_device_table.device[i].fd,
- IOC_SNAP_ADD, buf))) {
- fprintf(stderr, "add %s failed \n", snap_name);
- } else {
- fprintf(stderr, "add %s success\n", snap_name);
- }
- }
- return rc;
-}
+++ /dev/null
-/* snapctl.h */
-#define DEV_NAME_MAX_LEN 64
-struct snap_device {
- char name[DEV_NAME_MAX_LEN];
- char mntpt[DEV_NAME_MAX_LEN];
- unsigned long dev;
- int fd;
-};
-struct snap_mnt {
- struct snap_device device;
- struct list_head snap_mnt_list;
-};
-struct open_snap_device {
- struct snap_device device[10];
- int count;
-};
-extern void init_snap_list(void);
-
-extern int snap_dev_open(int argc, char **argv);
-extern int snap_dev_list(int argc, char **argv);
-extern int snap_snap_add(int argc, char **argv);
-extern int snap_snap_del(int argc, char **argv);
-extern int snap_snap_list(int argc, char **argv);