diff options
Diffstat (limited to 'fs/bcachefs')
-rw-r--r-- | fs/bcachefs/errcode.c | 13 | ||||
-rw-r--r-- | fs/bcachefs/errcode.h | 97 | ||||
-rw-r--r-- | fs/bcachefs/fs-io.c | 49 | ||||
-rw-r--r-- | fs/bcachefs/fs-ioctl.c | 50 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 23 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 15 | ||||
-rw-r--r-- | fs/bcachefs/xattr.c | 16 |
7 files changed, 164 insertions, 99 deletions
diff --git a/fs/bcachefs/errcode.c b/fs/bcachefs/errcode.c index 9da8a5973af0..cc9ce0be356e 100644 --- a/fs/bcachefs/errcode.c +++ b/fs/bcachefs/errcode.c @@ -15,7 +15,7 @@ static const char * const bch2_errcode_strs[] = { #define BCH_ERR_0 0 static unsigned bch2_errcode_parents[] = { -#define x(class, err) [BCH_ERR_##err - BCH_ERR_START] = BCH_ERR_##class, +#define x(class, err) [BCH_ERR_##err - BCH_ERR_START] = class, BCH_ERRCODES() #undef x }; @@ -49,3 +49,14 @@ bool __bch2_err_matches(int err, int class) return err == class; } + +int __bch2_err_class(int err) +{ + err = -err; + BUG_ON((unsigned) err >= BCH_ERR_MAX); + + while (err >= BCH_ERR_START && bch2_errcode_parents[err - BCH_ERR_START]) + err = bch2_errcode_parents[err - BCH_ERR_START]; + + return -err; +} diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h index 15a1be2fcc84..2088cc5a4f3c 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -3,51 +3,51 @@ #define _BCACHEFS_ERRCODE_H #define BCH_ERRCODES() \ - x(0, open_buckets_empty) \ - x(0, freelist_empty) \ - x(freelist_empty, no_buckets_found) \ - x(0, insufficient_devices) \ - x(0, transaction_restart) \ - x(transaction_restart, transaction_restart_fault_inject) \ - x(transaction_restart, transaction_restart_relock) \ - x(transaction_restart, transaction_restart_relock_path) \ - x(transaction_restart, transaction_restart_relock_path_intent) \ - x(transaction_restart, transaction_restart_relock_after_fill) \ - x(transaction_restart, transaction_restart_too_many_iters) \ - x(transaction_restart, transaction_restart_lock_node_reused) \ - x(transaction_restart, transaction_restart_fill_relock) \ - x(transaction_restart, transaction_restart_fill_mem_alloc_fail)\ - x(transaction_restart, transaction_restart_mem_realloced) \ - x(transaction_restart, transaction_restart_in_traverse_all) \ - x(transaction_restart, transaction_restart_would_deadlock) \ - x(transaction_restart, transaction_restart_would_deadlock_write)\ - x(transaction_restart, transaction_restart_upgrade) \ - x(transaction_restart, transaction_restart_key_cache_upgrade) \ - x(transaction_restart, transaction_restart_key_cache_fill) \ - x(transaction_restart, transaction_restart_key_cache_raced) \ - x(transaction_restart, transaction_restart_key_cache_realloced)\ - x(transaction_restart, transaction_restart_journal_preres_get) \ - x(transaction_restart, transaction_restart_nested) \ - x(0, no_btree_node) \ - x(no_btree_node, no_btree_node_relock) \ - x(no_btree_node, no_btree_node_upgrade) \ - x(no_btree_node, no_btree_node_drop) \ - x(no_btree_node, no_btree_node_lock_root) \ - x(no_btree_node, no_btree_node_up) \ - x(no_btree_node, no_btree_node_down) \ - x(no_btree_node, no_btree_node_init) \ - x(no_btree_node, no_btree_node_cached) \ - x(0, lock_fail_node_reused) \ - x(0, lock_fail_root_changed) \ - x(0, journal_reclaim_would_deadlock) \ - x(0, fsck) \ - x(fsck, fsck_fix) \ - x(fsck, fsck_ignore) \ - x(fsck, fsck_errors_not_fixed) \ - x(fsck, fsck_repair_unimplemented) \ - x(fsck, fsck_repair_impossible) \ - x(0, need_snapshot_cleanup) \ - x(0, need_topology_repair) + x(0, open_buckets_empty) \ + x(0, freelist_empty) \ + x(BCH_ERR_freelist_empty, no_buckets_found) \ + x(0, insufficient_devices) \ + x(0, transaction_restart) \ + x(BCH_ERR_transaction_restart, transaction_restart_fault_inject) \ + x(BCH_ERR_transaction_restart, transaction_restart_relock) \ + x(BCH_ERR_transaction_restart, transaction_restart_relock_path) \ + x(BCH_ERR_transaction_restart, transaction_restart_relock_path_intent) \ + x(BCH_ERR_transaction_restart, transaction_restart_relock_after_fill) \ + x(BCH_ERR_transaction_restart, transaction_restart_too_many_iters) \ + x(BCH_ERR_transaction_restart, transaction_restart_lock_node_reused) \ + x(BCH_ERR_transaction_restart, transaction_restart_fill_relock) \ + x(BCH_ERR_transaction_restart, transaction_restart_fill_mem_alloc_fail)\ + x(BCH_ERR_transaction_restart, transaction_restart_mem_realloced) \ + x(BCH_ERR_transaction_restart, transaction_restart_in_traverse_all) \ + x(BCH_ERR_transaction_restart, transaction_restart_would_deadlock) \ + x(BCH_ERR_transaction_restart, transaction_restart_would_deadlock_write)\ + x(BCH_ERR_transaction_restart, transaction_restart_upgrade) \ + x(BCH_ERR_transaction_restart, transaction_restart_key_cache_upgrade) \ + x(BCH_ERR_transaction_restart, transaction_restart_key_cache_fill) \ + x(BCH_ERR_transaction_restart, transaction_restart_key_cache_raced) \ + x(BCH_ERR_transaction_restart, transaction_restart_key_cache_realloced)\ + x(BCH_ERR_transaction_restart, transaction_restart_journal_preres_get) \ + x(BCH_ERR_transaction_restart, transaction_restart_nested) \ + x(0, no_btree_node) \ + x(BCH_ERR_no_btree_node, no_btree_node_relock) \ + x(BCH_ERR_no_btree_node, no_btree_node_upgrade) \ + x(BCH_ERR_no_btree_node, no_btree_node_drop) \ + x(BCH_ERR_no_btree_node, no_btree_node_lock_root) \ + x(BCH_ERR_no_btree_node, no_btree_node_up) \ + x(BCH_ERR_no_btree_node, no_btree_node_down) \ + x(BCH_ERR_no_btree_node, no_btree_node_init) \ + x(BCH_ERR_no_btree_node, no_btree_node_cached) \ + x(0, lock_fail_node_reused) \ + x(0, lock_fail_root_changed) \ + x(0, journal_reclaim_would_deadlock) \ + x(0, fsck) \ + x(BCH_ERR_fsck, fsck_fix) \ + x(BCH_ERR_fsck, fsck_ignore) \ + x(BCH_ERR_fsck, fsck_errors_not_fixed) \ + x(BCH_ERR_fsck, fsck_repair_unimplemented) \ + x(BCH_ERR_fsck, fsck_repair_impossible) \ + x(0, need_snapshot_cleanup) \ + x(0, need_topology_repair) enum bch_errcode { BCH_ERR_START = 2048, @@ -71,4 +71,11 @@ static inline bool _bch2_err_matches(int err, int class) _bch2_err_matches(_err, _class); \ }) +int __bch2_err_class(int); + +static inline long bch2_err_class(long err) +{ + return err < 0 ? __bch2_err_class(err) : err; +} + #endif /* _BCACHFES_ERRCODE_H */ diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 9f1ecb8d7b3b..c83e1de9a39a 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -1186,7 +1186,7 @@ int bch2_read_folio(struct file *file, struct folio *folio) ret = bch2_read_single_page(page, page->mapping); folio_unlock(folio); - return ret; + return bch2_err_class(ret); } /* writepages: */ @@ -1465,7 +1465,7 @@ int bch2_writepages(struct address_space *mapping, struct writeback_control *wbc if (w.io) bch2_writepage_do_io(&w); blk_finish_plug(&plug); - return ret; + return bch2_err_class(ret); } /* buffered writes: */ @@ -1550,7 +1550,7 @@ err_unlock: bch2_pagecache_add_put(&inode->ei_pagecache_lock); kfree(res); *fsdata = NULL; - return ret; + return bch2_err_class(ret); } int bch2_write_end(struct file *file, struct address_space *mapping, @@ -1975,7 +1975,7 @@ ssize_t bch2_read_iter(struct kiocb *iocb, struct iov_iter *iter) iocb->ki_pos, iocb->ki_pos + count - 1); if (ret < 0) - return ret; + goto out; } file_accessed(file); @@ -1991,8 +1991,8 @@ ssize_t bch2_read_iter(struct kiocb *iocb, struct iov_iter *iter) ret = generic_file_read_iter(iocb, iter); bch2_pagecache_add_put(&inode->ei_pagecache_lock); } - - return ret; +out: + return bch2_err_class(ret); } /* O_DIRECT writes */ @@ -2224,6 +2224,9 @@ err: /* inode->i_dio_count is our ref on inode and thus bch_fs */ inode_dio_end(&inode->v); + if (ret < 0) + ret = bch2_err_class(ret); + if (!sync) { req->ki_complete(req, ret); ret = -EIOCBQUEUED; @@ -2332,8 +2335,10 @@ ssize_t bch2_write_iter(struct kiocb *iocb, struct iov_iter *from) struct bch_inode_info *inode = file_bch_inode(file); ssize_t ret; - if (iocb->ki_flags & IOCB_DIRECT) - return bch2_direct_write(iocb, from); + if (iocb->ki_flags & IOCB_DIRECT) { + ret = bch2_direct_write(iocb, from); + goto out; + } inode_lock(&inode->v); @@ -2357,8 +2362,8 @@ unlock: if (ret > 0) ret = generic_write_sync(iocb, ret); - - return ret; +out: + return bch2_err_class(ret); } /* fsync: */ @@ -2392,7 +2397,7 @@ int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync) ret2 = sync_inode_metadata(&inode->v, 1); ret3 = bch2_flush_inode(c, inode_inum(inode)); - return ret ?: ret2 ?: ret3; + return bch2_err_class(ret ?: ret2 ?: ret3); } /* truncate: */ @@ -2698,7 +2703,7 @@ int bch2_truncate(struct mnt_idmap *idmap, ret = bch2_setattr_nonsize(idmap, inode, iattr); err: bch2_pagecache_block_put(&inode->ei_pagecache_lock); - return ret; + return bch2_err_class(ret); } /* fallocate: */ @@ -3128,7 +3133,7 @@ long bch2_fallocate_dispatch(struct file *file, int mode, inode_unlock(&inode->v); percpu_ref_put(&c->writes); - return ret; + return bch2_err_class(ret); } loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, @@ -3206,7 +3211,7 @@ loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, err: bch2_unlock_inodes(INODE_LOCK|INODE_PAGECACHE_BLOCK, src, dst); - return ret; + return bch2_err_class(ret); } /* fseek: */ @@ -3431,18 +3436,26 @@ err: loff_t bch2_llseek(struct file *file, loff_t offset, int whence) { + loff_t ret; + switch (whence) { case SEEK_SET: case SEEK_CUR: case SEEK_END: - return generic_file_llseek(file, offset, whence); + ret = generic_file_llseek(file, offset, whence); + break; case SEEK_DATA: - return bch2_seek_data(file, offset); + ret = bch2_seek_data(file, offset); + break; case SEEK_HOLE: - return bch2_seek_hole(file, offset); + ret = bch2_seek_hole(file, offset); + break; + default: + ret = -EINVAL; + break; } - return -EINVAL; + return bch2_err_class(ret); } void bch2_fs_fsio_exit(struct bch_fs *c) diff --git a/fs/bcachefs/fs-ioctl.c b/fs/bcachefs/fs-ioctl.c index de94895ace9f..3df2f5f3d1ea 100644 --- a/fs/bcachefs/fs-ioctl.c +++ b/fs/bcachefs/fs-ioctl.c @@ -455,51 +455,67 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg) { struct bch_inode_info *inode = file_bch_inode(file); struct bch_fs *c = inode->v.i_sb->s_fs_info; + long ret; switch (cmd) { case FS_IOC_GETFLAGS: - return bch2_ioc_getflags(inode, (int __user *) arg); + ret = bch2_ioc_getflags(inode, (int __user *) arg); + break; case FS_IOC_SETFLAGS: - return bch2_ioc_setflags(c, file, inode, (int __user *) arg); + ret = bch2_ioc_setflags(c, file, inode, (int __user *) arg); + break; case FS_IOC_FSGETXATTR: - return bch2_ioc_fsgetxattr(inode, (void __user *) arg); + ret = bch2_ioc_fsgetxattr(inode, (void __user *) arg); + break; + case FS_IOC_FSSETXATTR: - return bch2_ioc_fssetxattr(c, file, inode, - (void __user *) arg); + ret = bch2_ioc_fssetxattr(c, file, inode, + (void __user *) arg); + break; case BCHFS_IOC_REINHERIT_ATTRS: - return bch2_ioc_reinherit_attrs(c, file, inode, - (void __user *) arg); + ret = bch2_ioc_reinherit_attrs(c, file, inode, + (void __user *) arg); + break; case FS_IOC_GETVERSION: - return -ENOTTY; + ret = -ENOTTY; + break; + case FS_IOC_SETVERSION: - return -ENOTTY; + ret = -ENOTTY; + break; case FS_IOC_GOINGDOWN: - return bch2_ioc_goingdown(c, (u32 __user *) arg); + ret = bch2_ioc_goingdown(c, (u32 __user *) arg); + break; case BCH_IOCTL_SUBVOLUME_CREATE: { struct bch_ioctl_subvolume i; - if (copy_from_user(&i, (void __user *) arg, sizeof(i))) - return -EFAULT; - return bch2_ioctl_subvolume_create(c, file, i); + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_create(c, file, i); + break; } case BCH_IOCTL_SUBVOLUME_DESTROY: { struct bch_ioctl_subvolume i; - if (copy_from_user(&i, (void __user *) arg, sizeof(i))) - return -EFAULT; - return bch2_ioctl_subvolume_destroy(c, file, i); + ret = copy_from_user(&i, (void __user *) arg, sizeof(i)) + ? -EFAULT + : bch2_ioctl_subvolume_destroy(c, file, i); + break; } default: - return bch2_fs_ioctl(c, cmd, (void __user *) arg); + ret = bch2_fs_ioctl(c, cmd, (void __user *) arg); + break; } + + return bch2_err_class(ret); } #ifdef CONFIG_COMPAT diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index af4941862187..66fcd3e28e0c 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -419,7 +419,7 @@ static int bch2_mknod(struct mnt_idmap *idmap, (subvol_inum) { 0 }, 0); if (IS_ERR(inode)) - return PTR_ERR(inode); + return bch2_err_class(PTR_ERR(inode)); d_instantiate(dentry, &inode->v); return 0; @@ -529,7 +529,7 @@ static int bch2_symlink(struct mnt_idmap *idmap, inode = __bch2_create(idmap, dir, dentry, S_IFLNK|S_IRWXUGO, 0, (subvol_inum) { 0 }, BCH_CREATE_TMPFILE); if (unlikely(IS_ERR(inode))) - return PTR_ERR(inode); + return bch2_err_class(PTR_ERR(inode)); inode_lock(&inode->v); ret = page_symlink(&inode->v, symname, strlen(symname) + 1); @@ -769,7 +769,7 @@ err_trans: err: mutex_unlock(&inode->ei_update_lock); - return ret; + return bch2_err_class(ret); } static int bch2_getattr(struct mnt_idmap *idmap, @@ -839,7 +839,7 @@ static int bch2_tmpfile(struct mnt_idmap *idmap, (subvol_inum) { 0 }, BCH_CREATE_TMPFILE); if (IS_ERR(inode)) - return PTR_ERR(inode); + return bch2_err_class(PTR_ERR(inode)); d_mark_tmpfile(file, &inode->v); d_instantiate(file->f_path.dentry, &inode->v); @@ -1454,7 +1454,7 @@ static int bch2_vfs_write_inode(struct inode *vinode, ATTR_ATIME|ATTR_MTIME|ATTR_CTIME); mutex_unlock(&inode->ei_update_lock); - return ret; + return bch2_err_class(ret); } static void bch2_evict_inode(struct inode *vinode) @@ -1558,6 +1558,7 @@ static int bch2_statfs(struct dentry *dentry, struct kstatfs *buf) static int bch2_sync_fs(struct super_block *sb, int wait) { struct bch_fs *c = sb->s_fs_info; + int ret; if (c->opts.journal_flush_disabled) return 0; @@ -1567,7 +1568,8 @@ static int bch2_sync_fs(struct super_block *sb, int wait) return 0; } - return bch2_journal_flush(&c->journal); + ret = bch2_journal_flush(&c->journal); + return bch2_err_class(ret); } static struct bch_fs *bch2_path_to_fs(const char *path) @@ -1623,7 +1625,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) ret = bch2_parse_mount_opts(c, &opts, data); if (ret) - return ret; + goto err; if (opts.read_only != c->opts.read_only) { down_write(&c->state_lock); @@ -1637,7 +1639,8 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) if (ret) { bch_err(c, "error going rw: %i", ret); up_write(&c->state_lock); - return -EINVAL; + ret = -EINVAL; + goto err; } sb->s_flags &= ~SB_RDONLY; @@ -1650,8 +1653,8 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data) if (opts.errors >= 0) c->opts.errors = opts.errors; - - return ret; +err: + return bch2_err_class(ret); } static int bch2_show_devname(struct seq_file *seq, struct dentry *root) diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index 96c107e0508e..50b3ba92c5ae 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -40,14 +40,14 @@ #include "util.h" #define SYSFS_OPS(type) \ -const struct sysfs_ops type ## _sysfs_ops = { \ +const struct sysfs_ops type ## _sysfs_ops = { \ .show = type ## _show, \ .store = type ## _store \ } #define SHOW(fn) \ static ssize_t fn ## _to_text(struct printbuf *, \ - struct kobject *, struct attribute *);\ + struct kobject *, struct attribute *); \ \ static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\ char *buf) \ @@ -66,15 +66,24 @@ static ssize_t fn ## _show(struct kobject *kobj, struct attribute *attr,\ memcpy(buf, out.buf, ret); \ } \ printbuf_exit(&out); \ - return ret; \ + return bch2_err_class(ret); \ } \ \ static ssize_t fn ## _to_text(struct printbuf *out, struct kobject *kobj,\ struct attribute *attr) #define STORE(fn) \ +static ssize_t fn ## _store_inner(struct kobject *, struct attribute *,\ + const char *, size_t); \ + \ static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\ const char *buf, size_t size) \ +{ \ + return bch2_err_class(fn##_store_inner(kobj, attr, buf, size)); \ +} \ + \ +static ssize_t fn ## _store_inner(struct kobject *kobj, struct attribute *attr,\ + const char *buf, size_t size) #define __sysfs_attribute(_name, _mode) \ static struct attribute sysfs_##_name = \ diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index 37793b3357d3..2b9fb4941e9f 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c @@ -350,17 +350,19 @@ err: bch2_trans_exit(&trans); if (ret) - return ret; + goto out; ret = bch2_xattr_list_bcachefs(c, &inode->ei_inode, &buf, false); if (ret) - return ret; + goto out; ret = bch2_xattr_list_bcachefs(c, &inode->ei_inode, &buf, true); if (ret) - return ret; + goto out; return buf.used; +out: + return bch2_err_class(ret); } static int bch2_xattr_get_handler(const struct xattr_handler *handler, @@ -369,8 +371,10 @@ static int bch2_xattr_get_handler(const struct xattr_handler *handler, { struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_fs *c = inode->v.i_sb->s_fs_info; + int ret; - return bch2_xattr_get(c, inode, name, buffer, size, handler->flags); + ret = bch2_xattr_get(c, inode, name, buffer, size, handler->flags); + return bch2_err_class(ret); } static int bch2_xattr_set_handler(const struct xattr_handler *handler, @@ -382,11 +386,13 @@ static int bch2_xattr_set_handler(const struct xattr_handler *handler, struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode); + int ret; - return bch2_trans_do(c, NULL, NULL, 0, + ret = bch2_trans_do(c, NULL, NULL, 0, bch2_xattr_set(&trans, inode_inum(inode), &hash, name, value, size, handler->flags, flags)); + return bch2_err_class(ret); } static const struct xattr_handler bch_xattr_user_handler = { |