clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
dput(clone_sb->clone_cache->cache_sb->s_root);
list_del(&clone_sb->clone_list_entry);
+
+ put_snap_current_mnt(clone_sb->clone_cache->cache_sb);
EXIT;
}
dput(dentry); /* this will free the dentry memory */
}
+static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode)
+{
+ atomic_set(&dentry->d_count, 1);
+ dentry->d_vfs_flags = 0;
+ dentry->d_flags = 0;
+ dentry->d_inode = inode;
+ dentry->d_op = NULL;
+ dentry->d_fsdata = NULL;
+ dentry->d_mounted = 0;
+ INIT_LIST_HEAD(&dentry->d_hash);
+ INIT_LIST_HEAD(&dentry->d_lru);
+ INIT_LIST_HEAD(&dentry->d_subdirs);
+ INIT_LIST_HEAD(&dentry->d_alias);
+}
/*
* Return the underlying fs dentry with name in 'dentry' that points
* to the right inode. 'dir' is the clone fs directory to search for
struct dentry *clonefs_lookup(struct inode *dir, struct dentry *dentry)
{
struct inode *cache_dir = NULL;
- struct dentry *cache_dentry = NULL, *tmp = NULL;
+ struct dentry *cache_dentry = NULL;
struct inode *cache_inode;
struct dentry *result;
+ struct dentry tmp;
struct inode *inode;
struct snap_clone_info *clone_sb;
cache_dir = clonefs_get_inode(dir);
if (!cache_dir)
RETURN(ERR_PTR(-ENOENT));
-
- tmp = dget(list_entry(cache_dir->i_dentry.next, struct dentry, d_alias));
-
- cache_dentry = d_alloc(tmp->d_parent, &dentry->d_name);
+ /*FIXME later, we make parent dentry here
+ *there may some problems in lookup
+ */
+ prepare_parent_dentry(&tmp, cache_dir);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
if (!cache_dentry) {
iput(cache_dir);
- dput(tmp);
RETURN(ERR_PTR(-ENOENT));
}
/* Lock cache directory inode. */
down(&cache_dir->i_sem);
- dput(tmp);
/*
* Call underlying fs lookup function to set the 'd_inode' pointer
* to the corresponding directory inode.
&open_dentry);
/* tell currentfs_readpage the primary inode number */
open_dentry.d_fsdata = (void*)inode->i_ino;
-
+ page->mapping->host = cache_inode;
/* potemkin case: we are handed a directory inode */
down(&cache_inode->i_sem);
/* XXX - readpage NULL on directories... */
result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
up(&cache_inode->i_sem);
+ page->mapping->host = inode;
clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
iput(cache_inode);
RETURN(result);
static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
{
- int res;
struct inode * cache_inode;
struct inode * old_inode;
+ int rc = -ENOENT;
ENTRY;
cache_inode = clonefs_get_inode(dentry->d_inode);
- res = -ENOENT;
-
- if ( ! cache_inode ) {
+ if (!cache_inode) {
CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(res);
+ RETURN(rc);
}
/* XXX: shall we allocate a new dentry ?
/* set dentry inode to cache inode */
dentry->d_inode = cache_inode;
- if ( cache_inode->i_op->readlink ) {
- res = cache_inode->i_op->readlink(dentry, buf, len);
+ if (cache_inode->i_op->readlink) {
+ rc = cache_inode->i_op->readlink(dentry, buf, len);
}else {
CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
}
iput(cache_inode);
- RETURN(res);
+ RETURN(rc);
}
static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
{
struct inode * cache_inode;
struct inode * old_inode;
- int res;
+ int rc = -ENOENT;
ENTRY;
cache_inode = clonefs_get_inode(dentry->d_inode);
- if ( ! cache_inode ) {
+ if (!cache_inode) {
CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
- RETURN(-ENOENT);
+ RETURN(rc);
}
/* XXX: shall we allocate a new dentry ?
/* set dentry inode to cache inode */
dentry->d_inode = cache_inode;
- if ( cache_inode->i_op->follow_link ) {
- res = cache_inode->i_op->follow_link(dentry, nd);
+ if (cache_inode->i_op->follow_link) {
+ rc = cache_inode->i_op->follow_link(dentry, nd);
}
/* restore the old inode */
iput(cache_inode);
- RETURN(res);
+ RETURN(rc);
}
+static ssize_t
+clonefs_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size)
+{
+ struct inode * cache_inode;
+ struct inode * old_inode;
+ int rc = -ENOENT;
+
+ ENTRY;
+
+ cache_inode = clonefs_get_inode(dentry->d_inode);
+ if (!cache_inode) {
+ CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+ RETURN(rc);
+ }
+
+ /* XXX: shall we allocate a new dentry ?
+ The following is safe for ext2, etc. because ext2_follow_link
+ only use the inode info */
+
+ /* save the old dentry inode */
+ old_inode = dentry->d_inode;
+ /* set dentry inode to cache inode */
+ dentry->d_inode = cache_inode;
+
+ if (cache_inode->i_op->getxattr) {
+ rc = cache_inode->i_op->getxattr(dentry, name, buffer, size);
+ }
+ /* restore the old inode */
+ dentry->d_inode = old_inode;
+
+ iput(cache_inode);
+
+ RETURN(rc);
+}
+static ssize_t
+clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ struct inode * cache_inode;
+ struct inode * old_inode;
+ int rc = -ENOENT;
+
+ ENTRY;
+
+ cache_inode = clonefs_get_inode(dentry->d_inode);
+ if (!cache_inode) {
+ CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+ RETURN(rc);
+ }
+
+ /* XXX: shall we allocate a new dentry ?
+ The following is safe for ext2, etc. because ext2_follow_link
+ only use the inode info */
+
+ /* save the old dentry inode */
+ old_inode = dentry->d_inode;
+ /* set dentry inode to cache inode */
+ dentry->d_inode = cache_inode;
+
+ if (cache_inode->i_op->listxattr) {
+ rc = cache_inode->i_op->listxattr(dentry, buffer, size);
+ }
+
+ /* restore the old inode */
+ dentry->d_inode = old_inode;
+
+ iput(cache_inode);
+
+ RETURN(rc);
+
+}
struct inode_operations clonefs_symlink_inode_ops =
{
/*FIXME later getxattr, listxattr,
* other method need to be replaced too
* */
- readlink: clonefs_readlink, /* readlink */
- follow_link: clonefs_follow_link,/* follow_link */
+ readlink: clonefs_readlink, /* readlink */
+ follow_link: clonefs_follow_link, /* follow_link */
+ getxattr: clonefs_getxattr, /* get xattr */
+ listxattr: clonefs_listxattr, /* list xattr */
};
+int clonefs_mounted(struct snap_cache *cache, int index)
+{
+ struct snap_clone_info *clone_sb;
+ struct list_head *list, *end;
+
+ end = list = &cache->cache_clone_list;
+
+ list_for_each_entry(clone_sb, list, clone_list_entry) {
+ if (clone_sb->clone_index == index)
+ return 1;
+ }
+ return 0;
+}
+