struct file_operations *cache_fops,
struct address_space_operations *cache_aops)
{
-
struct smfs_super_info *smb;
struct inode_operations *iops;
struct file_operations *fops;
sops->statfs = smfs_sops->statfs;
if (cache_sb->s_op->remount_fs)
sops->remount_fs = smfs_sops->remount_fs;
- if (cache_sb->s_op->clear_inode)
- sops->clear_inode = smfs_sops->clear_inode;
if (cache_sb->s_op->umount_begin)
sops->umount_begin = smfs_sops->umount_begin;
if (cache_sb->s_op->fh_to_dentry)
sops->dentry_to_fh = smfs_sops->dentry_to_fh;
if (cache_sb->s_op->show_options)
sops->show_options = smfs_sops->show_options;
+ /*FIXME we need this method to clear the cache inode */
+ sops->clear_inode = smfs_sops->clear_inode;
}
return;
if (dentry) {
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
- dput(dentry);
+ dput(dentry);
}
}
static struct inode *sm_create_inode(struct super_block *sb,
if (!cache_dir || !cache_inode)
RETURN(-ENOENT);
+ igrab(cache_dentry->d_inode);
+
prepare_parent_dentry(&tmp, cache_dir);
cache_dentry = d_alloc(&tmp, &dentry->d_name);
d_add(cache_dentry, cache_inode);
- if (cache_inode->i_op->unlink)
+ if (cache_dir->i_op->unlink)
rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
- duplicate_inode(tmp.d_inode, dentry->d_inode);
+
+ duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
+ duplicate_inode(cache_dir, dir);
d_unalloc(cache_dentry);
RETURN(rc);
#include <linux/pagemap.h>
#include "smfs_internal.h"
-
static int smfs_readpage(struct file *file,
struct page *page)
{
struct inode *inode = page->mapping->host;
struct inode *cache_inode;
- int rc;
-
+ struct page *cache_page = NULL;
+ int rc = 0;
+
ENTRY;
cache_inode = I2CI(inode);
if (!cache_inode)
RETURN(-ENOENT);
+
+ cache_page = grab_cache_page(cache_inode->i_mapping, page->index);
- if (cache_inode->i_mapping->a_ops->readpage)
- rc = cache_inode->i_mapping->a_ops->readpage(file, page);
-
- RETURN(rc);
+ if (!cache_page)
+ GOTO(exit_release, rc = -ENOMEM);
+
+ if ((rc = cache_inode->i_mapping->a_ops->readpage(file, cache_page)))
+ GOTO(exit_release, 0);
+ wait_on_page(cache_page);
+
+ if (!Page_Uptodate(cache_page))
+ GOTO(exit_release, rc = -EIO);
+
+ memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
+
+ flush_dcache_page(page);
+
+ kunmap(cache_page);
+ page_cache_release(cache_page);
+
+exit:
+ kunmap(page);
+ SetPageUptodate(page);
+ UnlockPage(page);
+
+ RETURN(rc);
+
+exit_release:
+ if (cache_page)
+ page_cache_release(cache_page);
+ UnlockPage(page);
+ RETURN(rc);
}
+
static int smfs_writepage(struct page *page)
{
cache_file->f_flags = file->f_flags;
cache_file->f_count = file->f_count;
cache_file->f_owner = file->f_owner;
+ cache_file->f_error = file->f_error;
cache_file->f_op = inode->i_fop;
cache_file->f_dentry = cache_dentry;
cache_file->f_dentry->d_inode = cache_inode;
+ cache_file->f_vfsmnt = file->f_vfsmnt;
+ cache_file->private_data = file->private_data;
+ cache_file->f_it = file->f_it;
+ cache_file->f_reada = file->f_reada;
+ cache_file->f_ramax = file->f_ramax;
+ cache_file->f_raend = file->f_raend;
+ cache_file->f_ralen = file->f_ralen;
+ cache_file->f_rawin = file->f_rawin;
EXIT;
}
/* update file structs*/
file->f_flags = cache_file->f_flags;
file->f_count = cache_file->f_count;
file->f_owner = cache_file->f_owner;
+ file->f_reada = cache_file->f_reada;
+ file->f_ramax = cache_file->f_ramax;
+ file->f_raend = cache_file->f_raend;
+ file->f_ralen = cache_file->f_ralen;
+ file->f_rawin = cache_file->f_rawin;
EXIT;
}
struct inode *inode = dentry->d_inode;
struct file open_file;
struct dentry open_dentry;
- int rc;
+ int rc = 0;
ENTRY;
if (!cache_inode)
RETURN(-ENOENT);
-
+
smfs_prepare_cachefile(inode, filp, cache_inode,
&open_file, &open_dentry);
if (cache_inode->i_fop->write)
- cache_inode->i_fop->write(&open_file, buf, count, ppos);
-
+ rc = cache_inode->i_fop->write(&open_file, buf, count, ppos);
+
+ duplicate_inode(cache_inode, inode);
smfs_update_file(filp, &open_file);
+
RETURN(rc);
}
int smfs_ioctl(struct inode * inode, struct file * filp,
if (cache_inode->i_fop->ioctl)
rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
+ duplicate_inode(cache_inode, inode);
smfs_update_file(filp, &open_file);
RETURN(rc);
}
+
static ssize_t smfs_read (struct file *filp, char *buf,
size_t count, loff_t *ppos)
{
struct inode *cache_inode;
struct dentry *dentry = filp->f_dentry;
- struct file open_file;
- struct dentry open_dentry;
ssize_t rc;
ENTRY;
if (!cache_inode)
RETURN(-ENOENT);
- smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode,
- &open_file, &open_dentry);
-
if (cache_inode->i_fop->read)
- rc = cache_inode->i_fop->read(&open_file, buf, count, ppos);
-
- smfs_update_file(filp, &open_file);
- RETURN(rc);
+ rc = cache_inode->i_fop->read(filp, buf, count, ppos);
+
+ duplicate_inode(cache_inode, dentry->d_inode);
+ RETURN(rc);
}
+
static loff_t smfs_llseek(struct file *file,
loff_t offset,
int origin)
if (cache_inode->i_fop->llseek)
rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
+ duplicate_inode(cache_inode, dentry->d_inode);
smfs_update_file(file, &open_file);
RETURN(rc);
if (cache_inode->i_fop->mmap)
rc = cache_inode->i_fop->mmap(&open_file, vma);
+ duplicate_inode(cache_inode, inode);
smfs_update_file(file, &open_file);
RETURN(rc);
if (cache_inode->i_fop->open)
rc = cache_inode->i_fop->open(cache_inode, &open_file);
+ duplicate_inode(cache_inode, inode);
smfs_update_file(filp, &open_file);
RETURN(rc);
if (cache_inode->i_fop->release)
rc = cache_inode->i_fop->release(cache_inode, &open_file);
+ duplicate_inode(cache_inode, inode);
smfs_update_file(filp, &open_file);
RETURN(rc);
if (cache_inode->i_fop->fsync)
rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
+ duplicate_inode(cache_inode, inode);
smfs_update_file(file, &open_file);
RETURN(rc);
/*
- * fs/snap/snap.c
- *
- * A snap shot file system.
+ * smfs/inode.c
*
*/
* size */
inode->i_blocks = cache_inode->i_blocks;
inode->i_version = cache_inode->i_version;
+ inode->i_state = cache_inode->i_state;
}
static void smfs_read_inode(struct inode *inode)
{
cache_sb = S2CSB(inode->i_sb);
cache_inode = I2CI(inode);
+
+ duplicate_inode(inode, cache_inode);
+
+ if (cache_sb->s_op->clear_inode)
+ cache_sb->s_op->clear_inode(cache_inode);
+
clear_inode(cache_inode);
+ duplicate_inode(inode, cache_inode);
+
return;
}
+static void smfs_delete_inode(struct inode *inode)
+{
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
+
+ if (!cache_inode || !cache_sb)
+ return;
+
+ duplicate_inode(inode, cache_inode);
+
+ if (cache_sb->s_op->delete_inode)
+ cache_sb->s_op->delete_inode(cache_inode);
+
+ duplicate_inode(cache_inode, inode);
+
+ return;
+}
+static void smfs_write_inode(struct inode *inode, int wait)
+{
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
+
+ if (!cache_inode || !cache_sb)
+ return;
+
+ if (cache_sb->s_op->write_inode)
+ cache_sb->s_op->write_inode(cache_inode, wait);
+
+ duplicate_inode(cache_inode, inode);
+
+ return;
+}
+static void smfs_dirty_inode(struct inode *inode)
+{
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
+
+ if (!cache_inode || !cache_sb)
+ return;
+
+ if (cache_sb->s_op->dirty_inode)
+ cache_sb->s_op->dirty_inode(cache_inode);
+
+ duplicate_inode(cache_inode, inode);
+ return;
+}
+
+static void smfs_put_inode(struct inode *inode)
+{
+ struct inode *cache_inode;
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_inode = I2CI(inode);
+ cache_sb = S2CSB(inode->i_sb);
+
+ if (!cache_inode || !cache_sb)
+ return;
+
+ if (cache_sb->s_op->put_inode)
+ cache_sb->s_op->put_inode(cache_inode);
+
+ return;
+}
+
+static void smfs_write_super(struct super_block *sb)
+{
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_sb = S2CSB(sb);
+
+ if (!cache_sb)
+ return;
+
+ if (cache_sb->s_op->write_super)
+ cache_sb->s_op->write_super(cache_sb);
+
+ duplicate_sb(cache_sb, sb);
+ return;
+}
+
+static void smfs_write_super_lockfs(struct super_block *sb)
+{
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_sb = S2CSB(sb);
+
+ if (!cache_sb)
+ return;
+
+ if (cache_sb->s_op->write_super_lockfs)
+ cache_sb->s_op->write_super_lockfs(cache_sb);
+
+ duplicate_sb(cache_sb, sb);
+ return;
+}
+
+static void smfs_unlockfs(struct super_block *sb)
+{
+ struct super_block *cache_sb;
+
+ ENTRY;
+ cache_sb = S2CSB(sb);
+
+ if (!cache_sb)
+ return;
+
+ if (cache_sb->s_op->unlockfs)
+ cache_sb->s_op->unlockfs(cache_sb);
+
+ duplicate_sb(cache_sb, sb);
+ return;
+}
+static void smfs_statfs(struct super_block * sb, struct statfs * buf)
+{
+ struct super_block *cache_sb;
+ ENTRY;
+ cache_sb = S2CSB(sb);
+
+ if (!cache_sb)
+ return;
+
+ if (cache_sb->s_op->statfs)
+ cache_sb->s_op->statfs(cache_sb, buf);
+
+ duplicate_sb(cache_sb, sb);
+ return;
+}
+static int smfs_remount(struct super_block * sb, int * flags, char * data)
+{
+ struct super_block *cache_sb;
+ int rc = 0;
+
+ ENTRY;
+ cache_sb = S2CSB(sb);
+
+ if (!cache_sb)
+ RETURN(-EINVAL);
+
+ if (cache_sb->s_op->remount_fs)
+ rc = cache_sb->s_op->remount_fs(cache_sb, flags, data);
+
+ duplicate_sb(cache_sb, sb);
+ RETURN(rc);
+}
struct super_operations smfs_super_ops = {
read_inode: smfs_read_inode,
clear_inode: smfs_clear_inode,
put_super: smfs_put_super,
+ delete_inode: smfs_delete_inode,
+ write_inode: smfs_write_inode,
+ dirty_inode: smfs_dirty_inode, /* BKL not held. We take it */
+ put_inode: smfs_put_inode, /* BKL not held. Don't need */
+
+ write_super: smfs_write_super, /* BKL held */
+ write_super_lockfs: smfs_write_super_lockfs, /* BKL not held. Take it */
+ unlockfs: smfs_unlockfs, /* BKL not held. We take it */
+ statfs: smfs_statfs, /* BKL held */
+ remount_fs: smfs_remount, /* BKL held */
+
};
void init_smfs_cache(void);
void cleanup_smfs_cache(void);
/*super.c*/
-int init_smfs(void);
-int cleanup_smfs(void);
-void smfs_put_super(struct super_block *sb);
+extern int init_smfs(void);
+extern int cleanup_smfs(void);
+extern void smfs_put_super(struct super_block *sb);
+extern void duplicate_sb(struct super_block *csb, struct super_block *sb);
/*sysctl.c*/
extern int sm_debug_level;
extern int sm_inodes;
sb->s_magic = csb->s_magic;
sb->s_blocksize_bits = csb->s_blocksize_bits;
sb->s_maxbytes = csb->s_maxbytes;
+ sb->s_flags = csb->s_flags;
}
extern struct super_operations smfs_super_ops;