diff options
Diffstat (limited to 'fs/omfs/dir.c')
| -rw-r--r-- | fs/omfs/dir.c | 168 |
1 files changed, 63 insertions, 105 deletions
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index 393f3f659da..1b8e9e8405b 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c @@ -93,7 +93,7 @@ int omfs_make_empty(struct inode *inode, struct super_block *sb) memset(bh->b_data, 0, sizeof(struct omfs_inode)); - if (inode->i_mode & S_IFDIR) { + if (S_ISDIR(inode->i_mode)) { memset(&bh->b_data[OMFS_DIR_START], 0xff, sbi->s_sys_blocksize - OMFS_DIR_START); } else @@ -235,36 +235,27 @@ static int omfs_dir_is_empty(struct inode *inode) return *ptr != ~0; } -static int omfs_unlink(struct inode *dir, struct dentry *dentry) +static int omfs_remove(struct inode *dir, struct dentry *dentry) { - int ret; struct inode *inode = dentry->d_inode; + int ret; + + + if (S_ISDIR(inode->i_mode) && + !omfs_dir_is_empty(inode)) + return -ENOTEMPTY; ret = omfs_delete_entry(dentry); if (ret) - goto end_unlink; - - inode_dec_link_count(inode); + return ret; + + clear_nlink(inode); + mark_inode_dirty(inode); mark_inode_dirty(dir); - -end_unlink: - return ret; -} - -static int omfs_rmdir(struct inode *dir, struct dentry *dentry) -{ - int err = -ENOTEMPTY; - struct inode *inode = dentry->d_inode; - - if (omfs_dir_is_empty(inode)) { - err = omfs_unlink(dir, dentry); - if (!err) - inode_dec_link_count(inode); - } - return err; + return 0; } -static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode) +static int omfs_add_node(struct inode *dir, struct dentry *dentry, umode_t mode) { int err; struct inode *inode = omfs_new_inode(dir, mode); @@ -288,19 +279,19 @@ out_free_inode: return err; } -static int omfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int omfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { return omfs_add_node(dir, dentry, mode | S_IFDIR); } -static int omfs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) +static int omfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) { return omfs_add_node(dir, dentry, mode | S_IFREG); } static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) + unsigned int flags) { struct buffer_head *bh; struct inode *inode = NULL; @@ -336,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header, return is_bad; } -static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, +static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx, u64 fsblock, int hindex) { - struct inode *dir = filp->f_dentry->d_inode; - struct buffer_head *bh; - struct omfs_inode *oi; - u64 self; - int res = 0; - unsigned char d_type; - /* follow chain in this bucket */ while (fsblock != ~0) { - bh = omfs_bread(dir->i_sb, fsblock); + struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock); + struct omfs_inode *oi; + u64 self; + unsigned char d_type; + if (!bh) - goto out; + return true; oi = (struct omfs_inode *) bh->b_data; if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) { brelse(bh); - goto out; + return true; } self = fsblock; @@ -370,14 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG; - res = filldir(dirent, oi->i_name, strnlen(oi->i_name, - OMFS_NAMELEN), filp->f_pos, self, d_type); - if (res == 0) - filp->f_pos++; + if (!dir_emit(ctx, oi->i_name, + strnlen(oi->i_name, OMFS_NAMELEN), + self, d_type)) { + brelse(bh); + return false; + } brelse(bh); + ctx->pos++; } -out: - return res; + return true; } static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -385,102 +375,70 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry, { struct inode *new_inode = new_dentry->d_inode; struct inode *old_inode = old_dentry->d_inode; - struct buffer_head *bh; - int is_dir; int err; - is_dir = S_ISDIR(old_inode->i_mode); - if (new_inode) { /* overwriting existing file/dir */ - err = -ENOTEMPTY; - if (is_dir && !omfs_dir_is_empty(new_inode)) - goto out; - - err = -ENOENT; - bh = omfs_find_entry(new_dir, new_dentry->d_name.name, - new_dentry->d_name.len); - if (IS_ERR(bh)) - goto out; - brelse(bh); - - err = omfs_unlink(new_dir, new_dentry); + err = omfs_remove(new_dir, new_dentry); if (err) goto out; } /* since omfs locates files by name, we need to unlink _before_ * adding the new link or we won't find the old one */ - inode_inc_link_count(old_inode); - err = omfs_unlink(old_dir, old_dentry); - if (err) { - inode_dec_link_count(old_inode); + err = omfs_delete_entry(old_dentry); + if (err) goto out; - } + mark_inode_dirty(old_dir); err = omfs_add_link(new_dentry, old_inode); if (err) goto out; old_inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(old_inode); out: return err; } -static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) +static int omfs_readdir(struct file *file, struct dir_context *ctx) { - struct inode *dir = filp->f_dentry->d_inode; + struct inode *dir = file_inode(file); struct buffer_head *bh; - loff_t offset, res; + __be64 *p; unsigned int hchain, hindex; int nbuckets; - u64 fsblock; - int ret = -EINVAL; - - if (filp->f_pos >> 32) - goto success; - - switch ((unsigned long) filp->f_pos) { - case 0: - if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0) - goto success; - filp->f_pos++; - /* fall through */ - case 1: - if (filldir(dirent, "..", 2, 1, - parent_ino(filp->f_dentry), DT_DIR) < 0) - goto success; - filp->f_pos = 1 << 20; - /* fall through */ + + if (ctx->pos >> 32) + return -EINVAL; + + if (ctx->pos < 1 << 20) { + if (!dir_emit_dots(file, ctx)) + return 0; + ctx->pos = 1 << 20; } nbuckets = (dir->i_size - OMFS_DIR_START) / 8; /* high 12 bits store bucket + 1 and low 20 bits store hash index */ - hchain = (filp->f_pos >> 20) - 1; - hindex = filp->f_pos & 0xfffff; + hchain = (ctx->pos >> 20) - 1; + hindex = ctx->pos & 0xfffff; bh = omfs_bread(dir->i_sb, dir->i_ino); if (!bh) - goto out; - - offset = OMFS_DIR_START + hchain * 8; + return -EINVAL; - for (; hchain < nbuckets; hchain++, offset += 8) { - fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset])); + p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain; - res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex); - hindex = 0; - if (res < 0) + for (; hchain < nbuckets; hchain++) { + __u64 fsblock = be64_to_cpu(*p++); + if (!omfs_fill_chain(dir, ctx, fsblock, hindex)) break; - - filp->f_pos = (hchain+2) << 20; + hindex = 0; + ctx->pos = (hchain+2) << 20; } brelse(bh); -success: - ret = 0; -out: - return ret; + return 0; } const struct inode_operations omfs_dir_inops = { @@ -488,12 +446,12 @@ const struct inode_operations omfs_dir_inops = { .mkdir = omfs_mkdir, .rename = omfs_rename, .create = omfs_create, - .unlink = omfs_unlink, - .rmdir = omfs_rmdir, + .unlink = omfs_remove, + .rmdir = omfs_remove, }; const struct file_operations omfs_dir_operations = { .read = generic_read_dir, - .readdir = omfs_readdir, + .iterate = omfs_readdir, .llseek = generic_file_llseek, }; |
