if (rec->sa_valid & ATTR_FROM_OPEN)
req->rq_request_portal = MDS_SETATTR_PORTAL; //XXX FIXME bug 249
- if (rec->sa_valid & (ATTR_MTIME | ATTR_CTIME))
+ if (rec->sa_valid & (ATTR_MTIME | ATTR_CTIME))
CDEBUG(D_INODE, "setting mtime %lu, ctime %lu\n",
- LTIME_S(((time_t)rec->sa_mtime)),
- LTIME_S(((time_t)rec->sa_ctime)));
-
+ ((time_t)rec->sa_mtime),
+ ((time_t)rec->sa_ctime));
size[0] = sizeof(struct mds_body);
req->rq_replen = lustre_msg_size(1, size);
ENTRY;
lock_kernel();
- /* vv ptlrpc_daemonize(); vv */
- exit_mm(current);
-
- current->session = 1;
- current->pgrp = 1;
- current->tty = NULL;
-
- exit_files(current);
- reparent_to_init();
- /* ^^ ptlrpc_daemonize(); ^^ */
+
+ ptlrpc_daemonize();
SIGNAL_MASK_LOCK(current, flags);
sigfillset(¤t->blocked);
__u32 generation;
__u32 f_type;
__u32 mds;
- __u16 snap_index;
- __u16 padding;
+ __u32 padding;
};
struct mea_old {
mdc_pack_fid(fid, inode->i_ino, inode->i_generation,
inode->i_mode & S_IFMT);
LASSERT(ll_i2info(inode));
- fid->snap_index = ll_i2info(inode)->lli_snap_index,
fid->mds = ll_i2info(inode)->lli_mds;
}
if (body->valid & OBD_MD_FLSIZE)
set_bit(LLI_F_HAVE_MDS_SIZE_LOCK, &lli->lli_flags);
- lli->lli_snap_index = body->fid1.snap_index;
lli->lli_mds = body->mds;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
inode->i_dev = (kdev_t) body->mds;
+#endif
LASSERT(body->mds < 1000);
}
if (ll_i2info(inode)->lli_mds != md->body->mds)
return 0;
-#ifdef CONFIG_SNAPFS
- if (ll_i2info(inode)->lli_snap_index != md->body->fid1.snap_index)
- return 0;
-#endif
/* Apply the attributes in 'opaque' to this inode */
ll_update_inode(inode, md);
return 1;
#include <linux/ext3_fs.h>
#include <linux/ext3_jbd.h>
#include <linux/ext3_extents.h>
-#include <linux/locks.h>
#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <linux/locks.h>
#include <linux/ext3_xattr.h>
+#include <linux/module.h>
+#include <linux/iobuf.h>
#else
#include <ext3/xattr.h>
#endif
#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
#include <linux/lustre_smfs.h>
#include <linux/lustre_snap.h>
#define SNAP_EA_INO_BLOCK_SIZE(size) (((size)-sizeof(ino_t)*2)/2)
#define SNAP_EA_PARENT_OFFSET(size) (sizeof(ino_t)*2 + SNAP_EA_INO_BLOCK_SIZE((size)))
+#define EXT3_JOURNAL_START(sb, handle, blocks, rc) \
+do { \
+ journal_t *journal; \
+ journal = EXT3_SB(sb)->s_journal; \
+ lock_kernel(); \
+ handle = journal_start(journal, 1); \
+ unlock_kernel(); \
+ if(IS_ERR(handle)) { \
+ CERROR("can't start transaction\n"); \
+ rc = PTR_ERR(handle); \
+ } else \
+ rc = 0; \
+} while(0)
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static inline void double_lock_inode(struct inode *i1, struct inode *i2)
+{
+ if (i1 == i2)
+ down(&i1->i_sem);
+ else
+ double_down(&i1->i_sem, &i2->i_sem);
+}
+static inline void double_unlock_inode(struct inode *i1, struct inode *i2)
+{
+ if (i1 == i2)
+ up(&i1->i_sem);
+ else
+ double_up(&i1->i_sem, &i2->i_sem);
+}
+#else
+static inline void double_lock_inode(struct inode *i1, struct inode *i2)
+{
+ struct semaphore *s1 = &i1->i_sem;
+ struct semaphore *s2 = &i2->i_sem;
+
+ if (s1 != s2) {
+ if ((unsigned long) s1 < (unsigned long) s2) {
+ struct semaphore *tmp = s2;
+ s2 = s1; s1 = tmp;
+ }
+ down(s1);
+ }
+ down(s2);
+}
+
+static inline void double_unlock_inode(struct inode *i1, struct inode *i2)
+{
+ struct semaphore *s1 = &i1->i_sem;
+ struct semaphore *s2 = &i2->i_sem;
+
+ up(s1);
+ if (s1 != s2)
+ up(s2);
+}
+
+#endif
+
/* helper functions to manipulate field 'parent' in snap_ea */
static inline int
set_parent_ino(struct snap_ea *pea, int size, int index, ino_t val)
{
char buf[EXT3_MAX_SNAP_DATA];
struct snap_ea *snaps;
- int err = 0, inlist = 1;
+ int rc = 0, inlist = 1;
int ea_size;
handle_t *handle = NULL;
ENTRY;
RETURN(-EINVAL);
/* need lock the list before get_attr() to avoid race */
/* read ea at first */
- err = ext3_xattr_get(pri, EXT3_SNAP_INDEX ,EXT3_SNAP_ATTR,
+ rc = ext3_xattr_get(pri, EXT3_SNAP_INDEX ,EXT3_SNAP_ATTR,
buf, EXT3_MAX_SNAP_DATA);
- if (err == -ENODATA || err == -ENOATTR) {
+ if (rc == -ENODATA || rc == -ENODATA) {
CDEBUG(D_INODE, "no extended attributes - zeroing\n");
memset(buf, 0, EXT3_MAX_SNAP_DATA);
/* XXX
* So take care of snap ea of primary inodes very carefully.
* Is it right in snapfs EXT3, check it later?
*/
- inlist = 0;
- } else if (err < 0 || err > EXT3_MAX_SNAP_DATA) {
- GOTO(out_unlock, err);
+ inlist = 0;
+ rc = 0;
+ } else if (rc < 0 || rc > EXT3_MAX_SNAP_DATA) {
+ GOTO(out_unlock, rc);
}
+ EXT3_JOURNAL_START(pri->i_sb, handle, SNAP_SETIND_TRANS_BLOCKS, rc);
+ if(rc)
+ GOTO(out_unlock, rc = PTR_ERR(handle));
- handle = ext3_journal_start(pri, SNAP_SETIND_TRANS_BLOCKS);
- if(!handle)
- GOTO(out_unlock, err = PTR_ERR(handle));
-
- snaps = (struct snap_ea *)buf;
+ snaps = (struct snap_ea *)buf;
snaps->ino[index] = cpu_to_le32 (ind_ino);
ea_size = EXT3_MAX_SNAP_DATA;
set_parent_ino(snaps, ea_size, index, cpu_to_le32(parent_ino));
- err = ext3_xattr_set(handle, pri, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
- buf, EXT3_MAX_SNAP_DATA, 0);
+ rc = ext3_xattr_set_handle(handle, pri, EXT3_SNAP_INDEX,EXT3_SNAP_ATTR,
+ buf, EXT3_MAX_SNAP_DATA, 0);
ext3_mark_inode_dirty(handle, pri);
- ext3_journal_stop(handle, pri);
+ journal_stop(handle);
out_unlock:
- return err;
+ RETURN(rc);
}
static int ext3_set_generation(struct inode *inode, unsigned long gen)
handle_t *handle;
int err = 0;
ENTRY;
-
- handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
- if( !handle )
- RETURN(-EINVAL);
-
- err = ext3_xattr_set(handle, inode, EXT3_SNAP_INDEX,
- EXT3_SNAP_GENERATION,
- (char*)&gen, sizeof(int), 0);
+
+ EXT3_JOURNAL_START(inode->i_sb, handle, EXT3_XATTR_TRANS_BLOCKS, err);
+ if(err)
+ RETURN(err);
+
+ err = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX,
+ EXT3_SNAP_GENERATION, (char*)&gen,
+ sizeof(int), 0);
if (err < 0) {
CERROR("ino %lu, set_ext_attr err %d\n", inode->i_ino, err);
RETURN(err);
}
- ext3_journal_stop(handle, inode);
+ journal_stop(handle);
RETURN(0);
}
dst->i_mtime = src->i_mtime;
dst->i_ctime = src->i_ctime;
// dst->i_version = src->i_version;
- dst->i_attr_flags = src->i_attr_flags;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ dst->i_attr_flags = src->i_attr_flags;
+#endif
dst->i_generation = src->i_generation;
- dst->u.ext3_i.i_dtime = src->u.ext3_i.i_dtime;
- dst->u.ext3_i.i_flags = src->u.ext3_i.i_flags | EXT3_COW_FL;
+ EXT3_I(dst)->i_dtime = EXT3_I(src)->i_dtime;
+ EXT3_I(dst)->i_flags = EXT3_I(src)->i_flags | EXT3_COW_FL;
#ifdef EXT3_FRAGMENTS
- dst->u.ext3_i.i_faddr = src->u.ext3_i.i_faddr;
- dst->u.ext3_i.i_frag_no = src->u.ext3_i.i_frag_no;
- dst->u.ext3_i.i_frag_size = src->u.ext3_i.i_frag_size;
+ EXT3_I(dst)->i_faddr = EXT3_I(src)->i_faddr;
+ EXT3_I(dst)->i_frag_no = EXT3_I(src)->i_frag_no;
+ EXT3_I(dst)->i_frag_size = EXT3_I(src)->i_frag_size;
#endif
if ((size = ext3_xattr_list(src, NULL, 0)) > 0) {
char names[size];
if (ext3_xattr_get(src, EXT3_SNAP_INDEX,
EXT3_SNAP_ATTR, buf, attrlen) < 0)
continue;
- if (ext3_xattr_set(handle, dst, EXT3_SNAP_INDEX,
- EXT3_SNAP_ATTR, buf, attrlen, 0) < 0)
+ if (ext3_xattr_set_handle(handle, dst, EXT3_SNAP_INDEX,
+ EXT3_SNAP_ATTR, buf, attrlen,
+ 0) < 0)
break;
OBD_FREE(buf, attrlen);
name += namelen + 1; /* skip name and trailing NUL */
rc = 1;
dst_page_unlock:
kunmap(dst_page);
- UnlockPage(dst_page);
+ unlock_page(dst_page);
page_cache_release(dst_page);
src_page_unlock:
kunmap(src_page);
struct buffer_head *bh_dst = NULL, *bh_src = NULL;
int rc = 0;
handle_t *handle = NULL;
- ENTRY;
- handle = ext3_journal_start(dst, SNAP_COPYBLOCK_TRANS_BLOCKS);
- if( !handle )
- RETURN(-EINVAL);
+ ENTRY;
+
+ EXT3_JOURNAL_START(dst->i_sb, handle, SNAP_COPYBLOCK_TRANS_BLOCKS, rc);
+ if(rc)
+ RETURN(rc);
bh_src = ext3_bread(handle, src, blk, 0, &rc);
if (!bh_src) {
if (bh_src) brelse(bh_src);
if (bh_dst) brelse(bh_dst);
if (handle)
- ext3_journal_stop(handle, dst);
+ journal_stop(handle);
RETURN(rc);
}
/* fsfilt_ext3_copy_block - copy one data block from inode @src to @dst.
static void fs_flushinval_pages(handle_t *handle, struct inode* inode)
{
if (inode->i_blocks > 0 && inode->i_mapping) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
fsync_inode_data_buffers(inode);
+#endif
truncate_inode_pages(inode->i_mapping, 0);
}
}
{
unsigned long blocks, blk, cur_blks;
int low_credits, save_ref;
+ int err = 0;
ENTRY;
blocks =(src->i_size + src->i_sb->s_blocksize-1) >>
ext3_orphan_add(handle, dst);
*has_orphan = 1;
}
- dst->u.ext3_i.i_disksize =
+ EXT3_I(dst)->i_disksize =
blk * dst->i_sb->s_blocksize;
dst->i_blocks = cur_blks;
dst->i_mtime = CURRENT_TIME;
*/
save_ref = handle->h_ref;
handle->h_ref = 1;
- if( ext3_journal_stop(handle, dst) ){
+ if(journal_stop(handle) ){
CERROR("fail to stop journal\n");
handle = NULL;
break;
}
- handle = ext3_journal_start(dst,
- low_credits + needed);
- if( !handle ){
- CERROR("fail to restart handle\n");
- break;
- }
+ EXT3_JOURNAL_START(dst->i_sb, handle,
+ low_credits + needed, err);
+ if(err) break;
handle->h_ref = save_ref;
}
}
cur_blks += dst->i_sb->s_blocksize / 512;
}
- dst->i_size = dst->u.ext3_i.i_disksize = src->i_size;
+ dst->i_size = EXT3_I(dst)->i_disksize = src->i_size;
RETURN(handle);
}
/*Here delete the data of that pri inode
{
struct inode *tmp = NULL;
ENTRY;
-
tmp = ext3_new_inode(handle, inode, (int)inode->i_mode, 0);
if(tmp) {
CERROR("ext3_new_inode error\n");
RETURN(-EIO);
}
- double_down(&inode->i_sem, &tmp->i_sem);
+ double_lock_inode(inode, tmp);
ext3_migrate_data(handle, tmp, inode);
- double_up(&inode->i_sem, &tmp->i_sem);
+ double_unlock_inode(inode, tmp);
tmp->i_nlink = 0;
iput(tmp);
RETURN(0);
{
struct inode *ind = NULL;
handle_t *handle = NULL;
- int err = 0;
+ int err = 0;
int has_orphan = 0;
ENTRY;
- if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){
+ if( pri == EXT3_SB(pri->i_sb)->s_journal_inode ){
CERROR("TRY TO COW JOUNRAL\n");
RETURN(ERR_PTR(-EINVAL));
}
pri->i_ino, index, del ? "deleting" : "preserve");
ind = fsfilt_ext3_get_indirect(pri, NULL, index);
-
- handle = ext3_journal_start(pri, SNAP_CREATEIND_TRANS_BLOCKS);
- if( !handle ) {
- CERROR("handle not NULL\n");
- RETURN(ERR_PTR(-EINVAL));
- }
+
+ EXT3_JOURNAL_START(pri->i_sb, handle, SNAP_CREATEIND_TRANS_BLOCKS,
+ err);
+ if(err)
+ RETURN(ERR_PTR(err));
/* XXX ? We should pass an err argument to get_indirect and precisely
* detect the errors, for some errors, we should exit right away.
*/
GOTO(exit, err);
pri->i_nlink = 1;
}
- pri->u.ext3_i.i_dtime = CURRENT_TIME;
+ EXT3_I(pri)->i_dtime = LTIME_S(CURRENT_TIME);
ext3_mark_inode_dirty(handle, pri);
GOTO(exit, err=0);
}
/* XXX: check this, ext3_new_inode, the first arg should be "dir" */
ind = ext3_new_inode(handle, pri, (int)pri->i_mode, 0);
+
if (IS_ERR(ind))
GOTO(exit, err);
CDEBUG(D_INODE, "got new inode %lu\n", ind->i_ino);
GOTO(exit_unlock, err= -EINVAL);
}
- pri->u.ext3_i.i_flags |= EXT3_DEL_FL;
- ind->u.ext3_i.i_flags |= EXT3_COW_FL;
+ EXT3_I(pri)->i_flags |= EXT3_DEL_FL;
+ EXT3_I(ind)->i_flags |= EXT3_COW_FL;
if(S_ISREG(pri->i_mode)) pri->i_nlink = 1;
- pri->u.ext3_i.i_dtime = CURRENT_TIME;
- //pri->u.ext3_i.i_generation++;
+ EXT3_I(pri)->i_dtime = LTIME_S(CURRENT_TIME);
+ //EXT3_I(pri)->i_generation++;
ext3_mark_inode_dirty(handle, pri);
ext3_mark_inode_dirty(handle, ind);
up(&ind->i_sem);
}
}
/* set cow flag for ind */
- ind->u.ext3_i.i_flags |= EXT3_COW_FL;
- pri->u.ext3_i.i_flags &= ~EXT3_COW_FL;
+ EXT3_I(ind)->i_flags |= EXT3_COW_FL;
+ EXT3_I(pri)->i_flags &= ~EXT3_COW_FL;
ext3_mark_inode_dirty(handle, pri);
ext3_mark_inode_dirty(handle, ind);
if (!EXT3_HAS_COMPAT_FEATURE(pri->i_sb,
EXT3_FEATURE_COMPAT_SNAPFS)) {
lock_super(pri->i_sb);
- ext3_journal_get_write_access(handle, pri->i_sb->u.ext3_sb.s_sbh);
- pri->i_sb->u.ext3_sb.s_es->s_feature_compat |=
+ ext3_journal_get_write_access(handle, EXT3_SB(pri->i_sb)->s_sbh);
+ EXT3_SB(pri->i_sb)->s_es->s_feature_compat |=
cpu_to_le32(EXT3_FEATURE_COMPAT_SNAPFS);
- ext3_journal_dirty_metadata(handle, pri->i_sb->u.ext3_sb.s_sbh);
+ ext3_journal_dirty_metadata(handle, EXT3_SB(pri->i_sb)->s_sbh);
pri->i_sb->s_dirt = 1;
unlock_super(pri->i_sb);
}
ind->i_ino, ind->i_nlink);
ext3_orphan_del(handle, ind);
}
- ext3_journal_stop(handle, pri);
+ journal_stop(handle);
RETURN(ind);
ext3_orphan_del(handle, ind);
}
iput(ind);
- ext3_journal_stop(handle, pri);
+ journal_stop(handle);
RETURN(ERR_PTR(err));
}
switch (op) {
case SNAP_SET_FEATURE:
- handle = ext3_journal_start(sb->s_root->d_inode, 1);
- lock_super(sb);
- ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- SB_FEATURE_COMPAT(sb) |= cpu_to_le32(feature);
- sb->s_dirt = 1;
- ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- unlock_super(sb);
- ext3_journal_stop(handle, sb->s_root->d_inode);
- break;
case SNAP_CLEAR_FEATURE:
- handle = ext3_journal_start(sb->s_root->d_inode, 1);
+ EXT3_JOURNAL_START(sb, handle, 1, rc);
+ if(rc)
+ RETURN(rc);
lock_super(sb);
ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- SB_FEATURE_COMPAT(sb) &= ~cpu_to_le32(feature);
- ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ if (op == SNAP_SET_FEATURE)
+ SB_FEATURE_COMPAT(sb) |= cpu_to_le32(feature);
+ else
+ SB_FEATURE_COMPAT(sb) &= ~cpu_to_le32(feature);
sb->s_dirt = 1;
+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
unlock_super(sb);
- ext3_journal_stop(handle, sb->s_root->d_inode);
+ journal_stop(handle);
break;
case SNAP_HAS_FEATURE:
/*FIXME should lock super or not*/
}
err = ext3_xattr_get(primary, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
buf, EXT3_MAX_SNAP_DATA);
- if (err == -ENOATTR) {
- GOTO(err_free, ino = -ENOATTR);
+ if (err == -ENODATA) {
+ GOTO(err_free, ino = -ENODATA);
} else if (err < 0) {
CERROR(" attribute read error err=%d\n", err);
GOTO(err_free, ino = err);
int i1_d=0, i1_s=0, i2_d=0, i2_s=0, i3_d=0, i3_s=0;
int addr_per_block = EXT3_ADDR_PER_BLOCK(src->i_sb);
int addr_per_block_bits = EXT3_ADDR_PER_BLOCK_BITS(src->i_sb);
- unsigned long blksz = src->i_sb->s_blocksize;
- kdev_t ddev = dst->i_dev;
- kdev_t sdev = src->i_dev;
int physical = 0;
ENTRY;
else
RETURN(0);
}
- if(block_bmap(bread(ddev, i1_d, blksz), block))
+ if(block_bmap(sb_bread(dst->i_sb, i1_d), block))
RETURN(0);
i1_s = inode_bmap (src, EXT3_IND_BLOCK);
if( !i1_s) RETURN(0);
- physical = block_bmap(bread(sdev, i1_s, blksz), block);
+ physical = block_bmap(sb_bread(src->i_sb, i1_s), block);
if( physical) {
- block_setbmap(handle, bread(ddev, i1_d, blksz),block,
+ block_setbmap(handle, sb_bread(dst->i_sb, i1_d),block,
physical);
- block_setbmap(handle, bread(sdev, i1_s, blksz),block,0);
+ block_setbmap(handle, sb_bread(src->i_sb, i1_s),block,0);
RETURN(1);
}
else
else
RETURN(0);
}
- i2_d = block_bmap (bread (ddev, i1_d, blksz),
+ i2_d = block_bmap (sb_bread (dst->i_sb, i1_d),
block >> addr_per_block_bits);
if (!i2_d) {
if(!i1_s) RETURN(0);
- physical = block_bmap(bread (sdev, i1_s, blksz),
+ physical = block_bmap(sb_bread (src->i_sb, i1_s),
block >> addr_per_block_bits);
if(physical) {
- block_setbmap(handle, bread (ddev, i1_d,blksz),
+ block_setbmap(handle, sb_bread(dst->i_sb, i1_d),
block >> addr_per_block_bits,
physical);
- block_setbmap(handle, bread (sdev, i1_s,blksz),
+ block_setbmap(handle, sb_bread(src->i_sb, i1_s),
block >> addr_per_block_bits, 0);
RETURN(1);
}
else
RETURN(0);
}
- physical = block_bmap(bread (ddev, i2_d, blksz),
+ physical = block_bmap(sb_bread(dst->i_sb, i2_d),
block & (addr_per_block - 1));
if(physical)
RETURN(0);
else {
- i2_s = block_bmap (bread (sdev, i1_s, blksz),
+ i2_s = block_bmap (sb_bread(src->i_sb, i1_s),
block >> addr_per_block_bits);
if(!i2_s) RETURN(0);
- physical = block_bmap(bread (sdev, i2_s, blksz),
+ physical = block_bmap(sb_bread(src->i_sb, i2_s),
block & (addr_per_block - 1));
if(physical) {
- block_setbmap(handle, bread (ddev, i2_d, blksz),
+ block_setbmap(handle, sb_bread(dst->i_sb, i2_d),
block & (addr_per_block - 1), physical);
- block_setbmap(handle, bread (sdev, i2_s, blksz),
+ block_setbmap(handle, sb_bread(src->i_sb, i2_s),
block & (addr_per_block - 1), 0);
RETURN(1);
}
else
RETURN(0);
}
- i2_d = block_bmap(bread (ddev, i1_d, blksz),
+ i2_d = block_bmap(sb_bread (dst->i_sb, i1_d),
block >> (addr_per_block_bits * 2));
- if(i1_s) i2_s = block_bmap(bread(sdev, i1_s, blksz),
+ if(i1_s) i2_s = block_bmap(sb_bread(src->i_sb, i1_s),
block >> (addr_per_block_bits * 2));
if (!i2_d) {
if( !i1_s) RETURN(0);
- physical = block_bmap(bread (sdev, i1_s, blksz),
+ physical = block_bmap(sb_bread (src->i_sb, i1_s),
block >> (addr_per_block_bits * 2));
if(physical) {
- block_setbmap(handle, bread (ddev, i1_d, blksz),
+ block_setbmap(handle, sb_bread (dst->i_sb, i1_d),
block >> (addr_per_block_bits * 2), physical);
- block_setbmap(handle, bread (sdev, i1_s, blksz),
+ block_setbmap(handle, sb_bread (src->i_sb, i1_s),
block >> (addr_per_block_bits * 2), 0);
RETURN(1);
}
else
RETURN(0);
}
- i3_d = block_bmap (bread (ddev, i2_d, blksz),
+ i3_d = block_bmap (sb_bread (dst->i_sb, i2_d),
(block >> addr_per_block_bits) & (addr_per_block - 1));
- if( i2_s) i3_s = block_bmap (bread (sdev, i2_s, blksz),
+ if( i2_s) i3_s = block_bmap (sb_bread (src->i_sb, i2_s),
(block >> addr_per_block_bits) & (addr_per_block - 1));
if (!i3_d) {
if (!i2_s) RETURN(0);
- physical = block_bmap (bread (sdev, i2_s, blksz),
+ physical = block_bmap (sb_bread (src->i_sb, i2_s),
(block >> addr_per_block_bits) & (addr_per_block - 1));
if( physical) {
- block_setbmap (handle, bread (ddev, i2_d, blksz),
+ block_setbmap (handle, sb_bread (dst->i_sb, i2_d),
(block >> addr_per_block_bits) &
(addr_per_block - 1), physical);
- block_setbmap (handle, bread (sdev, i2_s, blksz),
+ block_setbmap (handle, sb_bread (src->i_sb, i2_s),
(block >> addr_per_block_bits) &
(addr_per_block - 1),0);
RETURN(1);
else
RETURN(0);
}
- physical = block_bmap (bread (ddev, i3_d, blksz),
+ physical = block_bmap (sb_bread (dst->i_sb, i3_d),
block & (addr_per_block - 1)) ;
if(physical)
RETURN(0);
else {
if(!i3_s)
RETURN(0);
- physical = block_bmap(bread(sdev, i3_s, blksz),
+ physical = block_bmap(sb_bread(src->i_sb, i3_s),
block & (addr_per_block - 1));
if(physical) {
- block_setbmap (handle, bread (ddev, i3_d, blksz),
+ block_setbmap (handle, sb_bread (dst->i_sb, i3_d),
block & (addr_per_block - 1), physical);
- block_setbmap (handle, bread (sdev, i3_s, blksz),
+ block_setbmap (handle, sb_bread (src->i_sb, i3_s),
block & (addr_per_block - 1), 0);
RETURN(1);
}
struct inode *ind;
int save = 0, i=0, err = 0;
handle_t *handle=NULL;
- time_t ctime;
ENTRY;
if (index < 0 || index > EXT3_MAX_SNAPS)
RETURN(0);
- if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){
+ if( pri == EXT3_SB(pri->i_sb)->s_journal_inode ){
CERROR("TRY TO DESTROY JOURNAL'S IND\n");
RETURN(-EINVAL);
}
CDEBUG(D_INODE, "iget ind %lu, ref count = %d\n",
ind->i_ino, atomic_read(&ind->i_count));
-
- handle = ext3_journal_start(pri, SNAP_DESTROY_TRANS_BLOCKS);
- if (!handle) {
+
+ EXT3_JOURNAL_START(pri->i_sb, handle, SNAP_DESTROY_TRANS_BLOCKS, err);
+ if (err) {
iput(ind);
- RETURN(-EINVAL);
+ RETURN(err);
}
/* if it's block level cow, first copy the blocks back */
if (EXT3_HAS_COMPAT_FEATURE(pri->i_sb, EXT3_FEATURE_COMPAT_BLOCKCOW) &&
next_ind = pri;
down(&ind->i_sem);
} else {
- double_down(&next_ind->i_sem, &ind->i_sem);
+ double_lock_inode(next_ind, ind);
}
blocks = (next_ind->i_size + next_ind->i_sb->s_blocksize-1)
>> next_ind->i_sb->s_blocksize_bits;
if (next_ind == pri)
up(&ind->i_sem);
else
- double_up(&next_ind->i_sem, &ind->i_sem);
-
+ double_unlock_inode(next_ind, ind);
}
CDEBUG(D_INODE, "delete indirect ino %lu\n", ind->i_ino);
* Otherwise, if we are deleting the last indirect inode remove the
* snaptable from the inode. XXX
*/
- if (!save && pri->u.ext3_i.i_dtime) {
+ if (!save && EXT3_I(pri)->i_dtime) {
CDEBUG(D_INODE, "deleting primary %lu\n", pri->i_ino);
pri->i_nlink = 0;
/* reset err to 0 now */
} else {
CDEBUG(D_INODE, "%s redirector table\n",
save ? "saving" : "deleting");
- /* XXX: since set ea will modify i_ctime of pri,
- so save/restore i_ctime. Need this necessary ? */
- ctime = pri->i_ctime;
- err = ext3_xattr_set(handle, pri, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
- save ? buf : NULL, EXT3_MAX_SNAP_DATA, 0);
- pri->i_ctime = ctime;
+ err = ext3_xattr_set_handle(handle, pri, EXT3_SNAP_INDEX,
+ EXT3_SNAP_ATTR, save ? buf : NULL,
+ EXT3_MAX_SNAP_DATA, 0);
ext3_mark_inode_dirty(handle, pri);
}
- ext3_journal_stop(handle, pri);
+ journal_stop(handle);
RETURN(err);
}
if (index < 0 || index > EXT3_MAX_SNAPS)
RETURN(-EINVAL);
- if( pri == pri->i_sb->u.ext3_sb.s_journal_inode ){
+ if( pri == EXT3_SB(pri->i_sb)->s_journal_inode ){
CERROR("TRY TO RESTORE JOURNAL\n");
RETURN(-EINVAL);
}
CDEBUG(D_INODE, "restore ino %lu to %lu\n", pri->i_ino, ind->i_ino);
- handle = ext3_journal_start(pri, SNAP_RESTORE_TRANS_BLOCKS);
- if( !handle )
- RETURN(-EINVAL);
+ EXT3_JOURNAL_START(pri->i_sb, handle, SNAP_RESTORE_TRANS_BLOCKS, err);
+ if(err)
+ RETURN(err);
/* first destroy all the data blocks in primary inode */
/* XXX: check this, ext3_new_inode, the first arg should be "dir" */
err = ext3_throw_inode_data(handle, pri);
CERROR("restore_indirect, new_inode err\n");
RETURN(err);
}
- double_down(&pri->i_sem, &ind->i_sem);
+ double_lock_inode(pri, ind);
ext3_migrate_data(handle, pri, ind);
- pri->u.ext3_i.i_flags &= ~EXT3_COW_FL;
+ EXT3_I(pri)->i_flags &= ~EXT3_COW_FL;
ext3_mark_inode_dirty(handle, pri);
- double_up(&pri->i_sem, &ind->i_sem);
+ double_unlock_inode(pri, ind);
iput(ind);
//fsfilt_ext3_destroy_indirect(pri, index);
- ext3_journal_stop(handle, pri);
+ journal_stop(handle);
RETURN(err);
}
ibase = gstart * EXT3_INODES_PER_GROUP(sb);
for (gnum = gstart; gnum < EXT3_SB(sb)->s_groups_count;
gnum++, ibase += EXT3_INODES_PER_GROUP(sb)) {
+ struct buffer_head *bitmap_bh = NULL;
struct ext3_group_desc * gdp;
- int bitmap_nr, ibyte;
- char *bitmap;
-
+ ino_t ino;
+
gdp = ext3_get_group_desc (sb, gnum, NULL);
if (!gdp || le16_to_cpu(gdp->bg_free_inodes_count) ==
EXT3_INODES_PER_GROUP(sb))
continue;
-
- bitmap_nr = ext3_load_inode_bitmap(sb, gnum);
- if (bitmap_nr < 0)
- continue;
-
- bitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr]->b_data;
- for (ibyte = istart >> 3; ibyte < EXT3_INODES_PER_GROUP(sb) >> 3;
- ibyte++) {
- int i, bit;
-
- if (!bitmap[ibyte])
- continue;
-
- /* FIXME need to verify if bit endianness will
- * work properly here for all architectures.
- */
- for (i = 1, bit = 1; i <= 8; i++, bit <<= 1) {
- ino_t ino = ibase + (ibyte << 3) + i;
-
- if ((bitmap[ibyte] & bit) == 0)
+ bitmap_bh = read_inode_bitmap(sb, gnum);
+
+ if (!bitmap_bh)
+ continue;
+ ino = 0;
+repeat:
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ ino = find_next_bit((unsigned long *)bitmap_bh->b_data,
+ EXT3_INODES_PER_GROUP(sb), ino);
+#else
+ ino = find_next_bit((unsigned long *)bitmap_bh->b_data,
+ EXT3_INODES_PER_GROUP(sb), ino);
+#warning"FIXME-WANGDI need to port find_next_bit to 2.4"
+#endif
+ if (ino < EXT3_INODES_PER_GROUP(sb)) {
+ ino_t inum = ino + gnum * EXT3_INODES_PER_GROUP(sb) + 1;
+ if (*start) {
+ if (inum < (*start)->i_ino)
continue;
- if (*start) {
- if (ino < (*start)->i_ino)
- continue;
- } else {
- *start = iget(sb, ino);
- if (!*start)
- GOTO(exit, err = -ENOMEM);
- if (is_bad_inode(*start))
- GOTO(exit, err = -EIO);
- }
- if ((err = (*repeat)(*start, priv)) != 0)
- GOTO(exit, err);
- iput(*start);
- *start = NULL;
+ } else {
+ *start = iget(sb, inum);
+ if (!*start)
+ GOTO(exit, err = -ENOMEM);
+ if (is_bad_inode(*start))
+ GOTO(exit, err = -EIO);
}
- }
+ if ((err = (*repeat)(*start, priv)) != 0)
+ GOTO(exit, err);
+ iput(*start);
+ *start = NULL;
+ if (++ino < EXT3_INODES_PER_GROUP(sb))
+ goto repeat;
+ }
istart = 0;
}
exit:
rc = ext3_xattr_get(inode, EXT3_SNAP_INDEX,EXT3_SNAP_GENERATION,
(char *)val, *vallen);
- if (rc == -ENOATTR) {
+ if (rc == -ENODATA) {
*((__u32 *)val) = 0;
*vallen = sizeof(int);
rc = 0;
if (keylen >= strlen(SNAPTABLE_INFO)
&& strcmp(key, SNAPTABLE_INFO) == 0) {
handle_t *handle;
-
- handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
- if( !handle )
- RETURN(-EINVAL);
- rc = ext3_xattr_set(handle, inode, EXT3_SNAP_INDEX,
- EXT3_SNAPTABLE_EA, val, *vallen, 0);
- ext3_journal_stop(handle, inode);
+ EXT3_JOURNAL_START(inode->i_sb, handle,
+ EXT3_XATTR_TRANS_BLOCKS, rc);
+ if(rc)
+ RETURN(rc);
+ rc = ext3_xattr_set_handle(handle, inode, EXT3_SNAP_INDEX,
+ EXT3_SNAPTABLE_EA, val, *vallen, 0);
+ journal_stop(handle);
RETURN(rc);
} else if (keylen >= strlen(SNAP_GENERATION)
if (cache_ind_inode && !IS_ERR(cache_ind_inode)){
/*FIXME: get indirect inode set_cow flags*/
- ind_inode = iget4(inode->i_sb, cache_ind_inode->i_ino, NULL, 0);
+ ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
+ inode, 0);
}
RETURN(ind_inode);
}
if (ino == 0)
RETURN(ERR_PTR(-ESTALE));
-#ifdef CONFIG_SNAPFS
- if (is_smfs_sb(mds->mds_sb)) {
- snprintf(fid_name, sizeof(fid_name), "0x%lx:%lx", ino,
- fid->snap_index);
- } else {
- snprintf(fid_name, sizeof(fid_name), "0x%lx", ino);
- }
-#else
snprintf(fid_name, sizeof(fid_name), "0x%lx", ino);
-#endif
CDEBUG(D_DENTRY, "--> mds_fid2dentry: ino/gen %lu/%u, sb %p\n",
ino, generation, mds->mds_sb);
void mds_pack_inode2fid(struct obd_device *obd, struct ll_fid *fid,
struct inode *inode)
{
-#ifdef CONFIG_SNAPFS
- if (is_smfs_sb(inode->i_sb)) {
- struct smfs_inode_info *sm_info = I2SMI(inode);
- fid->snap_index = sm_info->sm_sninfo.sn_index;
- }
-#endif
fid->id = inode->i_ino;
fid->generation = inode->i_generation;
fid->f_type = (S_IFMT & inode->i_mode);
}
created = 1;
- LTIME_S(iattr.ia_atime) = LTIME_S(rec->ur_time);
- LTIME_S(iattr.ia_ctime) = LTIME_S(rec->ur_time);
- LTIME_S(iattr.ia_mtime) = LTIME_S(rec->ur_time);
+ LTIME_S(iattr.ia_atime) = rec->ur_time;
+ LTIME_S(iattr.ia_ctime) = rec->ur_time;
+ LTIME_S(iattr.ia_mtime) = rec->ur_time;
iattr.ia_uid = rec->_ur_fsuid;
if (dparent->d_inode->i_mode & S_ISGID)
* it is more out-of-date than the specified limit. If we
* are already going to write out the atime then do it anyway.
* */
- if ((LTIME_S(request_body->atime) >
+ if ((request_body->atime >
LTIME_S(inode->i_atime) + MAX_ATIME_DIFF) ||
(iattr.ia_valid != 0 &&
- LTIME_S(request_body->atime) > LTIME_S(inode->i_atime))) {
- LTIME_S(iattr.ia_atime) = LTIME_S(request_body->atime);
+ request_body->atime > LTIME_S(inode->i_atime))) {
+ LTIME_S(iattr.ia_atime) = request_body->atime;
iattr.ia_valid |= ATTR_ATIME;
}
}
struct mds_body *body;
created = 1;
- LTIME_S(iattr.ia_atime) = LTIME_S(rec->ur_time);
- LTIME_S(iattr.ia_ctime) = LTIME_S(rec->ur_time);
- LTIME_S(iattr.ia_mtime) = LTIME_S(rec->ur_time);
+ LTIME_S(iattr.ia_atime) = rec->ur_time;
+ LTIME_S(iattr.ia_ctime) = rec->ur_time;
+ LTIME_S(iattr.ia_mtime) = rec->ur_time;
iattr.ia_uid = rec->_ur_fsuid;
if (dir->i_mode & S_ISGID)
iattr.ia_gid = dir->i_gid;
int err;
iattr.ia_valid = ATTR_MTIME | ATTR_CTIME;
- LTIME_S(iattr.ia_mtime) = LTIME_S(rec->ur_time);
- LTIME_S(iattr.ia_ctime) = LTIME_S(rec->ur_time);
+ LTIME_S(iattr.ia_mtime) = rec->ur_time;
+ LTIME_S(iattr.ia_ctime) = rec->ur_time;
err = fsfilt_setattr(obd, dparent, handle, &iattr, 0);
if (err)
MODULES := smfs
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
+smfs-objs += sysctl.o file.o symlink.o smfs_lib.o kml.o journal.o smfs_llog.o
smfs-objs += mds_kml.o ost_kml.o
@SNAPFS_TRUE@smfs-objs += smfs_cow.o
@INCLUDE_RULES@
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->dirty_inode)
sops->dirty_inode = smfs_sops->dirty_inode;
if (cache_sb->s_op->write_inode)
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;
if (cache_sb->s_op->show_options)
sops->show_options = smfs_sops->show_options;
-
+ sops->read_inode2 = smfs_sops->read_inode2;
+#endif
/* FIXME-WANGDI we need this method to clear the cache inode. */
sops->clear_inode = smfs_sops->clear_inode;
- sops->read_inode2 = smfs_sops->read_inode2;
}
lock_kernel();
sb->s_op = cache_sops(smb);
return;
}
-struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook,
- smfs_hook_func post_hook)
-{
- struct smfs_hook_ops *smfs_hops = NULL;
-
- ENTRY;
- OBD_ALLOC(smfs_hops, sizeof(struct smfs_hook_ops));
-
- if (!smfs_hops)
- RETURN(NULL);
-
- OBD_ALLOC(smfs_hops->smh_name, strlen(name) + 1);
-
- if (!smfs_hops->smh_name) {
- OBD_FREE(smfs_hops, sizeof(struct smfs_hook_ops));
- RETURN(NULL);
- }
-
- memcpy(smfs_hops->smh_name, name, strlen(name));
-
- smfs_hops->smh_post_op = post_hook;
- smfs_hops->smh_pre_op = pre_hook;
-
- RETURN(smfs_hops);
-}
-void smfs_free_hook_ops(struct smfs_hook_ops *hops)
-{
- if (hops) {
- if (hops->smh_name){
- OBD_FREE(hops->smh_name, strlen(hops->smh_name) + 1);
- }
- OBD_FREE(hops, sizeof(struct smfs_hook_ops));
- }
-}
-
-int smfs_register_hook_ops(struct super_block *sb,
- struct smfs_hook_ops *smh_ops)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- struct list_head *hlist = &smb->smsi_hook_list;
- struct list_head *p;
- ENTRY;
-
- list_for_each(p, hlist) {
- struct smfs_hook_ops *found;
- found = list_entry(p, struct smfs_hook_ops, smh_list);
- if (!strcmp(found->smh_name, smh_ops->smh_name)) {
- CWARN("hook ops %s list reregister\n", smh_ops->smh_name);
- RETURN(0);
- }
- }
- list_add(&smh_ops->smh_list, hlist);
- RETURN(0);
-}
-struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
- char *name)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- struct list_head *hlist = &smb->smsi_hook_list;
- struct list_head *p;
- ENTRY;
-
- list_for_each(p, hlist) {
- struct smfs_hook_ops *found;
-
- found = list_entry(p, typeof(*found), smh_list);
- if (!memcmp(found->smh_name, name, strlen(name))) {
- list_del(p);
- RETURN(found);
- }
- }
- RETURN(NULL);
-}
-
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
-
-static void smfs_read_inode(struct inode *inode)
+static void smfs_init_cache_inode (struct inode *inode, void *opaque)
{
- struct inode *cache_inode;
- ENTRY;
-
- if (!inode)
- return;
-
- CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
-
+ struct smfs_inode_info *sm_info = (struct smfs_inode_info *)opaque;
+ struct inode *cache_inode = NULL;
+
cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
-
- I2CI(inode) = cache_inode;
+ if (sm_info)
+ memcpy(I2SMI(inode), sm_info, sizeof(struct smfs_inode_info));
+
+ I2CI(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));
- return;
+#if CONFIG_SNAPFS
+ if (sm_info) {
+ smfs_init_snap_inode_info(inode, &sm_info->sm_sninfo);
+ }
+#endif
}
static void smfs_read_inode2(struct inode *inode, void *opaque)
{
- struct inode *cache_inode;
ENTRY;
-
if (!inode)
return;
CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
-
- cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino);
-
- if (opaque)
- I2SMI(inode)->smi_flags = *((int *)opaque);
-
- I2CI(inode) = cache_inode;
-
- post_smfs_inode(inode, cache_inode);
- sm_set_inode_ops(cache_inode, inode);
-#if CONFIG_SNAPFS
- if (opaque)
- smfs_init_snap_inode_info(inode, *((int *)opaque));
-#endif
+ smfs_init_cache_inode(inode, opaque);
CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
inode->i_ino, atomic_read(&inode->i_count));
+ EXIT;
return;
}
-/* Although some filesystem(such as ext3) do not have
- * clear_inode method, but we need it to free the
- * cache inode
- */
-static void smfs_clear_inode(struct inode *inode)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static int smfs_test_inode(struct inode *inode, unsigned long ino,
+ void *opaque)
+#else
+static int smfs_test_inode(struct inode *inode, void *opaque)
+#endif
{
- struct inode *cache_inode;
+ struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
+ struct snap_inode_info *test_info = (struct snap_inode_info *)opaque;
+
+ if (!sn_info || !test_info)
+ return 0;
+ if (sn_info->sn_index != test_info->sn_index)
+ return 0;
+ if (sn_info->sn_gen != test_info->sn_gen)
+ return 0;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ smfs_init_cache_inode(inode, opaque);
+#endif
+ return 1;
+}
- ENTRY;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+int smfs_set_inode(struct inode *inode, void *opaque)
+{
+ smfs_read_inode2(inode, opaque);
+ return 0;
+}
- if (!inode) return;
+struct inode *smfs_iget(struct super_block *sb, ino_t hash,
+ struct smfs_inode_info *si_info)
+{
+ struct inode *inode;
- cache_inode = I2CI(inode);
+ LASSERT(hash != 0);
+ inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode,
+ si_info);
- /* 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 (cache_inode != cache_inode->i_sb->s_root->d_inode) {
- struct list_head *lp;
- struct dentry *tmp;
- while (!list_empty(&cache_inode->i_dentry)) {
- lp = cache_inode->i_dentry.next;
- tmp = list_entry(lp, struct dentry, d_alias);
- if (atomic_read(&tmp->d_count) >= 1)
- post_smfs_dentry(tmp);
- }
- if (atomic_read(&cache_inode->i_count) < 1)
- LBUG();
-
- 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;
+ if (inode) {
+ if (inode->i_state & I_NEW)
+ unlock_new_inode(inode);
+ CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
+ inode->i_generation, inode);
}
- return;
+ return inode;
}
+#else
+struct inode *smfs_iget(struct super_block *sb, ino_t hash,
+ struct smfs_inode_info *si_info)
+{
+ struct inode *inode;
+ LASSERT(hash != 0);
+
+ inode = iget4(sb, hash, smfs_test_inode, si_info);
+ if (inode)
+ CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
+ inode->i_generation, inode);
+ return inode;
+}
+#endif
+struct inode *smfs_get_inode (struct super_block *sb, ino_t hash,
+ struct inode *dir, int index)
+{
+ struct smfs_inode_info sm_info;
+ struct inode *inode = NULL;
+ ENTRY;
+
+ sm_info.smi_flags = I2SMI(dir)->smi_flags;
+ sm_info.sm_sninfo.sn_flags = I2SMI(dir)->sm_sninfo.sn_flags;
+ sm_info.sm_sninfo.sn_index = index;
+ sm_info.sm_sninfo.sn_gen = I2SMI(dir)->sm_sninfo.sn_gen;
+ inode = smfs_iget(sb, hash, &sm_info);
+
+ RETURN(inode);
+}
+EXPORT_SYMBOL(smfs_get_inode);
static void smfs_delete_inode(struct inode *inode)
{
struct inode *cache_inode;
CWARN("cache inode null\n");
return;
}
+
+ if (atomic_read(&cache_inode->i_count) > 1 &&
+ cache_inode != cache_inode->i_sb->s_root->d_inode)
+ iput(cache_inode);
+
if (S2CSB(inode->i_sb)->s_op->put_inode)
S2CSB(inode->i_sb)->s_op->put_inode(cache_inode);
-
+
EXIT;
}
S2CSB(sb)->s_op->write_super(S2CSB(sb));
duplicate_sb(sb, S2CSB(sb));
EXIT;
+ return;
+}
+
+static void smfs_clear_inode(struct inode *inode)
+{
+ struct inode *cache_inode;
+
+ ENTRY;
+
+ if (!inode) return;
+
+ cache_inode = I2CI(inode);
+
+ if (cache_inode != cache_inode->i_sb->s_root->d_inode) {
+ iput(cache_inode);
+ SMFS_CLEAN_INODE_REC(inode);
+ I2CI(inode) = NULL;
+ }
+ EXIT;
+ return;
}
static void smfs_write_super_lockfs(struct super_block *sb)
RETURN(rc);
}
-
static int smfs_remount(struct super_block *sb, int *flags, char *data)
{
struct super_block *cache_sb;
duplicate_sb(sb, cache_sb);
RETURN(rc);
}
-
struct super_operations smfs_super_ops = {
- .read_inode = smfs_read_inode,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
.read_inode2 = smfs_read_inode2,
+#endif
.clear_inode = smfs_clear_inode,
.put_super = smfs_put_super,
.delete_inode = smfs_delete_inode,
.statfs = smfs_statfs, /* BKL held */
.remount_fs = smfs_remount, /* BKL held */
};
+
+int is_smfs_sb(struct super_block *sb)
+{
+ return (sb->s_op->put_super == smfs_super_ops.put_super);
+}
+EXPORT_SYMBOL(is_smfs_sb);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/smfs/sm_fs.c
- * Lustre filesystem abstraction routines
- *
- * 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
-
-#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_fsfilt.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);
-
-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 smfs, %d\n", err);
- return -EINVAL;
- }
-
- if ( (err = init_smfs_proc_sys()) ) {
- printk("Error initializing smfs proc sys, %d\n", err);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void __exit smfs_cleanup(void)
-{
- cleanup_smfs();
- smfs_cleanup_psdev();
-}
-module_init(smfs_init);
-module_exit(smfs_cleanup);
strlen(SNAPTABLE_INFO),
snap_table, &table_size);
if (rc < 0) {
- if (rc == -ENOATTR) {
+ if (rc == -ENODATA) {
snap_table->sntbl_count = 0;
CDEBUG(D_INFO, "No snaptable here\n");
RETURN(0);
{
struct snap_info *snap_info = S2SNAPI(sb);
struct snap_table *table = snap_info->sntbl;
- time_t now = CURRENT_TIME;
+ time_t now = LTIME_S(CURRENT_TIME);
int i ;
ENTRY;
snap_item = &snap_table->sntbl_items[count];
/*add item in snap_table set generation*/
- snap_item->sn_time = CURRENT_TIME;
+ snap_item->sn_time = LTIME_S(CURRENT_TIME);
/* find table index */
index = get_index_of_item(snap_table, name);
if (index < 0)
struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
char *name);
-/*super.c*/
-extern int init_smfs(void);
-extern int cleanup_smfs(void);
-extern void smfs_put_super(struct super_block *sb);
+/*smfs_lib.c*/
+void smfs_put_super(struct super_block *sb);
extern struct super_block *smfs_get_sb_by_path(char *path, int len);
+int smfs_fill_super(struct super_block *sb, void *data, int silent);
/*sysctl.c*/
extern int sm_debug_level;
extern int sm_inodes;
/*inode.c*/
struct inode *smfs_get_inode(struct super_block *sb, ino_t hash,
struct inode *dir, int index);
+
extern struct super_operations smfs_super_ops;
+
/*symlink.c*/
extern struct inode_operations smfs_sym_iops;
extern struct file_operations smfs_sym_fops;
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * lustre/smfs/super.c
+ * Lustre filesystem abstraction routines
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/utime.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/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 <linux/lustre_fsfilt.h>
+#include <linux/lustre_smfs.h>
+#include "smfs_internal.h"
+static char *smfs_options(char *data, char **devstr, char **namestr,
+ int *kml, int *cache, char **opts, int *iopen_nopriv,
+ int *cow)
+{
+ 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 if (!strcmp(opt_value->opt, "snap")) {
+ *cow = 1;
+ } else {
+ break;
+ }
+ }
+ return pos;
+}
+
+struct super_block *smfs_get_sb_by_path(char *path, int len)
+{
+ 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);
+}
+
+static int smfs_init_fsfilt_ops(struct super_block *sb)
+{
+ ENTRY;
+ if (!S2SMI(sb)->sm_cache_fsfilt) {
+ S2SMI(sb)->sm_cache_fsfilt =
+ fsfilt_get_ops(S2SMI(sb)->smsi_cache_ftype);
+ if (!S2SMI(sb)->sm_cache_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by kml\n",
+ S2SMI(sb)->smsi_cache_ftype);
+ RETURN(-EINVAL);
+ }
+ }
+ if (!S2SMI(sb)->sm_fsfilt) {
+ S2SMI(sb)->sm_fsfilt =
+ fsfilt_get_ops(S2SMI(sb)->smsi_ftype);
+ if (!S2SMI(sb)->sm_fsfilt) {
+ CERROR("Can not get %s fsfilt ops needed by kml\n",
+ S2SMI(sb)->smsi_ftype);
+ RETURN(-EINVAL);
+ }
+ }
+ RETURN(0);
+}
+
+void smfs_cleanup_fsfilt_ops(struct super_block *sb)
+{
+ 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);
+}
+
+static int sm_mount_cache(struct super_block *sb, char *devstr,
+ char *typestr, char *opts, int iopen_nopriv)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ 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);
+
+ 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)) {
+ CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
+ GOTO(err_out, err = PTR_ERR(mnt));
+ }
+
+ smb->smsi_sb = mnt->mnt_sb;
+ smb->smsi_mnt = mnt;
+
+ smfs_init_sm_ops(smb);
+
+ OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
+ memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
+
+ OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
+ memcpy(smb->smsi_ftype, 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:
+ return err;
+}
+
+static int sm_umount_cache(struct super_block *sb)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+
+ iput(S2CSB(sb)->s_root->d_inode);
+ dput(S2CSB(sb)->s_root);
+ mntput(smb->smsi_mnt);
+ smfs_cleanup_sm_ops(smb);
+ smfs_cleanup_fsfilt_ops(sb);
+
+ if (smb->smsi_cache_ftype)
+ OBD_FREE(smb->smsi_cache_ftype,
+ strlen(smb->smsi_cache_ftype) + 1);
+ if (smb->smsi_ftype)
+ OBD_FREE(smb->smsi_ftype, strlen(smb->smsi_ftype) + 1);
+
+ return 0;
+}
+
+static int smfs_init_hook_ops(struct super_block *sb)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ ENTRY;
+
+ INIT_LIST_HEAD(&smb->smsi_hook_list);
+
+ RETURN(0);
+}
+static void smfs_cleanup_hook_ops(struct super_block *sb)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_hook_list;
+ ENTRY;
+
+ while (!list_empty(hlist)) {
+ struct smfs_hook_ops *smfs_hops;
+
+ smfs_hops = list_entry(hlist->next, struct smfs_hook_ops,
+ smh_list);
+ CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);
+
+ smfs_unregister_hook_ops(sb, smfs_hops->smh_name);
+ smfs_free_hook_ops(smfs_hops);
+ }
+ EXIT;
+ return;
+}
+
+void smfs_put_super(struct super_block *sb)
+{
+ if (SMFS_CACHE_HOOK(S2SMI(sb)))
+ cache_space_hook_exit(sb);
+ if (SMFS_DO_REC(S2SMI(sb)))
+ smfs_rec_cleanup(sb);
+#if CONFIG_SNAPFS
+ if (SMFS_DO_COW(S2SMI(sb)))
+ smfs_cow_cleanup(sb);
+#endif
+ smfs_cleanup_hook_ops(sb);
+
+ if (sb)
+ sm_umount_cache(sb);
+ return;
+}
+int smfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ 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, do_cow = 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, &do_cow);
+
+ 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\n", devstr, typestr);
+ GOTO(out_err, 0);
+ }
+
+ err = smfs_init_hook_ops(sb);
+ if (err) {
+ CERROR("Can not init super hook ops err %d\n", err);
+ GOTO(out_err, 0);
+ }
+
+ 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 CONFIG_SNAPFS
+ if (do_cow) smfs_cow_init(sb);
+#endif
+
+#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();
+ return err;
+}
+struct smfs_hook_ops *smfs_alloc_hook_ops(char *name, smfs_hook_func pre_hook,
+ smfs_hook_func post_hook)
+{
+ struct smfs_hook_ops *smfs_hops = NULL;
+
+ ENTRY;
+ OBD_ALLOC(smfs_hops, sizeof(struct smfs_hook_ops));
+
+ if (!smfs_hops)
+ RETURN(NULL);
+
+ OBD_ALLOC(smfs_hops->smh_name, strlen(name) + 1);
+
+ if (!smfs_hops->smh_name) {
+ OBD_FREE(smfs_hops, sizeof(struct smfs_hook_ops));
+ RETURN(NULL);
+ }
+
+ memcpy(smfs_hops->smh_name, name, strlen(name));
+
+ smfs_hops->smh_post_op = post_hook;
+ smfs_hops->smh_pre_op = pre_hook;
+
+ RETURN(smfs_hops);
+}
+
+void smfs_free_hook_ops(struct smfs_hook_ops *hops)
+{
+ if (hops) {
+ if (hops->smh_name){
+ OBD_FREE(hops->smh_name, strlen(hops->smh_name) + 1);
+ }
+ OBD_FREE(hops, sizeof(struct smfs_hook_ops));
+ }
+}
+
+int smfs_register_hook_ops(struct super_block *sb,
+ struct smfs_hook_ops *smh_ops)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_hook_list;
+ struct list_head *p;
+ ENTRY;
+
+ list_for_each(p, hlist) {
+ struct smfs_hook_ops *found;
+ found = list_entry(p, struct smfs_hook_ops, smh_list);
+ if (!strcmp(found->smh_name, smh_ops->smh_name)) {
+ CWARN("hook ops %s list reregister\n", smh_ops->smh_name);
+ RETURN(0);
+ }
+ }
+ list_add(&smh_ops->smh_list, hlist);
+ RETURN(0);
+}
+struct smfs_hook_ops *smfs_unregister_hook_ops(struct super_block *sb,
+ char *name)
+{
+ struct smfs_super_info *smb = S2SMI(sb);
+ struct list_head *hlist = &smb->smsi_hook_list;
+ struct list_head *p;
+ ENTRY;
+
+ list_for_each(p, hlist) {
+ struct smfs_hook_ops *found;
+
+ found = list_entry(p, typeof(*found), smh_list);
+ if (!memcmp(found->smh_name, name, strlen(name))) {
+ list_del(p);
+ RETURN(found);
+ }
+ }
+ RETURN(NULL);
+}
+
#include <linux/lustre_smfs.h>
#include "smfs_internal.h"
-static char *smfs_options(char *data, char **devstr, char **namestr,
- int *kml, int *cache, char **opts, int *iopen_nopriv,
- int *cow)
-{
- 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 if (!strcmp(opt_value->opt, "snap")) {
- *cow = 1;
- } else {
- break;
- }
- }
- return pos;
-}
-
-struct super_block *smfs_get_sb_by_path(char *path, int len)
-{
- 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);
-}
-
-static int smfs_init_fsfilt_ops(struct super_block *sb)
-{
- ENTRY;
- if (!S2SMI(sb)->sm_cache_fsfilt) {
- S2SMI(sb)->sm_cache_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_cache_ftype);
- if (!S2SMI(sb)->sm_cache_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_cache_ftype);
- RETURN(-EINVAL);
- }
- }
- if (!S2SMI(sb)->sm_fsfilt) {
- S2SMI(sb)->sm_fsfilt =
- fsfilt_get_ops(S2SMI(sb)->smsi_ftype);
- if (!S2SMI(sb)->sm_fsfilt) {
- CERROR("Can not get %s fsfilt ops needed by kml\n",
- S2SMI(sb)->smsi_ftype);
- RETURN(-EINVAL);
- }
- }
- RETURN(0);
-}
-
-void smfs_cleanup_fsfilt_ops(struct super_block *sb)
-{
- 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);
-}
-
-static int sm_mount_cache(struct super_block *sb, char *devstr,
- char *typestr, char *opts, int iopen_nopriv)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- 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);
-
- 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)) {
- CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
- GOTO(err_out, err = PTR_ERR(mnt));
- }
-
- smb->smsi_sb = mnt->mnt_sb;
- smb->smsi_mnt = mnt;
-
- smfs_init_sm_ops(smb);
-
- OBD_ALLOC(smb->smsi_cache_ftype, strlen(typestr) + 1);
- memcpy(smb->smsi_cache_ftype, typestr, strlen(typestr));
-
- OBD_ALLOC(smb->smsi_ftype, strlen(SMFS_TYPE) + 1);
- memcpy(smb->smsi_ftype, 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:
- return err;
-}
-
-static int sm_umount_cache(struct super_block *sb)
-{
- struct smfs_super_info *smb = S2SMI(sb);
-
- iput(S2CSB(sb)->s_root->d_inode);
- dput(S2CSB(sb)->s_root);
- mntput(smb->smsi_mnt);
- smfs_cleanup_sm_ops(smb);
- smfs_cleanup_fsfilt_ops(sb);
-
- if (smb->smsi_cache_ftype)
- OBD_FREE(smb->smsi_cache_ftype,
- strlen(smb->smsi_cache_ftype) + 1);
- if (smb->smsi_ftype)
- OBD_FREE(smb->smsi_ftype, strlen(smb->smsi_ftype) + 1);
-
- return 0;
-}
-
-static int smfs_init_hook_ops(struct super_block *sb)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- ENTRY;
-
- INIT_LIST_HEAD(&smb->smsi_hook_list);
-
- RETURN(0);
-}
-static void smfs_cleanup_hook_ops(struct super_block *sb)
-{
- struct smfs_super_info *smb = S2SMI(sb);
- struct list_head *hlist = &smb->smsi_hook_list;
- ENTRY;
-
- while (!list_empty(hlist)) {
- struct smfs_hook_ops *smfs_hops;
-
- smfs_hops = list_entry(hlist->next, struct smfs_hook_ops,
- smh_list);
- CERROR("Unregister %s hook ops\n", smfs_hops->smh_name);
-
- smfs_unregister_hook_ops(sb, smfs_hops->smh_name);
- smfs_free_hook_ops(smfs_hops);
- }
- EXIT;
- return;
-}
-
-void smfs_put_super(struct super_block *sb)
-{
- if (SMFS_CACHE_HOOK(S2SMI(sb)))
- cache_space_hook_exit(sb);
- if (SMFS_DO_REC(S2SMI(sb)))
- smfs_rec_cleanup(sb);
-#if CONFIG_SNAPFS
- if (SMFS_DO_COW(S2SMI(sb)))
- smfs_cow_cleanup(sb);
-#endif
- smfs_cleanup_hook_ops(sb);
-
- if (sb)
- sm_umount_cache(sb);
- return;
-}
-static int smfs_fill_super(struct super_block *sb,
- void *data, int silent)
-{
- 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, do_cow = 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, &do_cow);
-
- 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\n", devstr, typestr);
- GOTO(out_err, 0);
- }
-
- err = smfs_init_hook_ops(sb);
- if (err) {
- CERROR("Can not init super hook ops err %d\n", err);
- GOTO(out_err, 0);
- }
-
- 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 CONFIG_SNAPFS
- if (do_cow) smfs_cow_init(sb);
-#endif
-
-#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();
- 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)
+static struct super_block *smfs_read_super(struct super_block *sb, void *data,
+ int silent)
{
int err;
return sb;
}
+
+static struct file_system_type smfs_type = {
+ .owner = THIS_MODULE,
+ .name = "smfs",
+ .read_super = smfs_read_super,
+};
#else
-struct super_block *smfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+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 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
};
+#endif
-int init_smfs(void)
+static int init_smfs(void)
{
int err;
return err;
}
-int cleanup_smfs(void)
+static int cleanup_smfs(void)
{
int err = 0;
CERROR("unregister_filesystem() failed, rc = %d\n", err);
return 0;
}
+
+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 smfs, %d\n", err);
+ return -EINVAL;
+ }
+
+ if ( (err = init_smfs_proc_sys()) ) {
+ printk("Error initializing smfs proc sys, %d\n", err);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void __exit smfs_cleanup(void)
+{
+ cleanup_smfs();
+ smfs_cleanup_psdev();
+}
+
+MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
+MODULE_DESCRIPTION("Smfs file system filters v0.01");
+MODULE_LICENSE("GPL");
+
+module_init(smfs_init);
+module_exit(smfs_cleanup);