aboutsummaryrefslogtreecommitdiff
path: root/fs/omfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/omfs')
-rw-r--r--fs/omfs/dir.c168
-rw-r--r--fs/omfs/file.c37
-rw-r--r--fs/omfs/inode.c21
-rw-r--r--fs/omfs/omfs.h6
4 files changed, 99 insertions, 133 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,
};
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 8a6d34fa668..902e88527fc 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -4,7 +4,6 @@
* Released under GPL v2.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
@@ -147,8 +146,7 @@ static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe,
be64_to_cpu(entry->e_blocks);
if (omfs_allocate_block(inode->i_sb, new_block)) {
- entry->e_blocks =
- cpu_to_be64(be64_to_cpu(entry->e_blocks) + 1);
+ be64_add_cpu(&entry->e_blocks, 1);
terminator->e_blocks = ~(cpu_to_be64(
be64_to_cpu(~terminator->e_blocks) + 1));
goto out;
@@ -178,7 +176,7 @@ static int omfs_grow_extent(struct inode *inode, struct omfs_extent *oe,
be64_to_cpu(~terminator->e_blocks) + (u64) new_count));
/* write in new entry */
- oe->e_extent_count = cpu_to_be32(1 + be32_to_cpu(oe->e_extent_count));
+ be32_add_cpu(&oe->e_extent_count, 1);
out:
*ret_block = new_block;
@@ -308,6 +306,16 @@ omfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
return mpage_writepages(mapping, wbc, omfs_get_block);
}
+static void omfs_write_failed(struct address_space *mapping, loff_t to)
+{
+ struct inode *inode = mapping->host;
+
+ if (to > inode->i_size) {
+ truncate_pagecache(inode, inode->i_size);
+ omfs_truncate(inode);
+ }
+}
+
static int omfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata)
@@ -316,11 +324,8 @@ static int omfs_write_begin(struct file *file, struct address_space *mapping,
ret = block_write_begin(mapping, pos, len, flags, pagep,
omfs_get_block);
- if (unlikely(ret)) {
- loff_t isize = mapping->host->i_size;
- if (pos + len > isize)
- vmtruncate(mapping->host, isize);
- }
+ if (unlikely(ret))
+ omfs_write_failed(mapping, pos + len);
return ret;
}
@@ -332,10 +337,10 @@ static sector_t omfs_bmap(struct address_space *mapping, sector_t block)
const struct file_operations omfs_file_operations = {
.llseek = generic_file_llseek,
- .read = do_sync_read,
- .write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read = new_sync_read,
+ .write = new_sync_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
@@ -352,9 +357,11 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
- error = vmtruncate(inode, attr->ia_size);
+ error = inode_newsize_ok(inode, attr->ia_size);
if (error)
return error;
+ truncate_setsize(inode, attr->ia_size);
+ omfs_truncate(inode);
}
setattr_copy(inode, attr);
@@ -364,7 +371,6 @@ static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
const struct inode_operations omfs_file_inops = {
.setattr = omfs_setattr,
- .truncate = omfs_truncate
};
const struct address_space_operations omfs_aops = {
@@ -372,7 +378,6 @@ const struct address_space_operations omfs_aops = {
.readpages = omfs_readpages,
.writepage = omfs_writepage,
.writepages = omfs_writepages,
- .sync_page = block_sync_page,
.write_begin = omfs_write_begin,
.write_end = generic_write_end,
.bmap = omfs_bmap,
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index e043c4cb9a9..ec58c765918 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -28,7 +28,7 @@ struct buffer_head *omfs_bread(struct super_block *sb, sector_t block)
return sb_bread(sb, clus_to_blk(sbi, block));
}
-struct inode *omfs_new_inode(struct inode *dir, int mode)
+struct inode *omfs_new_inode(struct inode *dir, umode_t mode)
{
struct inode *inode;
u64 new_block;
@@ -183,8 +183,8 @@ int omfs_sync_inode(struct inode *inode)
*/
static void omfs_evict_inode(struct inode *inode)
{
- truncate_inode_pages(&inode->i_data, 0);
- end_writeback(inode);
+ truncate_inode_pages_final(&inode->i_data);
+ clear_inode(inode);
if (inode->i_nlink)
return;
@@ -391,12 +391,16 @@ static int parse_options(char *options, struct omfs_sb_info *sbi)
case Opt_uid:
if (match_int(&args[0], &option))
return 0;
- sbi->s_uid = option;
+ sbi->s_uid = make_kuid(current_user_ns(), option);
+ if (!uid_valid(sbi->s_uid))
+ return 0;
break;
case Opt_gid:
if (match_int(&args[0], &option))
return 0;
- sbi->s_gid = option;
+ sbi->s_gid = make_kgid(current_user_ns(), option);
+ if (!gid_valid(sbi->s_gid))
+ return 0;
break;
case Opt_umask:
if (match_octal(&args[0], &option))
@@ -539,11 +543,9 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
goto out_brelse_bh2;
}
- sb->s_root = d_alloc_root(root);
- if (!sb->s_root) {
- iput(root);
+ sb->s_root = d_make_root(root);
+ if (!sb->s_root)
goto out_brelse_bh2;
- }
printk(KERN_DEBUG "omfs: Mounted volume %s\n", omfs_rb->r_name);
ret = 0;
@@ -570,6 +572,7 @@ static struct file_system_type omfs_fs_type = {
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
+MODULE_ALIAS_FS("omfs");
static int __init init_omfs_fs(void)
{
diff --git a/fs/omfs/omfs.h b/fs/omfs/omfs.h
index 7d414fef501..f0f8bc75e60 100644
--- a/fs/omfs/omfs.h
+++ b/fs/omfs/omfs.h
@@ -19,8 +19,8 @@ struct omfs_sb_info {
unsigned long **s_imap;
int s_imap_size;
struct mutex s_bitmap_lock;
- int s_uid;
- int s_gid;
+ kuid_t s_uid;
+ kgid_t s_gid;
int s_dmask;
int s_fmask;
};
@@ -60,7 +60,7 @@ extern int omfs_shrink_inode(struct inode *inode);
/* inode.c */
extern struct buffer_head *omfs_bread(struct super_block *sb, sector_t block);
extern struct inode *omfs_iget(struct super_block *sb, ino_t inode);
-extern struct inode *omfs_new_inode(struct inode *dir, int mode);
+extern struct inode *omfs_new_inode(struct inode *dir, umode_t mode);
extern int omfs_reserve_block(struct super_block *sb, sector_t block);
extern int omfs_find_empty_block(struct super_block *sb, int mode, ino_t *ino);
extern int omfs_sync_inode(struct inode *inode);