inode->i_ino = cache_inode->i_ino;
inode->i_mode = cache_inode->i_mode;
}
-
+ I2CI(inode) = cache_inode;
return inode;
}
GOTO(exit, rc);
cache_inode = cache_dentry->d_inode;
- inode = sm_create_inode(dir->i_sb, cache_inode);
+// inode = sm_create_inode(dir->i_sb, cache_inode);
+ inode = iget(dir->i_sb, cache_inode->i_ino);
+
if (!inode)
- GOTO(exit, rc);
+ GOTO(exit, rc = -ENOMEM);
+
+ d_instantiate(dentry, inode);
sm_set_inode_ops(cache_inode, inode);
exit:
d_unalloc(cache_dentry);
RETURN(rc);
}
+
static struct dentry *smfs_lookup(struct inode *dir,
struct dentry *dentry)
{
d_unalloc(cache_dentry);
RETURN(rc);
}
+
+static int smfs_lookup_raw(struct inode *dir, const char *name,
+ int len, ino_t *data)
+{
+ struct inode *cache_dir;
+ int rc = 0;
+
+ cache_dir = I2CI(dir);
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ if (cache_dir->i_op->lookup_raw)
+ rc = cache_dir->i_op->lookup_raw(cache_dir, name, len, data);
+
+ RETURN(rc);
+}
+
+static int smfs_link(struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+{
+ struct inode *cache_old_inode = NULL;
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ struct dentry tmp_old;
+ int rc = 0;
+
+ inode = old_dentry->d_inode;
+
+ cache_old_inode = I2CI(inode);
+
+ if (!cache_old_inode || !dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp_old, cache_old_inode);
+
+ prepare_parent_dentry(&tmp, cache_dir);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (cache_dir->i_op->link)
+ rc = cache_dir->i_op->link(&tmp, cache_dir, cache_dentry);
+
+ if (rc == 0) {
+ d_instantiate(dentry, inode);
+ }
+
+ d_unalloc(cache_dentry);
+
+ RETURN(rc);
+}
+static int smfs_unlink(struct inode * dir,
+ struct dentry *dentry)
+{
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *cache_inode = I2CI(dentry->d_inode);
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ int rc = 0;
+
+ if (!cache_dir || !cache_inode)
+ RETURN(-ENOENT);
+
+ 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)
+ rc = cache_dir->i_op->unlink(cache_dir, cache_dentry);
+
+ duplicate_inode(tmp.d_inode, dentry->d_inode);
+
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+static int smfs_symlink (struct inode * dir,
+ struct dentry *dentry,
+ const char * symname)
+{
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *cache_inode = NULL;
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp, NULL);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (cache_inode->i_op->symlink)
+ rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname);
+
+ cache_inode = cache_dentry->d_inode;
+
+ inode = iget(dir->i_sb, cache_inode->i_ino);
+
+ if (inode)
+ d_instantiate(dentry, inode);
+ else
+ rc = -ENOENT;
+
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+static int smfs_mkdir(struct inode * dir,
+ struct dentry * dentry,
+ int mode)
+{
+ struct inode *cache_dir = I2CI(dir);
+ struct inode *cache_inode = NULL;
+ struct inode *inode = NULL;
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp, NULL);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (cache_dir->i_op->mkdir)
+ rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode);
+
+ cache_inode = cache_dentry->d_inode;
+
+ inode = iget(dir->i_sb, cache_inode->i_ino);
+
+ if (!inode)
+ GOTO(exit, rc = -ENOENT);
+
+ d_instantiate(dentry, inode);
+ duplicate_inode(cache_dir, dir);
+exit:
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+static int smfs_rmdir(struct inode * dir,
+ struct dentry *dentry)
+{
+ struct inode *cache_dir = I2CI(dir);
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp, NULL);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (cache_dir->i_op->rmdir)
+ rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry);
+
+ duplicate_inode(cache_dir, dir);
+ duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
+
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+
+static int smfs_mknod(struct inode * dir, struct dentry *dentry,
+ int mode, int rdev)
+{
+ struct inode *cache_dir = I2CI(dir);
+ struct dentry *cache_dentry = NULL;
+ struct dentry tmp;
+ int rc = 0;
+
+ if (!cache_dir)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp, NULL);
+ cache_dentry = d_alloc(&tmp, &dentry->d_name);
+
+ if (cache_dir->i_op->mknod)
+ rc = cache_dir->i_op->mknod(cache_dir, dentry, mode, rdev);
+
+ duplicate_inode(cache_dir, dir);
+ duplicate_inode(cache_dentry->d_inode, dentry->d_inode);
+
+ d_unalloc(cache_dentry);
+ RETURN(rc);
+}
+static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry,
+ struct inode * new_dir,struct dentry *new_dentry)
+{
+ struct inode *cache_old_dir = I2CI(old_dir);
+ struct inode *cache_new_dir = I2CI(new_dir);
+ struct inode *cache_old_inode = I2CI(old_dentry->d_inode);
+ struct inode *cache_new_inode = NULL;
+ struct inode *new_inode = NULL;
+ struct dentry *cache_old_dentry = NULL;
+ struct dentry *cache_new_dentry = NULL;
+ struct dentry tmp_new;
+ struct dentry tmp_old;
+ int rc = 0;
+
+ if (!cache_old_dir || !cache_new_dir || !cache_old_inode)
+ RETURN(-ENOENT);
+
+ prepare_parent_dentry(&tmp_old, old_dir);
+ cache_old_dentry = d_alloc(&tmp_old, &old_dentry->d_name);
+ d_add(cache_old_dentry, cache_old_inode);
+
+ prepare_parent_dentry(&tmp_new, NULL);
+ cache_new_dentry = d_alloc(&tmp_new, &new_dentry->d_name);
+
+ if (cache_old_dir->i_op->rename)
+ rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry,
+ cache_new_dir, cache_new_dentry);
+
+ cache_new_inode = cache_new_dentry->d_inode;
+ new_inode = iget(new_dir->i_sb, cache_new_inode->i_ino);
+
+ d_instantiate(new_dentry, new_inode);
+
+ duplicate_inode(cache_old_dir, old_dir);
+ duplicate_inode(cache_new_dir, new_dir);
+
+ d_unalloc(cache_old_dentry);
+ d_unalloc(cache_new_dentry);
+
+ RETURN(rc);
+}
+
struct inode_operations smfs_dir_iops = {
- create: smfs_create,
- lookup: smfs_lookup,
+ create: smfs_create,
+ lookup: smfs_lookup,
+ lookup_raw: smfs_lookup_raw, /* BKL held */
+ link: smfs_link, /* BKL held */
+ unlink: smfs_unlink, /* BKL held */
+ symlink: smfs_symlink, /* BKL held */
+ mkdir: smfs_mkdir, /* BKL held */
+ rmdir: smfs_rmdir, /* BKL held */
+ mknod: smfs_mknod, /* BKL held */
+ rename: smfs_rename, /* BKL held */
+ setxattr: smfs_setxattr, /* BKL held */
+ getxattr: smfs_getxattr, /* BKL held */
+ listxattr: smfs_listxattr, /* BKL held */
+ removexattr: smfs_removexattr, /* BKL held */
};
-struct file_operations smfs_dir_fops = {
+
+static ssize_t smfs_read_dir(struct file *filp, char *buf,
+ size_t size, loff_t *ppos)
+{
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *cache_inode = NULL;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ 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, size, ppos);
+
+ smfs_update_file(filp, &open_file);
+ RETURN(rc);
+}
+
+static int smfs_readdir(struct file * filp,
+ void * dirent,
+ filldir_t filldir)
+{
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *cache_inode = NULL;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-EINVAL);
+
+ smfs_prepare_cachefile(dentry->d_inode, filp, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->readdir)
+ rc = cache_inode->i_fop->readdir(&open_file, dirent, filldir);
+
+ smfs_update_file(filp, &open_file);
+ RETURN(rc);
+}
+
+struct file_operations smfs_dir_fops = {
+ read: smfs_read_dir,
+ readdir: smfs_readdir, /* BKL held */
+ ioctl: smfs_ioctl, /* BKL held */
+ fsync: smfs_fsync, /* BKL held */
};
rc = cache_inode->i_mapping->a_ops->writepage(page);
RETURN(rc);
-
}
+
struct address_space_operations smfs_file_aops = {
readpage: smfs_readpage,
writepage: smfs_writepage,
};
-
+
+/* instantiate a file handle to the cache file */
+void smfs_prepare_cachefile(struct inode *inode,
+ struct file *file,
+ struct inode *cache_inode,
+ struct file *cache_file,
+ struct dentry *cache_dentry)
+{
+ ENTRY;
+ cache_file->f_pos = file->f_pos;
+ cache_file->f_mode = file->f_mode;
+ cache_file->f_flags = file->f_flags;
+ cache_file->f_count = file->f_count;
+ cache_file->f_owner = file->f_owner;
+ cache_file->f_op = inode->i_fop;
+ cache_file->f_dentry = cache_dentry;
+ cache_file->f_dentry->d_inode = cache_inode;
+ EXIT;
+}
+/* update file structs*/
+void smfs_update_file(struct file *file,
+ struct file *cache_file)
+{
+ ENTRY;
+ file->f_pos = cache_file->f_pos;
+ file->f_mode = cache_file->f_mode;
+ file->f_flags = cache_file->f_flags;
+ file->f_count = cache_file->f_count;
+ file->f_owner = cache_file->f_owner;
+ EXIT;
+}
static ssize_t smfs_write (struct file *filp, const char *buf,
size_t count, loff_t *ppos)
{
struct inode *cache_inode;
struct dentry *dentry = filp->f_dentry;
+ struct inode *inode = dentry->d_inode;
+ struct file open_file;
+ struct dentry open_dentry;
int rc;
ENTRY;
- cache_inode = I2CI(dentry->d_inode);
+ cache_inode = I2CI(inode);
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(filp, buf, count, ppos);
+ cache_inode->i_fop->write(&open_file, buf, count, ppos);
+
+ smfs_update_file(filp, &open_file);
+ RETURN(rc);
+}
+int smfs_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct inode *cache_inode;
+ struct dentry *dentry = filp->f_dentry;
+ struct file open_file;
+ struct dentry open_dentry;
+ ssize_t rc;
+
+ ENTRY;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(inode, filp, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->ioctl)
+ rc = cache_inode->i_fop->ioctl(cache_inode, &open_file, cmd, arg);
+ 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;
cache_inode = I2CI(dentry->d_inode);
-
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(filp, buf, count, ppos);
+ rc = cache_inode->i_fop->read(&open_file, buf, count, ppos);
+
+ smfs_update_file(filp, &open_file);
+ RETURN(rc);
+}
+static loff_t smfs_llseek(struct file *file,
+ loff_t offset,
+ int origin)
+{
+ struct inode *cache_inode;
+ struct dentry *dentry = file->f_dentry;
+ struct file open_file;
+ struct dentry open_dentry;
+ ssize_t rc;
+
+ ENTRY;
+
+ cache_inode = I2CI(dentry->d_inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(dentry->d_inode, file, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->llseek)
+ rc = cache_inode->i_fop->llseek(&open_file, offset, origin);
+
+ smfs_update_file(file, &open_file);
RETURN(rc);
}
+static int smfs_mmap(struct file * file, struct vm_area_struct * vma)
+{
+ struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+ struct inode *inode = mapping->host;
+ struct inode *cache_inode = NULL;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(inode, file, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->mmap)
+ rc = cache_inode->i_fop->mmap(&open_file, vma);
+
+ smfs_update_file(file, &open_file);
+
+ RETURN(rc);
+}
+
+static int smfs_open(struct inode * inode, struct file * filp)
+{
+ struct inode *cache_inode = NULL;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(inode, filp, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->open)
+ rc = cache_inode->i_fop->open(cache_inode, &open_file);
+
+ smfs_update_file(filp, &open_file);
+
+ RETURN(rc);
+
+}
+static int smfs_release(struct inode * inode, struct file * filp)
+{
+ struct inode *cache_inode = NULL;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(inode, filp, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->release)
+ rc = cache_inode->i_fop->release(cache_inode, &open_file);
+
+ smfs_update_file(filp, &open_file);
+
+ RETURN(rc);
+}
+int smfs_fsync(struct file * file,
+ struct dentry *dentry,
+ int datasync)
+{
+ struct inode *inode = dentry->d_inode;
+ struct inode *cache_inode;
+ struct file open_file;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(inode);
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cachefile(inode, file, cache_inode,
+ &open_file, &open_dentry);
+
+ if (cache_inode->i_fop->fsync)
+ rc = cache_inode->i_fop->fsync(&open_file, &open_dentry, datasync);
+
+ smfs_update_file(file, &open_file);
+
+ RETURN(rc);
+}
+
struct file_operations smfs_file_fops = {
- read: smfs_read,
- write: smfs_write,
+ llseek: smfs_llseek,
+ read: smfs_read,
+ write: smfs_write,
+ ioctl: smfs_ioctl,
+ mmap: smfs_mmap,
+ open: smfs_open,
+ release: smfs_release,
+ fsync: smfs_fsync,
};
+static void smfs_prepare_cache_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);
+}
+
static void smfs_truncate(struct inode * inode)
{
struct inode *cache_inode;
if (cache_inode->i_op->truncate)
cache_inode->i_op->truncate(cache_inode);
- duplicate(inode, cache_inode);
+ duplicate_inode(inode, cache_inode);
return;
}
-static int smfs_setattr(struct dentry *dentry, struct iattr *attr)
+int smfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *cache_inode;
+ struct dentry open_dentry;
+
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+ smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+
+ if (cache_inode->i_op->setattr)
+ rc = cache_inode->i_op->setattr(&open_dentry, attr);
+
+ RETURN(rc);
+}
+
+int smfs_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
{
struct inode *cache_inode;
+ struct dentry open_dentry;
int rc = 0;
cache_inode = I2CI(dentry->d_inode);
if (!cache_inode)
RETURN(-ENOENT);
+
+ smfs_prepare_cache_dentry(&open_dentry, cache_inode);
if (cache_inode->i_op->setattr)
- rc = cache_inode->i_op->setattr(dentry, attr);
+ rc = cache_inode->i_op->setxattr(&open_dentry, name, value, size, flags);
RETURN(rc);
}
-
+
+int smfs_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size)
+{
+ struct inode *cache_inode;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+
+ if (cache_inode->i_op->setattr)
+ rc = cache_inode->i_op->getxattr(&open_dentry, name, buffer, size);
+
+ RETURN(rc);
+}
+
+ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ struct inode *cache_inode;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+
+ if (cache_inode->i_op->listxattr)
+ rc = cache_inode->i_op->listxattr(&open_dentry, buffer, size);
+
+ RETURN(rc);
+}
+
+int smfs_removexattr(struct dentry *dentry, const char *name)
+{
+ struct inode *cache_inode;
+ struct dentry open_dentry;
+ int rc = 0;
+
+ cache_inode = I2CI(dentry->d_inode);
+
+ if (!cache_inode)
+ RETURN(-ENOENT);
+
+ smfs_prepare_cache_dentry(&open_dentry, cache_inode);
+
+ if (cache_inode->i_op->removexattr)
+ rc = cache_inode->i_op->removexattr(&open_dentry, name);
+
+ RETURN(rc);
+}
+
struct inode_operations smfs_file_iops = {
truncate: smfs_truncate, /* BKL held */
setattr: smfs_setattr, /* BKL held */
+ setxattr: smfs_setxattr, /* BKL held */
+ getxattr: smfs_getxattr, /* BKL held */
+ listxattr: smfs_listxattr, /* BKL held */
+ removexattr: smfs_removexattr, /* BKL held */
};
extern struct file_operations smfs_dir_fops;
/*inode.c*/
extern void duplicate_inode(struct inode *cache_inode, struct inode *inode);
+/*file.c*/
+extern void smfs_prepare_cachefile(struct inode *inode,
+ struct file *file,
+ struct inode *cache_inode,
+ struct file *cache_file,
+ struct dentry *cache_dentry);
+extern int smfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd,
+ unsigned long arg);
+extern int smfs_fsync(struct file * file, struct dentry *dentry, int datasync);
+extern int smfs_setattr(struct dentry *dentry, struct iattr *attr);
+extern int smfs_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags);
+extern int smfs_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size);
+extern ssize_t smfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+extern int smfs_removexattr(struct dentry *dentry, const char *name);
+extern void smfs_update_file(struct file *file, struct file *cache_file);
#endif /* __LINUX_SMFS_H */