diff options
Diffstat (limited to 'libbcachefs/fs.c')
-rw-r--r-- | libbcachefs/fs.c | 868 |
1 files changed, 363 insertions, 505 deletions
diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c index 76829f49..081ae140 100644 --- a/libbcachefs/fs.c +++ b/libbcachefs/fs.c @@ -9,6 +9,7 @@ #include "extents.h" #include "fs.h" #include "fs-io.h" +#include "fs-ioctl.h" #include "fsck.h" #include "inode.h" #include "journal.h" @@ -18,10 +19,8 @@ #include <linux/aio.h> #include <linux/backing-dev.h> -#include <linux/compat.h> #include <linux/exportfs.h> #include <linux/module.h> -#include <linux/mount.h> #include <linux/posix_acl.h> #include <linux/random.h> #include <linux/statfs.h> @@ -62,16 +61,15 @@ static void bch2_vfs_inode_init(struct bch_fs *, */ int __must_check __bch2_write_inode(struct bch_fs *c, - struct bch_inode_info *ei, + struct bch_inode_info *inode, inode_set_fn set, void *p) { struct btree_iter iter; - struct inode *inode = &ei->vfs_inode; struct bch_inode_unpacked inode_u; struct bkey_inode_buf inode_p; - u64 inum = inode->i_ino; - unsigned i_nlink = READ_ONCE(inode->i_nlink); + u64 inum = inode->v.i_ino; + unsigned i_nlink = READ_ONCE(inode->v.i_nlink); int ret; /* @@ -82,7 +80,7 @@ int __must_check __bch2_write_inode(struct bch_fs *c, if (!i_nlink) return 0; - lockdep_assert_held(&ei->update_lock); + lockdep_assert_held(&inode->ei_update_lock); bch2_btree_iter_init(&iter, c, BTREE_ID_INODES, POS(inum, 0), BTREE_ITER_INTENT); @@ -107,33 +105,34 @@ int __must_check __bch2_write_inode(struct bch_fs *c, } if (set) { - ret = set(ei, &inode_u, p); + ret = set(inode, &inode_u, p); if (ret) goto out; } - BUG_ON(i_nlink < nlink_bias(inode->i_mode)); + BUG_ON(i_nlink < nlink_bias(inode->v.i_mode)); - inode_u.i_mode = inode->i_mode; - inode_u.i_uid = i_uid_read(inode); - inode_u.i_gid = i_gid_read(inode); - inode_u.i_nlink = i_nlink - nlink_bias(inode->i_mode); - inode_u.i_dev = inode->i_rdev; - inode_u.i_atime = timespec_to_bch2_time(c, inode->i_atime); - inode_u.i_mtime = timespec_to_bch2_time(c, inode->i_mtime); - inode_u.i_ctime = timespec_to_bch2_time(c, inode->i_ctime); + inode_u.bi_mode = inode->v.i_mode; + inode_u.bi_uid = i_uid_read(&inode->v); + inode_u.bi_gid = i_gid_read(&inode->v); + inode_u.bi_nlink= i_nlink - nlink_bias(inode->v.i_mode); + inode_u.bi_dev = inode->v.i_rdev; + inode_u.bi_atime= timespec_to_bch2_time(c, inode->v.i_atime); + inode_u.bi_mtime= timespec_to_bch2_time(c, inode->v.i_mtime); + inode_u.bi_ctime= timespec_to_bch2_time(c, inode->v.i_ctime); bch2_inode_pack(&inode_p, &inode_u); - ret = bch2_btree_insert_at(c, NULL, NULL, &ei->journal_seq, + ret = bch2_btree_insert_at(c, NULL, NULL, + &inode->ei_journal_seq, BTREE_INSERT_ATOMIC| BTREE_INSERT_NOFAIL, BTREE_INSERT_ENTRY(&iter, &inode_p.inode.k_i)); } while (ret == -EINTR); if (!ret) { - ei->i_size = inode_u.i_size; - ei->i_flags = inode_u.i_flags; + inode->ei_size = inode_u.bi_size; + inode->ei_flags = inode_u.bi_flags; } out: bch2_btree_iter_unlock(&iter); @@ -142,484 +141,475 @@ out: } int __must_check bch2_write_inode(struct bch_fs *c, - struct bch_inode_info *ei) + struct bch_inode_info *inode) { - return __bch2_write_inode(c, ei, NULL, NULL); + return __bch2_write_inode(c, inode, NULL, NULL); } -int bch2_inc_nlink(struct bch_fs *c, struct bch_inode_info *ei) +int bch2_inc_nlink(struct bch_fs *c, struct bch_inode_info *inode) { int ret; - mutex_lock(&ei->update_lock); - inc_nlink(&ei->vfs_inode); - ret = bch2_write_inode(c, ei); - mutex_unlock(&ei->update_lock); + mutex_lock(&inode->ei_update_lock); + inc_nlink(&inode->v); + ret = bch2_write_inode(c, inode); + mutex_unlock(&inode->ei_update_lock); return ret; } -int bch2_dec_nlink(struct bch_fs *c, struct bch_inode_info *ei) +int bch2_dec_nlink(struct bch_fs *c, struct bch_inode_info *inode) { int ret = 0; - mutex_lock(&ei->update_lock); - drop_nlink(&ei->vfs_inode); - ret = bch2_write_inode(c, ei); - mutex_unlock(&ei->update_lock); + mutex_lock(&inode->ei_update_lock); + drop_nlink(&inode->v); + ret = bch2_write_inode(c, inode); + mutex_unlock(&inode->ei_update_lock); return ret; } -static struct inode *bch2_vfs_inode_get(struct super_block *sb, u64 inum) +static struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum) { - struct bch_fs *c = sb->s_fs_info; - struct inode *inode; struct bch_inode_unpacked inode_u; - struct bch_inode_info *ei; + struct bch_inode_info *inode; int ret; - pr_debug("inum %llu", inum); - - inode = iget_locked(sb, inum); + inode = to_bch_ei(iget_locked(c->vfs_sb, inum)); if (unlikely(!inode)) return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; + if (!(inode->v.i_state & I_NEW)) + return &inode->v; ret = bch2_inode_find_by_inum(c, inum, &inode_u); if (ret) { - iget_failed(inode); + iget_failed(&inode->v); return ERR_PTR(ret); } - ei = to_bch_ei(inode); - bch2_vfs_inode_init(c, ei, &inode_u); + bch2_vfs_inode_init(c, inode, &inode_u); - ei->journal_seq = bch2_inode_journal_seq(&c->journal, inum); + inode->ei_journal_seq = bch2_inode_journal_seq(&c->journal, inum); - unlock_new_inode(inode); + unlock_new_inode(&inode->v); - return inode; + return &inode->v; } -static struct inode *bch2_vfs_inode_create(struct bch_fs *c, - struct inode *parent, - umode_t mode, dev_t rdev) +static struct bch_inode_info *bch2_vfs_inode_create(struct bch_fs *c, + struct bch_inode_info *dir, + umode_t mode, dev_t rdev) { - struct inode *inode; struct posix_acl *default_acl = NULL, *acl = NULL; - struct bch_inode_info *ei; + struct bch_inode_info *inode; struct bch_inode_unpacked inode_u; int ret; - inode = new_inode(parent->i_sb); + inode = to_bch_ei(new_inode(c->vfs_sb)); if (unlikely(!inode)) return ERR_PTR(-ENOMEM); - inode_init_owner(inode, parent, mode); + inode_init_owner(&inode->v, &dir->v, mode); - ret = posix_acl_create(parent, &inode->i_mode, &default_acl, &acl); +#ifdef CONFIG_BCACHEFS_POSIX_ACL + ret = posix_acl_create(&dir->v, &inode->v.i_mode, &default_acl, &acl); if (ret) { - make_bad_inode(inode); + make_bad_inode(&inode->v); goto err; } +#endif - ei = to_bch_ei(inode); - - bch2_inode_init(c, &inode_u, i_uid_read(inode), - i_gid_read(inode), inode->i_mode, rdev); + bch2_inode_init(c, &inode_u, + i_uid_read(&inode->v), + i_gid_read(&inode->v), + inode->v.i_mode, rdev); ret = bch2_inode_create(c, &inode_u, - BLOCKDEV_INODE_MAX, 0, - &c->unused_inode_hint); + BLOCKDEV_INODE_MAX, 0, + &c->unused_inode_hint); if (unlikely(ret)) { /* * indicate to bch_evict_inode that the inode was never actually * created: */ - make_bad_inode(inode); + make_bad_inode(&inode->v); goto err; } - bch2_vfs_inode_init(c, ei, &inode_u); + bch2_vfs_inode_init(c, inode, &inode_u); if (default_acl) { - ret = bch2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT); + ret = bch2_set_acl(&inode->v, default_acl, ACL_TYPE_DEFAULT); if (unlikely(ret)) goto err; } if (acl) { - ret = bch2_set_acl(inode, acl, ACL_TYPE_ACCESS); + ret = bch2_set_acl(&inode->v, acl, ACL_TYPE_ACCESS); if (unlikely(ret)) goto err; } - insert_inode_hash(inode); + insert_inode_hash(&inode->v); atomic_long_inc(&c->nr_inodes); out: posix_acl_release(default_acl); posix_acl_release(acl); return inode; err: - clear_nlink(inode); - iput(inode); + clear_nlink(&inode->v); + iput(&inode->v); inode = ERR_PTR(ret); goto out; } -static int bch2_vfs_dirent_create(struct bch_fs *c, struct inode *dir, +static int bch2_vfs_dirent_create(struct bch_fs *c, + struct bch_inode_info *dir, u8 type, const struct qstr *name, - struct inode *dst) + u64 dst) { - struct bch_inode_info *dir_ei = to_bch_ei(dir); int ret; - ret = bch2_dirent_create(c, dir->i_ino, &dir_ei->str_hash, - type, name, dst->i_ino, - &dir_ei->journal_seq, + ret = bch2_dirent_create(c, dir->v.i_ino, &dir->ei_str_hash, + type, name, dst, + &dir->ei_journal_seq, BCH_HASH_SET_MUST_CREATE); if (unlikely(ret)) return ret; - dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb); - mark_inode_dirty_sync(dir); + dir->v.i_mtime = dir->v.i_ctime = current_fs_time(c->vfs_sb); + mark_inode_dirty_sync(&dir->v); return 0; } -static int __bch2_create(struct inode *dir, struct dentry *dentry, +static int __bch2_create(struct bch_inode_info *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { - struct bch_inode_info *dir_ei = to_bch_ei(dir); - struct bch_fs *c = dir->i_sb->s_fs_info; - struct inode *inode; - struct bch_inode_info *ei; + struct bch_fs *c = dir->v.i_sb->s_fs_info; + struct bch_inode_info *inode; int ret; inode = bch2_vfs_inode_create(c, dir, mode, rdev); if (unlikely(IS_ERR(inode))) return PTR_ERR(inode); - ei = to_bch_ei(inode); - ret = bch2_vfs_dirent_create(c, dir, mode_to_type(mode), - &dentry->d_name, inode); + &dentry->d_name, inode->v.i_ino); if (unlikely(ret)) { - clear_nlink(inode); - iput(inode); + clear_nlink(&inode->v); + iput(&inode->v); return ret; } - if (dir_ei->journal_seq > ei->journal_seq) - ei->journal_seq = dir_ei->journal_seq; + if (dir->ei_journal_seq > inode->ei_journal_seq) + inode->ei_journal_seq = dir->ei_journal_seq; - d_instantiate(dentry, inode); + d_instantiate(dentry, &inode->v); return 0; } /* methods */ -static struct dentry *bch2_lookup(struct inode *dir, struct dentry *dentry, +static struct dentry *bch2_lookup(struct inode *vdir, struct dentry *dentry, unsigned int flags) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct bch_inode_info *dir_ei = to_bch_ei(dir); - struct inode *inode = NULL; + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir); + struct inode *vinode = NULL; u64 inum; - inum = bch2_dirent_lookup(c, dir->i_ino, - &dir_ei->str_hash, - &dentry->d_name); + inum = bch2_dirent_lookup(c, dir->v.i_ino, + &dir->ei_str_hash, + &dentry->d_name); if (inum) - inode = bch2_vfs_inode_get(dir->i_sb, inum); + vinode = bch2_vfs_inode_get(c, inum); - return d_splice_alias(inode, dentry); + return d_splice_alias(vinode, dentry); } -static int bch2_create(struct inode *dir, struct dentry *dentry, +static int bch2_create(struct inode *vdir, struct dentry *dentry, umode_t mode, bool excl) { - return __bch2_create(dir, dentry, mode|S_IFREG, 0); + return __bch2_create(to_bch_ei(vdir), dentry, mode|S_IFREG, 0); } -static int bch2_link(struct dentry *old_dentry, struct inode *dir, +static int bch2_link(struct dentry *old_dentry, struct inode *vdir, struct dentry *dentry) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct inode *inode = old_dentry->d_inode; - struct bch_inode_info *ei = to_bch_ei(inode); + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir); + struct bch_inode_info *inode = to_bch_ei(old_dentry->d_inode); int ret; - lockdep_assert_held(&inode->i_rwsem); + lockdep_assert_held(&inode->v.i_rwsem); - inode->i_ctime = current_fs_time(dir->i_sb); + inode->v.i_ctime = current_fs_time(dir->v.i_sb); - ret = bch2_inc_nlink(c, ei); + ret = bch2_inc_nlink(c, inode); if (ret) return ret; - ihold(inode); + ihold(&inode->v); - ret = bch2_vfs_dirent_create(c, dir, mode_to_type(inode->i_mode), - &dentry->d_name, inode); + ret = bch2_vfs_dirent_create(c, dir, mode_to_type(inode->v.i_mode), + &dentry->d_name, inode->v.i_ino); if (unlikely(ret)) { - bch2_dec_nlink(c, ei); - iput(inode); + bch2_dec_nlink(c, inode); + iput(&inode->v); return ret; } - d_instantiate(dentry, inode); + d_instantiate(dentry, &inode->v); return 0; } -static int bch2_unlink(struct inode *dir, struct dentry *dentry) +static int bch2_unlink(struct inode *vdir, struct dentry *dentry) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct bch_inode_info *dir_ei = to_bch_ei(dir); - struct inode *inode = dentry->d_inode; - struct bch_inode_info *ei = to_bch_ei(inode); + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir); + struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); int ret; - lockdep_assert_held(&inode->i_rwsem); + lockdep_assert_held(&inode->v.i_rwsem); - ret = bch2_dirent_delete(c, dir->i_ino, &dir_ei->str_hash, - &dentry->d_name, &dir_ei->journal_seq); + ret = bch2_dirent_delete(c, dir->v.i_ino, &dir->ei_str_hash, + &dentry->d_name, &dir->ei_journal_seq); if (ret) return ret; - if (dir_ei->journal_seq > ei->journal_seq) - ei->journal_seq = dir_ei->journal_seq; + if (dir->ei_journal_seq > inode->ei_journal_seq) + inode->ei_journal_seq = dir->ei_journal_seq; - inode->i_ctime = dir->i_ctime; + inode->v.i_ctime = dir->v.i_ctime; - if (S_ISDIR(inode->i_mode)) { - bch2_dec_nlink(c, dir_ei); - drop_nlink(inode); + if (S_ISDIR(inode->v.i_mode)) { + bch2_dec_nlink(c, dir); + drop_nlink(&inode->v); } - bch2_dec_nlink(c, ei); + bch2_dec_nlink(c, inode); return 0; } -static int bch2_symlink(struct inode *dir, struct dentry *dentry, +static int bch2_symlink(struct inode *vdir, struct dentry *dentry, const char *symname) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct inode *inode; - struct bch_inode_info *ei, *dir_ei = to_bch_ei(dir); + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir), *inode; int ret; inode = bch2_vfs_inode_create(c, dir, S_IFLNK|S_IRWXUGO, 0); if (unlikely(IS_ERR(inode))) return PTR_ERR(inode); - ei = to_bch_ei(inode); - - inode_lock(inode); - ret = page_symlink(inode, symname, strlen(symname) + 1); - inode_unlock(inode); + inode_lock(&inode->v); + ret = page_symlink(&inode->v, symname, strlen(symname) + 1); + inode_unlock(&inode->v); if (unlikely(ret)) goto err; - ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); + ret = filemap_write_and_wait_range(inode->v.i_mapping, 0, LLONG_MAX); if (unlikely(ret)) goto err; /* XXX: racy */ - if (dir_ei->journal_seq < ei->journal_seq) - dir_ei->journal_seq = ei->journal_seq; + if (dir->ei_journal_seq < inode->ei_journal_seq) + dir->ei_journal_seq = inode->ei_journal_seq; - ret = bch2_vfs_dirent_create(c, dir, DT_LNK, &dentry->d_name, inode); + ret = bch2_vfs_dirent_create(c, dir, DT_LNK, &dentry->d_name, + inode->v.i_ino); if (unlikely(ret)) goto err; - d_instantiate(dentry, inode); + d_instantiate(dentry, &inode->v); return 0; err: - clear_nlink(inode); - iput(inode); + clear_nlink(&inode->v); + iput(&inode->v); return ret; } -static int bch2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +static int bch2_mkdir(struct inode *vdir, struct dentry *dentry, umode_t mode) { - struct bch_fs *c = dir->i_sb->s_fs_info; + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir); int ret; - lockdep_assert_held(&dir->i_rwsem); + lockdep_assert_held(&dir->v.i_rwsem); ret = __bch2_create(dir, dentry, mode|S_IFDIR, 0); if (unlikely(ret)) return ret; - bch2_inc_nlink(c, to_bch_ei(dir)); + bch2_inc_nlink(c, dir); return 0; } -static int bch2_rmdir(struct inode *dir, struct dentry *dentry) +static int bch2_rmdir(struct inode *vdir, struct dentry *dentry) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct inode *inode = dentry->d_inode; + struct bch_fs *c = vdir->i_sb->s_fs_info; - if (bch2_empty_dir(c, inode->i_ino)) + if (bch2_empty_dir(c, dentry->d_inode->i_ino)) return -ENOTEMPTY; - return bch2_unlink(dir, dentry); + return bch2_unlink(vdir, dentry); } -static int bch2_mknod(struct inode *dir, struct dentry *dentry, +static int bch2_mknod(struct inode *vdir, struct dentry *dentry, umode_t mode, dev_t rdev) { - return __bch2_create(dir, dentry, mode, rdev); + return __bch2_create(to_bch_ei(vdir), dentry, mode, rdev); } -static int bch2_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +static int bch2_rename(struct bch_fs *c, + struct bch_inode_info *old_dir, + struct dentry *old_dentry, + struct bch_inode_info *new_dir, + struct dentry *new_dentry) { - struct bch_fs *c = old_dir->i_sb->s_fs_info; - struct inode *old_inode = old_dentry->d_inode; - struct bch_inode_info *ei = to_bch_ei(old_inode); - struct inode *new_inode = new_dentry->d_inode; - struct timespec now = current_fs_time(old_dir->i_sb); + struct bch_inode_info *old_inode = to_bch_ei(old_dentry->d_inode); + struct bch_inode_info *new_inode = to_bch_ei(new_dentry->d_inode); + struct timespec now = current_fs_time(old_dir->v.i_sb); int ret; - lockdep_assert_held(&old_dir->i_rwsem); - lockdep_assert_held(&new_dir->i_rwsem); + lockdep_assert_held(&old_dir->v.i_rwsem); + lockdep_assert_held(&new_dir->v.i_rwsem); if (new_inode) - filemap_write_and_wait_range(old_inode->i_mapping, + filemap_write_and_wait_range(old_inode->v.i_mapping, 0, LLONG_MAX); - if (new_inode && S_ISDIR(old_inode->i_mode)) { - lockdep_assert_held(&new_inode->i_rwsem); + if (new_inode && S_ISDIR(old_inode->v.i_mode)) { + lockdep_assert_held(&new_inode->v.i_rwsem); - if (!S_ISDIR(new_inode->i_mode)) + if (!S_ISDIR(new_inode->v.i_mode)) return -ENOTDIR; - if (bch2_empty_dir(c, new_inode->i_ino)) + if (bch2_empty_dir(c, new_inode->v.i_ino)) return -ENOTEMPTY; ret = bch2_dirent_rename(c, - old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name, - &ei->journal_seq, BCH_RENAME_OVERWRITE); + old_dir, &old_dentry->d_name, + new_dir, &new_dentry->d_name, + &old_inode->ei_journal_seq, BCH_RENAME_OVERWRITE); if (unlikely(ret)) return ret; - clear_nlink(new_inode); - bch2_dec_nlink(c, to_bch_ei(old_dir)); + clear_nlink(&new_inode->v); + bch2_dec_nlink(c, old_dir); } else if (new_inode) { - lockdep_assert_held(&new_inode->i_rwsem); + lockdep_assert_held(&new_inode->v.i_rwsem); ret = bch2_dirent_rename(c, - old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name, - &ei->journal_seq, BCH_RENAME_OVERWRITE); + old_dir, &old_dentry->d_name, + new_dir, &new_dentry->d_name, + &old_inode->ei_journal_seq, BCH_RENAME_OVERWRITE); if (unlikely(ret)) return ret; - new_inode->i_ctime = now; - bch2_dec_nlink(c, to_bch_ei(new_inode)); - } else if (S_ISDIR(old_inode->i_mode)) { + new_inode->v.i_ctime = now; + bch2_dec_nlink(c, new_inode); + } else if (S_ISDIR(old_inode->v.i_mode)) { ret = bch2_dirent_rename(c, - old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name, - &ei->journal_seq, BCH_RENAME); + old_dir, &old_dentry->d_name, + new_dir, &new_dentry->d_name, + &old_inode->ei_journal_seq, BCH_RENAME); if (unlikely(ret)) return ret; - bch2_inc_nlink(c, to_bch_ei(new_dir)); - bch2_dec_nlink(c, to_bch_ei(old_dir)); + bch2_inc_nlink(c, new_dir); + bch2_dec_nlink(c, old_dir); } else { ret = bch2_dirent_rename(c, - old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name, - &ei->journal_seq, BCH_RENAME); + old_dir, &old_dentry->d_name, + new_dir, &new_dentry->d_name, + &old_inode->ei_journal_seq, BCH_RENAME); if (unlikely(ret)) return ret; } - old_dir->i_ctime = old_dir->i_mtime = now; - new_dir->i_ctime = new_dir->i_mtime = now; - mark_inode_dirty_sync(old_dir); - mark_inode_dirty_sync(new_dir); + old_dir->v.i_ctime = old_dir->v.i_mtime = now; + new_dir->v.i_ctime = new_dir->v.i_mtime = now; + mark_inode_dirty_sync(&old_dir->v); + mark_inode_dirty_sync(&new_dir->v); - old_inode->i_ctime = now; - mark_inode_dirty_sync(old_inode); + old_inode->v.i_ctime = now; + mark_inode_dirty_sync(&old_inode->v); return 0; } -static int bch2_rename_exchange(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +static int bch2_rename_exchange(struct bch_fs *c, + struct bch_inode_info *old_dir, + struct dentry *old_dentry, + struct bch_inode_info *new_dir, + struct dentry *new_dentry) { - struct bch_fs *c = old_dir->i_sb->s_fs_info; - struct inode *old_inode = old_dentry->d_inode; - struct inode *new_inode = new_dentry->d_inode; - struct bch_inode_info *ei = to_bch_ei(old_inode); - struct timespec now = current_fs_time(old_dir->i_sb); + struct bch_inode_info *old_inode = to_bch_ei(old_dentry->d_inode); + struct bch_inode_info *new_inode = to_bch_ei(new_dentry->d_inode); + struct timespec now = current_fs_time(old_dir->v.i_sb); int ret; ret = bch2_dirent_rename(c, - old_dir, &old_dentry->d_name, - new_dir, &new_dentry->d_name, - &ei->journal_seq, BCH_RENAME_EXCHANGE); + old_dir, &old_dentry->d_name, + new_dir, &new_dentry->d_name, + &old_inode->ei_journal_seq, BCH_RENAME_EXCHANGE); if (unlikely(ret)) return ret; - if (S_ISDIR(old_inode->i_mode) != - S_ISDIR(new_inode->i_mode)) { - if (S_ISDIR(old_inode->i_mode)) { - bch2_inc_nlink(c, to_bch_ei(new_dir)); - bch2_dec_nlink(c, to_bch_ei(old_dir)); + if (S_ISDIR(old_inode->v.i_mode) != + S_ISDIR(new_inode->v.i_mode)) { + if (S_ISDIR(old_inode->v.i_mode)) { + bch2_inc_nlink(c, new_dir); + bch2_dec_nlink(c, old_dir); } else { - bch2_dec_nlink(c, to_bch_ei(new_dir)); - bch2_inc_nlink(c, to_bch_ei(old_dir)); + bch2_dec_nlink(c, new_dir); + bch2_inc_nlink(c, old_dir); } } - old_dir->i_ctime = old_dir->i_mtime = now; - new_dir->i_ctime = new_dir->i_mtime = now; - mark_inode_dirty_sync(old_dir); - mark_inode_dirty_sync(new_dir); + old_dir->v.i_ctime = old_dir->v.i_mtime = now; + new_dir->v.i_ctime = new_dir->v.i_mtime = now; + mark_inode_dirty_sync(&old_dir->v); + mark_inode_dirty_sync(&new_dir->v); - old_inode->i_ctime = now; - new_inode->i_ctime = now; - mark_inode_dirty_sync(old_inode); - mark_inode_dirty_sync(new_inode); + old_inode->v.i_ctime = now; + new_inode->v.i_ctime = now; + mark_inode_dirty_sync(&old_inode->v); + mark_inode_dirty_sync(&new_inode->v); return 0; } -static int bch2_rename2(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, +static int bch2_rename2(struct inode *old_vdir, struct dentry *old_dentry, + struct inode *new_vdir, struct dentry *new_dentry, unsigned flags) { + struct bch_fs *c = old_vdir->i_sb->s_fs_info; + struct bch_inode_info *old_dir = to_bch_ei(old_vdir); + struct bch_inode_info *new_dir = to_bch_ei(new_vdir); + if (flags & ~(RENAME_NOREPLACE|RENAME_EXCHANGE)) return -EINVAL; if (flags & RENAME_EXCHANGE) - return bch2_rename_exchange(old_dir, old_dentry, - new_dir, new_dentry); + return bch2_rename_exchange(c, old_dir, old_dentry, + new_dir, new_dentry); - return bch2_rename(old_dir, old_dentry, new_dir, new_dentry); + return bch2_rename(c, old_dir, old_dentry, new_dir, new_dentry); } static int bch2_setattr(struct dentry *dentry, struct iattr *iattr) { - struct inode *inode = dentry->d_inode; - struct bch_inode_info *ei = to_bch_ei(inode); - struct bch_fs *c = inode->i_sb->s_fs_info; + struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); + struct bch_fs *c = inode->v.i_sb->s_fs_info; int ret = 0; - lockdep_assert_held(&inode->i_rwsem); - - pr_debug("i_size was %llu update has %llu", - inode->i_size, iattr->ia_size); + lockdep_assert_held(&inode->v.i_rwsem); ret = setattr_prepare(dentry, iattr); if (ret) @@ -628,32 +618,33 @@ static int bch2_setattr(struct dentry *dentry, struct iattr *iattr) if (iattr->ia_valid & ATTR_SIZE) { ret = bch2_truncate(inode, iattr); } else { - mutex_lock(&ei->update_lock); - setattr_copy(inode, iattr); - ret = bch2_write_inode(c, ei); - mutex_unlock(&ei->update_lock); + mutex_lock(&inode->ei_update_lock); + setattr_copy(&inode->v, iattr); + ret = bch2_write_inode(c, inode); + mutex_unlock(&inode->ei_update_lock); } if (unlikely(ret)) return ret; if (iattr->ia_valid & ATTR_MODE) - ret = posix_acl_chmod(inode, inode->i_mode); + ret = posix_acl_chmod(&inode->v, inode->v.i_mode); return ret; } -static int bch2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +static int bch2_tmpfile(struct inode *vdir, struct dentry *dentry, umode_t mode) { - struct bch_fs *c = dir->i_sb->s_fs_info; - struct inode *inode; + struct bch_fs *c = vdir->i_sb->s_fs_info; + struct bch_inode_info *dir = to_bch_ei(vdir); + struct bch_inode_info *inode; /* XXX: i_nlink should be 0? */ inode = bch2_vfs_inode_create(c, dir, mode, 0); if (unlikely(IS_ERR(inode))) return PTR_ERR(inode); - d_tmpfile(dentry, inode); + d_tmpfile(dentry, &inode->v); return 0; } @@ -700,10 +691,11 @@ static int bch2_fill_extent(struct fiemap_extent_info *info, } } -static int bch2_fiemap(struct inode *inode, struct fiemap_extent_info *info, +static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, u64 start, u64 len) { - struct bch_fs *c = inode->i_sb->s_fs_info; + struct bch_fs *c = vinode->i_sb->s_fs_info; + struct bch_inode_info *ei = to_bch_ei(vinode); struct btree_iter iter; struct bkey_s_c k; BKEY_PADDED(k) tmp; @@ -714,11 +706,11 @@ static int bch2_fiemap(struct inode *inode, struct fiemap_extent_info *info, return -EINVAL; for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, - POS(inode->i_ino, start >> 9), 0, k) + POS(ei->v.i_ino, start >> 9), 0, k) if (bkey_extent_is_data(k.k) || k.k->type == BCH_RESERVATION) { if (bkey_cmp(bkey_start_pos(k.k), - POS(inode->i_ino, (start + len) >> 9)) >= 0) + POS(ei->v.i_ino, (start + len) >> 9)) >= 0) break; if (have_extent) { @@ -752,175 +744,6 @@ static int bch2_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -/* Inode flags: */ - -static const unsigned bch_inode_flags_to_vfs_flags_map[] = { - [__BCH_INODE_SYNC] = S_SYNC, - [__BCH_INODE_IMMUTABLE] = S_IMMUTABLE, - [__BCH_INODE_APPEND] = S_APPEND, - [__BCH_INODE_NOATIME] = S_NOATIME, -}; - -static const unsigned bch_inode_flags_to_user_flags_map[] = { - [__BCH_INODE_SYNC] = FS_SYNC_FL, - [__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL, - [__BCH_INODE_APPEND] = FS_APPEND_FL, - [__BCH_INODE_NODUMP] = FS_NODUMP_FL, - [__BCH_INODE_NOATIME] = FS_NOATIME_FL, -}; - -/* Set VFS inode flags from bcachefs inode: */ -static void bch2_inode_flags_to_vfs(struct inode *inode) -{ - unsigned i, flags = to_bch_ei(inode)->i_flags; - - for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_vfs_flags_map); i++) - if (flags & (1 << i)) - inode->i_flags |= bch_inode_flags_to_vfs_flags_map[i]; - else - inode->i_flags &= ~bch_inode_flags_to_vfs_flags_map[i]; -} - -/* Get FS_IOC_GETFLAGS flags from bcachefs inode: */ -static unsigned bch2_inode_flags_to_user_flags(unsigned flags) -{ - unsigned i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_user_flags_map); i++) - if (flags & (1 << i)) - ret |= bch_inode_flags_to_user_flags_map[i]; - - return ret; -} - -static int bch2_inode_user_flags_set(struct bch_inode_info *ei, - struct bch_inode_unpacked *bi, - void *p) -{ - /* - * We're relying on btree locking here for exclusion with other ioctl - * calls - use the flags in the btree (@bi), not ei->i_flags: - */ - unsigned bch_flags = bi->i_flags; - unsigned oldflags = bch2_inode_flags_to_user_flags(bch_flags); - unsigned newflags = *((unsigned *) p); - unsigned i; - - if (((newflags ^ oldflags) & (FS_APPEND_FL|FS_IMMUTABLE_FL)) && - !capable(CAP_LINUX_IMMUTABLE)) - return -EPERM; - - for (i = 0; i < ARRAY_SIZE(bch_inode_flags_to_user_flags_map); i++) { - if (newflags & bch_inode_flags_to_user_flags_map[i]) - bch_flags |= (1 << i); - else - bch_flags &= ~(1 << i); - - newflags &= ~bch_inode_flags_to_user_flags_map[i]; - oldflags &= ~bch_inode_flags_to_user_flags_map[i]; - } - - if (oldflags != newflags) - return -EOPNOTSUPP; - - bi->i_flags = bch_flags; - ei->vfs_inode.i_ctime = current_fs_time(ei->vfs_inode.i_sb); - - return 0; -} - -#define FS_IOC_GOINGDOWN _IOR ('X', 125, __u32) - -static long bch2_fs_file_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = file_inode(filp); - struct super_block *sb = inode->i_sb; - struct bch_fs *c = sb->s_fs_info; - struct bch_inode_info *ei = to_bch_ei(inode); - unsigned flags; - int ret; - - switch (cmd) { - case FS_IOC_GETFLAGS: - return put_user(bch2_inode_flags_to_user_flags(ei->i_flags), - (int __user *) arg); - - case FS_IOC_SETFLAGS: { - ret = mnt_want_write_file(filp); - if (ret) - return ret; - - if (!inode_owner_or_capable(inode)) { - ret = -EACCES; - goto setflags_out; - } - - if (get_user(flags, (int __user *) arg)) { - ret = -EFAULT; - goto setflags_out; - } - - if (!S_ISREG(inode->i_mode) && - !S_ISDIR(inode->i_mode) && - (flags & (FS_NODUMP_FL|FS_NOATIME_FL)) != flags) { - ret = -EINVAL; - goto setflags_out; - } - - inode_lock(inode); - - mutex_lock(&ei->update_lock); - ret = __bch2_write_inode(c, ei, bch2_inode_user_flags_set, &flags); - mutex_unlock(&ei->update_lock); - - if (!ret) - bch2_inode_flags_to_vfs(inode); - - inode_unlock(inode); -setflags_out: - mnt_drop_write_file(filp); - return ret; - } - - case FS_IOC_GETVERSION: - return -ENOTTY; - case FS_IOC_SETVERSION: - return -ENOTTY; - - case FS_IOC_GOINGDOWN: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - down_write(&sb->s_umount); - sb->s_flags |= MS_RDONLY; - bch2_fs_emergency_read_only(c); - up_write(&sb->s_umount); - return 0; - - default: - return bch2_fs_ioctl(c, cmd, (void __user *) arg); - } -} - -#ifdef CONFIG_COMPAT -static long bch2_compat_fs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - /* These are just misnamed, they actually get/put from/to user an int */ - switch (cmd) { - case FS_IOC_GETFLAGS: - cmd = FS_IOC_GETFLAGS; - break; - case FS_IOC32_SETFLAGS: - cmd = FS_IOC_SETFLAGS; - break; - default: - return -ENOIOCTLCMD; - } - return bch2_fs_file_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); -} -#endif - /* Directories: */ static loff_t bch2_dir_llseek(struct file *file, loff_t offset, int whence) @@ -931,8 +754,7 @@ static loff_t bch2_dir_llseek(struct file *file, loff_t offset, int whence) static int bch2_vfs_readdir(struct file *file, struct dir_context *ctx) { - struct inode *inode = file_inode(file); - struct bch_fs *c = inode->i_sb->s_fs_info; + struct bch_fs *c = file_inode(file)->i_sb->s_fs_info; return bch2_readdir(c, file, ctx); } @@ -957,8 +779,10 @@ static const struct inode_operations bch_file_inode_operations = { .setattr = bch2_setattr, .fiemap = bch2_fiemap, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct inode_operations bch_dir_inode_operations = { @@ -974,8 +798,10 @@ static const struct inode_operations bch_dir_inode_operations = { .setattr = bch2_setattr, .tmpfile = bch2_tmpfile, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct file_operations bch_dir_file_operations = { @@ -993,15 +819,19 @@ static const struct inode_operations bch_symlink_inode_operations = { .get_link = page_get_link, .setattr = bch2_setattr, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct inode_operations bch_special_inode_operations = { .setattr = bch2_setattr, .listxattr = bch2_xattr_list, +#ifdef CONFIG_BCACHEFS_POSIX_ACL .get_acl = bch2_get_acl, .set_acl = bch2_set_acl, +#endif }; static const struct address_space_operations bch_address_space_operations = { @@ -1024,20 +854,21 @@ static const struct address_space_operations bch_address_space_operations = { static struct inode *bch2_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation) { - struct inode *inode; + struct bch_fs *c = sb->s_fs_info; + struct inode *vinode; if (ino < BCACHEFS_ROOT_INO) return ERR_PTR(-ESTALE); - inode = bch2_vfs_inode_get(sb, ino); - if (IS_ERR(inode)) - return ERR_CAST(inode); - if (generation && inode->i_generation != generation) { + vinode = bch2_vfs_inode_get(c, ino); + if (IS_ERR(vinode)) + return ERR_CAST(vinode); + if (generation && vinode->i_generation != generation) { /* we didn't find the right inode.. */ - iput(inode); + iput(vinode); return ERR_PTR(-ESTALE); } - return inode; + return vinode; } static struct dentry *bch2_fh_to_dentry(struct super_block *sb, struct fid *fid, @@ -1061,127 +892,119 @@ static const struct export_operations bch_export_ops = { }; static void bch2_vfs_inode_init(struct bch_fs *c, - struct bch_inode_info *ei, + struct bch_inode_info *inode, struct bch_inode_unpacked *bi) { - struct inode *inode = &ei->vfs_inode; - - pr_debug("init inode %llu with mode %o", - bi->inum, bi->i_mode); - - ei->i_flags = bi->i_flags; - ei->i_size = bi->i_size; - - inode->i_mode = bi->i_mode; - i_uid_write(inode, bi->i_uid); - i_gid_write(inode, bi->i_gid); + inode->v.i_mode = bi->bi_mode; + i_uid_write(&inode->v, bi->bi_uid); + i_gid_write(&inode->v, bi->bi_gid); + inode->v.i_blocks = bi->bi_sectors; + inode->v.i_ino = bi->bi_inum; + set_nlink(&inode->v, bi->bi_nlink + nlink_bias(inode->v.i_mode)); + inode->v.i_rdev = bi->bi_dev; + inode->v.i_generation = bi->bi_generation; + inode->v.i_size = bi->bi_size; + inode->v.i_atime = bch2_time_to_timespec(c, bi->bi_atime); + inode->v.i_mtime = bch2_time_to_timespec(c, bi->bi_mtime); + inode->v.i_ctime = bch2_time_to_timespec(c, bi->bi_ctime); + + inode->ei_journal_seq = 0; + inode->ei_size = bi->bi_size; + inode->ei_flags = bi->bi_flags; + atomic64_set(&inode->ei_sectors, bi->bi_sectors); + inode->ei_str_hash = bch2_hash_info_init(c, bi); - atomic64_set(&ei->i_sectors, bi->i_sectors); - inode->i_blocks = bi->i_sectors; - - inode->i_ino = bi->inum; - set_nlink(inode, bi->i_nlink + nlink_bias(inode->i_mode)); - inode->i_rdev = bi->i_dev; - inode->i_generation = bi->i_generation; - inode->i_size = bi->i_size; - inode->i_atime = bch2_time_to_timespec(c, bi->i_atime); - inode->i_mtime = bch2_time_to_timespec(c, bi->i_mtime); - inode->i_ctime = bch2_time_to_timespec(c, bi->i_ctime); bch2_inode_flags_to_vfs(inode); - ei->str_hash = bch2_hash_info_init(c, bi); - - inode->i_mapping->a_ops = &bch_address_space_operations; + inode->v.i_mapping->a_ops = &bch_address_space_operations; - switch (inode->i_mode & S_IFMT) { + switch (inode->v.i_mode & S_IFMT) { case S_IFREG: - inode->i_op = &bch_file_inode_operations; - inode->i_fop = &bch_file_operations; + inode->v.i_op = &bch_file_inode_operations; + inode->v.i_fop = &bch_file_operations; break; case S_IFDIR: - inode->i_op = &bch_dir_inode_operations; - inode->i_fop = &bch_dir_file_operations; + inode->v.i_op = &bch_dir_inode_operations; + inode->v.i_fop = &bch_dir_file_operations; break; case S_IFLNK: - inode_nohighmem(inode); - inode->i_op = &bch_symlink_inode_operations; + inode_nohighmem(&inode->v); + inode->v.i_op = &bch_symlink_inode_operations; break; default: - init_special_inode(inode, inode->i_mode, inode->i_rdev); - inode->i_op = &bch_special_inode_operations; + init_special_inode(&inode->v, inode->v.i_mode, inode->v.i_rdev); + inode->v.i_op = &bch_special_inode_operations; break; } } static struct inode *bch2_alloc_inode(struct super_block *sb) { - struct bch_inode_info *ei; + struct bch_inode_info *inode; - ei = kmem_cache_alloc(bch2_inode_cache, GFP_NOFS); - if (!ei) + inode = kmem_cache_alloc(bch2_inode_cache, GFP_NOFS); + if (!inode) return NULL; - pr_debug("allocated %p", &ei->vfs_inode); + inode_init_once(&inode->v); + mutex_init(&inode->ei_update_lock); + inode->ei_journal_seq = 0; + atomic_long_set(&inode->ei_size_dirty_count, 0); + atomic_long_set(&inode->ei_sectors_dirty_count, 0); - inode_init_once(&ei->vfs_inode); - mutex_init(&ei->update_lock); - ei->journal_seq = 0; - atomic_long_set(&ei->i_size_dirty_count, 0); - atomic_long_set(&ei->i_sectors_dirty_count, 0); - - return &ei->vfs_inode; + return &inode->v; } static void bch2_i_callback(struct rcu_head *head) { - struct inode *inode = container_of(head, struct inode, i_rcu); + struct inode *vinode = container_of(head, struct inode, i_rcu); + struct bch_inode_info *inode = to_bch_ei(vinode); - kmem_cache_free(bch2_inode_cache, to_bch_ei(inode)); + kmem_cache_free(bch2_inode_cache, inode); } -static void bch2_destroy_inode(struct inode *inode) +static void bch2_destroy_inode(struct inode *vinode) { - call_rcu(&inode->i_rcu, bch2_i_callback); + call_rcu(&vinode->i_rcu, bch2_i_callback); } -static int bch2_vfs_write_inode(struct inode *inode, +static int bch2_vfs_write_inode(struct inode *vinode, struct writeback_control *wbc) { - struct bch_fs *c = inode->i_sb->s_fs_info; - struct bch_inode_info *ei = to_bch_ei(inode); + struct bch_fs *c = vinode->i_sb->s_fs_info; + struct bch_inode_info *inode = to_bch_ei(vinode); int ret; - mutex_lock(&ei->update_lock); - ret = bch2_write_inode(c, ei); - mutex_unlock(&ei->update_lock); + mutex_lock(&inode->ei_update_lock); + ret = bch2_write_inode(c, inode); + mutex_unlock(&inode->ei_update_lock); if (c->opts.journal_flush_disabled) return ret; if (!ret && wbc->sync_mode == WB_SYNC_ALL) - ret = bch2_journal_flush_seq(&c->journal, ei->journal_seq); + ret = bch2_journal_flush_seq(&c->journal, inode->ei_journal_seq); return ret; } -static void bch2_evict_inode(struct inode *inode) +static void bch2_evict_inode(struct inode *vinode) { - struct bch_fs *c = inode->i_sb->s_fs_info; - - truncate_inode_pages_final(&inode->i_data); + struct bch_fs *c = vinode->i_sb->s_fs_info; + struct bch_inode_info *inode = to_bch_ei(vinode); - if (!bch2_journal_error(&c->journal) && !is_bad_inode(inode)) { - struct bch_inode_info *ei = to_bch_ei(inode); + truncate_inode_pages_final(&inode->v.i_data); + if (!bch2_journal_error(&c->journal) && !is_bad_inode(&inode->v)) { /* XXX - we want to check this stuff iff there weren't IO errors: */ - BUG_ON(atomic_long_read(&ei->i_sectors_dirty_count)); - BUG_ON(atomic64_read(&ei->i_sectors) != inode->i_blocks); + BUG_ON(atomic_long_read(&inode->ei_sectors_dirty_count)); + BUG_ON(atomic64_read(&inode->ei_sectors) != inode->v.i_blocks); } - clear_inode(inode); + clear_inode(&inode->v); - if (!inode->i_nlink && !is_bad_inode(inode)) { - bch2_inode_rm(c, inode->i_ino); + if (!inode->v.i_nlink && !is_bad_inode(&inode->v)) { + bch2_inode_rm(c, inode->v.i_ino); atomic_long_dec(&c->nr_inodes); } } @@ -1305,16 +1128,17 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) struct bch_opts opts = bch2_opts_empty(); int ret; - opts.read_only = (*flags & MS_RDONLY) != 0; + opt_set(opts, read_only, (*flags & MS_RDONLY) != 0); ret = bch2_parse_mount_opts(&opts, data); if (ret) return ret; - if (opts.read_only >= 0 && - opts.read_only != c->opts.read_only) { + if (opts.read_only != c->opts.read_only) { const char *err = NULL; + mutex_lock(&c->state_lock); + if (opts.read_only) { bch2_fs_read_only(c); @@ -1330,6 +1154,8 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) } c->opts.read_only = opts.read_only; + + mutex_unlock(&c->state_lock); } if (opts.errors >= 0) @@ -1338,6 +1164,38 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) return ret; } +static int bch2_show_options(struct seq_file *seq, struct dentry *root) +{ + struct bch_fs *c = root->d_sb->s_fs_info; + enum bch_opt_id i; + + for (i = 0; i < bch2_opts_nr; i++) { + const struct bch_option *opt = &bch2_opt_table[i]; + u64 v = bch2_opt_get_by_id(&c->opts, i); + + if (opt->mode < OPT_MOUNT) + continue; + + if (v == bch2_opt_get_by_id(&bch2_opts_default, i)) + continue; + + switch (opt->type) { + case BCH_OPT_BOOL: + seq_printf(seq, ",%s%s", v ? "" : "no", opt->attr.name); + break; + case BCH_OPT_UINT: + seq_printf(seq, ",%s=%llu", opt->attr.name, v); + break; + case BCH_OPT_STR: + seq_printf(seq, ",%s=%s", opt->attr.name, opt->choices[v]); + break; + } + } + + return 0; + +} + static const struct super_operations bch_super_operations = { .alloc_inode = bch2_alloc_inode, .destroy_inode = bch2_destroy_inode, @@ -1345,7 +1203,7 @@ static const struct super_operations bch_super_operations = { .evict_inode = bch2_evict_inode, .sync_fs = bch2_sync_fs, .statfs = bch2_statfs, - .show_options = generic_show_options, + .show_options = bch2_show_options, .remount_fs = bch2_remount, #if 0 .put_super = bch2_put_super, @@ -1371,12 +1229,12 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type, struct bch_fs *c; struct bch_dev *ca; struct super_block *sb; - struct inode *inode; + struct inode *vinode; struct bch_opts opts = bch2_opts_empty(); unsigned i; int ret; - opts.read_only = (flags & MS_RDONLY) != 0; + opt_set(opts, read_only, (flags & MS_RDONLY) != 0); ret = bch2_parse_mount_opts(&opts, data); if (ret) @@ -1427,18 +1285,18 @@ static struct dentry *bch2_mount(struct file_system_type *fs_type, break; } - if (opts.posix_acl < 0) +#ifdef CONFIG_BCACHEFS_POSIX_ACL + if (c->opts.acl) sb->s_flags |= MS_POSIXACL; - else - sb->s_flags |= opts.posix_acl ? MS_POSIXACL : 0; +#endif - inode = bch2_vfs_inode_get(sb, BCACHEFS_ROOT_INO); - if (IS_ERR(inode)) { - ret = PTR_ERR(inode); + vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_INO); + if (IS_ERR(vinode)) { + ret = PTR_ERR(vinode); goto err_put_super; } - sb->s_root = d_make_root(inode); + sb->s_root = d_make_root(vinode); if (!sb->s_root) { ret = -ENOMEM; goto err_put_super; |