int (* fs_is_indirect)(struct inode *inode);
struct inode * (* fs_create_indirect)(struct inode *pri, int index,
- unsigned int gen, struct inode *parent,
+ unsigned int gen,
+ struct inode *parent,
int del);
struct inode * (* fs_get_indirect)(struct inode *pri, int *table,
int slot);
- ino_t (* fs_get_indirect_ino)(struct inode *pri, int index);
+ ino_t (* fs_get_indirect_ino)(struct super_block *sb, ino_t pri,
+ int index);
int (* fs_destroy_indirect)(struct inode *pri, int index,
struct inode *next_ind);
int (* fs_restore_indirect)(struct inode *pri, int index);
int (* fs_iterate)(struct super_block *sb,
int (*repeat)(struct inode *inode, void *priv),
struct inode **start, void *priv, int flag);
- int (* fs_copy_block)(struct inode *dst, struct inode *src, int blk);
+ int (* fs_copy_block)(struct inode *dst, struct inode *src,
+ int blk);
int (* fs_set_indirect)(struct inode *pri, int index,
ino_t ind_ino, ino_t parent_ino);
- int (* fs_snap_feature)(struct super_block *sb, int feature, int op);
- int (* fs_set_snap_info)(struct inode *inode, void* key, __u32 keylen,
- void *val, __u32 *vallen);
- int (* fs_get_snap_info)(struct inode *inode, void* key, __u32 keylen,
- void *val, __u32 *vallen);
+ int (* fs_snap_feature)(struct super_block *sb, int feature,
+ int op);
+ int (* fs_set_snap_info)(struct inode *inode, void* key,
+ __u32 keylen, void *val, __u32 *vallen);
+ int (* fs_get_snap_info)(struct inode *inode, void* key,
+ __u32 keylen, void *val, __u32 *vallen);
int (* fs_set_snap_item)(struct super_block *sb, char *name);
+ int (* fs_read_dotsnap_dir_page)(struct file *file, char *buf,
+ size_t count, loff_t *ppos);
+ int (* fs_dir_ent_size)(char *name);
+ int (* fs_set_dir_ent)(struct super_block *sb, char *name,
+ char *buf, int buf_off, int nlen,
+ size_t count);
};
extern int fsfilt_register_ops(struct fsfilt_operations *fs_ops);
__u32 generation;
__u32 f_type;
__u32 mds;
- __u32 padding;
+ __u16 snap_index;
+ __u16 padding;
};
struct mea_old {
/* this lock protects s_d_w and p_w_ll */
spinlock_t lli_lock;
int lli_send_done_writing;
+
+ int lli_snap_index;
+
struct list_head lli_pending_write_llaps;
struct list_head lli_close_item;
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;
}
#define __LUSTRE_SMFS_H
struct snap_inode_info {
- int sn_flags; /* the flags indicated inode type */
+ int sn_flags; /*the flags indicated inode type */
int sn_gen; /*the inode generation*/
+ int sn_index; /*the inode snap_index*/
};
struct smfs_inode_info {
struct inode *smi_inode;
dput(dentry); /* this will free the dentry memory */
}
+static inline int smfs_get_dentry_name_index(struct dentry *dentry,
+ struct qstr *str,
+ int *index)
+{
+ char *name = (char *)dentry->d_name.name;
+ unsigned long hash;
+ unsigned char c;
+ char *str_name;
+ int len = 0, name_len = 0;
+
+ name_len = dentry->d_name.len;
+ if (!name_len)
+ return 0;
+ hash = init_name_hash();
+ while (name_len--) {
+ c = *(const unsigned char *)name++;
+ if (c == ':' || c == '\0')
+ break;
+ hash = partial_name_hash(c, hash);
+ len ++;
+ }
+ str->hash = end_name_hash(hash);
+ OBD_ALLOC(str_name, len + 1);
+ memcpy(str_name, dentry->d_name.name, len);
+ str->len = len;
+ str->name = str_name;
+ if (index && c == ':') {
+ *index = simple_strtoul(name, 0, 0);
+ }
+ return 0;
+}
+
+static inline void smfs_free_dentry_name(struct qstr *str)
+{
+ OBD_FREE(str->name, str->len + 1);
+}
+
static inline struct dentry *pre_smfs_dentry(struct dentry *parent_dentry,
struct inode *cache_inode,
- struct dentry *dentry)
+ struct dentry *dentry,
+ int *index)
{
struct dentry *cache_dentry = NULL;
-
- cache_dentry = d_alloc(parent_dentry, &dentry->d_name);
+ struct qstr name;
+
+ smfs_get_dentry_name_index(dentry, &name, index);
+ cache_dentry = d_alloc(parent_dentry, &name);
+ smfs_free_dentry_name(&name);
if (!cache_dentry)
RETURN(NULL);
if (!parent_dentry)
return 0;
}
+
/* XXX BUG 3188 -- must return to one set of opcodes */
#define SMFS_TRANS_OP(inode, op) \
{ \
extern int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt);
extern int smfs_post_cleanup(struct super_block *sb);
+extern struct inode *smfs_get_inode (struct super_block *sb, ino_t hash,
+ struct inode *dir, int index);
+
+extern int is_smfs_sb(struct super_block *sb);
#endif /* _LUSTRE_SMFS_H */
struct snap sntbl_items[0];
};
+#define DOT_NAME_MAX_LEN 32
struct snap_dot_info {
- char *dot_name;
- int dot_name_len;
- int dot_snap_enable;
+ char *dot_name;
+ int dot_name_len;
+ int dot_snap_enable;
};
struct snap_info {
struct snap_table *sntbl;
struct dentry *sn_cowed_dentry;
struct snap_dot_info *sn_dot_info;
-
};
extern int smfs_add_snap_item(struct super_block *sb, char *name);
int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
void *data2);
struct inode* smfs_cow_get_ind(struct inode *inode, int index);
+
+
+#define DOT_SNAP_NAME ".snap"
+#define DOT_SNAP_INDEX 0xffff
+static inline int smfs_primary_inode(struct inode *inode)
+{
+ struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
+
+ if (sn_info->sn_index == 0)
+ return 1;
+ return 0;
+}
+static inline int smfs_dotsnap_inode(struct inode *inode)
+{
+ struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
+
+ if (sn_info->sn_index == DOT_SNAP_INDEX)
+ return 1;
+ return 0;
+}
+static inline int smfs_under_dotsnap_inode(struct inode *inode)
+{
+ struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo;
+
+ if (sn_info->sn_index > 0 && sn_info->sn_index != DOT_SNAP_INDEX)
+ return 1;
+ return 0;
+}
+
+
+
#endif /*_LUSTRE_SNAP_H*/
rc = OBP(exp->exp_obd, init_ea_size)(exp, size, size2);
RETURN(rc);
}
-
static inline int md_getstatus(struct obd_export *exp, struct ll_fid *fid)
{
int rc;
#include <linux/lustre_mds.h>
#include <linux/lustre_lite.h>
#include <linux/lustre_dlm.h>
+#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
#include "llite_internal.h"
typedef struct ext2_dir_entry_2 ext2_dirent;
if (de->inode) {
int over;
unsigned char d_type = DT_UNKNOWN;
-
+
+
rc = 0; /* no error if we return something */
if (types && de->file_type < EXT2_FT_MAX)
d_type = types[de->file_type];
offset = (char *)de - kaddr;
+#ifdef CONFIG_SNAPFS
+ /*FIXME-WANGDI will get dot info from MDS*/
+ if ((n << PAGE_CACHE_SHIFT | offset) == 0) {
+ int off =n << PAGE_CACHE_SHIFT | offset;
+ over = filldir(dirent, DOT_SNAP_NAME,
+ strlen(DOT_SNAP_NAME),
+ off, -1, 0);
+ if (over) {
+ ext2_put_page(page);
+ GOTO(done, rc);
+ }
+ }
+ offset+=EXT2_DIR_REC_LEN(strlen(DOT_SNAP_NAME));
+#endif
over = filldir(dirent, de->name, de->name_len,
(n<<PAGE_CACHE_SHIFT) | offset,
le32_to_cpu(de->inode), d_type);
int ll_gns_state;
struct timer_list ll_gns_timer;
struct list_head ll_gns_sbi_head;
+ void *ll_dot_snap_info;
};
#define LL_GNS_STATE_IDLE 1100
#include <linux/lustre_ha.h>
#include <linux/lustre_dlm.h>
#include <linux/lprocfs_status.h>
+#include <linux/lustre_smfs.h>
#include <linux/lustre_snap.h>
#include "llite_internal.h"
sbi->ll_osc_exp = class_conn2export(&osc_conn);
lustre_init_ea_size(sbi);
-
err = md_getstatus(sbi->ll_mdc_exp, &rootfid);
if (err) {
CERROR("cannot mds_connect: rc = %d\n", err);
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;
inode->i_dev = (kdev_t) body->mds;
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;
return NULL;
cache_inode = I2CI(fso->fso_dentry->d_inode);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, fso->fso_dentry,
+ NULL);
if (!cache_dentry)
GOTO(exit, rc = ERR_PTR(-ENOMEM));
cache_inode = I2CI(dentry->d_inode);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);
*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);
#include <linux/module.h>
#include <linux/iobuf.h>
#endif
+#include <linux/lustre_smfs.h>
#include <linux/lustre_snap.h>
/* For snapfs in EXT3 flags --- FIXME will find other ways to store it*/
* return value: postive: indirect ino number
* negative or 0: error
*/
-static ino_t fsfilt_ext3_get_indirect_ino(struct inode *primary, int index)
+static ino_t fsfilt_ext3_get_indirect_ino(struct super_block *sb,
+ ino_t primary_ino, int index)
{
char buf[EXT3_MAX_SNAP_DATA];
+ struct inode *primary = NULL;
struct snap_ea *snaps;
ino_t ino = 0;
int err;
ENTRY;
if (index < 0 || index > EXT3_MAX_SNAPS || !primary)
RETURN(0);
-
+ primary = iget(sb, primary_ino);
+
+ if (!primary) {
+ err = -EIO;
+ CERROR("attribute read error=%d", err);
+ GOTO (err_free, ino = err);
+ }
err = ext3_xattr_get(primary, EXT3_SNAP_INDEX, EXT3_SNAP_ATTR,
buf, EXT3_MAX_SNAP_DATA);
if (err == -ENOATTR) {
CDEBUG(D_INODE, "snap ino for %ld at index %d is %lu\n",
primary->i_ino, index, ino);
err_free:
+ if (primary)
+ iput(primary);
RETURN(ino);
}
}
RETURN(-EINVAL);
}
+static int fsfilt_ext3_dir_ent_size(char *name)
+{
+ if (name) {
+ return EXT3_DIR_REC_LEN(strlen(name));
+ }
+ return 0;
+}
+static int fsfilt_ext3_set_dir_ent(struct super_block *sb, char *name,
+ char *buf, int buf_off, int nlen, size_t count)
+{
+ int rc = 0;
+ ENTRY;
+ if (buf_off == 0 && nlen == 0) {
+ struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *)buf;
+ LASSERT(count == PAGE_CACHE_SIZE);
+ de->rec_len = count;
+ de->inode = 0;
+ RETURN(rc);
+ } else {
+ struct ext3_dir_entry_2 *de, *de1;
+ de = (struct ext3_dir_entry_2 *)(buf + buf_off - nlen);
+ de1 = (struct ext3_dir_entry_2 *)(buf + buf_off);
+ int rlen, nlen;
+
+ LASSERT(nlen == EXT3_DIR_REC_LEN_DE(de));
+
+ rlen = le16_to_cpu(de->rec_len);
+ de->rec_len = cpu_to_le16(nlen);
+
+ de1->rec_len = cpu_to_le16(rlen - nlen);
+ de1->name_len = strlen(name);
+ memcpy (de1->name, name, de->name_len);
+ nlen = EXT3_DIR_REC_LEN_DE(de1);
+ RETURN(nlen);
+ }
+
+}
struct fsfilt_operations fsfilt_ext3_snap_ops = {
.fs_type = "ext3_snap",
.fs_owner = THIS_MODULE,
.fs_copy_block = fsfilt_ext3_copy_block,
.fs_set_snap_info = fsfilt_ext3_set_snap_info,
.fs_get_snap_info = fsfilt_ext3_get_snap_info,
+ .fs_dir_ent_size = fsfilt_ext3_dir_ent_size,
+ .fs_set_dir_ent = fsfilt_ext3_set_dir_ent,
};
+
static int __init fsfilt_ext3_snap_init(void)
{
int rc;
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, slot);
}
RETURN(ind_inode);
}
RETURN(rc);
}
-static ino_t fsfilt_smfs_get_indirect_ino(struct inode *inode, int index)
+static ino_t fsfilt_smfs_get_indirect_ino(struct super_block *sb, ino_t ino,
+ int index)
{
- struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
- struct inode *cache_inode = NULL;
+ struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
+ struct super_block *csb = S2CSB(sb);
int rc = -EIO;
ENTRY;
if (snap_fsfilt == NULL)
RETURN(rc);
- cache_inode = I2CI(inode);
- if (!cache_inode)
- RETURN(rc);
-
- pre_smfs_inode(inode, cache_inode);
if (snap_fsfilt->fs_get_indirect_ino)
- rc = snap_fsfilt->fs_get_indirect_ino(cache_inode, index);
- post_smfs_inode(inode, cache_inode);
-
+ rc = snap_fsfilt->fs_get_indirect_ino(csb, ino, index);
+
RETURN(rc);
}
RETURN(rc);
}
+
+static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
+ size_t count, loff_t *off)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
+ struct snap_table *stbl = S2SNAPI(inode->i_sb)->sntbl;
+ int i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
+ ENTRY;
+
+ /*Get the offset of dir ent*/
+ while (size < *off && off_count < stbl->sntbl_count) {
+ char *name = stbl->sntbl_items[i].sn_name;
+ size +=snap_cops->fs_dir_ent_size(name);
+ off_count ++;
+ }
+ for (i = off_count; i < stbl->sntbl_count; i++) {
+ char *name = stbl->sntbl_items[i].sn_name;
+ rc = snap_cops->fs_set_dir_ent(inode->i_sb, name, buf, buf_off,
+ rc, count);
+ if (rc < 0)
+ break;
+
+ buf_off += rc;
+
+ if (buf_off >= count)
+ break;
+ }
+ if (rc > 0)
+ rc = 0;
+
+ RETURN(rc);
+}
+
struct fsfilt_operations fsfilt_smfs_snap_ops = {
.fs_type = "smfs_snap",
.fs_owner = THIS_MODULE,
.fs_copy_block = fsfilt_smfs_copy_block,
.fs_set_snap_info = fsfilt_smfs_set_snap_info,
.fs_get_snap_info = fsfilt_smfs_get_snap_info,
+ .fs_read_dotsnap_dir_page = fsfilt_smfs_read_dotsnap_dir_page,
};
#include <linux/obd_class.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_dlm.h>
-#include <linux/lustre_snap.h>
+//#include <linux/lustre_smfs.h>
+//#include <linux/lustre_snap.h>
#include <linux/lprocfs_status.h>
#include "mdc_internal.h"
return 0;
}
-#if CONFIG_SNAPFS
-int mdc_set_clone_info(struct obd_export *exp, struct lustre_msg *msg,
- int offset)
-{
- struct client_obd *cli_obd = &exp->exp_obd->u.cli;
- struct clonefs_info *cl_info;
- ENTRY;
-
- if (cli_obd->cl_clone_info) {
- cl_info = (struct clonefs_info *)lustre_msg_buf(msg, offset,
- sizeof (*cl_info));
- memcpy(cl_info, cli_obd->cl_clone_info, sizeof(*cl_info));
- }
- RETURN(0);
-}
-#endif
-
/* We always reserve enough space in the reply packet for a stripe MD, because
* we don't know in advance the file type. */
int mdc_enqueue(struct obd_export *exp,
if (it->it_op & IT_GETATTR)
policy.l_inodebits.bits = MDS_INODELOCK_UPDATE;
-#if CONFIG_SNAPFS
- size[4] = sizeof(struct clonefs_info);
- req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 5,
- size, NULL);
-#else
req = ptlrpc_prep_req(class_exp2cliimp(exp), LDLM_ENQUEUE, 4,
size, NULL);
-#endif
if (!req)
RETURN(-ENOMEM);
/* pack the intended request */
mdc_getattr_pack(req->rq_reqmsg, valid, 2, it->it_flags, data);
-#if CONFIG_SNAPFS
- mdc_set_clone_info(exp, req->rq_reqmsg, 4);
-#endif
/* get ready for the reply */
reply_buffers = 3;
req->rq_replen = lustre_msg_size(3, repsize);
.o_connect = client_connect_import,
.o_disconnect = client_disconnect_export,
.o_iocontrol = mdc_iocontrol,
- .o_set_info = mdc_set_info,
.o_statfs = mdc_statfs,
.o_pin = mdc_pin,
.o_unpin = mdc_unpin,
#include <linux/obd_ost.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_fsfilt.h>
-#include <linux/lustre_snap.h>
#include <linux/lprocfs_status.h>
#include <linux/lustre_commit_confd.h>
+#ifdef CONFIG_SNAPFS
+#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
+#endif
#include "mds_internal.h"
static int mds_intent_policy(struct ldlm_namespace *ns,
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);
CERROR("Can't unpack name\n");
GOTO(cleanup, rc = -EFAULT);
}
-#if CONFIG_SNAPFS
- clone_info = lustre_swab_reqbuf(req, offset + 2, sizeof(*clone_info),
- lustre_swab_clonefs_info);
- if (clone_info) {
- CDEBUG(D_INFO,"getattr name %s clone_info index %d \n", name,
- clone_info->clone_index);
- }
-#endif
namesize = req->rq_reqmsg->buflens[offset + 1];
LASSERT (offset == 0 || offset == 2);
#include <linux/lustre_lib.h>
#include <linux/lustre_mds.h>
+#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
+
void mds_pack_dentry2fid(struct ll_fid *fid, struct dentry *dentry)
{
fid->id = dentry->d_inum;
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);
#include <linux/lustre_lib.h>
#include <linux/lustre_idl.h>
#include <linux/lustre_fsfilt.h>
-#include <linux/lustre_snap.h>
#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
#include "smfs_internal.h"
lock_kernel();
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_CREATE, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
if (!cache_dentry || !cache_parent)
GOTO(exit, rc = -ENOMEM);
#endif
if (rc)
GOTO(exit, rc);
-
- inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
- &I2SMI(dir)->smi_flags);
+
+ inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
if (!inode)
GOTO(exit, rc = -ENOMEM);
struct dentry *cache_parent = NULL;
struct dentry *rc = NULL;
void *handle = NULL;
- int rc2 = 0;
+ int rc2 = 0, index = 0;
ENTRY;
if (!(cache_dir = I2CI(dir)))
RETURN(ERR_PTR(-ENOENT));
- SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, PRE_HOOK, rc2,
- exit);
- if (rc2)
- RETURN(ERR_PTR(rc2));
-
/* 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);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, &index);
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));
+ SMFS_HOOK(dir, dentry, &index, NULL, HOOK_LOOKUP, handle,
+ PRE_HOOK, rc2, exit);
+
/* 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);
dentry->d_inode = cache_inode;
GOTO(exit, rc = NULL);
}
- inode = iget4(dir->i_sb, cache_inode->i_ino, NULL,
- &I2SMI(dir)->smi_flags);
+ inode = smfs_get_inode(dir->i_sb, cache_inode->i_ino, dir, index);
} else {
d_add(dentry, NULL);
GOTO(exit, rc);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_LOOKUP, handle, POST_HOOK, rc2,
exit);
exit:
- if (rc2)
+ if (rc2 < 0)
rc = ERR_PTR(rc2);
post_smfs_dentry(cache_dentry);
post_smfs_dentry(cache_parent);
SMFS_HOOK(dir, old_dentry, NULL, NULL, HOOK_LINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
cache_old_dentry = pre_smfs_dentry(NULL, cache_old_inode,
- old_dentry);
+ old_dentry, NULL);
if (!cache_old_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_UNLINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_SYMLINK, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
if (cache_dir->i_op->symlink)
rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
- inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
- &I2SMI(dir)->smi_flags);
+
+ inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
post_smfs_inode(dir, cache_dir);
if (inode)
d_instantiate(dentry, inode);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKDIR, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
if (rc)
GOTO(exit, rc);
+
+ inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
- inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
- &I2SMI(dir)->smi_flags);
if (!inode)
GOTO(exit, rc = -ENOENT);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_RMDIR, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry);
- cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, cache_inode, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
SMFS_HOOK(dir, dentry, NULL, NULL, HOOK_MKNOD, handle, PRE_HOOK, rc,
exit);
- cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent);
- cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry);
+ cache_parent = pre_smfs_dentry(NULL, cache_dir, dentry->d_parent, NULL);
+ cache_dentry = pre_smfs_dentry(cache_parent, NULL, dentry, NULL);
if (!cache_parent || !cache_dentry)
GOTO(exit, rc = -ENOMEM);
mode, rdev)))
GOTO(exit, rc);
- inode = iget4(dir->i_sb, cache_dentry->d_inode->i_ino, NULL,
- &I2SMI(dir)->smi_flags);
+ inode = smfs_get_inode(dir->i_sb, cache_dentry->d_inode->i_ino, dir, 0);
+
d_instantiate(dentry, inode);
pre_smfs_inode(dir, cache_dir);
SMFS_HOOK(old_dir, old_dentry, new_dir, new_dentry, HOOK_RENAME, handle,
PRE_HOOK, rc, exit);
- cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry);
+ cache_old_parent = pre_smfs_dentry(NULL, cache_old_dir, old_dentry, NULL);
cache_old_dentry = pre_smfs_dentry(cache_old_parent, cache_old_inode,
- old_dentry);
+ old_dentry, NULL);
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_parent = pre_smfs_dentry(NULL, cache_new_dir, new_dentry, NULL);
cache_new_dentry = pre_smfs_dentry(cache_new_parent, cache_new_inode,
- new_dentry);
+ new_dentry, NULL);
if (!cache_new_parent || !cache_new_dentry)
GOTO(exit, rc = -ENOMEM);
sfi->magic = SMFS_FILE_MAGIC;
- cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry);
+ cache_dentry = pre_smfs_dentry(NULL, I2CI(inode), filp->f_dentry, NULL);
if (!cache_dentry)
GOTO(err_exit, rc = -ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
RETURN(-ENOMEM);
#include <linux/lustre_idl.h>
#include <linux/lustre_fsfilt.h>
-#include <linux/lustre_snap.h>
#include <linux/lustre_smfs.h>
+#include <linux/lustre_snap.h>
#include "smfs_internal.h"
#define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap))
snap_info->sn_cowed_dentry = dentry;
RETURN(rc);
}
-#define DOT_SNAP_NAME ".snap"
static int smfs_init_dotinfo(struct super_block *sb)
{
struct snap_info *snap_info = S2SNAPI(sb);
RETURN(0);
}
+static int smfs_dotsnap_dir_size(struct inode *inode)
+{
+ struct snap_info *snap_info = S2SNAPI(inode->i_sb);
+ struct fsfilt_operations *snapops = snap_info->snap_cache_fsfilt;
+ struct snap_table *stbl = snap_info->sntbl;
+ int size = 0, dir_size = 0, blocks;
+ int i = 0;
+ ENTRY;
+
+ for (i = 0; i < stbl->sntbl_count; i++) {
+ size += snapops->fs_dir_ent_size(stbl->sntbl_items[i].sn_name);
+ }
+ /*FIXME this is only for ext3 dir format, may need fix for other FS*/
+ blocks = (size + inode->i_sb->s_blocksize - 1) >>
+ inode->i_sb->s_blocksize_bits;
+
+ dir_size = blocks * inode->i_sb->s_blocksize;
+ RETURN(dir_size);
+
+}
/*FIXME Note indirect and primary inode
* should be recorgnized here*/
-int smfs_init_snap_inode_info(struct inode *inode, int flags)
+int smfs_init_snap_inode_info(struct inode *inode,
+ struct snap_inode_info *sn_info)
{
+ struct smfs_inode_info *smi = I2SMI(inode);
int vallen, rc = 0;
ENTRY;
- if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
- (flags & SM_DO_COW)) {
+ LASSERT(sn_info && smi);
+ smi->sm_sninfo.sn_flags = sn_info->sn_flags;
+ smi->sm_sninfo.sn_gen = sn_info->sn_gen;
+ smi->sm_sninfo.sn_index = sn_info->sn_index;
+
+ if (smfs_dotsnap_inode(inode)) {
+ struct snap_table *stbl= S2SNAPI(inode->i_sb)->sntbl;
+ int size = 0;
+ /*init dot_snap inode info*/
+ size = smfs_dotsnap_dir_size(inode);
+ inode->i_size = (loff_t)size;
+ inode->i_nlink = stbl->sntbl_count + 2;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ } else if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
+ (smi->smi_flags & SM_DO_COW) &&
+ smfs_primary_inode(inode)) {
struct snap_inode_info *sni_info = I2SNAPI(inode);
struct fsfilt_operations *snapops = I2SNAPOPS(inode);
- sni_info->sn_flags = flags;
vallen = sizeof(sni_info->sn_gen);
-
+
rc = snapops->fs_get_snap_info(inode, SNAP_GENERATION,
strlen(SNAP_GENERATION),
&sni_info->sn_gen, &vallen);
}
RETURN(rc);
-
}
/* latest snap: returns
- the index of the latest snapshot before NOW
LASSERT(dchild->d_inode == inode);
GOTO(out_dput, rc = 0);
}
- tmp = pre_smfs_dentry(NULL, inode, cowed_dir);
+ tmp = pre_smfs_dentry(NULL, inode, cowed_dir, NULL);
/* link() is semanticaly-wrong for S_IFDIR, so we set S_IFREG
* for linking and return real mode back then -bzzz */
mode = inode->i_mode;
ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen,
dparent->d_inode, del);
if(ind && IS_ERR(ind)) {
- CERROR("Create ind inode %lu index %d gen %d del %d\n rc%u\n",
+ CERROR("Create ind inode %lu index %d gen %d del %d rc%lu\n",
inode->i_ino, snap.sn_index, snap.sn_gen, del,
PTR_ERR(ind));
RETURN(PTR_ERR(ind));
I2SMI(ind)->sm_sninfo.sn_flags = 0;
I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
+ I2SMI(ind)->sm_sninfo.sn_index = snap.sn_index;
iput(ind);
}
RETURN(rc);
}
EXPORT_SYMBOL(smfs_cow_write);
-
+/*lookup inode in dotsnap inode */
+static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry)
+{
+ if (dentry->d_name.len == 1 &&
+ !strcmp(dentry->d_name.name, ".")) {
+ d_add(dentry, iget(dir->i_sb, dir->i_ino));
+ } else if (dentry->d_name.len == 2 &&
+ !strcmp(dentry->d_name.name, "..")) {
+ struct inode *inode;
+ struct dentry *dparent = dentry->d_parent;
+ if (dparent->d_inode) {
+ inode = iget(dir->i_sb, dparent->d_inode->i_ino);
+ if (inode) {
+ if (!is_bad_inode(inode))
+ d_add(dentry, inode);
+ else
+ iput(inode);
+ }
+ }
+ } else {
+ /*find the name from the snaptable*/
+ struct fsfilt_operations *snapops = I2SNAPOPS(dir);
+ struct snap_table *table = S2SNAPI(dir->i_sb)->sntbl;
+ struct inode *inode;
+ int i = 0, index = -1;
+ for (i = 0; i < table->sntbl_count; i++) {
+ char *name = table->sntbl_items[i].sn_name;
+ if ((dentry->d_name.len == strlen(name)) &&
+ (memcmp(dentry->d_name.name, name,
+ dentry->d_name.len) == 0)) {
+ index = table->sntbl_items[i].sn_index;
+ break;
+ }
+ }
+ if (index != -1) {
+ CERROR("No such %s in this .snap dir \n",
+ dentry->d_name.name);
+ RETURN(-ENOENT);
+ }
+ inode = snapops->fs_get_indirect(dir, NULL, index);
+ d_add(dentry, inode);
+ }
+ RETURN(0);
+}
int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
void *data2)
{
struct snap_info *snap_info = S2SNAPI(inode->i_sb);
- struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
- struct dentry *dparent = dentry->d_parent;
- struct clonefs_info *clone_info=(struct clonefs_info*)dparent->d_fsdata;
- int rc = 0;
-
- if (clone_info && clone_info->clone_flags && SM_CLONE_FS) {
- struct inode *ind_inode = NULL;
- struct inode *cache_ind = NULL;
- struct dentry *cache_dentry = NULL;
- struct dentry *cache_parent = NULL;
- struct inode *cache_inode;
- struct dentry *tmp;
- rc = 1;
-
- ind_inode = snapops->fs_get_indirect(inode, NULL, clone_info->clone_index);
- if (!ind_inode)
- RETURN(-ENOENT);
-
- if (!(cache_ind = I2CI(ind_inode)))
- GOTO(exit, rc = -ENOENT);
-
- cache_parent=pre_smfs_dentry(NULL, cache_ind, dentry->d_parent);
- cache_dentry=pre_smfs_dentry(cache_parent, NULL, dentry);
+ struct snap_dot_info *dot_info = snap_info->sn_dot_info;
+ int rc = 0, index = 0;
+ ENTRY;
- tmp = cache_ind->i_op->lookup(cache_ind, cache_dentry);
+ LASSERT(dot_info != NULL);
+ LASSERT(data1 != NULL);
- if (IS_ERR(tmp))
- GOTO(exit, rc = -ENOENT);
-
- if ((cache_inode = tmp ? tmp->d_inode : cache_dentry->d_inode)) {
- if (IS_ERR(cache_inode)) {
- dentry->d_inode = cache_inode;
- GOTO(exit, rc = -ENOENT);
- }
- inode = iget4(inode->i_sb, cache_inode->i_ino, NULL,
- &I2SMI(inode)->smi_flags);
- } else {
- d_add(dentry, NULL);
- GOTO(exit, rc = -ENOENT);
- }
- d_add(dentry, inode);
-exit:
- iput(ind_inode);
- post_smfs_dentry(cache_dentry);
- post_smfs_dentry(cache_parent);
+ index = *(int *)data1;
+
+ if (smfs_primary_inode(inode) &&
+ dentry->d_name.len == dot_info->dot_name_len &&
+ memcmp(dentry->d_name.name, dot_info->dot_name,
+ strlen(dot_info->dot_name)) == 0) {
+ struct inode *dot_inode = NULL;
+
+ dot_inode = smfs_get_inode(inode->i_sb, inode->i_ino, inode,
+ DOT_SNAP_INDEX);
+ d_add(dentry, dot_inode);
+ rc = 1;
RETURN(rc);
+ }
+ if (smfs_dotsnap_inode(inode)) {
+ rc = smfs_dotsnap_lookup(inode, dentry);
+ if (rc == 0)
+ rc = 1;
+ RETURN(rc);
}
+ if (index > 0) {
+ /*HERE: will replace ino in dentry->d_name according to index*/
+ struct fsfilt_operations *snapops = I2SNAPOPS(inode);
+ char *name = (char *)dentry->d_name.name;
+ unsigned long ino, hash, ind_ino;
+ int len = sizeof(ind_ino);
+
+ ino = simple_strtoul(name, 0, 0);
+
+ ind_ino = snapops->fs_get_indirect_ino(inode->i_sb, ino, index);
+
+ snprintf(name, strlen(name), "0x%lx", ind_ino);
+
+ hash = init_name_hash();
+ while (len--) {
+ unsigned char c;
+ c = *(const unsigned char *)name++;
+ if (c == '\0') break;
+ hash = partial_name_hash(c, hash);
+ }
+ dentry->d_name.hash = end_name_hash(hash);
+ }
RETURN(rc);
}
extern int smfs_open(struct inode * inode, struct file * filp);
extern int smfs_release(struct inode * inode, struct file * filp);
/*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;
#if CONFIG_SNAPFS
extern int smfs_cow_init(struct super_block *sb);
extern int smfs_cow_cleanup(struct super_block *sb);
-extern int smfs_init_snap_inode_info(struct inode *inode, int flags);
+extern int smfs_init_snap_inode_info(struct inode *inode,
+ struct snap_inode_info *sn_info);
#else
#define SMFS_PRE_COW(dir, dentry, new_dir, new_dentry, op, name, rc, label)
#endif
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);
if (cache_inode->i_op && cache_inode->i_op->readlink)
if (!cache_inode)
RETURN(-ENOENT);
- cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry);
+ cache_dentry = pre_smfs_dentry(NULL, cache_inode, dentry, NULL);
if (!cache_dentry)
GOTO(exit, rc = -ENOMEM);