diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 378df892afc86d6d309ddfc717af6a5f1b036da3..bd7dcf2531cbdb7d5d2e78115407e44cfb347940 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -33,7 +33,7 @@ static struct inode *sm_create_inode(struct super_block *sb, inode->i_ino = cache_inode->i_ino; inode->i_mode = cache_inode->i_mode; } - + I2CI(inode) = cache_inode; return inode; } @@ -80,16 +80,21 @@ static int smfs_create(struct inode *dir, 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) { @@ -128,10 +133,305 @@ exit: 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 */ }; diff --git a/lustre/smfs/file.c b/lustre/smfs/file.c index fec85afb47514a22b0d2770fb9a16cd01e9328fe..e4666c49b4548a87152131e2a5ab3f3a698135ef 100644 --- a/lustre/smfs/file.c +++ b/lustre/smfs/file.c @@ -52,59 +52,263 @@ static int smfs_writepage(struct page *page) 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; @@ -117,29 +321,114 @@ static void smfs_truncate(struct inode * 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 */ }; diff --git a/lustre/smfs/smfs_internal.h b/lustre/smfs/smfs_internal.h index 1e09a61446e5af1b78285709f545bf7334c1ed4a..0e5c1d2152ea29f338c607c109a315a34eca354b 100644 --- a/lustre/smfs/smfs_internal.h +++ b/lustre/smfs/smfs_internal.h @@ -71,4 +71,21 @@ extern struct inode_operations smfs_dir_iops; 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 */