From 5335d979bf9bad5b6d3af1f3140f73f8afada437 Mon Sep 17 00:00:00 2001 From: tappro Date: Wed, 13 Apr 2005 06:51:33 +0000 Subject: [PATCH] b=5881 adding sets of smfs fsfilt methods adds some new HOOKs --- lustre/smfs/fsfilt.c | 1160 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1160 insertions(+) create mode 100644 lustre/smfs/fsfilt.c diff --git a/lustre/smfs/fsfilt.c b/lustre/smfs/fsfilt.c new file mode 100644 index 0000000..64bfcaf --- /dev/null +++ b/lustre/smfs/fsfilt.c @@ -0,0 +1,1160 @@ +/* -*- 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) 2004 Cluster File Systems, Inc. + * Author: Wang Di + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "smfs_internal.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; + + //SMFS_TRANS_OP(inode, op); + + 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) + RETURN(ERR_PTR(-ENOMEM)); + + cache_fso.fso_dentry = cache_dentry; + cache_fso.fso_bufcnt = fso->fso_bufcnt; + + if (!cache_fsfilt->fs_brw_start) { + rc = ERR_PTR(-ENOSYS); + goto exit; + } + + rc = cache_fsfilt->fs_brw_start(objcount, &cache_fso, niocount, nb, + desc_private, logs); +exit: + post_smfs_dentry(cache_dentry); + RETURN(rc); +} + +/* FIXME-WANGDI: here we can easily have inode == NULL due to + mds_open() behavior. It passes NULL inode to mds_finish_transno() + sometimes. Probably we should have spare way to get cache fsfilt + operations. */ +static int fsfilt_smfs_commit(struct super_block *sb, struct inode *inode, + void *h, int force_sync) +{ + struct fsfilt_operations *cache_fsfilt = S2SMI(sb)->sm_cache_fsfilt; + struct super_block *csb = S2CSB(sb); + struct inode *cache_inode = NULL; + int rc = -EIO; + + ENTRY; + + if (inode) + cache_inode = I2CI(inode); + + if (cache_fsfilt == NULL) + RETURN(rc); + + if (!cache_fsfilt->fs_commit) + RETURN(-ENOSYS); + + rc = cache_fsfilt->fs_commit(csb, 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 = I2CI(dentry->d_inode); + struct hook_setattr_msg msg = { + .dentry = dentry, + .attr = iattr + }; + int rc = -EIO; + + if (!cache_fsfilt) + RETURN(rc); + + if (!cache_fsfilt->fs_setattr) + RETURN(-ENOSYS); + + cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry); + if (!cache_dentry) + RETURN(-ENOMEM); + + pre_smfs_inode(dentry->d_inode, cache_inode); + + SMFS_PRE_HOOK(dentry->d_inode, HOOK_F_SETATTR, &msg); + + rc = cache_fsfilt->fs_setattr(cache_dentry, handle, iattr, do_trunc); + + SMFS_POST_HOOK(dentry->d_inode, HOOK_F_SETATTR, &msg, rc); + post_smfs_inode(dentry->d_inode, cache_inode); + + 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 = I2CI(inode); + struct smfs_file_info *sfi = NULL; + struct file * cache_file = NULL; + int rc = -EIO; + ENTRY; + + if (!cache_fsfilt || !cache_inode) + RETURN(rc); + + if (!cache_fsfilt->fs_iocontrol) + RETURN(-ENOSYS); + + + if (file != NULL) { + sfi = F2SMFI(file); + if (sfi->magic != SMFS_FILE_MAGIC) + BUG(); + cache_file = sfi->c_file; + } + + pre_smfs_inode(inode, cache_inode); + + rc = cache_fsfilt->fs_iocontrol(cache_inode, cache_file, cmd, arg); + +#if 0 + /* FIXME-UMKA: Should this be in duplicate_inode()? */ + if (rc == 0 && cmd == EXT3_IOC_SETFLAGS) + inode->i_flags = cache_inode->i_flags; +#endif + post_smfs_inode(inode, cache_inode); + + RETURN(rc); +} + +static int fsfilt_smfs_set_md(struct inode *inode, void *handle, + void *lmm, int lmm_size, enum ea_type type) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); + struct inode *cache_inode = I2CI(inode); + int rc = -EIO; + + if (!cache_fsfilt) + RETURN(-EINVAL); + + if (!cache_inode) + RETURN(-ENOENT); + /*TODO: HOOK is needed here */ + pre_smfs_inode(inode, cache_inode); + + down(&cache_inode->i_sem); + rc = cache_fsfilt->fs_set_md(cache_inode, handle, lmm, + lmm_size, type); + up(&cache_inode->i_sem); + + post_smfs_inode(inode, cache_inode); + + RETURN(rc); +} + +static int fsfilt_smfs_get_md(struct inode *inode, void *lmm, + int lmm_size, enum ea_type type) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); + struct inode *cache_inode = I2CI(inode); + int rc = -EIO; + + if (!cache_fsfilt) + RETURN(-EINVAL); + + if (!cache_inode) + RETURN(-ENOENT); + + pre_smfs_inode(inode, cache_inode); + + down(&cache_inode->i_sem); + rc = cache_fsfilt->fs_get_md(cache_inode, lmm, lmm_size, type); + up(&cache_inode->i_sem); + + post_smfs_inode(inode, cache_inode); + + RETURN(rc); +} + +static int fsfilt_smfs_send_bio(int rw, struct inode *inode, void *bio) +{ + struct inode *cache_inode; + struct fsfilt_operations *cache_fsfilt; + + ENTRY; + + 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(rw, cache_inode, bio); +} + +static struct page * fsfilt_smfs_getpage(struct inode *inode, long int index) +{ + struct fsfilt_operations *cache_fsfilt; + struct inode *cache_inode; + ENTRY; + 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)); +#if CONFIG_SNAPFS + if (SMFS_DO_COW(S2SMI(inode->i_sb))) { + struct address_space_operations *aops = + cache_inode->i_mapping->a_ops; + if (aops->bmap(cache_inode->i_mapping, index)) { + struct inode *ind_inode = NULL; + struct inode *cache_ind = NULL; + struct page *page = NULL; + + ind_inode = smfs_cow_get_ind(inode, index); + if (!ind_inode) { + RETURN(ERR_PTR(-EIO)); + } + cache_ind = I2CI(ind_inode); + /*FIXME cow inode should be bottom fs inode */ + page = cache_fsfilt->fs_getpage(cache_ind, index); + iput(ind_inode); + RETURN(page); + } + } +#endif + 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 CONFIG_SNAPFS + /*readdir page*/ + if (smfs_dotsnap_inode(file->f_dentry->d_inode)) { + struct fsfilt_operations *snapops = + I2SNAPOPS(file->f_dentry->d_inode); + + LASSERT(S_ISDIR(file->f_dentry->d_inode->i_mode)); + + rc = snapops->fs_read_dotsnap_dir_page(sfi->c_file, buf, count, + cache_ppos); + } else { + if (cache_fsfilt->fs_readpage) + rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count, + cache_ppos); + } +#else + if (cache_fsfilt->fs_readpage) + rc = cache_fsfilt->fs_readpage(sfi->c_file, buf, count, + cache_ppos); + +#endif + *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; + + ENTRY; + + 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; + + ENTRY; + + 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 = -ENOSYS; + + if (!cache_fsfilt) + RETURN(-EINVAL); + + if (cache_fsfilt->fs_sync) + rc = cache_fsfilt->fs_sync(csb); + + RETURN(rc); +} + +int fsfilt_smfs_map_inode_pages(struct inode *inode, struct page **page, + int pages, unsigned long *blocks, int *created, + int create, struct semaphore *sem) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); + struct inode *cache_inode = NULL; + int rc = -EIO; + + ENTRY; + + if (!cache_fsfilt) + RETURN(-EINVAL); + + cache_inode = I2CI(inode); + + if (!cache_inode) + RETURN(rc); + + if (!cache_fsfilt->fs_map_inode_pages) + RETURN(-ENOSYS); + + down(&cache_inode->i_sem); + + rc = cache_fsfilt->fs_map_inode_pages(cache_inode, page, pages, blocks, + created, create, sem); + 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_post_setup(struct obd_device *obd, struct vfsmount *mnt, + struct dentry *root_dentry) +{ + struct super_block *sb = NULL; + int rc = 0; + + ENTRY; + + if (mnt) { + sb = mnt->mnt_sb; + + if (obd) + S2SMI(sb)->smsi_exp = obd->obd_self_export; + + rc = smfs_post_setup(sb, mnt); + if (!rc) { + if (obd) + obd->obd_llog_ctxt[LLOG_REINT_ORIG_CTXT] = + S2SMI(sb)->smsi_kml_log; + } + else { + CERROR("can not do post setup in obd %p rc=%d", + obd, rc); + } + } + + RETURN(rc); +} + +static int fsfilt_smfs_post_cleanup(struct obd_device *obd, + struct vfsmount *mnt) +{ + struct super_block *sb = NULL; + int rc = 0; + ENTRY; + + if (mnt) { + sb = mnt->mnt_sb; + smfs_post_cleanup(sb); + } + + RETURN(rc); +} + +static int fsfilt_smfs_set_fs_flags(struct inode *inode, int flags) +{ + int rc = 0; + ENTRY; + + if (flags & SM_DO_REC) + SMFS_SET(I2SMI(inode)->smi_flags, SMFS_PLG_KML); + + //if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC)) + // SMFS_SET_INODE_REC(inode); + if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW)) + SMFS_SET_INODE_COW(inode); + RETURN(rc); +} + +static int fsfilt_smfs_clear_fs_flags(struct inode *inode, int flags) +{ + int rc = 0; + ENTRY; + + if (SMFS_DO_REC(S2SMI(inode->i_sb)) && (flags & SM_DO_REC)) + SMFS_CLEAN_INODE_REC(inode); + if (SMFS_DO_COW(S2SMI(inode->i_sb)) && (flags & SM_DO_COW)) + SMFS_CLEAN_INODE_COW(inode); + RETURN(rc); +} + +static int fsfilt_smfs_get_fs_flags(struct dentry *de) +{ + struct inode *inode = de->d_inode; + int flags = 0; + ENTRY; + + LASSERT(inode); + + if (SMFS_DO_REC(S2SMI(inode->i_sb)) && SMFS_DO_INODE_REC(inode)) + flags |= SM_DO_REC; + if (SMFS_DO_COW(S2SMI(inode->i_sb)) && SMFS_DO_INODE_COW(inode)) + flags |= SM_DO_COW; + + RETURN(flags); +} +static int fsfilt_smfs_set_ost_flags(struct super_block *sb) +{ + int rc = 0; + SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_OST); + RETURN(rc); +} + +static int fsfilt_smfs_set_mds_flags(struct super_block *sb) +{ + int rc = 0; + SET_REC_PACK_TYPE_INDEX(S2SMI(sb)->smsi_flags, PACK_MDS); + RETURN(rc); +} + +static int fsfilt_smfs_get_reint_log_ctxt(struct super_block *sb, + struct llog_ctxt **ctxt) +{ + struct smfs_super_info *smfs_info = S2SMI(sb); + int rc = 0; + + *ctxt = smfs_info->smsi_kml_log; + RETURN(rc); +} + +static int fsfilt_smfs_setup(struct obd_device *obd, struct super_block *sb) +{ + struct smfs_super_info *smfs_info = S2SMI(sb); + struct fsfilt_operations *cache_fsfilt; + struct super_block *csb; + int rc = 0; + + ENTRY; + + /* It should be initialized olready by smfs_read_super(). */ + if (!(cache_fsfilt = smfs_info->sm_cache_fsfilt)) + cache_fsfilt = fsfilt_get_ops(smfs_info->smsi_cache_ftype); + + if (!cache_fsfilt) + RETURN(-ENOENT); + + csb = S2CSB(sb); + if (cache_fsfilt->fs_setup) + rc = cache_fsfilt->fs_setup(obd, csb); + + duplicate_sb(sb, 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; + + ENTRY; + + 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 int fsfilt_smfs_insert_extents_ea(struct inode *inode, + unsigned long from, unsigned long num) +{ + 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_insert_extents_ea) + rc = cache_fsfilt->fs_insert_extents_ea(cache_inode, from, num); + + post_smfs_inode(inode, cache_inode); + return rc; +} + +static int fsfilt_smfs_remove_extents_ea(struct inode *inode, + unsigned long from, unsigned long num) +{ + 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_remove_extents_ea) + rc = cache_fsfilt->fs_remove_extents_ea(cache_inode, from, num); + + post_smfs_inode(inode, cache_inode); + return rc; +} + +static int fsfilt_smfs_init_extents_ea(struct inode *inode) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(inode); + struct inode *cache_inode = NULL; + int rc = -EIO; + ENTRY; + + if (!cache_fsfilt) + RETURN(rc); + + cache_inode = I2CI(inode); + if (!cache_inode) + RETURN(rc); + + pre_smfs_inode(inode, cache_inode); + + if (cache_fsfilt->fs_init_extents_ea) + rc = cache_fsfilt->fs_init_extents_ea(cache_inode); + + post_smfs_inode(inode, cache_inode); + return rc; +} + +static int fsfilt_smfs_free_extents(struct super_block *sb, ino_t ino, + char *pbuf, int size) +{ + OBD_FREE(pbuf, size * (sizeof(struct ldlm_extent))); + return 0; +} + +static int fsfilt_smfs_write_extents(struct dentry *dentry, + unsigned long from, unsigned long num) +{ + int rc = 0; + ENTRY; + if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb))) + rc = smfs_write_extents(dentry->d_inode, dentry, from, num); + + return rc; +} + +static int fsfilt_smfs_precreate_rec(struct dentry *dentry, int *count, + struct obdo *oa) +{ + int rc = 0; + + if (SMFS_DO_REC(S2SMI(dentry->d_inode->i_sb))) + rc = smfs_rec_precreate(dentry, count, oa); + + return rc; +} + +static int fsfilt_smfs_get_ino_write_extents(struct super_block *sb, ino_t ino, + char **pbuf, int *size) +{ + struct fs_extent *fs_extents; + struct ldlm_extent *extents = NULL; + struct inode *inode; + struct inode *cache_inode; + struct fsfilt_operations *cache_fsfilt = NULL; + struct lvfs_run_ctxt saved; + int rc = 0, fs_ex_size, ex_num, flags; + char *buf = NULL, *ex_buf = NULL; + ENTRY; + + push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL); + + inode = iget(sb, ino); + + if (!inode || is_bad_inode(inode)) { + CWARN("Can not get inode %lu ino\n", ino); + GOTO(out, rc = 0); + } + cache_inode = I2CI(inode); + cache_fsfilt = I2FOPS(inode); + + rc = cache_fsfilt->fs_get_xattr(cache_inode, REINT_EXTENTS_FLAGS, + &flags, sizeof(int)); + if (!(flags & SMFS_OVER_WRITE) && !(flags & SMFS_DIRTY_WRITE)) { + GOTO(out, rc = 0); + } else if (flags & SMFS_OVER_WRITE) { + *size = 1; + OBD_ALLOC(ex_buf, sizeof(struct ldlm_extent)); + if (!ex_buf) + GOTO(out, rc=-ENOMEM); + extents = (struct ldlm_extent*)(ex_buf); + extents->start = 0; + extents->end = 0xffffffff; + } + if (rc < 0) + GOTO(out, rc); + rc = cache_fsfilt->fs_get_write_extents_num(cache_inode, &fs_ex_size); + if (rc) + GOTO(out, rc); + OBD_ALLOC(buf, fs_ex_size); + if (!buf) + GOTO(out, rc=-ENOMEM); + + rc = cache_fsfilt->fs_get_inode_write_extents(cache_inode, &buf, + &fs_ex_size); + if (rc < 0) + GOTO(out, rc); + rc = 0; + ex_num = fs_ex_size / sizeof(struct fs_extent); + *size = ex_num; + OBD_ALLOC(ex_buf, ex_num* sizeof(struct ldlm_extent)); + if (!ex_buf) + GOTO(out, rc=-ENOMEM); + + fs_extents = (struct fs_extent*)(buf); + extents = (struct ldlm_extent*)(ex_buf); + while (ex_num > 0) { + int blk_size = I2CI(inode)->i_blksize; + + extents->start = fs_extents->e_block * blk_size; + extents->end = extents->start + fs_extents->e_num * blk_size; + fs_extents++; + extents++; + ex_num--; + } + *pbuf = ex_buf; +out: + iput(inode); + if (buf) + OBD_FREE(buf, fs_ex_size); + if (rc && extents) + OBD_FREE(ex_buf, (*size) * (sizeof(struct ldlm_extent))); + pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL); + return rc; +} + +static int fsfilt_smfs_set_snap_item(struct super_block *sb, char *name) +{ + int rc = 0; + + ENTRY; +#if CONFIG_SNAPFS +#warning "still not implement for add snap item -wangdi" +#endif + RETURN(rc); +} +static int fsfilt_smfs_do_write_cow(struct dentry *de, void *extents, + int num_extents) +{ + int rc = 0; +#if CONFIG_SNAPFS + struct write_extents *w_ext = (struct write_extents *)extents; + int i = 0; + ENTRY; + for (i = 0; i < num_extents; i++) { + size_t count = w_ext->w_count; + loff_t off = w_ext->w_pos; + rc = smfs_cow_write_pre(de->d_inode, de, &count, &off); + if (rc) + RETURN(rc); + w_ext ++; + } +#endif + RETURN(rc); +} + +static int fsfilt_smfs_add_dir_entry(struct obd_device * obd, + struct dentry * parent, char* name, + int namelen, unsigned long ino, + unsigned long generation, + unsigned long mds, + unsigned long fid) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(parent->d_inode); + struct dentry *cache_dentry = NULL, *dentry = NULL; + struct inode *cache_parent = I2CI(parent->d_inode); + int rc = -EIO; + + ENTRY; + + if (!cache_fsfilt) + RETURN(rc); + + if (!cache_fsfilt->fs_add_dir_entry) + RETURN(-ENOSYS); + + dentry = ll_lookup_one_len(name, parent, namelen); + if (IS_ERR(dentry)) { + CERROR("can't lookup %*s in %lu/%lu: %d\n", namelen, + name, parent->d_inode->i_ino, + (unsigned long) parent->d_inode->i_generation, + (int) PTR_ERR(dentry)); + RETURN(PTR_ERR(dentry)); + } + if (dentry->d_inode != NULL || dentry->d_flags & DCACHE_CROSS_REF) { + CERROR("dentry %*s(0x%p) found\n", dentry->d_name.len, + dentry->d_name.name, dentry); + l_dput(dentry); + RETURN(-EEXIST); + } + /* mds_reint_rename() may use this method to add dir entry + * that points onto local inode. and we don't want to find + * it cross-ref by subsequent lookups */ + d_drop(dentry); + + dentry->d_flags |= DCACHE_CROSS_REF; + dentry->d_inum = ino; + dentry->d_mdsnum = mds; + dentry->d_generation = generation; + dentry->d_fid = fid; + l_dput(dentry); + + cache_dentry = pre_smfs_dentry(NULL, cache_parent, parent); + if (!cache_dentry) { + RETURN(-ENOMEM); + } + + pre_smfs_inode(parent->d_inode, cache_parent); + + rc = cache_fsfilt->fs_add_dir_entry(obd, cache_dentry, name, namelen, + ino, generation, mds, fid); + + post_smfs_inode(parent->d_inode, cache_parent); + + post_smfs_dentry(cache_dentry); + + RETURN(rc); + +} + +static int fsfilt_smfs_del_dir_entry(struct obd_device * obd, + struct dentry * dentry) +{ + struct fsfilt_operations *cache_fsfilt = I2FOPS(dentry->d_parent->d_inode); + struct dentry *cache_dentry = NULL, *cache_parent = NULL; + struct inode * cache_dir = I2CI(dentry->d_parent->d_inode); + struct inode * cache_inode = NULL; + int rc = -EIO; + + ENTRY; + + if (!cache_fsfilt) + RETURN(rc); + + if (!cache_fsfilt->fs_del_dir_entry) + RETURN(-ENOSYS); + + if (dentry->d_inode) + cache_inode = I2CI(dentry->d_inode); + + cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent); + cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry); + if (!cache_parent || !cache_dentry) { + rc = (-ENOMEM); + goto exit; + } + + pre_smfs_inode(dentry->d_parent->d_inode, cache_dir); + pre_smfs_inode(dentry->d_inode, cache_inode); + + rc = cache_fsfilt->fs_del_dir_entry(obd, cache_dentry); + + if (!rc) + d_drop(dentry); + + post_smfs_inode(dentry->d_inode, cache_inode); + post_smfs_inode(dentry->d_parent->d_inode, cache_dir); +exit: + post_smfs_dentry(cache_dentry); + post_smfs_dentry(cache_parent); + 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_pages = fsfilt_smfs_map_inode_pages, + .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, + .fs_get_op_len = NULL, + .fs_del_dir_entry = fsfilt_smfs_del_dir_entry, + .fs_add_dir_entry = fsfilt_smfs_add_dir_entry, + .fs_insert_extents_ea = fsfilt_smfs_insert_extents_ea, + .fs_remove_extents_ea = fsfilt_smfs_remove_extents_ea, + .fs_init_extents_ea = fsfilt_smfs_init_extents_ea, + .fs_get_ino_write_extents = fsfilt_smfs_get_ino_write_extents, + .fs_get_write_extents_num = NULL, + + .fs_free_write_extents = fsfilt_smfs_free_extents, + .fs_write_extents = fsfilt_smfs_write_extents, + .fs_post_setup = fsfilt_smfs_post_setup, + .fs_post_cleanup = fsfilt_smfs_post_cleanup, + .fs_set_fs_flags = fsfilt_smfs_set_fs_flags, + .fs_clear_fs_flags = fsfilt_smfs_clear_fs_flags, + .fs_get_fs_flags = fsfilt_smfs_get_fs_flags, + .fs_set_ost_flags = fsfilt_smfs_set_ost_flags, + .fs_set_mds_flags = fsfilt_smfs_set_mds_flags, + .fs_precreate_rec = fsfilt_smfs_precreate_rec, + .fs_get_reint_log_ctxt = fsfilt_smfs_get_reint_log_ctxt, + .fs_set_snap_item = fsfilt_smfs_set_snap_item, + .fs_do_write_cow = fsfilt_smfs_do_write_cow, + }; + +struct fsfilt_operations *get_smfs_fs_ops(void) +{ + return (&fsfilt_smfs_ops); +} +EXPORT_SYMBOL(get_smfs_fs_ops); + + -- 1.8.3.1