# endif
#endif
-#ifndef LP_POISON
+/*#ifndef LP_POISON
# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
-#endif
+#endif*/
#if defined(__x86_64__)
# define LPU64 "%Lu"
# define LPX64 "%#Lx"
# define LPSZ "%lu"
# define LPSSZ "%ld"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#endif
#elif (BITS_PER_LONG == 32 || __WORDSIZE == 32)
# define LPU64 "%Lu"
# define LPD64 "%Ld"
# define LPX64 "%#Lx"
# define LPSZ "%u"
# define LPSSZ "%d"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a)
+#endif
#elif (BITS_PER_LONG == 64 || __WORDSIZE == 64)
# define LPU64 "%lu"
# define LPD64 "%ld"
# define LPX64 "%#lx"
# define LPSZ "%lu"
# define LPSSZ "%ld"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#endif
#endif
#ifndef LPU64
# error "No word size defined"
#define S_PTLROUTER 0x00100000
#define S_COBD 0x00200000
#define S_IBNAL 0x00400000
+#define S_SM 0x00800000
/* If you change these values, please keep portals/utils/debug.c
* up to date! */
{"mds", "lustre/mds"},
{"mdc", "lustre/mdc"},
{"llite", "lustre/llite"},
+ {"smfs", "lustre/smfs"},
{"obdecho", "lustre/obdecho"},
{"ldlm", "lustre/ldlm"},
{"obdfilter", "lustre/obdfilter"},
{"fsfilt_ext3", "lustre/lvfs"},
{"fsfilt_extN", "lustre/lvfs"},
{"fsfilt_reiserfs", "lustre/lvfs"},
+ {"fsfilt_smfs", "lustre/lvfs"},
{"mds_ext2", "lustre/mds"},
{"mds_ext3", "lustre/mds"},
{"mds_extN", "lustre/mds"},
lustre_net.h obd_class.h obd_ost.h obd_support.h lustre_commit_confd.h \
lustre_export.h lustre_log.h obd_echo.h obd_ptlbd.h obd_trace.h \
lustre_compat25.h lustre_fsfilt.h lustre_import.h lustre_mds.h obd.h \
- lvfs.h lvfs_linux.h lustre_cfg.h lustre_lite.h lustre_idl.h
+ lvfs.h lvfs_linux.h lustre_cfg.h lustre_lite.h lustre_idl.h lustre_smfs.h
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
+ * Copyright (C) 2001-2004 Cluster File Systems, Inc. <info@clusterfs.com>
*
* This file is part of Lustre, http://www.lustre.org.
*
#ifdef __KERNEL__
#include <linux/obd.h>
+#include <linux/lustre_log.h>
#include <linux/obd_class.h>
typedef void (*fsfilt_cb_t)(struct obd_device *obd, __u64 last_rcvd,
int (* fs_set_md)(struct inode *inode, void *handle, void *md,
int size);
int (* fs_get_md)(struct inode *inode, void *md, int size);
+
+ /* this method is needed to make IO operation fsfilt nature depend. */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ int (* fs_send_bio)(struct inode *inode, struct bio *bio);
+#else
+ int (* fs_send_bio)(struct inode *inode, struct kiobuf *bio);
+#endif
+
+ /* methods for getting page from backing fs and putting page there
+ * during IO. Used on OST. */
+ int (* fs_putpage)(struct inode *inode, struct page *page);
+ struct page *(* fs_getpage)(struct inode *inode, long int index);
+
ssize_t (* fs_readpage)(struct file *file, char *buf, size_t count,
loff_t *offset);
- int (* fs_add_journal_cb)(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func,
+ int (* fs_add_journal_cb)(struct obd_device *obd, struct super_block *sb,
+ __u64 last_rcvd, void *handle, fsfilt_cb_t cb_func,
void *cb_data);
int (* fs_statfs)(struct super_block *sb, struct obd_statfs *osfs);
int (* fs_sync)(struct super_block *sb);
int force_sync);
int (* fs_read_record)(struct file *, void *, int size, loff_t *);
int (* fs_setup)(struct super_block *sb);
+
+ int (* fs_set_xattr)(struct inode *inode, void *handle, char *name,
+ void *buffer, int buffer_size);
+ int (* fs_get_xattr)(struct inode *inode, char *name,
+ void *buffer, int buffer_size);
+
int (* fs_get_op_len)(int, struct fsfilt_objinfo *, int);
};
#define FSFILT_OP_SETATTR 8
#define FSFILT_OP_LINK 9
#define FSFILT_OP_CANCEL_UNLINK 10
-
-static inline void *fsfilt_start_log(struct obd_device *obd,
- struct inode *inode, int op,
- struct obd_trans_info *oti, int logs)
+#define FSFILT_OP_NOOP 15
+
+/* XXX BUG 3188 -- must return to one set of opcodes */
+#define KML_UNLINK 0x11
+#define KML_RMDIR 0x12
+#define KML_RENAME 0x13
+#define KML_CREATE 0x14
+#define KML_MKDIR 0x15
+#define KML_SYMLINK 0x16
+#define KML_MKNOD 0x17
+#define KML_LINK 0x19
+
+#define CACHE_UNLINK 0x21
+#define CACHE_RMDIR 0x22
+#define CACHE_RENAME 0x23
+#define CACHE_CREATE 0x24
+#define CACHE_MKDIR 0x25
+#define CACHE_SYMLINK 0x26
+#define CACHE_MKNOD 0x27
+#define CACHE_LINK 0x29
+#define CACHE_NOOP 0x2f
+
+#define KML_CACHE_UNLINK 0x31
+#define KML_CACHE_RMDIR 0x32
+#define KML_CACHE_RENAME 0x33
+#define KML_CACHE_CREATE 0x34
+#define KML_CACHE_MKDIR 0x35
+#define KML_CACHE_SYMLINK 0x36
+#define KML_CACHE_MKNOD 0x37
+#define KML_CACHE_LINK 0x39
+#define KML_CACHE_NOOP 0x3f
+
+static inline void *
+fsfilt_start_ops(struct fsfilt_operations *ops, struct inode *inode,
+ int op, struct obd_trans_info *oti, int logs)
{
unsigned long now = jiffies;
void *parent_handle = oti ? oti->oti_handle : NULL;
- void *handle = obd->obd_fsops->fs_start(inode, op, parent_handle, logs);
- CDEBUG(D_INFO, "started handle %p (%p)\n", handle, parent_handle);
+ void *handle = ops->fs_start(inode, op, parent_handle, logs);
+ CDEBUG(D_HA, "started handle %p (%p)\n", handle, parent_handle);
if (oti != NULL) {
if (parent_handle == NULL) {
return handle;
}
-static inline void *fsfilt_start(struct obd_device *obd, struct inode *inode,
- int op, struct obd_trans_info *oti)
+static inline void *
+fsfilt_start_log(struct obd_device *obd, struct inode *inode,
+ int op, struct obd_trans_info *oti, int logs)
+{
+ return fsfilt_start_ops(obd->obd_fsops, inode, op, oti, logs);
+}
+
+static inline void *
+fsfilt_start(struct obd_device *obd, struct inode *inode,
+ int op, struct obd_trans_info *oti)
+{
+ return fsfilt_start_ops(obd->obd_fsops, inode, op, oti, 0);
+}
+
+static inline void *
+llog_fsfilt_start(struct llog_ctxt *ctxt, struct inode *inode,
+ int op, struct obd_trans_info *oti)
+{
+ return fsfilt_start_ops(ctxt->loc_fsops, inode, op, oti, 1);
+}
+
+static inline int
+fsfilt_commit_ops(struct fsfilt_operations *ops, struct inode *inode,
+ void *handle, int force_sync)
+{
+ unsigned long now = jiffies;
+ int rc = ops->fs_commit(inode, handle, force_sync);
+ CDEBUG(D_HA, "committing handle %p\n", handle);
+
+ if (time_after(jiffies, now + 15 * HZ))
+ CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
+
+ return rc;
+}
+
+static inline int
+fsfilt_commit(struct obd_device *obd, struct inode *inode,
+ void *handle, int force_sync)
+{
+ return fsfilt_commit_ops(obd->obd_fsops, inode, handle, force_sync);
+}
+
+static inline int
+llog_fsfilt_commit(struct llog_ctxt *ctxt, struct inode *inode,
+ void *handle, int force_sync)
{
- return fsfilt_start_log(obd, inode, op, oti, 0);
+ return fsfilt_commit_ops(ctxt->loc_fsops, inode, handle, force_sync);
}
-static inline void *fsfilt_brw_start_log(struct obd_device *obd,
- int objcount,
- struct fsfilt_objinfo *fso,
- int niocount, struct niobuf_local *nb,
- struct obd_trans_info *oti, int logs)
+static inline void *
+fsfilt_brw_start_log(struct obd_device *obd, int objcount,
+ struct fsfilt_objinfo *fso, int niocount,
+ struct niobuf_local *nb, struct obd_trans_info *oti,
+ int logs)
{
unsigned long now = jiffies;
void *parent_handle = oti ? oti->oti_handle : NULL;
return handle;
}
-static inline void *fsfilt_brw_start(struct obd_device *obd, int objcount,
- struct fsfilt_objinfo *fso, int niocount,
- struct niobuf_local *nb,
- struct obd_trans_info *oti)
+static inline void *
+fsfilt_brw_start(struct obd_device *obd, int objcount,
+ struct fsfilt_objinfo *fso, int niocount,
+ struct niobuf_local *nb, struct obd_trans_info *oti)
{
return fsfilt_brw_start_log(obd, objcount, fso, niocount, nb, oti, 0);
}
-static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode,
- void *handle, int force_sync)
-{
- unsigned long now = jiffies;
- int rc = obd->obd_fsops->fs_commit(inode, handle, force_sync);
- CDEBUG(D_INFO, "committing handle %p\n", handle);
-
- if (time_after(jiffies, now + 15 * HZ))
- CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
-
- return rc;
-}
-
-static inline int fsfilt_commit_async(struct obd_device *obd,
- struct inode *inode, void *handle,
- void **wait_handle)
+static inline int
+fsfilt_commit_async(struct obd_device *obd, struct inode *inode,
+ void *handle, void **wait_handle)
{
unsigned long now = jiffies;
int rc = obd->obd_fsops->fs_commit_async(inode, handle, wait_handle);
return rc;
}
-static inline int fsfilt_commit_wait(struct obd_device *obd,
- struct inode *inode, void *handle)
+static inline int
+fsfilt_commit_wait(struct obd_device *obd, struct inode *inode, void *handle)
{
unsigned long now = jiffies;
int rc = obd->obd_fsops->fs_commit_wait(inode, handle);
return rc;
}
-static inline int fsfilt_setattr(struct obd_device *obd, struct dentry *dentry,
- void *handle, struct iattr *iattr,int do_trunc)
+static inline int
+fsfilt_setattr(struct obd_device *obd, struct dentry *dentry,
+ void *handle, struct iattr *iattr, int do_trunc)
{
unsigned long now = jiffies;
int rc;
return rc;
}
-static inline int fsfilt_iocontrol(struct obd_device *obd, struct inode *inode,
- struct file *file, unsigned int cmd,
- unsigned long arg)
+static inline int
+fsfilt_iocontrol(struct obd_device *obd, struct inode *inode,
+ struct file *file, unsigned int cmd,
+ unsigned long arg)
{
return obd->obd_fsops->fs_iocontrol(inode, file, cmd, arg);
}
-static inline int fsfilt_set_md(struct obd_device *obd, struct inode *inode,
- void *handle, void *md, int size)
+static inline int fsfilt_setup(struct obd_device *obd,
+ struct super_block *fs)
+{
+ if (obd->obd_fsops->fs_setup)
+ return obd->obd_fsops->fs_setup(fs);
+
+ return 0;
+}
+
+static inline int
+fsfilt_set_md(struct obd_device *obd, struct inode *inode,
+ void *handle, void *md, int size)
{
return obd->obd_fsops->fs_set_md(inode, handle, md, size);
}
-static inline int fsfilt_get_md(struct obd_device *obd, struct inode *inode,
- void *md, int size)
+static inline int
+fsfilt_get_md(struct obd_device *obd, struct inode *inode,
+ void *md, int size)
{
return obd->obd_fsops->fs_get_md(inode, md, size);
}
-static inline ssize_t fsfilt_readpage(struct obd_device *obd,
- struct file *file, char *buf,
- size_t count, loff_t *offset)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static inline int
+fsfilt_send_bio(struct obd_device *obd, struct inode *inode,
+ struct bio *bio)
+#else
+static inline int
+fsfilt_send_bio(struct obd_device *obd, struct inode *inode,
+ struct kiobuf *bio)
+#endif
+{
+ return obd->obd_fsops->fs_send_bio(inode, bio);
+}
+
+static inline int
+fsfilt_putpage(struct obd_device *obd, struct inode *inode,
+ struct page *page)
+{
+ int rc = 0;
+ struct filter_obd *filter;
+ unsigned long now = jiffies;
+
+ LASSERT(obd != NULL);
+ LASSERT(inode != NULL);
+ LASSERT(page != NULL);
+
+ filter = &obd->u.filter;
+
+ if (!obd->obd_fsops->fs_putpage)
+ return -ENOSYS;
+
+ CDEBUG(D_INFO, "putpage %lx\n", page->index);
+
+ rc = obd->obd_fsops->fs_putpage(inode, page);
+
+ if (time_after(jiffies, now + 15 * HZ))
+ CERROR("long putpage time %lus\n", (jiffies - now) / HZ);
+
+ return rc;
+}
+
+static inline struct page *
+fsfilt_getpage(struct obd_device *obd, struct inode *inode,
+ unsigned long index)
+{
+ struct page *page;
+ unsigned long now = jiffies;
+
+ LASSERT(obd != NULL);
+ LASSERT(inode != NULL);
+
+ if (!obd->obd_fsops->fs_getpage)
+ return ERR_PTR(-ENOSYS);
+
+ CDEBUG(D_INFO, "getpage %lx\n", index);
+
+ page = obd->obd_fsops->fs_getpage(inode, index);
+
+ if (time_after(jiffies, now + 15 * HZ))
+ CERROR("long getpage time %lus\n", (jiffies - now) / HZ);
+
+ return page;
+}
+
+static inline ssize_t
+fsfilt_readpage(struct obd_device *obd, struct file *file, char *buf,
+ size_t count, loff_t *offset)
{
return obd->obd_fsops->fs_readpage(file, buf, count, offset);
}
-static inline int fsfilt_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
- void *handle, fsfilt_cb_t cb_func,
- void *cb_data)
+static inline int
+fsfilt_add_journal_cb(struct obd_device *obd, struct super_block *sb,
+ __u64 last_rcvd, void *handle, fsfilt_cb_t cb_func,
+ void *cb_data)
{
- return obd->obd_fsops->fs_add_journal_cb(obd, last_rcvd,
- handle, cb_func, cb_data);
+ return obd->obd_fsops->fs_add_journal_cb(obd, sb, last_rcvd, handle,
+ cb_func, cb_data);
}
/* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
-static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
- unsigned long max_age)
+static inline int
+fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
+ unsigned long max_age)
{
int rc = 0;
return rc;
}
-static inline int fsfilt_sync(struct obd_device *obd, struct super_block *sb)
+static inline int
+fsfilt_sync(struct obd_device *obd, struct super_block *sb)
{
return obd->obd_fsops->fs_sync(sb);
}
-static inline int fsfilt_map_inode_page(struct obd_device *obd,
- struct inode *inode, struct page *page,
- unsigned long *blocks, int *created,
- int create)
+static inline int
+fsfilt_map_inode_page(struct obd_device *obd, struct inode *inode,
+ struct page *page, unsigned long *blocks,
+ int *created, int create)
{
- return obd->obd_fsops->fs_map_inode_page(inode, page, blocks, created,
- create);
+ return obd->obd_fsops->fs_map_inode_page(inode, page, blocks,
+ created, create);
}
-static inline int fs_prep_san_write(struct obd_device *obd,
- struct inode *inode,
- long *blocks,
- int nblocks,
- loff_t newsize)
+static inline int
+fs_prep_san_write(struct obd_device *obd, struct inode *inode,
+ long *blocks, int nblocks, loff_t newsize)
{
return obd->obd_fsops->fs_prep_san_write(inode, blocks,
nblocks, newsize);
}
-static inline int fsfilt_read_record(struct obd_device *obd, struct file *file,
- void *buf, loff_t size, loff_t *offs)
+static inline int
+fsfilt_read_record(struct obd_device *obd, struct file *file,
+ void *buf, loff_t size, loff_t *offs)
{
return obd->obd_fsops->fs_read_record(file, buf, size, offs);
}
-static inline int fsfilt_write_record(struct obd_device *obd, struct file *file,
- void *buf, loff_t size, loff_t *offs,
- int force_sync)
+static inline int
+fsfilt_write_record(struct obd_device *obd, struct file *file,
+ void *buf, loff_t size, loff_t *offs, int force_sync)
{
- return obd->obd_fsops->fs_write_record(file, buf, size,offs,force_sync);
+ return obd->obd_fsops->fs_write_record(file, buf, size, offs,
+ force_sync);
}
-static inline int fsfilt_setup(struct obd_device *obd, struct super_block *fs)
+static inline int
+llog_fsfilt_write_record(struct llog_ctxt *ctxt, struct file *file,
+ void *buf, loff_t size, loff_t *offs,
+ int force_sync)
{
- if (obd->obd_fsops->fs_setup)
- return obd->obd_fsops->fs_setup(fs);
- return 0;
+ return ctxt->loc_fsops->fs_write_record(file, buf, size, offs,
+ force_sync);
+}
+
+static inline int
+llog_fsfilt_read_record(struct llog_ctxt *ctxt, struct file *file,
+ void *buf, loff_t size, loff_t *offs)
+{
+ return ctxt->loc_fsops->fs_read_record(file, buf, size, offs);
}
#endif /* __KERNEL__ */
# include <linux/types.h>
# include <linux/list.h>
# include <linux/string.h> /* for strncpy, below */
-# include <linux/fs.h> /* to check for FMODE_EXEC, lest we redefine */
+# include <linux/fs.h> /* to check for FMODE_EXEC, dev_t, lest we redefine */
#else
#ifdef __CYGWIN__
# include <sys/types.h>
MDS_DONE_WRITING = 45,
MDS_LAST_OPC
} mds_cmd_t;
+
#define MDS_FIRST_OPC MDS_GETATTR
/*
* Do not exceed 63
*/
-#define REINT_SETATTR 1
-#define REINT_CREATE 2
-#define REINT_LINK 3
-#define REINT_UNLINK 4
-#define REINT_RENAME 5
-#define REINT_OPEN 6
-#define REINT_MAX 6
+#define REINT_SETATTR 1
+#define REINT_CREATE 2
+#define REINT_LINK 3
+#define REINT_UNLINK 4
+#define REINT_RENAME 5
+#define REINT_OPEN 6
+#define REINT_CLOSE 7
+#define REINT_WRITE 8
+#define REINT_MAX 8
/* the disposition of the intent outlines what was executed */
#define DISP_IT_EXECD 1
extern void lustre_swab_mds_body (struct mds_body *b);
-/* MDS update records */
-
-//struct mds_update_record_hdr {
-// __u32 ur_opcode;
-//};
-
struct mds_rec_setattr {
__u32 sa_opcode;
__u32 sa_fsuid;
LLOG_GEN_REC = 0x10640000,
LLOG_HDR_MAGIC = 0x10645539,
LLOG_LOGID_MAGIC = 0x1064553b,
+ SMFS_UPDATE_REC = 0x10650000,
+ CACHE_LRU_REC = 0x10660000,
} llog_op_type;
/* Log record header - stored in little endian order.
struct llog_gen {
__u64 mnt_cnt;
__u64 conn_cnt;
-} __attribute__((packed));
+};
struct llog_gen_rec {
struct llog_rec_hdr lgr_hdr;
struct llog_gen lgr_gen;
struct llog_rec_tail lgr_tail;
+} __attribute__((packed));
+
+struct llog_lru_rec {
+ struct llog_rec_hdr llr_hdr;
+ struct ll_fid llr_cfid;
+ struct ll_fid llr_pfid;
+ struct llog_rec_tail llr_tail;
+} __attribute__((packed));
+
+/* got from mds_update_record. FIXME: maybe some attribute in reint_record and
+ update_record will be changed later. */
+/* XXX BUG 3188 -- must return to one set of structures. */
+
+struct update_record {
+ __u32 ur_opcode;
+ __u32 ur_fsuid;
+ __u32 ur_fsgid;
+ dev_t ur_rdev;
+ struct iattr ur_iattr;
+ struct iattr ur_pattr;
+ __u32 ur_flags;
+ __u32 ur_len;
};
+struct reint_record {
+ struct update_record u_rec;
+ char *rec_data1;
+ int rec1_size;
+ char *rec_data2;
+ int rec2_size;
+};
+struct llog_smfs_rec {
+ struct llog_rec_hdr lsr_hdr;
+ struct update_record lsr_rec;
+ struct llog_rec_tail lsr_tail;
+};
+
/* On-disk header structure of each log object, stored in little endian order */
#define LLOG_CHUNK_SIZE 8192
#define LLOG_HEADER_SIZE (96)
__u32 llh_size;
__u32 llh_flags;
__u32 llh_cat_idx;
- /* for a catlog the first plain slot is next to it */
+ /* for a catalog the first plain slot is next to it */
struct obd_uuid llh_tgtuuid;
__u32 llh_reserved[LLOG_HEADER_SIZE/sizeof(__u32) - 23];
__u32 llh_bitmap[LLOG_BITMAP_BYTES/sizeof(__u32)];
LLOG_ORIGIN_HANDLE_CLOSE = 505,
LLOG_ORIGIN_CONNECT = 506,
LLOG_CATINFO = 507, /* for lfs catinfo */
+ LLOG_ORIGIN_HANDLE_PREV_BLOCK = 508,
};
struct llogd_body {
#include <linux/lustre_idl.h>
#include <linux/lustre_cfg.h>
-#define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
-#define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#if BITS_PER_LONG > 32 && !defined(__x86_64__)
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#endif
+#else
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a)
+#endif
+#endif
#ifndef LPU64
/* x86_64 has 64bit longs and defines u64 as long long */
#define LOG_NAME_LIMIT(logname, name) \
snprintf(logname, sizeof(logname), "LOGS/%s", name)
+#define LLOG_EEMPTY 4711
struct plain_handle_data {
struct list_head phd_entry;
} u;
};
-#define LLOG_EEMPTY 4711
-
/* llog.c - general API */
typedef int (*llog_cb_t)(struct llog_handle *, struct llog_rec_hdr *, void *);
+struct llog_handle *llog_alloc_handle(void);
+void llog_free_handle(struct llog_handle *handle);
+int llog_cancel_rec(struct llog_handle *loghandle, int index);
int llog_init_handle(struct llog_handle *handle, int flags,
struct obd_uuid *uuid);
+int llog_close(struct llog_handle *cathandle);
int llog_process(struct llog_handle *loghandle, llog_cb_t cb,
void *data, void *catdata);
-extern struct llog_handle *llog_alloc_handle(void);
-extern void llog_free_handle(struct llog_handle *handle);
-extern int llog_close(struct llog_handle *cathandle);
-extern int llog_cancel_rec(struct llog_handle *loghandle, int index);
+int llog_reverse_process(struct llog_handle *loghandle, llog_cb_t cb,
+ void *data, void *catdata);
/* llog_cat.c - catalog api */
struct llog_process_data {
struct llog_process_cat_data {
int first_idx;
int last_idx;
- /* to process catlog across zero record */
+ /* to process catalog across zero record */
};
+int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
+ struct llog_logid *logid);
int llog_cat_put(struct llog_handle *cathandle);
int llog_cat_add_rec(struct llog_handle *cathandle, struct llog_rec_hdr *rec,
struct llog_cookie *reccookie, void *buf);
int llog_cat_cancel_records(struct llog_handle *cathandle, int count,
struct llog_cookie *cookies);
int llog_cat_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data);
+int llog_cat_reverse_process(struct llog_handle *cat_llh, llog_cb_t cb, void *data);
int llog_cat_set_first_idx(struct llog_handle *cathandle, int index);
-/* llog_obd.c */
-int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
- int count, struct llog_logid *logid,struct llog_operations *op);
-int llog_cleanup(struct llog_ctxt *);
-int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp);
-int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
- struct lov_stripe_md *lsm, struct llog_cookie *logcookies,
- int numcookies);
-int llog_cancel(struct llog_ctxt *, struct lov_stripe_md *lsm,
- int count, struct llog_cookie *cookies, int flags);
+int llog_catalog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *reccookie, int, void *data);
+int llog_catalog_cancel(struct llog_ctxt *ctxt, int count, struct llog_cookie *,
+ int flags, void *data);
+int llog_catalog_setup(struct llog_ctxt **res, char *name, struct lvfs_run_ctxt *,
+ struct fsfilt_operations *fsops, struct dentry *logs_de,
+ struct dentry *objects_de);
+int llog_catalog_cleanup(struct llog_ctxt *ctxt);
+int llog_cat_half_bottom(struct llog_cookie *, struct llog_handle *);
+
+/* llog_lvfs.c */
+int llog_get_cat_list(struct lvfs_run_ctxt *, struct fsfilt_operations *,
+ char *name, int count, struct llog_catid *idarray);
+int llog_put_cat_list(struct lvfs_run_ctxt *, struct fsfilt_operations *,
+ char *name, int count, struct llog_catid *idarray);
+extern struct llog_operations llog_lvfs_ops;
+/* llog_obd.c - obd llog api */
+int obd_llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
+ int count, struct llog_logid *logid,struct llog_operations *op);
+int obd_llog_cleanup(struct llog_ctxt *);
int llog_obd_origin_setup(struct obd_device *obd, int index,
struct obd_device *disk_obd, int count,
struct llog_logid *logid);
-int llog_obd_origin_cleanup(struct llog_ctxt *ctxt);
-int llog_obd_origin_add(struct llog_ctxt *ctxt,
- struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies);
-
-int llog_cat_initialize(struct obd_device *obd, int count);
+int obd_llog_cat_initialize(struct obd_device *obd, int count, char *name);
int obd_llog_init(struct obd_device *obd, struct obd_device *disk_obd,
int count, struct llog_catid *logid);
/* llog_ioctl.c */
int llog_ioctl(struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data);
-int llog_catlog_list(struct obd_device *obd, int count,
+int llog_catalog_list(struct obd_device *obd, int count,
struct obd_ioctl_data *data);
/* llog_net.c */
int llog_handle_connect(struct ptlrpc_request *req);
/* recov_thread.c */
-int llog_obd_repl_cancel(struct llog_ctxt *ctxt,
- struct lov_stripe_md *lsm, int count,
- struct llog_cookie *cookies, int flags);
+int llog_obd_repl_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data);
+
int llog_obd_repl_sync(struct llog_ctxt *ctxt, struct obd_export *exp);
int llog_repl_connect(struct llog_ctxt *ctxt, int count,
struct llog_logid *logid, struct llog_gen *gen,
struct obd_uuid *uuid);
struct llog_operations {
+ int (*lop_setup)(struct obd_device *obd, int ctxt_idx,
+ struct obd_device *disk_obd, int count,
+ struct llog_logid *logid);
+ int (*lop_cleanup)(struct llog_ctxt *ctxt);
+ int (*lop_create)(struct llog_ctxt *ctxt, struct llog_handle **,
+ struct llog_logid *logid, char *name);
+ int (*lop_destroy)(struct llog_handle *handle);
+ int (*lop_close)(struct llog_handle *handle);
+
+ int (*lop_read_header)(struct llog_handle *handle);
+ int (*lop_add)(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *logcookies,
+ int numcookies, void *data);
+ int (*lop_cancel)(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data);
int (*lop_write_rec)(struct llog_handle *loghandle,
struct llog_rec_hdr *rec,
struct llog_cookie *logcookies, int numcookies,
void *, int idx);
- int (*lop_destroy)(struct llog_handle *handle);
int (*lop_next_block)(struct llog_handle *h, int *curr_idx,
int next_idx, __u64 *offset, void *buf, int len);
- int (*lop_create)(struct llog_ctxt *ctxt, struct llog_handle **,
- struct llog_logid *logid, char *name);
- int (*lop_close)(struct llog_handle *handle);
- int (*lop_read_header)(struct llog_handle *handle);
+ int (*lop_prev_block)(struct llog_handle *h,
+ int prev_idx, void *buf, int len);
- int (*lop_setup)(struct obd_device *obd, int ctxt_idx,
- struct obd_device *disk_obd, int count,
- struct llog_logid *logid);
+ /* XXX add 2 more: commit callbacks and llog recovery functions */
int (*lop_sync)(struct llog_ctxt *ctxt, struct obd_export *exp);
- int (*lop_cleanup)(struct llog_ctxt *ctxt);
- int (*lop_add)(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
- struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies);
- int (*lop_cancel)(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm,
- int count, struct llog_cookie *cookies, int flags);
int (*lop_connect)(struct llog_ctxt *ctxt, int count,
struct llog_logid *logid, struct llog_gen *gen,
struct obd_uuid *uuid);
- /* XXX add 2 more: commit callbacks and llog recovery functions */
};
-/* llog_lvfs.c */
-extern struct llog_operations llog_lvfs_ops;
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray);
-
struct llog_ctxt {
- int loc_idx; /* my index the obd array of ctxt's */
- struct llog_gen loc_gen;
+ /* needed for lvfs based log */
+ struct llog_handle *loc_handle;
+ struct llog_operations *loc_logops;
+ struct fsfilt_operations *loc_fsops;
+ struct dentry *loc_logs_dir;
+ struct dentry *loc_objects_dir;
+ struct lvfs_run_ctxt *loc_lvfs_ctxt;
+
struct obd_device *loc_obd; /* points back to the containing obd*/
+ struct llog_gen loc_gen;
+ int loc_idx; /* my index the obd array of ctxt's */
+
struct obd_export *loc_exp;
struct obd_import *loc_imp; /* to use in RPC's: can be backward
pointing import */
- struct llog_operations *loc_logops;
- struct llog_handle *loc_handle;
struct llog_canceld_ctxt *loc_llcd;
struct semaphore loc_sem; /* protects loc_llcd */
- void *llog_proc_cb;
+ void *loc_proc_cb; /* cb for recovery */
};
static inline void llog_gen_init(struct llog_ctxt *ctxt)
#define LLOG_GEN_INC(gen) ((gen).conn_cnt) ++
#define LLOG_PROC_BREAK 0x0001
-static inline int llog_obd2ops(struct llog_ctxt *ctxt,
+static inline int llog_ctxt2ops(struct llog_ctxt *ctxt,
struct llog_operations **lop)
{
- if (ctxt == NULL)
+ if (ctxt == NULL)
return -ENOTCONN;
*lop = ctxt->loc_logops;
if (loghandle == NULL)
return -EINVAL;
- return llog_obd2ops(loghandle->lgh_ctxt, lop);
+ return llog_ctxt2ops(loghandle->lgh_ctxt, lop);
}
static inline int llog_data_len(int len)
return obd->obd_llog_ctxt[index];
}
-static inline int llog_write_rec(struct llog_handle *handle,
- struct llog_rec_hdr *rec,
- struct llog_cookie *logcookies,
- int numcookies, void *buf, int idx)
+static inline int llog_create(struct llog_ctxt *ctxt, struct llog_handle **res,
+ struct llog_logid *logid, char *name)
{
struct llog_operations *lop;
- int rc, buflen;
+ int rc;
ENTRY;
- rc = llog_handle2ops(handle, &lop);
+ rc = llog_ctxt2ops(ctxt, &lop);
if (rc)
RETURN(rc);
- if (lop->lop_write_rec == NULL)
+ if (lop->lop_create == NULL)
RETURN(-EOPNOTSUPP);
- if (buf)
- buflen = rec->lrh_len + sizeof(struct llog_rec_hdr)
- + sizeof(struct llog_rec_tail);
- else
- buflen = rec->lrh_len;
- LASSERT(size_round(buflen) == buflen);
+ rc = lop->lop_create(ctxt, res, logid, name);
+ RETURN(rc);
+}
- rc = lop->lop_write_rec(handle, rec, logcookies, numcookies, buf, idx);
+static inline int llog_destroy(struct llog_handle *handle)
+{
+ struct llog_operations *lop;
+ int rc;
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_destroy == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ rc = lop->lop_destroy(handle);
RETURN(rc);
}
RETURN(rc);
}
-static inline int llog_destroy(struct llog_handle *handle)
+static inline int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *logcookies,
+ int numcookies, void *data)
{
struct llog_operations *lop;
int rc;
ENTRY;
- rc = llog_handle2ops(handle, &lop);
+ rc = llog_ctxt2ops(ctxt, &lop);
if (rc)
RETURN(rc);
- if (lop->lop_destroy == NULL)
+ if (lop->lop_add == NULL)
RETURN(-EOPNOTSUPP);
- rc = lop->lop_destroy(handle);
+ rc = lop->lop_add(ctxt, rec, buf, logcookies, numcookies, data);
RETURN(rc);
}
-#if 0
-static inline int llog_cancel(struct obd_export *exp,
- struct lov_stripe_md *lsm, int count,
- struct llog_cookie *cookies, int flags)
+static inline int llog_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data)
{
struct llog_operations *lop;
int rc;
ENTRY;
- rc = llog_handle2ops(loghandle, &lop);
+ rc = llog_ctxt2ops(ctxt, &lop);
if (rc)
RETURN(rc);
if (lop->lop_cancel == NULL)
RETURN(-EOPNOTSUPP);
- rc = lop->lop_cancel(exp, lsm, count, cookies, flags);
+ rc = lop->lop_cancel(ctxt, count, cookies, flags, data);
+ RETURN(rc);
+}
+
+static inline int llog_write_rec(struct llog_handle *handle,
+ struct llog_rec_hdr *rec,
+ struct llog_cookie *logcookies,
+ int numcookies, void *buf, int idx)
+{
+ struct llog_operations *lop;
+ int rc, buflen;
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_write_rec == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ if (buf)
+ buflen = le32_to_cpu(rec->lrh_len) + sizeof(struct llog_rec_hdr)
+ + sizeof(struct llog_rec_tail);
+ else
+ buflen = le32_to_cpu(rec->lrh_len);
+ LASSERT(size_round(buflen) == buflen);
+
+ rc = lop->lop_write_rec(handle, rec, logcookies, numcookies, buf, idx);
RETURN(rc);
}
-#endif
-static inline int llog_next_block(struct llog_handle *loghandle, int *cur_idx,
- int next_idx, __u64 *cur_offset, void *buf,
+static inline int llog_next_block(struct llog_handle *loghandle, int *curr_idx,
+ int next_idx, __u64 *curr_offset, void *buf,
int len)
{
struct llog_operations *lop;
if (lop->lop_next_block == NULL)
RETURN(-EOPNOTSUPP);
- rc = lop->lop_next_block(loghandle, cur_idx, next_idx, cur_offset, buf,
+ rc = lop->lop_next_block(loghandle, curr_idx, next_idx, curr_offset, buf,
len);
RETURN(rc);
}
-static inline int llog_create(struct llog_ctxt *ctxt, struct llog_handle **res,
- struct llog_logid *logid, char *name)
+static inline int llog_prev_block(struct llog_handle *loghandle,
+ int prev_idx, void *buf, int len)
{
struct llog_operations *lop;
int rc;
ENTRY;
- rc = llog_obd2ops(ctxt, &lop);
+ rc = llog_handle2ops(loghandle, &lop);
if (rc)
RETURN(rc);
- if (lop->lop_create == NULL)
+ if (lop->lop_prev_block == NULL)
RETURN(-EOPNOTSUPP);
- rc = lop->lop_create(ctxt, res, logid, name);
+ rc = lop->lop_prev_block(loghandle, prev_idx, buf, len);
RETURN(rc);
}
int rc;
ENTRY;
- rc = llog_obd2ops(ctxt, &lop);
+ rc = llog_ctxt2ops(ctxt, &lop);
if (rc)
RETURN(rc);
if (lop->lop_connect == NULL)
RETURN(rc);
}
+static inline int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp)
+{
+ struct llog_operations *lop;
+ int rc;
+ ENTRY;
+
+ rc = llog_ctxt2ops(ctxt, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_sync == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ rc = lop->lop_sync(ctxt, exp);
+ RETURN(rc);
+}
+
#endif
int ur_cookielen;
struct llog_cookie *ur_logcookies;
struct iattr ur_iattr;
- struct obd_ucred ur_uc;
+ struct lvfs_ucred ur_uc;
__u64 ur_rdev;
__u32 ur_mode;
__u64 ur_time;
__u32 ur_flags;
};
-#define ur_fsuid ur_uc.ouc_fsuid
-#define ur_fsgid ur_uc.ouc_fsgid
-#define ur_cap ur_uc.ouc_cap
-#define ur_suppgid1 ur_uc.ouc_suppgid1
-#define ur_suppgid2 ur_uc.ouc_suppgid2
+#define ur_fsuid ur_uc.luc_fsuid
+#define ur_fsgid ur_uc.luc_fsgid
+#define ur_cap ur_uc.luc_cap
+#define ur_suppgid1 ur_uc.luc_suppgid1
+#define ur_suppgid2 ur_uc.luc_suppgid2
/* i_attr_flags holds the open count in the inode in 2.4 */
//XXX Alex implement on 2.4 with i_attr_flags and find soln for 2.5 please
/* ptlrpc/llog_server.c */
int llog_origin_handle_create(struct ptlrpc_request *req);
+int llog_origin_handle_prev_block(struct ptlrpc_request *req);
int llog_origin_handle_next_block(struct ptlrpc_request *req);
int llog_origin_handle_read_header(struct ptlrpc_request *req);
int llog_origin_handle_close(struct ptlrpc_request *req);
--- /dev/null
+#ifndef __LUSTRE_SMFS_H
+#define __LUSTRE_SMFS_H
+
+struct smfs_inode_info {
+ struct inode *smi_inode;
+ __u32 smi_flags;
+};
+
+struct journal_operations {
+ void *(*tr_start)(struct inode *, int op);
+ void (*tr_commit)(void *handle);
+};
+
+struct sm_operations {
+ /* 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 smfs_super_info {
+ struct super_block *smsi_sb;
+ struct vfsmount *smsi_mnt; /* mount the cache kern with
+ * kern_do_mount (like MDS) */
+ struct fsfilt_operations *sm_cache_fsfilt; /* fsfilt operations */
+ struct fsfilt_operations *sm_fsfilt; /* fsfilt operations */
+ struct sm_operations *sm_ops; /* cache ops for set cache
+ * inode ops */
+
+ struct lvfs_run_ctxt *smsi_ctxt;
+ struct llog_ctxt *smsi_rec_log; /* smfs kml llog */
+ struct dentry *smsi_logs_dir;
+ struct dentry *smsi_objects_dir;
+ struct dentry *smsi_delete_dir; /* for delete inode dir */
+ char *cache_fs_type; /* cache file system type */
+ char *fs_type; /* file system type */
+ __u32 flags; /* flags */
+ __u32 ops_check;
+};
+
+#define SMFS_FILE_TYPE "smfs"
+#define SMFS_FILE_MAGIC 0x19760218
+
+struct smfs_file_info {
+ struct file *c_file;
+ int magic;
+};
+
+struct smfs_record_extents {
+ size_t sre_count;
+ loff_t sre_off;
+};
+
+#define I2SMI(inode) ((struct smfs_inode_info *) (&(inode->u.generic_ip)))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define S2SMI(sb) ((struct smfs_super_info *) (&(sb->u.generic_sbp)))
+#define S2CSB(sb) (((struct smfs_super_info *) (&(sb->u.generic_sbp)))->smsi_sb)
+#else
+#define S2SMI(sb) ((struct smfs_super_info *) (sb->s_fs_info))
+#define S2CSB(sb) (((struct smfs_super_info *) (sb->s_fs_info))->smsi_sb)
+#endif
+
+#define I2CI(inode) (((struct smfs_inode_info*) (&(inode->u.generic_ip)))->smi_inode)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define I2CSB(inode) ((struct smfs_super_info *) (&(inode->i_sb->u.generic_sbp)))
+#else
+#define I2CSB(inode) ((struct smfs_super_info *) (inode->i_sb->s_fs_info))
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define I2FOPS(inode) (((struct smfs_super_info *) \
+ (&(inode->i_sb->u.generic_sbp)))->sm_cache_fsfilt)
+#else
+#define I2FOPS(inode) (((struct smfs_super_info *) \
+ (inode->i_sb->s_fs_info))->sm_cache_fsfilt)
+#endif
+
+#define F2SMFI(file) ((struct smfs_file_info *)((file->private_data)))
+#define F2CF(file) (((struct smfs_file_info *) ((file->private_data)))->c_file)
+
+#define SM_DO_REC 0x1
+#define SM_INIT_REC 0x2
+#define SM_CACHE_HOOK 0x4
+
+#define SMFS_DO_REC(smfs_info) (smfs_info->flags & SM_DO_REC)
+#define SMFS_SET_REC(smfs_info) (smfs_info->flags |= SM_DO_REC)
+#define SMFS_CLEAN_REC(smfs_info) (smfs_info->flags &= ~SM_DO_REC)
+
+#define SMFS_INIT_REC(smfs_info) (smfs_info->flags & SM_INIT_REC)
+#define SMFS_SET_INIT_REC(smfs_info) (smfs_info->flags |= SM_INIT_REC)
+#define SMFS_CLEAN_INIT_REC(smfs_info) (smfs_info->flags &= ~SM_INIT_REC)
+
+#define SMFS_SET_INODE_REC(inode) (I2SMI(inode)->smi_flags |= SM_DO_REC)
+#define SMFS_DO_INODE_REC(inode) (I2SMI(inode)->smi_flags & SM_DO_REC)
+#define SMFS_CLEAN_INODE_REC(inode) (I2SMI(inode)->smi_flags &= ~SM_DO_REC)
+
+#define SMFS_CACHE_HOOK(smfs_info) (smfs_info->flags & SM_CACHE_HOOK)
+#define SMFS_SET_CACHE_HOOK(smfs_info) (smfs_info->flags |= SM_CACHE_HOOK)
+#define SMFS_CLEAN_CACHE_HOOK(smfs_info) (smfs_info->flags &= ~SM_CACHE_HOOK)
+
+#define SMFS_INODE_CACHE_HOOK(inode) (I2SMI(inode)->smi_flags & SM_CACHE_HOOK)
+#define SMFS_SET_INODE_CACHE_HOOK(inode) (I2SMI(inode)->smi_flags |= SM_CACHE_HOOK)
+#define SMFS_CLEAN_INODE_CACHE_HOOK(inode) (I2SMI(inode)->smi_flags &= ~SM_CACHE_HOOK)
+
+#define LVFS_SMFS_BACK_ATTR "lvfs_back_attr"
+
+
+#define REC_COUNT_BIT 0
+#define REC_COUNT_MASK 0x01 /*0001*/
+#define REC_OP_BIT 1
+#define REC_OP_MASK 0x06 /*0110*/
+#define REC_WRITE_KML_BIT 3
+#define REC_WRITE_KML_MASK 0x08 /*1000*/
+#define REC_DEC_LINK_BIT 4
+#define REC_DEC_LINK_MASK 0x10 /*10000* different with unlink*/
+
+
+#define SET_REC_COUNT_FLAGS(flag, count_flag) \
+ (flag |= count_flag << REC_COUNT_BIT)
+#define GET_REC_COUNT_FLAGS(flag) \
+ ((flag & REC_COUNT_MASK) >> REC_COUNT_BIT)
+
+#define SET_REC_OP_FLAGS(flag, op_flag) \
+ (flag |= op_flag << REC_OP_BIT)
+#define GET_REC_OP_FLAGS(flag) \
+ ((flag & REC_OP_MASK) >> REC_OP_BIT)
+
+#define SET_REC_WRITE_KML_FLAGS(flag, op_flag) \
+ (flag |= op_flag << REC_OP_BIT)
+#define GET_REC_WRITE_KML_FLAGS(flag) \
+ ((flag & REC_WRITE_KML_MASK) >> REC_WRITE_KML_BIT)
+
+#define SET_REC_DEC_LINK_FLAGS(flag, op_flag) \
+ (flag |= op_flag << REC_DEC_LINK_BIT)
+#define GET_REC_DEC_LINK_FLAGS(flag) \
+ ((flag & REC_DEC_LINK_MASK) >> REC_DEC_LINK_BIT)
+
+#define SMFS_REC_ALL 0x1
+#define SMFS_REC_BY_COUNT 0x0
+
+#define SMFS_REINT_REC 0x1
+#define SMFS_UNDO_REC 0x2
+
+#define SMFS_WRITE_KML 0x1
+
+#define SMFS_DEC_LINK 0x1
+
+#define SMFS_DO_REINT_REC(flag) \
+ (GET_REC_OP_FLAGS(flag) == SMFS_REINT_REC)
+#define SMFS_DO_UNDO_REC(flag) \
+ (GET_REC_OP_FLAGS(flag) == SMFS_UNDO_REC)
+#define SMFS_DO_REC_ALL(flag) \
+ (GET_REC_COUNT_FLAGS(flag) == SMFS_REC_ALL)
+#define SMFS_DO_REC_BY_COUNT(flag) \
+ (GET_REC_COUNT_FLAGS(flag) == SMFS_REC_BY_COUNT)
+#define SMFS_DO_WRITE_KML(flag) \
+ (GET_REC_WRITE_KML_FLAGS(flag) == SMFS_WRITE_KML)
+#define SMFS_DO_DEC_LINK(flag) \
+ (GET_REC_DEC_LINK_FLAGS(flag) == SMFS_DEC_LINK)
+
+static inline 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_version = src_inode->i_version;
+ dst_inode->i_state = src_inode->i_state;
+ dst_inode->i_generation = src_inode->i_generation;
+
+ /* This is to make creating special files working. */
+ dst_inode->i_rdev = src_inode->i_rdev;
+}
+
+static inline 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;
+ inode->i_blocks = cache_inode->i_blocks;
+ }
+}
+
+static inline void pre_smfs_inode(struct inode *inode,
+ struct inode *cache_inode)
+{
+ if (inode && cache_inode)
+ duplicate_inode(cache_inode, inode);
+}
+
+/* instantiate a file handle to the cache file */
+static inline void duplicate_file(struct file *dst_file,
+ struct file *src_file)
+{
+ dst_file->f_pos = src_file->f_pos;
+ dst_file->f_mode = src_file->f_mode;
+ dst_file->f_flags = src_file->f_flags;
+ dst_file->f_owner = src_file->f_owner;
+ dst_file->f_vfsmnt = src_file->f_vfsmnt;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ dst_file->f_reada = src_file->f_reada;
+ dst_file->f_ramax = src_file->f_ramax;
+ dst_file->f_raend = src_file->f_raend;
+ dst_file->f_ralen = src_file->f_ralen;
+ dst_file->f_rawin = src_file->f_rawin;
+#else
+ dst_file->f_ra = src_file->f_ra;
+#endif
+}
+
+static inline void duplicate_sb(struct super_block *dst_sb,
+ struct super_block *src_sb)
+{
+ dst_sb->s_blocksize = src_sb->s_blocksize;
+ dst_sb->s_magic = src_sb->s_magic;
+ dst_sb->s_blocksize_bits = src_sb->s_blocksize_bits;
+ dst_sb->s_maxbytes = src_sb->s_maxbytes;
+}
+
+static inline void d_unalloc(struct dentry *dentry)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ list_del(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_hash);
+#else
+ hlist_del_init(&dentry->d_hash);
+#endif
+ dput(dentry); /* this will free the dentry memory */
+}
+
+static inline struct dentry *pre_smfs_dentry(struct dentry *parent_dentry,
+ struct inode *cache_inode,
+ struct dentry *dentry)
+{
+ struct dentry *cache_dentry = NULL;
+
+ cache_dentry = d_alloc(parent_dentry, &dentry->d_name);
+ if (!cache_dentry)
+ RETURN(NULL);
+ if (!parent_dentry)
+ cache_dentry->d_parent = cache_dentry;
+ if (cache_inode)
+ d_add(cache_dentry, cache_inode);
+ RETURN(cache_dentry);
+}
+
+static inline void post_smfs_dentry(struct dentry *cache_dentry)
+{
+ if (!cache_dentry)
+ return;
+ if (cache_dentry->d_inode)
+ igrab(cache_dentry->d_inode);
+ d_unalloc(cache_dentry);
+}
+#endif /* _LUSTRE_SMFS_H */
#endif
/* simple.c */
-struct obd_ucred {
- __u32 ouc_fsuid;
- __u32 ouc_fsgid;
- __u32 ouc_cap;
- __u32 ouc_suppgid1;
- __u32 ouc_suppgid2;
+struct lvfs_ucred {
+ __u32 luc_fsuid;
+ __u32 luc_fsgid;
+ __u32 luc_cap;
+ __u32 luc_suppgid1;
+ __u32 luc_suppgid2;
};
struct lvfs_callback_ops {
#define OBD_RUN_CTXT_MAGIC 0xC0FFEEAA
#define OBD_CTXT_DEBUG /* development-only debugging */
-struct obd_run_ctxt {
+struct lvfs_run_ctxt {
struct vfsmount *pwdmnt;
struct dentry *pwd;
mm_segment_t fs;
- struct obd_ucred ouc;
+ struct lvfs_ucred luc;
int ngroups;
struct lvfs_callback_ops cb_ops;
#ifdef OBD_CTXT_DEBUG
#endif
/* lvfs_common.c */
-struct dentry *lvfs_fid2dentry(struct obd_run_ctxt *, __u64, __u32, __u64 ,void *data);
+struct dentry *lvfs_fid2dentry(struct lvfs_run_ctxt *, __u64, __u32, __u64 ,void *data);
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *cred);
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *cred);
+void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *cred);
+void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *cred);
#ifdef __KERNEL__
-
+int lvfs_reint(struct super_block *sb, void *r_rec);
+int lvfs_undo(struct super_block *sb, void *r_rec);
struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode, int fix);
struct dentry *simple_mknod(struct dentry *dir, char *name, int mode, int fix);
int lustre_fread(struct file *file, void *buf, int len, loff_t *off);
#define l_filp_open filp_open
-struct obd_run_ctxt;
-struct l_file *l_dentry_open(struct obd_run_ctxt *, struct l_dentry *,
+struct lvfs_run_ctxt;
+struct l_file *l_dentry_open(struct lvfs_run_ctxt *, struct l_dentry *,
int flags);
struct l_linux_dirent {
# include <linux/mount.h>
#endif
+#include <linux/lvfs.h>
#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
#include <linux/lustre_export.h>
spinlock_t obd_osfs_lock;
struct obd_statfs obd_osfs;
unsigned long obd_osfs_age;
- struct obd_run_ctxt obd_ctxt;
+ struct lvfs_run_ctxt obd_lvfs_ctxt;
struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS];
+
struct obd_device *obd_observer;
struct obd_export *obd_self_export;
{
LASSERT(exp->exp_obd);
- return lvfs_fid2dentry(&exp->exp_obd->obd_ctxt, id_ino, gen, gr,
+ return lvfs_fid2dentry(&exp->exp_obd->obd_lvfs_ctxt, id_ino, gen, gr,
exp->exp_obd);
}
+++ /dev/null
-diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/mm.h linux-2.4.20/include/linux/mm.h
---- linux-2.4.20.orig/include/linux/mm.h 2004-02-10 11:43:10.000000000 +0200
-+++ linux-2.4.20/include/linux/mm.h 2004-03-01 13:44:45.000000000 +0200
-@@ -468,7 +468,8 @@ extern void clear_page_tables(struct mm_
- extern int fail_writepage(struct page *);
- struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
- struct file *shmem_file_setup(char * name, loff_t size);
--int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr);
-+struct page *shmem_getpage_locked(struct inode *inode, unsigned long idx);
-+struct page *shmem_getpage_unlocked(struct inode *inode, unsigned long idx);
- extern void shmem_lock(struct file * file, int lock);
- extern int shmem_zero_setup(struct vm_area_struct *);
-
-diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/shmem_fs.h linux-2.4.20/include/linux/shmem_fs.h
---- linux-2.4.20.orig/include/linux/shmem_fs.h 2004-02-10 18:39:17.000000000 +0200
-+++ linux-2.4.20/include/linux/shmem_fs.h 2004-02-23 12:40:28.000000000 +0200
-@@ -7,6 +7,9 @@
-
- #define SHMEM_NR_DIRECT 16
-
-+#define SHMEM_MOUNT_IOPEN 0x8000 /* Allow access via iopen */
-+#define SHMEM_MOUNT_IOPEN_NOPRIV 0x10000 /* Make iopen world-readable */
-+
- /*
- * A swap entry has to fit into a "unsigned long", as
- * the entry is hidden in the "index" field of the
-@@ -38,6 +41,9 @@ struct shmem_inode_info {
- };
-
- struct shmem_sb_info {
-+ struct dentry *iopen;
-+ unsigned long options;
-+ unsigned long root_ino;
- unsigned long max_blocks; /* How many blocks are allowed */
- unsigned long free_blocks; /* How many are left for allocation */
- unsigned long max_inodes; /* How many inodes are allowed */
-@@ -59,11 +65,9 @@ shmem_xattr_find(struct inode *inode, co
- extern ssize_t
- shmem_xattr_set(struct inode *inode, const char *name,
- const void *value, u16 valuelen, int flags);
--
- extern ssize_t
- shmem_xattr_get(struct inode *inode, const char *name,
- void *value, size_t valuelen);
--
- extern int
- shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr);
-
-diff -rupN --exclude='ide*' linux-2.4.20.orig/mm/shmem.c linux-2.4.20/mm/shmem.c
---- linux-2.4.20.orig/mm/shmem.c 2004-02-10 18:44:05.000000000 +0200
-+++ linux-2.4.20/mm/shmem.c 2004-03-01 14:37:21.000000000 +0200
-@@ -36,29 +36,45 @@
- #define TMPFS_MAGIC 0x01021994
-
- #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
-+
- #define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
-
--#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
-+#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * \
-+ (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
-+
- #define SHMEM_MAX_BYTES ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
- #define VM_ACCT(size) (((size) + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT)
-
- /* Pretend that each entry is of this size in directory's i_size */
--#define BOGO_DIRENT_SIZE 20
--
-+#define BOGO_DIRENT_SIZE (20)
- #define SHMEM_SB(sb) (&sb->u.shmem_sb)
-
-+#define SHMEM_IOPEN_INO 2
-+#define SHMEM_IOPEN_NAME_LEN 32
-+
-+#define ASSERT(cond) \
-+do { \
-+ if (!(cond)) { \
-+ printk (KERN_EMERG \
-+ "Assertion failure in %s() at %s:%d: \"%s\"\n", \
-+ __FUNCTION__, __FILE__, __LINE__, # cond); \
-+ BUG(); \
-+ } \
-+} while (0)
-+
- static struct super_operations shmem_ops;
-+static struct vm_operations_struct shmem_vm_ops;
- static struct address_space_operations shmem_aops;
- static struct file_operations shmem_file_operations;
- static struct inode_operations shmem_inode_operations;
- static struct inode_operations shmem_dir_inode_operations;
--static struct vm_operations_struct shmem_vm_ops;
-
- LIST_HEAD (shmem_inodes);
- static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
- atomic_t shmem_nrpages = ATOMIC_INIT(0); /* Not used right now */
-
--static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
-+struct page *shmem_getpage_locked(struct inode *inode, unsigned long idx);
-+struct page *shmem_getpage_unlocked(struct inode *inode, unsigned long idx);
-
- #ifdef CONFIG_TMPFS
- static struct inode_operations shmem_symlink_inode_operations;
-@@ -327,7 +343,7 @@ shmem_getxattr(struct dentry *dentry, co
- * inode attributes list.*/
- static int
- shmem_setxattr(struct dentry *dentry, const char *name,
-- void *value, size_t valuelen, int flags)
-+ const void *value, size_t valuelen, int flags)
- {
- int error;
- struct inode *inode = dentry->d_inode;
-@@ -404,8 +420,8 @@ shmem_listxattr(struct dentry *dentry, c
- * @inode: inode to recalc
- * @swap: additional swap pages freed externally
- *
-- * We have to calculate the free blocks since the mm can drop pages
-- * behind our back
-+ * We have to calculate the free blocks since the mm can drop pages behind our
-+ * back
- *
- * But we know that normally
- * inodes->i_blocks/BLOCKS_PER_PAGE ==
-@@ -441,24 +457,23 @@ static void shmem_recalc_inode(struct in
- * @page: optional page to add to the structure. Has to be preset to
- * all zeros
- *
-- * If there is no space allocated yet it will return -ENOMEM when
-- * page == 0 else it will use the page for the needed block.
-+ * If there is no space allocated yet it will return -ENOMEM when page == 0 else
-+ * it will use the page for the needed block.
- *
- * returns -EFBIG if the index is too big.
- *
- *
- * The swap vector is organized the following way:
- *
-- * There are SHMEM_NR_DIRECT entries directly stored in the
-- * shmem_inode_info structure. So small files do not need an addional
-- * allocation.
-- *
-- * For pages with index > SHMEM_NR_DIRECT there is the pointer
-- * i_indirect which points to a page which holds in the first half
-- * doubly indirect blocks, in the second half triple indirect blocks:
-+ * There are SHMEM_NR_DIRECT entries directly stored in the shmem_inode_info
-+ * structure. So small files do not need an addional allocation.
-+ *
-+ * For pages with index > SHMEM_NR_DIRECT there is the pointer i_indirect which
-+ * points to a page which holds in the first half doubly indirect blocks, in the
-+ * second half triple indirect blocks:
- *
-- * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
-- * following layout (for SHMEM_NR_DIRECT == 16):
-+ * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the following
-+ * layout (for SHMEM_NR_DIRECT == 16):
- *
- * i_indirect -> dir --> 16-19
- * | +-> 20-23
-@@ -473,7 +488,9 @@ static void shmem_recalc_inode(struct in
- * +-> 48-51
- * +-> 52-55
- */
--static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page)
-+static swp_entry_t *
-+shmem_swp_entry (struct shmem_inode_info *info, unsigned long index,
-+ unsigned long page)
- {
- unsigned long offset;
- void **dir;
-@@ -520,7 +537,8 @@ static swp_entry_t * shmem_swp_entry (st
- * @info: info structure for the inode
- * @index: index of the page to find
- */
--static inline swp_entry_t * shmem_alloc_entry (struct shmem_inode_info *info, unsigned long index)
-+static inline swp_entry_t *
-+shmem_alloc_entry(struct shmem_inode_info *info, unsigned long index)
- {
- unsigned long page = 0;
- swp_entry_t * res;
-@@ -545,7 +563,8 @@ static inline swp_entry_t * shmem_alloc_
- * @dir: pointer to the directory
- * @count: number of entries to scan
- */
--static int shmem_free_swp(swp_entry_t *dir, unsigned int count)
-+static int
-+shmem_free_swp(swp_entry_t *dir, unsigned int count)
- {
- swp_entry_t *ptr, entry;
- int freed = 0;
-@@ -573,7 +592,9 @@ static int shmem_free_swp(swp_entry_t *d
- */
-
- static inline unsigned long
--shmem_truncate_direct(swp_entry_t *** dir, unsigned long start, unsigned long len) {
-+shmem_truncate_direct(swp_entry_t ***dir, unsigned long start,
-+ unsigned long len)
-+{
- swp_entry_t **last, **ptr;
- unsigned long off, freed = 0;
-
-@@ -639,7 +660,8 @@ shmem_truncate_indirect(struct shmem_ino
- BUG();
-
- baseidx = max & ~(ENTRIES_PER_PAGE*ENTRIES_PER_PAGE-1);
-- base = (swp_entry_t ***) info->i_indirect + ENTRIES_PER_PAGE/2 + baseidx/ENTRIES_PER_PAGE/ENTRIES_PER_PAGE ;
-+ base = (swp_entry_t ***) info->i_indirect + ENTRIES_PER_PAGE/2 +
-+ baseidx/ENTRIES_PER_PAGE/ENTRIES_PER_PAGE ;
- len = max - baseidx + 1;
- baseidx += ENTRIES_PER_PAGE*ENTRIES_PER_PAGE/2+SHMEM_NR_DIRECT;
- }
-@@ -654,7 +676,8 @@ shmem_truncate_indirect(struct shmem_ino
- return shmem_truncate_direct(base, start, len);
- }
-
--static void shmem_truncate (struct inode * inode)
-+static void
-+shmem_truncate(struct inode *inode)
- {
- unsigned long index;
- unsigned long partial;
-@@ -668,16 +691,16 @@ static void shmem_truncate (struct inode
- partial = inode->i_size & ~PAGE_CACHE_MASK;
-
- if (partial) {
-- swp_entry_t *entry = shmem_swp_entry(info, index-1, 0);
- struct page *page;
-- /*
-- * This check is racy: it's faintly possible that page
-- * was assigned to swap during truncate_inode_pages,
-- * and now assigned to file; but better than nothing.
-+ swp_entry_t *entry = shmem_swp_entry(info, index - 1, 0);
-+
-+ /* This check is racy: it's faintly possible that page was
-+ * assigned to swap during truncate_inode_pages, and now
-+ * assigned to file; but better than nothing.
- */
- if (!IS_ERR(entry) && entry->val) {
- spin_unlock(&info->lock);
-- page = shmem_getpage_locked(info, inode, index-1);
-+ page = shmem_getpage_locked(inode, index - 1);
- if (!IS_ERR(page)) {
- memclear_highpage_flush(page, partial,
- PAGE_CACHE_SIZE - partial);
-@@ -697,8 +720,166 @@ static void shmem_truncate (struct inode
- up(&info->sem);
- }
-
--static void shmem_delete_inode(struct inode * inode)
-+static struct inode *
-+shmem_find_inode(struct super_block *sb, long int ino)
-+{
-+ struct list_head *p;
-+ struct inode *inode = NULL;
-+ struct shmem_inode_info *info;
-+
-+ spin_lock (&shmem_ilock);
-+ list_for_each(p, &shmem_inodes) {
-+ info = list_entry(p, struct shmem_inode_info, list);
-+
-+ if (info->inode->i_ino == ino &&
-+ info->inode->i_sb == sb)
-+ {
-+ inode = info->inode;
-+ break;
-+ }
-+ }
-+
-+ spin_unlock (&shmem_ilock);
-+
-+ if (inode)
-+ igrab(inode);
-+
-+ return inode;
-+}
-+
-+#define switch_fields(x,y) do { \
-+ __typeof__ (x) __tmp = x; \
-+ x = y; y = __tmp; } while (0)
-+
-+static inline void
-+switch_names(struct dentry *dentry, struct dentry *target)
-+{
-+ const unsigned char *old_name, *new_name;
-+
-+ memcpy(dentry->d_iname, target->d_iname,
-+ DNAME_INLINE_LEN);
-+
-+ old_name = target->d_name.name;
-+ new_name = dentry->d_name.name;
-+
-+ if (old_name == target->d_iname)
-+ old_name = dentry->d_iname;
-+
-+ if (new_name == dentry->d_iname)
-+ new_name = target->d_iname;
-+
-+ target->d_name.name = new_name;
-+ dentry->d_name.name = old_name;
-+}
-+
-+static struct dentry *
-+shmem_iopen_lookup(struct inode *dir,
-+ struct dentry *dentry)
-+{
-+ struct inode *inode;
-+ unsigned long ino;
-+ struct list_head *lp;
-+ struct dentry *alternate;
-+ char buf[SHMEM_IOPEN_NAME_LEN];
-+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
-+
-+ if (dentry->d_name.len >= SHMEM_IOPEN_NAME_LEN)
-+ return ERR_PTR(-ENAMETOOLONG);
-+
-+ memcpy(buf, dentry->d_name.name, dentry->d_name.len);
-+ buf[dentry->d_name.len] = 0;
-+
-+ if (strcmp(buf, ".") == 0)
-+ ino = dir->i_ino;
-+ else if (strcmp(buf, "..") == 0)
-+ ino = sbinfo->root_ino;
-+ else
-+ ino = simple_strtoul(buf, 0, 0);
-+
-+ if (ino < sbinfo->root_ino)
-+ return ERR_PTR(-ENOENT);
-+
-+ if (!(inode = shmem_find_inode(dir->i_sb, ino)))
-+ return ERR_PTR(-ENOENT);
-+
-+ ASSERT(list_empty(&dentry->d_alias));
-+ ASSERT(list_empty(&dentry->d_hash));
-+
-+ /* preferrably return a connected dentry */
-+ spin_lock(&dcache_lock);
-+ list_for_each(lp, &inode->i_dentry) {
-+ alternate = list_entry(lp, struct dentry, d_alias);
-+ ASSERT(!(alternate->d_flags & DCACHE_NFSD_DISCONNECTED));
-+ }
-+
-+ if (!list_empty(&inode->i_dentry)) {
-+ alternate = list_entry(inode->i_dentry.next,
-+ struct dentry, d_alias);
-+ dget_locked(alternate);
-+ alternate->d_vfs_flags |= DCACHE_REFERENCED;
-+ iput(inode);
-+ spin_unlock(&dcache_lock);
-+ return alternate;
-+ }
-+ dentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
-+
-+ /* d_add(), but don't drop dcache_lock before adding dentry to inode */
-+ list_add(&dentry->d_alias, &inode->i_dentry);
-+ dentry->d_inode = inode;
-+
-+ __d_rehash(dentry, 0);
-+ spin_unlock(&dcache_lock);
-+
-+ return NULL;
-+}
-+
-+struct dentry *
-+shmem_iopen_unalias(struct dentry *dentry, struct inode *inode)
-+{
-+ struct dentry *tmp, *goal = NULL;
-+ struct list_head *lp;
-+
-+ list_for_each(lp, &inode->i_dentry) {
-+ tmp = list_entry(lp, struct dentry, d_alias);
-+ if (tmp->d_flags & DCACHE_NFSD_DISCONNECTED) {
-+ ASSERT(tmp->d_alias.next == &inode->i_dentry);
-+ ASSERT(tmp->d_alias.prev == &inode->i_dentry);
-+ goal = tmp;
-+ dget_locked(goal);
-+ break;
-+ }
-+ }
-+
-+ if (!goal)
-+ return NULL;
-+
-+ goal->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
-+ list_del_init(&goal->d_hash);
-+
-+ list_del(&goal->d_child);
-+ list_del(&dentry->d_child);
-+
-+ switch_names(goal, dentry);
-+ switch_fields(goal->d_parent, dentry->d_parent);
-+ switch_fields(goal->d_name.len, dentry->d_name.len);
-+ switch_fields(goal->d_name.hash, dentry->d_name.hash);
-+
-+ list_add(&goal->d_child, &goal->d_parent->d_subdirs);
-+ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
-+ __d_rehash(goal, 0);
-+
-+ return goal;
-+}
-+
-+static struct inode_operations iopen_inode_operations = {
-+ lookup: shmem_iopen_lookup,
-+};
-+
-+static void
-+shmem_delete_inode(struct inode *inode)
- {
-+ struct dentry *dentry;
-+
- #ifdef CONFIG_TMPFS_XATTR
- struct list_head *tmp, *p;
- struct shmem_xattr *xattr;
-@@ -706,16 +887,30 @@ static void shmem_delete_inode(struct in
- #endif
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-
-- if (inode->i_op->truncate == shmem_truncate) {
-+ if (inode->i_ino != SHMEM_IOPEN_INO) {
-+ /* eliminating iopen alias */
-+ spin_lock(&dcache_lock);
-+ if (!list_empty(&inode->i_dentry)) {
-+ dentry = list_entry(inode->i_dentry.next,
-+ struct dentry, d_alias);
-+ shmem_iopen_unalias(dentry, inode);
-+ }
-+ spin_unlock(&dcache_lock);
-+
- spin_lock (&shmem_ilock);
- list_del (&SHMEM_I(inode)->list);
- spin_unlock (&shmem_ilock);
-- inode->i_size = 0;
-- shmem_truncate (inode);
-+
-+ if (inode->i_op->truncate == shmem_truncate) {
-+ inode->i_size = 0;
-+ shmem_truncate (inode);
-+ }
-+
-+ spin_lock (&sbinfo->stat_lock);
-+ sbinfo->free_inodes++;
-+ spin_unlock (&sbinfo->stat_lock);
- }
-- spin_lock (&sbinfo->stat_lock);
-- sbinfo->free_inodes++;
-- spin_unlock (&sbinfo->stat_lock);
-+
- #ifdef CONFIG_TMPFS_XATTR
- list_for_each_safe(p, tmp, &info->xattrs) {
- xattr = list_entry(p, struct shmem_xattr, list);
-@@ -725,7 +920,8 @@ static void shmem_delete_inode(struct in
- clear_inode(inode);
- }
-
--static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *ptr, swp_entry_t *eptr)
-+static inline int
-+shmem_find_swp(swp_entry_t entry, swp_entry_t *ptr, swp_entry_t *eptr)
- {
- swp_entry_t *test;
-
-@@ -736,7 +932,9 @@ static inline int shmem_find_swp(swp_ent
- return -1;
- }
-
--static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
-+static int
-+shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry,
-+ struct page *page)
- {
- swp_entry_t *ptr;
- unsigned long idx;
-@@ -875,9 +1073,11 @@ getswap:
- * still need to guard against racing with shm_writepage(), which might
- * be trying to move the page to the swap cache as we run.
- */
--static struct page * shmem_getpage_locked(struct shmem_inode_info *info, struct inode * inode, unsigned long idx)
-+struct page *
-+shmem_getpage_locked(struct inode *inode, unsigned long idx)
- {
- struct address_space * mapping = inode->i_mapping;
-+ struct shmem_inode_info *info = SHMEM_I(inode);
- struct shmem_sb_info *sbinfo;
- struct page * page;
- swp_entry_t *entry;
-@@ -941,7 +1141,8 @@ repeat:
- swap_free(*entry);
- *entry = (swp_entry_t) {0};
- delete_from_swap_cache(page);
-- flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced) | (1 << PG_arch_1));
-+ flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) |
-+ (1 << PG_referenced) | (1 << PG_arch_1));
- page->flags = flags | (1 << PG_dirty);
- add_to_page_cache_locked(page, mapping, idx);
- info->swapped--;
-@@ -985,46 +1186,53 @@ wait_retry:
- goto repeat;
- }
-
--int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
-+struct page *
-+shmem_getpage_unlocked(struct inode *inode, unsigned long idx)
- {
-+ struct page *page;
- struct shmem_inode_info *info = SHMEM_I(inode);
-- int error;
-
-- down (&info->sem);
-- *ptr = ERR_PTR(-EFAULT);
-- if (inode->i_size <= (loff_t) idx * PAGE_CACHE_SIZE)
-+ down(&info->sem);
-+ page = ERR_PTR(-EFAULT);
-+
-+ if (inode->i_size <= (loff_t)idx * PAGE_CACHE_SIZE)
- goto failed;
-
-- *ptr = shmem_getpage_locked(info, inode, idx);
-- if (IS_ERR (*ptr))
-+ page = shmem_getpage_locked(inode, idx);
-+
-+ if (IS_ERR(page))
- goto failed;
-
-- UnlockPage(*ptr);
-- up (&info->sem);
-- return 0;
-+ UnlockPage(page);
-+ up(&info->sem);
-+ return page;
- failed:
-- up (&info->sem);
-- error = PTR_ERR(*ptr);
-- *ptr = NOPAGE_SIGBUS;
-- if (error == -ENOMEM)
-- *ptr = NOPAGE_OOM;
-- return error;
-+ up(&info->sem);
-+
-+ if (PTR_ERR(page) == -ENOMEM)
-+ return NOPAGE_OOM;
-+
-+ return page;
- }
-
--struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused)
-+struct page *
-+shmem_nopage(struct vm_area_struct *vma,
-+ unsigned long address, int unused)
- {
-- struct page * page;
- unsigned int idx;
-+ struct page * page;
- struct inode * inode = vma->vm_file->f_dentry->d_inode;
-
-- idx = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
-- idx += vma->vm_pgoff;
-+ idx = ((address - vma->vm_start) >> PAGE_CACHE_SHIFT) +
-+ vma->vm_pgoff;
-
-- if (shmem_getpage(inode, idx, &page))
-+ page = shmem_getpage_unlocked(inode, idx);
-+
-+ if (IS_ERR(page))
- return page;
-
- flush_page_to_ram(page);
-- return(page);
-+ return page;
- }
-
- void shmem_lock(struct file * file, int lock)
-@@ -1037,7 +1245,8 @@ void shmem_lock(struct file * file, int
- up(&info->sem);
- }
-
--static int shmem_mmap(struct file * file, struct vm_area_struct * vma)
-+static int
-+shmem_mmap(struct file * file, struct vm_area_struct * vma)
- {
- struct vm_operations_struct * ops;
- struct inode *inode = file->f_dentry->d_inode;
-@@ -1050,39 +1259,53 @@ static int shmem_mmap(struct file * file
- return 0;
- }
-
--struct inode *shmem_get_inode(struct super_block *sb, int mode, int dev)
-+static void
-+shmem_fill_inode(struct inode *inode, int mode, int dev)
- {
-- struct inode * inode;
- struct shmem_inode_info *info;
-- struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-+
-+ info = SHMEM_I(inode);
-+ info->inode = inode;
-+ spin_lock_init (&info->lock);
-+ sema_init (&info->sem, 1);
-
-- spin_lock (&sbinfo->stat_lock);
-- if (!sbinfo->free_inodes) {
-- spin_unlock (&sbinfo->stat_lock);
-- return NULL;
-- }
-- sbinfo->free_inodes--;
-- spin_unlock (&sbinfo->stat_lock);
-+#ifdef CONFIG_TMPFS_XATTR
-+ INIT_LIST_HEAD(&info->xattrs);
-+ info->xtail = &info->xattrs;
-+#endif
-
-- inode = new_inode(sb);
-- if (inode) {
-+ inode->i_blocks = 0;
-+ inode->i_rdev = NODEV;
-+ inode->i_atime = CURRENT_TIME;
-+ inode->i_ctime = CURRENT_TIME;
-+ inode->i_mtime = CURRENT_TIME;
-+ inode->i_blksize = PAGE_CACHE_SIZE;
-+
-+ /* handling speciall iopen inode. */
-+ if (inode->i_ino == SHMEM_IOPEN_INO) {
-+ struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-+
-+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
-+
-+ if (sbinfo->options & SHMEM_MOUNT_IOPEN_NOPRIV)
-+ inode->i_mode |= 0777;
-+
-+ inode->i_uid = 0;
-+ inode->i_gid = 0;
-+ inode->i_nlink = 1;
-+ inode->i_size = 2 * BOGO_DIRENT_SIZE;
-+ inode->i_version = 1;
-+ inode->i_generation = 0;
-+
-+ inode->i_op = &iopen_inode_operations;
-+ inode->i_fop = &dcache_dir_ops;
-+ inode->i_mapping->a_ops = 0;
-+ } else {
- inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
-- inode->i_blksize = PAGE_CACHE_SIZE;
-- inode->i_blocks = 0;
-- inode->i_rdev = NODEV;
- inode->i_mapping->a_ops = &shmem_aops;
-- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-- info = SHMEM_I(inode);
-- info->inode = inode;
-- spin_lock_init (&info->lock);
-- sema_init (&info->sem, 1);
-
--#ifdef CONFIG_TMPFS_XATTR
-- INIT_LIST_HEAD(&info->xattrs);
-- info->xtail = &info->xattrs;
--#endif
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
-@@ -1090,9 +1313,6 @@ struct inode *shmem_get_inode(struct sup
- case S_IFREG:
- inode->i_op = &shmem_inode_operations;
- inode->i_fop = &shmem_file_operations;
-- spin_lock (&shmem_ilock);
-- list_add_tail(&info->list, &shmem_inodes);
-- spin_unlock (&shmem_ilock);
- break;
- case S_IFDIR:
- inode->i_nlink++;
-@@ -1104,12 +1324,59 @@ struct inode *shmem_get_inode(struct sup
- case S_IFLNK:
- break;
- }
-+
-+ spin_lock (&shmem_ilock);
-+ list_add_tail(&info->list, &shmem_inodes);
-+ spin_unlock (&shmem_ilock);
-+ }
-+}
-+
-+struct inode *
-+shmem_get_inode(struct super_block *sb,
-+ int mode, int dev, int root)
-+{
-+ struct inode *inode;
-+ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-+
-+ spin_lock (&sbinfo->stat_lock);
-+ if (!sbinfo->free_inodes) {
-+ spin_unlock (&sbinfo->stat_lock);
-+ return NULL;
-+ }
-+ sbinfo->free_inodes--;
-+ spin_unlock (&sbinfo->stat_lock);
-+
-+ if ((inode = new_inode(sb))) {
-+ shmem_fill_inode(inode, mode, dev);
-+ if (root)
-+ sbinfo->root_ino = inode->i_ino;
- }
-+
- return inode;
- }
-
--static int shmem_set_size(struct shmem_sb_info *info,
-- unsigned long max_blocks, unsigned long max_inodes)
-+void shmem_read_inode(struct inode *inode)
-+{
-+ struct shmem_sb_info *sbinfo;
-+
-+ if (inode->i_ino != SHMEM_IOPEN_INO)
-+ return;
-+
-+ sbinfo = SHMEM_SB(inode->i_sb);
-+
-+ spin_lock (&sbinfo->stat_lock);
-+ if (!sbinfo->free_inodes) {
-+ spin_unlock (&sbinfo->stat_lock);
-+ return;
-+ }
-+ sbinfo->free_inodes--;
-+ spin_unlock (&sbinfo->stat_lock);
-+ shmem_fill_inode(inode, 0, 0);
-+}
-+
-+static int
-+shmem_set_size(struct shmem_sb_info *info, unsigned long max_blocks,
-+ unsigned long max_inodes)
- {
- int error;
- unsigned long blocks, inodes;
-@@ -1192,7 +1459,6 @@ shmem_file_write(struct file *file,const
-
- while (count) {
- unsigned long bytes, index, offset;
-- char *kaddr;
-
- /*
- * Try to find the page in the cache. If it isn't there,
-@@ -1201,9 +1467,9 @@ shmem_file_write(struct file *file,const
- offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
- index = pos >> PAGE_CACHE_SHIFT;
- bytes = PAGE_CACHE_SIZE - offset;
-- if (bytes > count) {
-+
-+ if (bytes > count)
- bytes = count;
-- }
-
- /*
- * Bring in the user page that we will copy from _first_.
-@@ -1218,7 +1484,7 @@ shmem_file_write(struct file *file,const
-
- info = SHMEM_I(inode);
- down (&info->sem);
-- page = shmem_getpage_locked(info, inode, index);
-+ page = shmem_getpage_locked(inode, index);
- up (&info->sem);
-
- status = PTR_ERR(page);
-@@ -1226,17 +1492,19 @@ shmem_file_write(struct file *file,const
- break;
-
- /* We have exclusive IO access to the page.. */
-- if (!PageLocked(page)) {
-+ if (!PageLocked(page))
- PAGE_BUG(page);
-- }
-
-- kaddr = kmap(page);
-- status = copy_from_user(kaddr+offset, buf, bytes);
-+ status = copy_from_user(kmap(page) + offset,
-+ buf, bytes);
-+
- kunmap(page);
-+
- if (status)
- goto fail_write;
-
- flush_dcache_page(page);
-+
- if (bytes > 0) {
- SetPageDirty(page);
- written += bytes;
-@@ -1266,7 +1534,8 @@ fail_write:
- goto unlock;
- }
-
--static void do_shmem_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc)
-+static void
-+do_shmem_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc)
- {
- struct inode *inode = filp->f_dentry->d_inode;
- struct address_space *mapping = inode->i_mapping;
-@@ -1292,15 +1561,18 @@ static void do_shmem_file_read(struct fi
-
- nr = nr - offset;
-
-- if ((desc->error = shmem_getpage(inode, index, &page)))
-+ page = shmem_getpage_unlocked(inode, index);
-+
-+ if (IS_ERR(page)) {
-+ desc->error = PTR_ERR(page);
- break;
-+ }
-
- if (mapping->i_mmap_shared != NULL)
- flush_dcache_page(page);
-
-- /*
-- * Ok, we have the page, and it's up-to-date, so
-- * now we can copy it to user space...
-+ /* Ok, we have the page, and it's up-to-date, so now we can copy
-+ * it to user space...
- *
- * The actor routine returns how many bytes were actually used..
- * NOTE! This may not be the same as how much of a user buffer
-@@ -1309,6 +1581,8 @@ static void do_shmem_file_read(struct fi
- * pointers and the remaining count).
- */
- nr = file_read_actor(desc, page, offset, nr);
-+
-+ /* updating counters */
- offset += nr;
- index += offset >> PAGE_CACHE_SHIFT;
- offset &= ~PAGE_CACHE_MASK;
-@@ -1320,7 +1594,8 @@ static void do_shmem_file_read(struct fi
- UPDATE_ATIME(inode);
- }
-
--static ssize_t shmem_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
-+static ssize_t
-+shmem_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
- {
- ssize_t retval;
-
-@@ -1345,7 +1620,8 @@ static ssize_t shmem_file_read(struct fi
- return retval;
- }
-
--static int shmem_statfs(struct super_block *sb, struct statfs *buf)
-+static int
-+shmem_statfs(struct super_block *sb, struct statfs *buf)
- {
- struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-
-@@ -1361,22 +1637,62 @@ static int shmem_statfs(struct super_blo
- return 0;
- }
-
--/*
-- * Lookup the data. This is trivial - if the dentry didn't already
-- * exist, we know it is negative.
-- */
--static struct dentry * shmem_lookup(struct inode *dir, struct dentry *dentry)
-+static int
-+match_dentry(struct dentry *dentry, const char *name)
-+{
-+ int len = strlen(name);
-+
-+ if (dentry->d_name.len != len)
-+ return 0;
-+
-+ if (strncmp(dentry->d_name.name, name, len))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+static int
-+shmem_iopen_check(struct inode *dir, struct dentry *dentry)
-+{
-+ struct inode *inode;
-+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb);
-+
-+ if (dir->i_ino != sbinfo->root_ino ||
-+ !(sbinfo->options & SHMEM_MOUNT_IOPEN) ||
-+ !match_dentry(dentry, "__iopen__"))
-+ {
-+ return 0;
-+ }
-+
-+ if (!(inode = iget(dir->i_sb, SHMEM_IOPEN_INO)))
-+ return 0;
-+
-+ d_add(dentry, inode);
-+
-+ spin_lock (&sbinfo->stat_lock);
-+ sbinfo->iopen = dentry;
-+ spin_unlock (&sbinfo->stat_lock);
-+
-+ dget(dentry);
-+ return 1;
-+}
-+
-+static struct dentry *
-+shmem_lookup(struct inode *dir, struct dentry *dentry)
- {
-- d_add(dentry, NULL);
-+ if (!shmem_iopen_check(dir, dentry))
-+ d_add(dentry, NULL);
-+
- return NULL;
- }
-
- /*
- * File creation. Allocate an inode, and we're done..
- */
--static int shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
-+static int
-+shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
- {
-- struct inode * inode = shmem_get_inode(dir->i_sb, mode, dev);
-+ struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev, 0);
- int error = -ENOSPC;
-
- if (inode) {
-@@ -1386,20 +1702,24 @@ static int shmem_mknod(struct inode *dir
- dget(dentry); /* Extra count - pin the dentry in core */
- error = 0;
- }
-+
- return error;
- }
-
--static int shmem_mkdir(struct inode * dir, struct dentry * dentry, int mode)
-+static int
-+shmem_mkdir(struct inode * dir, struct dentry * dentry, int mode)
- {
- int error;
-
- if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
- return error;
-+
- dir->i_nlink++;
- return 0;
- }
-
--static int shmem_create(struct inode *dir, struct dentry *dentry, int mode)
-+static int
-+shmem_create(struct inode *dir, struct dentry *dentry, int mode)
- {
- return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
- }
-@@ -1407,7 +1727,8 @@ static int shmem_create(struct inode *di
- /*
- * Link a file..
- */
--static int shmem_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
-+static int
-+shmem_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
- {
- struct inode *inode = old_dentry->d_inode;
-
-@@ -1429,13 +1750,11 @@ static inline int shmem_positive(struct
- }
-
- /*
-- * Check that a directory is empty (this works
-- * for regular files too, they'll just always be
-- * considered empty..).
-+ * Check that a directory is empty (this works for regular files too, they'll
-+ * just always be considered empty..).
- *
-- * Note that an empty directory can still have
-- * children, they just all have to be negative..
-- */
-+ * Note that an empty directory can still have children, they just all have to
-+ * be negative.. */
- static int shmem_empty(struct dentry *dentry)
- {
- struct list_head *list;
-@@ -1456,18 +1775,22 @@ static int shmem_empty(struct dentry *de
- return 1;
- }
-
--static int shmem_unlink(struct inode * dir, struct dentry *dentry)
-+static int
-+shmem_unlink(struct inode *dir, struct dentry *dentry)
- {
- struct inode *inode = dentry->d_inode;
-
- dir->i_size -= BOGO_DIRENT_SIZE;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- inode->i_nlink--;
-- dput(dentry); /* Undo the count from "create" - this does all the work */
-+
-+ /* undo the count from "create" - this does all the work. */
-+ dput(dentry);
- return 0;
- }
-
--static int shmem_rmdir(struct inode * dir, struct dentry *dentry)
-+static int
-+shmem_rmdir(struct inode *dir, struct dentry *dentry)
- {
- if (!shmem_empty(dentry))
- return -ENOTEMPTY;
-@@ -1477,12 +1800,13 @@ static int shmem_rmdir(struct inode * di
- }
-
- /*
-- * The VFS layer already does all the dentry stuff for rename,
-- * we just have to decrement the usage count for the target if
-- * it exists so that the VFS layer correctly free's it when it
-- * gets overwritten.
-+ * The VFS layer already does all the dentry stuff for rename, we just have to
-+ * decrement the usage count for the target if it exists so that the VFS layer
-+ * correctly free's it when it gets overwritten.
- */
--static int shmem_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
-+static int
-+shmem_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry)
- {
- struct inode *inode = old_dentry->d_inode;
- int they_are_dirs = S_ISDIR(inode->i_mode);
-@@ -1507,19 +1831,20 @@ static int shmem_rename(struct inode * o
- return 0;
- }
-
--static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
-+static int
-+shmem_symlink(struct inode *dir, struct dentry *dentry,
-+ const char *symname)
- {
- int len;
-- struct inode *inode;
- struct page *page;
-- char *kaddr;
-- struct shmem_inode_info * info;
-+ struct inode *inode;
-+ struct shmem_inode_info *info;
-
- len = strlen(symname) + 1;
- if (len > PAGE_CACHE_SIZE)
- return -ENAMETOOLONG;
-
-- inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
-+ inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, 0);
- if (!inode)
- return -ENOSPC;
-
-@@ -1531,7 +1856,7 @@ static int shmem_symlink(struct inode *
- inode->i_op = &shmem_symlink_inline_operations;
- } else {
- down(&info->sem);
-- page = shmem_getpage_locked(info, inode, 0);
-+ page = shmem_getpage_locked(inode, 0);
- if (IS_ERR(page)) {
- up(&info->sem);
- iput(inode);
-@@ -1541,8 +1866,7 @@ static int shmem_symlink(struct inode *
- spin_lock (&shmem_ilock);
- list_add_tail(&info->list, &shmem_inodes);
- spin_unlock (&shmem_ilock);
-- kaddr = kmap(page);
-- memcpy(kaddr, symname, len);
-+ memcpy(kmap(page), symname, len);
- kunmap(page);
- SetPageDirty(page);
- UnlockPage(page);
-@@ -1556,40 +1880,52 @@ static int shmem_symlink(struct inode *
- return 0;
- }
-
--static int shmem_readlink_inline(struct dentry *dentry, char *buffer, int buflen)
-+static int
-+shmem_readlink_inline(struct dentry *dentry, char *buffer, int buflen)
- {
-- return vfs_readlink(dentry,buffer,buflen, (const char *)SHMEM_I(dentry->d_inode));
-+ return vfs_readlink(dentry,buffer, buflen,
-+ (const char *)SHMEM_I(dentry->d_inode));
- }
-
--static int shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
-+static int
-+shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
- {
- return vfs_follow_link(nd, (const char *)SHMEM_I(dentry->d_inode));
- }
-
--static int shmem_readlink(struct dentry *dentry, char *buffer, int buflen)
-+static int
-+shmem_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-- struct page * page;
-- int res = shmem_getpage(dentry->d_inode, 0, &page);
-+ int res;
-+ struct page *page;
-+
-+ page = shmem_getpage_unlocked(dentry->d_inode, 0);
-
-- if (res)
-- return res;
-+ if (IS_ERR(page))
-+ return PTR_ERR(page);
-
- res = vfs_readlink(dentry,buffer,buflen, kmap(page));
- kunmap(page);
- page_cache_release(page);
-+
- return res;
- }
-
--static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static int
-+shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
- struct page * page;
-- int res = shmem_getpage(dentry->d_inode, 0, &page);
-- if (res)
-- return res;
-+ int res;
-+
-+ page = shmem_getpage_unlocked(dentry->d_inode, 0);
-+
-+ if (IS_ERR(page))
-+ return PTR_ERR(page);
-
- res = vfs_follow_link(nd, kmap(page));
- kunmap(page);
- page_cache_release(page);
-+
- return res;
- }
-
-@@ -1610,7 +1946,10 @@ static struct inode_operations shmem_sym
- #endif
- };
-
--static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes)
-+static int
-+shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid,
-+ unsigned long *blocks, unsigned long *inodes,
-+ unsigned long *opts)
- {
- char *this_char, *value, *rest;
-
-@@ -1620,11 +1959,6 @@ static int shmem_parse_options(char *opt
- for ( ; this_char; this_char = strtok(NULL,",")) {
- if ((value = strchr(this_char,'=')) != NULL) {
- *value++ = 0;
-- } else {
-- printk(KERN_ERR
-- "tmpfs: No value for mount option '%s'\n",
-- this_char);
-- return 1;
- }
-
- if (!strcmp(this_char,"size")) {
-@@ -1659,6 +1993,17 @@ static int shmem_parse_options(char *opt
- *gid = simple_strtoul(value,&rest,0);
- if (*rest)
- goto bad_val;
-+ } else if (!strcmp(this_char, "iopen")) {
-+ *opts |= SHMEM_MOUNT_IOPEN;
-+ *opts &= ~SHMEM_MOUNT_IOPEN_NOPRIV;
-+ }
-+ else if (!strcmp(this_char, "noiopen")) {
-+ *opts &= ~SHMEM_MOUNT_IOPEN;
-+ *opts &= ~SHMEM_MOUNT_IOPEN_NOPRIV;
-+ }
-+ else if (!strcmp (this_char, "iopen_nopriv")) {
-+ *opts |= SHMEM_MOUNT_IOPEN;
-+ *opts |= SHMEM_MOUNT_IOPEN_NOPRIV;
- } else {
- printk(KERN_ERR "tmpfs: Bad mount option %s\n",
- this_char);
-@@ -1674,14 +2019,19 @@ bad_val:
-
- }
-
--static int shmem_remount_fs (struct super_block *sb, int *flags, char *data)
-+static int
-+shmem_remount_fs(struct super_block *sb, int *flags, char *data)
- {
- struct shmem_sb_info *sbinfo = &sb->u.shmem_sb;
- unsigned long max_blocks = sbinfo->max_blocks;
- unsigned long max_inodes = sbinfo->max_inodes;
-
-- if (shmem_parse_options (data, NULL, NULL, NULL, &max_blocks, &max_inodes))
-+ if (shmem_parse_options (data, NULL, NULL, NULL, &max_blocks,
-+ &max_inodes, &sbinfo->options))
-+ {
- return -EINVAL;
-+ }
-+
- return shmem_set_size(sbinfo, max_blocks, max_inodes);
- }
-
-@@ -1691,7 +2041,8 @@ int shmem_sync_file(struct file * file,
- }
- #endif
-
--static struct super_block *shmem_read_super(struct super_block * sb, void * data, int silent)
-+static struct super_block *
-+shmem_read_super(struct super_block * sb, void * data, int silent)
- {
- struct inode * inode;
- struct dentry * root;
-@@ -1710,11 +2061,15 @@ static struct super_block *shmem_read_su
- blocks = inodes = si.totalram / 2;
-
- #ifdef CONFIG_TMPFS
-- if (shmem_parse_options (data, &mode, &uid, &gid, &blocks, &inodes))
-+ if (shmem_parse_options (data, &mode, &uid, &gid, &blocks,
-+ &inodes, &sbinfo->options))
-+ {
- return NULL;
-+ }
- #endif
-
- spin_lock_init (&sbinfo->stat_lock);
-+ sbinfo->iopen = NULL;
- sbinfo->max_blocks = blocks;
- sbinfo->free_blocks = blocks;
- sbinfo->max_inodes = inodes;
-@@ -1724,7 +2079,7 @@ static struct super_block *shmem_read_su
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = TMPFS_MAGIC;
- sb->s_op = &shmem_ops;
-- inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
-+ inode = shmem_get_inode(sb, S_IFDIR | mode, 0, 1);
- if (!inode)
- return NULL;
-
-@@ -1739,7 +2094,19 @@ static struct super_block *shmem_read_su
- return sb;
- }
-
-+void shmem_put_super(struct super_block *sb)
-+{
-+ struct dentry *iopen;
-+ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-
-+ spin_lock(&sbinfo->stat_lock);
-+ iopen = sbinfo->iopen;
-+ sbinfo->iopen = NULL;
-+ spin_unlock(&sbinfo->stat_lock);
-+
-+ if (iopen)
-+ dput(iopen);
-+}
-
- static struct address_space_operations shmem_aops = {
- writepage: shmem_writepage,
-@@ -1790,11 +2157,13 @@ static struct super_operations shmem_ops
- remount_fs: shmem_remount_fs,
- #endif
- delete_inode: shmem_delete_inode,
-- put_inode: force_delete,
-+ read_inode: shmem_read_inode,
-+ put_inode: force_delete,
-+ put_super: shmem_put_super,
- };
-
- static struct vm_operations_struct shmem_vm_ops = {
-- nopage: shmem_nopage,
-+ nopage: shmem_nopage,
- };
-
- #ifdef CONFIG_TMPFS
-@@ -1885,7 +2254,7 @@ struct file *shmem_file_setup(char * nam
- goto put_dentry;
-
- error = -ENOSPC;
-- inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
-+ inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, 0);
- if (!inode)
- goto close_file;
-
-@@ -1921,15 +2290,17 @@ int shmem_zero_setup(struct vm_area_stru
-
- if (vma->vm_file)
- fput (vma->vm_file);
-+
- vma->vm_file = file;
- vma->vm_ops = &shmem_vm_ops;
- return 0;
- }
-
- EXPORT_SYMBOL(shmem_file_setup);
--EXPORT_SYMBOL(shmem_getpage);
- EXPORT_SYMBOL(shmem_xattr_find);
- EXPORT_SYMBOL(shmem_xattr_set);
- EXPORT_SYMBOL(shmem_xattr_get);
- EXPORT_SYMBOL(shmem_xattr_delete);
- EXPORT_SYMBOL(shmem_xattr_remove);
-+EXPORT_SYMBOL(shmem_getpage_locked);
-+EXPORT_SYMBOL(shmem_getpage_unlocked);
+++ /dev/null
-diff -rupN --exclude='ide*' linux-2.4.20.orig/fs/Config.in linux-2.4.20/fs/Config.in
---- linux-2.4.20.orig/fs/Config.in 2002-11-29 01:53:15.000000000 +0200
-+++ linux-2.4.20/fs/Config.in 2004-02-08 21:37:47.000000000 +0200
-@@ -48,6 +48,9 @@ if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFI
- fi
- tristate 'Compressed ROM file system support' CONFIG_CRAMFS
- bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
-+if [ "$CONFIG_TMPFS" = "y" ]; then
-+ bool ' tmpfs Extended Attributes' CONFIG_TMPFS_XATTR
-+fi
- define_bool CONFIG_RAMFS y
-
- tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
-diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/mm.h linux-2.4.20/include/linux/mm.h
---- linux-2.4.20.orig/include/linux/mm.h 2002-08-03 03:39:45.000000000 +0300
-+++ linux-2.4.20/include/linux/mm.h 2004-02-10 11:43:10.000000000 +0200
-@@ -468,6 +468,7 @@ extern void clear_page_tables(struct mm_
- extern int fail_writepage(struct page *);
- struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
- struct file *shmem_file_setup(char * name, loff_t size);
-+int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr);
- extern void shmem_lock(struct file * file, int lock);
- extern int shmem_zero_setup(struct vm_area_struct *);
-
-diff -rupN --exclude='ide*' linux-2.4.20.orig/include/linux/shmem_fs.h linux-2.4.20/include/linux/shmem_fs.h
---- linux-2.4.20.orig/include/linux/shmem_fs.h 2001-12-21 19:42:03.000000000 +0200
-+++ linux-2.4.20/include/linux/shmem_fs.h 2004-02-10 18:39:17.000000000 +0200
-@@ -3,6 +3,8 @@
-
- /* inode in-kernel data */
-
-+#include <linux/config.h>
-+
- #define SHMEM_NR_DIRECT 16
-
- /*
-@@ -28,6 +30,10 @@ struct shmem_inode_info {
- unsigned long swapped;
- int locked; /* into memory */
- struct list_head list;
-+#ifdef CONFIG_TMPFS_XATTR
-+ struct list_head xattrs;
-+ struct list_head *xtail;
-+#endif
- struct inode *inode;
- };
-
-@@ -39,6 +45,32 @@ struct shmem_sb_info {
- spinlock_t stat_lock;
- };
-
-+#ifdef CONFIG_TMPFS_XATTR
-+struct shmem_xattr {
-+ u8 namelen;
-+ u16 valuelen;
-+ void *entity;
-+ struct list_head list;
-+};
-+
-+extern struct shmem_xattr *
-+shmem_xattr_find(struct inode *inode, const char *name);
-+
-+extern ssize_t
-+shmem_xattr_set(struct inode *inode, const char *name,
-+ const void *value, u16 valuelen, int flags);
-+
-+extern ssize_t
-+shmem_xattr_get(struct inode *inode, const char *name,
-+ void *value, size_t valuelen);
-+
-+extern int
-+shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr);
-+
-+extern int
-+shmem_xattr_remove(struct inode *inode, const char *name);
-+#endif
-+
- #define SHMEM_I(inode) (&inode->u.shmem_i)
-
- #endif
-diff -rupN --exclude='ide*' linux-2.4.20.orig/mm/shmem.c linux-2.4.20/mm/shmem.c
---- linux-2.4.20.orig/mm/shmem.c 2002-11-29 01:53:15.000000000 +0200
-+++ linux-2.4.20/mm/shmem.c 2004-02-10 18:44:05.000000000 +0200
-@@ -27,6 +27,8 @@
- #include <linux/string.h>
- #include <linux/locks.h>
- #include <linux/smp_lock.h>
-+#include <linux/slab.h>
-+#include <linux/xattr.h>
-
- #include <asm/uaccess.h>
-
-@@ -58,6 +60,344 @@ atomic_t shmem_nrpages = ATOMIC_INIT(0);
-
- static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
-
-+#ifdef CONFIG_TMPFS
-+static struct inode_operations shmem_symlink_inode_operations;
-+static struct inode_operations shmem_symlink_inline_operations;
-+#endif
-+
-+#ifdef CONFIG_TMPFS_XATTR
-+#define xattr_name(xattr) \
-+ ((char *)xattr->entity)
-+
-+#define xattr_value(xattr) \
-+ ((void *)xattr->entity + xattr->namelen + 1)
-+
-+/* allocates memory for new xattr with name length of @namelen and value size of
-+ * @valuelen. */
-+static struct shmem_xattr *
-+shmem_xattr_alloc(u8 namelen, u16 valuelen)
-+{
-+ u16 size;
-+ struct shmem_xattr *xattr;
-+
-+ size = namelen + 1 + valuelen;
-+
-+ if (!(xattr = kmalloc(sizeof(*xattr), GFP_KERNEL)))
-+ return NULL;
-+
-+ if (!(xattr->entity = kmalloc(size, GFP_KERNEL))) {
-+ kfree(xattr);
-+ return NULL;
-+ }
-+
-+ xattr->namelen = namelen;
-+ xattr->valuelen = valuelen;
-+ return xattr;
-+}
-+
-+/* reallocs passed @xattr with new @value. */
-+static int
-+shmem_xattr_realloc(struct shmem_xattr *xattr, u16 valuelen)
-+{
-+ if (xattr->valuelen != valuelen) {
-+ u16 new_size;
-+ void *entity;
-+
-+ /* allocating new entity. */
-+ new_size = xattr->namelen + 1 + valuelen;
-+
-+ if (!(entity = kmalloc(new_size, GFP_KERNEL)))
-+ return -ENOMEM;
-+
-+ /* copying old name to new entity.*/
-+ memcpy(entity, xattr->entity, xattr->namelen);
-+ *((char *)(entity + xattr->namelen)) = '\0';
-+
-+ /* finishing the change.*/
-+ kfree(xattr->entity);
-+ xattr->entity = entity;
-+ xattr->valuelen = valuelen;
-+ }
-+
-+ return 0;
-+}
-+
-+/* assigns @name and @value to passed @xattr. */
-+static int
-+shmem_xattr_assign(struct shmem_xattr *xattr,
-+ const char *name, const void *value)
-+{
-+ if (name) {
-+ if (xattr->namelen != strlen(name))
-+ return -EINVAL;
-+
-+ memcpy(xattr->entity, name, xattr->namelen);
-+ *((char *)(xattr->entity + xattr->namelen)) = '\0';
-+ }
-+
-+ if (value) {
-+ memcpy(xattr_value(xattr),
-+ value, xattr->valuelen);
-+ }
-+
-+ return 0;
-+}
-+
-+/* frees passed @xattr. */
-+static void
-+shmem_xattr_free(struct shmem_xattr *xattr)
-+{
-+ kfree(xattr->entity);
-+ kfree(xattr);
-+}
-+
-+/* lookups passed @name inside @inode's xattr list. */
-+struct shmem_xattr *
-+shmem_xattr_find(struct inode *inode, const char *name)
-+{
-+ u8 namelen;
-+ struct list_head *p;
-+ struct shmem_xattr *xattr;
-+ struct shmem_inode_info *info;
-+
-+ info = SHMEM_I(inode);
-+ namelen = strlen(name);
-+
-+ list_for_each(p, &info->xattrs) {
-+ xattr = list_entry(p, struct shmem_xattr, list);
-+
-+ if (xattr->namelen == namelen &&
-+ !memcmp(xattr->entity, name, namelen))
-+ {
-+ return xattr;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+/* allocates new xattr and fills it with passed value, name, etc. */
-+ssize_t
-+shmem_xattr_set(struct inode *inode, const char *name,
-+ const void *value, u16 valuelen, int flags)
-+{
-+ ssize_t error;
-+ struct shmem_xattr *xattr;
-+ struct shmem_inode_info *info;
-+
-+ xattr = shmem_xattr_find(inode, name);
-+
-+ if (xattr) {
-+ if (flags & XATTR_CREATE)
-+ return -EEXIST;
-+
-+ if ((error = shmem_xattr_realloc(xattr, valuelen)))
-+ return error;
-+
-+ if ((error = shmem_xattr_assign(xattr, NULL, value)))
-+ return error;
-+ } else {
-+ info = SHMEM_I(inode);
-+
-+ if (flags & XATTR_REPLACE)
-+ return -ENODATA;
-+
-+ if (!(xattr = shmem_xattr_alloc(strlen(name), valuelen)))
-+ return -ENOMEM;
-+
-+ if ((error = shmem_xattr_assign(xattr, name, value)))
-+ return error;
-+
-+ list_add(&xattr->list, info->xtail);
-+ info->xtail = &xattr->list;
-+ }
-+
-+ return 0;
-+}
-+
-+/* fills passed @value by attribute value found by @name. */
-+ssize_t
-+shmem_xattr_get(struct inode *inode, const char *name,
-+ void *value, size_t valuelen)
-+{
-+ struct shmem_xattr *xattr;
-+
-+ if (!(xattr = shmem_xattr_find(inode, name)))
-+ return -ENODATA;
-+
-+ /* handling value size guess request */
-+ if (valuelen == 0 || value == NULL)
-+ return xattr->valuelen;
-+
-+ if (xattr->valuelen > valuelen)
-+ return -ERANGE;
-+
-+ memcpy(value, xattr_value(xattr),
-+ xattr->valuelen);
-+
-+ return xattr->valuelen;
-+}
-+
-+/* deletes passed @xattr from inode xattr list and frees it. */
-+int
-+shmem_xattr_delete(struct inode *inode, struct shmem_xattr *xattr)
-+{
-+ struct shmem_inode_info *info;
-+
-+ info = SHMEM_I(inode);
-+
-+ if (&xattr->list == info->xtail)
-+ info->xtail = xattr->list.prev;
-+
-+ list_del(&xattr->list);
-+ shmem_xattr_free(xattr);
-+
-+ return 0;
-+}
-+
-+/* removes attribute found by passed @name. */
-+int
-+shmem_xattr_remove(struct inode *inode, const char *name)
-+{
-+ struct shmem_xattr *xattr;
-+
-+ if (!(xattr = shmem_xattr_find(inode, name)))
-+ return -ENODATA;
-+
-+ return shmem_xattr_delete(inode, xattr);
-+}
-+
-+static int
-+shmem_xattr_can_read(struct inode *inode, const char *name)
-+{
-+ /* check for inlined symlinks. They store path inside inode info and
-+ * thus, cannot be used for access xattrs. */
-+ if (S_ISLNK(inode->i_mode) &&
-+ inode->i_op == &shmem_symlink_inline_operations)
-+ {
-+ return -EPERM;
-+ }
-+
-+ return permission(inode, MAY_READ);
-+}
-+
-+static int
-+shmem_xattr_can_write(struct inode *inode, const char *name)
-+{
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode) ||
-+ S_ISLNK(inode->i_mode))
-+ {
-+ return -EPERM;
-+ }
-+
-+ if ((!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) ||
-+ inode->i_mode & S_ISVTX)
-+ {
-+ return -EPERM;
-+ }
-+
-+ return permission(inode, MAY_WRITE);
-+}
-+
-+/* fills passed @value with data of attribute @name from @dentry->d_inode
-+ * attribute list. */
-+static ssize_t
-+shmem_getxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t valuelen)
-+{
-+ int error;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+
-+ if ((error = shmem_xattr_can_read(inode, name)))
-+ return error;
-+
-+ return shmem_xattr_get(inode, name,
-+ value, valuelen);
-+
-+}
-+
-+/* updates attribute with @name inside @dentry->d_inode attributes list (if
-+ * any), or creates new attribute with name @name and value @value and put it to
-+ * inode attributes list.*/
-+static int
-+shmem_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t valuelen, int flags)
-+{
-+ int error;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+
-+ if ((error = shmem_xattr_can_write(inode, name)))
-+ return error;
-+
-+ if (value == NULL) {
-+ value = "";
-+ valuelen = 0;
-+ }
-+
-+ return shmem_xattr_set(inode, name, value,
-+ valuelen, flags);
-+}
-+
-+/* removes attribute with passed @name from @dentry->d_inode attributes list. */
-+static int
-+shmem_removexattr(struct dentry *dentry, const char *name)
-+{
-+ int error;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+
-+ if ((error = shmem_xattr_can_write(inode, name)))
-+ return error;
-+
-+ return shmem_xattr_remove(inode, name);
-+}
-+
-+/* fills passed @data with list of @dentry->d_inode attributes. Returns size of
-+ * actuall data put to @data. */
-+static ssize_t
-+shmem_listxattr(struct dentry *dentry, char *data, size_t buf_size)
-+{
-+ ssize_t size = 0;
-+ struct list_head *p;
-+ struct shmem_xattr *xattr;
-+ struct shmem_inode_info *info;
-+ struct inode *inode = dentry->d_inode;
-+
-+ info = SHMEM_I(inode);
-+
-+ list_for_each(p, &info->xattrs) {
-+ xattr = list_entry(p, struct shmem_xattr, list);
-+ size += xattr->namelen + 1;
-+ }
-+
-+ /* handling data size guess request. */
-+ if (buf_size == 0 || data == NULL)
-+ return size;
-+
-+ if (size > buf_size)
-+ return -ERANGE;
-+
-+ list_for_each(p, &info->xattrs) {
-+ xattr = list_entry(p, struct shmem_xattr, list);
-+ memcpy(data, xattr->entity, xattr->namelen + 1);
-+ data += xattr->namelen + 1;
-+ }
-+
-+ return size;
-+}
-+#endif
-+
- /*
- * shmem_recalc_inode - recalculate the size of an inode
- *
-@@ -359,6 +699,11 @@ static void shmem_truncate (struct inode
-
- static void shmem_delete_inode(struct inode * inode)
- {
-+#ifdef CONFIG_TMPFS_XATTR
-+ struct list_head *tmp, *p;
-+ struct shmem_xattr *xattr;
-+ struct shmem_inode_info * info = SHMEM_I(inode);
-+#endif
- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-
- if (inode->i_op->truncate == shmem_truncate) {
-@@ -371,6 +716,12 @@ static void shmem_delete_inode(struct in
- spin_lock (&sbinfo->stat_lock);
- sbinfo->free_inodes++;
- spin_unlock (&sbinfo->stat_lock);
-+#ifdef CONFIG_TMPFS_XATTR
-+ list_for_each_safe(p, tmp, &info->xattrs) {
-+ xattr = list_entry(p, struct shmem_xattr, list);
-+ shmem_xattr_delete(inode, xattr);
-+ }
-+#endif
- clear_inode(inode);
- }
-
-@@ -634,7 +985,7 @@ wait_retry:
- goto repeat;
- }
-
--static int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
-+int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
- {
- struct shmem_inode_info *info = SHMEM_I(inode);
- int error;
-@@ -727,6 +1078,11 @@ struct inode *shmem_get_inode(struct sup
- info->inode = inode;
- spin_lock_init (&info->lock);
- sema_init (&info->sem, 1);
-+
-+#ifdef CONFIG_TMPFS_XATTR
-+ INIT_LIST_HEAD(&info->xattrs);
-+ info->xtail = &info->xattrs;
-+#endif
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
-@@ -777,10 +1133,6 @@ out:
- }
-
- #ifdef CONFIG_TMPFS
--
--static struct inode_operations shmem_symlink_inode_operations;
--static struct inode_operations shmem_symlink_inline_operations;
--
- static ssize_t
- shmem_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
- {
-@@ -1250,6 +1602,12 @@ static struct inode_operations shmem_sym
- truncate: shmem_truncate,
- readlink: shmem_readlink,
- follow_link: shmem_follow_link,
-+#ifdef CONFIG_TMPFS_XATTR
-+ setxattr: shmem_setxattr,
-+ getxattr: shmem_getxattr,
-+ listxattr: shmem_listxattr,
-+ removexattr: shmem_removexattr,
-+#endif
- };
-
- static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes)
-@@ -1398,6 +1756,12 @@ static struct file_operations shmem_file
-
- static struct inode_operations shmem_inode_operations = {
- truncate: shmem_truncate,
-+#ifdef CONFIG_TMPFS_XATTR
-+ setxattr: shmem_setxattr,
-+ getxattr: shmem_getxattr,
-+ listxattr: shmem_listxattr,
-+ removexattr: shmem_removexattr,
-+#endif
- };
-
- static struct inode_operations shmem_dir_inode_operations = {
-@@ -1411,6 +1775,12 @@ static struct inode_operations shmem_dir
- rmdir: shmem_rmdir,
- mknod: shmem_mknod,
- rename: shmem_rename,
-+#ifdef CONFIG_TMPFS_XATTR
-+ setxattr: shmem_setxattr,
-+ getxattr: shmem_getxattr,
-+ listxattr: shmem_listxattr,
-+ removexattr: shmem_removexattr,
-+#endif
- #endif
- };
-
-@@ -1557,3 +1927,9 @@ int shmem_zero_setup(struct vm_area_stru
- }
-
- EXPORT_SYMBOL(shmem_file_setup);
-+EXPORT_SYMBOL(shmem_getpage);
-+EXPORT_SYMBOL(shmem_xattr_find);
-+EXPORT_SYMBOL(shmem_xattr_set);
-+EXPORT_SYMBOL(shmem_xattr_get);
-+EXPORT_SYMBOL(shmem_xattr_delete);
-+EXPORT_SYMBOL(shmem_xattr_remove);
ext3-xattr-ptr-arith-fix.patch
gfp_memalloc-2.4.22.patch
procfs-ndynamic-2.4.patch
-linux-2.4.20-tmpfs-xattr.patch
-linux-2.4.20-tmpfs-iopen.patch
linux-2.4.20-filemap.patch
ext3-truncate-buffer-head.patch
rc = llog_origin_handle_next_block(req);
ldlm_callback_reply(req, rc);
RETURN(0);
+ case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
+ OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
+ rc = llog_origin_handle_prev_block(req);
+ ldlm_callback_reply(req, rc);
+ RETURN(0);
case LLOG_ORIGIN_HANDLE_READ_HEADER:
OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
rc = llog_origin_handle_read_header(req);
* we need to keep cookies in stripe order, even if some are NULL, so that
* the right cookies are passed back to the right OSTs at the client side.
* Unset cookies should be all-zero (which will never occur naturally). */
-static int lov_llog_origin_add(struct llog_ctxt *ctxt,
- struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies)
+static int lov_llog_origin_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *logcookies,
+ int numcookies, void *data)
{
struct obd_device *obd = ctxt->loc_obd;
struct lov_obd *lov = &obd->u.lov;
struct lov_oinfo *loi;
struct llog_unlink_rec *lur;
+ struct lov_stripe_md *lsm = (struct lov_stripe_md *)data;
int i, rc = 0;
ENTRY;
lur->lur_oid = loi->loi_id;
lur->lur_ogen = loi->loi_gr;
rc += llog_add(cctxt, &lur->lur_hdr, NULL, logcookies + rc,
- numcookies - rc);
+ numcookies - rc, NULL);
}
OBD_FREE(lur, sizeof(*lur));
}
/* the replicators commit callback */
-static int lov_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm,
- int count, struct llog_cookie *cookies, int flags)
+static int lov_llog_repl_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags,
+ void *data)
{
+ struct lov_stripe_md *lsm = (struct lov_stripe_md *)data;
struct lov_obd *lov;
struct obd_device *obd = ctxt->loc_obd;
struct lov_oinfo *loi;
struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);
int err;
- err = llog_cancel(cctxt, NULL, 1, cookies, flags);
+ err = llog_cancel(cctxt, 1, cookies, flags, NULL);
if (err && lov->tgts[loi->loi_ost_idx].active) {
CERROR("error: objid "LPX64" subobj "LPX64
" on OST idx %d: rc = %d\n", lsm->lsm_object_id,
lop_cancel: lov_llog_repl_cancel
};
-
int lov_llog_init(struct obd_device *obd, struct obd_device *tgt,
int count, struct llog_catid *logid)
{
struct lov_obd *lov = &obd->u.lov;
int i, rc = 0;
ENTRY;
-
- rc = llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, 0, NULL,
- &lov_unlink_orig_logops);
+
+ rc = obd_llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, 0, NULL,
+ &lov_unlink_orig_logops);
if (rc)
RETURN(rc);
- rc = llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, 0, NULL,
- &lov_size_repl_logops);
+ rc = obd_llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, 0, NULL,
+ &lov_size_repl_logops);
if (rc)
RETURN(rc);
int i, rc = 0;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
if (rc)
RETURN(rc);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
if (rc)
RETURN(rc);
-MODULES := lvfs fsfilt_@BACKINGFS@
+MODULES := lvfs fsfilt_@BACKINGFS@ fsfilt_smfs
-lvfs-objs := lvfs_common.o lvfs_linux.o fsfilt.o
+lvfs-objs := fsfilt.o lvfs_common.o llog_lvfs.o lvfs_linux.o
+lvfs-objs += llog.o llog_cat.o lvfs_reint.o lvfs_undo.o
ifeq ($(PATCHLEVEL),6)
fsfilt_@BACKINGFS@-objs := fsfilt-@BACKINGFS@.o
ln -s $< $@
endif
+fsfilt_smfs-objs := fsfilt-smfs.o
+
# for <ext3/xattr.h> on 2.6
EXTRA_PRE_CFLAGS := -I@LINUX@/fs -I@LUSTRE@ -I@LUSTRE@/ldiskfs
include $(src)/../portals/Kernelenv
-obj-y += lvfs.o fsfilt_ext3.o
-lvfs-objs := fsfilt.o lvfs_common.o lvfs_linux.o
+obj-y += lvfs.o fsfilt_ext3.o fsfilt_smfs.o
+lvfs-objs := fsfilt.o lvfs_common.o llog_lvfs.o lvfs_linux.o
+lvfs-objs += llog.o llog_cat.o lvfs_reint.o lvfs_undo.o
if LIBLUSTRE
noinst_LIBRARIES = liblvfs.a
-liblvfs_a_SOURCES = lvfs_userfs.c
+liblvfs_a_SOURCES = lvfs_userfs.c llog_lvfs.c llog_cat.c llog.c
liblvfs_a_CFLAGS = $(LLCFLAGS)
liblvfs_a_CPPFLAGS = $(LLCPPFLAGS)
if MODULES
-modulefs_DATA = lvfs$(KMODEXT) fsfilt_$(BACKINGFS)$(KMODEXT)
+modulefs_DATA = lvfs$(KMODEXT) fsfilt_$(BACKINGFS)$(KMODEXT) fsfilt_smfs$(KMODEXT)
-sources: fsfilt_$(BACKINGFS).c
+sources: fsfilt_$(BACKINGFS).c fsfilt_smfs.c
touch sources
fsfilt_extN.c: fsfilt_ext3.c
sed -e "s/EXT3/EXTN/g" -e "s/ext3/extN/g" $< > $@
+fsfilt_smfs.c:
+ $< > $@
+
ldiskfs_sed_flags = \
-e "s/dx_hash_info/ext3_dx_hash_info/g" \
-e "s/dir_private_info/ext3_dir_private_info/g" \
endif # MODULES
-DIST_SOURCES = fsfilt.c fsfilt_ext3.c fsfilt_reiserfs.c lvfs_common.c \
- lvfs_internal.h lvfs_linux.c lvfs_userfs.c
+DIST_SOURCES = fsfilt.c fsfilt_ext3.c fsfilt_smfs.c fsfilt_reiserfs.c \
+ lvfs_common.c lvfs_internal.h lvfs_linux.c llog.c llog_cat.c \
+ llog_lvfs.c lvfs_reint.c lvfs_undo.c lvfs_userfs.c
MOSTLYCLEANFILES = *.o *.ko *.mod.c
CLEANFILES = fsfilt-*.c fsfilt_ldiskfs.c fsfilt_extN.c sources
#include <linux/lustre_fsfilt.h>
#include <linux/obd.h>
#include <linux/obd_class.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/module.h>
+#include <linux/iobuf.h>
+#endif
static kmem_cache_t *fcb_cache;
static atomic_t fcb_cache_count = ATOMIC_INIT(0);
goto journal_start;
}
+ /* XXX BUG 3188 -- must return to one set of opcodes */
+ /* FIXME - cache hook */
+ if (op & 0x20) {
+ nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
+ op = op & ~0x20;
+ }
+
+ /* FIXME - kml */
+ if (op & 0x10) {
+ nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
+ op = op & ~0x10;
+ }
+
switch(op) {
case FSFILT_OP_RMDIR:
case FSFILT_OP_UNLINK:
nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) +
EXT3_DELETE_TRANS_BLOCKS * logs;
break;
+ case FSFILT_OP_NOOP:
+ nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
+ break;
default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
+ LBUG();
}
LASSERT(current->journal_info == desc_private);
tid_t tid = (tid_t)(long)h;
CDEBUG(D_INODE, "commit wait: %lu\n", (unsigned long) tid);
- if (is_journal_aborted(EXT3_JOURNAL(inode)))
+ if (is_journal_aborted(EXT3_JOURNAL(inode)))
return -EIO;
log_wait_commit(EXT3_JOURNAL(inode), tid);
return rc;
}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static int fsfilt_ext3_send_bio(struct inode *inode, struct bio *bio)
+{
+ submit_bio(WRITE, bio);
+ return 0;
+}
+#else
+static int fsfilt_ext3_send_bio(struct inode *inode, struct kiobuf *bio)
+{
+ int rc, blocks_per_page;
+
+ rc = brw_kiovec(WRITE, 1, &bio, inode->i_dev,
+ bio->blocks, 1 << inode->i_blkbits);
+
+ blocks_per_page = PAGE_SIZE >> inode->i_blkbits;
+
+ if (rc != (1 << inode->i_blkbits) * bio->nr_pages *
+ blocks_per_page) {
+ CERROR("short write? expected %d, wrote %d\n",
+ (1 << inode->i_blkbits) * bio->nr_pages *
+ blocks_per_page, rc);
+ }
+
+ return rc;
+}
+#endif
+
+/* FIXME-UMKA: This should be used in 2.6.x io code later. */
+static struct page *fsfilt_ext3_getpage(struct inode *inode, long int index)
+{
+ int rc;
+ struct page *page;
+
+ page = grab_cache_page(inode->i_mapping, index);
+ if (page == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ if (PageUptodate(page)) {
+ unlock_page(page);
+ return page;
+ }
+
+ rc = inode->i_mapping->a_ops->readpage(NULL, page);
+ if (rc < 0) {
+ page_cache_release(page);
+ return ERR_PTR(rc);
+ }
+
+ return page;
+}
+
static ssize_t fsfilt_ext3_readpage(struct file *file, char *buf, size_t count,
loff_t *off)
{
atomic_dec(&fcb_cache_count);
}
-static int fsfilt_ext3_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
+static int fsfilt_ext3_add_journal_cb(struct obd_device *obd,
+ struct super_block *sb,
+ __u64 last_rcvd,
void *handle, fsfilt_cb_t cb_func,
void *cb_data)
{
return 0;
}
+static int fsfilt_ext3_set_xattr(struct inode * inode, void *handle, char *name,
+ void *buffer, int buffer_size)
+{
+ int rc = 0;
+
+ lock_kernel();
+
+ rc = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_TRUSTED,
+ name, buffer, buffer_size, 0);
+ unlock_kernel();
+ if (rc)
+ CERROR("set xattr %s from inode %lu: rc %d\n",
+ name, inode->i_ino, rc);
+ return rc;
+}
+
+static int fsfilt_ext3_get_xattr(struct inode *inode, char *name,
+ void *buffer, int buffer_size)
+{
+ int rc = 0;
+ lock_kernel();
+
+ rc = ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED,
+ name, buffer, buffer_size);
+ unlock_kernel();
+
+ if (buffer == NULL)
+ return (rc == -ENODATA) ? 0 : rc;
+ if (rc < 0) {
+ CDEBUG(D_INFO, "error getting EA %s from inode %lu: rc %d\n",
+ name, inode->i_ino, rc);
+ memset(buffer, 0, buffer_size);
+ return (rc == -ENODATA) ? 0 : rc;
+ }
+
+ return rc;
+}
+
/* If fso is NULL, op is FSFILT operation, otherwise op is number of fso
objects. Logs is number of logfiles to update */
static int fsfilt_ext3_get_op_len(int op, struct fsfilt_objinfo *fso, int logs)
.fs_write_record = fsfilt_ext3_write_record,
.fs_read_record = fsfilt_ext3_read_record,
.fs_setup = fsfilt_ext3_setup,
+ .fs_getpage = fsfilt_ext3_getpage,
+ .fs_send_bio = fsfilt_ext3_send_bio,
+ .fs_set_xattr = fsfilt_ext3_set_xattr,
+ .fs_get_xattr = fsfilt_ext3_get_xattr,
.fs_get_op_len = fsfilt_ext3_get_op_len,
};
{
int rc;
- //rc = ext3_xattr_register();
fcb_cache = kmem_cache_create("fsfilt_ext3_fcb",
sizeof(struct fsfilt_cb_data), 0,
0, NULL, NULL);
CERROR("can't free fsfilt callback cache: count %d, rc = %d\n",
atomic_read(&fcb_cache_count), rc);
}
-
- //rc = ext3_xattr_unregister();
}
module_init(fsfilt_ext3_init);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * lustre/lib/fsfilt_smfs.c
+ * Lustre filesystem abstraction routines
+ *
+ * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
+ * Author: Wang Di <wangdi@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.
+ */
+
+#define DEBUG_SUBSYSTEM S_FILTER
+
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/version.h>
+#include <linux/kp30.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include <linux/obd.h>
+#include <linux/obd_class.h>
+#include <linux/module.h>
+
+static void *fsfilt_smfs_start(struct inode *inode, int op,
+ void *desc_private, int logs)
+{
+ void *handle;
+ struct inode *cache_inode = I2CI(inode);
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+
+ if (cache_fsfilt == NULL)
+ return NULL;
+
+ if (!cache_fsfilt->fs_start)
+ return ERR_PTR(-ENOSYS);
+
+ handle = cache_fsfilt->fs_start(cache_inode, op,
+ desc_private, logs);
+ return handle;
+}
+
+static void *fsfilt_smfs_brw_start(int objcount, struct fsfilt_objinfo *fso,
+ int niocount, struct niobuf_local *nb,
+ void *desc_private, int logs)
+{
+ struct fsfilt_operations *cache_fsfilt;
+ struct dentry *cache_dentry = NULL;
+ struct inode *cache_inode = NULL;
+ struct fsfilt_objinfo cache_fso;
+ void *rc = NULL;
+
+ ENTRY;
+ cache_fsfilt = I2FOPS(fso->fso_dentry->d_inode);
+ if (cache_fsfilt == NULL)
+ return NULL;
+
+ cache_inode = I2CI(fso->fso_dentry->d_inode);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);
+
+ if (!cache_dentry)
+ GOTO(exit, rc = ERR_PTR(-ENOMEM));
+
+ cache_fso.fso_dentry = cache_dentry;
+ cache_fso.fso_bufcnt = fso->fso_bufcnt;
+
+ if (!cache_fsfilt->fs_brw_start)
+ return ERR_PTR(-ENOSYS);
+
+ rc = (cache_fsfilt->fs_brw_start(objcount, &cache_fso,
+ niocount, nb, desc_private,
+ logs));
+exit:
+ post_smfs_dentry(cache_dentry);
+ return rc;
+}
+
+static int fsfilt_smfs_commit(struct inode *inode, void *h,
+ int force_sync)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ cache_inode = I2CI(inode);
+
+ if (cache_fsfilt == NULL)
+ RETURN(rc);
+
+ if (!cache_fsfilt->fs_commit)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_commit(cache_inode, h, force_sync);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_commit_async(struct inode *inode, void *h,
+ void **wait_handle)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ cache_inode = I2CI(inode);
+ if (cache_fsfilt == NULL)
+ RETURN(-EINVAL);
+
+ if (!cache_fsfilt->fs_commit_async)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_commit_async(cache_inode, h, wait_handle);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_commit_wait(struct inode *inode, void *h)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ cache_inode = I2CI(inode);
+ if (cache_fsfilt == NULL)
+ RETURN(-EINVAL);
+
+ if (!cache_fsfilt->fs_commit_wait)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_commit_wait(cache_inode, h);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_setattr(struct dentry *dentry, void *handle,
+ struct iattr *iattr, int do_trunc)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_inode);
+ struct dentry *cache_dentry = NULL;
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(dentry->d_inode, cache_inode);
+
+ if (!cache_fsfilt->fs_setattr)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_setattr(cache_dentry, handle,
+ iattr, do_trunc);
+
+ post_smfs_inode(dentry->d_inode, cache_inode);
+
+exit:
+ post_smfs_dentry(cache_dentry);
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_iocontrol(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ struct smfs_file_info *sfi = NULL;
+ int rc = -EIO;
+ ENTRY;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ RETURN(rc);
+
+ if (file != NULL) {
+ sfi = F2SMFI(file);
+
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+ } else {
+ sfi = NULL;
+ }
+
+ if (!cache_fsfilt->fs_iocontrol)
+ RETURN(-ENOSYS);
+
+ if (sfi) {
+ rc = cache_fsfilt->fs_iocontrol(cache_inode,
+ sfi->c_file,
+ cmd, arg);
+ } else {
+ rc = cache_fsfilt->fs_iocontrol(cache_inode,
+ NULL, cmd, arg);
+ }
+
+ /* FIXME-UMKA: Should this be in duplicate_inode()? */
+ if (rc == 0 && cmd == EXT3_IOC_SETFLAGS)
+ inode->i_flags = cache_inode->i_flags;
+
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_set_md(struct inode *inode, void *handle,
+ void *lmm, int lmm_size)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ pre_smfs_inode(inode, cache_inode);
+
+ if (!cache_fsfilt->fs_set_md)
+ RETURN(-ENOSYS);
+
+ down(&cache_inode->i_sem);
+
+ rc = cache_fsfilt->fs_set_md(cache_inode, handle,
+ lmm, lmm_size);
+
+ up(&cache_inode->i_sem);
+
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
+/* Must be called with i_sem held */
+static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, int lmm_size)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ pre_smfs_inode(inode, cache_inode);
+
+ if (!cache_fsfilt->fs_get_md)
+ RETURN(-ENOSYS);
+
+ down(&cache_inode->i_sem);
+
+ rc = cache_fsfilt->fs_get_md(cache_inode, lmm,
+ lmm_size);
+
+ up(&cache_inode->i_sem);
+
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+static int fsfilt_smfs_send_bio(struct inode *inode,
+ struct bio *bio)
+#else
+static int fsfilt_smfs_send_bio(struct inode *inode,
+ struct kiobuf *bio)
+#endif
+{
+ struct inode *cache_inode;
+ struct fsfilt_operations *cache_fsfilt;
+
+ cache_fsfilt = I2FOPS(inode);
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ if (!cache_fsfilt->fs_send_bio)
+ RETURN(-ENOSYS);
+
+ return cache_fsfilt->fs_send_bio(cache_inode, bio);
+}
+
+static struct page *
+fsfilt_smfs_getpage(struct inode *inode, long int index)
+{
+ struct fsfilt_operations *cache_fsfilt;
+ struct inode *cache_inode;
+
+ cache_fsfilt = I2FOPS(inode);
+ if (!cache_fsfilt)
+ RETURN(ERR_PTR(-EINVAL));
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(ERR_PTR(-EINVAL));
+
+ if (!cache_fsfilt->fs_getpage)
+ RETURN(ERR_PTR(-ENOSYS));
+
+ return cache_fsfilt->fs_getpage(cache_inode, index);
+}
+
+static ssize_t fsfilt_smfs_readpage(struct file *file, char *buf,
+ size_t count, loff_t *off)
+{
+ struct fsfilt_operations *cache_fsfilt;
+ struct smfs_file_info *sfi;
+ struct inode *cache_inode;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ ssize_t rc = -EIO;
+
+ ENTRY;
+
+ cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ cache_inode = I2CI(file->f_dentry->d_inode);
+ if (!cache_inode)
+ RETURN(rc);
+
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ if (off != &(file->f_pos)) {
+ cache_ppos = &tmp_ppos;
+ } else {
+ cache_ppos = &sfi->c_file->f_pos;
+ }
+ *cache_ppos = *off;
+
+ pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
+
+ if (cache_fsfilt->fs_readpage)
+ rc = cache_fsfilt->fs_readpage(sfi->c_file, buf,
+ count, cache_ppos);
+
+ *off = *cache_ppos;
+ post_smfs_inode(file->f_dentry->d_inode, cache_inode);
+ duplicate_file(file, sfi->c_file);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_add_journal_cb(struct obd_device *obd,
+ struct super_block *sb,
+ __u64 last_rcvd, void *handle,
+ fsfilt_cb_t cb_func,
+ void *cb_data)
+{
+ struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
+ struct super_block *csb = S2CSB(sb);
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+ if (cache_fsfilt->fs_add_journal_cb)
+ rc = cache_fsfilt->fs_add_journal_cb(obd, csb, last_rcvd,
+ handle, cb_func, cb_data);
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_statfs(struct super_block *sb, struct obd_statfs *osfs)
+{
+ struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
+ struct super_block *csb = S2CSB(sb);
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ if (!cache_fsfilt->fs_statfs)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_statfs(csb, osfs);
+ duplicate_sb(csb, sb);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_sync(struct super_block *sb)
+{
+ struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt;
+ struct super_block *csb = S2CSB(sb);
+ int rc = -EIO;
+
+ if(!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ if (!cache_fsfilt->fs_sync)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_sync(csb);
+
+ RETURN(rc);
+}
+
+int fsfilt_smfs_map_inode_page(struct inode *inode, struct page *page,
+ unsigned long *blocks, int *created, int create)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ RETURN(rc);
+
+ if (!cache_fsfilt->fs_map_inode_page)
+ RETURN(-ENOSYS);
+
+ down(&cache_inode->i_sem);
+ rc = cache_fsfilt->fs_map_inode_page(cache_inode, page,
+ blocks, created, create);
+ up(&cache_inode->i_sem);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_prep_san_write(struct inode *inode, long *blocks,
+ int nblocks, loff_t newsize)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ if (!cache_fsfilt->fs_prep_san_write)
+ RETURN(-ENOSYS);
+
+ down(&cache_inode->i_sem);
+ rc = cache_fsfilt->fs_prep_san_write(cache_inode, blocks,
+ nblocks, newsize);
+ up(&cache_inode->i_sem);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_read_record(struct file * file, void *buf,
+ int size, loff_t *offs)
+{
+ struct fsfilt_operations *cache_fsfilt;
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ ssize_t rc;
+
+ ENTRY;
+ cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(file->f_dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC) BUG();
+
+ if (offs != &(file->f_pos)) {
+ cache_ppos = &tmp_ppos;
+ } else {
+ cache_ppos = &sfi->c_file->f_pos;
+ }
+ *cache_ppos = *offs;
+
+ pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
+
+ if (!cache_fsfilt->fs_read_record)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_read_record(sfi->c_file, buf,
+ size, cache_ppos);
+
+ *offs = *cache_ppos;
+ post_smfs_inode(file->f_dentry->d_inode, cache_inode);
+ duplicate_file(file, sfi->c_file);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_write_record(struct file *file, void *buf, int bufsize,
+ loff_t *offs, int force_sync)
+{
+ struct fsfilt_operations *cache_fsfilt;
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ ssize_t rc = -EIO;
+
+ ENTRY;
+
+ cache_fsfilt = I2FOPS(file->f_dentry->d_inode);
+ if (!cache_fsfilt)
+ RETURN(-EINVAL);
+
+ cache_inode = I2CI(file->f_dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC) BUG();
+
+ if (offs != &(file->f_pos)) {
+ cache_ppos = &tmp_ppos;
+ } else {
+ cache_ppos = &sfi->c_file->f_pos;
+ }
+ *cache_ppos = *offs;
+
+ pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
+
+ if (!cache_fsfilt->fs_write_record)
+ RETURN(-ENOSYS);
+
+ rc = cache_fsfilt->fs_write_record(sfi->c_file, buf,
+ bufsize, cache_ppos, force_sync);
+ *offs = *cache_ppos;
+ post_smfs_inode(file->f_dentry->d_inode, cache_inode);
+ duplicate_file(file, sfi->c_file);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_setup(struct super_block *sb)
+{
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+ struct fsfilt_operations *cache_fsfilt;
+ struct super_block *csb;
+ int rc = 0;
+
+ /* It should be initialized olready by smfs_read_super(). */
+ if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt))
+ cache_fsfilt = fsfilt_get_ops(smfs_info->cache_fs_type);
+
+ if (!cache_fsfilt)
+ RETURN(-ENOENT);
+
+ csb = S2CSB(sb);
+
+ if (cache_fsfilt->fs_setup)
+ rc = cache_fsfilt->fs_setup(csb);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_set_xattr(struct inode *inode, void *handle,
+ char *name, void *buffer,
+ int buffer_size)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(rc);
+
+ pre_smfs_inode(inode, cache_inode);
+
+ if (cache_fsfilt->fs_set_xattr)
+ rc = cache_fsfilt->fs_set_xattr(cache_inode, handle, name,
+ buffer, buffer_size);
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
+static int fsfilt_smfs_get_xattr(struct inode *inode, char *name,
+ void *buffer, int buffer_size)
+{
+ struct fsfilt_operations *cache_fsfilt = I2FOPS(inode);
+ struct inode *cache_inode = NULL;
+ int rc = -EIO;
+
+ if (!cache_fsfilt)
+ RETURN(rc);
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(rc);
+
+ pre_smfs_inode(inode, cache_inode);
+
+ if (cache_fsfilt->fs_get_xattr)
+ rc = cache_fsfilt->fs_get_xattr(cache_inode, name,
+ buffer, buffer_size);
+ post_smfs_inode(inode, cache_inode);
+
+ RETURN(rc);
+}
+
+static struct fsfilt_operations fsfilt_smfs_ops = {
+ .fs_type = "smfs",
+ .fs_owner = THIS_MODULE,
+ .fs_start = fsfilt_smfs_start,
+ .fs_brw_start = fsfilt_smfs_brw_start,
+ .fs_commit = fsfilt_smfs_commit,
+ .fs_commit_async = fsfilt_smfs_commit_async,
+ .fs_commit_wait = fsfilt_smfs_commit_wait,
+ .fs_setattr = fsfilt_smfs_setattr,
+ .fs_iocontrol = fsfilt_smfs_iocontrol,
+ .fs_set_md = fsfilt_smfs_set_md,
+ .fs_get_md = fsfilt_smfs_get_md,
+ .fs_readpage = fsfilt_smfs_readpage,
+ .fs_getpage = fsfilt_smfs_getpage,
+ .fs_add_journal_cb = fsfilt_smfs_add_journal_cb,
+ .fs_statfs = fsfilt_smfs_statfs,
+ .fs_sync = fsfilt_smfs_sync,
+ .fs_map_inode_page = fsfilt_smfs_map_inode_page,
+ .fs_prep_san_write = fsfilt_smfs_prep_san_write,
+ .fs_write_record = fsfilt_smfs_write_record,
+ .fs_read_record = fsfilt_smfs_read_record,
+ .fs_setup = fsfilt_smfs_setup,
+ .fs_send_bio = fsfilt_smfs_send_bio,
+ .fs_set_xattr = fsfilt_smfs_set_xattr,
+ .fs_get_xattr = fsfilt_smfs_get_xattr,
+
+ /* FIXME-UMKA: probably fsfilt_smfs_get_op_len() should be put here
+ * too. */
+};
+
+static int __init fsfilt_smfs_init(void)
+{
+ int rc;
+
+ rc = fsfilt_register_ops(&fsfilt_smfs_ops);
+ return rc;
+}
+
+static void __exit fsfilt_smfs_exit(void)
+{
+ fsfilt_unregister_ops(&fsfilt_smfs_ops);
+}
+
+module_init(fsfilt_smfs_init);
+module_exit(fsfilt_smfs_exit);
+
+MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
+MODULE_DESCRIPTION("Lustre SMFS Filesystem Helper v0.1");
+MODULE_LICENSE("GPL");
#include <liblustre.h>
#endif
-#include <linux/obd_class.h>
#include <linux/lustre_log.h>
-#include <portals/list.h>
/* Allocate a new log or catalog handle */
struct llog_handle *llog_alloc_handle(void)
}
EXPORT_SYMBOL(llog_alloc_handle);
-
void llog_free_handle(struct llog_handle *loghandle)
{
if (!loghandle)
if (!loghandle->lgh_hdr)
goto out;
- if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)
+ if (le32_to_cpu(loghandle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)
list_del_init(&loghandle->u.phd.phd_entry);
- if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
+ if (le32_to_cpu(loghandle->lgh_hdr->llh_flags) & LLOG_F_IS_CAT)
LASSERT(list_empty(&loghandle->u.chd.chd_head));
OBD_FREE(loghandle->lgh_hdr, LLOG_CHUNK_SIZE);
RETURN(-EINVAL);
}
- llh->llh_count--;
+ llh->llh_count = cpu_to_le32(le32_to_cpu(llh->llh_count) - 1);
- if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
- (llh->llh_count == 1) &&
+ if ((le32_to_cpu(llh->llh_flags) & LLOG_F_ZAP_WHEN_EMPTY) &&
+ (le32_to_cpu(llh->llh_count) == 1) &&
(loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
rc = llog_destroy(loghandle);
if (rc)
RETURN(-ENOMEM);
handle->lgh_hdr = llh;
/* first assign flags to use llog_client_ops */
- llh->llh_flags = flags;
+ llh->llh_flags = cpu_to_le32(flags);
rc = llog_read_header(handle);
if (rc == 0) {
- flags = llh->llh_flags;
+ flags = le32_to_cpu(llh->llh_flags);
if (uuid)
LASSERT(obd_uuid_equals(uuid, &llh->llh_tgtuuid));
GOTO(out, rc);
rc = 0;
handle->lgh_last_idx = 0; /* header is record with index 0 */
- llh->llh_count = 1; /* for the header record */
- llh->llh_hdr.lrh_type = LLOG_HDR_MAGIC;
- llh->llh_hdr.lrh_len = llh->llh_tail.lrt_len = LLOG_CHUNK_SIZE;
+ llh->llh_count = cpu_to_le32(1); /* for the header record */
+ llh->llh_hdr.lrh_type = cpu_to_le32(LLOG_HDR_MAGIC);
+ llh->llh_hdr.lrh_len = llh->llh_tail.lrt_len =
+ cpu_to_le32(LLOG_CHUNK_SIZE);
llh->llh_hdr.lrh_index = llh->llh_tail.lrt_index = 0;
- llh->llh_timestamp = LTIME_S(CURRENT_TIME);
+ llh->llh_timestamp = cpu_to_le64(LTIME_S(CURRENT_TIME));
if (uuid)
memcpy(&llh->llh_tgtuuid, uuid, sizeof(llh->llh_tgtuuid));
- llh->llh_bitmap_offset = offsetof(typeof(*llh),llh_bitmap);
+ llh->llh_bitmap_offset = cpu_to_le32(offsetof(typeof(*llh),llh_bitmap));
ext2_set_bit(0, llh->llh_bitmap);
out:
if (flags & LLOG_F_IS_CAT) {
INIT_LIST_HEAD(&handle->u.chd.chd_head);
- llh->llh_size = sizeof(struct llog_logid_rec);
+ llh->llh_size = cpu_to_le32(sizeof(struct llog_logid_rec));
}
else if (flags & LLOG_F_IS_PLAIN)
INIT_LIST_HEAD(&handle->u.phd.phd_entry);
GOTO(out, rc);
rec = buf;
- idx = rec->lrh_index;
+ idx = le32_to_cpu(rec->lrh_index);
if (idx < index)
CDEBUG(D_HA, "index %u : idx %u\n", index, idx);
while (idx < index) {
- rec = (struct llog_rec_hdr *)
- ((char *)rec + rec->lrh_len);
+ rec = ((void *)rec + le32_to_cpu(rec->lrh_len));
idx ++;
}
++index;
if (index > last_index)
GOTO(out, rc = 0);
- rec = (struct llog_rec_hdr *)
- ((char *)rec + rec->lrh_len);
+ rec = ((void *)rec + le32_to_cpu(rec->lrh_len));
}
}
RETURN(rc);
}
EXPORT_SYMBOL(llog_process);
+
+int llog_reverse_process(struct llog_handle *loghandle, llog_cb_t cb,
+ void *data, void *catdata)
+{
+ struct llog_log_hdr *llh = loghandle->lgh_hdr;
+ struct llog_process_cat_data *cd = catdata;
+ void *buf;
+ int rc = 0, first_index = 1, index, idx;
+ struct llog_rec_tail *tail;
+ ENTRY;
+
+ OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
+ if (!buf)
+ RETURN(-ENOMEM);
+
+ if (cd != NULL)
+ first_index = cd->first_idx + 1;
+ if (cd != NULL && cd->last_idx)
+ index = cd->last_idx;
+ else
+ index = LLOG_BITMAP_BYTES * 8 - 1;
+
+ while (rc == 0) {
+ struct llog_rec_hdr *rec;
+
+ /* skip records not set in bitmap */
+ while (index >= first_index &&
+ !ext2_test_bit(index, llh->llh_bitmap))
+ --index;
+
+ LASSERT(index >= first_index - 1);
+ if (index == first_index - 1)
+ break;
+
+ /* get the buf with our target record; avoid old garbage */
+ memset(buf, 0, LLOG_CHUNK_SIZE);
+ rc = llog_prev_block(loghandle, index, buf, LLOG_CHUNK_SIZE);
+ if (rc)
+ GOTO(out, rc);
+
+ rec = buf;
+ idx = le32_to_cpu(rec->lrh_index);
+ if (idx < index)
+ CDEBUG(D_HA, "index %u : idx %u\n", index, idx);
+ while (idx < index) {
+ rec = ((void *)rec + le32_to_cpu(rec->lrh_len));
+ idx ++;
+ }
+
+ /* process records in buffer, starting where we found one */
+ while ((void *)rec >= buf) {
+ if (rec->lrh_index == 0)
+ GOTO(out, 0); /* no more records */
+
+ /* if set, process the callback on this record */
+ if (ext2_test_bit(index, llh->llh_bitmap)) {
+ rc = cb(loghandle, rec, data);
+ if (rc == LLOG_PROC_BREAK) {
+ CWARN("recovery from log: "LPX64":%x"
+ " stopped\n",
+ loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen);
+ GOTO(out, rc);
+ }
+ if (rc)
+ GOTO(out, rc);
+ }
+
+ /* previous record, still in buffer? */
+ --index;
+ if (index < first_index)
+ GOTO(out, rc = 0);
+ tail = (void *)rec - sizeof(struct llog_rec_tail);
+ rec = ((void *)rec - le32_to_cpu(tail->lrt_len));
+ }
+ }
+
+ out:
+ if (buf)
+ OBD_FREE(buf, LLOG_CHUNK_SIZE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_reverse_process);
#include <liblustre.h>
#endif
-#include <linux/obd_class.h>
#include <linux/lustre_log.h>
#include <portals/list.h>
{
struct llog_handle *loghandle;
struct llog_log_hdr *llh;
- struct llog_logid_rec rec = { { 0 }, };
+ struct llog_logid_rec rec;
int rc, index, bitmap_size;
ENTRY;
index = (cathandle->lgh_last_idx + 1) % bitmap_size;
- /* maximum number of available slots in catlog is bitmap_size - 2 */
- if (llh->llh_cat_idx == index) {
+ /* maximum number of available slots in catalog is bitmap_size - 2 */
+ if (llh->llh_cat_idx == cpu_to_le32(index)) {
CERROR("no free catalog slots for log...\n");
RETURN(ERR_PTR(-ENOSPC));
} else {
LBUG(); /* should never happen */
}
cathandle->lgh_last_idx = index;
- llh->llh_count++;
- llh->llh_tail.lrt_index = index;
+ llh->llh_count = cpu_to_le32(le32_to_cpu(llh->llh_count) + 1);
+ llh->llh_tail.lrt_index = cpu_to_le32(index);
}
rc = llog_create(cathandle->lgh_ctxt, &loghandle, NULL, NULL);
LPX64"\n", loghandle->lgh_id.lgl_oid, loghandle->lgh_id.lgl_ogen,
index, cathandle->lgh_id.lgl_oid);
/* build the record for this log in the catalog */
- rec.lid_hdr.lrh_len = sizeof(rec);
- rec.lid_hdr.lrh_index = index;
- rec.lid_hdr.lrh_type = LLOG_LOGID_MAGIC;
+ rec.lid_hdr.lrh_len = cpu_to_le32(sizeof(rec));
+ rec.lid_hdr.lrh_index = cpu_to_le32(index);
+ rec.lid_hdr.lrh_type = cpu_to_le32(LLOG_LOGID_MAGIC);
rec.lid_id = loghandle->lgh_id;
- rec.lid_tail.lrt_len = sizeof(rec);
- rec.lid_tail.lrt_index = index;
+ rec.lid_tail.lrt_len = cpu_to_le32(sizeof(rec));
+ rec.lid_tail.lrt_index = cpu_to_le32(index);
/* update the catalog: header and record */
rc = llog_write_rec(cathandle, &rec.lid_hdr,
GOTO(out_destroy, rc);
}
- loghandle->lgh_hdr->llh_cat_idx = index;
+ loghandle->lgh_hdr->llh_cat_idx = cpu_to_le32(index);
cathandle->u.chd.chd_current_log = loghandle;
LASSERT(list_empty(&loghandle->u.phd.phd_entry));
list_add_tail(&loghandle->u.phd.phd_entry, &cathandle->u.chd.chd_head);
RETURN(loghandle);
}
-EXPORT_SYMBOL(llog_cat_new_log);
/* Open an existent log handle and add it to the open list.
* This log handle will be closed when all of the records in it are removed.
* We return a lock on the handle to ensure nobody yanks it from us.
*/
int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
- struct llog_logid *logid)
+ struct llog_logid *logid)
{
struct llog_handle *loghandle;
int rc = 0;
if (!rc) {
loghandle->u.phd.phd_cat_handle = cathandle;
loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id;
- loghandle->u.phd.phd_cookie.lgc_index =
- loghandle->lgh_hdr->llh_cat_idx;
+ loghandle->u.phd.phd_cookie.lgc_index =
+ le32_to_cpu(loghandle->lgh_hdr->llh_cat_idx);
}
out:
*res = loghandle;
RETURN(rc);
}
+EXPORT_SYMBOL(llog_cat_id2handle);
int llog_cat_put(struct llog_handle *cathandle)
{
int rc;
ENTRY;
- LASSERT(rec->lrh_len <= LLOG_CHUNK_SIZE);
+ LASSERT(le32_to_cpu(rec->lrh_len) <= LLOG_CHUNK_SIZE);
loghandle = llog_cat_current_log(cathandle, 1);
if (IS_ERR(loghandle))
RETURN(PTR_ERR(loghandle));
/* loghandle is already locked by llog_cat_current_log() for us */
rc = llog_write_rec(loghandle, rec, reccookie, 1, buf, -1);
up_write(&loghandle->lgh_lock);
- if (rc == -ENOSPC) {
- /* to create a new plain log */
- loghandle = llog_cat_current_log(cathandle, 1);
- if (IS_ERR(loghandle))
- RETURN(PTR_ERR(loghandle));
- rc = llog_write_rec(loghandle, rec, reccookie, 1, buf, -1);
- up_write(&loghandle->lgh_lock);
- }
RETURN(rc);
}
* Assumes caller has already pushed us into the kernel context.
*/
int llog_cat_cancel_records(struct llog_handle *cathandle, int count,
- struct llog_cookie *cookies)
+ struct llog_cookie *cookies)
{
int i, index, rc = 0;
ENTRY;
}
EXPORT_SYMBOL(llog_cat_cancel_records);
-int llog_cat_process_cb(struct llog_handle *cat_llh, struct llog_rec_hdr *rec,
- void *data)
+static int llog_cat_process_cb(struct llog_handle *cat_llh,
+ struct llog_rec_hdr *rec, void *data)
{
struct llog_process_data *d = data;
struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
struct llog_handle *llh;
int rc;
- if (rec->lrh_type != LLOG_LOGID_MAGIC) {
+ if (le32_to_cpu(rec->lrh_type) != LLOG_LOGID_MAGIC) {
CERROR("invalid record in catalog\n");
RETURN(-EINVAL);
}
CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
- rec->lrh_index, cat_llh->lgh_id.lgl_oid);
+ le32_to_cpu(rec->lrh_index), cat_llh->lgh_id.lgl_oid);
rc = llog_cat_id2handle(cat_llh, &llh, &lir->lid_id);
if (rc) {
int rc;
ENTRY;
- LASSERT(llh->llh_flags & LLOG_F_IS_CAT);
+ LASSERT(llh->llh_flags &cpu_to_le32(LLOG_F_IS_CAT));
d.lpd_data = data;
d.lpd_cb = cb;
if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
- CWARN("catlog "LPX64" crosses index zero\n",
+ CWARN("catalog "LPX64" crosses index zero\n",
cat_llh->lgh_id.lgl_oid);
- cd.first_idx = llh->llh_cat_idx;
+ cd.first_idx = le32_to_cpu(llh->llh_cat_idx);
cd.last_idx = 0;
rc = llog_process(cat_llh, llog_cat_process_cb, &d, &cd);
if (rc != 0)
}
EXPORT_SYMBOL(llog_cat_process);
+static int llog_cat_reverse_process_cb(struct llog_handle *cat_llh,
+ struct llog_rec_hdr *rec, void *data)
+{
+ struct llog_process_data *d = data;
+ struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
+ struct llog_handle *llh;
+ int rc;
+
+ if (le32_to_cpu(rec->lrh_type) != LLOG_LOGID_MAGIC) {
+ CERROR("invalid record in catalog\n");
+ RETURN(-EINVAL);
+ }
+ CWARN("processing log "LPX64":%x at index %u of catalog "LPX64"\n",
+ lir->lid_id.lgl_oid, lir->lid_id.lgl_ogen,
+ le32_to_cpu(rec->lrh_index), cat_llh->lgh_id.lgl_oid);
+
+ rc = llog_cat_id2handle(cat_llh, &llh, &lir->lid_id);
+ if (rc) {
+ CERROR("Cannot find handle for log "LPX64"\n",
+ lir->lid_id.lgl_oid);
+ RETURN(rc);
+ }
+
+ rc = llog_reverse_process(llh, d->lpd_cb, d->lpd_data, NULL);
+ RETURN(rc);
+}
+
+int llog_cat_reverse_process(struct llog_handle *cat_llh,
+ llog_cb_t cb, void *data)
+{
+ struct llog_process_data d;
+ struct llog_process_cat_data cd;
+ struct llog_log_hdr *llh = cat_llh->lgh_hdr;
+ int rc;
+ ENTRY;
+
+ LASSERT(llh->llh_flags &cpu_to_le32(LLOG_F_IS_CAT));
+ d.lpd_data = data;
+ d.lpd_cb = cb;
+
+ if (llh->llh_cat_idx > cat_llh->lgh_last_idx) {
+ CWARN("catalog "LPX64" crosses index zero\n",
+ cat_llh->lgh_id.lgl_oid);
+
+ cd.first_idx = 0;
+ cd.last_idx = cat_llh->lgh_last_idx;
+ rc = llog_reverse_process(cat_llh, llog_cat_reverse_process_cb,
+ &d, &cd);
+ if (rc != 0)
+ RETURN(rc);
+
+ cd.first_idx = le32_to_cpu(llh->llh_cat_idx);
+ cd.last_idx = 0;
+ rc = llog_reverse_process(cat_llh, llog_cat_reverse_process_cb,
+ &d, &cd);
+ } else {
+ rc = llog_reverse_process(cat_llh, llog_cat_reverse_process_cb,
+ &d, NULL);
+ }
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_cat_reverse_process);
+
int llog_cat_set_first_idx(struct llog_handle *cathandle, int index)
{
struct llog_log_hdr *llh = cathandle->lgh_hdr;
ENTRY;
bitmap_size = sizeof(llh->llh_bitmap) * 8;
- if (llh->llh_cat_idx == (index - 1)) {
- idx = llh->llh_cat_idx + 1;
- llh->llh_cat_idx = idx;
+ if (llh->llh_cat_idx == cpu_to_le32(index - 1)) {
+ idx = le32_to_cpu(llh->llh_cat_idx) + 1;
+ llh->llh_cat_idx = cpu_to_le32(idx);
if (idx == cathandle->lgh_last_idx)
goto out;
for (i = (index + 1) % bitmap_size;
i != cathandle->lgh_last_idx;
i = (i + 1) % bitmap_size) {
if (!ext2_test_bit(i, llh->llh_bitmap)) {
- idx = llh->llh_cat_idx + 1;
- llh->llh_cat_idx = idx;
+ idx = le32_to_cpu(llh->llh_cat_idx) + 1;
+ llh->llh_cat_idx = cpu_to_le32(idx);
} else if (i == 0) {
llh->llh_cat_idx = 0;
} else {
}
}
out:
- CDEBUG(D_HA, "set catlog "LPX64" first idx %u\n",
- cathandle->lgh_id.lgl_oid, llh->llh_cat_idx);
+ CDEBUG(D_HA, "set catalog "LPX64" first idx %u\n",
+ cathandle->lgh_id.lgl_oid,le32_to_cpu(llh->llh_cat_idx));
}
RETURN(0);
}
+EXPORT_SYMBOL(llog_cat_set_first_idx);
-#if 0
-/* Assumes caller has already pushed us into the kernel context. */
-int llog_cat_init(struct llog_handle *cathandle, struct obd_uuid *tgtuuid)
+int llog_catalog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *logcookies,
+ int numcookies, void *data)
{
- struct llog_log_hdr *llh;
- loff_t offset = 0;
- int rc = 0;
+ struct llog_handle *cathandle;
+ int rc;
ENTRY;
+
+ cathandle = ctxt->loc_handle;
+ LASSERT(cathandle != NULL);
+
+ rc = llog_cat_add_rec(cathandle, rec, logcookies, buf);
+ if (rc != 1)
+ CERROR("write one catalog record failed: %d\n", rc);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_catalog_add);
- LASSERT(sizeof(*llh) == LLOG_CHUNK_SIZE);
+int llog_catalog_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data)
+{
+ struct llog_handle *cathandle;
+ int rc;
+ ENTRY;
- down(&cathandle->lgh_lock);
- llh = cathandle->lgh_hdr;
+ if (cookies == NULL || count == 0)
+ RETURN(-EINVAL);
+ cathandle = ctxt->loc_handle;
+ LASSERT(cathandle != NULL);
+ rc = llog_cat_cancel_records(cathandle, count, cookies);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_catalog_cancel);
- if (cathandle->lgh_file->f_dentry->d_inode->i_size == 0) {
- llog_write_rec(cathandle, &llh->llh_hdr, NULL, 0, NULL, 0);
-
-write_hdr:
- rc = lustre_fwrite(cathandle->lgh_file, llh, LLOG_CHUNK_SIZE,
- &offset);
- if (rc != LLOG_CHUNK_SIZE) {
- CERROR("error writing catalog header: rc %d\n", rc);
- OBD_FREE(llh, sizeof(*llh));
- if (rc >= 0)
- rc = -ENOSPC;
- } else
- rc = 0;
- } else {
- rc = lustre_fread(cathandle->lgh_file, llh, LLOG_CHUNK_SIZE,
- &offset);
- if (rc != LLOG_CHUNK_SIZE) {
- CERROR("error reading catalog header: rc %d\n", rc);
- /* Can we do much else if the header is bad? */
- goto write_hdr;
- } else
- rc = 0;
+int llog_catalog_setup(struct llog_ctxt **res, char *name,
+ struct lvfs_run_ctxt *lvfs_ctxt,
+ struct fsfilt_operations *fsops,
+ struct dentry *logs_de,
+ struct dentry *objects_de)
+{
+ struct llog_ctxt *ctxt;
+ struct llog_catid catid;
+ struct llog_handle *handle;
+ int rc;
+
+ ENTRY;
+
+ OBD_ALLOC(ctxt, sizeof(*ctxt));
+ if (!ctxt)
+ RETURN(-ENOMEM);
+
+ *res = ctxt;
+
+ ctxt->loc_fsops = fsops;
+ ctxt->loc_lvfs_ctxt = lvfs_ctxt;
+ ctxt->loc_logs_dir = logs_de;
+ ctxt->loc_objects_dir = objects_de;
+ ctxt->loc_logops = &llog_lvfs_ops;
+ ctxt->loc_logops->lop_add = llog_catalog_add;
+ ctxt->loc_logops->lop_cancel = llog_catalog_cancel;
+
+ memset(&catid, 0, sizeof(struct llog_catid));
+ rc = llog_get_cat_list(lvfs_ctxt, fsops, name, 1, &catid);
+ if (rc) {
+ CERROR("error llog_get_cat_list rc: %d\n", rc);
+ RETURN(rc);
+ }
+ if (catid.lci_logid.lgl_oid)
+ rc = llog_create(ctxt, &handle, &catid.lci_logid, 0);
+ else {
+ rc = llog_create(ctxt, &handle, NULL, NULL);
+ if (!rc)
+ catid.lci_logid = handle->lgh_id;
}
+ if (rc)
+ GOTO(out, rc);
- cathandle->lgh_tgtuuid = &llh->llh_tgtuuid;
- up(&cathandle->lgh_lock);
+ ctxt->loc_handle = handle;
+ rc = llog_init_handle(handle, LLOG_F_IS_CAT, NULL);
+ if (rc)
+ GOTO(out, rc);
+
+ rc = llog_put_cat_list(lvfs_ctxt, fsops, name, 1, &catid);
+ if (rc)
+ CERROR("error llog_get_cat_list rc: %d\n", rc);
+out:
+ if (ctxt && rc)
+ OBD_FREE(ctxt, sizeof(*ctxt));
RETURN(rc);
}
-EXPORT_SYMBOL(llog_cat_init);
+EXPORT_SYMBOL(llog_catalog_setup);
-#endif
+int llog_catalog_cleanup(struct llog_ctxt *ctxt)
+{
+ struct llog_handle *cathandle, *n, *loghandle;
+ struct llog_log_hdr *llh;
+ int rc, index;
+ ENTRY;
+
+ if (!ctxt)
+ return 0;
+
+ cathandle = ctxt->loc_handle;
+ if (cathandle) {
+ list_for_each_entry_safe(loghandle, n,
+ &cathandle->u.chd.chd_head,
+ u.phd.phd_entry) {
+ llh = loghandle->lgh_hdr;
+ if ((le32_to_cpu(llh->llh_flags) &
+ LLOG_F_ZAP_WHEN_EMPTY) &&
+ (le32_to_cpu(llh->llh_count) == 1)) {
+ rc = llog_destroy(loghandle);
+ if (rc)
+ CERROR("failure destroying log during "
+ "cleanup: %d\n", rc);
+ LASSERT(rc == 0);
+ index = loghandle->u.phd.phd_cookie.lgc_index;
+ llog_free_handle(loghandle);
+
+ LASSERT(index);
+ llog_cat_set_first_idx(cathandle, index);
+ rc = llog_cancel_rec(cathandle, index);
+ if (rc == 0)
+ CDEBUG(D_HA, "cancel plain log at index"
+ " %u of catalog "LPX64"\n",
+ index,cathandle->lgh_id.lgl_oid);
+ }
+ }
+ llog_cat_put(ctxt->loc_handle);
+ }
+ OBD_FREE(ctxt, sizeof(*ctxt));
+ return 0;
+}
+EXPORT_SYMBOL(llog_catalog_cleanup);
+
+int llog_cat_half_bottom(struct llog_cookie *cookie, struct llog_handle *handle)
+{
+ struct llog_handle *loghandle;
+ struct llog_logid *lgl = &cookie->lgc_lgl;
+ int rc;
+
+ down_read(&handle->lgh_lock);
+ rc = llog_cat_id2handle(handle, &loghandle, lgl);
+ if (rc)
+ GOTO(out, rc);
+ if (2 * loghandle->lgh_hdr->llh_cat_idx <=
+ handle->lgh_last_idx + handle->lgh_hdr->llh_cat_idx + 1)
+ rc = 1;
+ else
+ rc = 0;
+out:
+ up_read(&handle->lgh_lock);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_cat_half_bottom);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2001-2003 Cluster File Systems, Inc.
+ * Author: Andreas Dilger <adilger@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.
+ *
+ * OST<->MDS recovery logging infrastructure.
+ *
+ * Invariants in implementation:
+ * - we do not share logs among different OST<->MDS connections, so that
+ * if an OST or MDS fails it need only look at log(s) relevant to itself
+ */
+
+#define DEBUG_SUBSYSTEM S_LOG
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
+#ifdef __KERNEL__
+#include <linux/fs.h>
+#else
+#include <liblustre.h>
+#endif
+
+#include <linux/lvfs.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_log.h>
+
+#ifdef __KERNEL__
+
+static int llog_lvfs_pad(struct llog_ctxt *ctxt, struct l_file *file,
+ int len, int index)
+{
+ struct llog_rec_hdr rec;
+ struct llog_rec_tail tail;
+ int rc;
+ ENTRY;
+
+ LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0);
+
+ tail.lrt_len = rec.lrh_len = cpu_to_le32(len);
+ tail.lrt_index = rec.lrh_index = cpu_to_le32(index);
+ rec.lrh_type = 0;
+
+ rc = llog_fsfilt_write_record(ctxt, file, &rec, sizeof(rec),
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing padding record: rc %d\n", rc);
+ goto out;
+ }
+
+ file->f_pos += len - sizeof(rec) - sizeof(tail);
+ rc = llog_fsfilt_write_record(ctxt, file, &tail, sizeof(tail),
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing padding record: rc %d\n", rc);
+ goto out;
+ }
+
+ out:
+ RETURN(rc);
+}
+
+static int llog_lvfs_write_blob(struct llog_ctxt *ctxt, struct l_file *file,
+ struct llog_rec_hdr *rec, void *buf, loff_t off)
+{
+ int rc;
+ struct llog_rec_tail end;
+ loff_t saved_off = file->f_pos;
+ int buflen = le32_to_cpu(rec->lrh_len);
+
+ ENTRY;
+ file->f_pos = off;
+
+ if (!buf) {
+ rc = llog_fsfilt_write_record(ctxt, file, rec, buflen,
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing log record: rc %d\n", rc);
+ goto out;
+ }
+ GOTO(out, rc = 0);
+ }
+
+ /* the buf case */
+ rec->lrh_len = cpu_to_le32(sizeof(*rec) + buflen + sizeof(end));
+ rc = llog_fsfilt_write_record(ctxt, file, rec, sizeof(*rec),
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing log hdr: rc %d\n", rc);
+ goto out;
+ }
+
+ rc = llog_fsfilt_write_record(ctxt, file, buf, buflen,
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing log buffer: rc %d\n", rc);
+ goto out;
+ }
+
+ end.lrt_len = rec->lrh_len;
+ end.lrt_index = rec->lrh_index;
+ rc = llog_fsfilt_write_record(ctxt, file, &end, sizeof(end),
+ &file->f_pos, 0);
+ if (rc) {
+ CERROR("error writing log tail: rc %d\n", rc);
+ goto out;
+ }
+
+ rc = 0;
+ out:
+ if (saved_off > file->f_pos)
+ file->f_pos = saved_off;
+ LASSERT(rc <= 0);
+ RETURN(rc);
+}
+
+static int llog_lvfs_read_blob(struct llog_ctxt *ctxt, struct l_file *file,
+ void *buf, int size, loff_t off)
+{
+ loff_t offset = off;
+ int rc;
+ ENTRY;
+
+ rc = llog_fsfilt_read_record(ctxt, file, buf, size, &offset);
+ if (rc) {
+ CERROR("error reading log record: rc %d\n", rc);
+ RETURN(rc);
+ }
+ RETURN(0);
+}
+
+static int llog_lvfs_read_header(struct llog_handle *handle)
+{
+ struct llog_ctxt *ctxt = handle->lgh_ctxt;
+ int rc;
+ ENTRY;
+
+ LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE);
+ LASSERT(ctxt != NULL);
+
+ if (handle->lgh_file->f_dentry->d_inode->i_size == 0) {
+ CDEBUG(D_HA, "not reading header from 0-byte log\n");
+ RETURN(LLOG_EEMPTY);
+ }
+
+ rc = llog_lvfs_read_blob(ctxt, handle->lgh_file, handle->lgh_hdr,
+ LLOG_CHUNK_SIZE, 0);
+ if (rc)
+ CERROR("error reading log header\n");
+
+ handle->lgh_last_idx = le32_to_cpu(handle->lgh_hdr->llh_tail.lrt_index);
+ handle->lgh_file->f_pos = handle->lgh_file->f_dentry->d_inode->i_size;
+
+ RETURN(rc);
+}
+
+/* returns negative in on error; 0 if success && reccookie == 0; 1 otherwise */
+/* appends if idx == -1, otherwise overwrites record idx. */
+static int llog_lvfs_write_rec(struct llog_handle *loghandle,
+ struct llog_rec_hdr *rec,
+ struct llog_cookie *reccookie,
+ int cookiecount,
+ void *buf, int idx)
+{
+ struct llog_log_hdr *llh;
+ int reclen = le32_to_cpu(rec->lrh_len), index, rc;
+ struct llog_rec_tail *lrt;
+ struct llog_ctxt *ctxt = loghandle->lgh_ctxt;
+ struct file *file;
+ loff_t offset;
+ size_t left;
+ ENTRY;
+
+ llh = loghandle->lgh_hdr;
+ file = loghandle->lgh_file;
+
+ /* record length should not bigger than LLOG_CHUNK_SIZE */
+ if (buf)
+ rc = (reclen > LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr)
+ - sizeof(struct llog_rec_tail)) ? -E2BIG : 0;
+ else
+ rc = (reclen > LLOG_CHUNK_SIZE) ? -E2BIG : 0;
+ if (rc)
+ RETURN(rc);
+
+ if (idx != -1) {
+ loff_t saved_offset;
+
+ /* no header: only allowed to insert record 1 */
+ if (idx != 1 && !file->f_dentry->d_inode->i_size) {
+ CERROR("idx != -1 in empty log\n");
+ LBUG();
+ }
+
+ if (idx && llh->llh_size && llh->llh_size != reclen)
+ RETURN(-EINVAL);
+
+ rc = llog_lvfs_write_blob(ctxt, file, &llh->llh_hdr, NULL, 0);
+ /* we are done if we only write the header or on error */
+ if (rc || idx == 0)
+ RETURN(rc);
+
+ saved_offset = sizeof(*llh) + (idx-1)*le32_to_cpu(rec->lrh_len);
+ rc = llog_lvfs_write_blob(ctxt, file, rec, buf, saved_offset);
+ if (rc == 0 && reccookie) {
+ reccookie->lgc_lgl = loghandle->lgh_id;
+ reccookie->lgc_index = idx;
+ rc = 1;
+ }
+ RETURN(rc);
+ }
+
+ /* Make sure that records don't cross a chunk boundary, so we can
+ * process them page-at-a-time if needed. If it will cross a chunk
+ * boundary, write in a fake (but referenced) entry to pad the chunk.
+ *
+ * We know that llog_current_log() will return a loghandle that is
+ * big enough to hold reclen, so all we care about is padding here.
+ */
+ left = LLOG_CHUNK_SIZE - (file->f_pos & (LLOG_CHUNK_SIZE - 1));
+ if (buf)
+ reclen = sizeof(*rec) + le32_to_cpu(rec->lrh_len) +
+ sizeof(struct llog_rec_tail);
+
+ /* NOTE: padding is a record, but no bit is set */
+ if (left != 0 && left != reclen &&
+ left < (reclen + LLOG_MIN_REC_SIZE)) {
+ loghandle->lgh_last_idx++;
+ rc = llog_lvfs_pad(ctxt, file, left, loghandle->lgh_last_idx);
+ if (rc)
+ RETURN(rc);
+ }
+
+ loghandle->lgh_last_idx++;
+ index = loghandle->lgh_last_idx;
+ rec->lrh_index = cpu_to_le32(index);
+ if (buf == NULL) {
+ lrt = (void *)rec + le32_to_cpu(rec->lrh_len) - sizeof(*lrt);
+ lrt->lrt_len = rec->lrh_len;
+ lrt->lrt_index = rec->lrh_index;
+ }
+ if (ext2_set_bit(index, llh->llh_bitmap)) {
+ CERROR("argh, index %u already set in log bitmap?\n", index);
+ LBUG(); /* should never happen */
+ }
+ llh->llh_count = cpu_to_le32(le32_to_cpu(llh->llh_count) + 1);
+ llh->llh_tail.lrt_index = cpu_to_le32(index);
+
+ offset = 0;
+ rc = llog_lvfs_write_blob(ctxt, file, &llh->llh_hdr, NULL, 0);
+ if (rc)
+ RETURN(rc);
+
+ rc = llog_lvfs_write_blob(ctxt, file, rec, buf, file->f_pos);
+ if (rc)
+ RETURN(rc);
+
+ CDEBUG(D_HA, "added record "LPX64": idx: %u, %u bytes\n",
+ loghandle->lgh_id.lgl_oid, index, le32_to_cpu(rec->lrh_len));
+ if (rc == 0 && reccookie) {
+ reccookie->lgc_lgl = loghandle->lgh_id;
+ reccookie->lgc_index = index;
+ if (le32_to_cpu(rec->lrh_type) == MDS_UNLINK_REC)
+ reccookie->lgc_subsys = LLOG_UNLINK_ORIG_CTXT;
+ else if (le32_to_cpu(rec->lrh_type) == OST_SZ_REC)
+ reccookie->lgc_subsys = LLOG_SIZE_ORIG_CTXT;
+ else if (le32_to_cpu(rec->lrh_type) == OST_RAID1_REC)
+ reccookie->lgc_subsys = LLOG_RD1_ORIG_CTXT;
+ else
+ reccookie->lgc_subsys = -1;
+ rc = 1;
+ }
+ if (rc == 0 && (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC ||
+ le32_to_cpu(rec->lrh_type) == SMFS_UPDATE_REC))
+ rc = 1;
+
+ RETURN(rc);
+}
+
+/* We can skip reading at least as many log blocks as the number of
+* minimum sized log records we are skipping. If it turns out
+* that we are not far enough along the log (because the
+* actual records are larger than minimum size) we just skip
+* some more records. */
+
+static void llog_skip_over(__u64 *off, int curr, int goal)
+{
+ if (goal <= curr)
+ return;
+ *off = (*off + (goal-curr-1) * LLOG_MIN_REC_SIZE) &
+ ~(LLOG_CHUNK_SIZE - 1);
+}
+
+/* sets:
+ * - curr_offset to the furthest point read in the log file
+ * - curr_idx to the log index preceeding curr_offset
+ * returns -EIO/-EINVAL on error
+ */
+static int llog_lvfs_next_block(struct llog_handle *loghandle, int *curr_idx,
+ int next_idx, __u64 *curr_offset, void *buf,
+ int len)
+{
+ struct llog_ctxt *ctxt = loghandle->lgh_ctxt;
+ int rc;
+ ENTRY;
+
+ if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
+ RETURN(-EINVAL);
+
+ CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
+ next_idx, *curr_idx, *curr_offset);
+
+ while (*curr_offset < loghandle->lgh_file->f_dentry->d_inode->i_size) {
+ struct llog_rec_hdr *rec;
+ struct llog_rec_tail *tail;
+ loff_t ppos;
+
+ llog_skip_over(curr_offset, *curr_idx, next_idx);
+
+ ppos = *curr_offset;
+ rc = llog_fsfilt_read_record(ctxt, loghandle->lgh_file,
+ buf, len, &ppos);
+
+ if (rc) {
+ CERROR("Cant read llog block at log id "LPU64
+ "/%u offset "LPU64"\n",
+ loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen,
+ *curr_offset);
+ RETURN(rc);
+ }
+
+ /* put number of bytes read into rc to make code simpler */
+ rc = ppos - *curr_offset;
+ *curr_offset = ppos;
+
+ if (rc == 0) /* end of file, nothing to do */
+ RETURN(0);
+
+ if (rc < sizeof(*tail)) {
+ CERROR("Invalid llog block at log id "LPU64"/%u offset "
+ LPU64"\n", loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen, *curr_offset);
+ RETURN(-EINVAL);
+ }
+
+ tail = buf + rc - sizeof(struct llog_rec_tail);
+ *curr_idx = le32_to_cpu(tail->lrt_index);
+
+ /* this shouldn't happen */
+ if (tail->lrt_index == 0) {
+ CERROR("Invalid llog tail at log id "LPU64"/%u offset "
+ LPU64"\n", loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen, *curr_offset);
+ RETURN(-EINVAL);
+ }
+ if (le32_to_cpu(tail->lrt_index) < next_idx)
+ continue;
+
+ /* sanity check that the start of the new buffer is no farther
+ * than the record that we wanted. This shouldn't happen. */
+ rec = buf;
+ if (le32_to_cpu(rec->lrh_index) > next_idx) {
+ CERROR("missed desired record? %u > %u\n",
+ le32_to_cpu(rec->lrh_index), next_idx);
+ RETURN(-ENOENT);
+ }
+ RETURN(0);
+ }
+ RETURN(-EIO);
+}
+
+static int llog_lvfs_prev_block(struct llog_handle *loghandle,
+ int prev_idx, void *buf, int len)
+{
+ struct llog_ctxt *ctxt = loghandle->lgh_ctxt;
+ __u64 curr_offset;
+ int rc;
+ ENTRY;
+
+ if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
+ RETURN(-EINVAL);
+
+ CDEBUG(D_OTHER, "looking for log index %u n", prev_idx);
+
+ curr_offset = LLOG_CHUNK_SIZE;
+ llog_skip_over(&curr_offset, 0, prev_idx);
+
+ while (curr_offset < loghandle->lgh_file->f_dentry->d_inode->i_size) {
+ struct llog_rec_hdr *rec;
+ struct llog_rec_tail *tail;
+ loff_t ppos;
+
+ ppos = curr_offset;
+ rc = llog_fsfilt_read_record(ctxt, loghandle->lgh_file,
+ buf, len, &ppos);
+
+ if (rc) {
+ CERROR("Cant read llog block at log id "LPU64
+ "/%u offset "LPU64"\n",
+ loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen,
+ curr_offset);
+ RETURN(rc);
+ }
+
+ /* put number of bytes read into rc to make code simpler */
+ rc = ppos - curr_offset;
+ curr_offset = ppos;
+
+ if (rc == 0) /* end of file, nothing to do */
+ RETURN(0);
+
+ if (rc < sizeof(*tail)) {
+ CERROR("Invalid llog block at log id "LPU64"/%u offset "
+ LPU64"\n", loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen, curr_offset);
+ RETURN(-EINVAL);
+ }
+
+ tail = buf + rc - sizeof(struct llog_rec_tail);
+
+ /* this shouldn't happen */
+ if (tail->lrt_index == 0) {
+ CERROR("Invalid llog tail at log id "LPU64"/%u offset "
+ LPU64"\n", loghandle->lgh_id.lgl_oid,
+ loghandle->lgh_id.lgl_ogen, curr_offset);
+ RETURN(-EINVAL);
+ }
+ if (le32_to_cpu(tail->lrt_index) < prev_idx)
+ continue;
+
+ /* sanity check that the start of the new buffer is no farther
+ * than the record that we wanted. This shouldn't happen. */
+ rec = buf;
+ if (le32_to_cpu(rec->lrh_index) > prev_idx) {
+ CERROR("missed desired record? %u > %u\n",
+ le32_to_cpu(rec->lrh_index), prev_idx);
+ RETURN(-ENOENT);
+ }
+ RETURN(0);
+ }
+ RETURN(-EIO);
+}
+
+static struct file *llog_filp_open(char *name, int flags, int mode)
+{
+ char *logname;
+ struct file *filp;
+ int len;
+
+ OBD_ALLOC(logname, PATH_MAX);
+ if (logname == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ len = snprintf(logname, PATH_MAX, "LOGS/%s", name);
+ if (len >= PATH_MAX - 1) {
+ filp = ERR_PTR(-ENAMETOOLONG);
+ } else {
+ filp = l_filp_open(logname, flags, mode);
+ if (IS_ERR(filp)) {
+ CERROR("logfile creation %s: %ld\n", logname,
+ PTR_ERR(filp));
+ }
+ }
+
+ OBD_FREE(logname, PATH_MAX);
+ return filp;
+}
+
+static struct file *llog_object_create(struct llog_ctxt *ctxt)
+{
+ unsigned int tmpname = ll_insecure_random_int();
+ char fidname[LL_FID_NAMELEN];
+ struct file *filp;
+ struct dentry *new_child, *parent;
+ void *handle;
+ int rc = 0, err, namelen;
+ ENTRY;
+
+ sprintf(fidname, "OBJECTS/%u", tmpname);
+ filp = filp_open(fidname, O_CREAT | O_EXCL, 0644);
+ if (IS_ERR(filp)) {
+ rc = PTR_ERR(filp);
+ if (rc == -EEXIST) {
+ CERROR("impossible object name collision %u\n",
+ tmpname);
+ LBUG();
+ }
+ CERROR("error creating tmp object %u: rc %d\n", tmpname, rc);
+ RETURN(filp);
+ }
+
+ namelen = ll_fid2str(fidname, filp->f_dentry->d_inode->i_ino,
+ filp->f_dentry->d_inode->i_generation);
+ parent = filp->f_dentry->d_parent;
+ down(&parent->d_inode->i_sem);
+ new_child = lookup_one_len(fidname, parent, namelen);
+ if (IS_ERR(new_child)) {
+ CERROR("getting neg dentry for obj rename: %d\n", rc);
+ GOTO(out_close, rc = PTR_ERR(new_child));
+ }
+ if (new_child->d_inode != NULL) {
+ CERROR("impossible non-negative obj dentry %lu:%u!\n",
+ filp->f_dentry->d_inode->i_ino,
+ filp->f_dentry->d_inode->i_generation);
+ LBUG();
+ }
+
+ handle = llog_fsfilt_start(ctxt, parent->d_inode, FSFILT_OP_RENAME, NULL);
+ if (IS_ERR(handle))
+ GOTO(out_dput, rc = PTR_ERR(handle));
+
+ lock_kernel();
+ rc = vfs_rename(parent->d_inode, filp->f_dentry,
+ parent->d_inode, new_child);
+ unlock_kernel();
+ if (rc)
+ CERROR("error renaming new object %lu:%u: rc %d\n",
+ filp->f_dentry->d_inode->i_ino,
+ filp->f_dentry->d_inode->i_generation, rc);
+
+ err = llog_fsfilt_commit(ctxt, parent->d_inode, handle, 0);
+ if (!rc)
+ rc = err;
+out_dput:
+ dput(new_child);
+out_close:
+ up(&parent->d_inode->i_sem);
+ if (rc) {
+ filp_close(filp, 0);
+ filp = (struct file *)rc;
+ }
+
+ RETURN(filp);
+}
+
+static int llog_add_link_object(struct llog_ctxt *ctxt, struct llog_logid logid,
+ struct dentry *dentry)
+{
+ struct dentry *new_child;
+ char fidname[LL_FID_NAMELEN];
+ void *handle;
+ int namelen, rc = 0, err;
+ ENTRY;
+
+ namelen = ll_fid2str(fidname, logid.lgl_oid, logid.lgl_ogen);
+ down(&ctxt->loc_objects_dir->d_inode->i_sem);
+ new_child = lookup_one_len(fidname, ctxt->loc_objects_dir, namelen);
+ if (IS_ERR(new_child)) {
+ CERROR("getting neg dentry for obj rename: %d\n", rc);
+ GOTO(out, rc = PTR_ERR(new_child));
+ }
+ if (new_child->d_inode == dentry->d_inode)
+ GOTO(out_dput, rc);
+ if (new_child->d_inode != NULL) {
+ CERROR("impossible non-negative obj dentry "LPX64":%u!\n",
+ logid.lgl_oid, logid.lgl_ogen);
+ LBUG();
+ }
+ handle = llog_fsfilt_start(ctxt, ctxt->loc_objects_dir->d_inode,
+ FSFILT_OP_LINK, NULL);
+ if (IS_ERR(handle))
+ GOTO(out_dput, rc = PTR_ERR(handle));
+
+ lock_kernel();
+ rc = vfs_link(dentry, ctxt->loc_objects_dir->d_inode, new_child);
+ unlock_kernel();
+ if (rc)
+ CERROR("error link new object "LPX64":%u: rc %d\n",
+ logid.lgl_oid, logid.lgl_ogen, rc);
+ err = llog_fsfilt_commit(ctxt, ctxt->loc_objects_dir->d_inode, handle, 0);
+out_dput:
+ l_dput(new_child);
+out:
+ up(&ctxt->loc_objects_dir->d_inode->i_sem);
+ RETURN(rc);
+}
+
+/* This is a callback from the llog_* functions.
+ * Assumes caller has already pushed us into the kernel context. */
+static int llog_lvfs_create(struct llog_ctxt *ctxt, struct llog_handle **res,
+ struct llog_logid *logid, char *name)
+{
+ struct llog_handle *handle;
+ struct lvfs_run_ctxt saved;
+ int rc = 0;
+ int open_flags = O_RDWR | O_CREAT | O_LARGEFILE;
+ ENTRY;
+
+ handle = llog_alloc_handle();
+ if (handle == NULL)
+ RETURN(-ENOMEM);
+ *res = handle;
+
+ LASSERT(ctxt);
+ if (ctxt->loc_lvfs_ctxt)
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+
+ if (logid != NULL) {
+ char logname[LL_FID_NAMELEN + 10] = "OBJECTS/";
+ char fidname[LL_FID_NAMELEN];
+ ll_fid2str(fidname, logid->lgl_oid, logid->lgl_ogen);
+ strcat(logname, fidname);
+
+ handle->lgh_file = filp_open(logname, O_RDWR | O_LARGEFILE, 0644);
+ if (IS_ERR(handle->lgh_file)) {
+ CERROR("cannot open %s file\n", logname);
+ GOTO(cleanup, rc = PTR_ERR(handle->lgh_file));
+ }
+ if (!S_ISREG(handle->lgh_file->f_dentry->d_inode->i_mode)) {
+ CERROR("%s is not a regular file!: mode = %o\n", logname,
+ handle->lgh_file->f_dentry->d_inode->i_mode);
+ GOTO(cleanup, rc = -ENOENT);
+ }
+ LASSERT(handle->lgh_file->f_dentry->d_parent == ctxt->loc_objects_dir);
+ handle->lgh_id = *logid;
+ } else if (name) {
+ handle->lgh_file = llog_filp_open(name, open_flags, 0644);
+ if (IS_ERR(handle->lgh_file))
+ GOTO(cleanup, rc = PTR_ERR(handle->lgh_file));
+ LASSERT(handle->lgh_file->f_dentry->d_parent == ctxt->loc_logs_dir);
+
+ handle->lgh_id.lgl_oid = handle->lgh_file->f_dentry->d_inode->i_ino;
+ handle->lgh_id.lgl_ogen = handle->lgh_file->f_dentry->d_inode->i_generation;
+ rc = llog_add_link_object(ctxt, handle->lgh_id, handle->lgh_file->f_dentry);
+ if (rc)
+ GOTO(cleanup, rc);
+ } else {
+ handle->lgh_file = llog_object_create(ctxt);
+ if (IS_ERR(handle->lgh_file))
+ GOTO(cleanup, rc = PTR_ERR(handle->lgh_file));
+ LASSERT(handle->lgh_file->f_dentry->d_parent == ctxt->loc_objects_dir);
+ handle->lgh_id.lgl_oid = handle->lgh_file->f_dentry->d_inode->i_ino;
+ handle->lgh_id.lgl_ogen = handle->lgh_file->f_dentry->d_inode->i_generation;
+ }
+
+ handle->lgh_id.lgl_ogr = 1;
+ handle->lgh_ctxt = ctxt;
+ finish:
+ if (ctxt->loc_lvfs_ctxt)
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+ RETURN(rc);
+cleanup:
+ llog_free_handle(handle);
+ goto finish;
+}
+
+static int llog_lvfs_close(struct llog_handle *handle)
+{
+ int rc;
+ ENTRY;
+
+ rc = filp_close(handle->lgh_file, 0);
+ if (rc)
+ CERROR("error closing log: rc %d\n", rc);
+ RETURN(rc);
+}
+
+static int llog_lvfs_destroy(struct llog_handle *loghandle)
+{
+ struct llog_ctxt *ctxt = loghandle->lgh_ctxt;
+ struct lvfs_run_ctxt saved;
+ struct dentry *fdentry;
+ struct inode *parent_inode;
+ char fidname[LL_FID_NAMELEN];
+ void *handle;
+ int rc = -EINVAL, err, namelen;
+ ENTRY;
+
+ if (ctxt->loc_lvfs_ctxt)
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+
+ fdentry = loghandle->lgh_file->f_dentry;
+ parent_inode = fdentry->d_parent->d_inode;
+
+ if (!strcmp(fdentry->d_parent->d_name.name, "LOGS")) {
+ LASSERT(parent_inode == ctxt->loc_logs_dir->d_inode);
+
+ namelen = ll_fid2str(fidname, fdentry->d_inode->i_ino,
+ fdentry->d_inode->i_generation);
+ dget(fdentry);
+ rc = llog_lvfs_close(loghandle);
+ if (rc) {
+ dput(fdentry);
+ GOTO(out, rc);
+ }
+
+ handle = llog_fsfilt_start(ctxt, parent_inode,
+ FSFILT_OP_UNLINK, NULL);
+ if (IS_ERR(handle)) {
+ dput(fdentry);
+ GOTO(out, rc = PTR_ERR(handle));
+ }
+
+ down(&parent_inode->i_sem);
+ rc = vfs_unlink(parent_inode, fdentry);
+ up(&parent_inode->i_sem);
+ dput(fdentry);
+
+ if (!rc) {
+ down(&ctxt->loc_objects_dir->d_inode->i_sem);
+ fdentry = lookup_one_len(fidname, ctxt->loc_objects_dir,
+ namelen);
+ if (fdentry == NULL || fdentry->d_inode == NULL) {
+ CERROR("destroy non_existent object %s\n", fidname);
+ GOTO(out_err, rc = IS_ERR(fdentry) ?
+ PTR_ERR(fdentry) : -ENOENT);
+ }
+ rc = vfs_unlink(ctxt->loc_objects_dir->d_inode, fdentry);
+ l_dput(fdentry);
+out_err:
+ up(&ctxt->loc_objects_dir->d_inode->i_sem);
+ }
+ err = llog_fsfilt_commit(ctxt, parent_inode, handle, 0);
+ if (err && !rc)
+ err = rc;
+
+ GOTO(out, rc);
+ }
+
+ if (!strcmp(fdentry->d_parent->d_name.name, "OBJECTS")) {
+ LASSERT(parent_inode == ctxt->loc_objects_dir->d_inode);
+
+ dget(fdentry);
+ rc = llog_lvfs_close(loghandle);
+ if (rc == 0) {
+ down(&parent_inode->i_sem);
+ rc = vfs_unlink(parent_inode, fdentry);
+ up(&parent_inode->i_sem);
+ }
+ dput(fdentry);
+ }
+out:
+ if (ctxt->loc_lvfs_ctxt)
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+ RETURN(rc);
+}
+
+/* reads the catalog list */
+int llog_get_cat_list(struct lvfs_run_ctxt *ctxt,
+ struct fsfilt_operations *fsops, char *name,
+ int count, struct llog_catid *idarray)
+{
+ struct lvfs_run_ctxt saved;
+ struct l_file *file;
+ int size = sizeof(*idarray) * count;
+ loff_t off = 0;
+ int rc;
+
+ LASSERT(count);
+
+ if (ctxt)
+ push_ctxt(&saved, ctxt, NULL);
+ file = l_filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
+ if (!file || IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ CERROR("OBD filter: cannot open/create %s: rc = %d\n",
+ name, rc);
+ GOTO(out, rc);
+ }
+
+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
+ CERROR("%s is not a regular file!: mode = %o\n", name,
+ file->f_dentry->d_inode->i_mode);
+ GOTO(out, rc = -ENOENT);
+ }
+
+ rc = fsops->fs_read_record(file, idarray, size, &off);
+ if (rc) {
+ CDEBUG(D_INODE,"OBD filter: error reading %s: rc %d\n",
+ name, rc);
+ GOTO(out, rc);
+ }
+
+ out:
+ if (file && !IS_ERR(file))
+ rc = filp_close(file, 0);
+ if (ctxt)
+ pop_ctxt(&saved, ctxt, NULL);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_get_cat_list);
+
+/* writes the cat list */
+int llog_put_cat_list(struct lvfs_run_ctxt *ctxt,
+ struct fsfilt_operations *fsops, char *name,
+ int count, struct llog_catid *idarray)
+{
+ struct lvfs_run_ctxt saved;
+ struct l_file *file;
+ int size = sizeof(*idarray) * count;
+ loff_t off = 0;
+ int rc;
+
+ LASSERT(count);
+
+ if (ctxt)
+ push_ctxt(&saved, ctxt, NULL);
+ file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
+ if (!file || IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ CERROR("OBD filter: cannot open/create %s: rc = %d\n",
+ name, rc);
+ GOTO(out, rc);
+ }
+
+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
+ CERROR("%s is not a regular file!: mode = %o\n", name,
+ file->f_dentry->d_inode->i_mode);
+ GOTO(out, rc = -ENOENT);
+ }
+
+ rc = fsops->fs_write_record(file, idarray, size, &off, 1);
+ if (rc) {
+ CDEBUG(D_INODE,"OBD filter: error reading %s: rc %d\n",
+ name, rc);
+ GOTO(out, rc);
+ }
+
+ out:
+ if (file && !IS_ERR(file))
+ rc = filp_close(file, 0);
+ if (ctxt)
+ pop_ctxt(&saved, ctxt, NULL);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_put_cat_list);
+
+struct llog_operations llog_lvfs_ops = {
+ lop_create: llog_lvfs_create,
+ lop_destroy: llog_lvfs_destroy,
+ lop_close: llog_lvfs_close,
+ lop_read_header: llog_lvfs_read_header,
+ lop_write_rec: llog_lvfs_write_rec,
+ lop_next_block: llog_lvfs_next_block,
+ lop_prev_block: llog_lvfs_prev_block,
+};
+EXPORT_SYMBOL(llog_lvfs_ops);
+
+#else /* !__KERNEL__ */
+
+static int llog_lvfs_read_header(struct llog_handle *handle)
+{
+ LBUG();
+ return 0;
+}
+
+static int llog_lvfs_write_rec(struct llog_handle *loghandle,
+ struct llog_rec_hdr *rec,
+ struct llog_cookie *reccookie, int cookiecount,
+ void *buf, int idx)
+{
+ LBUG();
+ return 0;
+}
+
+static int llog_lvfs_create(struct llog_ctxt *ctxt, struct llog_handle **res,
+ struct llog_logid *logid, char *name)
+{
+ LBUG();
+ return 0;
+}
+
+static int llog_lvfs_close(struct llog_handle *handle)
+{
+ LBUG();
+ return 0;
+}
+
+static int llog_lvfs_destroy(struct llog_handle *handle)
+{
+ LBUG();
+ return 0;
+}
+
+int llog_get_cat_list(struct lvfs_run_ctxt *ctxt,
+ struct fsfilt_operations *fsops, char *name,
+ int count, struct llog_catid *idarray)
+{
+ LBUG();
+ return 0;
+}
+
+int llog_put_cat_list(struct lvfs_run_ctxt *ctxt,
+ struct fsfilt_operations *fsops, char *name,
+ int count, struct llog_catid *idarray)
+{
+ LBUG();
+ return 0;
+}
+
+int llog_lvfs_prev_block(struct llog_handle *loghandle,
+ int prev_idx, void *buf, int len)
+{
+ LBUG();
+ return 0;
+}
+
+int llog_lvfs_next_block(struct llog_handle *loghandle,
+ int next_idx, void *buf, int len)
+{
+ LBUG();
+ return 0;
+}
+
+struct llog_operations llog_lvfs_ops = {
+ lop_create: llog_lvfs_create,
+ lop_destroy: llog_lvfs_destroy,
+ lop_close: llog_lvfs_close,
+ lop_read_header: llog_lvfs_read_header,
+ lop_write_rec: llog_lvfs_write_rec,
+ lop_next_block: llog_lvfs_next_block,
+ lop_prev_block: llog_lvfs_prev_block,
+};
+#endif
#include <linux/lvfs.h>
-struct dentry *lvfs_fid2dentry(struct obd_run_ctxt *ctxt, __u64 id,
+struct dentry *lvfs_fid2dentry(struct lvfs_run_ctxt *ctxt, __u64 id,
__u32 gen, __u64 gr, void *data)
{
return ctxt->cb_ops.l_fid2dentry(id, gen, gr, data);
int fsfilt_reiser_init(void);
void fsfilt_reiser_exit(void);
+
+int lookup_by_path(char *path, int flags, struct nameidata *nd);
+struct dentry *lookup_create(struct nameidata *nd, int is_dir);
#endif
/* push / pop to root of obd store */
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
//ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
ASSERT_CTXT_MAGIC(new_ctx->magic);
LASSERT(new_ctx->pwdmnt);
if (uc) {
- save->ouc.ouc_fsuid = current->fsuid;
- save->ouc.ouc_fsgid = current->fsgid;
- save->ouc.ouc_cap = current->cap_effective;
- save->ouc.ouc_suppgid1 = current_groups[0];
- save->ouc.ouc_suppgid2 = current_groups[1];
-
- current->fsuid = uc->ouc_fsuid;
- current->fsgid = uc->ouc_fsgid;
- current->cap_effective = uc->ouc_cap;
+ save->luc.luc_fsuid = current->fsuid;
+ save->luc.luc_fsgid = current->fsgid;
+ save->luc.luc_cap = current->cap_effective;
+ save->luc.luc_suppgid1 = current_groups[0];
+ save->luc.luc_suppgid2 = current_groups[1];
+
+ current->fsuid = uc->luc_fsuid;
+ current->fsgid = uc->luc_fsgid;
+ current->cap_effective = uc->luc_cap;
current_ngroups = 0;
- if (uc->ouc_suppgid1 != -1)
- current_groups[current_ngroups++] = uc->ouc_suppgid1;
- if (uc->ouc_suppgid2 != -1)
- current_groups[current_ngroups++] = uc->ouc_suppgid2;
+ if (uc->luc_suppgid1 != -1)
+ current_groups[current_ngroups++] = uc->luc_suppgid1;
+ if (uc->luc_suppgid2 != -1)
+ current_groups[current_ngroups++] = uc->luc_suppgid2;
}
set_fs(new_ctx->fs);
set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
}
EXPORT_SYMBOL(push_ctxt);
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
//printk("pc0");
ASSERT_CTXT_MAGIC(saved->magic);
dput(saved->pwd);
mntput(saved->pwdmnt);
if (uc) {
- current->fsuid = saved->ouc.ouc_fsuid;
- current->fsgid = saved->ouc.ouc_fsgid;
- current->cap_effective = saved->ouc.ouc_cap;
+ current->fsuid = saved->luc.luc_fsuid;
+ current->fsgid = saved->luc.luc_fsgid;
+ current->cap_effective = saved->luc.luc_cap;
current_ngroups = saved->ngroups;
- current_groups[0] = saved->ouc.ouc_suppgid1;
- current_groups[1] = saved->ouc.ouc_suppgid2;
+ current_groups[0] = saved->luc.luc_suppgid1;
+ current_groups[1] = saved->luc.luc_suppgid2;
}
/*
}
EXPORT_SYMBOL(lustre_fsync);
-struct l_file *l_dentry_open(struct obd_run_ctxt *ctxt, struct l_dentry *de,
+struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de,
int flags)
{
mntget(ctxt->pwdmnt);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+
+#define DEBUG_SUBSYSTEM S_FILTER
+
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <asm/unistd.h>
+#include <linux/jbd.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/version.h>
+#include <linux/kp30.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/obd.h>
+#include <linux/obd_class.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/lustre_compat25.h>
+#include <linux/lvfs.h>
+#include <linux/lustre_smfs.h>
+#include "lvfs_internal.h"
+
+#include <linux/obd.h>
+#include <linux/lustre_lib.h>
+
+/* from namei.c*/
+struct dentry *lookup_create(struct nameidata *nd, int is_dir)
+{
+ struct dentry *dentry;
+
+ dentry = ERR_PTR(-EEXIST);
+ if (nd->last_type != LAST_NORM)
+ goto fail;
+ dentry = lookup_hash(&nd->last, nd->dentry);
+ if (IS_ERR(dentry))
+ goto fail;
+ if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
+ goto enoent;
+ return dentry;
+enoent:
+ dput(dentry);
+ dentry = ERR_PTR(-ENOENT);
+fail:
+ return dentry;
+}
+
+int lookup_by_path(char *path, int flags, struct nameidata *nd)
+{
+ struct dentry *dentry = NULL;
+ int rc = 0;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (path_init(path, flags, nd)) {
+#else
+ if (path_lookup(path, flags, nd)) {
+#endif
+ rc = path_walk(path, nd);
+ if (rc)
+ RETURN(rc);
+ } else
+ RETURN(-EINVAL);
+
+ dentry = nd->dentry;
+
+ if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
+ (!S_ISDIR(dentry->d_inode->i_mode))) {
+ path_release(nd);
+ RETURN(-ENODEV);
+ }
+ RETURN(rc);
+}
+
+static int lvfs_reint_create(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0, created = 0, err = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+
+ down(&dparent->d_inode->i_sem);
+ /*create a new dentry*/
+ dentry = lookup_create(&nd, 0);
+ dir = dparent->d_inode;
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ switch(type) {
+ case S_IFREG:
+ handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = ll_vfs_create(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
+ NULL);
+ break;
+ case S_IFDIR:
+ handle = fsfilt->fs_start(dir, FSFILT_OP_MKDIR, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = vfs_mkdir(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode);
+ break;
+ case S_IFLNK: {
+ char *new_path = r_rec->rec_data2;
+ handle = fsfilt->fs_start(dir, FSFILT_OP_SYMLINK, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = vfs_symlink(dir, dentry, new_path);
+ break;
+ }
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK: {
+ int rdev = r_rec->u_rec.ur_rdev;
+ handle = fsfilt->fs_start(dir, FSFILT_OP_MKNOD, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, (handle = NULL, rc = PTR_ERR(handle)));
+ rc = vfs_mknod(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
+ rdev);
+ break;
+ }
+ default:
+ CERROR("Error type %d in create\n", type);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc) {
+ CERROR("Error for creating mkdir %s\n", path);
+ GOTO(cleanup, 0);
+ } else {
+ struct iattr iattr;
+
+ created = 1;
+
+ LTIME_S(iattr.ia_atime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_atime);
+ LTIME_S(iattr.ia_ctime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_ctime);
+ LTIME_S(iattr.ia_mtime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_mtime);
+
+ iattr.ia_uid = r_rec->u_rec.ur_fsuid;
+ if (dir->i_mode & S_ISGID)
+ iattr.ia_gid = dir->i_gid;
+ else
+ iattr.ia_gid = r_rec->u_rec.ur_fsgid;
+ iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |
+ ATTR_MTIME | ATTR_CTIME;
+
+ rc = fsfilt->fs_setattr(dentry, handle, &iattr, 0);
+ if (rc) {
+ CERROR("error on child setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+
+ iattr.ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, &iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (rc && created) {
+ /* Destroy the file we just created. This should not need
+ * extra journal credits, as we have already modified all of
+ * the blocks needed in order to create the file in the first
+ * place.
+ */
+ switch (type) {
+ case S_IFDIR:
+ err = vfs_rmdir(dir, dentry);
+ if (err)
+ CERROR("rmdir in error path: %d\n", err);
+ break;
+ default:
+ err = vfs_unlink(dir, dentry);
+ if (err)
+ CERROR("unlink in error path: %d\n", err);
+ break;
+ }
+ } else {
+ rc = err;
+ }
+ if (handle)
+ rc = fsfilt->fs_commit(dentry->d_inode, handle, 0);
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ up(&dparent->d_inode->i_sem);
+ path_release(&nd);
+ if (dentry)
+ l_dput(dentry);
+
+ RETURN(0);
+};
+
+static int lvfs_reint_link(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *old_path = r_rec->rec_data1;
+ char *new_path = r_rec->rec_data2;
+ struct nameidata old_nd;
+ struct nameidata new_nd;
+ struct dentry *old_dparent;
+ struct dentry *new_dparent;
+ struct dentry *old_dentry = NULL;
+ struct dentry *new_dentry = NULL;
+ void *handle = NULL;
+ struct inode *dir = NULL;
+ int rc = 0;
+
+ /*get parent dentry*/
+ rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
+ if (rc)
+ RETURN(rc);
+
+ new_dparent = new_nd.dentry;
+
+ dir = new_dparent->d_inode;
+
+ new_dentry = lookup_create(&new_nd, 0);
+
+ rc = lookup_by_path(old_path, LOOKUP_PARENT, &old_nd);
+ if (rc) {
+ path_release(&new_nd);
+ RETURN(rc);
+ }
+ old_dparent = old_nd.dentry;
+ old_dentry = lookup_one_len(old_nd.last.name, old_dparent,
+ old_nd.last.len);
+
+ if (! old_dentry || !old_dentry->d_inode
+ || is_bad_inode(old_dentry->d_inode)) {
+ GOTO(cleanup, rc = -ENODEV);
+ }
+ if (dir->i_rdev != old_dentry->d_inode->i_rdev) {
+ GOTO(cleanup, rc = -EINVAL);
+ }
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ handle = fsfilt->fs_start(dir, FSFILT_OP_LINK, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ rc = vfs_link(old_dentry, dir, new_dentry);
+ if (rc) {
+ CERROR("replay error: vfs_link error rc=%d", rc);
+ GOTO(cleanup, rc);
+ }
+cleanup:
+ if (handle) {
+ rc = fsfilt->fs_commit(dir, handle, 0);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (old_dentry)
+ l_dput(old_dentry);
+ if (new_dentry)
+ l_dput(new_dentry);
+ path_release(&new_nd);
+ path_release(&old_nd);
+ RETURN(rc);
+};
+static int lvfs_reint_unlink(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
+ char *path = r_rec->rec_data1;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+
+ dir = dparent->d_inode;
+
+ dentry = lookup_one_len(nd.last.name, dparent,
+ nd.last.len);
+ if (! dentry || !dentry->d_inode
+ || is_bad_inode(dentry->d_inode)) {
+ GOTO(cleanup, rc = -ENODEV);
+ }
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ handle = fsfilt->fs_start(dir, FSFILT_OP_UNLINK, NULL, 0);
+
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ switch (type) {
+ case S_IFDIR:
+ rc = vfs_rmdir(dir, dentry);
+ if (rc)
+ CERROR("rmdir in error path: %d\n", rc);
+ break;
+ default:
+ rc = vfs_unlink(dir, dentry);
+ if (rc)
+ CERROR("unlink in error path: %d\n", rc);
+ break;
+ }
+ if (!rc) {
+ /*time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ path_release(&nd);
+ RETURN(rc);
+};
+
+static int lvfs_reint_rename(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ char *new_path = r_rec->rec_data2;
+ struct nameidata nd;
+ struct nameidata new_nd;
+ struct dentry *dparent = NULL;
+ struct dentry *new_dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct dentry *new_dentry = NULL;
+ struct inode *dir = NULL;
+ struct inode *new_dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry || !dentry->d_inode
+ || is_bad_inode(dentry->d_inode)) {
+ path_release(&nd);
+ RETURN(rc);
+ }
+ rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
+ if (rc) {
+ path_release(&nd);
+ path_release(&new_nd);
+ RETURN(rc);
+ }
+ new_dparent = new_nd.dentry;
+ new_dir = new_dparent->d_inode;
+ new_dentry = lookup_create(&new_nd, 0);
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ handle = fsfilt->fs_start(dir, FSFILT_OP_RENAME, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ rc = vfs_rename(dir, dentry, new_dir, new_dentry);
+ if (rc) {
+ CERROR("unlink in error path: %d\n", rc);
+ GOTO(cleanup, 0);
+ } else {
+ /*restore time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ rc = fsfilt->fs_setattr(new_dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ rc = fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ if (new_dentry)
+ l_dput(new_dentry);
+ path_release(&nd);
+ path_release(&new_nd);
+ RETURN(0);
+};
+
+static int lvfs_reint_setattr(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry || !dentry->d_inode
+ || is_bad_inode(dentry->d_inode)) {
+ path_release(&nd);
+ RETURN(rc);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+ handle = fsfilt->fs_start(dir, FSFILT_OP_SETATTR, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = fsfilt->fs_setattr(dentry, handle, &r_rec->u_rec.ur_pattr, 0);
+cleanup:
+ if (handle)
+ fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ path_release(&nd);
+ RETURN(0);
+};
+static int lvfs_reint_close(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ struct iattr *iattr = &r_rec->u_rec.ur_iattr;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry || !dentry->d_inode
+ || is_bad_inode(dentry->d_inode)) {
+ path_release(&nd);
+ RETURN(rc);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+ handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_SIZE;
+
+ rc = fsfilt->fs_setattr(dentry, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+cleanup:
+ if (handle)
+ fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ path_release(&nd);
+ RETURN(0);
+};
+
+typedef int (*lvfs_reinter)(struct super_block *sb, struct reint_record *);
+static lvfs_reinter reinters[REINT_MAX + 1] = {
+ [REINT_SETATTR] lvfs_reint_setattr,
+ [REINT_CREATE] lvfs_reint_create,
+ [REINT_LINK] lvfs_reint_link,
+ [REINT_UNLINK] lvfs_reint_unlink,
+ [REINT_RENAME] lvfs_reint_rename,
+ [REINT_CLOSE] lvfs_reint_close,
+};
+int lvfs_reint(struct super_block *sb,
+ void *r_rec)
+{
+ return reinters[((struct reint_record*)r_rec)->u_rec.ur_opcode](sb,
+ (struct reint_record *)r_rec);
+};
+
+EXPORT_SYMBOL(lvfs_reint);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+
+#ifndef EXPORT_SYMTAB
+# define EXPORT_SYMTAB
+#endif
+
+#define DEBUG_SUBSYSTEM S_FILTER
+
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <asm/unistd.h>
+#include <linux/jbd.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/version.h>
+#include <linux/kp30.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/obd.h>
+#include <linux/obd_class.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/lustre_compat25.h>
+#include <linux/lvfs.h>
+#include <linux/lustre_smfs.h>
+#include "lvfs_internal.h"
+
+#include <linux/obd.h>
+#include <linux/lustre_lib.h>
+
+static int lvfs_undo_create(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+
+ down(&dir->i_sem);
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry->d_inode || is_bad_inode(dentry->d_inode)) {
+ up(&dir->i_sem);
+ if (dentry)
+ l_dput(dentry);
+ path_release(&nd);
+ RETURN(-ENODEV);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ switch(type) {
+ case S_IFREG:
+ case S_IFLNK:
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK:
+ handle = fsfilt->fs_start(dir, FSFILT_OP_UNLINK, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = vfs_unlink(dir, dentry);
+ if (rc)
+ CERROR("unlink in error path: %d\n", rc);
+ break;
+ case S_IFDIR:
+ handle = fsfilt->fs_start(dir, FSFILT_OP_RMDIR, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ rc = vfs_rmdir(dir, dentry);
+ if (rc)
+ CERROR("rmdir in error path: %d\n", rc);
+ break;
+ default:
+ CERROR("Error type %d in create\n", type);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc) {
+ CERROR("Error for undo node %s\n", path);
+ GOTO(cleanup, 0);
+ } else {
+ /*restore time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ rc = fsfilt->fs_commit(dparent->d_inode, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ up(&dir->i_sem);
+ path_release(&nd);
+ RETURN(0);
+};
+
+static int lvfs_undo_link(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *new_path = r_rec->rec_data2;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(new_path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+
+ down(&dir->i_sem);
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry->d_inode || is_bad_inode(dentry->d_inode)) {
+ up(&dir->i_sem);
+ path_release(&nd);
+ RETURN(-ENODEV);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+
+ handle = fsfilt->fs_start(dir, FSFILT_OP_UNLINK, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+ rc = vfs_unlink(dir, dentry);
+ if (rc)
+ CERROR("unlink in error path: %d\n", rc);
+
+ if (rc) {
+ CERROR("Error for undo node %s\n", new_path);
+ GOTO(cleanup, 0);
+ } else {
+ /*restore time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ rc = fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ up(&dir->i_sem);
+ path_release(&nd);
+ RETURN(0);
+}
+
+static int lvfs_undo_unlink(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ struct nameidata nd;
+ struct dentry *dparent;
+ struct dentry *dentry = NULL;
+ struct nameidata del_nd;
+ struct dentry *del_dparent = NULL;
+ struct dentry *del_dentry = NULL;
+ void *handle = NULL;
+ struct inode *dir = NULL;
+ int rc = 0;
+
+ /*get parent dentry*/
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+
+ dentry = lookup_create(&nd, 0);
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+ if (SMFS_DO_DEC_LINK(r_rec->u_rec.ur_flags)) {
+ ino_t ino = *((ino_t *)r_rec->rec_data2);
+ struct inode* inode = iget(dir->i_sb, ino);
+ if (!inode)
+ GOTO(cleanup1, rc = -EINVAL);
+ handle = fsfilt->fs_start(dir, FSFILT_OP_LINK, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup1, rc = PTR_ERR(handle));
+
+ del_dentry = pre_smfs_dentry(NULL, inode, dentry);
+ rc = vfs_link(del_dentry, dir, dentry);
+cleanup1:
+ post_smfs_dentry(del_dentry);
+ iput(inode);
+ } else {
+ char *del_path = r_rec->rec_data2;
+
+ rc = lookup_by_path(del_path, LOOKUP_PARENT, &del_nd);
+ if (rc)
+ GOTO(cleanup, rc = -ENODEV);
+ del_dparent = del_nd.dentry;
+ del_dentry = lookup_one_len(del_nd.last.name, del_dparent,
+ del_nd.last.len);
+
+ if (! del_dentry || !del_dentry->d_inode
+ || is_bad_inode(del_dentry->d_inode))
+ GOTO(cleanup2, rc = -ENODEV);
+
+ handle = fsfilt->fs_start(dir, FSFILT_OP_RENAME, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup2, rc = PTR_ERR(handle));
+
+ lock_kernel();
+ /*move the del dentry back to the original palace*/
+ rc = vfs_rename(del_dparent->d_inode, del_dentry, dir, dentry);
+ unlock_kernel();
+ if (!rc && S_ISDIR(del_dentry->d_inode->i_mode))
+ del_dentry->d_inode->i_flags &=~S_DEAD;
+cleanup2:
+ if (del_dentry)
+ l_dput(del_dentry);
+ path_release(&del_nd);
+ }
+ if (!rc) {
+ /*restore time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ fsfilt->fs_commit(dir, handle, 0);
+ if (dentry);
+ l_dput(dentry);
+ path_release(&nd);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ RETURN(rc);
+}
+
+static int lvfs_undo_rename(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ char *new_path = r_rec->rec_data2;
+ struct nameidata nd;
+ struct nameidata new_nd;
+ struct dentry *dparent;
+ struct dentry *new_dparent;
+ struct dentry *dentry = NULL;
+ struct dentry *new_dentry = NULL;
+ void *handle = NULL;
+ struct inode *dir = NULL;
+ struct inode *new_dir = NULL;
+ int rc = 0;
+
+ /*get parent dentry*/
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+ dentry = lookup_create(&nd, 0);
+
+ rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
+ if (rc) {
+ path_release(&nd);
+ RETURN(rc);
+ }
+ new_dparent = new_nd.dentry;
+ new_dir = new_dparent->d_inode;
+ new_dentry = lookup_one_len(new_nd.last.name, new_dparent,
+ new_nd.last.len);
+
+ if (! new_dentry || !new_dentry->d_inode
+ || is_bad_inode(new_dentry->d_inode)) {
+ GOTO(cleanup, rc = -ENODEV);
+ }
+
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(new_dir);
+
+ handle = fsfilt->fs_start(new_dir, FSFILT_OP_RENAME, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ lock_kernel();
+ /*move the del dentry back to the original palace*/
+ rc = vfs_rename(new_dir, new_dentry, dir, dentry);
+ unlock_kernel();
+ if (rc) {
+ CERROR("Error for undo node %s\n", new_path);
+ GOTO(cleanup, 0);
+ } else {
+ /*restore time attr of dir inode*/
+ struct iattr *iattr = &r_rec->u_rec.ur_pattr;
+
+ iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
+ rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
+ if (rc) {
+ CERROR("error on parent setattr: rc = %d\n", rc);
+ GOTO(cleanup, rc);
+ }
+ }
+cleanup:
+ if (handle)
+ rc = fsfilt->fs_commit(new_dir, handle, 0);
+ if (dentry);
+ l_dput(dentry);
+ if (new_dentry)
+ l_dput(new_dentry);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(new_dir);
+ path_release(&nd);
+ path_release(&new_nd);
+ RETURN(rc);
+};
+
+static int lvfs_undo_setattr(struct super_block *sb,
+ struct reint_record *r_rec)
+{
+ struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
+ char *path = r_rec->rec_data1;
+ struct nameidata nd;
+ struct dentry *dparent = NULL;
+ struct dentry *dentry = NULL;
+ struct inode *dir = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
+ if (rc)
+ RETURN(rc);
+
+ dparent = nd.dentry;
+ dir = dparent->d_inode;
+ dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
+
+ if (!dentry || !dentry->d_inode
+ || is_bad_inode(dentry->d_inode)) {
+ path_release(&nd);
+ RETURN(rc);
+ }
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_CLEAN_INODE_REC(dir);
+ handle = fsfilt->fs_start(dir, FSFILT_OP_SETATTR, NULL, 0);
+ if (IS_ERR(handle))
+ GOTO(cleanup, rc = PTR_ERR(handle));
+
+ /*FIXME later, did not set parent attr*/
+ r_rec->u_rec.ur_iattr.ia_valid = r_rec->u_rec.ur_pattr.ia_valid;
+ rc = fsfilt->fs_setattr(dentry, handle, &r_rec->u_rec.ur_iattr, 0);
+cleanup:
+ if (handle)
+ fsfilt->fs_commit(dir, handle, 0);
+ if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
+ SMFS_SET_INODE_REC(dir);
+ if (dentry)
+ l_dput(dentry);
+ path_release(&nd);
+ RETURN(0);
+
+ RETURN(0);
+};
+
+
+typedef int (*lvfs_undoer)(struct super_block *sb, struct reint_record *);
+
+static lvfs_undoer undoers[REINT_MAX + 1] = {
+ [REINT_SETATTR] lvfs_undo_setattr,
+ [REINT_CREATE] lvfs_undo_create,
+ [REINT_LINK] lvfs_undo_link,
+ [REINT_UNLINK] lvfs_undo_unlink,
+ [REINT_RENAME] lvfs_undo_rename,
+};
+
+int lvfs_undo(struct super_block *sb,
+ void *r_rec)
+{
+ return undoers[((struct reint_record*)r_rec)->u_rec.ur_opcode](sb,
+ (struct reint_record *)r_rec);
+};
+
+EXPORT_SYMBOL(lvfs_undo);
#include <liblustre.h>
#include <linux/lvfs.h>
-#include "lvfs_internal.h"
#include <linux/obd.h>
#include <linux/lustre_lib.h>
/* XXX currently ctxt functions should not be used ?? */
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
LBUG();
}
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
LBUG();
}
int rc;
ENTRY;
- rc = llog_setup(obd, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
- &llog_client_ops);
+ rc = obd_llog_setup(obd, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
+ &llog_client_ops);
if (rc == 0) {
ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
ctxt->loc_imp = obd->u.cli.cl_import;
int rc;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_REPL_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_CONFIG_REPL_CTXT));
RETURN(rc);
}
rc = -ETIMEDOUT; /* XXX should this be a different errno? */
}
-
+
DEBUG_REQ(D_ERROR, req, "bulk failed: %s %d(%d), evicting %s@%s\n",
(rc == -ETIMEDOUT) ? "timeout" : "network error",
desc->bd_nob_transferred, count,
return rc;
}
-static int mds_init_export(struct obd_export *exp)
+static int mds_init_export(struct obd_export *exp)
{
struct mds_export_data *med = &exp->exp_mds_data;
{
struct mds_export_data *med;
struct obd_device *obd = export->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc = 0;
ENTRY;
if (obd_uuid_equals(&export->exp_client_uuid, &obd->obd_uuid))
GOTO(out, 0);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
/* Close any open files (which may also cause orphan unlinking). */
spin_lock(&med->med_open_lock);
while (!list_empty(&med->med_open_head)) {
dentry->d_name.len, dentry->d_name.name,
ll_bdevname(dentry->d_inode->i_sb, btmp),
dentry->d_inode->i_ino);
- rc = mds_mfd_close(NULL, obd, mfd,
+ rc = mds_mfd_close(NULL, obd, mfd,
!(export->exp_flags & OBD_OPT_FAILOVER));
if (rc)
spin_lock(&med->med_open_lock);
}
spin_unlock(&med->med_open_lock);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
out:
mds_client_free(export, !(export->exp_flags & OBD_OPT_FAILOVER));
{
struct obd_device *obd = req->rq_export->exp_obd;
struct ldlm_reply *rep = NULL;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct mds_body *body;
struct dentry *dparent = NULL, *dchild = NULL;
- struct obd_ucred uc;
+ struct lvfs_ucred uc;
struct lustre_handle parent_lockh;
int namesize;
int rc = 0, cleanup_phase = 0, resent_req = 0;
LASSERT (offset == 0 || offset == 2);
/* if requests were at offset 2, the getattr reply goes back at 1 */
- if (offset) {
+ if (offset) {
rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof (*rep));
offset = 1;
}
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- uc.ouc_suppgid1 = body->suppgid;
- uc.ouc_suppgid2 = -1;
- push_ctxt(&saved, &obd->obd_ctxt, &uc);
+ uc.luc_fsuid = body->fsuid;
+ uc.luc_fsgid = body->fsgid;
+ uc.luc_cap = body->capability;
+ uc.luc_suppgid1 = body->suppgid;
+ uc.luc_suppgid2 = -1;
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
cleanup_phase = 1; /* kernel context */
intent_set_disposition(rep, DISP_LOOKUP_EXECD);
}
l_dput(dchild);
case 1:
- pop_ctxt(&saved, &obd->obd_ctxt, &uc);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
default: ;
}
return rc;
{
struct mds_obd *mds = mds_req2mds(req);
struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct dentry *de;
struct mds_body *body;
- struct obd_ucred uc;
+ struct lvfs_ucred uc;
int rc = 0;
ENTRY;
RETURN (-EFAULT);
}
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &obd->obd_ctxt, &uc);
+ uc.luc_fsuid = body->fsuid;
+ uc.luc_fsgid = body->fsgid;
+ uc.luc_cap = body->capability;
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
de = mds_fid2dentry(mds, &body->fid1, NULL);
if (IS_ERR(de)) {
rc = req->rq_status = -ENOENT;
l_dput(de);
GOTO(out_pop, rc);
out_pop:
- pop_ctxt(&saved, &obd->obd_ctxt, &uc);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
return rc;
}
struct dentry *de;
struct file *file;
struct mds_body *body, *repbody;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc, size = sizeof(*repbody);
- struct obd_ucred uc;
+ struct lvfs_ucred uc;
ENTRY;
rc = lustre_pack_reply(req, 1, &size, NULL);
if (body == NULL)
GOTO (out, rc = -EFAULT);
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &obd->obd_ctxt, &uc);
+ uc.luc_fsuid = body->fsuid;
+ uc.luc_fsgid = body->fsgid;
+ uc.luc_cap = body->capability;
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
de = mds_fid2dentry(&obd->u.mds, &body->fid1, &mnt);
if (IS_ERR(de))
GOTO(out_pop, rc = PTR_ERR(de));
out_file:
filp_close(file, 0);
out_pop:
- pop_ctxt(&saved, &obd->obd_ctxt, &uc);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
out:
req->rq_status = rc;
RETURN(0);
OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
rc = llog_origin_handle_next_block(req);
break;
+ case LLOG_ORIGIN_HANDLE_PREV_BLOCK:
+ DEBUG_REQ(D_INODE, req, "llog prev block");
+ OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
+ rc = llog_origin_handle_prev_block(req);
+ break;
case LLOG_ORIGIN_HANDLE_READ_HEADER:
DEBUG_REQ(D_INODE, req, "llog read header");
OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
struct mds_obd *mds = &obd->u.mds;
struct mds_server_data *msd = mds->mds_server_data;
struct file *filp = mds->mds_rcvd_filp;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
loff_t off = 0;
int rc;
ENTRY;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
msd->msd_last_transno = cpu_to_le64(mds->mds_last_transno);
CDEBUG(D_SUPER, "MDS mount_count is "LPU64", last_transno is "LPU64"\n",
rc = fsfilt_write_record(obd, filp, msd, sizeof(*msd), &off,force_sync);
if (rc)
CERROR("error writing MDS server data: rc = %d\n", rc);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
RETURN(rc);
}
struct lprocfs_static_vars lvars;
struct lustre_cfg* lcfg = buf;
struct mds_obd *mds = &obd->u.mds;
+ char *options = NULL;
struct vfsmount *mnt;
- int rc = 0;
unsigned long page;
+ int rc = 0;
ENTRY;
dev_clear_rdonly(2);
if (IS_ERR(obd->obd_fsops))
RETURN(rc = PTR_ERR(obd->obd_fsops));
- if (!(page = __get_free_page(GFP_KERNEL)))
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
RETURN(-ENOMEM);
- memset((void *)page, 0, PAGE_SIZE);
- sprintf((char *)page, "iopen_nopriv,errors=remount-ro");
+ options = (char *)page;
+ memset(options, 0, PAGE_SIZE);
- mnt = do_kern_mount(lcfg->lcfg_inlbuf2, 0,
- lcfg->lcfg_inlbuf1, (void *)page);
+ /* here we use "iopen_nopriv" hardcoded, because it affects MDS utility
+ * and the rest of options are passed by mount options. Probably this
+ * should be moved to somewhere else like startup scripts or lconf. */
+ sprintf(options, "iopen_nopriv");
+
+ if (lcfg->lcfg_inllen4 > 0 && lcfg->lcfg_inlbuf4)
+ sprintf(options + strlen(options), ",%s",
+ lcfg->lcfg_inlbuf4);
+
+ mnt = do_kern_mount(lcfg->lcfg_inlbuf2, 0,
+ lcfg->lcfg_inlbuf1, options);
+
free_page(page);
+
if (IS_ERR(mnt)) {
rc = PTR_ERR(mnt);
CERROR("do_kern_mount failed: rc = %d\n", rc);
int rc = 0;
ENTRY;
-
- rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
- &llog_lvfs_ops);
+ rc = obd_llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0,
+ NULL, &llog_lvfs_ops);
if (rc)
RETURN(rc);
- if (mds->mds_profile) {
- struct obd_run_ctxt saved;
+ /* This check for @dumb string is needed to handle
+ mounting MDS with smfs. Read lconf:MDSDEV.write_conf() for
+ more detail explanation. */
+ if (mds->mds_profile && strcmp(mds->mds_profile, "dumb")) {
+ struct lvfs_run_ctxt saved;
struct lustre_profile *lprof;
struct config_llog_instance cfg;
cfg.cfg_instance = NULL;
cfg.cfg_uuid = mds->mds_lov_uuid;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- rc = class_config_parse_llog(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ rc = class_config_parse_llog(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
mds->mds_profile, &cfg);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc)
GOTO(err_llog, rc);
err_cleanup:
mds_lov_clean(obd);
err_llog:
- llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
+ obd_llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
RETURN(rc);
}
-static int mds_postrecov(struct obd_device *obd)
+static int mds_postrecov(struct obd_device *obd)
{
int rc, rc2;
if (mds->mds_profile) {
char * cln_prof;
struct config_llog_instance cfg;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int len = strlen(mds->mds_profile) + sizeof("-clean") + 1;
OBD_ALLOC(cln_prof, len);
cfg.cfg_instance = NULL;
cfg.cfg_uuid = mds->mds_lov_uuid;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- class_config_parse_llog(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ class_config_parse_llog(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
cln_prof, &cfg);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
OBD_FREE(cln_prof, len);
OBD_FREE(mds->mds_profile, strlen(mds->mds_profile) + 1);
mds_lov_disconnect(obd, flags);
mds_lov_clean(obd);
- llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
+ obd_llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
RETURN(rc);
}
RETURN(ELDLM_LOCK_ABORTED);
if (intent_disposition(rep, DISP_LOOKUP_NEG) &&
!intent_disposition(rep, DISP_OPEN_OPEN))
-#endif
+#endif
RETURN(ELDLM_LOCK_ABORTED);
break;
case IT_LOOKUP:
getattr_part);
/* FIXME: LDLM can set req->rq_status. MDS sets
policy_res{1,2} with disposition and status.
- - replay: returns 0 & req->status is old status
+ - replay: returns 0 & req->status is old status
- otherwise: returns req->status */
if (intent_disposition(rep, DISP_LOOKUP_NEG))
rep->lock_policy_res2 = 0;
- if (!intent_disposition(rep, DISP_LOOKUP_POS) ||
+ if (!intent_disposition(rep, DISP_LOOKUP_POS) ||
rep->lock_policy_res2)
RETURN(ELDLM_LOCK_ABORTED);
if (req->rq_status != 0) {
mds->mds_service =
ptlrpc_init_svc(MDS_NBUFS, MDS_BUFSIZE, MDS_MAXREQSIZE,
MDS_REQUEST_PORTAL, MDC_REPLY_PORTAL,
- mds_handle, "mds",
- obd->obd_proc_entry);
+ mds_handle, "mds", obd->obd_proc_entry);
if (!mds->mds_service) {
CERROR("failed to start service\n");
(cl_idx * le16_to_cpu(mds->mds_server_data->msd_client_size));
if (new_client) {
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
loff_t off = med->med_off;
struct file *file = mds->mds_rcvd_filp;
int rc;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = fsfilt_write_record(obd, file, med->med_mcd,
sizeof(*med->med_mcd), &off, 1);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc)
return rc;
struct mds_obd *mds = &exp->exp_obd->u.mds;
struct obd_device *obd = exp->exp_obd;
struct mds_client_data zero_mcd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc;
unsigned long *bitmap = mds->mds_client_bitmap;
if (clear_client) {
memset(&zero_mcd, 0, sizeof zero_mcd);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = fsfilt_write_record(obd, mds->mds_rcvd_filp, &zero_mcd,
sizeof(zero_mcd), &med->med_off, 1);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
CDEBUG(rc == 0 ? D_INFO : D_ERROR,
"zeroing out client %s idx %u in %s rc %d\n",
int mds_fs_setup(struct obd_device *obd, struct vfsmount *mnt)
{
struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct dentry *dentry;
struct file *file;
int rc;
fsfilt_setup(obd, mds->mds_sb);
- OBD_SET_CTXT_MAGIC(&obd->obd_ctxt);
- obd->obd_ctxt.pwdmnt = mnt;
- obd->obd_ctxt.pwd = mnt->mnt_root;
- obd->obd_ctxt.fs = get_ds();
- obd->obd_ctxt.cb_ops = mds_lvfs_ops;
+ OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
+ obd->obd_lvfs_ctxt.pwdmnt = mnt;
+ obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
+ obd->obd_lvfs_ctxt.fs = get_ds();
+ obd->obd_lvfs_ctxt.cb_ops = mds_lvfs_ops;
/* setup the directory tree */
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
dentry = simple_mkdir(current->fs->pwd, "ROOT", 0755, 0);
if (IS_ERR(dentry)) {
rc = PTR_ERR(dentry);
GOTO(err_lov_objid, rc = -ENOENT);
}
err_pop:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
return rc;
int mds_fs_cleanup(struct obd_device *obd, int flags)
{
struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc = 0;
if (flags & OBD_OPT_FAILOVER)
class_disconnect_exports(obd, flags); /* cleans up client info too */
mds_server_free_data(mds);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (mds->mds_rcvd_filp) {
rc = filp_close(mds->mds_rcvd_filp, 0);
mds->mds_rcvd_filp = NULL;
l_dput(mds->mds_pending_dir);
mds->mds_pending_dir = NULL;
}
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
shrink_dcache_parent(mds->mds_fid_de);
dput(mds->mds_fid_de);
* performance sensitive, it is accomplished by creating a file, checking the
* fid, and renaming it. */
int mds_obd_create(struct obd_export *exp, struct obdo *oa,
- struct lov_stripe_md **ea, struct obd_trans_info *oti)
+ struct lov_stripe_md **ea, struct obd_trans_info *oti)
{
struct mds_obd *mds = &exp->exp_obd->u.mds;
struct inode *parent_inode = mds->mds_objects_dir->d_inode;
unsigned int tmpname = ll_insecure_random_int();
struct file *filp;
struct dentry *new_child;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
char fidname[LL_FID_NAMELEN];
void *handle;
int rc = 0, err, namelen;
ENTRY;
- push_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
sprintf(fidname, "OBJECTS/%u", tmpname);
filp = filp_open(fidname, O_CREAT | O_EXCL, 0644);
rc = err;
}
out_pop:
- pop_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
RETURN(rc);
}
struct mds_obd *mds = &exp->exp_obd->u.mds;
struct inode *parent_inode = mds->mds_objects_dir->d_inode;
struct obd_device *obd = exp->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
char fidname[LL_FID_NAMELEN];
struct dentry *de;
void *handle;
int err, namelen, rc = 0;
ENTRY;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
namelen = ll_fid2str(fidname, oa->o_id, oa->o_generation);
that is unlinked, not spanned across multiple OSTs */
handle = fsfilt_start_log(obd, mds->mds_objects_dir->d_inode,
FSFILT_OP_UNLINK, oti, 1);
- if (IS_ERR(handle)) {
+
+ if (IS_ERR(handle))
GOTO(out_dput, rc = PTR_ERR(handle));
- }
rc = vfs_unlink(mds->mds_objects_dir->d_inode, de);
if (rc)
if (de != NULL)
l_dput(de);
up(&parent_inode->i_sem);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
RETURN(rc);
}
#include "mds_internal.h"
-static int mds_llog_origin_add(struct llog_ctxt *ctxt,
- struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies)
+static int mds_llog_origin_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
+ void *buf, struct llog_cookie *logcookies,
+ int numcookies, void *data)
{
struct obd_device *obd = ctxt->loc_obd;
struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
ENTRY;
lctxt = llog_get_context(lov_obd, ctxt->loc_idx);
- rc = llog_add(lctxt, rec, lsm, logcookies, numcookies);
+ rc = llog_add(lctxt, rec, buf, logcookies, numcookies, data);
RETURN(rc);
}
static int mds_llog_origin_connect(struct llog_ctxt *ctxt, int count,
struct llog_logid *logid,
- struct llog_gen *gen,
- struct obd_uuid *uuid)
+ struct llog_gen *gen, struct obd_uuid *uuid)
{
struct obd_device *obd = ctxt->loc_obd;
struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
RETURN(rc);
}
-static int mds_llog_repl_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm,
- int count, struct llog_cookie *cookies, int flags)
+static int mds_llog_repl_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags,
+ void *data)
{
struct obd_device *obd = ctxt->loc_obd;
struct obd_device *lov_obd = obd->u.mds.mds_osc_obd;
ENTRY;
lctxt = llog_get_context(lov_obd, ctxt->loc_idx);
- rc = llog_cancel(lctxt, lsm, count, cookies,flags);
+ rc = llog_cancel(lctxt, count, cookies, flags, data);
RETURN(rc);
}
RETURN(rc);
ctxt = llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT);
- rc = llog_add(ctxt, NULL, lsm, logcookies,
- cookies_size / sizeof(struct llog_cookie));
+ rc = llog_add(ctxt, NULL, NULL, logcookies,
+ cookies_size / sizeof(struct llog_cookie), lsm);
obd_free_memmd(mds->mds_osc_exp, &lsm);
};
static struct llog_operations mds_size_repl_logops = {
- lop_cancel: mds_llog_repl_cancel
+ lop_cancel: mds_llog_repl_cancel,
};
int mds_llog_init(struct obd_device *obd, struct obd_device *tgt,
int rc;
ENTRY;
- rc = llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, 0, NULL,
- &mds_unlink_orig_logops);
+ rc = obd_llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, 0, NULL,
+ &mds_unlink_orig_logops);
if (rc)
RETURN(rc);
- rc = llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, 0, NULL,
- &mds_size_repl_logops);
+ rc = obd_llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, 0, NULL,
+ &mds_size_repl_logops);
if (rc)
RETURN(rc);
int rc;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
if (rc)
RETURN(rc);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
if (rc)
RETURN(rc);
{
struct mds_obd *mds = &obd->u.mds;
struct lustre_handle conn = {0,};
+ char name[32] = "CATLIST";
int valsize;
int rc, i;
ENTRY;
mds->mds_osc_obd = class_name2obd(lov_name);
if (!mds->mds_osc_obd) {
- CERROR("MDS cannot locate LOV %s\n", lov_name);
+ CERROR("MDS cannot locate LOV %s\n",
+ lov_name);
mds->mds_osc_obd = ERR_PTR(-ENOTCONN);
RETURN(-ENOTCONN);
}
rc = obd_connect(&conn, mds->mds_osc_obd, &obd->obd_uuid);
if (rc) {
- CERROR("MDS cannot connect to LOV %s (%d)\n", lov_name, rc);
+ CERROR("MDS cannot connect to LOV %s (%d)\n",
+ lov_name, rc);
mds->mds_osc_obd = ERR_PTR(rc);
RETURN(rc);
}
GOTO(err_reg, rc);
}
- rc = llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count);
+ rc = obd_llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count, name);
if (rc) {
CERROR("failed to initialize catalog %d\n", rc);
GOTO(err_reg, rc);
struct obd_device *obd = exp->exp_obd;
struct mds_obd *mds = &obd->u.mds;
struct obd_ioctl_data *data = karg;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc = 0;
switch (cmd) {
if (mds->mds_cfg_llh)
RETURN(-EBUSY);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
&mds->mds_cfg_llh, NULL, name);
if (rc == 0)
&cfg_uuid);
else
mds->mds_cfg_llh = NULL;
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
RETURN(rc);
}
if (!mds->mds_cfg_llh)
RETURN(-EBADF);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = llog_close(mds->mds_cfg_llh);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
mds->mds_cfg_llh = NULL;
RETURN(rc);
char *name = data->ioc_inlbuf1;
if (mds->mds_cfg_llh)
RETURN(-EBUSY);
-
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
+
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
&mds->mds_cfg_llh, NULL, name);
if (rc == 0) {
llog_init_handle(mds->mds_cfg_llh, LLOG_F_IS_PLAIN,
NULL);
-
+
rc = llog_destroy(mds->mds_cfg_llh);
llog_free_handle(mds->mds_cfg_llh);
}
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
-
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
mds->mds_cfg_llh = NULL;
RETURN(rc);
}
RETURN(rc);
}
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = llog_write_rec(mds->mds_cfg_llh, &rec, NULL, 0,
cfg_buf, -1);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
OBD_FREE(cfg_buf, data->ioc_plen1);
RETURN(rc);
case OBD_IOC_PARSE: {
struct llog_ctxt *ctxt =
llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = class_config_parse_llog(ctxt, data->ioc_inlbuf1, NULL);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc)
RETURN(rc);
case OBD_IOC_DUMP_LOG: {
struct llog_ctxt *ctxt =
llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc)
RETURN(rc);
case OBD_IOC_CATLOGLIST: {
int count = mds->mds_lov_desc.ld_tgt_count;
- rc = llog_catlog_list(obd, count, data);
+ rc = llog_catalog_list(obd, count, data);
RETURN(rc);
}
case OBD_IOC_LLOG_REMOVE: {
struct llog_ctxt *ctxt =
llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
+ char name[32] = "CATLIST";
int rc2;
obd_llog_finish(obd, mds->mds_lov_desc.ld_tgt_count);
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
rc = llog_ioctl(ctxt, cmd, data);
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
- llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count);
- rc2 = obd_set_info(mds->mds_osc_exp, strlen("mds_conn"), "mds_conn",
- 0, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+ obd_llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count,
+ name);
+ rc2 = obd_set_info(mds->mds_osc_exp, strlen("mds_conn"),
+ "mds_conn", 0, NULL);
if (!rc)
rc = rc2;
RETURN(rc);
struct llog_ctxt *ctxt =
llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
rc = llog_ioctl(ctxt, cmd, data);
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
RETURN(rc);
}
} else {
LASSERT(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT) != NULL);
- rc = obd_set_info(obd->u.mds.mds_osc_exp, strlen("mds_conn"), "mds_conn",
- 0, uuid);
+ rc = obd_set_info(obd->u.mds.mds_osc_exp, strlen("mds_conn"),
+ "mds_conn", 0, uuid);
if (rc != 0)
RETURN(rc);
{
struct obd_device *obd = req->rq_export->exp_obd;
struct mds_body *request_body, *reply_body;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc, size = sizeof(*reply_body);
ENTRY;
RETURN(rc);
reply_body = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*reply_body));
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = mds_open_by_fid(req, &request_body->fid1, reply_body,
request_body->flags, NULL, NULL);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
RETURN(rc);
}
GOTO(cleanup, rc);
cleanup:
- rc = mds_finish_transno(mds, dchild ? dchild->d_inode : NULL, handle,
- req, rc, rep ? rep->lock_policy_res1 : 0);
+ if (dchild && dchild->d_inode)
+ rc = mds_finish_transno(mds, dchild->d_inode, handle, req, rc,
+ rep ? rep->lock_policy_res1 : 0);
+ else
+ rc = mds_finish_transno(mds, !IS_ERR(dparent) ? dparent->d_inode :
+ NULL, handle, req, rc,
+ rep ? rep->lock_policy_res1 : 0);
switch (cleanup_phase) {
case 2:
struct obd_device *obd = req->rq_export->exp_obd;
struct mds_body *body;
struct mds_file_data *mfd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct inode *inode;
int rc, repsize[3] = {sizeof(struct mds_body),
obd->u.mds.mds_max_mdsize,
list_del(&mfd->mfd_list);
spin_unlock(&med->med_open_lock);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
req->rq_status = mds_mfd_close(rc ? NULL : req, obd, mfd, 1);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK)) {
CERROR("test case OBD_FAIL_MDS_CLOSE_PACK\n");
#include <linux/lustre_idl.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_dlm.h>
+#include <linux/lustre_log.h>
#include <linux/lustre_fsfilt.h>
#include "mds_internal.h"
} else {
///* XXX 0 normally, SENDNOW for debug */);
ctxt = llog_get_context(obd,mlcd->mlcd_cookies[0].lgc_subsys+1);
- rc = llog_cancel(ctxt, lsm, mlcd->mlcd_cookielen /
- sizeof(*mlcd->mlcd_cookies),
- mlcd->mlcd_cookies, OBD_LLOG_FL_SENDNOW);
+ rc = llog_cancel(ctxt, mlcd->mlcd_cookielen /
+ sizeof(*mlcd->mlcd_cookies),
+ mlcd->mlcd_cookies, OBD_LLOG_FL_SENDNOW, lsm);
if (rc)
CERROR("error cancelling %d log cookies: rc %d\n",
(int)(mlcd->mlcd_cookielen /
mcd->mcd_last_result = cpu_to_le32(rc);
mcd->mcd_last_data = cpu_to_le32(op_data);
- fsfilt_add_journal_cb(req->rq_export->exp_obd, transno, handle,
- mds_commit_cb, NULL);
+ fsfilt_add_journal_cb(req->rq_export->exp_obd, mds->mds_sb,
+ transno, handle, mds_commit_cb, NULL);
err = fsfilt_write_record(obd, mds->mds_rcvd_filp, mcd, sizeof(*mcd),
&off, 0);
EXIT;
cleanup:
if (mlcd != NULL)
- fsfilt_add_journal_cb(req->rq_export->exp_obd, 0, handle,
- mds_cancel_cookies_cb, mlcd);
+ fsfilt_add_journal_cb(req->rq_export->exp_obd, mds->mds_sb, 0,
+ handle, mds_cancel_cookies_cb, mlcd);
err = mds_finish_transno(mds, inode, handle, req, rc, 0);
switch (cleanup_phase) {
case 1:
struct ptlrpc_request *req, struct lustre_handle *lockh)
{
struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc;
ENTRY;
LASSERT(rec->ur_opcode <= REINT_MAX &&
reinters[rec->ur_opcode] != NULL);
- push_ctxt(&saved, &obd->obd_ctxt, &rec->ur_uc);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, &rec->ur_uc);
rc = reinters[rec->ur_opcode] (rec, offset, req, lockh);
- pop_ctxt(&saved, &obd->obd_ctxt, &rec->ur_uc);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &rec->ur_uc);
RETURN(rc);
}
int mds_cleanup_orphans(struct obd_device *obd)
{
struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct file *file;
struct dentry *dchild, *dentry;
struct vfsmount *mnt;
int rc = 0, item = 0, namlen;
ENTRY;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
dentry = dget(mds->mds_pending_dir);
if (IS_ERR(dentry))
GOTO(err_pop, rc = PTR_ERR(dentry));
OBD_FREE(dirent, sizeof(*dirent));
}
err_pop:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc == 0)
rc = item;
RETURN(rc);
MODULES := obdclass llog_test
-obdclass-objs := llog.o llog_cat.o llog_lvfs.o llog_obd.o class_obd.o
+obdclass-objs := llog_obd.o class_obd.o
obdclass-objs += debug.o genops.o sysctl.o uuid.o llog_ioctl.o
obdclass-objs += lprocfs_status.o lustre_handles.o lustre_peer.o
obdclass-objs += statfs_pack.o obdo.o obd_config.o
include $(src)/../portals/Kernelenv
obj-y += obdclass.o
-obdclass-objs := llog.o llog_cat.o class_obd.o debug.o \
+obdclass-objs := class_obd.o debug.o \
genops.o sysctl.o uuid.o lprocfs_status.o lustre_handles.o \
- lustre_peer.o statfs_pack.o obdo.o llog_lvfs.o llog_obd.o \
+ lustre_peer.o statfs_pack.o obdo.o llog_obd.o \
obd_config.o llog_ioctl.o
$(obj)/class_obd.o: lustre_build_version
noinst_LIBRARIES = liblustreclass.a
liblustreclass_a_SOURCES = class_obd.c debug.c genops.c statfs_pack.c uuid.c
liblustreclass_a_SOURCES += lustre_handles.c lustre_peer.c lprocfs_status.c
-liblustreclass_a_SOURCES += obdo.c obd_config.c llog.c llog_obd.c llog_cat.c
-liblustreclass_a_SOURCES += llog_lvfs.c #llog_ioctl.c rbtree.c
+liblustreclass_a_SOURCES += obdo.c obd_config.c llog_obd.c #llog_ioctl.c rbtree.c
liblustreclass_a_CPPFLAGS = $(LLCPPFLAGS) -DLUSTRE_VERSION=\"32\" -DBUILD_VERSION=\"1\"
liblustreclass_a_CFLAGS = $(LLCFLAGS)
endif # MODULES
MOSTLYCLEANFILES = *.o *.ko *.mod.c llog-test.c
-DIST_SOURCES = $(filter-out llog-test.c,$(obdclass-objs:.o=.c)) $(llog-test-objs:.o=.c) llog_test.c llog_internal.h
+DIST_SOURCES = $(filter-out llog-test.c,$(obdclass-objs:.o=.c)) $(llog-test-objs:.o=.c) llog_test.c
#include <linux/lustre_build_version.h>
#endif
#include <portals/list.h>
-#include "llog_internal.h"
#ifndef __KERNEL__
/* liblustre workaround */
+++ /dev/null
-#ifndef __LLOG_INTERNAL_H__
-#define __LLOG_INTERNAL_H__
-
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray);
-int llog_cat_id2handle(struct llog_handle *cathandle, struct llog_handle **res,
- struct llog_logid *logid);
-#endif
#include <linux/obd_class.h>
#include <linux/lustre_log.h>
#include <portals/list.h>
-#include "llog_internal.h"
static int str2logid(struct llog_logid *logid, char *str, int len)
{
}
EXPORT_SYMBOL(llog_ioctl);
-int llog_catlog_list(struct obd_device *obd, int count,
- struct obd_ioctl_data *data)
+int llog_catalog_list(struct obd_device *obd, int count,
+ struct obd_ioctl_data *data)
{
int size, i;
struct llog_catid *idarray;
RETURN(-ENOMEM);
memset(idarray, 0, size);
- rc = llog_get_cat_list(obd, obd, name, count, idarray);
+ rc = llog_get_cat_list(&obd->obd_lvfs_ctxt, obd->obd_fsops,
+ name, count, idarray);
if (rc) {
OBD_FREE(idarray, size);
RETURN(rc);
RETURN(0);
}
-EXPORT_SYMBOL(llog_catlog_list);
+EXPORT_SYMBOL(llog_catalog_list);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001-2003 Cluster File Systems, Inc.
- * Author: Andreas Dilger <adilger@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.
- *
- * OST<->MDS recovery logging infrastructure.
- *
- * Invariants in implementation:
- * - we do not share logs among different OST<->MDS connections, so that
- * if an OST or MDS fails it need only look at log(s) relevant to itself
- */
-
-#define DEBUG_SUBSYSTEM S_LOG
-
-#ifndef EXPORT_SYMTAB
-#define EXPORT_SYMTAB
-#endif
-
-#ifdef __KERNEL__
-#include <linux/fs.h>
-#else
-#include <liblustre.h>
-#endif
-
-#include <linux/obd.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_log.h>
-#include <linux/obd_ost.h>
-#include <portals/list.h>
-#include <linux/lvfs.h>
-#include <linux/lustre_fsfilt.h>
-#include "llog_internal.h"
-
-#ifdef __KERNEL__
-
-static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file,
- int len, int index)
-{
- struct llog_rec_hdr rec = { 0 };
- struct llog_rec_tail tail;
- int rc;
- ENTRY;
-
- LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0);
-
- tail.lrt_len = rec.lrh_len = len;
- tail.lrt_index = rec.lrh_index = index;
- rec.lrh_type = 0;
-
- rc = fsfilt_write_record(obd, file, &rec, sizeof(rec), &file->f_pos, 0);
- if (rc) {
- CERROR("error writing padding record: rc %d\n", rc);
- goto out;
- }
-
- file->f_pos += len - sizeof(rec) - sizeof(tail);
- rc = fsfilt_write_record(obd, file, &tail, sizeof(tail),&file->f_pos,0);
- if (rc) {
- CERROR("error writing padding record: rc %d\n", rc);
- goto out;
- }
-
- out:
- RETURN(rc);
-}
-
-static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file,
- struct llog_rec_hdr *rec, void *buf, loff_t off)
-{
- int rc;
- struct llog_rec_tail end;
- loff_t saved_off = file->f_pos;
- int buflen = rec->lrh_len;
-
- ENTRY;
- file->f_pos = off;
-
- if (!buf) {
- rc = fsfilt_write_record(obd, file, rec, buflen,&file->f_pos,0);
- if (rc) {
- CERROR("error writing log record: rc %d\n", rc);
- goto out;
- }
- GOTO(out, rc = 0);
- }
-
- /* the buf case */
- rec->lrh_len = sizeof(*rec) + buflen + sizeof(end);
- rc = fsfilt_write_record(obd, file, rec, sizeof(*rec), &file->f_pos, 0);
- if (rc) {
- CERROR("error writing log hdr: rc %d\n", rc);
- goto out;
- }
-
- rc = fsfilt_write_record(obd, file, buf, buflen, &file->f_pos, 0);
- if (rc) {
- CERROR("error writing log buffer: rc %d\n", rc);
- goto out;
- }
-
- end.lrt_len = rec->lrh_len;
- end.lrt_index = rec->lrh_index;
- rc = fsfilt_write_record(obd, file, &end, sizeof(end), &file->f_pos, 0);
- if (rc) {
- CERROR("error writing log tail: rc %d\n", rc);
- goto out;
- }
-
- rc = 0;
- out:
- if (saved_off > file->f_pos)
- file->f_pos = saved_off;
- LASSERT(rc <= 0);
- RETURN(rc);
-}
-
-static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file,
- void *buf, int size, loff_t off)
-{
- loff_t offset = off;
- int rc;
- ENTRY;
-
- rc = fsfilt_read_record(obd, file, buf, size, &offset);
- if (rc) {
- CERROR("error reading log record: rc %d\n", rc);
- RETURN(rc);
- }
- RETURN(0);
-}
-
-static int llog_lvfs_read_header(struct llog_handle *handle)
-{
- struct obd_device *obd;
- int rc;
- ENTRY;
-
- LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE);
-
- obd = handle->lgh_ctxt->loc_exp->exp_obd;
-
- if (handle->lgh_file->f_dentry->d_inode->i_size == 0) {
- CDEBUG(D_HA, "not reading header from 0-byte log\n");
- RETURN(LLOG_EEMPTY);
- }
-
- rc = llog_lvfs_read_blob(obd, handle->lgh_file, handle->lgh_hdr,
- LLOG_CHUNK_SIZE, 0);
- if (rc) {
- CERROR("error reading log header from %*s\n",
- handle->lgh_file->f_dentry->d_name.len,
- handle->lgh_file->f_dentry->d_name.name);
- } else {
- struct llog_rec_hdr *llh_hdr = &handle->lgh_hdr->llh_hdr;
- /*
- * These need to be fixed for bug 1987
- */
- if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) {
- CERROR("bad log %*s header magic: %#x (expected %#x)\n",
- handle->lgh_file->f_dentry->d_name.len,
- handle->lgh_file->f_dentry->d_name.name,
- llh_hdr->lrh_type, LLOG_HDR_MAGIC);
- rc = -EIO;
- } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) {
- CERROR("incorrectly sized log %*s header: %#x "
- "(expected %#x)\n",
- handle->lgh_file->f_dentry->d_name.len,
- handle->lgh_file->f_dentry->d_name.name,
- llh_hdr->lrh_len, LLOG_CHUNK_SIZE);
- CERROR("you may need to re-run lconf --write_conf.\n");
- rc = -EIO;
- }
- }
-
- handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index;
- handle->lgh_file->f_pos = handle->lgh_file->f_dentry->d_inode->i_size;
-
- RETURN(rc);
-}
-
-/* returns negative in on error; 0 if success && reccookie == 0; 1 otherwise */
-/* appends if idx == -1, otherwise overwrites record idx. */
-static int llog_lvfs_write_rec(struct llog_handle *loghandle,
- struct llog_rec_hdr *rec,
- struct llog_cookie *reccookie, int cookiecount,
- void *buf, int idx)
-{
- struct llog_log_hdr *llh;
- int reclen = rec->lrh_len, index, rc;
- struct llog_rec_tail *lrt;
- struct obd_device *obd;
- struct file *file;
- size_t left;
- ENTRY;
-
- llh = loghandle->lgh_hdr;
- file = loghandle->lgh_file;
- obd = loghandle->lgh_ctxt->loc_exp->exp_obd;
-
- /* record length should not bigger than LLOG_CHUNK_SIZE */
- if (buf)
- rc = (reclen > LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr) -
- sizeof(struct llog_rec_tail)) ? -E2BIG : 0;
- else
- rc = (reclen > LLOG_CHUNK_SIZE) ? -E2BIG : 0;
- if (rc)
- RETURN(rc);
-
- if (idx != -1) {
- loff_t saved_offset;
-
- /* no header: only allowed to insert record 1 */
- if (idx != 1 && !file->f_dentry->d_inode->i_size) {
- CERROR("idx != -1 in empty log\n");
- LBUG();
- }
-
- if (idx && llh->llh_size && llh->llh_size != reclen)
- RETURN(-EINVAL);
-
- rc = llog_lvfs_write_blob(obd, file, &llh->llh_hdr, NULL, 0);
- /* we are done if we only write the header or on error */
- if (rc || idx == 0)
- RETURN(rc);
-
- saved_offset = sizeof(*llh) + (idx-1)*rec->lrh_len;
- rc = llog_lvfs_write_blob(obd, file, rec, buf, saved_offset);
- if (rc == 0 && reccookie) {
- reccookie->lgc_lgl = loghandle->lgh_id;
- reccookie->lgc_index = idx;
- rc = 1;
- }
- RETURN(rc);
- }
-
- /* Make sure that records don't cross a chunk boundary, so we can
- * process them page-at-a-time if needed. If it will cross a chunk
- * boundary, write in a fake (but referenced) entry to pad the chunk.
- *
- * We know that llog_current_log() will return a loghandle that is
- * big enough to hold reclen, so all we care about is padding here.
- */
- left = LLOG_CHUNK_SIZE - (file->f_pos & (LLOG_CHUNK_SIZE - 1));
- if (buf)
- reclen = sizeof(*rec) + rec->lrh_len +
- sizeof(struct llog_rec_tail);
-
- /* NOTE: padding is a record, but no bit is set */
- if (left != 0 && left != reclen &&
- left < (reclen + LLOG_MIN_REC_SIZE)) {
- int bitmap_size = sizeof(llh->llh_bitmap) * 8;
- loghandle->lgh_last_idx++;
- rc = llog_lvfs_pad(obd, file, left, loghandle->lgh_last_idx);
- if (rc)
- RETURN(rc);
- /* if it's the last idx in log file, then return -ENOSPC */
- if (loghandle->lgh_last_idx == bitmap_size - 1)
- RETURN(-ENOSPC);
- }
-
- loghandle->lgh_last_idx++;
- index = loghandle->lgh_last_idx;
- rec->lrh_index = index;
- if (buf == NULL) {
- lrt = (struct llog_rec_tail *)
- ((char *)rec + rec->lrh_len - sizeof(*lrt));
- lrt->lrt_len = rec->lrh_len;
- lrt->lrt_index = rec->lrh_index;
- }
- if (ext2_set_bit(index, llh->llh_bitmap)) {
- CERROR("argh, index %u already set in log bitmap?\n", index);
- LBUG(); /* should never happen */
- }
- llh->llh_count++;
- llh->llh_tail.lrt_index = index;
-
- rc = llog_lvfs_write_blob(obd, file, &llh->llh_hdr, NULL, 0);
- if (rc)
- RETURN(rc);
-
- rc = llog_lvfs_write_blob(obd, file, rec, buf, file->f_pos);
- if (rc)
- RETURN(rc);
-
- CDEBUG(D_HA, "added record "LPX64": idx: %u, %u bytes\n",
- loghandle->lgh_id.lgl_oid, index, rec->lrh_len);
- if (rc == 0 && reccookie) {
- reccookie->lgc_lgl = loghandle->lgh_id;
- reccookie->lgc_index = index;
- if (rec->lrh_type == MDS_UNLINK_REC)
- reccookie->lgc_subsys = LLOG_UNLINK_ORIG_CTXT;
- else if (rec->lrh_type == OST_SZ_REC)
- reccookie->lgc_subsys = LLOG_SIZE_ORIG_CTXT;
- else if (rec->lrh_type == OST_RAID1_REC)
- reccookie->lgc_subsys = LLOG_RD1_ORIG_CTXT;
- else
- reccookie->lgc_subsys = -1;
- rc = 1;
- }
- if (rc == 0 && rec->lrh_type == LLOG_GEN_REC)
- rc = 1;
-
- RETURN(rc);
-}
-
-/* We can skip reading at least as many log blocks as the number of
-* minimum sized log records we are skipping. If it turns out
-* that we are not far enough along the log (because the
-* actual records are larger than minimum size) we just skip
-* some more records. */
-
-static void llog_skip_over(__u64 *off, int curr, int goal)
-{
- if (goal <= curr)
- return;
- *off = (*off + (goal-curr-1) * LLOG_MIN_REC_SIZE) &
- ~(LLOG_CHUNK_SIZE - 1);
-}
-
-
-/* sets:
- * - cur_offset to the furthest point read in the log file
- * - cur_idx to the log index preceeding cur_offset
- * returns -EIO/-EINVAL on error
- */
-static int llog_lvfs_next_block(struct llog_handle *loghandle, int *cur_idx,
- int next_idx, __u64 *cur_offset, void *buf,
- int len)
-{
- int rc;
- ENTRY;
-
- if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
- RETURN(-EINVAL);
-
- CDEBUG(D_OTHER, "looking for log index %u (cur idx %u off "LPU64")\n",
- next_idx, *cur_idx, *cur_offset);
-
- while (*cur_offset < loghandle->lgh_file->f_dentry->d_inode->i_size) {
- struct llog_rec_hdr *rec;
- struct llog_rec_tail *tail;
- loff_t ppos;
-
- llog_skip_over(cur_offset, *cur_idx, next_idx);
-
- ppos = *cur_offset;
- rc = fsfilt_read_record(loghandle->lgh_ctxt->loc_exp->exp_obd,
- loghandle->lgh_file, buf, len,
- &ppos);
-
- if (rc) {
- CERROR("Cant read llog block at log id "LPU64
- "/%u offset "LPU64"\n",
- loghandle->lgh_id.lgl_oid,
- loghandle->lgh_id.lgl_ogen,
- *cur_offset);
- RETURN(rc);
- }
-
- /* put number of bytes read into rc to make code simpler */
- rc = ppos - *cur_offset;
- *cur_offset = ppos;
-
- if (rc == 0) /* end of file, nothing to do */
- RETURN(0);
-
- if (rc < sizeof(*tail)) {
- CERROR("Invalid llog block at log id "LPU64"/%u offset "
- LPU64"\n", loghandle->lgh_id.lgl_oid,
- loghandle->lgh_id.lgl_ogen, *cur_offset);
- RETURN(-EINVAL);
- }
-
- tail = buf + rc - sizeof(struct llog_rec_tail);
- *cur_idx = tail->lrt_index;
-
- /* this shouldn't happen */
- if (tail->lrt_index == 0) {
- CERROR("Invalid llog tail at log id "LPU64"/%u offset "
- LPU64"\n", loghandle->lgh_id.lgl_oid,
- loghandle->lgh_id.lgl_ogen, *cur_offset);
- RETURN(-EINVAL);
- }
- if (tail->lrt_index < next_idx)
- continue;
-
- /* sanity check that the start of the new buffer is no farther
- * than the record that we wanted. This shouldn't happen. */
- rec = buf;
- if (rec->lrh_index > next_idx) {
- CERROR("missed desired record? %u > %u\n",
- rec->lrh_index, next_idx);
- RETURN(-ENOENT);
- }
- RETURN(0);
- }
- RETURN(-EIO);
-}
-
-static struct file *llog_filp_open(char *name, int flags, int mode)
-{
- char *logname;
- struct file *filp;
- int len;
-
- OBD_ALLOC(logname, PATH_MAX);
- if (logname == NULL)
- return ERR_PTR(-ENOMEM);
-
- len = snprintf(logname, PATH_MAX, "LOGS/%s", name);
- if (len >= PATH_MAX - 1) {
- filp = ERR_PTR(-ENAMETOOLONG);
- } else {
- filp = l_filp_open(logname, flags, mode);
- if (IS_ERR(filp))
- CERROR("logfile creation %s: %ld\n", logname,
- PTR_ERR(filp));
- }
-
- OBD_FREE(logname, PATH_MAX);
- return filp;
-}
-
-/* This is a callback from the llog_* functions.
- * Assumes caller has already pushed us into the kernel context. */
-static int llog_lvfs_create(struct llog_ctxt *ctxt, struct llog_handle **res,
- struct llog_logid *logid, char *name)
-{
- struct llog_handle *handle;
- struct obd_device *obd;
- struct l_dentry *dchild = NULL;
- struct obdo *oa = NULL;
- int rc = 0, cleanup_phase = 1;
- int open_flags = O_RDWR | O_CREAT | O_LARGEFILE;
- ENTRY;
-
- handle = llog_alloc_handle();
- if (handle == NULL)
- RETURN(-ENOMEM);
- *res = handle;
-
- LASSERT(ctxt);
- LASSERT(ctxt->loc_exp);
- obd = ctxt->loc_exp->exp_obd;
-
- if (logid != NULL) {
- dchild = obd_lvfs_fid2dentry(ctxt->loc_exp, logid->lgl_oid,
- logid->lgl_ogen, logid->lgl_ogr);
-
- if (IS_ERR(dchild)) {
- rc = PTR_ERR(dchild);
- CERROR("error looking up logfile "LPX64":0x%x: rc %d\n",
- logid->lgl_oid, logid->lgl_ogen, rc);
- GOTO(cleanup, rc);
- }
-
- cleanup_phase = 2;
- if (dchild->d_inode == NULL) {
- rc = -ENOENT;
- CERROR("nonexistent log file "LPX64":"LPX64": rc %d\n",
- logid->lgl_oid, logid->lgl_ogr, rc);
- GOTO(cleanup, rc);
- }
-
- handle->lgh_file = l_dentry_open(&obd->obd_ctxt, dchild,
- O_RDWR | O_LARGEFILE);
- if (IS_ERR(handle->lgh_file)) {
- rc = PTR_ERR(handle->lgh_file);
- CERROR("error opening logfile "LPX64"0x%x: rc %d\n",
- logid->lgl_oid, logid->lgl_ogen, rc);
- GOTO(cleanup, rc);
- }
-
- /* assign the value of lgh_id for handle directly */
- handle->lgh_id = *logid;
-
- } else if (name) {
- handle->lgh_file = llog_filp_open(name, open_flags, 0644);
- if (IS_ERR(handle->lgh_file))
- GOTO(cleanup, rc = PTR_ERR(handle->lgh_file));
-
- handle->lgh_id.lgl_ogr = 1;
- handle->lgh_id.lgl_oid =
- handle->lgh_file->f_dentry->d_inode->i_ino;
- handle->lgh_id.lgl_ogen =
- handle->lgh_file->f_dentry->d_inode->i_generation;
- } else {
- oa = obdo_alloc();
- if (oa == NULL)
- GOTO(cleanup, rc = -ENOMEM);
- /* XXX get some filter group constants */
- oa->o_gr = 1;
- oa->o_valid = OBD_MD_FLGENER | OBD_MD_FLGROUP;
- rc = obd_create(ctxt->loc_exp, oa, NULL, NULL);
- if (rc)
- GOTO(cleanup, rc);
-
- dchild = obd_lvfs_fid2dentry(ctxt->loc_exp, oa->o_id,
- oa->o_generation, oa->o_gr);
-
- if (IS_ERR(dchild))
- GOTO(cleanup, rc = PTR_ERR(dchild));
- cleanup_phase = 2;
- handle->lgh_file = l_dentry_open(&obd->obd_ctxt, dchild,
- open_flags);
- if (IS_ERR(handle->lgh_file))
- GOTO(cleanup, rc = PTR_ERR(handle->lgh_file));
-
- handle->lgh_id.lgl_ogr = oa->o_gr;
- handle->lgh_id.lgl_oid = oa->o_id;
- handle->lgh_id.lgl_ogen = oa->o_generation;
- }
-
- handle->lgh_ctxt = ctxt;
- finish:
- if (oa)
- obdo_free(oa);
- RETURN(rc);
-cleanup:
- switch (cleanup_phase) {
- case 2:
- l_dput(dchild);
- case 1:
- llog_free_handle(handle);
- }
- goto finish;
-}
-
-static int llog_lvfs_close(struct llog_handle *handle)
-{
- int rc;
- ENTRY;
-
- rc = filp_close(handle->lgh_file, 0);
- if (rc)
- CERROR("error closing log: rc %d\n", rc);
- RETURN(rc);
-}
-
-static int llog_lvfs_destroy(struct llog_handle *handle)
-{
- struct dentry *fdentry;
- struct obdo *oa;
- int rc;
- ENTRY;
-
- fdentry = handle->lgh_file->f_dentry;
- if (!strcmp(fdentry->d_parent->d_name.name, "LOGS")) {
- struct obd_device *obd = handle->lgh_ctxt->loc_exp->exp_obd;
- struct inode *inode = fdentry->d_parent->d_inode;
- struct obd_run_ctxt saved;
-
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- dget(fdentry);
- rc = llog_lvfs_close(handle);
-
- if (rc == 0) {
- down(&inode->i_sem);
- rc = vfs_unlink(inode, fdentry);
- up(&inode->i_sem);
- }
-
- dput(fdentry);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
- RETURN(rc);
- }
-
- oa = obdo_alloc();
- if (oa == NULL)
- RETURN(-ENOMEM);
-
- oa->o_id = handle->lgh_id.lgl_oid;
- oa->o_gr = handle->lgh_id.lgl_ogr;
- oa->o_generation = handle->lgh_id.lgl_ogen;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLGENER;
-
- rc = llog_lvfs_close(handle);
- if (rc)
- GOTO(out, rc);
-
- rc = obd_destroy(handle->lgh_ctxt->loc_exp, oa, NULL, NULL);
- out:
- obdo_free(oa);
- RETURN(rc);
-}
-
-/* reads the catalog list */
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray)
-{
- struct obd_run_ctxt saved;
- struct l_file *file;
- int rc;
- int size = sizeof(*idarray) * count;
- loff_t off = 0;
-
- LASSERT(count);
-
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
- if (!file || IS_ERR(file)) {
- rc = PTR_ERR(file);
- CERROR("OBD filter: cannot open/create %s: rc = %d\n",
- name, rc);
- GOTO(out, rc);
- }
-
- if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
- CERROR("%s is not a regular file!: mode = %o\n", name,
- file->f_dentry->d_inode->i_mode);
- GOTO(out, rc = -ENOENT);
- }
-
- rc = fsfilt_read_record(disk_obd, file, idarray, size, &off);
- if (rc) {
- CDEBUG(D_INODE,"OBD filter: error reading %s: rc %d\n",
- name, rc);
- GOTO(out, rc);
- }
-
- out:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
- if (file && !IS_ERR(file))
- rc = filp_close(file, 0);
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_get_cat_list);
-
-/* writes the cat list */
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray)
-{
- struct obd_run_ctxt saved;
- struct l_file *file;
- int rc;
- int size = sizeof(*idarray) * count;
- loff_t off = 0;
-
- LASSERT(count);
-
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
- file = filp_open(name, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
- if (!file || IS_ERR(file)) {
- rc = PTR_ERR(file);
- CERROR("OBD filter: cannot open/create %s: rc = %d\n",
- name, rc);
- GOTO(out, rc);
- }
-
- if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
- CERROR("%s is not a regular file!: mode = %o\n", name,
- file->f_dentry->d_inode->i_mode);
- GOTO(out, rc = -ENOENT);
- }
-
- rc = fsfilt_write_record(disk_obd, file, idarray, size, &off, 1);
- if (rc) {
- CDEBUG(D_INODE,"OBD filter: error reading %s: rc %d\n",
- name, rc);
- GOTO(out, rc);
- }
-
- out:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
- if (file && !IS_ERR(file))
- rc = filp_close(file, 0);
- RETURN(rc);
-}
-
-struct llog_operations llog_lvfs_ops = {
- lop_write_rec: llog_lvfs_write_rec,
- lop_next_block: llog_lvfs_next_block,
- lop_read_header: llog_lvfs_read_header,
- lop_create: llog_lvfs_create,
- lop_destroy: llog_lvfs_destroy,
- lop_close: llog_lvfs_close,
- // lop_cancel: llog_lvfs_cancel,
-};
-
-EXPORT_SYMBOL(llog_lvfs_ops);
-
-#else /* !__KERNEL__ */
-
-static int llog_lvfs_read_header(struct llog_handle *handle)
-{
- LBUG();
- return 0;
-}
-
-static int llog_lvfs_write_rec(struct llog_handle *loghandle,
- struct llog_rec_hdr *rec,
- struct llog_cookie *reccookie, int cookiecount,
- void *buf, int idx)
-{
- LBUG();
- return 0;
-}
-
-static int llog_lvfs_next_block(struct llog_handle *loghandle, int *cur_idx,
- int next_idx, __u64 *cur_offset, void *buf,
- int len)
-{
- LBUG();
- return 0;
-}
-
-static int llog_lvfs_create(struct llog_ctxt *ctxt, struct llog_handle **res,
- struct llog_logid *logid, char *name)
-{
- LBUG();
- return 0;
-}
-
-static int llog_lvfs_close(struct llog_handle *handle)
-{
- LBUG();
- return 0;
-}
-
-static int llog_lvfs_destroy(struct llog_handle *handle)
-{
- LBUG();
- return 0;
-}
-
-int llog_get_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray)
-{
- LBUG();
- return 0;
-}
-
-int llog_put_cat_list(struct obd_device *obd, struct obd_device *disk_obd,
- char *name, int count, struct llog_catid *idarray)
-{
- LBUG();
- return 0;
-}
-
-struct llog_operations llog_lvfs_ops = {
- lop_write_rec: llog_lvfs_write_rec,
- lop_next_block: llog_lvfs_next_block,
- lop_read_header: llog_lvfs_read_header,
- lop_create: llog_lvfs_create,
- lop_destroy: llog_lvfs_destroy,
- lop_close: llog_lvfs_close,
-// lop_cancel: llog_lvfs_cancel,
-};
-#endif
#include <linux/obd_class.h>
#include <linux/lustre_log.h>
#include <portals/list.h>
-#include "llog_internal.h"
/* helper functions for calling the llog obd methods */
-int llog_setup(struct obd_device *obd, int index, struct obd_device *disk_obd,
- int count, struct llog_logid *logid, struct llog_operations *op)
+int obd_llog_setup(struct obd_device *obd, int index,
+ struct obd_device *disk_obd, int count,
+ struct llog_logid *logid, struct llog_operations *op)
{
int rc = 0;
struct llog_ctxt *ctxt;
RETURN(-ENOMEM);
obd->obd_llog_ctxt[index] = ctxt;
+ ctxt->loc_logops = op;
ctxt->loc_obd = obd;
- ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
ctxt->loc_idx = index;
- ctxt->loc_logops = op;
+ ctxt->loc_exp = class_export_get(disk_obd->obd_self_export);
sema_init(&ctxt->loc_sem, 1);
+ if (op->lop_close == llog_lvfs_ops.lop_close) {
+ ctxt->loc_fsops = disk_obd->obd_fsops;
+ ctxt->loc_lvfs_ctxt = &disk_obd->obd_lvfs_ctxt;
+ if (!strcmp(disk_obd->obd_type->typ_name, "mds")) {
+ struct mds_obd *mds = &disk_obd->u.mds;
+ ctxt->loc_objects_dir = mds->mds_objects_dir;
+ ctxt->loc_logs_dir = mds->mds_logs_dir;
+ }
+ }
+
if (op->lop_setup)
rc = op->lop_setup(obd, index, disk_obd, count, logid);
- if (ctxt && rc)
+ if (ctxt && rc) {
+ obd->obd_llog_ctxt[index] = NULL;
OBD_FREE(ctxt, sizeof(*ctxt));
+ }
RETURN(rc);
}
-EXPORT_SYMBOL(llog_setup);
+EXPORT_SYMBOL(obd_llog_setup);
-int llog_cleanup(struct llog_ctxt *ctxt)
+int obd_llog_cleanup(struct llog_ctxt *ctxt)
{
int rc = 0;
ENTRY;
LASSERT(ctxt);
- if (CTXTP(ctxt, cleanup))
- rc = CTXTP(ctxt, cleanup)(ctxt);
-
ctxt->loc_obd->obd_llog_ctxt[ctxt->loc_idx] = NULL;
class_export_put(ctxt->loc_exp);
ctxt->loc_exp = NULL;
- OBD_FREE(ctxt, sizeof(*ctxt));
-
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_cleanup);
-
-int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp)
-{
- int rc = 0;
- ENTRY;
-
- if (!ctxt)
- RETURN(0);
-
- if (CTXTP(ctxt, sync))
- rc = CTXTP(ctxt, sync)(ctxt, exp);
-
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_sync);
-int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
- struct lov_stripe_md *lsm, struct llog_cookie *logcookies,
- int numcookies)
-{
- int rc;
- ENTRY;
-
- LASSERT(ctxt);
- CTXT_CHECK_OP(ctxt, add, -EOPNOTSUPP);
-
- rc = CTXTP(ctxt, add)(ctxt, rec, lsm, logcookies, numcookies);
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_add);
-
-int llog_cancel(struct llog_ctxt *ctxt, struct lov_stripe_md *lsm,
- int count, struct llog_cookie *cookies, int flags)
-{
- int rc;
- ENTRY;
+ if (CTXTP(ctxt, cleanup))
+ rc = CTXTP(ctxt, cleanup)(ctxt);
+ else
+ OBD_FREE(ctxt, sizeof(*ctxt));
- LASSERT(ctxt);
- CTXT_CHECK_OP(ctxt, cancel, -EOPNOTSUPP);
- rc = CTXTP(ctxt, cancel)(ctxt, lsm, count, cookies, flags);
RETURN(rc);
}
-EXPORT_SYMBOL(llog_cancel);
+EXPORT_SYMBOL(obd_llog_cleanup);
/* callback func for llog_process in llog_obd_origin_setup */
static int cat_cancel_cb(struct llog_handle *cathandle,
{
struct llog_ctxt *ctxt;
struct llog_handle *handle;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc;
ENTRY;
*logid = handle->lgh_id;
}
if (rc)
- GOTO(out, rc);
+ RETURN(rc);
ctxt->loc_handle = handle;
- push_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
rc = llog_init_handle(handle, LLOG_F_IS_CAT, NULL);
- pop_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &disk_obd->obd_lvfs_ctxt, NULL);
if (rc)
- GOTO(out, rc);
+ RETURN(rc);
rc = llog_process(handle, (llog_cb_t)cat_cancel_cb, NULL, NULL);
if (rc)
CERROR("llog_process with cat_cancel_cb failed: %d\n", rc);
- out:
- if (ctxt && rc) {
- obd->obd_llog_ctxt[index] = NULL;
- OBD_FREE(ctxt, sizeof(*ctxt));
- }
RETURN(rc);
}
EXPORT_SYMBOL(llog_obd_origin_setup);
-int llog_obd_origin_cleanup(struct llog_ctxt *ctxt)
-{
- struct llog_handle *cathandle, *n, *loghandle;
- struct llog_log_hdr *llh;
- int rc, index;
- ENTRY;
-
- if (!ctxt)
- return 0;
-
- cathandle = ctxt->loc_handle;
- if (cathandle) {
- list_for_each_entry_safe(loghandle, n,
- &cathandle->u.chd.chd_head,
- u.phd.phd_entry) {
- llh = loghandle->lgh_hdr;
- if ((llh->llh_flags &
- LLOG_F_ZAP_WHEN_EMPTY) &&
- (llh->llh_count == 1)) {
- rc = llog_destroy(loghandle);
- if (rc)
- CERROR("failure destroying log during "
- "cleanup: %d\n", rc);
- LASSERT(rc == 0);
-
- index = loghandle->u.phd.phd_cookie.lgc_index;
- llog_free_handle(loghandle);
-
- LASSERT(index);
- llog_cat_set_first_idx(cathandle, index);
- rc = llog_cancel_rec(cathandle, index);
- if (rc == 0)
- CDEBUG(D_HA, "cancel plain log at index"
- " %u of catalog "LPX64"\n",
- index,cathandle->lgh_id.lgl_oid);
- }
- }
- llog_cat_put(ctxt->loc_handle);
- }
- return 0;
-}
-EXPORT_SYMBOL(llog_obd_origin_cleanup);
-
-/* add for obdfilter/sz and mds/unlink */
-int llog_obd_origin_add(struct llog_ctxt *ctxt,
- struct llog_rec_hdr *rec, struct lov_stripe_md *lsm,
- struct llog_cookie *logcookies, int numcookies)
-{
- struct llog_handle *cathandle;
- int rc;
- ENTRY;
-
- cathandle = ctxt->loc_handle;
- LASSERT(cathandle != NULL);
- rc = llog_cat_add_rec(cathandle, rec, logcookies, NULL);
- if (rc != 1)
- CERROR("write one catalog record failed: %d\n", rc);
- RETURN(rc);
-}
-EXPORT_SYMBOL(llog_obd_origin_add);
-
-int llog_cat_initialize(struct obd_device *obd, int count)
+int obd_llog_cat_initialize(struct obd_device *obd, int count, char *name)
{
struct llog_catid *idarray;
int size = sizeof(*idarray) * count;
- char name[32] = CATLIST;
int rc;
ENTRY;
if (!idarray)
RETURN(-ENOMEM);
- rc = llog_get_cat_list(obd, obd, name, count, idarray);
+ rc = llog_get_cat_list(&obd->obd_lvfs_ctxt, obd->obd_fsops,
+ name, count, idarray);
if (rc) {
CERROR("rc: %d\n", rc);
GOTO(out, rc);
GOTO(out, rc);
}
- rc = llog_put_cat_list(obd, obd, name, count, idarray);
+ rc = llog_put_cat_list(&obd->obd_lvfs_ctxt, obd->obd_fsops,
+ name, count, idarray);
if (rc) {
CERROR("rc: %d\n", rc);
GOTO(out, rc);
OBD_FREE(idarray, size);
RETURN(rc);
}
-EXPORT_SYMBOL(llog_cat_initialize);
+EXPORT_SYMBOL(obd_llog_cat_initialize);
int obd_llog_init(struct obd_device *obd, struct obd_device *disk_obd,
int count, struct llog_catid *logid)
RETURN(0);
}
-
-
/* Test log and catalogue processing */
static int llog_test_5(struct obd_device *obd)
{
GOTO(out, rc);
}
+ CWARN("5f: print plain log entries reversely.. expect 6\n");
+ rc = llog_cat_reverse_process(llh, plain_print_cb, "foobar");
+ if (rc) {
+ CERROR("5f: reversely process with plain_print_cb failed: %d\n",
+ rc);
+ GOTO(out, rc);
+ }
+
out:
CWARN("5: close re-opened catalog\n");
if (llh)
if (rc)
CERROR("6: llog_process failed %d\n", rc);
+ rc = llog_reverse_process(llh, (llog_cb_t)plain_print_cb, NULL, NULL);
+ if (rc)
+ CERROR("6: llog_reverse_process failed %d\n", rc);
+
parse_out:
rc = llog_close(llh);
if (rc) {
static int llog_run_tests(struct obd_device *obd)
{
struct llog_handle *llh;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
int rc, err, cleanup_phase = 0;
char name[10];
ENTRY;
sprintf(name, "%x", llog_test_rand);
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
rc = llog_test_1(obd, name);
if (rc)
if (!rc)
rc = err;
case 0:
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
}
return rc;
int rc;
ENTRY;
- rc = llog_setup(obd, LLOG_TEST_ORIG_CTXT, tgt, 0, NULL, &llog_lvfs_ops);
+ rc = obd_llog_setup(obd, LLOG_TEST_ORIG_CTXT, tgt, 0, NULL,
+ &llog_lvfs_ops);
RETURN(rc);
}
int rc;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_TEST_ORIG_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_TEST_ORIG_CTXT));
RETURN(rc);
}
#endif
/* push / pop to root of obd store */
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
//ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
ASSERT_CTXT_MAGIC(new_ctx->magic);
LASSERT(new_ctx->pwdmnt);
if (uc) {
- save->ouc.ouc_fsuid = current->fsuid;
- save->ouc.ouc_fsgid = current->fsgid;
- save->ouc.ouc_cap = current->cap_effective;
- save->ouc.ouc_suppgid1 = current->groups[0];
- save->ouc.ouc_suppgid2 = current->groups[1];
-
- current->fsuid = uc->ouc_fsuid;
- current->fsgid = uc->ouc_fsgid;
- current->cap_effective = uc->ouc_cap;
+ save->luc.luc_fsuid = current->fsuid;
+ save->luc.luc_fsgid = current->fsgid;
+ save->luc.luc_cap = current->cap_effective;
+ save->luc.luc_suppgid1 = current->groups[0];
+ save->luc.luc_suppgid2 = current->groups[1];
+
+ current->fsuid = uc->luc_fsuid;
+ current->fsgid = uc->luc_fsgid;
+ current->cap_effective = uc->luc_cap;
current->ngroups = 0;
- if (uc->ouc_suppgid1 != -1)
- current->groups[current->ngroups++] = uc->ouc_suppgid1;
- if (uc->ouc_suppgid2 != -1)
- current->groups[current->ngroups++] = uc->ouc_suppgid2;
+ if (uc->luc_suppgid1 != -1)
+ current->groups[current->ngroups++] = uc->luc_suppgid1;
+ if (uc->luc_suppgid2 != -1)
+ current->groups[current->ngroups++] = uc->luc_suppgid2;
}
set_fs(new_ctx->fs);
set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
}
EXPORT_SYMBOL(push_ctxt);
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
+void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
+ struct lvfs_ucred *uc)
{
//printk("pc0");
ASSERT_CTXT_MAGIC(saved->magic);
dput(saved->pwd);
mntput(saved->pwdmnt);
if (uc) {
- current->fsuid = saved->ouc.ouc_fsuid;
- current->fsgid = saved->ouc.ouc_fsgid;
- current->cap_effective = saved->ouc.ouc_cap;
+ current->fsuid = saved->luc.luc_fsuid;
+ current->fsgid = saved->luc.luc_fsgid;
+ current->cap_effective = saved->luc.luc_cap;
current->ngroups = saved->ngroups;
- current->groups[0] = saved->ouc.ouc_suppgid1;
- current->groups[1] = saved->ouc.ouc_suppgid2;
+ current->groups[0] = saved->luc.luc_suppgid1;
+ current->groups[1] = saved->luc.luc_suppgid2;
}
/*
fcd->fcd_last_xid = 0;
off = fed->fed_lr_off;
- fsfilt_add_journal_cb(exp->exp_obd, last_rcvd, oti->oti_handle,
- filter_commit_cb, NULL);
+ fsfilt_add_journal_cb(exp->exp_obd, filter->fo_sb, last_rcvd,
+ oti->oti_handle, filter_commit_cb, NULL);
err = fsfilt_write_record(exp->exp_obd, filter->fo_rcvd_filp, fcd,
sizeof(*fcd), &off, 0);
if (err) {
fed->fed_lr_idx, fed->fed_lr_off, fed->fed_fcd->fcd_uuid);
if (new_client) {
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
loff_t off = fed->fed_lr_off;
int err;
void *handle;
CDEBUG(D_INFO, "writing client fcd at idx %u (%llu) (len %u)\n",
fed->fed_lr_idx,off,(unsigned int)sizeof(*fed->fed_fcd));
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
/* Transaction needed to fix bug 1403 */
handle = fsfilt_start(obd,
filter->fo_rcvd_filp->f_dentry->d_inode,
filter->fo_rcvd_filp->f_dentry->d_inode,
handle, 1);
}
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (err) {
CERROR("error writing %s client idx %u: rc %d\n",
struct filter_obd *filter = &exp->exp_obd->u.filter;
struct obd_device *obd = exp->exp_obd;
struct filter_client_data zero_fcd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int rc;
loff_t off;
ENTRY;
}
memset(&zero_fcd, 0, sizeof zero_fcd);
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = fsfilt_write_record(obd, filter->fo_rcvd_filp, &zero_fcd,
sizeof(zero_fcd), &off, 1);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
CDEBUG(rc == 0 ? D_INFO : D_ERROR,
"zeroing disconnecting client %s at idx %u (%llu) in %s rc %d\n",
/* setup the object store with correct subdirectories */
static int filter_prep(struct obd_device *obd)
{
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct filter_obd *filter = &obd->u.filter;
struct file *file;
struct inode *inode;
int rc = 0;
ENTRY;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
file = filp_open(LAST_RCVD, O_RDWR | O_CREAT | O_LARGEFILE, 0700);
if (!file || IS_ERR(file)) {
rc = PTR_ERR(file);
GOTO(err_server_data, rc);
out:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
return(rc);
/* cleanup the filter: write last used object id to status file */
static void filter_post(struct obd_device *obd)
{
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct filter_obd *filter = &obd->u.filter;
int rc, i;
* best to start a transaction with h_sync, because we removed this
* from lastobjid */
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
rc = filter_update_server_data(obd, filter->fo_rcvd_filp,
filter->fo_fsd, 0);
if (rc)
filter_cleanup_groups(obd);
filter_free_server_data(filter);
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
}
static void filter_set_last_id(struct filter_obd *filter, struct obdo *oa,
}
/* mount the file system (secretly) */
-int filter_common_setup(struct obd_device *obd, obd_count len, void *buf,
- char *option)
+int filter_common_setup(struct obd_device *obd, obd_count len,
+ void *buf, char *option)
{
struct lustre_cfg* lcfg = buf;
struct filter_obd *filter = &obd->u.filter;
struct vfsmount *mnt;
+ char name[32] = "CATLIST";
int rc = 0;
ENTRY;
filter->fo_fstype = mnt->mnt_sb->s_type->name;
CDEBUG(D_SUPER, "%s: mnt = %p\n", filter->fo_fstype, mnt);
- OBD_SET_CTXT_MAGIC(&obd->obd_ctxt);
- obd->obd_ctxt.pwdmnt = mnt;
- obd->obd_ctxt.pwd = mnt->mnt_root;
- obd->obd_ctxt.fs = get_ds();
- obd->obd_ctxt.cb_ops = filter_lvfs_ops;
+ OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
+ obd->obd_lvfs_ctxt.pwdmnt = mnt;
+ obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
+ obd->obd_lvfs_ctxt.fs = get_ds();
+ obd->obd_lvfs_ctxt.cb_ops = filter_lvfs_ops;
+
+ rc = fsfilt_setup(obd, mnt->mnt_sb);
+ if (rc)
+ GOTO(err_mntput, rc);
rc = filter_prep(obd);
if (rc)
ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
"filter_ldlm_cb_client", &obd->obd_ldlm_client);
- rc = llog_cat_initialize(obd, 1);
+ rc = obd_llog_cat_initialize(obd, 1, name);
if (rc) {
CERROR("failed to setup llogging subsystems\n");
GOTO(err_post, rc);
{
struct lprocfs_static_vars lvars;
struct lustre_cfg* lcfg = buf;
- const char *str = NULL;
- char *option = NULL;
- int n = 0;
int rc;
- if (!lcfg->lcfg_inlbuf1 || !lcfg->lcfg_inlbuf2)
- RETURN(-EINVAL);
-
- if (!strcmp(lcfg->lcfg_inlbuf2, "ext3") ||
- !strcmp(lcfg->lcfg_inlbuf2, "ldiskfs")) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- /* bug 1577: implement async-delete for 2.5 */
- str = "errors=remount-ro,asyncdel";
-#else
- str = "errors=remount-ro";
-#endif
- n = strlen(str) + 1;
- OBD_ALLOC(option, n);
- if (option == NULL)
- RETURN(-ENOMEM);
- strcpy(option, str);
- }
-
- rc = filter_common_setup(obd, len, buf, option);
- if (option)
- OBD_FREE(option, n);
+ /* all mount options including errors=remount-ro and asyncdel are passed
+ * using 4th lcfg param. And it is good, finally we have got rid of
+ * hardcoded fs types in the code. */
+
+ rc = filter_common_setup(obd, len, buf, lcfg->lcfg_inlbuf4);
lprocfs_init_vars(filter, &lvars);
if (rc == 0 && lprocfs_obd_setup(obd, lvars.obd_vars) == 0 &&
static int filter_setattr(struct obd_export *exp, struct obdo *oa,
struct lov_stripe_md *md, struct obd_trans_info *oti)
{
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct filter_obd *filter;
struct dentry *dentry;
struct iattr iattr;
iattr_from_obdo(&iattr, oa, oa->o_valid);
- push_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
lock_kernel();
if (iattr.ia_valid & ATTR_SIZE)
if (iattr.ia_valid & ATTR_SIZE)
up(&dentry->d_inode->i_sem);
unlock_kernel();
- pop_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
f_dput(dentry);
RETURN(rc);
struct lov_stripe_md **ea, struct obd_trans_info *oti)
{
struct obd_device *obd = NULL;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct lov_stripe_md *lsm = NULL;
obd_gr group = 0;
int rc = 0, diff;
}
obd = exp->exp_obd;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if ((oa->o_valid & OBD_MD_FLFLAGS) &&
(oa->o_flags & OBD_FL_RECREATE_OBJS)) {
}
}
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
if (rc && ea != NULL && *ea != lsm) {
obd_free_memmd(exp, &lsm);
} else if (rc == 0 && ea != NULL) {
struct obd_device *obd;
struct filter_obd *filter;
struct dentry *dchild = NULL, *dparent = NULL;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
void *handle = NULL;
struct llog_cookie *fcc = NULL;
int rc, rc2, cleanup_phase = 0, have_prepared = 0;
obd = exp->exp_obd;
filter = &obd->u.filter;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
acquire_locks:
dparent = filter_parent_lock(obd, group, oa->o_id);
goto acquire_locks;
}
- handle = fsfilt_start_log(obd, dparent->d_inode,FSFILT_OP_UNLINK,oti,1);
+ handle = fsfilt_start_log(obd, dparent->d_inode, FSFILT_OP_UNLINK, oti, 1);
if (IS_ERR(handle))
GOTO(cleanup, rc = PTR_ERR(handle));
+
cleanup_phase = 3;
/* Our MDC connection is established by the MDS to us */
case 3:
if (fcc != NULL) {
if (oti != NULL)
- fsfilt_add_journal_cb(obd, 0, oti->oti_handle,
+ fsfilt_add_journal_cb(obd, filter->fo_sb, 0,
+ oti->oti_handle,
filter_cancel_cookies_cb,
fcc);
else
- fsfilt_add_journal_cb(obd, 0, handle,
+ fsfilt_add_journal_cb(obd, filter->fo_sb, 0,
+ handle,
filter_cancel_cookies_cb,
fcc);
}
case 1:
filter_parent_unlock(dparent);
case 0:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
break;
default:
CERROR("invalid cleanup_phase %d\n", cleanup_phase);
static int filter_sync(struct obd_export *exp, struct obdo *oa,
struct lov_stripe_md *lsm, obd_off start, obd_off end)
{
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct filter_obd *filter;
struct dentry *dentry;
struct llog_ctxt *ctxt;
if (IS_ERR(dentry))
RETURN(PTR_ERR(dentry));
- push_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
down(&dentry->d_inode->i_sem);
rc = filemap_fdatasync(dentry->d_inode->i_mapping);
oa->o_valid = OBD_MD_FLID;
obdo_from_inode(oa, dentry->d_inode, FILTER_VALID_FLAGS);
- pop_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
f_dput(dentry);
RETURN(rc);
}
case OBD_IOC_CATLOGLIST: {
- rc = llog_catlog_list(obd, 1, data);
+ rc = llog_catalog_list(obd, 1, data);
RETURN(rc);
}
/*
struct llog_ctxt *ctxt = NULL;
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &ctxt->loc_ctxt, NULL);
rc = llog_ioctl(ctxt, cmd, data);
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &ctxt->loc_ctxt, NULL);
RETURN(rc);
*/
static struct llog_operations filter_unlink_repl_logops;
static struct llog_operations filter_size_orig_logops = {
lop_setup: llog_obd_origin_setup,
- lop_cleanup: llog_obd_origin_cleanup,
- lop_add: llog_obd_origin_add
+ lop_cleanup: llog_catalog_cleanup,
+ lop_add: llog_catalog_add,
};
static int filter_llog_init(struct obd_device *obd, struct obd_device *tgt,
- int count, struct llog_catid *logid)
+ int count, struct llog_catid *catid)
{
struct llog_ctxt *ctxt;
int rc;
filter_unlink_repl_logops.lop_connect = llog_repl_connect;
filter_unlink_repl_logops.lop_sync = llog_obd_repl_sync;
- rc = llog_setup(obd, LLOG_UNLINK_REPL_CTXT, tgt, 0, NULL,
- &filter_unlink_repl_logops);
+ rc = obd_llog_setup(obd, LLOG_UNLINK_REPL_CTXT, tgt, 0, NULL,
+ &filter_unlink_repl_logops);
if (rc)
RETURN(rc);
/* FIXME - assign unlink_cb for filter's recovery */
ctxt = llog_get_context(obd, LLOG_UNLINK_REPL_CTXT);
- ctxt->llog_proc_cb = filter_recov_log_unlink_cb;
+ ctxt->loc_proc_cb = filter_recov_log_unlink_cb;
- rc = llog_setup(obd, LLOG_SIZE_ORIG_CTXT, tgt, 0, NULL,
- &filter_size_orig_logops);
+ /* FIXME - count should be 1 to setup size log */
+ rc = obd_llog_setup(obd, LLOG_SIZE_ORIG_CTXT, tgt, 0, &catid->lci_logid,
+ &filter_size_orig_logops);
RETURN(rc);
}
int rc;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_REPL_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_UNLINK_REPL_CTXT));
if (rc)
RETURN(rc);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_ORIG_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_SIZE_ORIG_CTXT));
RETURN(rc);
}
#include <linux/lustre_fsfilt.h>
#include "filter_internal.h"
-static int filter_start_page_read(struct inode *inode, struct niobuf_local *lnb)
+static int filter_start_page_read(struct obd_device *obd, struct inode *inode,
+ struct niobuf_local *lnb)
{
- struct address_space *mapping = inode->i_mapping;
struct page *page;
unsigned long index = lnb->offset >> PAGE_SHIFT;
- int rc;
- page = grab_cache_page(mapping, index); /* locked page */
- if (page == NULL)
- return lnb->rc = -ENOMEM;
+ page = fsfilt_getpage(obd, inode, index);
+ if (IS_ERR(page)) {
+ CERROR("page index %lu, rc = %ld\n", index, PTR_ERR(page));
- LASSERT(page->mapping == mapping);
+ lnb->page = NULL;
+ lnb->rc = PTR_ERR(page);
+ return lnb->rc;
+ }
lnb->page = page;
else
lnb->rc = lnb->len;
- if (PageUptodate(page)) {
- unlock_page(page);
- return 0;
- }
-
- rc = mapping->a_ops->readpage(NULL, page);
- if (rc < 0) {
- CERROR("page index %lu, rc = %d\n", index, rc);
- lnb->page = NULL;
- page_cache_release(page);
- return lnb->rc = rc;
- }
-
return 0;
}
struct obd_trans_info *oti)
{
struct obd_device *obd = exp->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct obd_ioobj *o;
struct niobuf_remote *rnb;
struct niobuf_local *lnb = NULL;
memset(res, 0, niocount * sizeof(*res));
- push_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
for (i = 0, o = obj; i < objcount; i++, o++) {
LASSERT(o->ioo_bufcnt);
* easy to detect later. */
break;
} else {
- rc = filter_start_page_read(inode, lnb);
+ rc = filter_start_page_read(obd, inode, lnb);
}
if (rc) {
CERROR("NULL dentry in cleanup -- tell CFS\n");
case 0:
OBD_FREE(fso, objcount * sizeof(*fso));
- pop_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
}
return rc;
}
struct niobuf_local *res,
struct obd_trans_info *oti)
{
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct niobuf_remote *rnb;
struct niobuf_local *lnb;
struct fsfilt_objinfo fso;
memset(res, 0, niocount * sizeof(*res));
- push_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
dentry = filter_fid2dentry(exp->exp_obd, NULL, obj->ioo_gr,
obj->ioo_id);
if (IS_ERR(dentry))
spin_unlock(&exp->exp_obd->obd_osfs_lock);
default: ;
}
- pop_ctxt(&saved, &exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, NULL);
return rc;
}
if (rc < 0)
GOTO(cleanup, rc);
- rc = brw_kiovec(WRITE, 1, &iobuf, inode->i_dev, iobuf->blocks,
- 1 << inode->i_blkbits);
+ rc = fsfilt_send_bio(obd, inode, iobuf);
+
CDEBUG(D_INFO, "tried to write %d pages, rc = %d\n",
iobuf->nr_pages, rc);
- if (rc != (1 << inode->i_blkbits) * iobuf->nr_pages * blocks_per_page)
- CERROR("short write? expected %d, wrote %d\n",
- (1 << inode->i_blkbits) * iobuf->nr_pages *
- blocks_per_page, rc);
+
if (rc > 0)
rc = 0;
int rc)
{
struct obd_device *obd = exp->exp_obd;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct niobuf_local *lnb;
struct fsfilt_objinfo fso;
struct iattr iattr = { 0 };
iattr.ia_size = this_size;
}
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
cleanup_phase = 2;
down(&inode->i_sem);
switch (cleanup_phase) {
case 2:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
LASSERT(current->journal_info == NULL);
case 1:
free_kiovec(1, &iobuf);
struct bio *bio = NULL;
int blocks_per_page, err;
struct niobuf_local *lnb;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct fsfilt_objinfo fso;
struct iattr iattr = { 0 };
struct inode *inode = NULL;
struct obd_device *obd = exp->exp_obd;
ENTRY;
+
LASSERT(oti != NULL);
LASSERT(objcount == 1);
LASSERT(current->journal_info == NULL);
fso.fso_dentry = res->dentry;
fso.fso_bufcnt = obj->ioo_bufcnt;
- push_ctxt(&saved, &obd->obd_ctxt, NULL);
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
cleanup_phase = 2;
oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso,
}
}
- /* We expect these pages to be in offset order, but we'll
+ /* we expect these pages to be in offset order, but we'll
* be forgiving */
this_size = lnb->offset + lnb->len;
if (this_size > iattr.ia_size)
#warning This probably needs filemap_fdatasync() like filter_io_24 (bug 2366)
if (bio) {
atomic_inc(&dreq->numreqs);
- submit_bio(WRITE, bio);
+ fsfilt_send_bio(obd, inode, bio);
}
/* time to wait for I/O completion */
switch (cleanup_phase) {
case 2:
- pop_ctxt(&saved, &obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
LASSERT(current->journal_info == NULL);
case 1:
OBD_FREE(dreq, sizeof(*dreq));
void *cb_data, int error)
{
struct llog_cookie *cookie = cb_data;
- llog_cancel(llog_get_context(obd, cookie->lgc_subsys + 1),
- NULL, 1, cookie, 0);
- //NULL, 1, cookie, OBD_LLOG_FL_SENDNOW);
+ int rc;
+ rc = llog_cancel(llog_get_context(obd, cookie->lgc_subsys + 1),
+ 1, cookie, 0, NULL);
+ if (rc)
+ CERROR("error cancelling log cookies: rc = %d\n", rc);
OBD_FREE(cb_data, sizeof(struct llog_cookie));
}
else
rc = LLOG_PROC_BREAK;
CWARN("fetch generation log, send cookie\n");
- llog_cancel(ctxt, NULL, 1, &cookie, 0);
+ llog_cancel(ctxt, 1, &cookie, 0, NULL);
RETURN(rc);
}
obdo_free(oa);
if (rc == -ENOENT) {
CDEBUG(D_HA, "object already removed, send cookie\n");
- llog_cancel(ctxt, NULL, 1, &cookie, 0);
+ llog_cancel(ctxt, 1, &cookie, 0, NULL);
RETURN(0);
}
osc_unlink_orig_logops = llog_lvfs_ops;
osc_unlink_orig_logops.lop_setup = llog_obd_origin_setup;
- osc_unlink_orig_logops.lop_cleanup = llog_obd_origin_cleanup;
- osc_unlink_orig_logops.lop_add = llog_obd_origin_add;
+ osc_unlink_orig_logops.lop_cleanup = llog_catalog_cleanup;
+ osc_unlink_orig_logops.lop_add = llog_catalog_add;
osc_unlink_orig_logops.lop_connect = llog_origin_connect;
- rc = llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, count,
- &catid->lci_logid, &osc_unlink_orig_logops);
+ rc = obd_llog_setup(obd, LLOG_UNLINK_ORIG_CTXT, tgt, count,
+ &catid->lci_logid, &osc_unlink_orig_logops);
if (rc)
RETURN(rc);
- rc = llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, count, NULL,
- &osc_size_repl_logops);
+ rc = obd_llog_setup(obd, LLOG_SIZE_REPL_CTXT, tgt, count, NULL,
+ &osc_size_repl_logops);
RETURN(rc);
}
int rc;
ENTRY;
- rc = llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_UNLINK_ORIG_CTXT));
if (rc)
RETURN(rc);
- rc = llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
+ rc = obd_llog_cleanup(llog_get_context(obd, LLOG_SIZE_REPL_CTXT));
RETURN(rc);
}
# endif
#endif
-#ifndef LP_POISON
+/*#ifndef LP_POISON
# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
-#endif
+#endif*/
#if defined(__x86_64__)
# define LPU64 "%Lu"
# define LPX64 "%#Lx"
# define LPSZ "%lu"
# define LPSSZ "%ld"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#endif
#elif (BITS_PER_LONG == 32 || __WORDSIZE == 32)
# define LPU64 "%Lu"
# define LPD64 "%Ld"
# define LPX64 "%#Lx"
# define LPSZ "%u"
# define LPSSZ "%d"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a)
+#endif
#elif (BITS_PER_LONG == 64 || __WORDSIZE == 64)
# define LPU64 "%lu"
# define LPD64 "%ld"
# define LPX64 "%#lx"
# define LPSZ "%lu"
# define LPSSZ "%ld"
+#ifndef LP_POISON
+# define LI_POISON ((int)0x5a5a5a5a5a5a5a5a)
+# define LL_POISON ((long)0x5a5a5a5a5a5a5a5a)
+# define LP_POISON ((void *)(long)0x5a5a5a5a5a5a5a5a)
+#endif
#endif
#ifndef LPU64
# error "No word size defined"
#define S_PTLROUTER 0x00100000
#define S_COBD 0x00200000
#define S_IBNAL 0x00400000
+#define S_SM 0x00800000
/* If you change these values, please keep portals/utils/debug.c
* up to date! */
{"mds", "lustre/mds"},
{"mdc", "lustre/mdc"},
{"llite", "lustre/llite"},
+ {"smfs", "lustre/smfs"},
{"obdecho", "lustre/obdecho"},
{"ldlm", "lustre/ldlm"},
{"obdfilter", "lustre/obdfilter"},
{"fsfilt_ext3", "lustre/lvfs"},
{"fsfilt_extN", "lustre/lvfs"},
{"fsfilt_reiserfs", "lustre/lvfs"},
+ {"fsfilt_smfs", "lustre/lvfs"},
{"mds_ext2", "lustre/mds"},
{"mds_ext3", "lustre/mds"},
{"mds_extN", "lustre/mds"},
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*
- * Copyright (C) 2001-2003 Cluster File Systems, Inc.
+ * Copyright (C) 2001-2004 Cluster File Systems, Inc.
* Author: Andreas Dilger <adilger@clusterfs.com>
*
* This file is part of Lustre, http://www.lustre.org.
if (rc)
GOTO(err_free, rc);
- body = lustre_swab_repbuf(req, 0, sizeof(*body),
+ body = lustre_swab_repbuf(req, 0, sizeof(*body),
lustre_swab_llogd_body);
- if (body == NULL) {
+ if (body == NULL) {
CERROR ("Can't unpack llogd_body\n");
GOTO(err_free, rc =-EFAULT);
- }
+ }
handle->lgh_id = body->lgd_logid;
handle->lgh_ctxt = ctxt;
goto out;
}
+static int llog_client_prev_block(struct llog_handle *loghandle,
+ int prev_idx, void *buf, int len)
+{
+ struct obd_import *imp = loghandle->lgh_ctxt->loc_imp;
+ struct ptlrpc_request *req = NULL;
+ struct llogd_body *body;
+ void * ptr;
+ int size = sizeof(*body);
+ int repsize[2] = {sizeof (*body)};
+ int rc;
+ ENTRY;
+
+ req = ptlrpc_prep_req(imp, LLOG_ORIGIN_HANDLE_PREV_BLOCK, 1,&size,NULL);
+ if (!req)
+ GOTO(out, rc = -ENOMEM);
+
+ body = lustre_msg_buf(req->rq_reqmsg, 0, sizeof (*body));
+ body->lgd_logid = loghandle->lgh_id;
+ body->lgd_ctxt_idx = loghandle->lgh_ctxt->loc_idx - 1;
+ body->lgd_llh_flags = loghandle->lgh_hdr->llh_flags;
+ body->lgd_index = prev_idx;
+ body->lgd_len = len;
+ repsize[1] = len;
+
+ req->rq_replen = lustre_msg_size(2, repsize);
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ GOTO(out, rc);
+
+ body = lustre_swab_repbuf(req, 0, sizeof(*body),
+ lustre_swab_llogd_body);
+ if (body == NULL) {
+ CERROR ("Can't unpack llogd_body\n");
+ GOTO(out, rc =-EFAULT);
+ }
+
+ ptr = lustre_msg_buf(req->rq_repmsg, 1, len);
+ if (ptr == NULL) {
+ CERROR ("Can't unpack bitmap\n");
+ GOTO(out, rc =-EFAULT);
+ }
+
+ memcpy(buf, ptr, len);
+
+out:
+ if (req)
+ ptlrpc_req_finished(req);
+ RETURN(rc);
+}
static int llog_client_next_block(struct llog_handle *loghandle,
int *cur_idx, int next_idx,
if (rc)
GOTO(out, rc);
- body = lustre_swab_repbuf(req, 0, sizeof(*body),
+ body = lustre_swab_repbuf(req, 0, sizeof(*body),
lustre_swab_llogd_body);
- if (body == NULL) {
+ if (body == NULL) {
CERROR ("Can't unpack llogd_body\n");
GOTO(out, rc =-EFAULT);
- }
+ }
ptr = lustre_msg_buf(req->rq_repmsg, 1, len);
- if (ptr == NULL) {
+ if (ptr == NULL) {
CERROR ("Can't unpack bitmap\n");
GOTO(out, rc =-EFAULT);
- }
+ }
*cur_idx = body->lgd_saved_index;
*cur_offset = body->lgd_cur_offset;
if (rc)
GOTO(out, rc);
- hdr = lustre_swab_repbuf(req, 0, sizeof(*hdr), lustre_swab_llog_hdr);
- if (hdr == NULL) {
+ hdr = lustre_swab_repbuf(req, 0, sizeof(*hdr), lustre_swab_llog_hdr);
+ if (hdr == NULL) {
CERROR ("Can't unpack llog_hdr\n");
GOTO(out, rc =-EFAULT);
}
struct llog_operations llog_client_ops = {
+ lop_prev_block: llog_client_prev_block,
lop_next_block: llog_client_next_block,
lop_read_header: llog_client_read_header,
lop_create: llog_client_create,
lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
lgr->lgr_gen = ctxt->loc_gen;
- rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1);
+ rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1, NULL);
OBD_FREE(lgr, sizeof(*lgr));
if (rc != 1)
RETURN(rc);
{
struct obd_export *exp = req->rq_export;
struct obd_device *obd = exp->exp_obd;
- struct obd_device *disk_obd;
struct llog_handle *loghandle;
struct llogd_body *body;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_logid *logid = NULL;
struct llog_ctxt *ctxt;
char * name = NULL;
ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
LASSERT(ctxt != NULL);
- disk_obd = ctxt->loc_exp->exp_obd;
- push_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
rc = llog_create(ctxt, &loghandle, logid, name);
if (rc)
if (!rc)
rc = rc2;
out_pop:
- pop_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+out:
+ RETURN(rc);
+}
+
+int llog_origin_handle_prev_block(struct ptlrpc_request *req)
+{
+ struct obd_export *exp = req->rq_export;
+ struct obd_device *obd = exp->exp_obd;
+ struct llog_handle *loghandle;
+ struct llogd_body *body;
+ struct lvfs_run_ctxt saved;
+ struct llog_ctxt *ctxt;
+ __u32 flags;
+ __u8 *buf;
+ void * ptr;
+ int rc, rc2, size[] = {sizeof (*body), LLOG_CHUNK_SIZE};
+ ENTRY;
+
+ body = lustre_swab_reqbuf(req, 0, sizeof(*body),
+ lustre_swab_llogd_body);
+ if (body == NULL) {
+ CERROR ("Can't unpack llogd_body\n");
+ GOTO(out, rc =-EFAULT);
+ }
+
+ OBD_ALLOC(buf, LLOG_CHUNK_SIZE);
+ if (!buf)
+ GOTO(out, rc = -ENOMEM);
+
+ ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
+ LASSERT(ctxt != NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+
+ rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
+ if (rc)
+ GOTO(out_pop, rc);
+
+ flags = body->lgd_llh_flags;
+ rc = llog_init_handle(loghandle, flags, NULL);
+ if (rc)
+ GOTO(out_close, rc);
+
+ memset(buf, 0, LLOG_CHUNK_SIZE);
+ rc = llog_prev_block(loghandle, body->lgd_index, buf, LLOG_CHUNK_SIZE);
+ if (rc)
+ GOTO(out_close, rc);
+
+
+ rc = lustre_pack_reply(req, 2, size, NULL);
+ if (rc)
+ GOTO(out_close, rc = -ENOMEM);
+
+ ptr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (body));
+ memcpy(ptr, body, sizeof(*body));
+
+ ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_CHUNK_SIZE);
+ memcpy(ptr, buf, LLOG_CHUNK_SIZE);
+
+out_close:
+ rc2 = llog_close(loghandle);
+ if (!rc)
+ rc = rc2;
+
+out_pop:
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
+ OBD_FREE(buf, LLOG_CHUNK_SIZE);
out:
RETURN(rc);
}
{
struct obd_export *exp = req->rq_export;
struct obd_device *obd = exp->exp_obd;
- struct obd_device *disk_obd;
struct llog_handle *loghandle;
struct llogd_body *body;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_ctxt *ctxt;
__u32 flags;
__u8 *buf;
ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
LASSERT(ctxt != NULL);
- disk_obd = ctxt->loc_exp->exp_obd;
- push_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
if (rc)
rc = rc2;
out_pop:
- pop_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
OBD_FREE(buf, LLOG_CHUNK_SIZE);
out:
RETURN(rc);
{
struct obd_export *exp = req->rq_export;
struct obd_device *obd = exp->exp_obd;
- struct obd_device *disk_obd;
struct llog_handle *loghandle;
struct llogd_body *body;
struct llog_log_hdr *hdr;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_ctxt *ctxt;
__u32 flags;
int size[] = {sizeof (*hdr)};
ctxt = llog_get_context(obd, body->lgd_ctxt_idx);
LASSERT(ctxt != NULL);
- disk_obd = ctxt->loc_exp->exp_obd;
- push_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
rc = llog_create(ctxt, &loghandle, &body->lgd_logid, NULL);
if (rc)
rc = rc2;
out_pop:
- pop_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
out:
RETURN(rc);
int llog_origin_handle_cancel(struct ptlrpc_request *req)
{
struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_device *disk_obd;
struct llog_cookie *logcookies;
struct llog_ctxt *ctxt;
int num_cookies, rc = 0, err, i;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_handle *cathandle;
struct inode *inode;
void *handle;
RETURN(-ENOENT);
}
- disk_obd = ctxt->loc_exp->exp_obd;
- push_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
for (i = 0; i < num_cookies; i++, logcookies++) {
cathandle = ctxt->loc_handle;
LASSERT(cathandle != NULL);
inode = cathandle->lgh_file->f_dentry->d_inode;
- handle = fsfilt_start_log(disk_obd, inode,
- FSFILT_OP_CANCEL_UNLINK, NULL, 1);
+ handle = llog_fsfilt_start(ctxt, inode,
+ FSFILT_OP_CANCEL_UNLINK, NULL);
if (IS_ERR(handle)) {
CERROR("fsfilt_start failed: %ld\n", PTR_ERR(handle));
GOTO(pop_ctxt, rc = PTR_ERR(handle));
rc = llog_cat_cancel_records(cathandle, 1, logcookies);
- err = fsfilt_commit(disk_obd, inode, handle, 0);
+ err = llog_fsfilt_commit(ctxt, inode, handle, 0);
if (err) {
CERROR("error committing transaction: %d\n", err);
if (!rc)
}
}
pop_ctxt:
- pop_ctxt(&saved, &disk_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
if (rc)
CERROR("cancel %d llog-records failed: %d\n", num_cookies, rc);
else
{
struct mds_obd *mds = &obd->u.mds;
struct llog_ctxt *ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
struct llog_handle *handle = NULL;
char name[4][64];
int rc, i, l, remains = buf_len;
if (ctxt == NULL || mds == NULL)
RETURN(-EOPNOTSUPP);
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
sprintf(name[0], "%s", mds->mds_profile);
sprintf(name[1], "%s-clean", mds->mds_profile);
break;
}
out_pop:
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
RETURN(rc);
}
{
struct mds_obd *mds = &obd->u.mds;
struct llog_handle *handle;
- struct obd_run_ctxt saved;
+ struct lvfs_run_ctxt saved;
int size, i, count;
struct llog_catid *idarray;
struct llog_logid *id;
if (!idarray)
RETURN(-ENOMEM);
- rc = llog_get_cat_list(obd, obd, name, count, idarray);
+ rc = llog_get_cat_list(&obd->obd_lvfs_ctxt, obd->obd_fsops,
+ name, count, idarray);
if (rc)
GOTO(out_free, rc);
- push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ push_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
data.ctxt = ctxt;
data.out = buf;
break;
}
out_pop:
- pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_ctxt, NULL);
+ pop_ctxt(&saved, ctxt->loc_lvfs_ctxt, NULL);
out_free:
OBD_FREE(idarray, size);
RETURN(rc);
LBUG();
return 0;
}
+int llog_origin_handle_prev_block(struct ptlrpc_request *req)
+{
+ LBUG();
+ return 0;
+}
int llog_origin_handle_next_block(struct ptlrpc_request *req)
{
LBUG();
(long long)REINT_RENAME);
LASSERTF(REINT_OPEN == 6, " found %lld\n",
(long long)REINT_OPEN);
- LASSERTF(REINT_MAX == 6, " found %lld\n",
+ LASSERTF(REINT_MAX == 8, " found %lld\n",
(long long)REINT_MAX);
LASSERTF(DISP_IT_EXECD == 1, " found %lld\n",
(long long)DISP_IT_EXECD);
/* llogd.c */
EXPORT_SYMBOL(llog_origin_handle_create);
+EXPORT_SYMBOL(llog_origin_handle_prev_block);
EXPORT_SYMBOL(llog_origin_handle_next_block);
EXPORT_SYMBOL(llog_origin_handle_read_header);
EXPORT_SYMBOL(llog_origin_handle_close);
* log record for the deletion. The commit callback calls this
* function
*/
-int llog_obd_repl_cancel(struct llog_ctxt *ctxt,
- struct lov_stripe_md *lsm, int count,
- struct llog_cookie *cookies, int flags)
+int llog_obd_repl_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data)
{
struct llog_canceld_ctxt *llcd;
int rc = 0;
}
up(&ctxt->loc_sem);
} else {
- rc = llog_cancel(ctxt, NULL, 0, NULL, OBD_LLOG_FL_SENDNOW);
+ rc = llog_cancel(ctxt, 0, NULL, OBD_LLOG_FL_SENDNOW, NULL);
}
RETURN(rc);
ctxt->loc_llcd = llcd;
up(&ctxt->loc_sem);
- rc = llog_recovery_generic(ctxt, ctxt->llog_proc_cb, logid);
+ rc = llog_recovery_generic(ctxt, ctxt->loc_proc_cb, logid);
if (rc != 0)
CERROR("error recovery process: %d\n", rc);
#else /* !__KERNEL__ */
-int llog_obd_repl_cancel(struct llog_ctxt *ctxt,
- struct lov_stripe_md *lsm, int count,
- struct llog_cookie *cookies, int flags)
+int llog_obd_repl_cancel(struct llog_ctxt *ctxt, int count,
+ struct llog_cookie *cookies, int flags, void *data)
{
return 0;
}
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
+smfs-objs := super.o options.o inode.o cache.o cache_space.o dir.o ioctl.o
+smfs-objs += sysctl.o file.o symlink.o sm_fs.o kml.o journal.o smfs_llog.o
@INCLUDE_RULES@
endif
MOSTLYCLEANFILES = *.o *.ko *.mod.c
-DIST_SOURCES = $(smfs-objs:%.o=%.c) kml_idl.h smfs_internal.h smfs_support.h
+DIST_SOURCES = $(smfs-objs:%.o=%.c) smfs_internal.h
-/*
- * snapfs/cache.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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_SM
#include <linux/string.h>
#include <linux/lustre_idl.h>
#include <portals/list.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_smfs.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;
+#include "smfs_internal.h"
+int smfs_init_sm_ops(struct smfs_super_info *smb)
+{
+ struct sm_operations *sm_ops; /*cache ops for set cache inode ops*/
+ OBD_ALLOC(sm_ops, sizeof(struct sm_operations));
+ if (!sm_ops)
+ RETURN(-ENOMEM);
-inline struct super_operations *cache_sops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sb_ops;
+ smb->sm_ops = sm_ops;
+ RETURN(0);
}
-inline struct inode_operations *cache_diops(struct sm_ops *smfs_ops)
+void smfs_cleanup_sm_ops(struct smfs_super_info *smb)
{
- return &smfs_ops->sm_dir_iops;
+ if (smb->sm_ops)
+ OBD_FREE(smb->sm_ops, sizeof(struct sm_operations));
}
-inline struct inode_operations *cache_fiops(struct sm_ops *smfs_ops)
+static void setup_iops(struct inode *cache_inode,
+ struct inode_operations *iops,
+ struct inode_operations *cache_iops)
{
- return &smfs_ops->sm_file_iops;
-}
-inline struct inode_operations *cache_siops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sym_iops;
+ if (cache_inode->i_op && cache_iops && iops) {
+ if (cache_inode->i_op->create)
+ iops->create = cache_iops->create;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (cache_inode->i_op->create_it)
+ iops->create_it = cache_iops->create_it;
+#endif
+ if (cache_inode->i_op->lookup)
+ iops->lookup = cache_iops->lookup;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ 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;
+#endif
+ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ 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;
+#endif
+ 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;
+ }
}
-inline struct file_operations *cache_dfops(struct sm_ops *smfs_ops)
+static void setup_fops(struct inode *cache_inode,
+ struct file_operations *fops,
+ struct file_operations *cache_fops)
{
- return &smfs_ops->sm_dir_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;
+ }
}
-inline struct file_operations *cache_ffops(struct sm_ops *smfs_ops)
+static void setup_sm_file_ops(struct inode *cache_inode,
+ struct inode *inode,
+ struct inode_operations *cache_iops,
+ struct file_operations *cache_fops)
{
- return &smfs_ops->sm_file_fops;
-}
+ struct smfs_super_info *smb;
+ struct inode_operations *iops;
+ struct file_operations *fops;
-inline struct file_operations *cache_sfops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_sym_fops;
-}
+ smb = S2SMI(inode->i_sb);
-inline struct dentry_operations *cache_dops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_dentry_ops;
-}
+ if (smb->ops_check & FILE_OPS_CHECK)
+ return;
+ smb->ops_check |= FILE_OPS_CHECK;
-inline struct journal_operations *journal_ops(struct sm_ops *smfs_ops)
-{
- return &smfs_ops->sm_journal_ops;
-}
+ iops = cache_fiops(smb);
+ fops = cache_ffops(smb);
-void init_smfs_cache()
-{
- memset(&smfs_operations, 0, sizeof(struct sm_ops));
-}
-void cleanup_smfs_cache()
-{
- return;
-}
+ memset(iops , 0 , sizeof (struct inode_operations));
+ memset(fops , 0 , sizeof (struct file_operations));
-static void setup_iops(struct inode *cache_inode,
- struct inode_operations *iops,
- struct inode_operations *cache_iops)
-{
+ setup_iops(cache_inode, iops, cache_iops);
+ setup_fops(cache_inode, fops, cache_fops);
- 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;
- }
+ return;
}
-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)
+
+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;
+ struct smfs_super_info *smb;
+ struct inode_operations *iops;
+ struct file_operations *fops;
+
+ smb = S2SMI(inode->i_sb);
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & FILE_OPS_CHECK)
- return;
- smb->ops_check |= FILE_OPS_CHECK;
+ if (smb->ops_check & DIR_OPS_CHECK)
+ return;
+ smb->ops_check |= DIR_OPS_CHECK;
- iops = cache_fiops(&smfs_operations);
- fops = cache_ffops(&smfs_operations);
+ iops = cache_diops(smb);
+ fops = cache_dfops(smb);
- memset(iops , 0 , sizeof (struct inode_operations));
- memset(fops , 0 , sizeof (struct file_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);
+ setup_iops(cache_inode, iops, cache_dir_iops);
+ setup_fops(cache_inode, fops, cache_dir_fops);
- return;
+ 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)
+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;
+ struct smfs_super_info *smb;
+ struct inode_operations *iops;
+ struct file_operations *fops;
+
+ smb = S2SMI(inode->i_sb);
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & DIR_OPS_CHECK)
- return;
- smb->ops_check |= DIR_OPS_CHECK;
+ if (smb->ops_check & SYMLINK_OPS_CHECK)
+ return;
+ smb->ops_check |= SYMLINK_OPS_CHECK;
- iops = cache_diops(&smfs_operations);
- fops = cache_dfops(&smfs_operations);
+ iops = cache_siops(smb);
+ fops = cache_sfops(smb);
- memset(iops, 0, sizeof (struct inode_operations));
- memset(fops, 0, sizeof (struct file_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);
+ setup_iops(cache_inode, iops, cache_sym_iops);
+ setup_fops(cache_inode, fops, cache_sym_fops);
- return;
+ 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)
+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 inode_operations *iops;
- struct file_operations *fops;
+ struct smfs_super_info *smb;
+ struct super_operations *sops;
- smb = S2SMI(inode->i_sb);
-
- if (smb->ops_check & SYMLINK_OPS_CHECK)
- return;
- smb->ops_check |= SYMLINK_OPS_CHECK;
+ ENTRY;
- iops = cache_siops(&smfs_operations);
- fops = cache_sfops(&smfs_operations);
+ smb = S2SMI(sb);
- memset(iops , 0 , sizeof (struct inode_operations));
- memset(fops , 0 , sizeof (struct file_operations));
+ if (smb->ops_check & SB_OPS_CHECK)
+ return;
+ smb->ops_check |= SB_OPS_CHECK;
+ sops = cache_sops(smb);
+ memset(sops, 0, sizeof (struct super_operations));
- setup_iops(cache_inode, iops, cache_sym_iops);
- setup_fops(cache_inode, fops, cache_sym_fops);
+ if (cache_sb->s_op) {
+ if (cache_sb->s_op->read_inode)
+ sops->read_inode = smfs_sops->read_inode;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (cache_sb->s_op->read_inode2)
+ sops->read_inode2 = smfs_sops->read_inode2;
+#endif
+ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ 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;
+#endif
+ if (cache_sb->s_op->show_options)
+ sops->show_options = smfs_sops->show_options;
+
+ /* FIXME-WANGDI: we need this method to clear the cache
+ * inode. */
+ sops->clear_inode = smfs_sops->clear_inode;
+ }
- return;
+ 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 */
+ struct smfs_super_info *smb = S2SMI(inode->i_sb);
+ /* XXX now set the correct sm_{file,dir,sym}_iops */
if (S_ISDIR(inode->i_mode)) {
- setup_sm_dir_ops(cache_inode, inode,
+ 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);
+ inode->i_op = cache_diops(smb);
+ inode->i_fop = cache_dfops(smb);
} else if (S_ISREG(inode->i_mode)) {
- setup_sm_file_ops(cache_inode, inode,
+ 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)) {
+ inode->i_fop = cache_ffops(smb);
+ inode->i_op = cache_fiops(smb);
+
+ } 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);
+ &smfs_sym_iops,
+ &smfs_sym_fops);
+ inode->i_op = cache_siops(smb);
+ inode->i_fop = cache_sfops(smb);
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)
+void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb)
{
- 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);
- }
-}
+ struct smfs_super_info *smb;
+
+ smb = S2SMI(sb);
+ setup_sm_sb_ops(cache_sb, sb, &smfs_super_ops);
+
+ sb->s_op = cache_sops(smb);
+ return;
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * lustre/smfs/cache_space.c
+ * A library of functions to manage cache space based on ARC
+ * (modified LRU) replacement algorithm.
+ *
+ * Copyright (c) 2002, 2003 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_SM
+
+#include <linux/lustre_log.h>
+#include <linux/lustre_smfs.h>
+
+#include "smfs_internal.h"
+
+struct cache_purge_param {
+ int nfract; /* Percentage of cache dirty to activate cpurge */
+ int ndirty; /* Maximum number of objects to write out per
+ wake-cycle */
+ int interval; /* jiffies delay between cache purge */
+ int nfract_sync;/* Percentage of cache dirty to activate
+ cpurge synchronously */
+ int nfract_stop_cpurge; /* Percentage of cache dirty to stop cpurge */
+} cf_prm = {30, 512, 600 * HZ, 60, 20};
+
+static struct cache_purge_queue smfs_cpq;
+static struct cache_purge_queue *cpq = &smfs_cpq;
+
+int cache_space_hook_init(struct super_block *sb)
+{
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+
+ SMFS_SET_CACHE_HOOK(smfs_info);
+ return 0;
+}
+int cache_space_hook_exit(struct super_block *sb)
+{
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+
+ SMFS_CLEAN_CACHE_HOOK(smfs_info);
+ return 0;
+}
+int smfs_cache_hook(struct inode *inode)
+{
+ struct smfs_super_info *smfs_info = I2CSB(inode);
+
+ if (SMFS_CACHE_HOOK(smfs_info) && SMFS_INIT_REC(smfs_info)
+ && SMFS_INODE_CACHE_HOOK(inode))
+ return 1;
+ else
+ return 0;
+}
+
+static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (S_ISDIR(inode->i_mode)) {
+ if (inode->i_nlink != 2)
+ return 0;
+ if (!strncmp(dentry->d_name.name, "lost+found", dentry->d_name.len))
+ return 0;
+ LASSERT(active_entry != NULL);
+ get_active_entry(inode, active_entry);
+ return(*active_entry > 0 ? 0 : 1);
+ } else {
+ if (inode->i_nlink != 1)
+ return 0;
+ if (!strncmp(dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) ||
+ !strncmp(dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
+ return 0;
+ return 1;
+ }
+}
+static int cache_pre_leaf_node(struct dentry *dentry, __u64 *active_entry, int op)
+{
+ if (((op == 0 && dentry->d_inode->i_nlink == 0) ||
+ (op == 1 && dentry->d_inode->i_nlink == 2)) &&
+ strncmp(dentry->d_name.name, KML_LOG_NAME, dentry->d_name.len) &&
+ strncmp(dentry->d_name.name, CACHE_LRU_LOG, dentry->d_name.len))
+ return 1;
+ else if ((op == 2 && dentry->d_inode->i_nlink == 0) ||
+ (op == 3 && dentry->d_inode->i_nlink == 3)) {
+ LASSERT(active_entry != NULL);
+ get_active_entry(dentry->d_inode, active_entry);
+ return(*active_entry > 0 ? 0 : 1);
+ }
+ return 0;
+}
+
+static int set_lru_logcookie(struct inode *inode, void *handle,
+ struct llog_cookie *logcookie)
+{
+ struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
+ int rc;
+ rc = fsops->fs_set_xattr(inode, handle, XATTR_SMFS_CACHE_LOGCOOKIE,
+ logcookie, sizeof(*logcookie));
+ RETURN(rc);
+}
+static int get_lru_logcookie(struct inode *inode, struct llog_cookie *logcookie)
+{
+ struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
+ int rc;
+ rc = fsops->fs_get_xattr(inode, XATTR_SMFS_CACHE_LOGCOOKIE,
+ logcookie, sizeof(*logcookie));
+ RETURN(rc);
+}
+
+static int try2purge_from_cache(struct ll_fid cfid, struct ll_fid pfid)
+{
+ struct inode *inode, *parent;
+ struct super_block *sb = cpq->cpq_sb;
+ //struct llog_cookie logcookie;
+ __u32 hoard_priority = 0;
+ int rc = 0;
+ ENTRY;
+
+ inode = iget(sb, cfid.id);
+ if (IS_ERR(inode)) {
+ CERROR("not existent inode: "LPX64"/%u\n",
+ cfid.id, cfid.generation);
+ RETURN(-ENOENT);
+ }
+ parent = iget(sb, pfid.id);
+ if (IS_ERR(parent)) {
+ CERROR("not existent inode: "LPX64"/%u\n",
+ pfid.id, pfid.generation);
+ iput(inode);
+ RETURN(-ENOENT);
+ }
+
+ CWARN("inode/parent %lu:%lu on the lru list\n",
+ inode->i_ino, parent->i_ino);
+
+ rc = get_hoard_priority(inode, &hoard_priority);
+ if (hoard_priority) {
+ CWARN("inode %lu set hoard\n", inode->i_ino);
+ GOTO(out, rc);
+ }
+ if (atomic_read(&inode->i_count) > 1 || (inode->i_state & I_DIRTY)) {
+ CWARN("inode %lu is busy\n", inode->i_ino);
+ GOTO(out, rc = 0);
+ }
+
+out:
+ iput(inode);
+ iput(parent);
+ RETURN(rc);
+}
+
+static int cache_lru_get_rec_cb(struct llog_handle *llh,
+ struct llog_rec_hdr *rec, void *data)
+{
+ struct llog_lru_rec *llr;
+ int count = *(int *)data, rc = 0;
+ ENTRY;
+
+ if (!(le32_to_cpu(llh->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
+ CERROR("log is not plain\n");
+ RETURN(-EINVAL);
+ }
+ if (rec->lrh_type != CACHE_LRU_REC) {
+ CERROR("log record type error\n");
+ RETURN(-EINVAL);
+ }
+
+ llr = (struct llog_lru_rec *)rec;
+
+ if (try2purge_from_cache(llr->llr_cfid, llr->llr_pfid)==1){
+ CDEBUG(D_INODE, "purge ino/gen "LPX64"/%u from cache\n",
+ llr->llr_cfid.id, llr->llr_cfid.generation);
+ count --;
+ if (count == 0)
+ rc = LLOG_PROC_BREAK;
+ *(int *)data = count;
+ }
+
+ RETURN(rc);
+}
+
+static int cpurge_stop(void)
+{
+ struct fsfilt_operations *fsops = S2SMI(cpq->cpq_sb)->sm_fsfilt;
+ struct obd_statfs osfs;
+ int rc, free;
+
+ rc = fsops->fs_statfs(cpq->cpq_sb, &osfs);
+ LASSERT(rc == 0);
+
+ free = osfs.os_bfree * 100;
+ if (free < cf_prm.nfract_stop_cpurge * osfs.os_blocks)
+ return 1;
+ return 0;
+}
+
+static int cache_balance_state(void)
+{
+ struct fsfilt_operations *fsops = S2SMI(cpq->cpq_sb)->sm_fsfilt;
+ struct obd_statfs osfs;
+ int rc, free;
+
+ rc = fsops->fs_statfs(cpq->cpq_sb, &osfs);
+ LASSERT(rc == 0);
+
+ free = (osfs.os_blocks - osfs.os_bfree) * 100;
+ if (free > cf_prm.nfract * osfs.os_blocks) {
+ if (free < cf_prm.nfract_sync)
+ return 1;
+ return 0;
+ }
+ return -1;
+}
+
+void wakeup_cpurge(void)
+{
+ wake_up(&cpq->cpq_waitq);
+}
+
+/* walk the lru llog to purge count number of objects */
+static int purge_some_cache(int *count)
+{
+ int rc;
+ ENTRY;
+
+ rc = llog_cat_process(cpq->cpq_loghandle,
+ (llog_cb_t)cache_lru_get_rec_cb,
+ count);
+ if (!rc)
+ CDEBUG(D_INODE, "no enough objects available\n");
+
+ RETURN(rc);
+}
+
+#define CFLUSH_NR 512
+static void check_cache_space(void)
+{
+ int state = cache_balance_state();
+ ENTRY;
+
+ if (state < 0)
+ return;
+
+ wakeup_cpurge();
+
+ if (state > 0) {
+ int count = CFLUSH_NR;
+ purge_some_cache(&count);
+ }
+}
+
+void cache_space_pre(struct inode *inode, int op)
+{
+ ENTRY;
+
+ /* FIXME have not used op */
+ check_cache_space();
+}
+
+static int cache_space_hook_lru(struct inode *inode, struct inode *parent,
+ void *handle, int op, int flags)
+{
+ struct fsfilt_operations *fsops = S2SMI(cpq->cpq_sb)->sm_fsfilt;
+ struct llog_ctxt *ctxt = cpq->cpq_loghandle->lgh_ctxt;
+ struct llog_lru_rec *llr = NULL;
+ struct llog_cookie *logcookie = NULL;
+ int cookie_size = sizeof(struct llog_cookie);
+ int rc = 0, err;
+ ENTRY;
+
+ LASSERT(ctxt != NULL);
+
+ if (op & ~(CACHE_SPACE_DELETE | CACHE_SPACE_INSERT |CACHE_SPACE_COMMIT))
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(logcookie, cookie_size);
+ if (!logcookie)
+ GOTO(out, rc = -ENOMEM);
+
+ if (op & CACHE_SPACE_DELETE) {
+ rc = get_lru_logcookie(inode, logcookie);
+ if (rc < 0)
+ GOTO(out, rc);
+
+ if (logcookie->lgc_lgl.lgl_oid == 0) {
+ CWARN("inode %lu/%u is not in lru list\n",
+ inode->i_ino, inode->i_generation);
+ GOTO(insert, rc = -ENOENT);
+ }
+ if (flags && llog_cat_half_bottom(logcookie, ctxt->loc_handle))
+ GOTO(out, rc = 0);
+
+ rc = llog_cancel(ctxt, 1, logcookie, 0, NULL);
+ if (!rc) {
+ memset(logcookie, 0, cookie_size);
+ rc = set_lru_logcookie(inode, handle, logcookie);
+ if (rc)
+ GOTO(out, rc);
+ } else {
+ CERROR("failed at llog_cancel: %d\n", rc);
+ GOTO(out, rc);
+ }
+ }
+
+insert:
+ if (op & CACHE_SPACE_INSERT) {
+ LASSERT(parent != NULL);
+ OBD_ALLOC(llr, sizeof(*llr));
+ if (llr == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ llr->llr_hdr.lrh_len = llr->llr_tail.lrt_len = sizeof(*llr);
+ llr->llr_hdr.lrh_type = CACHE_LRU_REC;
+ llr->llr_cfid.id = inode->i_ino;
+ llr->llr_cfid.generation = inode->i_generation;
+ llr->llr_cfid.f_type = inode->i_mode & S_IFMT;
+ llr->llr_pfid.id = parent->i_ino;
+ llr->llr_pfid.generation = parent->i_generation;
+ llr->llr_pfid.f_type = parent->i_mode & S_IFMT;
+
+ rc = llog_add(ctxt, &llr->llr_hdr, NULL, logcookie, 1, NULL);
+ if (rc != 1) {
+ CERROR("failed at llog_add: %d\n", rc);
+ GOTO(out, rc);
+ }
+ rc = set_lru_logcookie(inode, handle, logcookie);
+ }
+
+ if (op & CACHE_SPACE_COMMIT) {
+ if (handle) {
+ err = fsops->fs_commit(inode, handle, 0);
+ if (err) {
+ CERROR("error committing transaction: %d\n", err);
+ if (!rc)
+ rc = err;
+ }
+ }
+ }
+out:
+ if (logcookie)
+ OBD_FREE(logcookie, cookie_size);
+ if (llr)
+ OBD_FREE(llr, sizeof(*llr));
+ RETURN(rc);
+}
+
+static int cache_purge_thread(void *args)
+{
+ unsigned long flags;
+ struct l_wait_info lwi = LWI_TIMEOUT(cf_prm.interval * HZ, NULL, NULL);
+ ENTRY;
+
+ lock_kernel();
+ kportal_daemonize("wb_cache_purge");
+
+ SIGNAL_MASK_LOCK(current, flags);
+ sigfillset(¤t->blocked);
+ RECALC_SIGPENDING;
+ SIGNAL_MASK_UNLOCK(current, flags);
+
+ unlock_kernel();
+ complete(&cpq->cpq_comp);
+
+ while (1) {
+ int ndirty = cf_prm.ndirty;
+
+ purge_some_cache(&ndirty);
+ if (ndirty > 0 || cpurge_stop())
+ l_wait_event(cpq->cpq_waitq,
+ cpq->cpq_flags & SVC_STOPPING,
+ &lwi);
+ if (cpq->cpq_flags & SVC_STOPPING) {
+ cpq->cpq_flags &= ~SVC_STOPPING;
+ EXIT;
+ break;
+ }
+ }
+ cpq->cpq_flags = SVC_STOPPED;
+ complete(&cpq->cpq_comp);
+ return 0;
+}
+
+int cache_space_hook_setup(struct super_block *sb)
+{
+ struct llog_ctxt *ctxt;
+ int rc;
+ ENTRY;
+
+ /* first to initialize the cache lru catalog on local fs */
+ rc = llog_catalog_setup(&ctxt, CACHE_LRU_LOG,
+ S2SMI(sb)->smsi_ctxt,
+ S2SMI(sb)->sm_fsfilt,
+ S2SMI(sb)->smsi_logs_dir,
+ S2SMI(sb)->smsi_objects_dir);
+ if (rc) {
+ CERROR("failed to initialize cache lru list catalog %d\n", rc);
+ RETURN(rc);
+ }
+ cpq->cpq_sb = sb;
+ cpq->cpq_loghandle = ctxt->loc_handle;
+
+ /* start cache purge daemon, only one daemon now */
+ init_waitqueue_head(&cpq->cpq_waitq);
+ init_completion(&cpq->cpq_comp);
+ cpq->cpq_flags = 0;
+
+ rc = kernel_thread(cache_purge_thread, NULL, CLONE_VM | CLONE_FILES);
+ if (rc < 0) {
+ CERROR("cannot start thread: %d\n", rc);
+ GOTO(err_out, rc);
+ }
+ wait_for_completion(&cpq->cpq_comp);
+
+ RETURN(0);
+err_out:
+ llog_catalog_cleanup(ctxt);
+ RETURN(rc);
+}
+
+int cache_space_hook_cleanup(void)
+{
+ int rc;
+ ENTRY;
+
+ init_completion(&cpq->cpq_comp);
+ cpq->cpq_flags = SVC_STOPPING;
+ wake_up(&cpq->cpq_waitq);
+ wait_for_completion(&cpq->cpq_comp);
+
+ rc = llog_catalog_cleanup(cpq->cpq_loghandle->lgh_ctxt);
+ if (rc)
+ CERROR("failed to clean up cache lru list catalog %d\n", rc);
+
+ RETURN(rc);
+}
+
+static int cache_space_hook_create(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry = 0;
+ int rc;
+
+ LASSERT(cache_leaf_node(dentry, NULL));
+ rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
+ CACHE_SPACE_INSERT, 0);
+ if (rc)
+ RETURN(rc);
+ if (cache_leaf_node(dentry->d_parent, &active_entry)) {
+ rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+ if (rc)
+ RETURN(rc);
+ }
+ if (!active_entry)
+ rc = get_active_entry(dir, &active_entry);
+ active_entry ++;
+ if (!rc)
+ rc = set_active_entry(dir, &active_entry, handle);
+ RETURN(rc);
+}
+static int cache_space_hook_lookup(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry;
+ int rc = 0;
+
+ if (cache_leaf_node(dentry, &active_entry))
+ rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
+ CACHE_SPACE_DELETE | CACHE_SPACE_INSERT,1);
+ RETURN(rc);
+}
+static int cache_space_hook_link(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry = 0;
+ int rc = 0;
+
+ if (cache_pre_leaf_node(dentry, NULL, 1)) {
+ rc = cache_space_hook_lru(dentry->d_inode, NULL,
+ handle, CACHE_SPACE_DELETE, 0);
+ if (rc)
+ RETURN(rc);
+ }
+
+ if (cache_leaf_node(dentry->d_parent, &active_entry)) {
+ rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+ if (rc)
+ RETURN(rc);
+ }
+
+ if (!active_entry)
+ rc = get_active_entry(dir, &active_entry);
+ active_entry ++;
+ if (!rc)
+ rc = set_active_entry(dir, &active_entry, handle);
+ RETURN(rc);
+}
+static int cache_space_hook_unlink(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry;
+ int rc = 0;
+
+ if (cache_pre_leaf_node(dentry, NULL, 0))
+ rc = cache_space_hook_lru(dentry->d_inode, NULL,
+ handle, CACHE_SPACE_DELETE, 0);
+ else if (cache_leaf_node(dentry, NULL))
+ rc = cache_space_hook_lru(dentry->d_inode, dir,
+ handle, CACHE_SPACE_INSERT,0);
+ if (rc)
+ RETURN(rc);
+
+ rc = get_active_entry(dir, &active_entry);
+ active_entry --;
+ if (!rc)
+ rc = set_active_entry(dir, &active_entry, handle);
+ if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
+ rc = cache_space_hook_lru(dir,
+ dentry->d_parent->d_parent->d_inode,
+ handle, CACHE_SPACE_INSERT, 0);
+ RETURN(rc);
+}
+static int cache_space_hook_mkdir(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry;
+ int rc;
+
+ LASSERT(cache_leaf_node(dentry, &active_entry));
+ rc = cache_space_hook_lru(dentry->d_inode, dir, handle,
+ CACHE_SPACE_INSERT,0);
+
+ if (!rc && cache_pre_leaf_node(dentry->d_parent, &active_entry, 3))
+ rc = cache_space_hook_lru(dir,NULL,handle,CACHE_SPACE_DELETE,0);
+ RETURN(rc);
+}
+static int cache_space_hook_rmdir(void *handle, struct inode *dir,
+ struct dentry *dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry;
+ int rc;
+
+ LASSERT(cache_pre_leaf_node(dentry, &active_entry, 2));
+ rc = cache_space_hook_lru(dentry->d_inode, NULL, handle,
+ CACHE_SPACE_DELETE, 0);
+
+ if (!rc && cache_leaf_node(dentry->d_parent, &active_entry))
+ rc = cache_space_hook_lru(dir,
+ dentry->d_parent->d_parent->d_inode,
+ handle, CACHE_SPACE_INSERT, 0);
+ RETURN(rc);
+}
+static int cache_space_hook_rename(void *handle, struct inode *old_dir,
+ struct dentry *old_dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ __u64 active_entry;
+ int rc = 0;
+
+ if (new_dentry->d_inode) {
+ if (cache_pre_leaf_node(new_dentry, NULL, 0))
+ rc = cache_space_hook_lru(new_dentry->d_inode, NULL,
+ handle, CACHE_SPACE_DELETE,0);
+ else if (cache_leaf_node(new_dentry, NULL))
+ rc = cache_space_hook_lru(new_dentry->d_inode,
+ new_dir, handle,
+ CACHE_SPACE_INSERT,0);
+ }
+
+ if (rc || old_dir == new_dir)
+ RETURN(rc);
+
+ if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
+ if (cache_leaf_node(new_dentry->d_parent, &active_entry)) {
+ rc = cache_space_hook_lru(new_dir, NULL, handle,
+ CACHE_SPACE_DELETE, 0);
+ if (rc)
+ RETURN(rc);
+ }
+ if (!active_entry)
+ rc = get_active_entry(new_dir, &active_entry);
+ active_entry ++;
+ if (!rc)
+ rc = set_active_entry(new_dir, &active_entry, handle);
+ if (rc)
+ RETURN(rc);
+ rc = get_active_entry(old_dir, &active_entry);
+ active_entry --;
+ if (!rc)
+ rc = set_active_entry(old_dir, &active_entry, handle);
+ } else if (cache_pre_leaf_node(new_dentry->d_parent, &active_entry, 3))
+ rc = cache_space_hook_lru(new_dir, NULL, handle,
+ CACHE_SPACE_DELETE, 0);
+
+ if (!rc && cache_leaf_node(old_dentry->d_parent, &active_entry))
+ rc = cache_space_hook_lru(old_dir,
+ old_dentry->d_parent->d_parent->d_inode,
+ handle, CACHE_SPACE_INSERT, 0);
+ RETURN(rc);
+}
+
+typedef int (*cache_hook_op)(void *handle, struct inode *old_dir,
+ struct dentry *old_dentry, struct inode *new_dir,
+ struct dentry *new_dentry);
+static cache_hook_op cache_space_hook_ops[CACHE_HOOK_MAX + 1] = {
+ [CACHE_HOOK_CREATE] cache_space_hook_create,
+ [CACHE_HOOK_LOOKUP] cache_space_hook_lookup,
+ [CACHE_HOOK_LINK] cache_space_hook_link,
+ [CACHE_HOOK_UNLINK] cache_space_hook_unlink,
+ [CACHE_HOOK_SYMLINK] cache_space_hook_create,
+ [CACHE_HOOK_MKDIR] cache_space_hook_mkdir,
+ [CACHE_HOOK_RMDIR] cache_space_hook_rmdir,
+ [CACHE_HOOK_MKNOD] cache_space_hook_create,
+ [CACHE_HOOK_RENAME] cache_space_hook_rename,
+};
+
+int cache_space_post(int op, void *handle, struct inode *old_dir,
+ struct dentry *old_dentry, struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ int rc;
+ ENTRY;
+
+ LASSERT(op <= CACHE_HOOK_MAX && cache_space_hook_ops[op] != NULL);
+
+ rc = cache_space_hook_ops[op](handle, old_dir, old_dentry,
+ new_dir, new_dentry);
+ RETURN(rc);
+}
-/*
- * dir.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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_SNAP
+
+#define DEBUG_SUBSYSTEM S_SM
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/unistd.h>
-#include <linux/lustre_idl.h>
#include <linux/smp_lock.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
-#include "smfs_internal.h"
-#include "kml_idl.h"
+#include "smfs_internal.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)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static int smfs_create(struct inode *dir, struct dentry *dentry,
+ int mode)
+#else
+static int smfs_create(struct inode *dir, struct dentry *dentry,
+ int mode, struct nameidata *nd)
+#endif
{
- 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);
+ struct inode *inode = NULL;
+ struct inode *cache_dir = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry *cache_parent = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ 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);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_CREATE, NULL);
+ if (IS_ERR(handle))
+ RETURN(-ENOSPC);
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_CREATE, handle, dir);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+
+ lock_kernel();
+ if (!cache_dentry || !cache_parent)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(dir, cache_dir);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (cache_dir && cache_dir->i_op->create)
+ rc = cache_dir->i_op->create(cache_dir, cache_dentry,
+ mode);
+#else
+ if (cache_dir && cache_dir->i_op->create)
+ rc = cache_dir->i_op->create(cache_dir, cache_dentry,
+ mode, nd);
+#endif
+ if (rc)
+ GOTO(exit, rc);
+
+ inode = iget(dir->i_sb, cache_dentry->d_inode->i_ino);
+ if (!inode)
+ GOTO(exit, rc = -ENOMEM);
+
+ d_instantiate(dentry, inode);
+ sm_set_inode_ops(cache_dentry->d_inode, inode);
+ post_smfs_inode(dir, cache_dir);
+
+ /* Do KML post hook */
+ SMFS_KML_POST(dir, dentry, NULL, NULL, REINT_CREATE, "create", rc,
+ exit);
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_CREATE, handle, dir, dentry,
+ NULL, NULL, rc, exit);
exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
+ unlock_kernel();
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static struct dentry *smfs_lookup(struct inode *dir,
- struct dentry *dentry)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry)
+#else
+static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
+#endif
{
- 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)
+ struct inode *cache_dir;
+ struct inode *cache_inode;
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry *cache_parent = NULL;
+ struct dentry *rc = NULL;
+ void *handle = NULL;
+ int rc2 = 0;
+
+ ENTRY;
+
+ if (!(cache_dir = I2CI(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);
+
+ handle = smfs_trans_start(dir, KML_CACHE_NOOP, NULL);
+ if (IS_ERR(handle))
+ RETURN(ERR_PTR(-ENOSPC));
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LOOKUP, handle, dir);
+
+ /* preparing artificial backing fs dentries. */
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+
+ if (!cache_dentry || !cache_parent)
+ GOTO(exit, rc = ERR_PTR(-ENOMEM));
+
+ if (!cache_dir && cache_dir->i_op->lookup)
+ GOTO(exit, rc = ERR_PTR(-ENOENT));
+
+ /* perform lookup in backing fs. */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ rc = cache_dir->i_op->lookup(cache_dir, cache_dentry);
+#else
+ rc = cache_dir->i_op->lookup(cache_dir, cache_dentry, nd);
+#endif
+
+ if (rc && IS_ERR(rc))
+ GOTO(exit, rc);
+
+ if ((cache_inode = rc ? rc->d_inode : cache_dentry->d_inode)) {
+ if (IS_ERR(cache_inode)) {
+ dentry->d_inode = cache_inode;
+ GOTO(exit, rc = NULL);
+ }
+ inode = iget(dir->i_sb, cache_inode->i_ino);
+ } else {
+ d_add(dentry, NULL);
+ GOTO(exit, rc);
+ }
+
+ d_add(dentry, inode);
+ rc = NULL;
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_LOOKUP, handle, dir, dentry,
+ NULL, NULL, rc2, exit);
exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
-}
+ if (rc2)
+ rc = ERR_PTR(rc2);
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
+}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
static int smfs_lookup_raw(struct inode *dir, const char *name,
int len, ino_t *data)
{
- struct inode *cache_dir;
- int rc = 0;
+ struct inode *cache_dir;
+ int rc = 0;
- cache_dir = I2CI(dir);
+ cache_dir = I2CI(dir);
- if (!cache_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);
+ if (cache_dir->i_op->lookup_raw)
+ rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);
+ RETURN(rc);
}
+#endif
-static int smfs_link(struct dentry * old_dentry,
- struct inode * dir, struct dentry *dentry)
+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);
+ struct inode *cache_old_inode = NULL;
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry *cache_old_dentry = NULL;
+ struct dentry *cache_parent = NULL;
+ struct dentry *cache_old_parent = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ inode = old_dentry->d_inode;
+
+ cache_old_inode = I2CI(inode);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_LINK, NULL);
+ if (IS_ERR(handle))
+ RETURN(-ENOSPC);
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_LINK, handle, dir);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ lock_kernel();
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ cache_old_parent = pre_smfs_dentry(NULL, cache_dir, old_dentry);
+ cache_old_dentry = pre_smfs_dentry(cache_parent, cache_old_inode,
+ old_dentry);
+
+ if (!cache_old_parent || !cache_old_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(dir, cache_dir);
+ 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);
+ post_smfs_inode(dir, cache_dir);
+
+ SMFS_KML_POST(dir, old_dentry, dentry, NULL,
+ REINT_LINK, "link", rc, exit);
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_LINK, handle,
+ dir, old_dentry, NULL, NULL, rc, exit);
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);
+ unlock_kernel();
+ post_smfs_dentry(cache_dentry);
+ post_smfs_dentry(cache_old_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static int smfs_unlink(struct inode * dir,
- struct dentry *dentry)
+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);
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *cache_inode = I2CI(dentry->d_inode);
+ struct dentry *cache_dentry;
+ struct dentry *cache_parent;
+ void *handle = NULL;
+ int rc = 0, flag;
+
+ if (!cache_dir || !cache_inode)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_UNLINK, NULL);
+ if (IS_ERR(handle))
+ RETURN(-ENOSPC);
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_UNLINK, handle, dir);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
+
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ if (smfs_do_rec(dir) && dentry->d_inode->i_nlink == 1) {
+ /*For unlink, we do not really unlink this
+ *inode and just remove it to a tmp dir for
+ *undo later, the inode will be deleted when
+ *the corresponding rec will be cancelled*/
+ flag = 0;
+ SMFS_KML_POST(dir, dentry, &flag, NULL, REINT_UNLINK,
+ "unlink", rc, exit);
+ } else {
+ lock_kernel();
+ pre_smfs_inode(dir, cache_dir);
+ pre_smfs_inode(dentry->d_inode, 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);
+ post_smfs_dentry(cache_dentry);
+ unlock_kernel();
+ flag = 1;
+ SMFS_KML_POST(dir, dentry, &flag, NULL, REINT_UNLINK,
+ "dec_link", rc, exit);
+ }
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_UNLINK, handle, dir, dentry,
+ NULL, NULL, rc, exit);
+exit:
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static int smfs_symlink (struct inode * dir,
- struct dentry *dentry,
- const char * symname)
+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);
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry;
+ struct dentry *cache_parent;
+ void *handle = NULL;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_SYMLINK, NULL);
+ if (IS_ERR(handle))
+ RETURN(-ENOSPC);
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_SYMLINK, handle, dir);
+
+ pre_smfs_inode(dir, cache_dir);
+ lock_kernel();
+ if (cache_dir->i_op->symlink)
+ rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
+
+ inode = iget(dir->i_sb, cache_dentry->d_inode->i_ino);
+
+ post_smfs_inode(dir, cache_dir);
+ if (inode)
+ d_instantiate(dentry, inode);
+ else
+ rc = -ENOENT;
+
+ SMFS_KML_POST(dir, dentry, (char*)symname, NULL, REINT_CREATE,
+ "symlink", rc, exit);
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_SYMLINK, handle, dir, dentry,
+ NULL, NULL, rc, exit);
+exit:
+ unlock_kernel();
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static int smfs_mkdir(struct inode * dir,
- struct dentry * dentry,
- int mode)
+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);
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry;
+ struct dentry *cache_parent;
+ void *handle = NULL;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_MKDIR, NULL);
+ if (IS_ERR(handle))
+ RETURN(-ENOSPC);
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKDIR, handle, dir);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+
+ lock_kernel();
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(dir, cache_dir);
+
+ if (cache_dir->i_op->mkdir)
+ rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
+
+ inode = iget(dir->i_sb, cache_dentry->d_inode->i_ino);
+
+ if (!inode)
+ GOTO(exit, rc = -ENOENT);
+
+ d_instantiate(dentry, inode);
+ post_smfs_inode(dir, cache_dir);
+
+ SMFS_KML_POST(dir, dentry, NULL, NULL, REINT_CREATE, "mkdir", rc, exit);
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKDIR, handle,
+ dir, dentry, NULL, NULL, rc, exit);
exit:
- unlock_kernel();
- smfs_trans_commit(handle);
- d_unalloc(cache_dentry);
- RETURN(rc);
+ unlock_kernel();
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static int smfs_rmdir(struct inode * dir,
- struct dentry *dentry)
+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);
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *cache_inode = I2CI(dentry->d_inode);
+ struct dentry *cache_dentry = NULL;
+ struct dentry *cache_parent = NULL;
+ void *handle = NULL;
+ int rc = 0, flag;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_RMDIR, NULL);
+ if (IS_ERR(handle)) {
+ CERROR("smfs_do_mkdir: no space for transaction\n");
+ RETURN(-ENOSPC);
+ }
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RMDIR, handle, dir);
+
+ if (smfs_do_rec(dir)) {
+ /*For rmdir, we do not really unlink this
+ *inode and just remove it to a tmp dir for
+ *undo later, the inode will be deleted when
+ *the corresponding rec will be cancelled*/
+ if (dentry->d_inode->i_nlink == 2) {
+ flag = 0;
+ SMFS_KML_POST(dir, dentry, &flag, NULL,
+ REINT_UNLINK, "rmdir", rc, exit);
+ }
+ } else {
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode,
+ dentry);
+
+ lock_kernel();
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ 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);
+ unlock_kernel();
+ }
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_RMDIR, handle, dir, dentry,
+ NULL, NULL, rc, exit);
+exit:
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ RETURN(rc);
}
-static int smfs_mknod(struct inode * dir, struct dentry *dentry,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static int smfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, int rdev)
+#else
+static int smfs_mknod(struct inode *dir, struct dentry *dentry,
+ int mode, dev_t rdev)
+#endif
{
- 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);
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry *cache_parent = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(dir, FSFILT_OP_MKNOD, NULL);
+ if (IS_ERR(handle)) {
+ CERROR("smfs_do_mkdir: no space for transaction\n");
+ RETURN(-ENOSPC);
+ }
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_MKNOD, handle, dir);
+
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ lock_kernel();
+ if (!cache_parent || !cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ pre_smfs_inode(dir, cache_dir);
+ pre_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+
+ if (!cache_dir->i_op->mknod)
+ RETURN(-ENOENT);
+
+ rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev);
+ if (rc)
+ GOTO(exit, rc);
+
+ inode = iget(dir->i_sb, cache_dentry->d_inode->i_ino);
+ d_instantiate(dentry, inode);
+
+ post_smfs_inode(dir, cache_dir);
+ post_smfs_inode(dentry->d_inode, cache_dentry->d_inode);
+
+ SMFS_KML_POST(dir, dentry, NULL, NULL,
+ REINT_CREATE, "mknod", rc, exit);
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_MKNOD, handle, dir,
+ dentry, NULL, NULL, rc, exit);
exit:
- d_unalloc(cache_dentry);
- RETURN(rc);
+ unlock_kernel();
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dir, handle, 0);
+ 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 *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 inode *cache_new_inode = new_dentry->d_inode ?
+ I2CI(new_dentry->d_inode) : NULL;
+
+ struct dentry *cache_old_dentry = NULL;
+ struct dentry *cache_new_dentry = NULL;
+ struct dentry *cache_new_parent = NULL;
+ struct dentry *cache_old_parent = NULL;
+ void *handle = NULL;
+ int rc = 0;
+
+ if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
+ RETURN(-ENOENT);
+
+ handle = smfs_trans_start(old_dir, FSFILT_OP_RENAME, NULL);
+ if (IS_ERR(handle)) {
+ CERROR("smfs_do_mkdir: no space for transaction\n");
+ RETURN(-ENOSPC);
+ }
+ lock_kernel();
+
+ SMFS_CACHE_HOOK_PRE(CACHE_HOOK_RENAME, handle, old_dir);
+
+ cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
+ cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
+ old_dentry);
+ if (!cache_old_parent || !cache_old_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ cache_new_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry);
+ cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
+ new_dentry);
+ if (!cache_new_parent || !cache_new_dentry)
+ GOTO(exit, rc = -ENOMEM);
+
+ 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);
+
+ SMFS_KML_POST(old_dir, old_dentry, new_dir,
+ new_dentry, REINT_RENAME, "rename", rc, exit);
+ if (new_dentry->d_inode)
+ post_smfs_inode(new_dentry->d_inode, cache_new_dentry->d_inode);
+
+ SMFS_CACHE_HOOK_POST(CACHE_HOOK_RENAME, handle, old_dir, old_dentry,
+ new_dir, new_dentry, rc, exit);
+exit:
+ unlock_kernel();
+ post_smfs_dentry(cache_old_dentry);
+ post_smfs_dentry(cache_new_dentry);
+ smfs_trans_commit(old_dir, handle, 0);
+ RETURN(rc);
}
struct inode_operations smfs_dir_iops = {
- create: smfs_create,
- lookup: smfs_lookup,
- lookup_raw: smfs_lookup_raw, /* BKL held */
+ create: smfs_create,
+ lookup: smfs_lookup,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ lookup_raw: smfs_lookup_raw, /* BKL held */
+#endif
link: smfs_link, /* BKL held */
unlink: smfs_unlink, /* BKL held */
symlink: smfs_symlink, /* BKL held */
removexattr: smfs_removexattr, /* BKL held */
};
-static ssize_t smfs_read_dir(struct file *filp, char *buf,
- size_t size, loff_t *ppos)
+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);
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *cache_inode = NULL;
+ struct smfs_file_info *sfi = NULL;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ sfi = F2SMFI(filp);
+ if (sfi->magic != SMFS_FILE_MAGIC) BUG();
+
+ if (ppos != &(filp->f_pos))
+ cache_ppos = &tmp_ppos;
+ else
+ cache_ppos = &sfi->c_file->f_pos;
+ *cache_ppos = *ppos;
+
+ if (cache_inode->i_fop->read)
+ rc = cache_inode->i_fop->read(sfi->c_file, buf, size,
+ cache_ppos);
+
+ *ppos = *cache_ppos;
+ duplicate_file(filp, sfi->c_file);
+ RETURN(rc);
}
-static int smfs_readdir(struct file * filp,
- void * dirent,
- filldir_t filldir)
+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 dentry *dentry = filp->f_dentry;
+ struct inode *cache_inode = NULL;
+ struct smfs_file_info *sfi = NULL;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ sfi = F2SMFI(filp);
+ if (sfi->magic != SMFS_FILE_MAGIC) BUG();
+
+ if (cache_inode->i_fop->readdir)
+ rc = cache_inode->i_fop->readdir(sfi->c_file, dirent, filldir);
+
+ duplicate_file(filp, sfi->c_file);
+ RETURN(rc);
}
struct file_operations smfs_dir_fops = {
- read: smfs_read_dir,
+ read: smfs_read_dir,
readdir: smfs_readdir, /* BKL held */
ioctl: smfs_ioctl, /* BKL held */
fsync: smfs_fsync, /* BKL held */
+ open: smfs_open,
+ release: smfs_release,
};
-/*
- * file.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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_SM
#include <linux/stat.h>
#include <linux/unistd.h>
#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.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;
-}
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
-static ssize_t smfs_write (struct file *filp, const char *buf,
- size_t count, loff_t *ppos)
+#include "smfs_internal.h"
+
+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);
-
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ int rc = 0;
+ ENTRY;
+
+ cache_inode = I2CI(filp->f_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->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);
+
+ sfi = F2SMFI(filp);
+
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ if (ppos != &(filp->f_pos))
+ cache_ppos = &tmp_ppos;
+ else
+ cache_ppos = &sfi->c_file->f_pos;
+ *cache_ppos = *ppos;
+
+ pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_fop->write)
+ rc = cache_inode->i_fop->write(sfi->c_file, buf, count,
+ cache_ppos);
+
+ post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
+ SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry,
+ &count ,ppos, REINT_WRITE, "write", rc, exit);
+exit:
+ *ppos = *cache_ppos;
+ duplicate_file(filp, sfi->c_file);
+ RETURN(rc);
}
-int smfs_ioctl(struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
+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);
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ ssize_t rc = 0;
+ ENTRY;
+
+ cache_inode = I2CI(filp->f_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);
+ sfi = F2SMFI(filp);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ pre_smfs_inode(inode, cache_inode);
+
+ if (cache_inode->i_fop->ioctl)
+ rc = cache_inode->i_fop->ioctl(cache_inode, sfi->c_file, cmd,
+ arg);
+
+ post_smfs_inode(inode, cache_inode);
+ duplicate_file(filp, sfi->c_file);
+
RETURN(rc);
}
-static ssize_t smfs_read (struct file *filp, char *buf,
- size_t count, loff_t *ppos)
+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);
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ loff_t tmp_ppos;
+ loff_t *cache_ppos;
+ ssize_t rc = 0;
+ ENTRY;
+
+ cache_inode = I2CI(filp->f_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);
+ sfi = F2SMFI(filp);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ if (ppos != &(filp->f_pos))
+ cache_ppos = &tmp_ppos;
+ else
+ cache_ppos = &sfi->c_file->f_pos;
+ *cache_ppos = *ppos;
+
+ pre_smfs_inode(filp->f_dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_fop->read)
+ rc = cache_inode->i_fop->read(sfi->c_file, buf, count,
+ cache_ppos);
+
+ *ppos = *cache_ppos;
+ post_smfs_inode(filp->f_dentry->d_inode, cache_inode);
+ duplicate_file(filp, sfi->c_file);
+
+ RETURN(rc);
}
-static loff_t smfs_llseek(struct file *file,
- loff_t offset,
- int origin)
+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);
+ struct inode *cache_inode;
+ struct smfs_file_info *sfi;
+ ssize_t rc = 0;
+ ENTRY;
+
+ cache_inode = I2CI(file->f_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);
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_fop->llseek)
+ rc = cache_inode->i_fop->llseek(sfi->c_file, offset, origin);
+
+ post_smfs_inode(file->f_dentry->d_inode, cache_inode);
+ duplicate_file(file, sfi->c_file);
- 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)
+static int smfs_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file->f_dentry->d_inode;
+ struct smfs_file_info *sfi;
struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
+ int rc = 0;
+ ENTRY;
- cache_inode = I2CI(inode);
+ 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)
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ 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);
+ pre_smfs_inode(inode, cache_inode);
+ if (cache_inode->i_fop->mmap)
+ rc = cache_inode->i_fop->mmap(sfi->c_file, vma);
+
+ post_smfs_inode(inode, cache_inode);
+ duplicate_file(file, sfi->c_file);
+
+ RETURN(rc);
+}
+
+static int smfs_init_cache_file(struct inode *inode, struct file *filp)
+{
+ struct smfs_file_info *sfi = NULL;
+ struct file *cache_filp = NULL;
+ struct dentry *cache_dentry = NULL;
+ int rc = 0;
+ ENTRY;
+
+ OBD_ALLOC(sfi, sizeof(struct smfs_file_info));
+ if (!sfi)
+ RETURN(-ENOMEM);
+
+ cache_filp = get_empty_filp();
+ if (!cache_filp)
+ GOTO(err_exit, rc = -ENOMEM);
+
+ sfi->magic = SMFS_FILE_MAGIC;
+
+ cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
+ if (!cache_dentry)
+ GOTO(err_exit, rc = -ENOMEM);
+
+ cache_filp->f_vfsmnt = filp->f_vfsmnt;
+
+ cache_filp->f_dentry = cache_dentry;
+ duplicate_file(cache_filp, filp);
+
+ sfi->c_file = cache_filp;
+
+ if (filp->private_data != NULL)
+ BUG();
+
+ filp->private_data = sfi;
+
+ RETURN(rc);
+err_exit:
+ if (sfi)
+ OBD_FREE(sfi, sizeof(struct smfs_file_info));
+ if (cache_filp)
+ put_filp(cache_filp);
+ RETURN(rc);
}
-static int smfs_open(struct inode * inode, struct file * filp)
+static int smfs_cleanup_cache_file(struct file *filp)
{
- struct inode *cache_inode = NULL;
- struct file open_file;
- struct dentry open_dentry;
- int rc = 0;
+ struct smfs_file_info *sfi = NULL;
+ int rc = 0;
+ ENTRY;
+
+ sfi = F2SMFI(filp);
+
+ post_smfs_dentry(sfi->c_file->f_dentry);
- cache_inode = I2CI(inode);
+ put_filp(sfi->c_file);
+
+ OBD_FREE(sfi, sizeof(struct smfs_file_info));
+
+ filp->private_data = NULL;
+
+ RETURN(rc);
+}
+
+int smfs_open(struct inode *inode, struct file *filp)
+{
+ struct inode *cache_inode = NULL;
+ int rc = 0, flag = 1;
+ ENTRY;
+
+ 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);
+ if ((rc = smfs_init_cache_file(inode, filp)))
+ RETURN(rc);
+
+ pre_smfs_inode(inode, cache_inode);
+ if (cache_inode->i_fop->open)
+ rc = cache_inode->i_fop->open(cache_inode, F2CF(filp));
+
+ post_smfs_inode(inode, cache_inode);
+ duplicate_file(filp, F2CF(filp));
+ SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry, &flag, NULL,
+ REINT_OPEN, "open", rc, exit);
+exit:
+ RETURN(rc);
}
-static int smfs_release(struct inode * inode, struct file * filp)
+
+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;
+ struct inode *cache_inode = NULL;
+ struct smfs_file_info *sfi = NULL;
+ int rc = 0, flag = 0;
+ ENTRY;
- cache_inode = I2CI(inode);
+ 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);
+
+ sfi = F2SMFI(filp);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ pre_smfs_inode(inode, cache_inode);
+ if (cache_inode->i_fop->release)
+ rc = cache_inode->i_fop->release(cache_inode, sfi->c_file);
+
+ post_smfs_inode(inode, cache_inode);
+ duplicate_file(filp, sfi->c_file);
+
+ smfs_cleanup_cache_file(filp);
+
+ SMFS_KML_POST(filp->f_dentry->d_inode, filp->f_dentry, &flag, NULL,
+ REINT_CLOSE, "close", rc, exit);
+exit:
+ RETURN(rc);
}
-int smfs_fsync(struct file * file,
- struct dentry *dentry,
- int datasync)
+
+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;
+ struct smfs_file_info *sfi = NULL;
+ struct inode *cache_inode;
+ int rc = 0;
- cache_inode = I2CI(inode);
+ cache_inode = I2CI(file->f_dentry->d_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);
+
+ sfi = F2SMFI(file);
+ if (sfi->magic != SMFS_FILE_MAGIC)
+ BUG();
+
+ pre_smfs_inode(file->f_dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_fop->fsync)
+ rc = cache_inode->i_fop->fsync(sfi->c_file,
+ sfi->c_file->f_dentry, datasync);
+
+ post_smfs_inode(file->f_dentry->d_inode, cache_inode);
+ duplicate_file(file, sfi->c_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,
+ 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)
+static void smfs_truncate(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);
+ struct inode *cache_inode;
+
+ cache_inode = I2CI(inode);
+
+ if (!cache_inode)
+ return;
+
+ pre_smfs_inode(inode, cache_inode);
+ if (cache_inode->i_op->truncate)
+ cache_inode->i_op->truncate(cache_inode);
+
+ post_smfs_inode(inode, cache_inode);
}
-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)
+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 *cache_dentry;
+ void *handle = NULL;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ RETURN(-ENOMEM);
+
+ handle = smfs_trans_start(dentry->d_inode, FSFILT_OP_SETATTR, NULL);
+ if (IS_ERR(handle) ) {
+ CERROR("smfs_do_mkdir: no space for transaction\n");
+ RETURN(-ENOSPC);
+ }
+
+ pre_smfs_inode(dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_op->setattr)
+ rc = cache_inode->i_op->setattr(cache_dentry, attr);
+
+ SMFS_KML_POST(dentry->d_inode, dentry, attr, NULL,
+ REINT_SETATTR, "setattr", rc, exit);
+exit:
+ post_smfs_inode(dentry->d_inode, cache_inode);
+ post_smfs_dentry(cache_dentry);
+ smfs_trans_commit(dentry->d_inode, handle, 0);
+ 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 *cache_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ RETURN(-ENOMEM);
+
+ pre_smfs_inode(dentry->d_inode, cache_inode);
+
+ if (cache_inode->i_op->setxattr)
+ rc = cache_inode->i_op->setxattr(cache_dentry, name, value,
+ size, flags);
+
+ post_smfs_inode(dentry->d_inode, cache_inode);
+ post_smfs_dentry(cache_dentry);
+
+ 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;
+ struct inode *cache_inode;
+ struct dentry *cache_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ RETURN(-ENOMEM);
- cache_inode = I2CI(dentry->d_inode);
+ pre_smfs_inode(dentry->d_inode, cache_inode);
- if (!cache_inode)
- RETURN(-ENOENT);
+ if (cache_inode->i_op->getattr)
+ rc = cache_inode->i_op->getxattr(cache_dentry, name, buffer,
+ size);
- 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);
+ post_smfs_dentry(cache_dentry);
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
+ 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;
+ struct inode *cache_inode;
+ struct dentry *cache_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
- cache_inode = I2CI(dentry->d_inode);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ RETURN(-ENOMEM);
- if (!cache_inode)
- RETURN(-ENOENT);
+ pre_smfs_inode(dentry->d_inode, cache_inode);
- 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);
+ if (cache_inode->i_op->listxattr)
+ rc = cache_inode->i_op->listxattr(cache_dentry, buffer, size);
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
-}
+ post_smfs_inode(dentry->d_inode, cache_inode);
+ post_smfs_dentry(cache_dentry);
+
+ RETURN(rc);
+}
int smfs_removexattr(struct dentry *dentry, const char *name)
{
- struct inode *cache_inode;
- struct dentry open_dentry;
- int rc = 0;
+ struct inode *cache_inode;
+ struct dentry *cache_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
- cache_inode = I2CI(dentry->d_inode);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ RETURN(-ENOMEM);
- if (!cache_inode)
- RETURN(-ENOENT);
+ pre_smfs_inode(dentry->d_inode, cache_inode);
- 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);
+ if (cache_inode->i_op->removexattr)
+ rc = cache_inode->i_op->removexattr(cache_dentry, name);
- post_smfs_inode(dentry->d_inode, cache_inode);
- RETURN(rc);
+ post_smfs_inode(dentry->d_inode, cache_inode);
+ post_smfs_dentry(cache_dentry);
+
+ RETURN(rc);
}
struct inode_operations smfs_file_iops = {
- truncate: smfs_truncate, /* BKL held */
+ 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 */
};
-
-/*
- * smfs/inode.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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/fs.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
+#include <linux/lustre_smfs.h>
+#include "smfs_internal.h"
-static void duplicate_inode(struct inode *dst_inode,
- struct inode *src_inode)
+static void smfs_read_inode(struct inode *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;
-}
+ struct super_block *cache_sb;
+ struct inode *cache_inode;
+ ENTRY;
-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);
- }
-}
+ if (!inode)
+ return;
-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;
+ 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);
+
+ SMFS_SET_INODE_REC(inode);
+ SMFS_SET_INODE_CACHE_HOOK(inode);
+ I2CI(inode) = cache_inode;
+
+ pre_smfs_inode(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));
+ EXIT;
}
/* Although some filesystem(such as ext3) do not have
- * clear_inode method, but we need it to free the
- * cache inode
+ * 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
+ 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;
+ 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);
+
+ SMFS_CLEAN_INODE_REC(inode);
+ I2CI(inode) = NULL;
+ EXIT;
}
+
static void smfs_delete_inode(struct inode *inode)
{
- struct inode *cache_inode;
- struct super_block *cache_sb;
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+ ENTRY;
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
- if (!cache_inode || !cache_sb)
- return;
+ 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*/
+ /* FIXME-WANGDI: 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);
- 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);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ list_del(&cache_inode->i_hash);
INIT_LIST_HEAD(&cache_inode->i_hash);
+#else
+ hlist_del_init(&cache_inode->i_hash);
+#endif
+
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;
+
+ 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;
+ EXIT;
}
+
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;
+ 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);
+ EXIT;
}
+
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;
-}
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+ ENTRY;
-static void smfs_put_inode(struct inode *inode)
-{
- struct inode *cache_inode;
- struct super_block *cache_sb;
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
- ENTRY;
- cache_inode = I2CI(inode);
- cache_sb = S2CSB(inode->i_sb);
+ if (!cache_inode || !cache_sb)
+ return;
- if (!cache_inode || !cache_sb)
- return;
- if (cache_sb->s_op->put_inode)
- cache_sb->s_op->put_inode(cache_inode);
+ pre_smfs_inode(inode, cache_inode);
+ if (cache_sb->s_op->dirty_inode)
+ cache_sb->s_op->dirty_inode(cache_inode);
- return;
+ post_smfs_inode(inode, cache_inode);
+ EXIT;
+}
+
+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);
+ EXIT;
}
static void smfs_write_super(struct super_block *sb)
{
- struct super_block *cache_sb;
+ struct super_block *cache_sb;
+ ENTRY;
- ENTRY;
- cache_sb = S2CSB(sb);
+ cache_sb = S2CSB(sb);
+ if (!cache_sb)
+ return;
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->write_super)
- cache_sb->s_op->write_super(cache_sb);
+ if (cache_sb->s_op->write_super)
+ cache_sb->s_op->write_super(cache_sb);
- duplicate_sb(cache_sb, sb);
- return;
+ duplicate_sb(sb, cache_sb);
+ EXIT;
}
static void smfs_write_super_lockfs(struct super_block *sb)
{
- struct super_block *cache_sb;
+ struct super_block *cache_sb;
+ ENTRY;
- ENTRY;
- cache_sb = S2CSB(sb);
+ cache_sb = S2CSB(sb);
+ if (!cache_sb)
+ return;
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->write_super_lockfs)
- cache_sb->s_op->write_super_lockfs(cache_sb);
+ if (cache_sb->s_op->write_super_lockfs)
+ cache_sb->s_op->write_super_lockfs(cache_sb);
- duplicate_sb(cache_sb, sb);
- return;
+ duplicate_sb(sb, cache_sb);
+ EXIT;
}
static void smfs_unlockfs(struct super_block *sb)
{
- struct super_block *cache_sb;
+ struct super_block *cache_sb;
+ ENTRY;
- ENTRY;
- cache_sb = S2CSB(sb);
+ cache_sb = S2CSB(sb);
+ if (!cache_sb)
+ return;
- if (!cache_sb)
- return;
-
- if (cache_sb->s_op->unlockfs)
- cache_sb->s_op->unlockfs(cache_sb);
+ if (cache_sb->s_op->unlockfs)
+ cache_sb->s_op->unlockfs(cache_sb);
- duplicate_sb(cache_sb, sb);
- return;
+ duplicate_sb(sb, cache_sb);
+ EXIT;
}
-static int smfs_statfs(struct super_block * sb, struct statfs * buf)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static int smfs_statfs(struct super_block *sb, struct statfs *buf)
+#else
+static int smfs_statfs(struct super_block *sb, struct kstatfs *buf)
+#endif
{
- struct super_block *cache_sb;
- int rc = 0;
+ struct super_block *cache_sb;
+ int rc = 0;
+ ENTRY;
- ENTRY;
- cache_sb = S2CSB(sb);
+ cache_sb = S2CSB(sb);
+ if (!cache_sb)
+ RETURN(-EINVAL);
- if (!cache_sb)
- RETURN(-EINVAL);
-
- if (cache_sb->s_op->statfs)
- rc = cache_sb->s_op->statfs(cache_sb, buf);
+ if (cache_sb->s_op->statfs)
+ rc = cache_sb->s_op->statfs(cache_sb, buf);
- duplicate_sb(cache_sb, sb);
-
- return rc;
+ duplicate_sb(sb, cache_sb);
+
+ RETURN(rc);
}
-static int smfs_remount(struct super_block * sb, int * flags, char * data)
+
+static int smfs_remount(struct super_block *sb, int *flags, char *data)
{
- struct super_block *cache_sb;
- int rc = 0;
+ struct super_block *cache_sb;
+ int rc = 0;
+ ENTRY;
+
+ cache_sb = S2CSB(sb);
- ENTRY;
- cache_sb = S2CSB(sb);
+ if (!cache_sb)
+ RETURN(-EINVAL);
- if (!cache_sb)
- RETURN(-EINVAL);
-
- if (cache_sb->s_op->remount_fs)
- rc = cache_sb->s_op->remount_fs(cache_sb, flags, data);
+ 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);
+ duplicate_sb(sb, cache_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,
+ 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 */
unlockfs: smfs_unlockfs, /* BKL not held. We take it */
statfs: smfs_statfs, /* BKL held */
remount_fs: smfs_remount, /* BKL held */
-
};
-
-
-
-
-
--- /dev/null
+#define DEBUG_SUBSYSTEM S_SM
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
+#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/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_debug.h>
+#include <linux/lustre_smfs.h>
+
+#include "smfs_internal.h"
+
+
+struct smfs_control_device smfs_dev;
+
+static int smfs_handle_ioctl(unsigned int cmd, unsigned long arg)
+{
+ struct obd_ioctl_data *data = NULL;
+ struct super_block *sb = NULL;
+ char *buf = NULL, *dir = NULL;
+ int err = 0, len = 0, count = 0, do_kml = 0;
+
+ if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
+ CERROR("OBD ioctl: data error\n");
+ GOTO(out, err = -EINVAL);
+ }
+ data = (struct obd_ioctl_data *)buf;
+
+ switch (cmd) {
+ case IOC_SMFS_START:
+ case IOC_SMFS_STOP:
+ case IOC_SMFS_REINT:
+ case IOC_SMFS_UNDO:{
+ char *name;
+ if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
+ CERROR("No mountpoint passed!\n");
+ GOTO(out, err = -EINVAL);
+ }
+ name = (char*) data->ioc_inlbuf1;
+ sb = smfs_get_sb_by_path(name, data->ioc_inllen1);
+ if (!sb) {
+ CERROR("can not find superblock at %s\n", buf);
+ GOTO(out, err = -EINVAL);
+ }
+ /*get cmd count*/
+ if (data->ioc_inllen2 && data->ioc_inlbuf2) {
+ dir = (char *)data->ioc_inlbuf2;
+ }
+ if (data->ioc_plen1)
+ count = *((int*)data->ioc_pbuf1);
+ if (data->ioc_plen2)
+ do_kml = *((int*)data->ioc_pbuf2);
+ break;
+ }
+ default: {
+ CERROR("The command passed in is Invalid\n");
+ GOTO(out, err = -EINVAL);
+ }
+ }
+
+ switch (cmd) {
+ case IOC_SMFS_START:
+ err = smfs_start_rec(sb);
+ break;
+ case IOC_SMFS_STOP:
+ err = smfs_stop_rec(sb);
+ break;
+ case IOC_SMFS_REINT:
+ case IOC_SMFS_UNDO: {
+ int flags = 0;
+ if (cmd == IOC_SMFS_REINT)
+ SET_REC_OP_FLAGS(flags, SMFS_REINT_REC);
+ else
+ SET_REC_OP_FLAGS(flags, SMFS_UNDO_REC);
+ if (count == 0)
+ SET_REC_COUNT_FLAGS(flags, SMFS_REC_ALL);
+ if (do_kml)
+ SET_REC_WRITE_KML_FLAGS(flags, SMFS_WRITE_KML);
+ err = smfs_process_rec(sb, count, dir, flags);
+ break;
+ }
+ }
+out:
+ if (buf)
+ obd_ioctl_freedata(buf, len);
+ RETURN(err);
+}
+static int smfs_psdev_ioctl (struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ int rc = 0;
+ rc = smfs_handle_ioctl(cmd, arg);
+ RETURN(rc);
+}
+
+/* called when opening /dev/device */
+static int smfs_psdev_open(struct inode * inode, struct file * file)
+{
+ int dev;
+ ENTRY;
+
+ if (!inode)
+ RETURN(-EINVAL);
+ dev = MINOR(inode->i_rdev);
+ if (dev != SMFS_PSDEV_MINOR)
+ RETURN(-ENODEV);
+
+ RETURN(0);
+}
+
+/* called when closing /dev/device */
+static int smfs_psdev_release(struct inode * inode, struct file * file)
+{
+ int dev;
+ ENTRY;
+
+ if (!inode)
+ RETURN(-EINVAL);
+ dev = MINOR(inode->i_rdev);
+ if (dev != SMFS_PSDEV_MINOR)
+ RETURN(-ENODEV);
+
+ RETURN(0);
+}
+
+/* declare character device */
+static struct file_operations smfscontrol_fops = {
+ ioctl: smfs_psdev_ioctl, /* ioctl */
+ open: smfs_psdev_open, /* open */
+ release: smfs_psdev_release, /* release */
+};
+
+#define SMFS_MINOR 250
+static struct miscdevice smfscontrol_dev = {
+ minor: SMFS_MINOR,
+ name: "smfscontrol",
+ fops: &smfscontrol_fops
+};
+
+int init_smfs_psdev(void)
+{
+ printk(KERN_INFO "SMFS psdev driver v0.01, braam@clusterfs.com\n");
+
+ misc_register(&smfscontrol_dev);
+
+ return 0;
+}
+
+void smfs_cleanup_psdev(void)
+{
+ ENTRY;
+ misc_deregister(&smfscontrol_dev);
+ EXIT;
+}
-/*
- * smfs/inode.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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/string.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "kml_idl.h"
-#include "smfs_internal.h"
-extern struct sm_ops smfs_operations;
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include <linux/lvfs.h>
+#include "smfs_internal.h"
#define size_round(x) (((x)+3) & ~0x3)
-void *smfs_trans_start(struct inode *inode, int op)
+void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
{
+ struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
+
+ CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start);
- 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;
+ SMFS_TRANS_OP(inode, op);
+
+ /* There are some problem here. fs_start in fsfilt is used by lustre
+ * the journal blocks of write rec are not counted in FIXME later */
+ if (fsfilt->fs_start)
+ return fsfilt->fs_start(inode, op, desc_private, 0);
+ return NULL;
}
-void smfs_trans_commit(void *handle)
+void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
{
- 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);
+ struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
+
+ CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit);
+
+ if (fsfilt->fs_commit)
+ fsfilt->fs_commit(inode, handle, force_sync);
}
-/*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)
+
+/*smfs_path is gotten from intermezzo*/
+static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
+ int buflen)
{
char * end = buffer+buflen;
+ char * name = buffer;
+ char * buf_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;
retval = end;
dentry = parent;
}
+
+ while (end != buf_end)
+ *name++ = *end++;
+ *name = '\0';
return retval;
}
-
-static inline char *logit(char *buf, const void *value, int size)
+static int smfs_log_path(struct dentry *root, struct dentry *dentry,
+ char *buffer, int buffer_len)
{
- char *ptr = (char *)value;
-
- memcpy(buf, ptr, size);
- buf += size;
- return buf;
+ char *p_name = buffer + sizeof(int);
+ char *name = NULL;
+ int namelen = 0;
+
+ name = smfs_path(dentry, root, p_name, buffer_len);
+ namelen = cpu_to_le32(strlen(p_name));
+ memcpy(buffer, &namelen, sizeof(int));
+
+ namelen += sizeof(int);
+ RETURN(namelen);
}
-static inline char *
-journal_log_prefix_with_groups_and_ids(char *buf, int opcode,
- __u32 ngroups, gid_t *groups,
- __u32 fsuid, __u32 fsgid)
+
+static inline int log_it(char *buffer, void *data, int length)
{
- 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;
+ memcpy(buffer, &length, sizeof(int));
+ memcpy(buffer + sizeof(int), data, length);
+ return (sizeof(int) + length);
}
-
-static inline char *
-journal_log_prefix(char *buf, int opcode)
+
+static int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- __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);
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dentry->d_inode->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, dir, REINT_CREATE);
+
+ p_name = buffer + sizeof(struct update_record);
+
+ root = dir->i_sb->s_root;
+
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ if (data1) {
+ /*for symlink data is the path of the symname*/
+ int data_len = strlen(data1);
+
+ buffer_length += log_it(p_name + buffer_length,
+ data1, data_len);
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+
+ RETURN(rc);
}
-
-static inline char *
-journal_log_prefix_with_groups(char *buf, int opcode,
- __u32 ngroups, gid_t *groups)
+
+static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- return journal_log_prefix_with_groups_and_ids(buf, opcode,
- ngroups, groups,
- (__u32)current->fsuid,
- (__u32)current->fsgid);
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ struct dentry *new_dentry = (struct dentry *)data1;
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name = NULL;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dir->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, NULL, REINT_LINK);
+
+ root = dir->i_sb->s_root;
+ /*record old_dentry path*/
+ p_name = buffer + sizeof(struct update_record);
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+ if (rc < 0)
+ GOTO(exit, rc);
+
+ buffer_length += rc;
+ p_name += buffer_length;
+
+ /*record new_dentry path*/
+ rc = smfs_log_path(root, new_dentry, p_name,
+ PAGE_SIZE - rc - sizeof(int));
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+ RETURN(rc);
}
-static inline char *log_dentry_version(char *buf, struct dentry *dentry)
+static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- 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));
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ int flag = *((int*)data1);
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name;
+ int rc = 0, buffer_length = 0;
+ char fidname[LL_FID_NAMELEN];
+ struct dentry *new_child = NULL;
+ int namelen;
+ ENTRY;
+
+ sinfo = S2SMI(dentry->d_inode->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, dir, REINT_UNLINK);
+
+ p_name = buffer + sizeof(struct update_record);
+
+ root = dir->i_sb->s_root;
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+ if (rc < 0)
+ GOTO(exit, rc);
+
+ buffer_length += rc;
+ p_name += rc;
+
+ if (!flag) {
+ /*unlink the inode*/
+ namelen = ll_fid2str(fidname, dentry->d_inode->i_ino,
+ dentry->d_inode->i_generation);
+
+ down(&sinfo->smsi_delete_dir->d_inode->i_sem);
+ new_child = lookup_one_len(fidname, sinfo->smsi_delete_dir, namelen);
+ if (new_child->d_inode != NULL) {
+ CERROR("has been deleted obj dentry %lu:%u!\n",
+ dentry->d_inode->i_ino,
+ dentry->d_inode->i_generation);
+ LBUG();
+ }
+
+ /* FIXME-WANGDI: this is ugly, but I do not know how to resolve
+ * it. */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ up(&dir->i_zombie);
+#endif
+ lock_kernel();
+ SMFS_CLEAN_INODE_REC(dir);
+ rc = vfs_rename(dir, dentry, sinfo->smsi_delete_dir->d_inode,
+ new_child);
+ SMFS_SET_INODE_REC(dir);
+ unlock_kernel();
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ down(&dir->i_zombie);
+#endif
+ up(&sinfo->smsi_delete_dir->d_inode->i_sem);
+ if (rc)
+ GOTO(exit, rc);
+ /* in vfs_unlink the inode on the dentry will be deleted, so we
+ * should delete it from dentry hash. */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ list_del_init(&dentry->d_hash);
+#else
+ hlist_del_init(&dentry->d_hash);
+#endif
+
+ /* put the new_file_name to the log. */
+ rc = smfs_log_path(root, dentry, p_name,
+ PAGE_SIZE - buffer_length);
+ if (rc < 0)
+ GOTO(exit, rc);
+ buffer_length += rc;
+ rc = 0;
+ } else {
+ /*only decrease the link count*/
+ namelen = sizeof(ino_t);
+
+ buffer_length += log_it(p_name + buffer_length,
+ &(dentry->d_inode->i_ino), namelen);
+ SET_REC_DEC_LINK_FLAGS(rec->ur_flags, SMFS_DEC_LINK);
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (new_child);
+ dput(new_child);
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+
+ RETURN(rc);
}
-
-static inline char *log_version(char *buf, struct smfs_version *pv)
+
+static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- 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));
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ struct inode *new_dir = (struct inode *)data1;
+ struct dentry *new_dentry = (struct dentry *)data2;
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name = NULL;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dir->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, dir, REINT_RENAME);
+
+ root = dir->i_sb->s_root;
+ /*record old_dentry path*/
+ p_name = buffer + sizeof(struct update_record);
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+ if (rc < 0)
+ GOTO(exit, rc);
+
+ buffer_length += rc;
+ p_name += rc;
+
+ root = new_dir->i_sb->s_root;
+ /*record new_dentry path*/
+ rc = smfs_log_path(root, new_dentry, p_name,
+ PAGE_SIZE - rc - sizeof(int));
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+ RETURN(rc);
}
-static inline char *journal_log_suffix(char *buf, char *log,
- struct dentry *dentry)
+
+static int smfs_post_rec_setattr(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- 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));
-}
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ struct iattr *attr = (struct iattr *)data1;
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dentry->d_inode->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
-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)
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, attr, REINT_SETATTR);
+
+ root = dentry->d_inode->i_sb->s_root;
+ /*record old_dentry path*/
+ p_name = buffer + sizeof(struct update_record);
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+ RETURN(rc);
+}
+static int smfs_post_rec_open_close(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- int rc = 0;
- /*should pack the record and dispatch it
- *create llog handle write to the log*/
- return rc;
+ struct smfs_super_info *sinfo;
+ struct dentry *root;
+ int open = *(int*)data1;
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dentry->d_inode->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+ rec = (struct update_record*)buffer;
+ if (open)
+ smfs_rec_pack(rec, dentry->d_inode, NULL, REINT_OPEN);
+ else
+ smfs_rec_pack(rec, dentry->d_inode, NULL, REINT_CLOSE);
+ root = dentry->d_inode->i_sb->s_root;
+ /*record old_dentry path*/
+ p_name = buffer + sizeof(struct update_record);
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+ RETURN(rc);
}
-int smfs_journal_mkdir(struct dentry *dentry,
- struct smfs_version *tgt_dir_ver,
- struct smfs_version *new_dir_ver,
- int mode)
+static int smfs_post_rec_write(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2)
{
- int opcode = KML_OPCODE_MKDIR;
- char *buffer, *path, *logrecord, record[292];
+ struct smfs_record_extents extents;
+ struct smfs_super_info *sinfo;
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);
+ struct update_record *rec = NULL;
+ char *buffer = NULL, *p_name;
+ int extents_length = 0;
+ int rc = 0, buffer_length = 0;
+ ENTRY;
+
+ sinfo = S2SMI(dentry->d_inode->i_sb);
+ if (!sinfo)
+ RETURN(-EINVAL);
+
+ OBD_ALLOC(buffer, PAGE_SIZE + sizeof(struct update_record));
+ if (!buffer)
+ GOTO(exit, rc = -ENOMEM);
+ rec = (struct update_record*)buffer;
+
+ smfs_rec_pack(rec, dentry->d_inode, NULL, REINT_OPEN);
+
+ root = dentry->d_inode->i_sb->s_root;
+ /*record old_dentry path*/
+ p_name = buffer + sizeof(struct update_record);
+ rc = smfs_log_path(root, dentry, p_name, PAGE_SIZE);
+
+ if (rc < 0) {
+ GOTO(exit, rc);
+ } else {
+ buffer_length += rc;
+ rc = 0;
+ }
+ /*record the extents of this write*/
+ extents.sre_count = *((size_t*)data1);
+ extents.sre_off = *((loff_t*)data2);
+ extents_length = sizeof(struct smfs_record_extents);
+
+ buffer_length += log_it(p_name + buffer_length,
+ &extents, extents_length);
+ rec->ur_len = sizeof(struct update_record) + buffer_length;
+ rc = smfs_llog_add_rec(sinfo, (void*)buffer, rec->ur_len);
+exit:
+ if (buffer)
+ OBD_FREE(buffer, PAGE_SIZE + sizeof(struct update_record));
+ RETURN(rc);
+}
+
+typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
+ void *data1, void *data2);
+
+static post_kml_rec smfs_kml_post[REINT_MAX + 1] = {
+ [REINT_SETATTR] smfs_post_rec_setattr,
+ [REINT_CREATE] smfs_post_rec_create,
+ [REINT_LINK] smfs_post_rec_link,
+ [REINT_UNLINK] smfs_post_rec_unlink,
+ [REINT_RENAME] smfs_post_rec_rename,
+ [REINT_OPEN] smfs_post_rec_open_close,
+ [REINT_CLOSE] smfs_post_rec_open_close,
+ [REINT_WRITE] smfs_post_rec_write,
+};
+
+int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
+ void *data1, void *data2, int op)
+{
+ return smfs_kml_post[op](dir, dst_dentry, data1, data2);
}
+++ /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
-
-/*
- * smfs/kml.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
-#include "kml_idl.h"
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include "smfs_internal.h"
/*FIXME there should be more conditions in this check*/
-int smfs_do_kml(struct inode *dir)
+int smfs_do_rec(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+
+ if (SMFS_DO_REC(smfs_info) && SMFS_INIT_REC(smfs_info) &&
+ SMFS_DO_INODE_REC(inode))
+ return 1;
+ return 0;
+}
+
+int smfs_rec_init(struct super_block *sb)
+{
+ struct smfs_super_info *smfs_info = S2SMI(sb);
+ int rc = 0;
+
+ SMFS_SET_REC(smfs_info);
+
+ RETURN(rc);
+}
+
+int smfs_rec_cleanup(struct super_block *sb)
{
- struct smfs_super_info *smfs_info = S2SMI(dir->i_sb);
-
- if (smfs_info->flags & SM_DO_KML) {
- return 1;
- }
- return 0;
+ int rc = 0;
+
+ SMFS_CLEAN_REC(S2SMI(sb));
+ RETURN(rc);
}
-void smfs_getversion(struct smfs_version * smfs_version,
- struct inode * inode)
+
+void reint_rec_free(struct reint_record *reint_rec)
{
- smfs_version->sm_mtime = (__u64)inode->i_mtime;
- smfs_version->sm_ctime = (__u64)inode->i_ctime;
- smfs_version->sm_size = (__u64)inode->i_size;
+ if (reint_rec) {
+ if (reint_rec->rec_data1)
+ OBD_FREE(reint_rec->rec_data1,
+ reint_rec->rec1_size + 1);
+ if (reint_rec->rec_data2)
+ OBD_FREE(reint_rec->rec_data2,
+ reint_rec->rec2_size + 1);
+
+ OBD_FREE(reint_rec, sizeof(struct reint_record));
+ }
}
-int smfs_kml_init(struct super_block *sb)
+static inline void copy_inode_attr(struct iattr *iattr, struct inode *inode)
{
- struct smfs_super_info *smfs_info = S2SMI(sb);
- int rc = 0;
- smfs_info->flags |= SM_DO_KML;
+ iattr->ia_mode = inode->i_mode;
+ iattr->ia_uid = inode->i_uid;
+ iattr->ia_gid = inode->i_gid;
+ iattr->ia_atime = inode->i_atime;
+ iattr->ia_ctime = inode->i_ctime;
+ iattr->ia_mtime = inode->i_mtime;
+ iattr->ia_size = inode->i_size;
+}
- rc = smfs_llog_setup(&smfs_info->kml_llog);
+void smfs_rec_pack(struct update_record *rec, struct inode *dst,
+ void *data, int op)
+{
+ rec->ur_fsuid = current->fsuid;
+ rec->ur_fsgid = current->fsgid;
+ rec->ur_rdev = dst->i_rdev;
+ rec->ur_opcode = op;
+ copy_inode_attr(&rec->ur_iattr, dst);
+ if (data) {
+ switch (op) {
+ case REINT_CREATE:
+ case REINT_LINK:
+ case REINT_UNLINK:
+ case REINT_RENAME: {
+ struct inode *dir = (struct inode *)data;
+ copy_inode_attr(&rec->ur_pattr, dir);
+ break;
+ }
+ case REINT_SETATTR: {
+ struct iattr *attr = (struct iattr *)data;
+ memcpy(&rec->ur_pattr, attr, sizeof(struct iattr));
+ break;
+ }
+ }
+ }
+}
- RETURN(rc);
+static inline void unpack_attr(struct reint_record *r_rec,
+ struct update_record *u_rec)
+{
+ memcpy(&r_rec->u_rec, u_rec, sizeof(struct update_record));
}
-int post_kml_mkdir(struct inode *dir, struct dentry *dentry)
+static inline int unpack_rec_data(char **p_buffer, int *size,
+ char *in_data, char *args_data)
{
- struct smfs_version tgt_dir_ver, new_dir_ver;
- int error;
+ int args_len = 0;
+ int rc = 0;
+ ENTRY;
+
+ if (args_data)
+ args_len = strlen(args_data);
+
+ *size = *((int*)(in_data));
+ rc = *size + sizeof(int);
- smfs_getversion(&tgt_dir_ver, dir);
+ OBD_ALLOC(*p_buffer, *size + args_len + 1);
+ if (!*p_buffer)
+ RETURN(-ENOMEM);
+ /*First copy reint dir */
+ if (args_data)
+ memcpy(*p_buffer, args_data, args_len);
- 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;
+ /*then copy the node name */
+ memcpy(*p_buffer + args_len,
+ (in_data + sizeof(int)), *size);
+
+ *size += args_len;
+
+ RETURN(rc);
}
+int smfs_rec_unpack(struct smfs_proc_args *args, struct reint_record *r_rec,
+ char *rec_buf)
+{
+ struct update_record *u_rec = (struct update_record *)rec_buf;
+ int rc = 0, length = 0;
+ ENTRY;
+ /*FIXME wangdi, there unpack are so smiliar that
+ *we will put it together later*/
+
+ if (SMFS_DO_WRITE_KML(args->sr_flags))
+ SET_REC_WRITE_KML_FLAGS(r_rec->u_rec.ur_flags, SMFS_WRITE_KML);
+ unpack_attr(r_rec, u_rec);
+ length += sizeof(struct update_record);
+ rc = unpack_rec_data(&r_rec->rec_data1, &r_rec->rec1_size,
+ (rec_buf + length), args->sr_data);
+ switch (u_rec->ur_opcode) {
+ case REINT_OPEN:
+ case REINT_CLOSE:
+ /*record src path which will be passed to reint and undo*/
+ rc = unpack_rec_data(&r_rec->rec_data2, &r_rec->rec2_size,
+ (rec_buf + length), NULL);
+ break;
+ case REINT_LINK:
+ case REINT_RENAME:
+ case REINT_SETATTR:
+ case REINT_UNLINK:
+ case REINT_CREATE:
+ case REINT_WRITE: {
+ length += rc;
+ if (length < u_rec->ur_len) {
+ char *pre_name;
+ if (u_rec->ur_opcode == REINT_CREATE ||
+ u_rec->ur_opcode == REINT_WRITE ||
+ (u_rec->ur_opcode == REINT_UNLINK &&
+ SMFS_DO_DEC_LINK(r_rec->u_rec.ur_flags)))
+ pre_name = NULL;
+ else
+ pre_name = args->sr_data;
+
+ rc = unpack_rec_data(&r_rec->rec_data2,
+ &r_rec->rec2_size,
+ (rec_buf + length), pre_name);
+ }
+ break;
+ }
+ }
+ if (rc > 0)
+ rc = 0;
+
+ RETURN(rc);
+}
+
+int smfs_start_rec(struct super_block *sb)
+{
+ struct dentry *dentry;
+ struct lvfs_run_ctxt saved;
+ int rc = 0;
+ ENTRY;
+
+ if (SMFS_INIT_REC(S2SMI(sb)) ||
+ (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
+ RETURN(rc);
+
+ rc = smfs_llog_setup(sb);
+ if (rc)
+ RETURN(rc);
+
+ push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+ dentry = simple_mkdir(current->fs->pwd, "DELETE", 0777, 1);
+ if (IS_ERR(dentry)) {
+ rc = PTR_ERR(dentry);
+ CERROR("cannot create LOGS directory: rc = %d\n", rc);
+ GOTO(err_exit, rc = -EINVAL);
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (list_empty(&dentry->d_hash))
+ d_rehash(dentry);
+#else
+ /* FIXME-WANGDI: here should be be something. */
+#endif
+
+ if (!rc)
+ SMFS_SET_INIT_REC(S2SMI(sb));
+ S2SMI(sb)->smsi_delete_dir = dentry;
+exit:
+ pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
+ RETURN(rc);
+err_exit:
+ if (S2SMI(sb)->smsi_ctxt)
+ OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
+ goto exit;
+}
+
+int smfs_stop_rec(struct super_block *sb)
+{
+ int rc = 0;
+ ENTRY;
+
+ if (!SMFS_INIT_REC(S2SMI(sb)) ||
+ (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
+ RETURN(rc);
+
+ rc = smfs_llog_cleanup(sb);
+
+ SMFS_CLEAN_INIT_REC(S2SMI(sb));
+
+ if (S2SMI(sb)->smsi_delete_dir) {
+ l_dput(S2SMI(sb)->smsi_delete_dir);
+ S2SMI(sb)->smsi_delete_dir = NULL;
+ }
+ RETURN(rc);
+}
+
+int smfs_process_rec(struct super_block *sb, int count, char *dir, int flags)
+{
+ struct llog_ctxt *ctxt;
+ struct llog_handle *loghandle;
+ struct smfs_proc_args args;
+ int rc = 0;
+ ENTRY;
+
+ if (!SMFS_INIT_REC(S2SMI(sb))) {
+ CWARN("Did not start up rec server \n");
+ RETURN(rc);
+ }
+
+ memset(&args, 0, sizeof(struct smfs_proc_args));
+ args.sr_sb = sb;
+ args.sr_count = count;
+ args.sr_data = dir;
+ args.sr_flags = flags ;
+ ctxt = S2SMI(sb)->smsi_rec_log;
+ loghandle = ctxt->loc_handle;
+
+ if (count == 0) {
+ if (SMFS_DO_REINT_REC(flags)) {
+ struct llog_gen_rec *lgr;
+
+ /*For reint rec, we need insert
+ *a gen rec to identify the end
+ *of the rec.*/
+ OBD_ALLOC(lgr, sizeof(*lgr));
+ if (!lgr)
+ RETURN(-ENOMEM);
+ lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len =
+ sizeof(*lgr);
+ lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
+ lgr->lgr_gen = ctxt->loc_gen;
+ rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1, NULL);
+ OBD_FREE(lgr, sizeof(*lgr));
+ if (rc != 1)
+ RETURN(rc);
+ }
+ } else {
+ SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
+ }
+ if (loghandle) {
+ if (SMFS_DO_REINT_REC(flags))
+ rc = llog_cat_process(loghandle, ctxt->loc_proc_cb,
+ (void *)&args);
+ else
+ rc = llog_cat_reverse_process(loghandle,
+ ctxt->loc_proc_cb,
+ (void *)&args);
+ if (rc == LLOG_PROC_BREAK)
+ rc = 0;
+ }
+ RETURN(rc);
+}
+++ /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
-
-
-/*
- * snapfs/options.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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_SM
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
+#include <linux/lustre_smfs.h>
+#include "smfs_internal.h"
static struct list_head option_list;
-char *options = NULL;
-char *opt_left = NULL;
+static char *options = NULL;
+static 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;
+ INIT_LIST_HEAD(&option_list);
+ OBD_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);
+ struct option *option;
+ while (!list_empty(&option_list)) {
+ option = list_entry(option_list.next, struct option, list);
+ list_del(&option->list);
+ OBD_FREE(option->opt, strlen(option->opt) + 1);
+ if (option->value)
+ OBD_FREE(option->value, strlen(option->value) + 1);
+ OBD_FREE(option, sizeof(struct option));
+ }
+ OBD_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;
+ char *name, *value, *left, *tmp;
+ struct option *tmp_opt;
+ int length = 0;
- *pos = opt_left;
+ *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);
- }
+ 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;
+ OBD_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++;
+ tmp = opt_left;
+ while(tmp != left && *tmp != '=') {
+ length++;
+ tmp++;
+ }
+ OBD_ALLOC(name, length + 1);
+ tmp_opt->opt = name;
+ 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;
+ if (*tmp == '=') {
+ /*this option has value*/
+ opt_left ++; /*after '='*/
+ if (left == opt_left) {
+ OBD_FREE(tmp_opt->opt, strlen(tmp_opt->opt) + 1);
+ OBD_FREE(tmp_opt, sizeof(struct option));
+ opt_left = *pos;
+ return -EINVAL;
+ }
+ length = left - opt_left;
+ OBD_ALLOC(value, length + 1);
+ if (!value) {
+ OBD_FREE(tmp_opt->opt, strlen(tmp_opt->opt) + 1);
+ OBD_FREE(tmp_opt, sizeof(struct option));
+ return -ENOMEM;
+ }
+ tmp_opt->value = value;
+ 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"
-
-/*
- * fs/smfs/sm_fs.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
*
- * A storage management file system.
+ * Copyright (C) 2004 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 EXPORT_SYMTAB
+
#define DEBUG_SUBSYSTEM S_SM
-
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/unistd.h>
#include <linux/miscdevice.h>
-#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_smfs.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");
-
+MODULE_LICENSE("GPL");
+
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_psdev()) ) {
+ printk("Error initializing smfs_psdev, %d\n", err);
+ return -EINVAL;
+ }
+
if ( (err = init_smfs()) ) {
- printk("Error initializing snapfs, %d\n", err);
+ printk("Error initializing smfs, %d\n", err);
return -EINVAL;
}
-
+
if ( (err = init_smfs_proc_sys()) ) {
- printk("Error initializing snapfs proc sys, %d\n", err);
+ printk("Error initializing smfs proc sys, %d\n", err);
return -EINVAL;
}
-
+
return 0;
}
-
+
static void __exit smfs_cleanup(void)
{
- cleanup_smfs();
+ cleanup_smfs();
+ smfs_cleanup_psdev();
}
module_init(smfs_init);
module_exit(smfs_cleanup);
-
#ifndef __LINUX_SMFS_H
#define __LINUX_SMFS_H
-struct smfs_inode_info {
- struct inode *smi_inode;
-};
+#include <linux/lustre_fsfilt.h>
+#define SMFSDEV_NAME "/dev/smfsconf"
+#define SMFS_PSDEV_MINOR 250
+#define SMFS_PSDEV_MAJOR 10
-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;
+struct option {
+ char *opt;
+ char *value;
+ struct list_head list;
};
-#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 smfs_control_device {
+ struct list_head smfs_dev_list;
};
-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;
+#define SMFS_TYPE "smfs"
+#define IOC_SMFS_START _IOWR('s', 41, long)
+#define IOC_SMFS_STOP _IOWR('s', 42, long)
+#define IOC_SMFS_REINT _IOWR('s', 43, long)
+#define IOC_SMFS_UNDO _IOWR('s', 44, long)
+#ifdef __KERNEL__
+
+struct smfs_proc_args {
+ struct super_block *sr_sb;
+ int sr_count;
+ int sr_flags;
+ void *sr_data;
};
-struct option {
- char *opt;
- char *value;
- struct list_head list;
-};
+
+
+#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 KML_LOG_NAME "kml_rec"
+
+#define MYPATHLEN(buffer, path) ((buffer) + PAGE_SIZE - (path))
+
+#define SMFS_KML_POST(dir, dentry, data1, data2, op, name, rc, label) \
+do { \
+ if(smfs_do_rec(dir) && !rc) { \
+ CDEBUG(D_INODE, "Do %s kml post for dir %lu \n", \
+ name, dir->i_ino); \
+ rc = smfs_post_kml_rec(dir, dentry, data1, data2, op); \
+ if (rc) \
+ GOTO(label, rc); \
+ } \
+} while(0)
extern int init_smfs_proc_sys(void);
/*options.c*/
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);
+extern void sm_set_inode_ops(struct inode *cache_inode, struct inode *inode);
+extern void sm_set_sb_ops(struct super_block *cache_sb, struct super_block *sb);
+extern void init_smfs_cache(void);
+extern void cleanup_smfs_cache(void);
+extern void sm_set_journal_ops(struct super_block *sb, char *cache_type);
+extern int smfs_init_sm_ops(struct smfs_super_info *smb);
+extern void smfs_cleanup_sm_ops(struct smfs_super_info *smb);
+static inline struct super_operations *cache_sops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_sb_ops;
+}
+static inline struct inode_operations *cache_diops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_dir_iops;
+}
+static inline struct inode_operations *cache_fiops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_file_iops;
+}
+static inline struct inode_operations *cache_siops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_sym_iops;
+}
+static inline struct file_operations *cache_dfops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_dir_fops;
+}
+static inline struct file_operations *cache_ffops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_file_fops;
+}
+static inline struct file_operations *cache_sfops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_sym_fops;
+}
+static inline struct dentry_operations *cache_dops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_dentry_ops;
+}
+static inline struct journal_operations *journal_ops(struct smfs_super_info *smb)
+{
+ return &smb->sm_ops->sm_journal_ops;
+}
/*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);
+extern struct super_block *smfs_get_sb_by_path(char *path, int len);
+extern struct vfsmount* get_vfsmount(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);
+extern struct inode_operations smfs_dir_iops;
+extern struct file_operations smfs_dir_fops;
/*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 struct inode_operations smfs_file_iops;
+extern struct file_operations smfs_file_fops;
+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_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);
+ 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);
+extern int smfs_open(struct inode * inode, struct file * filp);
+extern int smfs_release(struct inode * inode, struct file * filp);
+/*inode.c*/
+extern struct super_operations smfs_super_ops;
+/*symlink.c*/
+extern struct inode_operations smfs_sym_iops;
+extern struct file_operations smfs_sym_fops;
/*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;
+extern void *smfs_trans_start(struct inode *inode, int op, void *desc_private);
+extern void smfs_trans_commit(struct inode *inode, void *handle,
+ int force_sync);
+extern int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
+ void *data1, void *data2, int op);
/*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);
+extern int smfs_do_rec(struct inode *inode);
+extern int smfs_rec_cleanup(struct super_block *sb);
+extern int smfs_rec_init(struct super_block *sb);
+extern int smfs_rec_unpack(struct smfs_proc_args *args,
+ struct reint_record *u_rec, char *rec_buf);
+extern int smfs_start_rec(struct super_block *sb);
+extern int smfs_stop_rec(struct super_block *sb);
+extern int smfs_process_rec(struct super_block *sb, int count, char *dir,
+ int flags);
+void reint_rec_free(struct reint_record *reint_rec);
+
+extern void smfs_rec_pack(struct update_record *rec, struct inode *dst,
+ void *data, int op);
/*smfs_llog.c*/
-extern int smfs_llog_setup(struct llog_ctxt **ctxt);
+extern int smfs_llog_setup(struct super_block *sb);
+extern int smfs_llog_cleanup(struct super_block *sb);
+extern int smfs_llog_add_rec(struct smfs_super_info * sinfo, void *data,
+ int data_size);
+/*ioctl.c*/
+extern int init_smfs_psdev(void);
+extern void smfs_cleanup_psdev(void);
+
+/* cache_space.c */
+extern int do_cache_manage;
+struct cache_purge_queue {
+ wait_queue_head_t cpq_waitq;
+ struct super_block *cpq_sb;
+ struct llog_handle *cpq_loghandle;
+ __u32 cpq_flags;
+ struct completion cpq_comp;
+};
+
+/* opcodes */
+#define CACHE_SPACE_INSERT 0x1
+#define CACHE_SPACE_DELETE 0x2
+#define CACHE_SPACE_COMMIT 0x4
+
+#define CACHE_LRU_LOG "CACHE_LRU_LIST"
+
+extern int smfs_cache_hook(struct inode *inode);
+extern void cache_space_pre(struct inode *inode, int op);
+extern int cache_space_post(int op, void *handle, struct inode *old_dir,
+ struct dentry *old_dentry, struct inode *new_dir,
+ struct dentry *new_dentry);
+
+extern int cache_space_hook_setup(struct super_block *);
+extern int cache_space_hook_cleanup(void);
+extern int cache_space_hook_init(struct super_block *);
+extern int cache_space_hook_exit(struct super_block *);
+
+#define XATTR_SMFS_HOARD_MARK "hoard"
+#define XATTR_SMFS_CACHE_LOGCOOKIE "cache"
+#define XATTR_SMFS_ACTIVE_ENTRY "entry"
+
+#define SMFS_TRANS_OP(inode, op) \
+{ \
+ if (smfs_do_rec(inode)) \
+ op = op | 0x10; \
+ if (smfs_cache_hook(inode)) \
+ op = op | 0x20; \
+}
+
+static inline int set_hoard_priority(struct inode *inode, void *handle,
+ __u32 *hoard)
+{
+ struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
+ int rc;
+
+ rc = fsops->fs_set_xattr(inode, handle, XATTR_SMFS_HOARD_MARK,
+ hoard, sizeof(__u32));
+ RETURN(rc);
+}
+
+static inline int get_hoard_priority(struct inode *inode, __u32 *hoard)
+{
+ struct fsfilt_operations *fsops = I2CSB(inode)->sm_fsfilt;
+ int rc;
+
+ rc = fsops->fs_get_xattr(inode, XATTR_SMFS_HOARD_MARK,
+ hoard, sizeof(__u32));
+ RETURN(rc);
+}
+
+static inline int set_active_entry(struct inode *dir, __u64 *active_entry,
+ void *handle)
+{
+ struct fsfilt_operations *fsops = I2CSB(dir)->sm_fsfilt;
+ int rc;
+ *active_entry = cpu_to_le64(*active_entry);
+ rc = fsops->fs_set_xattr(dir, handle, XATTR_SMFS_ACTIVE_ENTRY,
+ active_entry, sizeof(__u64));
+ RETURN(rc);
+}
+static inline int get_active_entry(struct inode *dir, __u64 *active_entry)
+{
+ struct fsfilt_operations *fsops = I2CSB(dir)->sm_fsfilt;
+ int rc = fsops->fs_get_xattr(dir, XATTR_SMFS_ACTIVE_ENTRY,
+ active_entry, sizeof(__u64));
+ *active_entry = le64_to_cpu(*active_entry);
+ if (rc >= 0)
+ rc = 0;
+ RETURN(rc);
+}
+
+#define CACHE_HOOK_CREATE 1
+#define CACHE_HOOK_LOOKUP 2
+#define CACHE_HOOK_LINK 3
+#define CACHE_HOOK_UNLINK 4
+#define CACHE_HOOK_SYMLINK 5
+#define CACHE_HOOK_MKDIR 6
+#define CACHE_HOOK_RMDIR 7
+#define CACHE_HOOK_MKNOD 8
+#define CACHE_HOOK_RENAME 9
+
+#define CACHE_HOOK_MAX 9
+
+#define SMFS_CACHE_HOOK_PRE(op, handle, dir) \
+{ \
+ if (smfs_cache_hook(dir)) { \
+ LASSERT(handle != NULL); \
+ CDEBUG(D_INODE, "cache hook pre: op %d, dir %lu\n", \
+ op, dir->i_ino); \
+ cache_space_pre(dir, op); \
+ } \
+}
+
+#define SMFS_CACHE_HOOK_POST(op, handle, old_dir, old_dentry, \
+ new_dir, new_dentry, rc, label) \
+{ \
+ if (!rc && smfs_cache_hook(old_dir)) { \
+ LASSERT(handle != NULL); \
+ CDEBUG(D_INODE, "cache hook post: op %d, dir %lu\n", \
+ op, old_dir->i_ino); \
+ rc = cache_space_post(op, handle, old_dir, old_dentry, \
+ new_dir, new_dentry); \
+ if (rc) \
+ GOTO(label, rc); \
+ } \
+}
+
+#endif /*__KERNEL*/
#endif /* __LINUX_SMFS_H */
-/*
- * llog.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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_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 <linux/lustre_log.h>
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include <linux/lvfs.h>
#include "smfs_internal.h"
-int smfs_llog_setup(struct llog_ctxt **p_ctxt)
+static int smfs_llog_process_rec_cb(struct llog_handle *handle,
+ struct llog_rec_hdr *rec, void *data)
{
- int rc = 0;
-
+ struct reint_record *reint_rec;
+ char *rec_buf ;
+ struct smfs_proc_args *args = (struct smfs_proc_args *)data;
+ struct lvfs_run_ctxt saved;
+ int rc = 0;
+ ENTRY;
+
+ if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
+ CERROR("log is not plain\n");
+ RETURN(-EINVAL);
+ }
+
+ if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
+ struct llog_cookie cookie;
+
+ cookie.lgc_lgl = handle->lgh_id;
+ cookie.lgc_index = le32_to_cpu(rec->lrh_index);
+
+ llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
+ RETURN(LLOG_PROC_BREAK);
+ }
+
+ if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
+ RETURN(-EINVAL);
+
+ rec_buf = (char*) (rec + 1);
+
+ OBD_ALLOC(reint_rec, sizeof(struct reint_record));
+ if (!reint_rec)
+ RETURN(-ENOMEM);
+
+ rc = smfs_rec_unpack(args, reint_rec, rec_buf);
+ if (rc)
+ GOTO(exit, rc = -ENOMEM);
+
+ if (!S2SMI(args->sr_sb)->smsi_ctxt)
+ GOTO(exit, rc = -ENODEV);
+
+ push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
+ if (SMFS_DO_REINT_REC(args->sr_flags))
+ rc = lvfs_reint(args->sr_sb, reint_rec);
+ else
+ rc = lvfs_undo(args->sr_sb, reint_rec);
+
+ if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
+ args->sr_count --;
+ if (args->sr_count == 0)
+ rc = LLOG_PROC_BREAK;
+ }
+ pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
+exit:
+ reint_rec_free(reint_rec);
RETURN(rc);
-}
+}
+
+int smfs_llog_setup(struct super_block *sb)
+{
+ struct llog_ctxt **ctxt = &(S2SMI(sb)->smsi_rec_log);
+ struct lvfs_run_ctxt saved;
+ struct lvfs_run_ctxt *current_ctxt = NULL;
+ struct vfsmount *mnt;
+ struct dentry *dentry;
+ int rc = 0, rc2;
+ ENTRY;
+
+ /* create OBJECTS and LOGS for writing logs */
+ S2SMI(sb)->sm_cache_fsfilt->fs_setup(sb);
+ OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
+ if (!current_ctxt)
+ RETURN(-ENOMEM);
+ mnt = get_vfsmount(sb);
+ if (!mnt)
+ GOTO(err_exit, rc = -EINVAL);
+ OBD_SET_CTXT_MAGIC(current_ctxt);
+ current_ctxt->pwdmnt = mnt;
+ current_ctxt->pwd = mnt->mnt_root;
+ current_ctxt->fs = get_ds();
+ S2SMI(sb)->smsi_ctxt = current_ctxt;
+ push_ctxt(&saved, current_ctxt, NULL);
+ dentry = simple_mkdir(current->fs->pwd, "LOGS", 0777, 1);
+ if (IS_ERR(dentry)) {
+ rc = PTR_ERR(dentry);
+ CERROR("cannot create LOGS directory: rc = %d\n", rc);
+ GOTO(err_exit, rc = -EINVAL);
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (list_empty(&dentry->d_hash))
+ d_rehash(dentry);
+#else
+ /* FIXME-WANGDI: here should be something. */
+#endif
+
+ S2SMI(sb)->smsi_logs_dir = dentry;
+ dentry = simple_mkdir(current->fs->pwd, "OBJECTS", 0777, 1);
+ if (IS_ERR(dentry)) {
+ rc = PTR_ERR(dentry);
+ CERROR("cannot create OBJECTS directory: rc = %d\n", rc);
+ GOTO(err_exit, rc = -EINVAL);
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (list_empty(&dentry->d_hash))
+ d_rehash(dentry);
+#else
+ /* FIXME-WANGDI: here should be something. */
+#endif
+ S2SMI(sb)->smsi_objects_dir = dentry;
+ pop_ctxt(&saved, current_ctxt, NULL);
+
+ /* write log will not write to KML, cleanup kml flags */
+ SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_objects_dir->d_inode);
+ SMFS_CLEAN_INODE_REC(S2SMI(sb)->smsi_logs_dir->d_inode);
+
+ /* log create does not call cache hooks, cleanup hook flags */
+ SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_objects_dir->d_inode);
+ SMFS_CLEAN_INODE_CACHE_HOOK(S2SMI(sb)->smsi_logs_dir->d_inode);
+
+ if (SMFS_DO_REC(S2SMI(sb))) {
+ rc = llog_catalog_setup(ctxt, KML_LOG_NAME, current_ctxt,
+ S2SMI(sb)->sm_fsfilt,
+ S2SMI(sb)->smsi_logs_dir,
+ S2SMI(sb)->smsi_objects_dir);
+ (*ctxt)->loc_proc_cb = smfs_llog_process_rec_cb;
+ }
+
+ if (SMFS_CACHE_HOOK(S2SMI(sb))) {
+ rc2 = cache_space_hook_setup(sb);
+ if (!rc && rc2)
+ rc = rc2;
+ }
+exit:
+ RETURN(rc);
+err_exit:
+ if (current_ctxt)
+ OBD_FREE(current_ctxt, sizeof(*current_ctxt));
+ goto exit;
+}
+
+int smfs_llog_cleanup(struct super_block *sb)
+{
+ struct llog_ctxt *ctxt = S2SMI(sb)->smsi_rec_log;
+ int rc = 0, rc2;
+ ENTRY;
+
+ if (SMFS_CACHE_HOOK(S2SMI(sb)))
+ rc = cache_space_hook_cleanup();
+
+ if (SMFS_DO_REC(S2SMI(sb))) {
+ rc2 = llog_catalog_cleanup(ctxt);
+ if (!rc)
+ rc = rc2;
+ }
+
+ if (S2SMI(sb)->smsi_logs_dir) {
+ l_dput(S2SMI(sb)->smsi_logs_dir);
+ S2SMI(sb)->smsi_logs_dir = NULL;
+ }
+ if (S2SMI(sb)->smsi_objects_dir) {
+ l_dput(S2SMI(sb)->smsi_objects_dir);
+ S2SMI(sb)->smsi_objects_dir = NULL;
+ }
+
+ OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
+ RETURN(rc);
+}
+
+int smfs_llog_add_rec(struct smfs_super_info * sinfo, void *data, int data_size)
+{
+ struct llog_rec_hdr rec;
+ int rc = 0;
+ rec.lrh_len = size_round(data_size);
+ rec.lrh_type = SMFS_UPDATE_REC;
+ rc = llog_add(sinfo->smsi_rec_log,
+ &rec, data, NULL, 0, NULL);
+ if (rc != 1) {
+ CERROR("error adding kml rec: %d\n", rc);
+ RETURN(-EINVAL);
+ }
+ RETURN(0);
+}
+++ /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 */
-/*
- * snap_current
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
*
- * 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.
+ * Copyright (C) 2004 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.
*
- * Author: Peter J. Braam <braam@mountainviewdata.com>
*/
+
#define DEBUG_SUBSYSTEM S_SM
#include <linux/config.h>
#include <linux/utime.h>
#include <linux/file.h>
#include <linux/slab.h>
+#include <linux/dcache.h>
#include <linux/loop.h>
#include <linux/errno.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
+#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.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)
+static char *smfs_options(char *data, char **devstr, char **namestr,
+ int *kml, int *cache, char **opts,
+ int *iopen_nopriv)
{
- 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;
+ char *pos;
+ struct option *opt_value = NULL;
+
+ 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")) {
+ if (kml)
+ *kml = 1;
+ } else if (!strcmp(opt_value->opt, "cache")) {
+ if (cache)
+ *cache = 1;
+ } else if (!strcmp(opt_value->opt, "options")) {
+ if (opts != NULL)
+ *opts = opt_value->value;
+ } else if (!strcmp(opt_value->opt, "iopen_nopriv")) {
+ if (iopen_nopriv != NULL)
+ *iopen_nopriv = 1;
+ } else {
+ break;
+ }
+ }
+ return pos;
}
-static int set_loop_fd(char *dev_path, char *loop_dev)
+struct vfsmount *get_vfsmount(struct super_block *sb)
{
- 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);
+ 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;
}
-#define SIZE(a) (sizeof(a)/sizeof(a[0]))
-static char *find_unused_and_set_loop_device(char *dev_path)
+struct super_block *smfs_get_sb_by_path(char *path, int len)
{
- 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);
+ struct super_block *sb;
+ struct nameidata nd;
+ int error = 0;
+
+ ENTRY;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ if (path_init(path, LOOKUP_FOLLOW, &nd)) {
+#else
+ if (path_lookup(path, LOOKUP_FOLLOW, &nd)) {
+#endif
+ error = path_walk(path, &nd);
+ if (error) {
+ path_release(&nd);
+ RETURN(NULL);
+ }
+ } else {
+ RETURN(NULL);
+ }
+
+ /* FIXME-WANGDI: add some check code here. */
+ sb = nd.dentry->d_sb;
+ path_release(&nd);
+ RETURN(sb);
}
-#define MAX_LOOP_DEVICES 256
-static char *parse_path2dev(struct super_block *sb, char *dev_path)
+static int smfs_init_fsfilt_ops(struct super_block *sb)
{
- 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);
+ ENTRY;
+ if (!S2SMI(sb)->sm_cache_fsfilt) {
+ S2SMI(sb)->sm_cache_fsfilt =
+ fsfilt_get_ops(S2SMI(sb)->cache_fs_type);
+ if (!S2SMI(sb)->sm_cache_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by kml\n",
+ S2SMI(sb)->cache_fs_type);
+ RETURN(-EINVAL);
+ }
+ }
+ if (!S2SMI(sb)->sm_fsfilt) {
+ S2SMI(sb)->sm_fsfilt =
+ fsfilt_get_ops(S2SMI(sb)->fs_type);
+ if (!S2SMI(sb)->sm_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by kml\n",
+ S2SMI(sb)->fs_type);
+ RETURN(-EINVAL);
+ }
+ }
+ RETURN(0);
}
-void duplicate_sb(struct super_block *csb,
- struct super_block *sb)
+
+void smfs_cleanup_fsfilt_ops(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;
+ if (S2SMI(sb)->sm_cache_fsfilt)
+ fsfilt_put_ops(S2SMI(sb)->sm_cache_fsfilt);
+ if (S2SMI(sb)->sm_fsfilt)
+ fsfilt_put_ops(S2SMI(sb)->sm_fsfilt);
}
-extern struct super_operations smfs_super_ops;
-static int sm_mount_cache(struct super_block *sb,
- char *devstr,
- char *typestr)
+static int sm_mount_cache(struct super_block *sb, char *devstr,
+ char *typestr, char *opts, int iopen_nopriv)
{
- 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);
- }
+ struct smfs_super_info *smb;
+ int err = 0, typelen;
+ struct vfsmount *mnt;
+ unsigned long page;
+
+ ENTRY;
+
+ typelen = strlen(typestr);
+
+ page = __get_free_page(GFP_KERNEL);
+ if (!page)
+ 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);
+
+ if (iopen_nopriv)
+ sprintf((char *)page, "iopen_nopriv");
+
+ if (opts && strlen(opts)) {
+ int n = strlen((char *)page);
+ sprintf((char *)page + n, ",%s", opts);
+ }
+
+ printk("smfs: mounting %s at %s\n", typestr, devstr);
+
+ mnt = do_kern_mount(typestr, 0, devstr, (void *)page);
free_page(page);
-
- if (IS_ERR(mnt)) {
+
+ 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);
+ smb = S2SMI(sb);
+ smb->smsi_sb = mnt->mnt_sb;
+ smb->smsi_mnt = mnt;
+
+ smfs_init_sm_ops(smb);
+
+ OBD_ALLOC(smb->cache_fs_type, strlen(typestr) + 1);
+ memcpy(smb->cache_fs_type, typestr, strlen(typestr));
+
+ OBD_ALLOC(smb->fs_type, strlen(SMFS_TYPE) + 1);
+ memcpy(smb->fs_type, SMFS_TYPE, strlen(SMFS_TYPE));
+
+ duplicate_sb(sb, mnt->mnt_sb);
+ sm_set_sb_ops(mnt->mnt_sb, sb);
+ err = smfs_init_fsfilt_ops(sb);
err_out:
- if (dev_name)
- SM_FREE(dev_name, strlen(dev_name) + 2);
-
- return err;
+ return err;
}
+
static int sm_umount_cache(struct super_block *sb)
{
- struct smfs_super_info *smb = S2SMI(sb);
-
- mntput(smb->smsi_mnt);
-
- return 0;
+ struct smfs_super_info *smb = S2SMI(sb);
+
+ mntput(smb->smsi_mnt);
+ smfs_cleanup_sm_ops(smb);
+ smfs_cleanup_fsfilt_ops(sb);
+
+ if (smb->cache_fs_type)
+ OBD_FREE(smb->cache_fs_type, strlen(smb->cache_fs_type) + 1);
+
+ if (smb->fs_type)
+ OBD_FREE(smb->fs_type, strlen(smb->fs_type) + 1);
+
+ return 0;
}
+
void smfs_put_super(struct super_block *sb)
{
- if (sb)
- sm_umount_cache(sb);
- return;
+ if (SMFS_CACHE_HOOK(S2SMI(sb)))
+ cache_space_hook_exit(sb);
+
+ if (SMFS_DO_REC(S2SMI(sb)))
+ smfs_rec_cleanup(sb);
+
+ if (sb)
+ sm_umount_cache(sb);
+ return;
}
-struct super_block *
-smfs_read_super(
- struct super_block *sb,
- void *data,
- int silent)
+static int smfs_fill_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);
-
+ ino_t root_ino;
+ char *cache_data;
+
+ int iopen_nopriv = 0;
+ struct inode *root_inode = NULL;
+ int err = 0, do_rec = 0, cache_hook = 0;
+ char *devstr = NULL, *typestr = NULL, *opts = NULL;
+
+ ENTRY;
+
+ CDEBUG(D_SUPER, "mount opts: %s\n", data ?
+ (char *)data : "(none)");
+
+ init_option(data);
+
+ /* read and validate passed options. */
+ cache_data = smfs_options(data, &devstr, &typestr,
+ &do_rec, &cache_hook, &opts,
+ &iopen_nopriv);
+
+ if (*cache_data)
+ CWARN("smfs_fill_super(): options parsing stoped at "
+ "option %s\n", cache_data);
+
+ if (!typestr || !devstr) {
+ CERROR("mount options name and dev mandatory\n");
+ GOTO(out_err, err = -EINVAL);
+ }
+
+ err = sm_mount_cache(sb, devstr, typestr, opts,
+ iopen_nopriv);
+
+ if (err) {
+ CERROR("Can not mount %s as %s, rc = %d\n", devstr,
+ typestr, err);
+ GOTO(out_err, err);
+ }
+
+ if (do_rec)
+ smfs_rec_init(sb);
+
+ if (cache_hook)
+ cache_space_hook_init(sb);
+
+ 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) {
+ sm_umount_cache(sb);
+ GOTO(out_err, err = -EINVAL);
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
+ (ulong)sb, (ulong)&sb->u.generic_sbp);
+#else
+ CDEBUG(D_SUPER, "sb %lx, &sb->s_fs_info: %lx\n",
+ (ulong)sb, (ulong)&sb->s_fs_info);
+#endif
+
out_err:
- cleanup_option();
- if (err)
- return NULL;
- return sb;
+ cleanup_option();
+ return err;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static struct super_block *smfs_read_super(struct super_block *sb,
+ void *data, int silent)
+{
+ int err;
+
+ err = smfs_fill_super(sb, data, silent);
+ if (err)
+ return NULL;
+
+ return sb;
+}
+#else
+struct super_block *smfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ return get_sb_nodev(fs_type, flags, data, smfs_fill_super);
}
+#endif
-static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
+static struct file_system_type smfs_type = {
+ .owner = THIS_MODULE,
+ .name = "smfs",
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ .read_super = smfs_read_super,
+#else
+ .get_sb = smfs_get_sb,
+ .kill_sb = kill_anon_super,
+#endif
+};
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 err;
+
+ err = register_filesystem(&smfs_type);
+ if (err) {
+ CERROR("register_filesystem() failed, "
+ "rc = %d\n", err);
+ }
+ 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;
+ int err = 0;
+
+ err = unregister_filesystem(&smfs_type);
+ if (err) {
+ CERROR("unregister_filesystem() failed, "
+ "rc = %d\n", err);
+ }
+ return 0;
}
-/*
- * smfs/symlink.c
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
*
+ * Copyright (C) 2004 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_SNAP
+
+#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/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
+#include <linux/lustre_smfs.h>
-#include "smfs_internal.h"
+#include "smfs_internal.h"
-static int smfs_readlink(struct dentry * dentry, char * buffer, int buflen)
+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;
+ struct inode *cache_inode = I2CI(dentry->d_inode);
+ struct dentry *cache_dentry;
+ int rc = 0;
+ ENTRY;
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
- 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;
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
+ if (cache_inode->i_op && cache_inode->i_op->readlink)
+ rc = cache_inode->i_op->readlink(cache_dentry, buffer, buflen);
+ GOTO(exit, rc);
+exit:
+ post_smfs_dentry(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);
+ struct inode *cache_inode = I2CI(dentry->d_inode);
+ struct dentry *cache_dentry;
+ int rc = 0;
+ ENTRY;
- if (dentry->d_parent && dentry->d_parent->d_inode){
- cache_dir = I2CI(dentry->d_parent->d_inode);
- prepare_parent_dentry(&parent, cache_dir);
- }
+ if (!cache_inode)
+ RETURN(-ENOENT);
- cache_dentry = d_alloc(&parent, &dentry->d_name);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ if (!cache_dentry)
+ GOTO(exit, rc = -ENOMEM);
- 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;
+ if (cache_inode->i_op && cache_inode->i_op->follow_link)
+ rc = cache_inode->i_op->follow_link(cache_dentry, nd);
+exit:
+ post_smfs_dentry(cache_dentry);
+ return rc;
}
+
struct inode_operations smfs_sym_iops = {
- readlink: smfs_readlink,
- follow_link: smfs_follow_link,
- setxattr: smfs_setxattr, /* BKL held */
+ 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 */
-/*
- * Sysctrl entries for Snapfs
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2004 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.
+ *
*/
-/* /proc entries */
-
-#define DEBUG_SUBSYSTEM S_SNAP
+#define DEBUG_SUBSYSTEM S_SM
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/string.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/obd_class.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
-#include "smfs_internal.h"
+#include <linux/lustre_smfs.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;
*/
#define PSDEV_SMFS (0x130)
-#define PSDEV_DEBUG 1 /* control debugging */
-#define PSDEV_TRACE 2 /* control enter/leave pattern */
+#define PSDEV_DEBUG 1 /* control debugging */
+#define PSDEV_TRACE 2 /* control enter/leave pattern */
/* These are global control options */
#define ENTRY_CNT 3
/* 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}
+ {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}
+ {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;
+ 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);
+ if ( !smfs_table_header )
+ smfs_table_header =
+ register_sysctl_table(smfs_table, 0);
#endif
- return 0;
+ return 0;
}
-void cleanup_smfs_proc_sys(void)
+void cleanup_smfs_proc_sys(void)
{
#ifdef CONFIG_SYSCTL
- if ( smfs_table_header )
- unregister_sysctl_table(smfs_table_header);
- smfs_table_header = NULL;
+ 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);
+ remove_proc_entry("smfs", proc_root_fs);
#endif
}
-
static struct list_head option_list;
-char *options = NULL;
-char *opt_left = NULL;
+static char *options = NULL;
+static char *opt_left = NULL;
int init_option(char *data)
{
opt_left = options;
return 0;
}
+
/*cleanup options*/
void cleanup_option()
{
}
SNAP_FREE(options, strlen(options) + 1);
}
+
int get_opt(struct option **option, char **pos)
{
char *name, *value, *left;
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+
#define TEST_MINOR 120
#define TEST_MAJOR 25
exit(1);
}
+/* UMKA: This stuff inlined here instead of using appropriate header
+ to avoid linking to symbols which is not present in newer libc.
+
+ Currently this is the case, as UML image contains RedHat 9 and
+ developers use something newer (Fedora, etc.). */
+inline unsigned int
+__gnu_dev_major (unsigned long long int __dev)
+{
+ return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
+}
+
+inline unsigned int
+__gnu_dev_minor (unsigned long long int __dev)
+{
+ return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
+}
+
+inline unsigned long long int
+__gnu_dev_makedev (unsigned int __major, unsigned int __minor)
+{
+ return ((__minor & 0xff) | ((__major & 0xfff) << 8)
+ | (((unsigned long long int) (__minor & ~0xff)) << 12)
+ | (((unsigned long long int) (__major & ~0xfff)) << 32));
+}
+
+#define __minor(dev) __gnu_dev_minor(dev)
+#define __major(dev) __gnu_dev_major(dev)
+#define __makedev(maj, min) __gnu_dev_makedev(maj, min)
+
int main( int argc, char **argv)
{
char *prog = argv[0];
char *filename = argv[1];
int rc;
struct stat st;
- dev_t device = makedev(TEST_MAJOR, TEST_MINOR);
+ dev_t device = __makedev(TEST_MAJOR, TEST_MINOR);
if (argc != 2)
usage(prog);
unlink(filename);
+
/* First try block devices */
rc = mknod(filename, 0700 | S_IFBLK, device);
if ( rc < 0 ) {
prog, filename, errno, strerror(errno));
return 3;
}
+
if ( st.st_rdev != device) {
- fprintf(stderr, "%s: created device other than requested: (%d,%d) instead of (%d,%d)\n", prog, major(st.st_rdev),minor(st.st_rdev),major(device),minor(device));
+ fprintf(stderr, "%s: created device other than requested: (%u,%u) instead of (%u,%u)\n",
+ prog, __major(st.st_rdev),__minor(st.st_rdev),__major(device),__minor(device));
return 4;
}
if (!S_ISBLK(st.st_mode)) {
return 8;
}
if ( st.st_rdev != device) {
- fprintf(stderr, "%s: created device other than requested: (%d,%d) instead of (%d,%d)\n", prog, major(st.st_rdev),minor(st.st_rdev),major(device),minor(device));
+ fprintf(stderr, "%s: created device other than requested: (%u,%u) instead of (%u,%u)\n",
+ prog, __major(st.st_rdev),__minor(st.st_rdev),__major(device),__minor(device));
return 9;
}
if (!S_ISCHR(st.st_mode)) {
mkconfig=$NAME.sh
if [ "$PORTALS" ]; then
- portals_opt="--portals=$PORTALS"
+ portals_opt="--portals=$PORTALS"
fi
if [ "$LUSTRE" ]; then
- lustre_opt="--lustre=$LUSTRE"
+ lustre_opt="--lustre=$LUSTRE"
fi
if [ "$LDAPURL" ]; then
LMC="${LMC:-lmc} -m $config"
TMP=${TMP:-/tmp}
+FSTYPE=${FSTYPE:-ext3}
+
MDSDEV=${MDSDEV:-$TMP/mds1-`hostname`}
MDSSIZE=${MDSSIZE:-100000}
-FSTYPE=${FSTYPE:-ext3}
+
MOUNT=${MOUNT:-/mnt/lustre}
MOUNT2=${MOUNT2:-${MOUNT}2}
NETWORKTYPE=${NETWORKTYPE:-tcp}
OSTDEV=${OSTDEV:-$TMP/ost1-`hostname`}
OSTSIZE=${OSTSIZE:-200000}
+MDS_BACKFSTYPE=${MDS_BACKFSTYPE:-ext3}
+OST_BACKFSTYPE=${OST_BACKFSTYPE:-ext3}
+
+MDS_BACKDEV=${MDS_BACKDEV:-$TMP/mds1-`hostname`}
+OST_BACKDEV=${OST_BACKDEV:-$TMP/ost1-`hostname`}
+
+MDS_MOUNT_OPTS=${MDS_MOUNT_OPTS:-"errors=remount-ro"}
+OST_MOUNT_OPTS=${OST_MOUNT_OPTS:-"errors=remount-ro"}
+
+# adding some options needed for ext3 on 2.4.x kernels
+if test "x$(uname -r | sed -e 's/-.*//' -e 's/\.[[:digit:]]*$//')" = "x2.4"; then
+ if test "x$FSTYPE" = "xext3" || test "x$FSTYPE" = "xldiskfs"; then
+ if test "x$OST_MOUNT_OPTS" = "x"; then
+ OST_MOUNT_OPTS="asyncdel"
+ else
+ OST_MOUNT_OPTS="$OST_MOUNT_OPTS,asyncdel"
+ fi
+ fi
+fi
+
# specific journal size for the ost, in MB
JSIZE=${JSIZE:-0}
[ "$JSIZE" -gt 0 ] && JARG="--journal_size $JSIZE"
${LMC} --add net --node localhost --nid `hostname` --nettype $NETWORKTYPE || exit 11
${LMC} --add net --node client --nid '*' --nettype $NETWORKTYPE || exit 12
+echo "MDS mount options are: $MDS_MOUNT_OPTS"
+
# configure mds server
-${LMC} --add mds --nspath /mnt/mds_ns --node localhost --mds mds1 --fstype $FSTYPE --dev $MDSDEV --size $MDSSIZE $JARG $IARG || exit 20
+${LMC} --add mds --nspath /mnt/mds_ns --node localhost --mds mds1 \
+--fstype $FSTYPE --backfstype $MDS_BACKFSTYPE --dev $MDSDEV \
+--backdev $MDS_BACKDEV --mountfsoptions $MDS_MOUNT_OPTS \
+--size $MDSSIZE $JARG $IARG || exit 20
+
+echo "OST mount options are: $OST_MOUNT_OPTS"
# configure ost
-${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES --stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 || exit 20
-${LMC} --add ost --nspath /mnt/ost_ns --node localhost --lov lov1 --fstype $FSTYPE --dev $OSTDEV --size $OSTSIZE $JARG || exit 30
+${LMC} -m $config --add lov --lov lov1 --mds mds1 --stripe_sz $STRIPE_BYTES \
+--stripe_cnt $STRIPES_PER_OBJ --stripe_pattern 0 || exit 20
+
+${LMC} --add ost --nspath /mnt/ost_ns --node localhost --lov lov1 \
+--fstype $FSTYPE --backfstype $OST_BACKFSTYPE --dev $OSTDEV \
+--backdev $OST_BACKDEV --mountfsoptions $OST_MOUNT_OPTS \
+--size $OSTSIZE $JARG || exit 30
# create client config
${LMC} --add mtpt --node localhost --path $MOUNT --mds mds1 --lov lov1 || exit 40
--- /dev/null
+#!/bin/bash
+
+MDSDEV=smfs OSTDEV=smfs FSTYPE=smfs MDS_MOUNT_OPTS="kml" OST_MOUNT_OPTS="kml" \
+OSTSIZE=100000 MDSSIZE=50000 MDS_BACKFSTYPE=ext3 OST_BACKFSTYPE=ext3 \
+MDS_BACKDEV=/tmp/mds1-$(hostname) OST_BACKDEV=/tmp/ost1-$(hostname) sh llmount.sh
export LANG=C LC_LANG=C # for "No space left on device" message
+# make sure, that log file will be removed. Somehow it was possible
+# to me, that log file had +a and could not be rewritten, what led
+# to test fail.
+chattr -ai $LOG >/dev/null 2>&1
+rm -f $LOG >/dev/null 2>&1
+
# make sure we stripe over all OSTs to avoid OOS on only a subset of OSTs
$LFS setstripe $OOS 65536 0 $STRIPECOUNT
if dd if=/dev/zero of=$OOS count=$(($ORIGFREE + 100)) bs=1k 2> $LOG; then
GRANT=`cat $OSC/cur_grant_bytes`
[ $(($AVAIL - $GRANT / 1024)) -lt 400 ] && OSCFULL=full
done
+
if [ -z "$OSCFULL" ]; then
echo "no OSTs are close to full"
grep [0-9] /proc/fs/lustre/osc/OSC*MNT*/{kbytesavail,cur*}
quit""" % (type, name, uuid)
self.run(cmds)
- def setup(self, name, setup = ""):
+ def setup(self, name, setup = ""):
cmds = """
cfg_device %s
setup %s
panic ("can't access loop devices")
return loop
-# find loop device assigned to thefile
-def find_loop(file):
+# find loop device assigned to the file
+def find_assigned_loop(file):
loop = loop_base()
for n in xrange(0, MAX_LOOP_DEVICES):
dev = loop + str(n)
return ''
# create file if necessary and assign the first free loop device
-def init_loop(file, size, fstype, journal_size, inode_size, mkfsoptions, reformat):
- dev = find_loop(file)
+def init_loop(file, size, fstype, journal_size, inode_size,
+ mkfsoptions, reformat, backfstype, backfile):
+ if fstype == 'smfs':
+ realfile = backfile
+ realfstype = backfstype
+ else:
+ realfile = file
+ realfstype = fstype
+
+ dev = find_assigned_loop(realfile)
if dev:
- print 'WARNING file:', file, 'already mapped to', dev
+ print 'WARNING file:', realfile, 'already mapped to', dev
return dev
- if reformat or not os.access(file, os.R_OK | os.W_OK):
+
+ if reformat or not os.access(realfile, os.R_OK | os.W_OK):
if size < 8000:
- panic("size of loopback file '%s' must be larger than 8MB, but is set to %s" % (file,size))
- (ret, out) = run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size,
- file))
+ panic("size of loopback file '%s' must be larger than 8MB, but is set to %s" % (realfile, size))
+ (ret, out) = run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, realfile))
if ret:
- panic("Unable to create backing store:", file)
- mkfs(file, size, fstype, journal_size, inode_size, mkfsoptions, isblock=0)
+ panic("Unable to create backing store:", realfile)
+
+ mkfs(realfile, size, realfstype, journal_size, inode_size,
+ mkfsoptions, isblock=0)
loop = loop_base()
# find next free loop
if os.access(dev, os.R_OK):
(stat, out) = run('losetup', dev)
if stat:
- run('losetup', dev, file)
+ run('losetup', dev, realfile)
return dev
else:
print "out of loop devices"
# undo loop assignment
def clean_loop(file):
- dev = find_loop(file)
+ dev = find_assigned_loop(file)
if dev:
ret, out = run('losetup -d', dev)
if ret:
# initialize a block device if needed
def block_dev(dev, size, fstype, reformat, autoformat, journal_size,
- inode_size, mkfsoptions):
- if config.noexec: return dev
- if not is_block(dev):
+ inode_size, mkfsoptions, backfstype, backdev):
+ if config.noexec:
+ return dev
+
+ if fstype == 'smfs' or not is_block(dev):
dev = init_loop(dev, size, fstype, journal_size, inode_size,
- mkfsoptions, reformat)
+ mkfsoptions, reformat, backfstype, backdev)
elif reformat or (need_format(fstype, dev) and autoformat == 'yes'):
mkfs(dev, size, fstype, journal_size, inode_size, mkfsoptions,
isblock=0)
def __init__(self,db):
Module.__init__(self, 'MDSDEV', db)
self.devpath = self.db.get_val('devpath','')
+ self.backdevpath = self.db.get_val('backdevpath','')
self.size = self.db.get_val_int('devsize', 0)
self.journal_size = self.db.get_val_int('journalsize', 0)
self.fstype = self.db.get_val('fstype', '')
+ self.backfstype = self.db.get_val('backfstype', '')
self.nspath = self.db.get_val('nspath', '')
self.mkfsoptions = self.db.get_val('mkfsoptions', '')
+ self.mountfsoptions = self.db.get_val('mountfsoptions', '')
# overwrite the orignal MDSDEV name and uuid with the MDS name and uuid
target_uuid = self.db.get_first_ref('target')
mds = self.db.lookup(target_uuid)
self.target_dev_uuid = self.uuid
self.uuid = target_uuid
- # modules
+
+ # loading modules
self.add_lustre_module('mdc', 'mdc')
self.add_lustre_module('osc', 'osc')
self.add_lustre_module('lov', 'lov')
self.add_lustre_module('mds', 'mds')
+
+ if self.fstype == 'smfs':
+ self.add_lustre_module('smfs', 'smfs')
+
if self.fstype == 'ldiskfs':
self.add_lustre_module('ldiskfs', 'ldiskfs')
+
if self.fstype:
self.add_lustre_module('lvfs', 'fsfilt_%s' % (self.fstype))
+
+ # if fstype is smfs, then we should also take care about backing
+ # store fs.
+ if self.fstype == 'smfs':
+ self.add_lustre_module('lvfs', 'fsfilt_%s' % (self.backfstype))
def load_module(self):
if self.active:
# never reformat here
blkdev = block_dev(self.devpath, self.size, self.fstype, 0,
self.format, self.journal_size, self.inode_size,
- self.mkfsoptions)
+ self.mkfsoptions, self.backfstype, self.backdevpath)
if not is_prepared('MDT'):
lctl.newdev("mdt", 'MDT', 'MDT_UUID', setup ="")
try:
- lctl.newdev("mds", self.name, self.uuid,
- setup ="%s %s %s" %(blkdev, self.fstype, self.name))
+ if config.mountfsoptions != None:
+ mountfsoptions = config.mountfsoptions
+ if self.mountfsoptions != None:
+ mountfsoptions = mountfsoptions + ' ' + self.mountfsoptions
+ else:
+ mountfsoptions = self.mountfsoptions
+
+ # we count, that mountfsoptions is always not None for smfs
+ if self.fstype == 'smfs':
+ realdev = self.fstype
+ mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions,
+ self.backfstype,
+ blkdev)
+ else:
+ realdev = blkdev
+
+ if mountfsoptions != None:
+ lctl.newdev("mds", self.name, self.uuid,
+ setup ="%s %s %s %s" %(realdev, self.fstype,
+ self.name, mountfsoptions))
+ else:
+ lctl.newdev("mds", self.name, self.uuid,
+ setup ="%s %s %s" %(realdev, self.fstype,
+ self.name))
except CommandError, e:
if e.rc == 2:
panic("MDS is missing the config log. Need to run " +
if is_prepared(self.name):
return
self.info(self.devpath, self.fstype, self.format)
+
blkdev = block_dev(self.devpath, self.size, self.fstype,
config.reformat, self.format, self.journal_size,
- self.inode_size, self.mkfsoptions)
- lctl.newdev("mds", self.name, self.uuid,
- setup ="%s %s" %(blkdev, self.fstype))
-
+ self.inode_size, self.mkfsoptions, self.backfstype,
+ self.backdevpath)
+
+ if config.mountfsoptions != None:
+ mountfsoptions = config.mountfsoptions
+ if self.mountfsoptions != None:
+ mountfsoptions = mountfsoptions + ' ' + self.mountfsoptions
+ else:
+ mountfsoptions = self.mountfsoptions
+
+ # Even for writing logs we mount mds with supplied mount options
+ # because it will not mount smfs (if used) otherwise.
+
+ # we count, that mountfsoptions is always not None for smfs
+ if self.fstype == 'smfs':
+ realdev = self.fstype
+ mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions,
+ self.backfstype,
+ blkdev)
+ else:
+ realdev = blkdev
+
+ # As mount options are passed by 4th param to config tool, we need
+ # to pass something in 3rd param. But we do not want this 3rd param
+ # be counted as a profile name for reading log on MDS setup, thus,
+ # we pass there some predefined sign @dumb, which will be checked
+ # in MDS code and skipped.
+ if mountfsoptions != None:
+ lctl.newdev("mds", self.name, self.uuid,
+ setup ="%s %s %s %s" %(realdev, self.fstype, 'dumb',
+ mountfsoptions))
+ else:
+ lctl.newdev("mds", self.name, self.uuid,
+ setup ="%s %s %s" %(realdev, self.fstype, 'dumb'))
+
# record logs for the MDS lov
for uuid in self.filesystem_uuids:
log("recording clients for filesystem:", uuid)
e.dump()
cleanup_error(e.rc)
Module.cleanup(self)
- clean_loop(self.devpath)
+
+ if self.fstype == 'smfs':
+ clean_loop(self.backdevpath)
+ else:
+ clean_loop(self.devpath)
def msd_remaining(self):
out = lctl.device_list()
print "cleanup failed: ", self.name
e.dump()
cleanup_error(e.rc)
- clean_loop(self.devpath)
+
+ if self.fstype == 'smfs':
+ clean_loop(self.backdevpath)
+ else:
+ clean_loop(self.devpath)
class OSD(Module):
def __init__(self, db):
Module.__init__(self, 'OSD', db)
self.osdtype = self.db.get_val('osdtype')
self.devpath = self.db.get_val('devpath', '')
+ self.backdevpath = self.db.get_val('backdevpath', '')
self.size = self.db.get_val_int('devsize', 0)
self.journal_size = self.db.get_val_int('journalsize', 0)
self.inode_size = self.db.get_val_int('inodesize', 0)
self.mkfsoptions = self.db.get_val('mkfsoptions', '')
+ self.mountfsoptions = self.db.get_val('mountfsoptions', '')
self.fstype = self.db.get_val('fstype', '')
+ self.backfstype = self.db.get_val('backfstype', '')
self.nspath = self.db.get_val('nspath', '')
target_uuid = self.db.get_first_ref('target')
ost = self.db.lookup(target_uuid)
self.uuid = target_uuid
# modules
self.add_lustre_module('ost', 'ost')
+ if self.fstype == 'smfs':
+ self.add_lustre_module('smfs', 'smfs')
# FIXME: should we default to ext3 here?
if self.fstype == 'ldiskfs':
self.add_lustre_module('ldiskfs', 'ldiskfs')
if self.fstype:
self.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.fstype))
+ if self.fstype == 'smfs':
+ self.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.backfstype))
+
self.add_lustre_module(self.osdtype, self.osdtype)
def load_module(self):
else:
blkdev = block_dev(self.devpath, self.size, self.fstype,
config.reformat, self.format, self.journal_size,
- self.inode_size, self.mkfsoptions)
- lctl.newdev(self.osdtype, self.name, self.uuid,
- setup ="%s %s %s" %(blkdev, self.fstype,
- self.failover_ost))
+ self.inode_size, self.mkfsoptions, self.backfstype,
+ self.backdevpath)
+ if config.mountfsoptions != None:
+ mountfsoptions = config.mountfsoptions
+ if self.mountfsoptions != None:
+ mountfsoptions = mountfsoptions + ' ' + self.mountfsoptions
+ else:
+ mountfsoptions = self.mountfsoptions
+
+ # we count, that mountfsoptions is always not None for smfs
+ if self.fstype == 'smfs':
+ realdev = self.fstype
+ mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions,
+ self.backfstype,
+ blkdev)
+ else:
+ realdev = blkdev
+
+ if mountfsoptions != None:
+ lctl.newdev(self.osdtype, self.name, self.uuid,
+ setup ="%s %s %s %s" %(realdev, self.fstype,
+ self.failover_ost,
+ mountfsoptions))
+ else:
+ lctl.newdev(self.osdtype, self.name, self.uuid,
+ setup ="%s %s %s" %(realdev, self.fstype,
+ self.failover_ost))
if not is_prepared('OSS'):
lctl.newdev("ost", 'OSS', 'OSS_UUID', setup ="")
e.dump()
cleanup_error(e.rc)
if not self.osdtype == 'obdecho':
- clean_loop(self.devpath)
+ if self.fstype == 'smfs':
+ clean_loop(self.backdevpath)
+ else:
+ clean_loop(self.devpath)
def mgmt_uuid_for_fs(mtpt_name):
if not mtpt_name:
('nosetup', "Skip device setup/cleanup step."),
('reformat', "Reformat all devices (without question)"),
('mkfsoptions', "Additional options for the mk*fs command line", PARAM),
+ ('mountfsoptions', "Additional options for mount fs command line", PARAM),
('dump', "Dump the kernel debug log to file before portals is unloaded",
PARAM),
('write_conf', "Save all the client config information on mds."),
" check all records from index 1 by default."},
{"llog_cancel", jt_llog_cancel, 0,
"cancel one record in log.\n"
- "usage: llog_cancel <catlog id|catlog name> <log id> <index>"},
+ "usage: llog_cancel <catalog id|catalog name> <log id> <index>"},
{"llog_remove", jt_llog_remove, 0,
- "remove one log from catlog, erase it from disk.\n"
- "usage: llog_remove <catlog id|catlog name> <log id>"},
+ "remove one log from catalog, erase it from disk.\n"
+ "usage: llog_remove <catalog id|catalog name> <log id>"},
/* Debug commands */
{"======== debug =========", jt_noop, 0, "debug"},
--node node_name
--mds mds_name
--dev path
+ --backdev path
--fstype extN|ext3
+ --backfstype ext3|tmpfs
--size size
--nspath
--journal_size size
--ost ost_name
--lov lov_name
--dev path
+ --backdev path
--size size
--fstype extN|ext3
+ --backfstype ext3|tmpfs
--journal_size size
--inode_size size
--obdtype obdecho|obdfilter
('failover', "Enable failover support on OSTs or MDS?"),
('group', "", PARAM),
('dev', "Path of the device on local system.", PARAM,""),
+ ('backdev', "Path of the device for backing storage on local system.", PARAM,""),
('size', "Specify the size of the device if needed.", PARAM,"0"),
('journal_size', "Specify new journal size for underlying ext3 file system.", PARAM,"0"),
('inode_size', "Specify new inode size for underlying ext3 file system.", PARAM,"0"),
('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
+ ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
+ ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
('ostuuid', "", PARAM,""),
('nspath', "Local mount point of server namespace.", PARAM,""),
('format', ""),
return ldlm
def osd(self, name, uuid, fs, osdtype, devname, format, ost_uuid,
- node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="", mkfsoptions=""):
+ node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="",
+ mkfsoptions="", mountfsoptions="", backfs="", backdevname=""):
osd = self.newService("osd", name, uuid)
osd.setAttribute('osdtype', osdtype)
osd.appendChild(self.ref("target", ost_uuid))
osd.appendChild(self.ref("node", node_uuid))
if fs:
self.addElement(osd, "fstype", fs)
+ if backfs:
+ self.addElement(osd, "backfstype", backfs)
+ if backdevname:
+ self.addElement(osd, "backdevpath", backdevname)
if devname:
dev = self.addElement(osd, "devpath", devname)
self.addElement(osd, "autoformat", format)
self.addElement(osd, "inodesize", "%s" % (inode_size))
if mkfsoptions:
self.addElement(osd, "mkfsoptions", mkfsoptions)
+ if mountfsoptions:
+ self.addElement(osd, "mountfsoptions", mountfsoptions)
if nspath:
self.addElement(osd, "nspath", nspath)
return osd
def mdsdev(self, name, uuid, fs, devname, format, node_uuid,
mds_uuid, dev_size=0, journal_size=0, inode_size=256,
- nspath="", mkfsoptions=""):
+ nspath="", mkfsoptions="", mountfsoptions="", backfs="",
+ backdevname=""):
mdd = self.newService("mdsdev", name, uuid)
self.addElement(mdd, "fstype", fs)
+ if backfs:
+ self.addElement(mdd, "backfstype", backfs)
dev = self.addElement(mdd, "devpath", devname)
+ if backdevname:
+ self.addElement(mdd, "backdevpath", backdevname)
self.addElement(mdd, "autoformat", format)
if dev_size:
self.addElement(mdd, "devsize", "%s" % (dev_size))
self.addElement(mdd, "nspath", nspath)
if mkfsoptions:
self.addElement(mdd, "mkfsoptions", mkfsoptions)
+ if mountfsoptions:
+ self.addElement(mdd, "mountfsoptions", mountfsoptions)
+
mdd.appendChild(self.ref("node", node_uuid))
mdd.appendChild(self.ref("target", mds_uuid))
return mdd
mds.setAttribute('failover', "1")
devname = get_option(options, 'dev')
+ backdevname = get_option(options, 'backdev')
size = get_option(options, 'size')
fstype = get_option(options, 'fstype')
+ backfstype = get_option(options, 'backfstype')
journal_size = get_option(options, 'journal_size')
inode_size = get_option(options, 'inode_size')
nspath = get_option(options, 'nspath')
mkfsoptions = get_option(options, 'mkfsoptions')
+ mountfsoptions = get_option(options, 'mountfsoptions')
node_uuid = name2uuid(lustre, node_name, 'node')
mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
get_format_flag(options), node_uuid, mds_uuid,
- size, journal_size, inode_size, nspath, mkfsoptions)
+ size, journal_size, inode_size, nspath, mkfsoptions,
+ mountfsoptions, backfstype, backdevname)
lustre.appendChild(mdd)
if osdtype == 'obdecho':
fstype = ''
+ backfstype = ''
devname = ''
+ backdevname = ''
size = 0
fstype = ''
journal_size = ''
inode_size = ''
mkfsoptions = ''
+ mountfsoptions = ''
else:
devname = get_option(options, 'dev') # can be unset for bluearcs
+ backdevname = get_option(options, 'backdev')
size = get_option(options, 'size')
fstype = get_option(options, 'fstype')
+ backfstype = get_option(options, 'backfstype')
journal_size = get_option(options, 'journal_size')
inode_size = get_option(options, 'inode_size')
mkfsoptions = get_option(options, 'mkfsoptions')
+ mountfsoptions = get_option(options, 'mountfsoptions')
nspath = get_option(options, 'nspath')
osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
get_format_flag(options), ost_uuid, node_uuid, size,
- journal_size, inode_size, nspath, mkfsoptions)
+ journal_size, inode_size, nspath, mkfsoptions,
+ mountfsoptions, backfstype, backdevname)
node = findByName(lustre, node_name, "node")
lcfg.lcfg_inllen3 = strlen(argv[3]) + 1;
lcfg.lcfg_inlbuf3 = argv[3];
}
+
if (argc > 4) {
lcfg.lcfg_inllen4 = strlen(argv[4]) + 1;
lcfg.lcfg_inlbuf4 = argv[4];
if (argc == 3)
fprintf(stdout, "log %s are removed.\n", argv[2]);
else
- fprintf(stdout, "the log in catlog %s are removed. \n", argv[1]);
+ fprintf(stdout, "the log in catalog %s are removed. \n", argv[1]);
} else
fprintf(stderr, "OBD_IOC_LLOG_REMOVE failed: %s\n",
strerror(errno));
(long long)REINT_RENAME);
LASSERTF(REINT_OPEN == 6, " found %lld\n",
(long long)REINT_OPEN);
- LASSERTF(REINT_MAX == 6, " found %lld\n",
+ LASSERTF(REINT_MAX == 8, " found %lld\n",
(long long)REINT_MAX);
LASSERTF(DISP_IT_EXECD == 1, " found %lld\n",
(long long)DISP_IT_EXECD);