diff options
Diffstat (limited to 'fs/bfs')
| -rw-r--r-- | fs/bfs/file.c | 9 | ||||
| -rw-r--r-- | fs/bfs/inode.c | 49 |
2 files changed, 44 insertions, 14 deletions
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index fa66a09e496a..d33d6bde992b 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -27,7 +27,7 @@ const struct file_operations bfs_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, + .mmap_prepare = generic_file_mmap_prepare, .splice_read = filemap_splice_read, }; @@ -170,9 +170,10 @@ static void bfs_write_failed(struct address_space *mapping, loff_t to) truncate_pagecache(inode, inode->i_size); } -static int bfs_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, - struct folio **foliop, void **fsdata) +static int bfs_write_begin(const struct kiocb *iocb, + struct address_space *mapping, + loff_t pos, unsigned len, + struct folio **foliop, void **fsdata) { int ret; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index db81570c9637..984b365df046 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -17,6 +17,7 @@ #include <linux/writeback.h> #include <linux/uio.h> #include <linux/uaccess.h> +#include <linux/fs_context.h> #include "bfs.h" MODULE_AUTHOR("Tigran Aivazian <aivazian.tigran@gmail.com>"); @@ -60,7 +61,19 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino) off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; di = (struct bfs_inode *)bh->b_data + off; - inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); + /* + * https://martin.hinner.info/fs/bfs/bfs-structure.html explains that + * BFS in SCO UnixWare environment used only lower 9 bits of di->i_mode + * value. This means that, although bfs_write_inode() saves whole + * inode->i_mode bits (which include S_IFMT bits and S_IS{UID,GID,VTX} + * bits), middle 7 bits of di->i_mode value can be garbage when these + * bits were not saved by bfs_write_inode(). + * Since we can't tell whether middle 7 bits are garbage, use only + * lower 12 bits (i.e. tolerate S_IS{UID,GID,VTX} bits possibly being + * garbage) and reconstruct S_IFMT bits for Linux environment from + * di->i_vtype value. + */ + inode->i_mode = 0x00000FFF & le32_to_cpu(di->i_mode); if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { inode->i_mode |= S_IFDIR; inode->i_op = &bfs_dir_inops; @@ -70,6 +83,11 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino) inode->i_op = &bfs_file_inops; inode->i_fop = &bfs_file_operations; inode->i_mapping->a_ops = &bfs_aops; + } else { + brelse(bh); + printf("Unknown vtype=%u %s:%08lx\n", + le32_to_cpu(di->i_vtype), inode->i_sb->s_id, ino); + goto error; } BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); @@ -305,7 +323,7 @@ void bfs_dump_imap(const char *prefix, struct super_block *s) #endif } -static int bfs_fill_super(struct super_block *s, void *data, int silent) +static int bfs_fill_super(struct super_block *s, struct fs_context *fc) { struct buffer_head *bh, *sbh; struct bfs_super_block *bfs_sb; @@ -314,6 +332,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) struct bfs_sb_info *info; int ret = -EINVAL; unsigned long i_sblock, i_eblock, i_eoff, s_size; + int silent = fc->sb_flags & SB_SILENT; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -446,18 +465,28 @@ out: return ret; } -static struct dentry *bfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int bfs_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, bfs_fill_super); +} + +static const struct fs_context_operations bfs_context_ops = { + .get_tree = bfs_get_tree, +}; + +static int bfs_init_fs_context(struct fs_context *fc) { - return mount_bdev(fs_type, flags, dev_name, data, bfs_fill_super); + fc->ops = &bfs_context_ops; + + return 0; } static struct file_system_type bfs_fs_type = { - .owner = THIS_MODULE, - .name = "bfs", - .mount = bfs_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .owner = THIS_MODULE, + .name = "bfs", + .init_fs_context = bfs_init_fs_context, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("bfs"); |
