if (rc < 0) {
if (rc == -ENODATA) {
snap_table->sntbl_count = 0;
+ rc = 0;
} else {
CERROR("Can not retrive the snaptable from this filesystem\n");
GOTO(exit, rc);
RETURN(ERR_PTR(-ENOMEM));
rc = smfs_init_snap_info(sinfo, snap_info, dentry);
if (rc)
- GOTO(exit, snap_info = ERR_PTR(rc));
+ GOTO(exit, rc);
/*set cow flags for the snap root inode*/
I2SMI(dentry->d_inode)->smi_flags |= SM_DO_COW;
I2SNAPI(dentry->d_inode)->sn_root_ino = dentry->d_inode->i_ino;
exit:
- if (rc)
+ if (rc) {
OBD_FREE(snap_info, sizeof(struct snap_info));
+ snap_info = ERR_PTR(rc);
+ }
RETURN(snap_info);
}
-static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir,
+static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir,
void *new_dentry, int op);
-static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir,
+static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir,
void *new_dentry, int op);
#define COW_HOOK "cow_hook"
-static int smfs_cow_pre_hook(struct inode *inode, struct dentry *dentry,
- void *data1, void *data2, int op, void *handle)
+static int smfs_cow_pre_hook(struct inode *inode, void *dentry, void *data1,
+ void *data2, int op, void *handle)
{
int rc = 0;
ENTRY;
}
RETURN(rc);
}
-static int smfs_cow_post_hook(struct inode *inode, struct dentry *dentry,
- void *data1, void *data2, int op, void *handle)
+static int smfs_cow_post_hook(struct inode *inode, void *dentry, void *data1,
+ void *data2, int op, void *handle)
{
int rc = 0;
ENTRY;
RETURN(0);
}
/*Dir inode will do cow*/
-int smfs_cow_create(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
+int smfs_cow_create_pre(struct inode *dir, void *de, void *data1, void *data2)
{
- int rc = 0;
struct dentry *dparent;
+ struct dentry *dentry = (struct dentry *)de;
+ int rc = 0;
ENTRY;
if (smfs_needs_cow(dir) != -1) {
RETURN(rc);
}
-int smfs_cow_setattr(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
+int smfs_cow_setattr_pre(struct inode *dir, void *de, void *data1, void *data2)
{
+ struct dentry *dentry = (struct dentry *)de;
int rc = 0;
ENTRY;
if (smfs_needs_cow(dir) != -1) {
RETURN(rc);
}
-int smfs_cow_link(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
+int smfs_cow_link_pre(struct inode *dir, void *de, void *data1, void *data2)
{
- int rc = 0;
struct dentry *dparent;
+ struct dentry *dentry = (struct dentry *)de;
+ int rc = 0;
ENTRY;
if (smfs_needs_cow(dir) != -1) {
RETURN(rc);
}
-int smfs_cow_unlink(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
+int smfs_cow_unlink_pre(struct inode *dir, void *de, void *data1, void *data2)
{
+ struct dentry *dentry = (struct dentry *)de;
struct dentry *dparent;
int rc = 0;
ENTRY;
RETURN(rc);
}
-int smfs_cow_rename(struct inode *dir, struct dentry *dentry,
- void *data1, void *data2)
+int smfs_cow_rename_pre(struct inode *dir, void *de, void *data1, void *data2)
{
+ struct dentry *dentry = (struct dentry*)de;
struct inode *new_dir = (struct inode *)data1;
struct dentry *new_dentry = (struct dentry *)data2;
struct dentry *dparent;
RETURN(rc);
}
-int smfs_cow_write(struct inode *inode, struct dentry *dentry, void *data1,
- void *data2)
+int smfs_cow_write_pre(struct inode *inode, void *de, void *data1, void *data2)
{
+ struct dentry *dentry = (struct dentry*)de;
struct snap_info *snap_info = NULL;
struct snap_table *table;
long blocks[2]={-1,-1};
up(&inode->i_sem);
RETURN(rc);
}
-EXPORT_SYMBOL(smfs_cow_write);
+EXPORT_SYMBOL(smfs_cow_write_pre);
/*lookup inode in dotsnap inode */
static int smfs_dotsnap_lookup(struct inode *dir, struct dentry *dentry,
struct snap_info *snap_info)
}
RETURN(0);
}
-int smfs_cow_lookup(struct inode *inode, struct dentry *dentry, void *data1,
- void *data2)
+int smfs_cow_lookup_pre(struct inode *inode, void *de, void *data1,
+ void *data2)
{
+ struct dentry *dentry = (struct dentry*)de;
struct snap_info *snap_info;
struct snap_dot_info *dot_info;
- int rc = 0, index = 0;
+ int rc = 0;
ENTRY;
snap_info = smfs_find_snap_info(inode);
dot_info = snap_info->sni_dot_info;
- LASSERT(dot_info != NULL);
- LASSERT(data1 != NULL);
-
- 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,
d_add(dentry, dot_inode);
rc = 1;
RETURN(rc);
- }
- if (smfs_dotsnap_inode(inode)) {
+ } else if (smfs_dotsnap_inode(inode)) {
rc = smfs_dotsnap_lookup(inode, dentry, snap_info);
if (rc == 0)
rc = 1;
RETURN(rc);
- }
- if (index > 0) {
- /*HERE: will replace ino in dentry->d_name according to index*/
+ } else {
+ /*HERE: will replace ino in dentry->d_name according to index,
+ *For iopen, will fix it in integrating snapfs to Lustre*/
+#if 0
struct fsfilt_operations *snapops = I2SNAPOPS(inode);
char *name = (char *)dentry->d_name.name;
unsigned long ino, hash, ind_ino;
hash = partial_name_hash(c, hash);
}
dentry->d_name.hash = end_name_hash(hash);
- }
+#endif
+ }
RETURN(rc);
}
}
EXPORT_SYMBOL(smfs_cow_get_ind);
-typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry,
- void *new_dir, void *new_dentry);
+static int smfs_cow_readdir_pre(struct inode *dir, void *de, void *data1,
+ void *data2)
+{
+ struct file *filp = (struct file*)de;
+ void *dirent = data1;
+ filldir_t filldir = (filldir_t)data2;
+ struct snap_info *snap_info = NULL;
+
+ if (smfs_under_dotsnap_inode(dir))
+ RETURN(0);
+
+ snap_info = smfs_find_snap_info(dir);
+
+ if (!snap_info) {
+ CDEBUG(D_INFO, "can not find snap info for ino %lu\n",
+ dir->i_ino);
+ RETURN(-EINVAL);
+ }
+
+ if (smfs_primary_inode(dir)) {
+ if (filp->f_pos == 0) {
+ struct snap_dot_info *dot = snap_info->sni_dot_info;
+ if (filldir(dirent, dot->dot_name, dot->dot_name_len,
+ filp->f_pos, -1, 0)) {
+ CERROR("fill .snap error \n");
+ RETURN(-EINVAL);
+ }
+ } else {
+ filp->f_pos -= 1;
+ }
+ } else if (smfs_dotsnap_inode(dir)) {
+ struct snap_table *table = snap_info->sni_table;
+ int i = 0;
+
+ if (filp->f_pos < 0)
+ RETURN(-EINVAL);
+
+ if ((filp->f_pos == 0) && filldir(dirent, ".", 1,
+ filp->f_pos++,
+ dir->i_ino, 0) < 0)
+ RETURN(-EIO);
+ if ((filp->f_pos == 1) && filldir(dirent, "..", 2,
+ filp->f_pos++,
+ dir->i_ino, 0) < 0)
+ RETURN(-EIO);
+
+ for (i = filp->f_pos - 2; i < table->sntbl_count; i++,
+ filp->f_pos++) {
+ int slot = table->sntbl_count-i;
+
+ if (filldir(dirent, table->sntbl_items[slot].sn_name,
+ strlen(table->sntbl_items[slot].sn_name),
+ filp->f_pos, dir->i_ino, 0))
+ break;
+
+ }
+ RETURN(1);
+ }
+
+ RETURN(0);
+}
+
+
+typedef int (*cow_funcs)(struct inode *dir, void *dentry, void *new_dir,
+ void *new_dentry);
static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = {
- [HOOK_CREATE] smfs_cow_create,
- [HOOK_LOOKUP] smfs_cow_lookup,
- [HOOK_LINK] smfs_cow_link,
- [HOOK_UNLINK] smfs_cow_unlink,
- [HOOK_SYMLINK] smfs_cow_create,
- [HOOK_MKDIR] smfs_cow_create,
- [HOOK_RMDIR] smfs_cow_unlink,
- [HOOK_MKNOD] smfs_cow_create,
- [HOOK_RENAME] smfs_cow_rename,
- [HOOK_SETATTR] smfs_cow_setattr,
- [HOOK_WRITE] smfs_cow_write,
+ [HOOK_CREATE] smfs_cow_create_pre,
+ [HOOK_LOOKUP] smfs_cow_lookup_pre,
+ [HOOK_LINK] smfs_cow_link_pre,
+ [HOOK_UNLINK] smfs_cow_unlink_pre,
+ [HOOK_SYMLINK] smfs_cow_create_pre,
+ [HOOK_MKDIR] smfs_cow_create_pre,
+ [HOOK_RMDIR] smfs_cow_unlink_pre,
+ [HOOK_MKNOD] smfs_cow_create_pre,
+ [HOOK_RENAME] smfs_cow_rename_pre,
+ [HOOK_SETATTR] smfs_cow_setattr_pre,
+ [HOOK_WRITE] smfs_cow_write_pre,
+ [HOOK_READDIR] smfs_cow_readdir_pre,
};
-int smfs_cow_lookup_post(struct inode *dir, struct dentry *dentry, void *data1,
+int smfs_cow_lookup_post(struct inode *dir, void *de, void *data1,
void *data2)
{
+ struct dentry *dentry = (struct dentry*)de;
struct inode *inode = dentry->d_inode;
struct fsfilt_operations *sops = I2SNAPCOPS(inode);
int index = I2SNAPI(dir)->sn_index;
RETURN(0);
}
+static int smfs_cow_readdir_post(struct inode *dir, void *de, void *data1,
+ void *data2)
+{
+ struct file *filp = (struct file*)de;
+
+ if (smfs_primary_inode(dir)) {
+ filp->f_pos += 1;
+ }
+ RETURN(0);
+}
+
+
static cow_funcs smfs_cow_post_funcs[HOOK_MAX + 1] = {
[HOOK_CREATE] NULL,
[HOOK_LOOKUP] smfs_cow_lookup_post,
[HOOK_RENAME] NULL,
[HOOK_SETATTR] NULL,
[HOOK_WRITE] NULL,
+ [HOOK_READDIR] smfs_cow_readdir_post,
};
-static int smfs_cow_pre(struct inode *dir, struct dentry *dentry, void *new_dir,
+static int smfs_cow_pre(struct inode *dir, void *dentry, void *new_dir,
void *new_dentry, int op)
{
if (smfs_cow_pre_funcs[op]) {
return 0;
}
-static int smfs_cow_post(struct inode *dir, struct dentry *dentry, void *new_dir,
+static int smfs_cow_post(struct inode *dir, void *dentry, void *new_dir,
void *new_dentry, int op)
{
if (smfs_cow_post_funcs[op]) {