diff options
Diffstat (limited to 'fs')
444 files changed, 15252 insertions, 20664 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 6181ad79e1a5..adaf6f6dd858 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -34,6 +34,7 @@ #include <linux/idr.h> #include <linux/sched.h> #include <linux/uio.h> +#include <linux/bvec.h> #include <net/9p/9p.h> #include <net/9p/client.h> @@ -309,18 +310,10 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping, p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); - if (unlikely(copied < len)) { - /* - * zero out the rest of the area - */ - unsigned from = pos & (PAGE_SIZE - 1); - - zero_user(page, from + copied, len - copied); - flush_dcache_page(page); + if (unlikely(copied < len && !PageUptodate(page))) { + copied = 0; + goto out; } - - if (!PageUptodate(page)) - SetPageUptodate(page); /* * No need to use i_size_read() here, the i_size * cannot change under us because we hold the i_mutex. @@ -330,6 +323,7 @@ static int v9fs_write_end(struct file *filp, struct address_space *mapping, i_size_write(inode, last_pos); } set_page_dirty(page); +out: unlock_page(page); put_page(page); diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 30ca770c5e0b..f4f4450119e4 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1464,7 +1464,6 @@ static const struct inode_operations v9fs_file_inode_operations = { }; static const struct inode_operations v9fs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = v9fs_vfs_get_link, .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index afaa4b6de801..5999bd050678 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -979,7 +979,6 @@ const struct inode_operations v9fs_file_inode_operations_dotl = { }; const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, .get_link = v9fs_vfs_get_link_dotl, .getattr = v9fs_vfs_getattr_dotl, .setattr = v9fs_vfs_setattr_dotl, diff --git a/fs/Kconfig b/fs/Kconfig index 4bd03a2b0518..c2a377cdda2b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -55,7 +55,6 @@ config FS_DAX_PMD depends on FS_DAX depends on ZONE_DEVICE depends on TRANSPARENT_HUGEPAGE - depends on BROKEN endif # BLOCK @@ -235,7 +234,6 @@ source "fs/efs/Kconfig" source "fs/jffs2/Kconfig" # UBIFS File system configuration source "fs/ubifs/Kconfig" -source "fs/logfs/Kconfig" source "fs/cramfs/Kconfig" source "fs/squashfs/Kconfig" source "fs/freevxfs/Kconfig" diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 4c09d93d9569..b2f82cf6bf86 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -170,8 +170,8 @@ config BINFMT_MISC You can do other nice things, too. Read the file <file:Documentation/binfmt_misc.txt> to learn how to use this - feature, <file:Documentation/java.txt> for information about how - to include Java support. and <file:Documentation/mono.txt> for + feature, <file:Documentation/admin-guide/java.rst> for information about how + to include Java support. and <file:Documentation/admin-guide/mono.rst> for information about how to include Mono-based .NET support. To use binfmt_misc, you will need to mount it: diff --git a/fs/Makefile b/fs/Makefile index ed2b63257ba9..7bbaca9c67b1 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -97,7 +97,6 @@ obj-$(CONFIG_NTFS_FS) += ntfs/ obj-$(CONFIG_UFS_FS) += ufs/ obj-$(CONFIG_EFS_FS) += efs/ obj-$(CONFIG_JFFS2_FS) += jffs2/ -obj-$(CONFIG_LOGFS) += logfs/ obj-$(CONFIG_UBIFS_FS) += ubifs/ obj-$(CONFIG_AFFS_FS) += affs/ obj-$(CONFIG_ROMFS_FS) += romfs/ diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 69b03dbb792f..ae622cdce142 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -70,7 +70,6 @@ const struct address_space_operations affs_symlink_aops = { }; const struct inode_operations affs_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = page_get_link, .setattr = affs_notify_change, }; @@ -277,10 +277,10 @@ static void put_aio_ring_file(struct kioctx *ctx) struct address_space *i_mapping; if (aio_ring_file) { - truncate_setsize(aio_ring_file->f_inode, 0); + truncate_setsize(file_inode(aio_ring_file), 0); /* Prevent further access to the kioctx from migratepages */ - i_mapping = aio_ring_file->f_inode->i_mapping; + i_mapping = aio_ring_file->f_mapping; spin_lock(&i_mapping->private_lock); i_mapping->private_data = NULL; ctx->aio_ring_file = NULL; @@ -483,7 +483,7 @@ static int aio_setup_ring(struct kioctx *ctx) for (i = 0; i < nr_pages; i++) { struct page *page; - page = find_or_create_page(file->f_inode->i_mapping, + page = find_or_create_page(file->f_mapping, i, GFP_HIGHUSER | __GFP_ZERO); if (!page) break; @@ -1367,6 +1367,39 @@ out: return ret; } +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_events, u32 __user *, ctx32p) +{ + struct kioctx *ioctx = NULL; + unsigned long ctx; + long ret; + + ret = get_user(ctx, ctx32p); + if (unlikely(ret)) + goto out; + + ret = -EINVAL; + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: ctx %lu nr_events %u\n", + ctx, nr_events); + goto out; + } + + ioctx = ioctx_alloc(nr_events); + ret = PTR_ERR(ioctx); + if (!IS_ERR(ioctx)) { + /* truncating is ok because it's a user address */ + ret = put_user((u32)ioctx->user_id, ctx32p); + if (ret) + kill_ioctx(current->mm, ioctx, NULL); + percpu_ref_put(&ioctx->users); + } + +out: + return ret; +} +#endif + /* sys_io_destroy: * Destroy the aio_context specified. May cancel any outstanding * AIOs and block on completion. Will fail with -ENOSYS if not @@ -1591,8 +1624,8 @@ out_put_req: return ret; } -long do_io_submit(aio_context_t ctx_id, long nr, - struct iocb __user *__user *iocbpp, bool compat) +static long do_io_submit(aio_context_t ctx_id, long nr, + struct iocb __user *__user *iocbpp, bool compat) { struct kioctx *ctx; long ret = 0; @@ -1662,6 +1695,44 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr, return do_io_submit(ctx_id, nr, iocbpp, 0); } +#ifdef CONFIG_COMPAT +static inline long +copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64) +{ + compat_uptr_t uptr; + int i; + + for (i = 0; i < nr; ++i) { + if (get_user(uptr, ptr32 + i)) + return -EFAULT; + if (put_user(compat_ptr(uptr), ptr64 + i)) + return -EFAULT; + } + return 0; +} + +#define MAX_AIO_SUBMITS (PAGE_SIZE/sizeof(struct iocb *)) + +COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id, + int, nr, u32 __user *, iocb) +{ + struct iocb __user * __user *iocb64; + long ret; + + if (unlikely(nr < 0)) + return -EINVAL; + + if (nr > MAX_AIO_SUBMITS) + nr = MAX_AIO_SUBMITS; + + iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64)); + ret = copy_iocb(nr, iocb, iocb64); + if (!ret) + ret = do_io_submit(ctx_id, nr, iocb64, 1); + return ret; +} +#endif + /* lookup_kiocb * Finds a given iocb for cancellation. */ @@ -1761,3 +1832,25 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, } return ret; } + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, + compat_long_t, min_nr, + compat_long_t, nr, + struct io_event __user *, events, + struct compat_timespec __user *, timeout) +{ + struct timespec t; + struct timespec __user *ut = NULL; + + if (timeout) { + if (compat_get_timespec(&t, timeout)) + return -EFAULT; + + ut = compat_alloc_user_space(sizeof(*ut)); + if (copy_to_user(ut, &t, sizeof(t))) + return -EFAULT; + } + return sys_io_getevents(ctx_id, min_nr, nr, events, ut); +} +#endif diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index a1fba4285277..c885daae68c8 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -145,7 +145,7 @@ void autofs4_free_ino(struct autofs_info *); /* Expiration */ int is_autofs4_dentry(struct dentry *); -int autofs4_expire_wait(struct dentry *dentry, int rcu_walk); +int autofs4_expire_wait(const struct path *path, int rcu_walk); int autofs4_expire_run(struct super_block *, struct vfsmount *, struct autofs_sb_info *, struct autofs_packet_expire __user *); @@ -217,7 +217,8 @@ static inline int autofs_prepare_pipe(struct file *pipe) /* Queue management functions */ -int autofs4_wait(struct autofs_sb_info *, struct dentry *, enum autofs_notify); +int autofs4_wait(struct autofs_sb_info *, + const struct path *, enum autofs_notify); int autofs4_wait_release(struct autofs_sb_info *, autofs_wqt_t, int); void autofs4_catatonic_mode(struct autofs_sb_info *); diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index fc09eb77ddf3..6f48d670c941 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c @@ -204,7 +204,7 @@ static int autofs_dev_ioctl_protosubver(struct file *fp, /* Find the topmost mount satisfying test() */ static int find_autofs_mount(const char *pathname, struct path *res, - int test(struct path *path, void *data), + int test(const struct path *path, void *data), void *data) { struct path path; @@ -230,12 +230,12 @@ static int find_autofs_mount(const char *pathname, return err; } -static int test_by_dev(struct path *path, void *p) +static int test_by_dev(const struct path *path, void *p) { return path->dentry->d_sb->s_dev == *(dev_t *)p; } -static int test_by_type(struct path *path, void *p) +static int test_by_type(const struct path *path, void *p) { struct autofs_info *ino = autofs4_dentry_ino(path->dentry); @@ -468,7 +468,7 @@ static int autofs_dev_ioctl_requester(struct file *fp, ino = autofs4_dentry_ino(path.dentry); if (ino) { err = 0; - autofs4_expire_wait(path.dentry, 0); + autofs4_expire_wait(&path, 0); spin_lock(&sbi->fs_lock); param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid); @@ -575,7 +575,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, devid = new_encode_dev(dev); - err = have_submounts(path.dentry); + err = path_has_submounts(&path); if (follow_down_one(&path)) magic = path.dentry->d_sb->s_magic; diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index d8e6d421c27f..57725d4a8c59 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -310,26 +310,29 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, now = jiffies; timeout = sbi->exp_timeout; - spin_lock(&sbi->fs_lock); - ino = autofs4_dentry_ino(root); - /* No point expiring a pending mount */ - if (ino->flags & AUTOFS_INF_PENDING) - goto out; if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { + spin_lock(&sbi->fs_lock); + ino = autofs4_dentry_ino(root); + /* No point expiring a pending mount */ + if (ino->flags & AUTOFS_INF_PENDING) { + spin_unlock(&sbi->fs_lock); + goto out; + } ino->flags |= AUTOFS_INF_WANT_EXPIRE; spin_unlock(&sbi->fs_lock); synchronize_rcu(); - spin_lock(&sbi->fs_lock); if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { + spin_lock(&sbi->fs_lock); ino->flags |= AUTOFS_INF_EXPIRING; init_completion(&ino->expire_complete); spin_unlock(&sbi->fs_lock); return root; } + spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_WANT_EXPIRE; + spin_unlock(&sbi->fs_lock); } out: - spin_unlock(&sbi->fs_lock); dput(root); return NULL; @@ -495,8 +498,9 @@ found: return expired; } -int autofs4_expire_wait(struct dentry *dentry, int rcu_walk) +int autofs4_expire_wait(const struct path *path, int rcu_walk) { + struct dentry *dentry = path->dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); int status; @@ -525,7 +529,7 @@ retry: pr_debug("waiting for expire %p name=%pd\n", dentry, dentry); - status = autofs4_wait(sbi, dentry, NFY_NONE); + status = autofs4_wait(sbi, path, NFY_NONE); wait_for_completion(&ino->expire_complete); pr_debug("expire done status=%d\n", status); @@ -592,11 +596,12 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, if (dentry) { struct autofs_info *ino = autofs4_dentry_ino(dentry); + const struct path path = { .mnt = mnt, .dentry = dentry }; /* This is synchronous because it makes the daemon a * little easier */ - ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); + ret = autofs4_wait(sbi, &path, NFY_EXPIRE); spin_lock(&sbi->fs_lock); /* avoid rapid-fire expire attempts if expiry fails */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 438b5bf675b6..09e7d68dff02 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -94,7 +94,7 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",indirect"); #ifdef CONFIG_CHECKPOINT_RESTORE if (sbi->pipe) - seq_printf(m, ",pipe_ino=%ld", sbi->pipe->f_inode->i_ino); + seq_printf(m, ",pipe_ino=%ld", file_inode(sbi->pipe)->i_ino); else seq_printf(m, ",pipe_ino=-1"); #endif diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index a11f73174877..82e8f6edfb48 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -32,7 +32,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file); static struct dentry *autofs4_lookup(struct inode *, struct dentry *, unsigned int); static struct vfsmount *autofs4_d_automount(struct path *); -static int autofs4_d_manage(struct dentry *, bool); +static int autofs4_d_manage(const struct path *, bool); static void autofs4_dentry_release(struct dentry *); const struct file_operations autofs4_root_operations = { @@ -123,7 +123,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) * it. */ spin_lock(&sbi->lookup_lock); - if (!d_mountpoint(dentry) && simple_empty(dentry)) { + if (!path_is_mountpoint(&file->f_path) && simple_empty(dentry)) { spin_unlock(&sbi->lookup_lock); return -ENOENT; } @@ -269,39 +269,41 @@ next: return NULL; } -static int autofs4_mount_wait(struct dentry *dentry, bool rcu_walk) +static int autofs4_mount_wait(const struct path *path, bool rcu_walk) { - struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); - struct autofs_info *ino = autofs4_dentry_ino(dentry); + struct autofs_sb_info *sbi = autofs4_sbi(path->dentry->d_sb); + struct autofs_info *ino = autofs4_dentry_ino(path->dentry); int status = 0; if (ino->flags & AUTOFS_INF_PENDING) { if (rcu_walk) return -ECHILD; - pr_debug("waiting for mount name=%pd\n", dentry); - status = autofs4_wait(sbi, dentry, NFY_MOUNT); + pr_debug("waiting for mount name=%pd\n", path->dentry); + status = autofs4_wait(sbi, path, NFY_MOUNT); pr_debug("mount wait done status=%d\n", status); } ino->last_used = jiffies; return status; } -static int do_expire_wait(struct dentry *dentry, bool rcu_walk) +static int do_expire_wait(const struct path *path, bool rcu_walk) { + struct dentry *dentry = path->dentry; struct dentry *expiring; expiring = autofs4_lookup_expiring(dentry, rcu_walk); if (IS_ERR(expiring)) return PTR_ERR(expiring); if (!expiring) - return autofs4_expire_wait(dentry, rcu_walk); + return autofs4_expire_wait(path, rcu_walk); else { + const struct path this = { .mnt = path->mnt, .dentry = expiring }; /* * If we are racing with expire the request might not * be quite complete, but the directory has been removed * so it must have been successful, just wait for it. */ - autofs4_expire_wait(expiring, 0); + autofs4_expire_wait(&this, 0); autofs4_del_expiring(expiring); dput(expiring); } @@ -354,7 +356,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path) * and the directory was removed, so just go ahead and try * the mount. */ - status = do_expire_wait(dentry, 0); + status = do_expire_wait(path, 0); if (status && status != -EAGAIN) return NULL; @@ -362,7 +364,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path) spin_lock(&sbi->fs_lock); if (ino->flags & AUTOFS_INF_PENDING) { spin_unlock(&sbi->fs_lock); - status = autofs4_mount_wait(dentry, 0); + status = autofs4_mount_wait(path, 0); if (status) return ERR_PTR(status); goto done; @@ -370,28 +372,28 @@ static struct vfsmount *autofs4_d_automount(struct path *path) /* * If the dentry is a symlink it's equivalent to a directory - * having d_mountpoint() true, so there's no need to call back - * to the daemon. + * having path_is_mountpoint() true, so there's no need to call + * back to the daemon. */ if (d_really_is_positive(dentry) && d_is_symlink(dentry)) { spin_unlock(&sbi->fs_lock); goto done; } - if (!d_mountpoint(dentry)) { + if (!path_is_mountpoint(path)) { /* * It's possible that user space hasn't removed directories * after umounting a rootless multi-mount, although it - * should. For v5 have_submounts() is sufficient to handle - * this because the leaves of the directory tree under the - * mount never trigger mounts themselves (they have an autofs - * trigger mount mounted on them). But v4 pseudo direct mounts - * do need the leaves to trigger mounts. In this case we - * have no choice but to use the list_empty() check and + * should. For v5 path_has_submounts() is sufficient to + * handle this because the leaves of the directory tree under + * the mount never trigger mounts themselves (they have an + * autofs trigger mount mounted on them). But v4 pseudo direct + * mounts do need the leaves to trigger mounts. In this case + * we have no choice but to use the list_empty() check and * require user space behave. */ if (sbi->version > 4) { - if (have_submounts(dentry)) { + if (path_has_submounts(path)) { spin_unlock(&sbi->fs_lock); goto done; } @@ -403,7 +405,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path) } ino->flags |= AUTOFS_INF_PENDING; spin_unlock(&sbi->fs_lock); - status = autofs4_mount_wait(dentry, 0); + status = autofs4_mount_wait(path, 0); spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_PENDING; if (status) { @@ -421,8 +423,9 @@ done: return NULL; } -static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) +static int autofs4_d_manage(const struct path *path, bool rcu_walk) { + struct dentry *dentry = path->dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); int status; @@ -431,20 +434,20 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) /* The daemon never waits. */ if (autofs4_oz_mode(sbi)) { - if (!d_mountpoint(dentry)) + if (!path_is_mountpoint(path)) return -EISDIR; return 0; } /* Wait for pending expires */ - if (do_expire_wait(dentry, rcu_walk) == -ECHILD) + if (do_expire_wait(path, rcu_walk) == -ECHILD) return -ECHILD; /* * This dentry may be under construction so wait on mount * completion. */ - status = autofs4_mount_wait(dentry, rcu_walk); + status = autofs4_mount_wait(path, rcu_walk); if (status) return status; @@ -460,7 +463,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) if (ino->flags & AUTOFS_INF_WANT_EXPIRE) return 0; - if (d_mountpoint(dentry)) + if (path_is_mountpoint(path)) return 0; inode = d_inode_rcu(dentry); if (inode && S_ISLNK(inode->i_mode)) @@ -487,7 +490,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) * we can avoid needless calls ->d_automount() and avoid * an incorrect ELOOP error return. */ - if ((!d_mountpoint(dentry) && !simple_empty(dentry)) || + if ((!path_is_mountpoint(path) && !simple_empty(dentry)) || (d_really_is_positive(dentry) && d_is_symlink(dentry))) status = -EISDIR; } diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index 99aab00dc217..ab0b4285a202 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -25,6 +25,5 @@ static const char *autofs4_get_link(struct dentry *dentry, } const struct inode_operations autofs4_symlink_inode_operations = { - .readlink = generic_readlink, .get_link = autofs4_get_link }; diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index e44271dfceb6..1278335ce366 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -250,8 +250,9 @@ autofs4_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr) static int validate_request(struct autofs_wait_queue **wait, struct autofs_sb_info *sbi, const struct qstr *qstr, - struct dentry *dentry, enum autofs_notify notify) + const struct path *path, enum autofs_notify notify) { + struct dentry *dentry = path->dentry; struct autofs_wait_queue *wq; struct autofs_info *ino; @@ -314,6 +315,7 @@ static int validate_request(struct autofs_wait_queue **wait, */ if (notify == NFY_MOUNT) { struct dentry *new = NULL; + struct path this; int valid = 1; /* @@ -333,7 +335,9 @@ static int validate_request(struct autofs_wait_queue **wait, dentry = new; } } - if (have_submounts(dentry)) + this.mnt = path->mnt; + this.dentry = dentry; + if (path_has_submounts(&this)) valid = 0; if (new) @@ -345,8 +349,9 @@ static int validate_request(struct autofs_wait_queue **wait, } int autofs4_wait(struct autofs_sb_info *sbi, - struct dentry *dentry, enum autofs_notify notify) + const struct path *path, enum autofs_notify notify) { + struct dentry *dentry = path->dentry; struct autofs_wait_queue *wq; struct qstr qstr; char *name; @@ -405,7 +410,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, return -EINTR; } - ret = validate_request(&wq, sbi, &qstr, dentry, notify); + ret = validate_request(&wq, sbi, &qstr, path, notify); if (ret <= 0) { if (ret != -EINTR) mutex_unlock(&sbi->wq_mutex); diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 8712062275b8..5f685c819298 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -106,6 +106,50 @@ static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer, return -EIO; } +static const char *bad_inode_get_link(struct dentry *dentry, + struct inode *inode, + struct delayed_call *done) +{ + return ERR_PTR(-EIO); +} + +static struct posix_acl *bad_inode_get_acl(struct inode *inode, int type) +{ + return ERR_PTR(-EIO); +} + +static int bad_inode_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, u64 start, + u64 len) +{ + return -EIO; +} + +static int bad_inode_update_time(struct inode *inode, struct timespec *time, + int flags) +{ + return -EIO; +} + +static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry, + struct file *file, unsigned int open_flag, + umode_t create_mode, int *opened) +{ + return -EIO; +} + +static int bad_inode_tmpfile(struct inode *inode, struct dentry *dentry, + umode_t mode) +{ + return -EIO; +} + +static int bad_inode_set_acl(struct inode *inode, struct posix_acl *acl, + int type) +{ + return -EIO; +} + static const struct inode_operations bad_inode_ops = { .create = bad_inode_create, @@ -118,14 +162,17 @@ static const struct inode_operations bad_inode_ops = .mknod = bad_inode_mknod, .rename = bad_inode_rename2, .readlink = bad_inode_readlink, - /* follow_link must be no-op, otherwise unmounting this inode - won't work */ - /* put_link returns void */ - /* truncate returns void */ .permission = bad_inode_permission, .getattr = bad_inode_getattr, .setattr = bad_inode_setattr, .listxattr = bad_inode_listxattr, + .get_link = bad_inode_get_link, + .get_acl = bad_inode_get_acl, + .fiemap = bad_inode_fiemap, + .update_time = bad_inode_update_time, + .atomic_open = bad_inode_atomic_open, + .tmpfile = bad_inode_tmpfile, + .set_acl = bad_inode_set_acl, }; diff --git a/fs/befs/befs.h b/fs/befs/befs.h index c6bad51d8ec7..b914cfb03820 100644 --- a/fs/befs/befs.h +++ b/fs/befs/befs.h @@ -129,6 +129,7 @@ static inline befs_inode_addr blockno2iaddr(struct super_block *sb, befs_blocknr_t blockno) { befs_inode_addr iaddr; + iaddr.allocation_group = blockno >> BEFS_SB(sb)->ag_shift; iaddr.start = blockno - (iaddr.allocation_group << BEFS_SB(sb)->ag_shift); @@ -140,7 +141,7 @@ blockno2iaddr(struct super_block *sb, befs_blocknr_t blockno) static inline unsigned int befs_iaddrs_per_block(struct super_block *sb) { - return BEFS_SB(sb)->block_size / sizeof (befs_disk_inode_addr); + return BEFS_SB(sb)->block_size / sizeof(befs_disk_inode_addr); } #include "endian.h" diff --git a/fs/befs/befs_fs_types.h b/fs/befs/befs_fs_types.h index eb557d9dc8be..69c9d8cde955 100644 --- a/fs/befs/befs_fs_types.h +++ b/fs/befs/befs_fs_types.h @@ -55,12 +55,12 @@ enum super_flags { }; #define BEFS_BYTEORDER_NATIVE 0x42494745 -#define BEFS_BYTEORDER_NATIVE_LE (__force fs32)cpu_to_le32(BEFS_BYTEORDER_NATIVE) -#define BEFS_BYTEORDER_NATIVE_BE (__force fs32)cpu_to_be32(BEFS_BYTEORDER_NATIVE) +#define BEFS_BYTEORDER_NATIVE_LE ((__force fs32)cpu_to_le32(BEFS_BYTEORDER_NATIVE)) +#define BEFS_BYTEORDER_NATIVE_BE ((__force fs32)cpu_to_be32(BEFS_BYTEORDER_NATIVE)) #define BEFS_SUPER_MAGIC BEFS_SUPER_MAGIC1 -#define BEFS_SUPER_MAGIC1_LE (__force fs32)cpu_to_le32(BEFS_SUPER_MAGIC1) -#define BEFS_SUPER_MAGIC1_BE (__force fs32)cpu_to_be32(BEFS_SUPER_MAGIC1) +#define BEFS_SUPER_MAGIC1_LE ((__force fs32)cpu_to_le32(BEFS_SUPER_MAGIC1)) +#define BEFS_SUPER_MAGIC1_BE ((__force fs32)cpu_to_be32(BEFS_SUPER_MAGIC1)) /* * Flags of inode @@ -79,7 +79,7 @@ enum inode_flags { BEFS_INODE_WAS_WRITTEN = 0x00020000, BEFS_NO_TRANSACTION = 0x00040000, }; -/* +/* * On-Disk datastructures of BeFS */ @@ -139,7 +139,7 @@ typedef struct { } PACKED befs_super_block; -/* +/* * Note: the indirect and dbl_indir block_runs may * be longer than one block! */ diff --git a/fs/befs/btree.c b/fs/befs/btree.c index 7e135ea73fdd..d509887c580c 100644 --- a/fs/befs/btree.c +++ b/fs/befs/btree.c @@ -12,8 +12,8 @@ * * Dominic Giampaolo, author of "Practical File System * Design with the Be File System", for such a helpful book. - * - * Marcus J. Ranum, author of the b+tree package in + * + * Marcus J. Ranum, author of the b+tree package in * comp.sources.misc volume 10. This code is not copied from that * work, but it is partially based on it. * @@ -38,38 +38,38 @@ */ /* Befs B+tree structure: - * + * * The first thing in the tree is the tree superblock. It tells you * all kinds of useful things about the tree, like where the rootnode * is located, and the size of the nodes (always 1024 with current version * of BeOS). * * The rest of the tree consists of a series of nodes. Nodes contain a header - * (struct befs_btree_nodehead), the packed key data, an array of shorts + * (struct befs_btree_nodehead), the packed key data, an array of shorts * containing the ending offsets for each of the keys, and an array of - * befs_off_t values. In interior nodes, the keys are the ending keys for - * the childnode they point to, and the values are offsets into the - * datastream containing the tree. + * befs_off_t values. In interior nodes, the keys are the ending keys for + * the childnode they point to, and the values are offsets into the + * datastream containing the tree. */ /* Note: - * - * The book states 2 confusing things about befs b+trees. First, + * + * The book states 2 confusing things about befs b+trees. First, * it states that the overflow field of node headers is used by internal nodes * to point to another node that "effectively continues this one". Here is what * I believe that means. Each key in internal nodes points to another node that - * contains key values less than itself. Inspection reveals that the last key - * in the internal node is not the last key in the index. Keys that are - * greater than the last key in the internal node go into the overflow node. + * contains key values less than itself. Inspection reveals that the last key + * in the internal node is not the last key in the index. Keys that are + * greater than the last key in the internal node go into the overflow node. * I imagine there is a performance reason for this. * - * Second, it states that the header of a btree node is sufficient to - * distinguish internal nodes from leaf nodes. Without saying exactly how. + * Second, it states that the header of a btree node is sufficient to + * distinguish internal nodes from leaf nodes. Without saying exactly how. * After figuring out the first, it becomes obvious that internal nodes have * overflow nodes and leafnodes do not. */ -/* +/* * Currently, this code is only good for directory B+trees. * In order to be used for other BFS indexes, it needs to be extended to handle * duplicate keys and non-string keytypes (int32, int64, float, double). @@ -237,8 +237,8 @@ befs_bt_read_node(struct super_block *sb, const befs_data_stream *ds, * with @key (usually the disk block number of an inode). * * On failure, returns BEFS_ERR or BEFS_BT_NOT_FOUND. - * - * Algorithm: + * + * Algorithm: * Read the superblock and rootnode of the b+tree. * Drill down through the interior nodes using befs_find_key(). * Once at the correct leaf node, use befs_find_key() again to get the @@ -402,12 +402,12 @@ befs_find_key(struct super_block *sb, struct befs_btree_node *node, * * Here's how it works: Key_no is the index of the key/value pair to * return in keybuf/value. - * Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is + * Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is * the number of characters in the key (just a convenience). * * Algorithm: * Get the first leafnode of the tree. See if the requested key is in that - * node. If not, follow the node->right link to the next leafnode. Repeat + * node. If not, follow the node->right link to the next leafnode. Repeat * until the (key_no)th key is found or the tree is out of keys. */ int @@ -536,7 +536,7 @@ befs_btree_read(struct super_block *sb, const befs_data_stream *ds, * @node_off: Pointer to offset of current node within datastream. Modified * by the function. * - * Helper function for btree traverse. Moves the current position to the + * Helper function for btree traverse. Moves the current position to the * start of the first leaf node. * * Also checks for an empty tree. If there are no keys, returns BEFS_BT_EMPTY. @@ -592,10 +592,10 @@ befs_btree_seekleaf(struct super_block *sb, const befs_data_stream *ds, } /** - * befs_leafnode - Determine if the btree node is a leaf node or an + * befs_leafnode - Determine if the btree node is a leaf node or an * interior node * @node: Pointer to node structure to test - * + * * Return 1 if leaf, 0 if interior */ static int @@ -656,7 +656,7 @@ befs_bt_valarray(struct befs_btree_node *node) * @node: Pointer to the node structure to find the keydata array within * * Returns a pointer to the start of the keydata array - * of the node pointed to by the node header + * of the node pointed to by the node header */ static char * befs_bt_keydata(struct befs_btree_node *node) @@ -702,7 +702,7 @@ befs_bt_get_key(struct super_block *sb, struct befs_btree_node *node, /** * befs_compare_strings - compare two strings - * @key1: pointer to the first key to be compared + * @key1: pointer to the first key to be compared * @keylen1: length in bytes of key1 * @key2: pointer to the second key to be compared * @keylen2: length in bytes of key2 diff --git a/fs/befs/btree.h b/fs/befs/btree.h index f2a8f637e9e0..60c6c728e64e 100644 --- a/fs/befs/btree.h +++ b/fs/befs/btree.h @@ -1,13 +1,11 @@ /* * btree.h - * + * */ - int befs_btree_find(struct super_block *sb, const befs_data_stream *ds, - const char *key, befs_off_t * value); + const char *key, befs_off_t *value); int befs_btree_read(struct super_block *sb, const befs_data_stream *ds, loff_t key_no, size_t bufsize, char *keybuf, - size_t * keysize, befs_off_t * value); - + size_t *keysize, befs_off_t *value); diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c index b4c7ba013c0d..720b3bc5c16a 100644 --- a/fs/befs/datastream.c +++ b/fs/befs/datastream.c @@ -84,13 +84,11 @@ befs_read_datastream(struct super_block *sb, const befs_data_stream *ds, * * Takes a file position and gives back a brun who's starting block * is block number fblock of the file. - * + * * Returns BEFS_OK or BEFS_ERR. - * + * * Calls specialized functions for each of the three possible * datastream regions. - * - * 2001-11-15 Will Dyson */ int befs_fblock2brun(struct super_block *sb, const befs_data_stream *data, @@ -120,7 +118,7 @@ befs_fblock2brun(struct super_block *sb, const befs_data_stream *data, /** * befs_read_lsmylink - read long symlink from datastream. - * @sb: Filesystem superblock + * @sb: Filesystem superblock * @ds: Datastream to read from * @buff: Buffer in which to place long symlink data * @len: Length of the long symlink in bytes diff --git a/fs/befs/datastream.h b/fs/befs/datastream.h index 91ba8203d83f..7ff9ff09ec6e 100644 --- a/fs/befs/datastream.h +++ b/fs/befs/datastream.h @@ -5,10 +5,10 @@ struct buffer_head *befs_read_datastream(struct super_block *sb, const befs_data_stream *ds, - befs_off_t pos, uint * off); + befs_off_t pos, uint *off); int befs_fblock2brun(struct super_block *sb, const befs_data_stream *data, - befs_blocknr_t fblock, befs_block_run * run); + befs_blocknr_t fblock, befs_block_run *run); size_t befs_read_lsymlink(struct super_block *sb, const befs_data_stream *data, void *buff, befs_off_t len); @@ -17,4 +17,3 @@ befs_blocknr_t befs_count_blocks(struct super_block *sb, const befs_data_stream *ds); extern const befs_inode_addr BAD_IADDR; - diff --git a/fs/befs/debug.c b/fs/befs/debug.c index 85c13392e9e8..36656c86f50e 100644 --- a/fs/befs/debug.c +++ b/fs/befs/debug.c @@ -1,6 +1,6 @@ /* * linux/fs/befs/debug.c - * + * * Copyright (C) 2001 Will Dyson (will_dyson at pobox.com) * * With help from the ntfs-tng driver by Anton Altparmakov @@ -57,6 +57,7 @@ befs_debug(const struct super_block *sb, const char *fmt, ...) struct va_format vaf; va_list args; + va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; @@ -67,7 +68,7 @@ befs_debug(const struct super_block *sb, const char *fmt, ...) } void -befs_dump_inode(const struct super_block *sb, befs_inode * inode) +befs_dump_inode(const struct super_block *sb, befs_inode *inode) { #ifdef CONFIG_BEFS_DEBUG @@ -151,7 +152,7 @@ befs_dump_inode(const struct super_block *sb, befs_inode * inode) */ void -befs_dump_super_block(const struct super_block *sb, befs_super_block * sup) +befs_dump_super_block(const struct super_block *sb, befs_super_block *sup) { #ifdef CONFIG_BEFS_DEBUG @@ -202,7 +203,7 @@ befs_dump_super_block(const struct super_block *sb, befs_super_block * sup) #if 0 /* unused */ void -befs_dump_small_data(const struct super_block *sb, befs_small_data * sd) +befs_dump_small_data(const struct super_block *sb, befs_small_data *sd) { } @@ -221,7 +222,8 @@ befs_dump_run(const struct super_block *sb, befs_disk_block_run run) #endif /* 0 */ void -befs_dump_index_entry(const struct super_block *sb, befs_disk_btree_super * super) +befs_dump_index_entry(const struct super_block *sb, + befs_disk_btree_super *super) { #ifdef CONFIG_BEFS_DEBUG @@ -242,7 +244,7 @@ befs_dump_index_entry(const struct super_block *sb, befs_disk_btree_super * supe } void -befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead * node) +befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *node) { #ifdef CONFIG_BEFS_DEBUG diff --git a/fs/befs/inode.c b/fs/befs/inode.c index fa4b718de597..5367a6470a69 100644 --- a/fs/befs/inode.c +++ b/fs/befs/inode.c @@ -1,6 +1,6 @@ /* * inode.c - * + * * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com> */ @@ -10,12 +10,12 @@ #include "inode.h" /* - Validates the correctness of the befs inode - Returns BEFS_OK if the inode should be used, otherwise - returns BEFS_BAD_INODE -*/ + * Validates the correctness of the befs inode + * Returns BEFS_OK if the inode should be used, otherwise + * returns BEFS_BAD_INODE + */ int -befs_check_inode(struct super_block *sb, befs_inode * raw_inode, +befs_check_inode(struct super_block *sb, befs_inode *raw_inode, befs_blocknr_t inode) { u32 magic1 = fs32_to_cpu(sb, raw_inode->magic1); diff --git a/fs/befs/inode.h b/fs/befs/inode.h index 9dc7fd9b7570..2219e412f49b 100644 --- a/fs/befs/inode.h +++ b/fs/befs/inode.h @@ -1,8 +1,7 @@ /* * inode.h - * + * */ -int befs_check_inode(struct super_block *sb, befs_inode * raw_inode, +int befs_check_inode(struct super_block *sb, befs_inode *raw_inode, befs_blocknr_t inode); - diff --git a/fs/befs/io.c b/fs/befs/io.c index b4a558126ee1..227cb86e07fe 100644 --- a/fs/befs/io.c +++ b/fs/befs/io.c @@ -3,7 +3,7 @@ * * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com * - * Based on portions of file.c and inode.c + * Based on portions of file.c and inode.c * by Makoto Kato (m_kato@ga2.so-net.ne.jp) * * Many thanks to Dominic Giampaolo, author of Practical File System @@ -19,8 +19,7 @@ /* * Converts befs notion of disk addr to a disk offset and uses * linux kernel function sb_bread() to get the buffer containing - * the offset. -Will Dyson - * + * the offset. */ struct buffer_head * @@ -55,7 +54,7 @@ befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr) befs_debug(sb, "<--- %s", __func__); return bh; - error: +error: befs_debug(sb, "<--- %s ERROR", __func__); return NULL; } diff --git a/fs/befs/io.h b/fs/befs/io.h index 78d7bc6e60de..9b3e1967cb31 100644 --- a/fs/befs/io.h +++ b/fs/befs/io.h @@ -4,4 +4,3 @@ struct buffer_head *befs_bread_iaddr(struct super_block *sb, befs_inode_addr iaddr); - diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 647a276eba56..19407165f4aa 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -18,6 +18,7 @@ #include <linux/parser.h> #include <linux/namei.h> #include <linux/sched.h> +#include <linux/exportfs.h> #include "befs.h" #include "btree.h" @@ -37,7 +38,8 @@ static int befs_readdir(struct file *, struct dir_context *); static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); static int befs_readpage(struct file *file, struct page *page); static sector_t befs_bmap(struct address_space *mapping, sector_t block); -static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int); +static struct dentry *befs_lookup(struct inode *, struct dentry *, + unsigned int); static struct inode *befs_iget(struct super_block *, unsigned long); static struct inode *befs_alloc_inode(struct super_block *sb); static void befs_destroy_inode(struct inode *inode); @@ -51,6 +53,10 @@ static void befs_put_super(struct super_block *); static int befs_remount(struct super_block *, int *, char *); static int befs_statfs(struct dentry *, struct kstatfs *); static int parse_options(char *, struct befs_mount_options *); +static struct dentry *befs_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *befs_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type); static const struct super_operations befs_sops = { .alloc_inode = befs_alloc_inode, /* allocate a new inode */ @@ -83,9 +89,14 @@ static const struct address_space_operations befs_symlink_aops = { .readpage = befs_symlink_readpage, }; -/* +static const struct export_operations befs_export_operations = { + .fh_to_dentry = befs_fh_to_dentry, + .fh_to_parent = befs_fh_to_parent, +}; + +/* * Called by generic_file_read() to read a page of data - * + * * In turn, simply calls a generic block read function and * passes it the address of befs_get_block, for mapping file * positions to disk blocks. @@ -102,15 +113,13 @@ befs_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping, block, befs_get_block); } -/* - * Generic function to map a file position (block) to a +/* + * Generic function to map a file position (block) to a * disk offset (passed back in bh_result). * * Used by many higher level functions. * * Calls befs_fblock2brun() in datastream.c to do the real work. - * - * -WD 10-26-01 */ static int @@ -269,15 +278,15 @@ befs_alloc_inode(struct super_block *sb) struct befs_inode_info *bi; bi = kmem_cache_alloc(befs_inode_cachep, GFP_KERNEL); - if (!bi) - return NULL; - return &bi->vfs_inode; + if (!bi) + return NULL; + return &bi->vfs_inode; } static void befs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); + kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); } static void befs_destroy_inode(struct inode *inode) @@ -287,7 +296,7 @@ static void befs_destroy_inode(struct inode *inode) static void init_once(void *foo) { - struct befs_inode_info *bi = (struct befs_inode_info *) foo; + struct befs_inode_info *bi = (struct befs_inode_info *) foo; inode_init_once(&bi->vfs_inode); } @@ -338,7 +347,7 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) /* * set uid and gid. But since current BeOS is single user OS, so * you can change by "uid" or "gid" options. - */ + */ inode->i_uid = befs_sb->mount_opts.use_uid ? befs_sb->mount_opts.uid : @@ -353,14 +362,14 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) * BEFS's time is 64 bits, but current VFS is 32 bits... * BEFS don't have access time. Nor inode change time. VFS * doesn't have creation time. - * Also, the lower 16 bits of the last_modified_time and + * Also, the lower 16 bits of the last_modified_time and * create_time are just a counter to help ensure uniqueness * for indexing purposes. (PFD, page 54) */ inode->i_mtime.tv_sec = fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16; - inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ + inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ inode->i_ctime = inode->i_mtime; inode->i_atime = inode->i_mtime; @@ -414,10 +423,10 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino) unlock_new_inode(inode); return inode; - unacquire_bh: +unacquire_bh: brelse(bh); - unacquire_none: +unacquire_none: iget_failed(inode); befs_debug(sb, "<--- %s - Bad inode", __func__); return ERR_PTR(-EIO); @@ -442,7 +451,7 @@ befs_init_inodecache(void) } /* Called at fs teardown. - * + * * Taken from NFS implementation by Al Viro. */ static void @@ -491,13 +500,10 @@ fail: } /* - * UTF-8 to NLS charset convert routine - * + * UTF-8 to NLS charset convert routine * - * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than - * the nls tables directly + * Uses uni2char() / char2uni() rather than the nls tables directly */ - static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, char **out, int *out_len) @@ -521,9 +527,8 @@ befs_utf2nls(struct super_block *sb, const char *in, } *out = result = kmalloc(maxlen, GFP_NOFS); - if (!*out) { + if (!*out) return -ENOMEM; - } for (i = o = 0; i < in_len; i += utflen, o += unilen) { @@ -546,7 +551,7 @@ befs_utf2nls(struct super_block *sb, const char *in, return o; - conv_err: +conv_err: befs_error(sb, "Name using character set %s contains a character that " "cannot be converted to unicode.", nls->charset); befs_debug(sb, "<--- %s", __func__); @@ -561,18 +566,18 @@ befs_utf2nls(struct super_block *sb, const char *in, * @in_len: Length of input string in bytes * @out: The output string in UTF-8 format * @out_len: Length of the output buffer - * + * * Converts input string @in, which is in the format of the loaded NLS map, * into a utf8 string. - * + * * The destination string @out is allocated by this function and the caller is * responsible for freeing it with kfree() - * + * * On return, *@out_len is the length of @out in bytes. * * On success, the return value is the number of utf8 characters written to * the output buffer @out. - * + * * On Failure, a negative number coresponding to the error code is returned. */ @@ -585,9 +590,11 @@ befs_nls2utf(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - /* There're nls characters that will translate to 3-chars-wide UTF-8 - * characters, a additional byte is needed to save the final \0 - * in special cases */ + /* + * There are nls characters that will translate to 3-chars-wide UTF-8 + * characters, an additional byte is needed to save the final \0 + * in special cases + */ int maxlen = (3 * in_len) + 1; befs_debug(sb, "---> %s\n", __func__); @@ -624,14 +631,41 @@ befs_nls2utf(struct super_block *sb, const char *in, return i; - conv_err: - befs_error(sb, "Name using charecter set %s contains a charecter that " +conv_err: + befs_error(sb, "Name using character set %s contains a character that " "cannot be converted to unicode.", nls->charset); befs_debug(sb, "<--- %s", __func__); kfree(result); return -EILSEQ; } +static struct inode *befs_nfs_get_inode(struct super_block *sb, uint64_t ino, + uint32_t generation) +{ + /* No need to handle i_generation */ + return befs_iget(sb, ino); +} + +/* + * Map a NFS file handle to a corresponding dentry + */ +static struct dentry *befs_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + befs_nfs_get_inode); +} + +/* + * Find the parent for a file specified by NFS handle + */ +static struct dentry *befs_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + befs_nfs_get_inode); +} + enum { Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err, }; @@ -666,6 +700,7 @@ parse_options(char *options, struct befs_mount_options *opts) while ((p = strsep(&options, ",")) != NULL) { int token; + if (!*p) continue; @@ -721,7 +756,7 @@ parse_options(char *options, struct befs_mount_options *opts) } /* This function has the responsibiltiy of getting the - * filesystem ready for unmounting. + * filesystem ready for unmounting. * Basically, we free everything that we allocated in * befs_read_inode */ @@ -782,8 +817,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) * Linux 2.4.10 and later refuse to read blocks smaller than * the logical block size for the device. But we also need to read at * least 1k to get the second 512 bytes of the volume. - * -WD 10-26-01 - */ + */ blocksize = sb_min_blocksize(sb, 1024); if (!blocksize) { if (!silent) @@ -791,7 +825,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent) goto unacquire_priv_sbp; } - if (!(bh = sb_bread(sb, sb_block))) { + bh = sb_bread(sb, sb_block); + if (!bh) { if (!silent) befs_error(sb, "unable to read superblock"); goto unacquire_priv_sbp; @@ -816,7 +851,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) brelse(bh); - if( befs_sb->num_blocks > ~((sector_t)0) ) { + if (befs_sb->num_blocks > ~((sector_t)0)) { if (!silent) befs_error(sb, "blocks count: %llu is larger than the host can use", befs_sb->num_blocks); @@ -831,6 +866,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent) /* Set real blocksize of fs */ sb_set_blocksize(sb, (ulong) befs_sb->block_size); sb->s_op = &befs_sops; + sb->s_export_op = &befs_export_operations; root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); if (IS_ERR(root)) { ret = PTR_ERR(root); @@ -861,16 +897,16 @@ befs_fill_super(struct super_block *sb, void *data, int silent) } return 0; -/*****************/ - unacquire_bh: + +unacquire_bh: brelse(bh); - unacquire_priv_sbp: +unacquire_priv_sbp: kfree(befs_sb->mount_opts.iocharset); kfree(sb->s_fs_info); sb->s_fs_info = NULL; - unacquire_none: +unacquire_none: return ret; } @@ -919,7 +955,7 @@ static struct file_system_type befs_fs_type = { .name = "befs", .mount = befs_mount, .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("befs"); @@ -956,9 +992,9 @@ exit_befs_fs(void) } /* -Macros that typecheck the init and exit functions, -ensures that they are called at init and cleanup, -and eliminates warnings about unused functions. -*/ + * Macros that typecheck the init and exit functions, + * ensures that they are called at init and cleanup, + * and eliminates warnings about unused functions. + */ module_init(init_befs_fs) module_exit(exit_befs_fs) diff --git a/fs/befs/super.h b/fs/befs/super.h index dc4556376a22..ec1df30a7e9a 100644 --- a/fs/befs/super.h +++ b/fs/befs/super.h @@ -2,7 +2,5 @@ * super.h */ -int befs_load_sb(struct super_block *sb, befs_super_block * disk_sb); - +int befs_load_sb(struct super_block *sb, befs_super_block *disk_sb); int befs_check_sb(struct super_block *sb); - diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 2472af2798c7..e6c1bd443806 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -2204,7 +2204,9 @@ static int elf_core_dump(struct coredump_params *cprm) dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); - vma_filesz = kmalloc_array(segs - 1, sizeof(*vma_filesz), GFP_KERNEL); + if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz)) + goto end_coredump; + vma_filesz = vmalloc((segs - 1) * sizeof(*vma_filesz)); if (!vma_filesz) goto end_coredump; @@ -2311,7 +2313,7 @@ end_coredump: cleanup: free_note_info(&info); kfree(shdr4extnum); - kfree(vma_filesz); + vfree(vma_filesz); kfree(phdr4note); kfree(elf); out: diff --git a/fs/block_dev.c b/fs/block_dev.c index 05b553368bb4..7c4507224ed6 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -30,6 +30,7 @@ #include <linux/cleancache.h> #include <linux/dax.h> #include <linux/badblocks.h> +#include <linux/task_io_accounting_ops.h> #include <linux/falloc.h> #include <asm/uaccess.h> #include "internal.h" @@ -175,16 +176,269 @@ static struct inode *bdev_file_inode(struct file *file) return file->f_mapping->host; } +static unsigned int dio_bio_write_op(struct kiocb *iocb) +{ + unsigned int op = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; + + /* avoid the need for a I/O completion work item */ + if (iocb->ki_flags & IOCB_DSYNC) + op |= REQ_FUA; + return op; +} + +#define DIO_INLINE_BIO_VECS 4 + +static void blkdev_bio_end_io_simple(struct bio *bio) +{ + struct task_struct *waiter = bio->bi_private; + + WRITE_ONCE(bio->bi_private, NULL); + wake_up_process(waiter); +} + static ssize_t -blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +__blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, + int nr_pages) +{ + struct file *file = iocb->ki_filp; + struct block_device *bdev = I_BDEV(bdev_file_inode(file)); + struct bio_vec inline_vecs[DIO_INLINE_BIO_VECS], *vecs, *bvec; + loff_t pos = iocb->ki_pos; + bool should_dirty = false; + struct bio bio; + ssize_t ret; + blk_qc_t qc; + int i; + + if ((pos | iov_iter_alignment(iter)) & + (bdev_logical_block_size(bdev) - 1)) + return -EINVAL; + + if (nr_pages <= DIO_INLINE_BIO_VECS) + vecs = inline_vecs; + else { + vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL); + if (!vecs) + return -ENOMEM; + } + + bio_init(&bio, vecs, nr_pages); + bio.bi_bdev = bdev; + bio.bi_iter.bi_sector = pos >> 9; + bio.bi_private = current; + bio.bi_end_io = blkdev_bio_end_io_simple; + + ret = bio_iov_iter_get_pages(&bio, iter); + if (unlikely(ret)) + return ret; + ret = bio.bi_iter.bi_size; + + if (iov_iter_rw(iter) == READ) { + bio.bi_opf = REQ_OP_READ; + if (iter_is_iovec(iter)) + should_dirty = true; + } else { + bio.bi_opf = dio_bio_write_op(iocb); + task_io_account_write(ret); + } + + qc = submit_bio(&bio); + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (!READ_ONCE(bio.bi_private)) + break; + if (!(iocb->ki_flags & IOCB_HIPRI) || + !blk_mq_poll(bdev_get_queue(bdev), qc)) + io_schedule(); + } + __set_current_state(TASK_RUNNING); + + bio_for_each_segment_all(bvec, &bio, i) { + if (should_dirty && !PageCompound(bvec->bv_page)) + set_page_dirty_lock(bvec->bv_page); + put_page(bvec->bv_page); + } + + if (vecs != inline_vecs) + kfree(vecs); + + if (unlikely(bio.bi_error)) + return bio.bi_error; + return ret; +} + +struct blkdev_dio { + union { + struct kiocb *iocb; + struct task_struct *waiter; + }; + size_t size; + atomic_t ref; + bool multi_bio : 1; + bool should_dirty : 1; + bool is_sync : 1; + struct bio bio; +}; + +static struct bio_set *blkdev_dio_pool __read_mostly; + +static void blkdev_bio_end_io(struct bio *bio) +{ + struct blkdev_dio *dio = bio->bi_private; + bool should_dirty = dio->should_dirty; + + if (dio->multi_bio && !atomic_dec_and_test(&dio->ref)) { + if (bio->bi_error && !dio->bio.bi_error) + dio->bio.bi_error = bio->bi_error; + } else { + if (!dio->is_sync) { + struct kiocb *iocb = dio->iocb; + ssize_t ret = dio->bio.bi_error; + + if (likely(!ret)) { + ret = dio->size; + iocb->ki_pos += ret; + } + + dio->iocb->ki_complete(iocb, ret, 0); + bio_put(&dio->bio); + } else { + struct task_struct *waiter = dio->waiter; + + WRITE_ONCE(dio->waiter, NULL); + wake_up_process(waiter); + } + } + + if (should_dirty) { + bio_check_pages_dirty(bio); + } else { + struct bio_vec *bvec; + int i; + + bio_for_each_segment_all(bvec, bio, i) + put_page(bvec->bv_page); + bio_put(bio); + } +} + +static ssize_t +__blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) { struct file *file = iocb->ki_filp; struct inode *inode = bdev_file_inode(file); + struct block_device *bdev = I_BDEV(inode); + struct blkdev_dio *dio; + struct bio *bio; + bool is_read = (iov_iter_rw(iter) == READ); + loff_t pos = iocb->ki_pos; + blk_qc_t qc = BLK_QC_T_NONE; + int ret; + + if ((pos | iov_iter_alignment(iter)) & + (bdev_logical_block_size(bdev) - 1)) + return -EINVAL; + + bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, blkdev_dio_pool); + bio_get(bio); /* extra ref for the completion handler */ + + dio = container_of(bio, struct blkdev_dio, bio); + dio->is_sync = is_sync_kiocb(iocb); + if (dio->is_sync) + dio->waiter = current; + else + dio->iocb = iocb; + + dio->size = 0; + dio->multi_bio = false; + dio->should_dirty = is_read && (iter->type == ITER_IOVEC); + + for (;;) { + bio->bi_bdev = bdev; + bio->bi_iter.bi_sector = pos >> 9; + bio->bi_private = dio; + bio->bi_end_io = blkdev_bio_end_io; + + ret = bio_iov_iter_get_pages(bio, iter); + if (unlikely(ret)) { + bio->bi_error = ret; + bio_endio(bio); + break; + } + + if (is_read) { + bio->bi_opf = REQ_OP_READ; + if (dio->should_dirty) + bio_set_pages_dirty(bio); + } else { + bio->bi_opf = dio_bio_write_op(iocb); + task_io_account_write(bio->bi_iter.bi_size); + } + + dio->size += bio->bi_iter.bi_size; + pos += bio->bi_iter.bi_size; + + nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES); + if (!nr_pages) { + qc = submit_bio(bio); + break; + } + + if (!dio->multi_bio) { + dio->multi_bio = true; + atomic_set(&dio->ref, 2); + } else { + atomic_inc(&dio->ref); + } - return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, - blkdev_get_block, NULL, NULL, - DIO_SKIP_DIO_COUNT); + submit_bio(bio); + bio = bio_alloc(GFP_KERNEL, nr_pages); + } + + if (!dio->is_sync) + return -EIOCBQUEUED; + + for (;;) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (!READ_ONCE(dio->waiter)) + break; + + if (!(iocb->ki_flags & IOCB_HIPRI) || + !blk_mq_poll(bdev_get_queue(bdev), qc)) + io_schedule(); + } + __set_current_state(TASK_RUNNING); + + ret = dio->bio.bi_error; + if (likely(!ret)) + ret = dio->size; + + bio_put(&dio->bio); + return ret; +} + +static ssize_t +blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + int nr_pages; + + nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES + 1); + if (!nr_pages) + return 0; + if (is_sync_kiocb(iocb) && nr_pages <= BIO_MAX_PAGES) + return __blkdev_direct_IO_simple(iocb, iter, nr_pages); + + return __blkdev_direct_IO(iocb, iter, min(nr_pages, BIO_MAX_PAGES)); +} + +static __init int blkdev_init(void) +{ + blkdev_dio_pool = bioset_create(4, offsetof(struct blkdev_dio, bio)); + if (!blkdev_dio_pool) + return -ENOMEM; + return 0; } +module_init(blkdev_init); int __sync_blockdev(struct block_device *bdev, int wait) { @@ -832,7 +1086,7 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, return true; /* already a holder */ else if (bdev->bd_holder != NULL) return false; /* held by someone else */ - else if (bdev->bd_contains == bdev) + else if (whole == bdev) return true; /* is a whole device which isn't held */ else if (whole->bd_holder == bd_may_claim) @@ -1950,6 +2204,7 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) spin_lock(&blockdev_superblock->s_inode_list_lock); list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) { struct address_space *mapping = inode->i_mapping; + struct block_device *bdev; spin_lock(&inode->i_lock); if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) || @@ -1970,8 +2225,12 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) */ iput(old_inode); old_inode = inode; + bdev = I_BDEV(inode); - func(I_BDEV(inode), arg); + mutex_lock(&bdev->bd_mutex); + if (bdev->bd_openers) + func(bdev, arg); + mutex_unlock(&bdev->bd_mutex); spin_lock(&blockdev_superblock->s_inode_list_lock); } diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index e0f071f6b5a7..63d197724519 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -86,6 +86,20 @@ btrfs_work_owner(struct btrfs_work *work) return work->wq->fs_info; } +bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq) +{ + /* + * We could compare wq->normal->pending with num_online_cpus() + * to support "thresh == NO_THRESHOLD" case, but it requires + * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's + * postpone it until someone needs the support of that case. + */ + if (wq->normal->thresh == NO_THRESHOLD) + return false; + + return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2; +} + BTRFS_WORK_HELPER(worker_helper); BTRFS_WORK_HELPER(delalloc_helper); BTRFS_WORK_HELPER(flush_delalloc_helper); diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h index 8e52484cd461..1f9597355c9d 100644 --- a/fs/btrfs/async-thread.h +++ b/fs/btrfs/async-thread.h @@ -84,4 +84,5 @@ void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max); void btrfs_set_work_high_priority(struct btrfs_work *work); struct btrfs_fs_info *btrfs_work_owner(struct btrfs_work *work); struct btrfs_fs_info *btrfs_workqueue_owner(struct __btrfs_workqueue *wq); +bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq); #endif diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 85dc7ab8f89e..8299601a3549 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -788,8 +788,7 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info, if (ref->key_for_search.type) continue; BUG_ON(!ref->wanted_disk_byte); - eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte, - 0); + eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0); if (IS_ERR(eb)) { return PTR_ERR(eb); } else if (!extent_buffer_uptodate(eb)) { @@ -1405,8 +1404,7 @@ again: ref->level == 0) { struct extent_buffer *eb; - eb = read_tree_block(fs_info->extent_root, - ref->parent, 0); + eb = read_tree_block(fs_info, ref->parent, 0); if (IS_ERR(eb)) { ret = PTR_ERR(eb); goto out; @@ -1829,7 +1827,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, } btrfs_item_key_to_cpu(path->nodes[0], found_key, path->slots[0]); if (found_key->type == BTRFS_METADATA_ITEM_KEY) - size = fs_info->extent_root->nodesize; + size = fs_info->nodesize; else if (found_key->type == BTRFS_EXTENT_ITEM_KEY) size = found_key->offset; @@ -2058,7 +2056,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, out: if (!search_commit_root) { btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); - btrfs_end_transaction(trans, fs_info->extent_root); + btrfs_end_transaction(trans); } else { up_read(&fs_info->commit_root_sem); } diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 8e99251650b3..ab14c2e635ca 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -254,7 +254,7 @@ struct btrfsic_state { struct list_head all_blocks_list; struct btrfsic_block_hashtable block_hashtable; struct btrfsic_block_link_hashtable block_link_hashtable; - struct btrfs_root *root; + struct btrfs_fs_info *fs_info; u64 max_superblock_generation; struct btrfsic_block *latest_superblock; u32 metablock_size; @@ -646,11 +646,12 @@ static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup( static int btrfsic_process_superblock(struct btrfsic_state *state, struct btrfs_fs_devices *fs_devices) { - int ret = 0; + struct btrfs_fs_info *fs_info = state->fs_info; struct btrfs_super_block *selected_super; struct list_head *dev_head = &fs_devices->devices; struct btrfs_device *device; struct btrfsic_dev_state *selected_dev_state = NULL; + int ret = 0; int pass; BUG_ON(NULL == state); @@ -716,9 +717,8 @@ static int btrfsic_process_superblock(struct btrfsic_state *state, break; } - num_copies = - btrfs_num_copies(state->root->fs_info, - next_bytenr, state->metablock_size); + num_copies = btrfs_num_copies(fs_info, next_bytenr, + state->metablock_size); if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) pr_info("num_copies(log_bytenr=%llu) = %d\n", next_bytenr, num_copies); @@ -783,6 +783,7 @@ static int btrfsic_process_superblock_dev_mirror( struct btrfsic_dev_state **selected_dev_state, struct btrfs_super_block *selected_super) { + struct btrfs_fs_info *fs_info = state->fs_info; struct btrfs_super_block *super_tmp; u64 dev_bytenr; struct buffer_head *bh; @@ -832,7 +833,7 @@ static int btrfsic_process_superblock_dev_mirror( superblock_tmp->never_written = 0; superblock_tmp->mirror_num = 1 + superblock_mirror_num; if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) - btrfs_info_in_rcu(device->dev_root->fs_info, + btrfs_info_in_rcu(fs_info, "new initial S-block (bdev %p, %s) @%llu (%s/%llu/%d)", superblock_bdev, rcu_str_deref(device->name), dev_bytenr, @@ -887,9 +888,8 @@ static int btrfsic_process_superblock_dev_mirror( break; } - num_copies = - btrfs_num_copies(state->root->fs_info, - next_bytenr, state->metablock_size); + num_copies = btrfs_num_copies(fs_info, next_bytenr, + state->metablock_size); if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) pr_info("num_copies(log_bytenr=%llu) = %d\n", next_bytenr, num_copies); @@ -1254,6 +1254,7 @@ static int btrfsic_create_link_to_next_block( struct btrfs_disk_key *disk_key, u64 parent_generation) { + struct btrfs_fs_info *fs_info = state->fs_info; struct btrfsic_block *next_block = NULL; int ret; struct btrfsic_block_link *l; @@ -1262,9 +1263,8 @@ static int btrfsic_create_link_to_next_block( *next_blockp = NULL; if (0 == *num_copiesp) { - *num_copiesp = - btrfs_num_copies(state->root->fs_info, - next_bytenr, state->metablock_size); + *num_copiesp = btrfs_num_copies(fs_info, next_bytenr, + state->metablock_size); if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) pr_info("num_copies(log_bytenr=%llu) = %d\n", next_bytenr, *num_copiesp); @@ -1390,13 +1390,14 @@ static int btrfsic_handle_extent_data( struct btrfsic_block_data_ctx *block_ctx, u32 item_offset, int force_iodone_flag) { - int ret; + struct btrfs_fs_info *fs_info = state->fs_info; struct btrfs_file_extent_item file_extent_item; u64 file_extent_item_offset; u64 next_bytenr; u64 num_bytes; u64 generation; struct btrfsic_block_link *l; + int ret; file_extent_item_offset = offsetof(struct btrfs_leaf, items) + item_offset; @@ -1456,9 +1457,8 @@ static int btrfsic_handle_extent_data( else chunk_len = num_bytes; - num_copies = - btrfs_num_copies(state->root->fs_info, - next_bytenr, state->datablock_size); + num_copies = btrfs_num_copies(fs_info, next_bytenr, + state->datablock_size); if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) pr_info("num_copies(log_bytenr=%llu) = %d\n", next_bytenr, num_copies); @@ -1533,13 +1533,14 @@ static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, struct btrfsic_block_data_ctx *block_ctx_out, int mirror_num) { + struct btrfs_fs_info *fs_info = state->fs_info; int ret; u64 length; struct btrfs_bio *multi = NULL; struct btrfs_device *device; length = len; - ret = btrfs_map_block(state->root->fs_info, READ, + ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, bytenr, &length, &multi, mirror_num); if (ret) { @@ -1731,6 +1732,7 @@ static void btrfsic_dump_database(struct btrfsic_state *state) static int btrfsic_test_for_metadata(struct btrfsic_state *state, char **datav, unsigned int num_pages) { + struct btrfs_fs_info *fs_info = state->fs_info; struct btrfs_header *h; u8 csum[BTRFS_CSUM_SIZE]; u32 crc = ~(u32)0; @@ -1741,7 +1743,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state, num_pages = state->metablock_size >> PAGE_SHIFT; h = (struct btrfs_header *)datav[0]; - if (memcmp(h->fsid, state->root->fs_info->fsid, BTRFS_UUID_SIZE)) + if (memcmp(h->fsid, fs_info->fsid, BTRFS_UUID_SIZE)) return 1; for (i = 0; i < num_pages; i++) { @@ -2202,6 +2204,7 @@ static int btrfsic_process_written_superblock( struct btrfsic_block *const superblock, struct btrfs_super_block *const super_hdr) { + struct btrfs_fs_info *fs_info = state->fs_info; int pass; superblock->generation = btrfs_super_generation(super_hdr); @@ -2275,9 +2278,8 @@ static int btrfsic_process_written_superblock( break; } - num_copies = - btrfs_num_copies(state->root->fs_info, - next_bytenr, BTRFS_SUPER_INFO_SIZE); + num_copies = btrfs_num_copies(fs_info, next_bytenr, + BTRFS_SUPER_INFO_SIZE); if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) pr_info("num_copies(log_bytenr=%llu) = %d\n", next_bytenr, num_copies); @@ -2699,14 +2701,14 @@ static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state, struct btrfsic_dev_state *dev_state, u64 dev_bytenr) { + struct btrfs_fs_info *fs_info = state->fs_info; + struct btrfsic_block_data_ctx block_ctx; int num_copies; int mirror_num; - int ret; - struct btrfsic_block_data_ctx block_ctx; int match = 0; + int ret; - num_copies = btrfs_num_copies(state->root->fs_info, - bytenr, state->metablock_size); + num_copies = btrfs_num_copies(fs_info, bytenr, state->metablock_size); for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { ret = btrfsic_map_block(state, bytenr, state->metablock_size, @@ -2819,10 +2821,11 @@ static void __btrfsic_submit_bio(struct bio *bio) * btrfsic_mount(), this might return NULL */ dev_state = btrfsic_dev_state_lookup(bio->bi_bdev); if (NULL != dev_state && - (bio_op(bio) == REQ_OP_WRITE) && NULL != bio->bi_io_vec) { + (bio_op(bio) == REQ_OP_WRITE) && bio_has_data(bio)) { unsigned int i; u64 dev_bytenr; u64 cur_bytenr; + struct bio_vec *bvec; int bio_is_patched; char **mapped_datav; @@ -2840,32 +2843,23 @@ static void __btrfsic_submit_bio(struct bio *bio) if (!mapped_datav) goto leave; cur_bytenr = dev_bytenr; - for (i = 0; i < bio->bi_vcnt; i++) { - BUG_ON(bio->bi_io_vec[i].bv_len != PAGE_SIZE); - mapped_datav[i] = kmap(bio->bi_io_vec[i].bv_page); - if (!mapped_datav[i]) { - while (i > 0) { - i--; - kunmap(bio->bi_io_vec[i].bv_page); - } - kfree(mapped_datav); - goto leave; - } + + bio_for_each_segment_all(bvec, bio, i) { + BUG_ON(bvec->bv_len != PAGE_SIZE); + mapped_datav[i] = kmap(bvec->bv_page); + if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE) pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n", - i, cur_bytenr, bio->bi_io_vec[i].bv_len, - bio->bi_io_vec[i].bv_offset); - cur_bytenr += bio->bi_io_vec[i].bv_len; + i, cur_bytenr, bvec->bv_len, bvec->bv_offset); + cur_bytenr += bvec->bv_len; } btrfsic_process_written_block(dev_state, dev_bytenr, mapped_datav, bio->bi_vcnt, bio, &bio_is_patched, NULL, bio->bi_opf); - while (i > 0) { - i--; - kunmap(bio->bi_io_vec[i].bv_page); - } + bio_for_each_segment_all(bvec, bio, i) + kunmap(bvec->bv_page); kfree(mapped_datav); } else if (NULL != dev_state && (bio->bi_opf & REQ_PREFLUSH)) { if (dev_state->state->print_mask & @@ -2910,7 +2904,7 @@ int btrfsic_submit_bio_wait(struct bio *bio) return submit_bio_wait(bio); } -int btrfsic_mount(struct btrfs_root *root, +int btrfsic_mount(struct btrfs_fs_info *fs_info, struct btrfs_fs_devices *fs_devices, int including_extent_data, u32 print_mask) { @@ -2919,14 +2913,14 @@ int btrfsic_mount(struct btrfs_root *root, struct list_head *dev_head = &fs_devices->devices; struct btrfs_device *device; - if (root->nodesize & ((u64)PAGE_SIZE - 1)) { + if (fs_info->nodesize & ((u64)PAGE_SIZE - 1)) { pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n", - root->nodesize, PAGE_SIZE); + fs_info->nodesize, PAGE_SIZE); return -1; } - if (root->sectorsize & ((u64)PAGE_SIZE - 1)) { + if (fs_info->sectorsize & ((u64)PAGE_SIZE - 1)) { pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n", - root->sectorsize, PAGE_SIZE); + fs_info->sectorsize, PAGE_SIZE); return -1; } state = kzalloc(sizeof(*state), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); @@ -2944,12 +2938,12 @@ int btrfsic_mount(struct btrfs_root *root, btrfsic_is_initialized = 1; } mutex_lock(&btrfsic_mutex); - state->root = root; + state->fs_info = fs_info; state->print_mask = print_mask; state->include_extent_data = including_extent_data; state->csum_size = 0; - state->metablock_size = root->nodesize; - state->datablock_size = root->sectorsize; + state->metablock_size = fs_info->nodesize; + state->datablock_size = fs_info->sectorsize; INIT_LIST_HEAD(&state->all_blocks_list); btrfsic_block_hashtable_init(&state->block_hashtable); btrfsic_block_link_hashtable_init(&state->block_link_hashtable); @@ -2982,7 +2976,7 @@ int btrfsic_mount(struct btrfs_root *root, ret = btrfsic_process_superblock(state, fs_devices); if (0 != ret) { mutex_unlock(&btrfsic_mutex); - btrfsic_unmount(root, fs_devices); + btrfsic_unmount(fs_devices); return ret; } @@ -2995,8 +2989,7 @@ int btrfsic_mount(struct btrfs_root *root, return 0; } -void btrfsic_unmount(struct btrfs_root *root, - struct btrfs_fs_devices *fs_devices) +void btrfsic_unmount(struct btrfs_fs_devices *fs_devices) { struct btrfsic_block *b_all, *tmp_all; struct btrfsic_state *state; diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h index f78dff1c7e86..2de58a99ee92 100644 --- a/fs/btrfs/check-integrity.h +++ b/fs/btrfs/check-integrity.h @@ -29,10 +29,9 @@ int btrfsic_submit_bio_wait(struct bio *bio); #define btrfsic_submit_bio_wait submit_bio_wait #endif -int btrfsic_mount(struct btrfs_root *root, +int btrfsic_mount(struct btrfs_fs_info *fs_info, struct btrfs_fs_devices *fs_devices, int including_extent_data, u32 print_mask); -void btrfsic_unmount(struct btrfs_root *root, - struct btrfs_fs_devices *fs_devices); +void btrfsic_unmount(struct btrfs_fs_devices *fs_devices); #endif diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index d4d8b7e36b2f..7f390849343b 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -81,17 +81,17 @@ struct compressed_bio { u32 sums; }; -static int btrfs_decompress_biovec(int type, struct page **pages_in, - u64 disk_start, struct bio_vec *bvec, - int vcnt, size_t srclen); +static int btrfs_decompress_bio(int type, struct page **pages_in, + u64 disk_start, struct bio *orig_bio, + size_t srclen); -static inline int compressed_bio_size(struct btrfs_root *root, +static inline int compressed_bio_size(struct btrfs_fs_info *fs_info, unsigned long disk_size) { - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); return sizeof(struct compressed_bio) + - (DIV_ROUND_UP(disk_size, root->sectorsize)) * csum_size; + (DIV_ROUND_UP(disk_size, fs_info->sectorsize)) * csum_size; } static struct bio *compressed_bio_alloc(struct block_device *bdev, @@ -120,7 +120,7 @@ static int check_compressed_csum(struct inode *inode, kaddr = kmap_atomic(page); csum = btrfs_csum_data(kaddr, csum, PAGE_SIZE); - btrfs_csum_final(csum, (char *)&csum); + btrfs_csum_final(csum, (u8 *)&csum); kunmap_atomic(kaddr); if (csum != *cb_sum) { @@ -175,11 +175,10 @@ static void end_compressed_bio_read(struct bio *bio) /* ok, we're the last bio for this extent, lets start * the decompression. */ - ret = btrfs_decompress_biovec(cb->compress_type, + ret = btrfs_decompress_bio(cb->compress_type, cb->compressed_pages, cb->start, - cb->orig_bio->bi_io_vec, - cb->orig_bio->bi_vcnt, + cb->orig_bio, cb->compressed_len); csum_failed: if (ret) @@ -329,8 +328,8 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, struct page **compressed_pages, unsigned long nr_pages) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct bio *bio = NULL; - struct btrfs_root *root = BTRFS_I(inode)->root; struct compressed_bio *cb; unsigned long bytes_left; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; @@ -342,7 +341,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, int skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; WARN_ON(start & ((u64)PAGE_SIZE - 1)); - cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); + cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS); if (!cb) return -ENOMEM; atomic_set(&cb->pending_bios, 0); @@ -356,7 +355,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, cb->orig_bio = NULL; cb->nr_pages = nr_pages; - bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; + bdev = fs_info->fs_devices->latest_bdev; bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); if (!bio) { @@ -392,17 +391,16 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, * freed before we're done setting it up */ atomic_inc(&cb->pending_bios); - ret = btrfs_bio_wq_end_io(root->fs_info, bio, - BTRFS_WQ_ENDIO_DATA); + ret = btrfs_bio_wq_end_io(fs_info, bio, + BTRFS_WQ_ENDIO_DATA); BUG_ON(ret); /* -ENOMEM */ if (!skip_sum) { - ret = btrfs_csum_one_bio(root, inode, bio, - start, 1); + ret = btrfs_csum_one_bio(inode, bio, start, 1); BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, bio, 0, 1); + ret = btrfs_map_bio(fs_info, bio, 0, 1); if (ret) { bio->bi_error = ret; bio_endio(bio); @@ -418,7 +416,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, bio_add_page(bio, page, PAGE_SIZE, 0); } if (bytes_left < PAGE_SIZE) { - btrfs_info(BTRFS_I(inode)->root->fs_info, + btrfs_info(fs_info, "bytes left %lu compress len %lu nr %lu", bytes_left, cb->compressed_len, cb->nr_pages); } @@ -428,15 +426,15 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, } bio_get(bio); - ret = btrfs_bio_wq_end_io(root->fs_info, bio, BTRFS_WQ_ENDIO_DATA); + ret = btrfs_bio_wq_end_io(fs_info, bio, BTRFS_WQ_ENDIO_DATA); BUG_ON(ret); /* -ENOMEM */ if (!skip_sum) { - ret = btrfs_csum_one_bio(root, inode, bio, start, 1); + ret = btrfs_csum_one_bio(inode, bio, start, 1); BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, bio, 0, 1); + ret = btrfs_map_bio(fs_info, bio, 0, 1); if (ret) { bio->bi_error = ret; bio_endio(bio); @@ -446,6 +444,13 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, return 0; } +static u64 bio_end_offset(struct bio *bio) +{ + struct bio_vec *last = &bio->bi_io_vec[bio->bi_vcnt - 1]; + + return page_offset(last->bv_page) + last->bv_len + last->bv_offset; +} + static noinline int add_ra_bio_pages(struct inode *inode, u64 compressed_end, struct compressed_bio *cb) @@ -464,8 +469,7 @@ static noinline int add_ra_bio_pages(struct inode *inode, u64 end; int misses = 0; - page = cb->orig_bio->bi_io_vec[cb->orig_bio->bi_vcnt - 1].bv_page; - last_offset = (page_offset(page) + PAGE_SIZE); + last_offset = bio_end_offset(cb->orig_bio); em_tree = &BTRFS_I(inode)->extent_tree; tree = &BTRFS_I(inode)->io_tree; @@ -563,7 +567,6 @@ next: * * bio->bi_iter.bi_sector points to the compressed extent on disk * bio->bi_io_vec points to all of the inode pages - * bio->bi_vcnt is a count of pages * * After the compressed pages are read, we copy the bytes into the * bio we were passed and then call the bio end_io calls @@ -571,11 +574,10 @@ next: int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct extent_io_tree *tree; struct extent_map_tree *em_tree; struct compressed_bio *cb; - struct btrfs_root *root = BTRFS_I(inode)->root; - unsigned long uncompressed_len = bio->bi_vcnt * PAGE_SIZE; unsigned long compressed_len; unsigned long nr_pages; unsigned long pg_index; @@ -603,7 +605,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, return -EIO; compressed_len = em->block_len; - cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); + cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS); if (!cb) goto out; @@ -620,7 +622,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, free_extent_map(em); em = NULL; - cb->len = uncompressed_len; + cb->len = bio->bi_iter.bi_size; cb->compressed_len = compressed_len; cb->compress_type = extent_compress_type(bio_flags); cb->orig_bio = bio; @@ -631,7 +633,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, if (!cb->compressed_pages) goto fail1; - bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; + bdev = fs_info->fs_devices->latest_bdev; for (pg_index = 0; pg_index < nr_pages; pg_index++) { cb->compressed_pages[pg_index] = alloc_page(GFP_NOFS | @@ -648,8 +650,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, add_ra_bio_pages(inode, em_start + em_len, cb); /* include any pages we added in add_ra-bio_pages */ - uncompressed_len = bio->bi_vcnt * PAGE_SIZE; - cb->len = uncompressed_len; + cb->len = bio->bi_iter.bi_size; comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); if (!comp_bio) @@ -676,8 +677,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, PAGE_SIZE) { bio_get(comp_bio); - ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, - BTRFS_WQ_ENDIO_DATA); + ret = btrfs_bio_wq_end_io(fs_info, comp_bio, + BTRFS_WQ_ENDIO_DATA); BUG_ON(ret); /* -ENOMEM */ /* @@ -689,14 +690,14 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, atomic_inc(&cb->pending_bios); if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { - ret = btrfs_lookup_bio_sums(root, inode, - comp_bio, sums); + ret = btrfs_lookup_bio_sums(inode, comp_bio, + sums); BUG_ON(ret); /* -ENOMEM */ } sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size, - root->sectorsize); + fs_info->sectorsize); - ret = btrfs_map_bio(root, comp_bio, mirror_num, 0); + ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); if (ret) { comp_bio->bi_error = ret; bio_endio(comp_bio); @@ -717,16 +718,15 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, } bio_get(comp_bio); - ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, - BTRFS_WQ_ENDIO_DATA); + ret = btrfs_bio_wq_end_io(fs_info, comp_bio, BTRFS_WQ_ENDIO_DATA); BUG_ON(ret); /* -ENOMEM */ if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { - ret = btrfs_lookup_bio_sums(root, inode, comp_bio, sums); + ret = btrfs_lookup_bio_sums(inode, comp_bio, sums); BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, comp_bio, mirror_num, 0); + ret = btrfs_map_bio(fs_info, comp_bio, mirror_num, 0); if (ret) { comp_bio->bi_error = ret; bio_endio(comp_bio); @@ -959,9 +959,7 @@ int btrfs_compress_pages(int type, struct address_space *mapping, * * disk_start is the starting logical offset of this array in the file * - * bvec is a bio_vec of pages from the file that we want to decompress into - * - * vcnt is the count of pages in the biovec + * orig_bio contains the pages from the file that we want to decompress into * * srclen is the number of bytes in pages_in * @@ -970,18 +968,18 @@ int btrfs_compress_pages(int type, struct address_space *mapping, * be contiguous. They all correspond to the range of bytes covered by * the compressed extent. */ -static int btrfs_decompress_biovec(int type, struct page **pages_in, - u64 disk_start, struct bio_vec *bvec, - int vcnt, size_t srclen) +static int btrfs_decompress_bio(int type, struct page **pages_in, + u64 disk_start, struct bio *orig_bio, + size_t srclen) { struct list_head *workspace; int ret; workspace = find_workspace(type); - ret = btrfs_compress_op[type-1]->decompress_biovec(workspace, pages_in, - disk_start, - bvec, vcnt, srclen); + ret = btrfs_compress_op[type-1]->decompress_bio(workspace, pages_in, + disk_start, orig_bio, + srclen); free_workspace(type, workspace); return ret; } @@ -1021,9 +1019,7 @@ void btrfs_exit_compress(void) */ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, unsigned long total_out, u64 disk_start, - struct bio_vec *bvec, int vcnt, - unsigned long *pg_index, - unsigned long *pg_offset) + struct bio *bio) { unsigned long buf_offset; unsigned long current_buf_start; @@ -1031,13 +1027,13 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, unsigned long working_bytes = total_out - buf_start; unsigned long bytes; char *kaddr; - struct page *page_out = bvec[*pg_index].bv_page; + struct bio_vec bvec = bio_iter_iovec(bio, bio->bi_iter); /* * start byte is the first byte of the page we're currently * copying into relative to the start of the compressed data. */ - start_byte = page_offset(page_out) - disk_start; + start_byte = page_offset(bvec.bv_page) - disk_start; /* we haven't yet hit data corresponding to this page */ if (total_out <= start_byte) @@ -1057,80 +1053,46 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, /* copy bytes from the working buffer into the pages */ while (working_bytes > 0) { - bytes = min(PAGE_SIZE - *pg_offset, - PAGE_SIZE - buf_offset); + bytes = min_t(unsigned long, bvec.bv_len, + PAGE_SIZE - buf_offset); bytes = min(bytes, working_bytes); - kaddr = kmap_atomic(page_out); - memcpy(kaddr + *pg_offset, buf + buf_offset, bytes); + + kaddr = kmap_atomic(bvec.bv_page); + memcpy(kaddr + bvec.bv_offset, buf + buf_offset, bytes); kunmap_atomic(kaddr); - flush_dcache_page(page_out); + flush_dcache_page(bvec.bv_page); - *pg_offset += bytes; buf_offset += bytes; working_bytes -= bytes; current_buf_start += bytes; /* check if we need to pick another page */ - if (*pg_offset == PAGE_SIZE) { - (*pg_index)++; - if (*pg_index >= vcnt) - return 0; + bio_advance(bio, bytes); + if (!bio->bi_iter.bi_size) + return 0; + bvec = bio_iter_iovec(bio, bio->bi_iter); - page_out = bvec[*pg_index].bv_page; - *pg_offset = 0; - start_byte = page_offset(page_out) - disk_start; + start_byte = page_offset(bvec.bv_page) - disk_start; - /* - * make sure our new page is covered by this - * working buffer - */ - if (total_out <= start_byte) - return 1; + /* + * make sure our new page is covered by this + * working buffer + */ + if (total_out <= start_byte) + return 1; - /* - * the next page in the biovec might not be adjacent - * to the last page, but it might still be found - * inside this working buffer. bump our offset pointer - */ - if (total_out > start_byte && - current_buf_start < start_byte) { - buf_offset = start_byte - buf_start; - working_bytes = total_out - start_byte; - current_buf_start = buf_start + buf_offset; - } + /* + * the next page in the biovec might not be adjacent + * to the last page, but it might still be found + * inside this working buffer. bump our offset pointer + */ + if (total_out > start_byte && + current_buf_start < start_byte) { + buf_offset = start_byte - buf_start; + working_bytes = total_out - start_byte; + current_buf_start = buf_start + buf_offset; } } return 1; } - -/* - * When uncompressing data, we need to make sure and zero any parts of - * the biovec that were not filled in by the decompression code. pg_index - * and pg_offset indicate the last page and the last offset of that page - * that have been filled in. This will zero everything remaining in the - * biovec. - */ -void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt, - unsigned long pg_index, - unsigned long pg_offset) -{ - while (pg_index < vcnt) { - struct page *page = bvec[pg_index].bv_page; - unsigned long off = bvec[pg_index].bv_offset; - unsigned long len = bvec[pg_index].bv_len; - - if (pg_offset < off) - pg_offset = off; - if (pg_offset < off + len) { - unsigned long bytes = off + len - pg_offset; - char *kaddr; - - kaddr = kmap_atomic(page); - memset(kaddr + pg_offset, 0, bytes); - kunmap_atomic(kaddr); - } - pg_index++; - pg_offset = 0; - } -} diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h index f49d8b8c0f00..09879579fbc8 100644 --- a/fs/btrfs/compression.h +++ b/fs/btrfs/compression.h @@ -34,9 +34,7 @@ int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page, unsigned long start_byte, size_t srclen, size_t destlen); int btrfs_decompress_buf2page(char *buf, unsigned long buf_start, unsigned long total_out, u64 disk_start, - struct bio_vec *bvec, int vcnt, - unsigned long *pg_index, - unsigned long *pg_offset); + struct bio *bio); int btrfs_submit_compressed_write(struct inode *inode, u64 start, unsigned long len, u64 disk_start, @@ -45,9 +43,6 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, unsigned long nr_pages); int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags); -void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt, - unsigned long pg_index, - unsigned long pg_offset); enum btrfs_compression_type { BTRFS_COMPRESS_NONE = 0, @@ -72,11 +67,10 @@ struct btrfs_compress_op { unsigned long *total_out, unsigned long max_out); - int (*decompress_biovec)(struct list_head *workspace, + int (*decompress_bio)(struct list_head *workspace, struct page **pages_in, u64 disk_start, - struct bio_vec *bvec, - int vcnt, + struct bio *orig_bio, size_t srclen); int (*decompress)(struct list_head *workspace, diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index f6ba165d3f81..a426dc822d4d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -32,10 +32,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *ins_key, struct btrfs_path *path, int data_size, int extend); static int push_node_left(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst, + struct btrfs_fs_info *fs_info, + struct extent_buffer *dst, struct extent_buffer *src, int empty); static int balance_node_right(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct extent_buffer *dst_buf, struct extent_buffer *src_buf); static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, @@ -212,21 +213,23 @@ static struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) */ static void add_root_to_dirty_list(struct btrfs_root *root) { + struct btrfs_fs_info *fs_info = root->fs_info; + if (test_bit(BTRFS_ROOT_DIRTY, &root->state) || !test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state)) return; - spin_lock(&root->fs_info->trans_lock); + spin_lock(&fs_info->trans_lock); if (!test_and_set_bit(BTRFS_ROOT_DIRTY, &root->state)) { /* Want the extent tree to be the last on the list */ if (root->objectid == BTRFS_EXTENT_TREE_OBJECTID) list_move_tail(&root->dirty_list, - &root->fs_info->dirty_cowonly_roots); + &fs_info->dirty_cowonly_roots); else list_move(&root->dirty_list, - &root->fs_info->dirty_cowonly_roots); + &fs_info->dirty_cowonly_roots); } - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); } /* @@ -239,13 +242,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, struct extent_buffer *buf, struct extent_buffer **cow_ret, u64 new_root_objectid) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *cow; int ret = 0; int level; struct btrfs_disk_key disk_key; WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && - trans->transid != root->fs_info->running_transaction->transid); + trans->transid != fs_info->running_transaction->transid); WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && trans->transid != root->last_trans); @@ -260,7 +264,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, if (IS_ERR(cow)) return PTR_ERR(cow); - copy_extent_buffer(cow, buf, 0, 0, cow->len); + copy_extent_buffer_full(cow, buf); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV); @@ -271,8 +275,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, else btrfs_set_header_owner(cow, new_root_objectid); - write_extent_buffer(cow, root->fs_info->fsid, btrfs_header_fsid(), - BTRFS_FSID_SIZE); + write_extent_buffer_fsid(cow, fs_info->fsid); WARN_ON(btrfs_header_generation(buf) > trans->transid); if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) @@ -978,6 +981,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, struct extent_buffer *cow, int *last_ref) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 refs; u64 owner; u64 flags; @@ -1002,14 +1006,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, */ if (btrfs_block_can_be_shared(root, buf)) { - ret = btrfs_lookup_extent_info(trans, root, buf->start, + ret = btrfs_lookup_extent_info(trans, fs_info, buf->start, btrfs_header_level(buf), 1, &refs, &flags); if (ret) return ret; if (refs == 0) { ret = -EROFS; - btrfs_handle_fs_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(fs_info, ret, NULL); return ret; } } else { @@ -1052,7 +1056,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, if (new_flags != 0) { int level = btrfs_header_level(buf); - ret = btrfs_set_disk_extent_flags(trans, root, + ret = btrfs_set_disk_extent_flags(trans, fs_info, buf->start, buf->len, new_flags, level, 0); @@ -1070,7 +1074,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ret = btrfs_dec_ref(trans, root, buf, 1); BUG_ON(ret); /* -ENOMEM */ } - clean_tree_block(trans, root->fs_info, buf); + clean_tree_block(trans, fs_info, buf); *last_ref = 1; } return 0; @@ -1095,6 +1099,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct extent_buffer **cow_ret, u64 search_start, u64 empty_size) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_disk_key disk_key; struct extent_buffer *cow; int level, ret; @@ -1108,7 +1113,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, btrfs_assert_tree_locked(buf); WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && - trans->transid != root->fs_info->running_transaction->transid); + trans->transid != fs_info->running_transaction->transid); WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && trans->transid != root->last_trans); @@ -1130,7 +1135,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, /* cow is set to blocking by btrfs_init_new_buffer */ - copy_extent_buffer(cow, buf, 0, 0, cow->len); + copy_extent_buffer_full(cow, buf); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV); @@ -1141,8 +1146,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, else btrfs_set_header_owner(cow, root->root_key.objectid); - write_extent_buffer(cow, root->fs_info->fsid, btrfs_header_fsid(), - BTRFS_FSID_SIZE); + write_extent_buffer_fsid(cow, fs_info->fsid); ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); if (ret) { @@ -1174,7 +1178,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, add_root_to_dirty_list(root); } else { WARN_ON(trans->transid != btrfs_header_generation(parent)); - tree_mod_log_insert_key(root->fs_info, parent, parent_slot, + tree_mod_log_insert_key(fs_info, parent, parent_slot, MOD_LOG_KEY_REPLACE, GFP_NOFS); btrfs_set_node_blockptr(parent, parent_slot, cow->start); @@ -1182,7 +1186,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, trans->transid); btrfs_mark_buffer_dirty(parent); if (last_ref) { - ret = tree_mod_log_free_eb(root->fs_info, buf); + ret = tree_mod_log_free_eb(fs_info, buf); if (ret) { btrfs_abort_transaction(trans, ret); return ret; @@ -1359,8 +1363,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { BUG_ON(tm->slot != 0); - eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start, - eb->len); + eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start); if (!eb_rewin) { btrfs_tree_read_unlock_blocking(eb); free_extent_buffer(eb); @@ -1388,7 +1391,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, btrfs_tree_read_lock(eb_rewin); __tree_mod_log_rewind(fs_info, eb_rewin, time_seq, tm); WARN_ON(btrfs_header_nritems(eb_rewin) > - BTRFS_NODEPTRS_PER_BLOCK(fs_info->tree_root)); + BTRFS_NODEPTRS_PER_BLOCK(fs_info)); return eb_rewin; } @@ -1403,6 +1406,7 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, static inline struct extent_buffer * get_old_root(struct btrfs_root *root, u64 time_seq) { + struct btrfs_fs_info *fs_info = root->fs_info; struct tree_mod_elem *tm; struct extent_buffer *eb = NULL; struct extent_buffer *eb_root; @@ -1412,7 +1416,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) u64 logical; eb_root = btrfs_read_lock_root_node(root); - tm = __tree_mod_log_oldest_root(root->fs_info, eb_root, time_seq); + tm = __tree_mod_log_oldest_root(fs_info, eb_root, time_seq); if (!tm) return eb_root; @@ -1424,16 +1428,17 @@ get_old_root(struct btrfs_root *root, u64 time_seq) logical = eb_root->start; } - tm = tree_mod_log_search(root->fs_info, logical, time_seq); + tm = tree_mod_log_search(fs_info, logical, time_seq); if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) { btrfs_tree_read_unlock(eb_root); free_extent_buffer(eb_root); - old = read_tree_block(root, logical, 0); + old = read_tree_block(fs_info, logical, 0); if (WARN_ON(IS_ERR(old) || !extent_buffer_uptodate(old))) { if (!IS_ERR(old)) free_extent_buffer(old); - btrfs_warn(root->fs_info, - "failed to read tree block %llu from get_old_root", logical); + btrfs_warn(fs_info, + "failed to read tree block %llu from get_old_root", + logical); } else { eb = btrfs_clone_extent_buffer(old); free_extent_buffer(old); @@ -1441,8 +1446,7 @@ get_old_root(struct btrfs_root *root, u64 time_seq) } else if (old_root) { btrfs_tree_read_unlock(eb_root); free_extent_buffer(eb_root); - eb = alloc_dummy_extent_buffer(root->fs_info, logical, - root->nodesize); + eb = alloc_dummy_extent_buffer(fs_info, logical); } else { btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); eb = btrfs_clone_extent_buffer(eb_root); @@ -1462,10 +1466,10 @@ get_old_root(struct btrfs_root *root, u64 time_seq) btrfs_set_header_generation(eb, old_generation); } if (tm) - __tree_mod_log_rewind(root->fs_info, eb, time_seq, tm); + __tree_mod_log_rewind(fs_info, eb, time_seq, tm); else WARN_ON(btrfs_header_level(eb) != 0); - WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); + WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(fs_info)); return eb; } @@ -1527,17 +1531,18 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, struct extent_buffer *parent, int parent_slot, struct extent_buffer **cow_ret) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 search_start; int ret; - if (trans->transaction != root->fs_info->running_transaction) + if (trans->transaction != fs_info->running_transaction) WARN(1, KERN_CRIT "trans %llu running %llu\n", trans->transid, - root->fs_info->running_transaction->transid); + fs_info->running_transaction->transid); - if (trans->transid != root->fs_info->generation) + if (trans->transid != fs_info->generation) WARN(1, KERN_CRIT "trans %llu running %llu\n", - trans->transid, root->fs_info->generation); + trans->transid, fs_info->generation); if (!should_cow_block(trans, root, buf)) { trans->dirty = true; @@ -1614,6 +1619,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, int start_slot, u64 *last_ret, struct btrfs_key *progress) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *cur; u64 blocknr; u64 gen; @@ -1632,11 +1638,11 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, parent_level = btrfs_header_level(parent); - WARN_ON(trans->transaction != root->fs_info->running_transaction); - WARN_ON(trans->transid != root->fs_info->generation); + WARN_ON(trans->transaction != fs_info->running_transaction); + WARN_ON(trans->transid != fs_info->generation); parent_nritems = btrfs_header_nritems(parent); - blocksize = root->nodesize; + blocksize = fs_info->nodesize; end_slot = parent_nritems - 1; if (parent_nritems <= 1) @@ -1670,14 +1676,14 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, continue; } - cur = btrfs_find_tree_block(root->fs_info, blocknr); + cur = find_extent_buffer(fs_info, blocknr); if (cur) uptodate = btrfs_buffer_uptodate(cur, gen, 0); else uptodate = 0; if (!cur || !uptodate) { if (!cur) { - cur = read_tree_block(root, blocknr, gen); + cur = read_tree_block(fs_info, blocknr, gen); if (IS_ERR(cur)) { return PTR_ERR(cur); } else if (!extent_buffer_uptodate(cur)) { @@ -1715,7 +1721,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, return err; } - /* * search for key in the extent_buffer. The items start at offset p, * and they are item_size apart. There are 'max' items in p. @@ -1839,8 +1844,9 @@ static void root_sub_used(struct btrfs_root *root, u32 size) /* given a node and slot number, this reads the blocks it points to. The * extent buffer is returned with a reference taken (but unlocked). */ -static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root, - struct extent_buffer *parent, int slot) +static noinline struct extent_buffer * +read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, + int slot) { int level = btrfs_header_level(parent); struct extent_buffer *eb; @@ -1850,7 +1856,7 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root, BUG_ON(level == 0); - eb = read_tree_block(root, btrfs_node_blockptr(parent, slot), + eb = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot), btrfs_node_ptr_generation(parent, slot)); if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) { free_extent_buffer(eb); @@ -1869,6 +1875,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *right = NULL; struct extent_buffer *mid; struct extent_buffer *left = NULL; @@ -1906,10 +1913,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, return 0; /* promote the child to a root */ - child = read_node_slot(root, mid, 0); + child = read_node_slot(fs_info, mid, 0); if (IS_ERR(child)) { ret = PTR_ERR(child); - btrfs_handle_fs_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(fs_info, ret, NULL); goto enospc; } @@ -1930,7 +1937,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, path->locks[level] = 0; path->nodes[level] = NULL; - clean_tree_block(trans, root->fs_info, mid); + clean_tree_block(trans, fs_info, mid); btrfs_tree_unlock(mid); /* once for the path */ free_extent_buffer(mid); @@ -1942,10 +1949,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, return 0; } if (btrfs_header_nritems(mid) > - BTRFS_NODEPTRS_PER_BLOCK(root) / 4) + BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 4) return 0; - left = read_node_slot(root, parent, pslot - 1); + left = read_node_slot(fs_info, parent, pslot - 1); if (IS_ERR(left)) left = NULL; @@ -1960,7 +1967,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } } - right = read_node_slot(root, parent, pslot + 1); + right = read_node_slot(fs_info, parent, pslot + 1); if (IS_ERR(right)) right = NULL; @@ -1978,7 +1985,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, /* first, try to make some room in the middle buffer */ if (left) { orig_slot += btrfs_header_nritems(left); - wret = push_node_left(trans, root, left, mid, 1); + wret = push_node_left(trans, fs_info, left, mid, 1); if (wret < 0) ret = wret; } @@ -1987,11 +1994,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, * then try to empty the right most buffer into the middle */ if (right) { - wret = push_node_left(trans, root, mid, right, 1); + wret = push_node_left(trans, fs_info, mid, right, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; if (btrfs_header_nritems(right) == 0) { - clean_tree_block(trans, root->fs_info, right); + clean_tree_block(trans, fs_info, right); btrfs_tree_unlock(right); del_ptr(root, path, level + 1, pslot + 1); root_sub_used(root, right->len); @@ -2001,7 +2008,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } else { struct btrfs_disk_key right_key; btrfs_node_key(right, &right_key, 0); - tree_mod_log_set_node_key(root->fs_info, parent, + tree_mod_log_set_node_key(fs_info, parent, pslot + 1, 0); btrfs_set_node_key(parent, &right_key, pslot + 1); btrfs_mark_buffer_dirty(parent); @@ -2019,23 +2026,23 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, */ if (!left) { ret = -EROFS; - btrfs_handle_fs_error(root->fs_info, ret, NULL); + btrfs_handle_fs_error(fs_info, ret, NULL); goto enospc; } - wret = balance_node_right(trans, root, mid, left); + wret = balance_node_right(trans, fs_info, mid, left); if (wret < 0) { ret = wret; goto enospc; } if (wret == 1) { - wret = push_node_left(trans, root, left, mid, 1); + wret = push_node_left(trans, fs_info, left, mid, 1); if (wret < 0) ret = wret; } BUG_ON(wret == 1); } if (btrfs_header_nritems(mid) == 0) { - clean_tree_block(trans, root->fs_info, mid); + clean_tree_block(trans, fs_info, mid); btrfs_tree_unlock(mid); del_ptr(root, path, level + 1, pslot); root_sub_used(root, mid->len); @@ -2046,8 +2053,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, /* update the parent key to reflect our changes */ struct btrfs_disk_key mid_key; btrfs_node_key(mid, &mid_key, 0); - tree_mod_log_set_node_key(root->fs_info, parent, - pslot, 0); + tree_mod_log_set_node_key(fs_info, parent, pslot, 0); btrfs_set_node_key(parent, &mid_key, pslot); btrfs_mark_buffer_dirty(parent); } @@ -2094,6 +2100,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *right = NULL; struct extent_buffer *mid; struct extent_buffer *left = NULL; @@ -2117,7 +2124,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, if (!parent) return 1; - left = read_node_slot(root, parent, pslot - 1); + left = read_node_slot(fs_info, parent, pslot - 1); if (IS_ERR(left)) left = NULL; @@ -2129,7 +2136,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, btrfs_set_lock_blocking(left); left_nr = btrfs_header_nritems(left); - if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { + if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { wret = 1; } else { ret = btrfs_cow_block(trans, root, left, parent, @@ -2137,7 +2144,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, if (ret) wret = 1; else { - wret = push_node_left(trans, root, + wret = push_node_left(trans, fs_info, left, mid, 0); } } @@ -2147,8 +2154,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; orig_slot += left_nr; btrfs_node_key(mid, &disk_key, 0); - tree_mod_log_set_node_key(root->fs_info, parent, - pslot, 0); + tree_mod_log_set_node_key(fs_info, parent, pslot, 0); btrfs_set_node_key(parent, &disk_key, pslot); btrfs_mark_buffer_dirty(parent); if (btrfs_header_nritems(left) > orig_slot) { @@ -2169,7 +2175,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, btrfs_tree_unlock(left); free_extent_buffer(left); } - right = read_node_slot(root, parent, pslot + 1); + right = read_node_slot(fs_info, parent, pslot + 1); if (IS_ERR(right)) right = NULL; @@ -2183,7 +2189,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, btrfs_set_lock_blocking(right); right_nr = btrfs_header_nritems(right); - if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { + if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { wret = 1; } else { ret = btrfs_cow_block(trans, root, right, @@ -2192,7 +2198,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, if (ret) wret = 1; else { - wret = balance_node_right(trans, root, + wret = balance_node_right(trans, fs_info, right, mid); } } @@ -2202,7 +2208,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; btrfs_node_key(right, &disk_key, 0); - tree_mod_log_set_node_key(root->fs_info, parent, + tree_mod_log_set_node_key(fs_info, parent, pslot + 1, 0); btrfs_set_node_key(parent, &disk_key, pslot + 1); btrfs_mark_buffer_dirty(parent); @@ -2230,7 +2236,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, * readahead one full node of leaves, finding things that are close * to the block in 'slot', and triggering ra on them. */ -static void reada_for_search(struct btrfs_root *root, +static void reada_for_search(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int level, int slot, u64 objectid) { @@ -2254,8 +2260,8 @@ static void reada_for_search(struct btrfs_root *root, node = path->nodes[level]; search = btrfs_node_blockptr(node, slot); - blocksize = root->nodesize; - eb = btrfs_find_tree_block(root->fs_info, search); + blocksize = fs_info->nodesize; + eb = find_extent_buffer(fs_info, search); if (eb) { free_extent_buffer(eb); return; @@ -2284,7 +2290,7 @@ static void reada_for_search(struct btrfs_root *root, search = btrfs_node_blockptr(node, nr); if ((search <= target && target - search <= 65536) || (search > target && search - target <= 65536)) { - readahead_tree_block(root, search); + readahead_tree_block(fs_info, search); nread += blocksize; } nscan++; @@ -2293,7 +2299,7 @@ static void reada_for_search(struct btrfs_root *root, } } -static noinline void reada_for_balance(struct btrfs_root *root, +static noinline void reada_for_balance(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int level) { int slot; @@ -2314,7 +2320,7 @@ static noinline void reada_for_balance(struct btrfs_root *root, if (slot > 0) { block1 = btrfs_node_blockptr(parent, slot - 1); gen = btrfs_node_ptr_generation(parent, slot - 1); - eb = btrfs_find_tree_block(root->fs_info, block1); + eb = find_extent_buffer(fs_info, block1); /* * if we get -eagain from btrfs_buffer_uptodate, we * don't want to return eagain here. That will loop @@ -2327,16 +2333,16 @@ static noinline void reada_for_balance(struct btrfs_root *root, if (slot + 1 < nritems) { block2 = btrfs_node_blockptr(parent, slot + 1); gen = btrfs_node_ptr_generation(parent, slot + 1); - eb = btrfs_find_tree_block(root->fs_info, block2); + eb = find_extent_buffer(fs_info, block2); if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0) block2 = 0; free_extent_buffer(eb); } if (block1) - readahead_tree_block(root, block1); + readahead_tree_block(fs_info, block1); if (block2) - readahead_tree_block(root, block2); + readahead_tree_block(fs_info, block2); } @@ -2436,6 +2442,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, struct extent_buffer **eb_ret, int level, int slot, struct btrfs_key *key, u64 time_seq) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 blocknr; u64 gen; struct extent_buffer *b = *eb_ret; @@ -2445,7 +2452,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, blocknr = btrfs_node_blockptr(b, slot); gen = btrfs_node_ptr_generation(b, slot); - tmp = btrfs_find_tree_block(root->fs_info, blocknr); + tmp = find_extent_buffer(fs_info, blocknr); if (tmp) { /* first we do an atomic uptodate check */ if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { @@ -2484,12 +2491,12 @@ read_block_for_search(struct btrfs_trans_handle *trans, free_extent_buffer(tmp); if (p->reada != READA_NONE) - reada_for_search(root, p, level, slot, key->objectid); + reada_for_search(fs_info, p, level, slot, key->objectid); btrfs_release_path(p); ret = -EAGAIN; - tmp = read_tree_block(root, blocknr, 0); + tmp = read_tree_block(fs_info, blocknr, 0); if (!IS_ERR(tmp)) { /* * If the read above didn't mark this buffer up to date, @@ -2521,9 +2528,11 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, struct extent_buffer *b, int level, int ins_len, int *write_lock_level) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; + if ((p->search_for_split || ins_len > 0) && btrfs_header_nritems(b) >= - BTRFS_NODEPTRS_PER_BLOCK(root) - 3) { + BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 3) { int sret; if (*write_lock_level < level + 1) { @@ -2533,7 +2542,7 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, } btrfs_set_path_blocking(p); - reada_for_balance(root, p, level); + reada_for_balance(fs_info, p, level); sret = split_node(trans, root, p, level); btrfs_clear_path_blocking(p, NULL, 0); @@ -2544,7 +2553,7 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, } b = p->nodes[level]; } else if (ins_len < 0 && btrfs_header_nritems(b) < - BTRFS_NODEPTRS_PER_BLOCK(root) / 2) { + BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 2) { int sret; if (*write_lock_level < level + 1) { @@ -2554,7 +2563,7 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, } btrfs_set_path_blocking(p); - reada_for_balance(root, p, level); + reada_for_balance(fs_info, p, level); sret = balance_level(trans, root, p, level); btrfs_clear_path_blocking(p, NULL, 0); @@ -2663,6 +2672,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, int ins_len, int cow) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *b; int slot; int ret; @@ -2718,12 +2728,12 @@ again: * so we always do read locks */ if (p->need_commit_sem) - down_read(&root->fs_info->commit_root_sem); + down_read(&fs_info->commit_root_sem); b = root->commit_root; extent_buffer_get(b); level = btrfs_header_level(b); if (p->need_commit_sem) - up_read(&root->fs_info->commit_root_sem); + up_read(&fs_info->commit_root_sem); if (!p->skip_locking) btrfs_tree_read_lock(b); } else { @@ -2895,7 +2905,7 @@ cow_done: } else { p->slots[level] = slot; if (ins_len > 0 && - btrfs_leaf_free_space(root, b) < ins_len) { + btrfs_leaf_free_space(fs_info, b) < ins_len) { if (write_lock_level < 1) { write_lock_level = 1; btrfs_release_path(p); @@ -2946,6 +2956,7 @@ done: int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_path *p, u64 time_seq) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *b; int slot; int ret; @@ -3020,7 +3031,7 @@ again: btrfs_clear_path_blocking(p, b, BTRFS_READ_LOCK); } - b = tree_mod_log_rewind(root->fs_info, p, b, time_seq); + b = tree_mod_log_rewind(fs_info, p, b, time_seq); if (!b) { ret = -ENOMEM; goto done; @@ -3187,7 +3198,8 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, * error, and > 0 if there was no room in the left hand block. */ static int push_node_left(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst, + struct btrfs_fs_info *fs_info, + struct extent_buffer *dst, struct extent_buffer *src, int empty) { int push_items = 0; @@ -3197,7 +3209,7 @@ static int push_node_left(struct btrfs_trans_handle *trans, src_nritems = btrfs_header_nritems(src); dst_nritems = btrfs_header_nritems(dst); - push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; + push_items = BTRFS_NODEPTRS_PER_BLOCK(fs_info) - dst_nritems; WARN_ON(btrfs_header_generation(src) != trans->transid); WARN_ON(btrfs_header_generation(dst) != trans->transid); @@ -3222,7 +3234,7 @@ static int push_node_left(struct btrfs_trans_handle *trans, } else push_items = min(src_nritems - 8, push_items); - ret = tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0, + ret = tree_mod_log_eb_copy(fs_info, dst, src, dst_nritems, 0, push_items); if (ret) { btrfs_abort_transaction(trans, ret); @@ -3261,7 +3273,7 @@ static int push_node_left(struct btrfs_trans_handle *trans, * this will only push up to 1/2 the contents of the left node over */ static int balance_node_right(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct extent_buffer *dst, struct extent_buffer *src) { @@ -3276,7 +3288,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, src_nritems = btrfs_header_nritems(src); dst_nritems = btrfs_header_nritems(dst); - push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; + push_items = BTRFS_NODEPTRS_PER_BLOCK(fs_info) - dst_nritems; if (push_items <= 0) return 1; @@ -3291,13 +3303,13 @@ static int balance_node_right(struct btrfs_trans_handle *trans, if (max_push < push_items) push_items = max_push; - tree_mod_log_eb_move(root->fs_info, dst, push_items, 0, dst_nritems); + tree_mod_log_eb_move(fs_info, dst, push_items, 0, dst_nritems); memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items), btrfs_node_key_ptr_offset(0), (dst_nritems) * sizeof(struct btrfs_key_ptr)); - ret = tree_mod_log_eb_copy(root->fs_info, dst, src, 0, + ret = tree_mod_log_eb_copy(fs_info, dst, src, 0, src_nritems - push_items, push_items); if (ret) { btrfs_abort_transaction(trans, ret); @@ -3328,6 +3340,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 lower_gen; struct extent_buffer *lower; struct extent_buffer *c; @@ -3348,9 +3361,9 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, if (IS_ERR(c)) return PTR_ERR(c); - root_add_used(root, root->nodesize); + root_add_used(root, fs_info->nodesize); - memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header)); + memzero_extent_buffer(c, 0, sizeof(struct btrfs_header)); btrfs_set_header_nritems(c, 1); btrfs_set_header_level(c, level); btrfs_set_header_bytenr(c, c->start); @@ -3358,11 +3371,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(c, root->root_key.objectid); - write_extent_buffer(c, root->fs_info->fsid, btrfs_header_fsid(), - BTRFS_FSID_SIZE); - - write_extent_buffer(c, root->fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(c), BTRFS_UUID_SIZE); + write_extent_buffer_fsid(c, fs_info->fsid); + write_extent_buffer_chunk_tree_uuid(c, fs_info->chunk_tree_uuid); btrfs_set_node_key(c, &lower_key, 0); btrfs_set_node_blockptr(c, 0, lower->start); @@ -3396,7 +3406,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, * blocknr is the block the key points to. */ static void insert_ptr(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct btrfs_path *path, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, struct btrfs_disk_key *key, u64 bytenr, int slot, int level) { @@ -3409,10 +3419,10 @@ static void insert_ptr(struct btrfs_trans_handle *trans, lower = path->nodes[level]; nritems = btrfs_header_nritems(lower); BUG_ON(slot > nritems); - BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root)); + BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(fs_info)); if (slot != nritems) { if (level) - tree_mod_log_eb_move(root->fs_info, lower, slot + 1, + tree_mod_log_eb_move(fs_info, lower, slot + 1, slot, nritems - slot); memmove_extent_buffer(lower, btrfs_node_key_ptr_offset(slot + 1), @@ -3420,7 +3430,7 @@ static void insert_ptr(struct btrfs_trans_handle *trans, (nritems - slot) * sizeof(struct btrfs_key_ptr)); } if (level) { - ret = tree_mod_log_insert_key(root->fs_info, lower, slot, + ret = tree_mod_log_insert_key(fs_info, lower, slot, MOD_LOG_KEY_ADD, GFP_NOFS); BUG_ON(ret < 0); } @@ -3445,6 +3455,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *c; struct extent_buffer *split; struct btrfs_disk_key disk_key; @@ -3472,7 +3483,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, ret = push_nodes_for_insert(trans, root, path, level); c = path->nodes[level]; if (!ret && btrfs_header_nritems(c) < - BTRFS_NODEPTRS_PER_BLOCK(root) - 3) + BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 3) return 0; if (ret < 0) return ret; @@ -3487,22 +3498,18 @@ static noinline int split_node(struct btrfs_trans_handle *trans, if (IS_ERR(split)) return PTR_ERR(split); - root_add_used(root, root->nodesize); + root_add_used(root, fs_info->nodesize); - memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header)); + memzero_extent_buffer(split, 0, sizeof(struct btrfs_header)); btrfs_set_header_level(split, btrfs_header_level(c)); btrfs_set_header_bytenr(split, split->start); btrfs_set_header_generation(split, trans->transid); btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(split, root->root_key.objectid); - write_extent_buffer(split, root->fs_info->fsid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - write_extent_buffer(split, root->fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(split), - BTRFS_UUID_SIZE); - - ret = tree_mod_log_eb_copy(root->fs_info, split, c, 0, - mid, c_nritems - mid); + write_extent_buffer_fsid(split, fs_info->fsid); + write_extent_buffer_chunk_tree_uuid(split, fs_info->chunk_tree_uuid); + + ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); if (ret) { btrfs_abort_transaction(trans, ret); return ret; @@ -3518,7 +3525,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(c); btrfs_mark_buffer_dirty(split); - insert_ptr(trans, root, path, &disk_key, split->start, + insert_ptr(trans, fs_info, path, &disk_key, split->start, path->slots[level + 1] + 1, level + 1); if (path->slots[level] >= mid) { @@ -3566,17 +3573,19 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr) * the start of the leaf data. IOW, how much room * the leaf has left for both items and data */ -noinline int btrfs_leaf_free_space(struct btrfs_root *root, +noinline int btrfs_leaf_free_space(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf) { int nritems = btrfs_header_nritems(leaf); int ret; - ret = BTRFS_LEAF_DATA_SIZE(root) - leaf_space_used(leaf, 0, nritems); + + ret = BTRFS_LEAF_DATA_SIZE(fs_info) - leaf_space_used(leaf, 0, nritems); if (ret < 0) { - btrfs_crit(root->fs_info, - "leaf free space ret %d, leaf data size %lu, used %d nritems %d", - ret, (unsigned long) BTRFS_LEAF_DATA_SIZE(root), - leaf_space_used(leaf, 0, nritems), nritems); + btrfs_crit(fs_info, + "leaf free space ret %d, leaf data size %lu, used %d nritems %d", + ret, + (unsigned long) BTRFS_LEAF_DATA_SIZE(fs_info), + leaf_space_used(leaf, 0, nritems), nritems); } return ret; } @@ -3586,7 +3595,7 @@ noinline int btrfs_leaf_free_space(struct btrfs_root *root, * right. We'll push up to and including min_slot, but no lower */ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, int data_size, int empty, struct extent_buffer *right, @@ -3626,7 +3635,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, if (path->slots[0] > i) break; if (path->slots[0] == i) { - int space = btrfs_leaf_free_space(root, left); + int space = btrfs_leaf_free_space(fs_info, left); if (space + push_space * 2 > free_space) break; } @@ -3655,19 +3664,19 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, right_nritems = btrfs_header_nritems(right); push_space = btrfs_item_end_nr(left, left_nritems - push_items); - push_space -= leaf_data_end(root, left); + push_space -= leaf_data_end(fs_info, left); /* make room in the right data area */ - data_end = leaf_data_end(root, right); + data_end = leaf_data_end(fs_info, right); memmove_extent_buffer(right, btrfs_leaf_data(right) + data_end - push_space, btrfs_leaf_data(right) + data_end, - BTRFS_LEAF_DATA_SIZE(root) - data_end); + BTRFS_LEAF_DATA_SIZE(fs_info) - data_end); /* copy from the left data area */ copy_extent_buffer(right, left, btrfs_leaf_data(right) + - BTRFS_LEAF_DATA_SIZE(root) - push_space, - btrfs_leaf_data(left) + leaf_data_end(root, left), + BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, + btrfs_leaf_data(left) + leaf_data_end(fs_info, left), push_space); memmove_extent_buffer(right, btrfs_item_nr_offset(push_items), @@ -3682,7 +3691,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, /* update the item pointers */ right_nritems += push_items; btrfs_set_header_nritems(right, right_nritems); - push_space = BTRFS_LEAF_DATA_SIZE(root); + push_space = BTRFS_LEAF_DATA_SIZE(fs_info); for (i = 0; i < right_nritems; i++) { item = btrfs_item_nr(i); push_space -= btrfs_token_item_size(right, item, &token); @@ -3695,7 +3704,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, if (left_nritems) btrfs_mark_buffer_dirty(left); else - clean_tree_block(trans, root->fs_info, left); + clean_tree_block(trans, fs_info, left); btrfs_mark_buffer_dirty(right); @@ -3707,7 +3716,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, if (path->slots[0] >= left_nritems) { path->slots[0] -= left_nritems; if (btrfs_header_nritems(path->nodes[0]) == 0) - clean_tree_block(trans, root->fs_info, path->nodes[0]); + clean_tree_block(trans, fs_info, path->nodes[0]); btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; @@ -3739,6 +3748,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root int min_data_size, int data_size, int empty, u32 min_slot) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *left = path->nodes[0]; struct extent_buffer *right; struct extent_buffer *upper; @@ -3757,7 +3767,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_assert_tree_locked(path->nodes[1]); - right = read_node_slot(root, upper, slot + 1); + right = read_node_slot(fs_info, upper, slot + 1); /* * slot + 1 is not valid or we fail to read the right node, * no big deal, just return. @@ -3768,7 +3778,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_tree_lock(right); btrfs_set_lock_blocking(right); - free_space = btrfs_leaf_free_space(root, right); + free_space = btrfs_leaf_free_space(fs_info, right); if (free_space < data_size) goto out_unlock; @@ -3778,7 +3788,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root if (ret) goto out_unlock; - free_space = btrfs_leaf_free_space(root, right); + free_space = btrfs_leaf_free_space(fs_info, right); if (free_space < data_size) goto out_unlock; @@ -3799,7 +3809,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root return 0; } - return __push_leaf_right(trans, root, path, min_data_size, empty, + return __push_leaf_right(trans, fs_info, path, min_data_size, empty, right, free_space, left_nritems, min_slot); out_unlock: btrfs_tree_unlock(right); @@ -3816,7 +3826,7 @@ out_unlock: * items */ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, int data_size, int empty, struct extent_buffer *left, int free_space, u32 right_nritems, @@ -3849,7 +3859,7 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, if (path->slots[0] < i) break; if (path->slots[0] == i) { - int space = btrfs_leaf_free_space(root, right); + int space = btrfs_leaf_free_space(fs_info, right); if (space + push_space * 2 > free_space) break; } @@ -3878,11 +3888,11 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, btrfs_item_nr_offset(0), push_items * sizeof(struct btrfs_item)); - push_space = BTRFS_LEAF_DATA_SIZE(root) - + push_space = BTRFS_LEAF_DATA_SIZE(fs_info) - btrfs_item_offset_nr(right, push_items - 1); copy_extent_buffer(left, right, btrfs_leaf_data(left) + - leaf_data_end(root, left) - push_space, + leaf_data_end(fs_info, left) - push_space, btrfs_leaf_data(right) + btrfs_item_offset_nr(right, push_items - 1), push_space); @@ -3897,7 +3907,7 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, ioff = btrfs_token_item_offset(left, item, &token); btrfs_set_token_item_offset(left, item, - ioff - (BTRFS_LEAF_DATA_SIZE(root) - old_left_item_size), + ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size), &token); } btrfs_set_header_nritems(left, old_left_nritems + push_items); @@ -3909,11 +3919,11 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, if (push_items < right_nritems) { push_space = btrfs_item_offset_nr(right, push_items - 1) - - leaf_data_end(root, right); + leaf_data_end(fs_info, right); memmove_extent_buffer(right, btrfs_leaf_data(right) + - BTRFS_LEAF_DATA_SIZE(root) - push_space, + BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, btrfs_leaf_data(right) + - leaf_data_end(root, right), push_space); + leaf_data_end(fs_info, right), push_space); memmove_extent_buffer(right, btrfs_item_nr_offset(0), btrfs_item_nr_offset(push_items), @@ -3922,7 +3932,7 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, } right_nritems -= push_items; btrfs_set_header_nritems(right, right_nritems); - push_space = BTRFS_LEAF_DATA_SIZE(root); + push_space = BTRFS_LEAF_DATA_SIZE(fs_info); for (i = 0; i < right_nritems; i++) { item = btrfs_item_nr(i); @@ -3935,10 +3945,10 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, if (right_nritems) btrfs_mark_buffer_dirty(right); else - clean_tree_block(trans, root->fs_info, right); + clean_tree_block(trans, fs_info, right); btrfs_item_key(right, &disk_key, 0); - fixup_low_keys(root->fs_info, path, &disk_key, 1); + fixup_low_keys(fs_info, path, &disk_key, 1); /* then fixup the leaf pointer in the path */ if (path->slots[0] < push_items) { @@ -3972,6 +3982,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int min_data_size, int data_size, int empty, u32 max_slot) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *right = path->nodes[0]; struct extent_buffer *left; int slot; @@ -3991,7 +4002,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_assert_tree_locked(path->nodes[1]); - left = read_node_slot(root, path->nodes[1], slot - 1); + left = read_node_slot(fs_info, path->nodes[1], slot - 1); /* * slot - 1 is not valid or we fail to read the left node, * no big deal, just return. @@ -4002,7 +4013,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_tree_lock(left); btrfs_set_lock_blocking(left); - free_space = btrfs_leaf_free_space(root, left); + free_space = btrfs_leaf_free_space(fs_info, left); if (free_space < data_size) { ret = 1; goto out; @@ -4018,13 +4029,13 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root goto out; } - free_space = btrfs_leaf_free_space(root, left); + free_space = btrfs_leaf_free_space(fs_info, left); if (free_space < data_size) { ret = 1; goto out; } - return __push_leaf_left(trans, root, path, min_data_size, + return __push_leaf_left(trans, fs_info, path, min_data_size, empty, left, free_space, right_nritems, max_slot); out: @@ -4038,7 +4049,7 @@ out: * available for the resulting leaf level of the path. */ static noinline void copy_for_split(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, struct extent_buffer *l, struct extent_buffer *right, @@ -4054,19 +4065,18 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, nritems = nritems - mid; btrfs_set_header_nritems(right, nritems); - data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(root, l); + data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(fs_info, l); copy_extent_buffer(right, l, btrfs_item_nr_offset(0), btrfs_item_nr_offset(mid), nritems * sizeof(struct btrfs_item)); copy_extent_buffer(right, l, - btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - + btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(fs_info) - data_copy_size, btrfs_leaf_data(l) + - leaf_data_end(root, l), data_copy_size); + leaf_data_end(fs_info, l), data_copy_size); - rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - - btrfs_item_end_nr(l, mid); + rt_data_off = BTRFS_LEAF_DATA_SIZE(fs_info) - btrfs_item_end_nr(l, mid); for (i = 0; i < nritems; i++) { struct btrfs_item *item = btrfs_item_nr(i); @@ -4079,7 +4089,7 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans, btrfs_set_header_nritems(l, mid); btrfs_item_key(right, &disk_key, 0); - insert_ptr(trans, root, path, &disk_key, right->start, + insert_ptr(trans, fs_info, path, &disk_key, right->start, path->slots[1] + 1, 1); btrfs_mark_buffer_dirty(right); @@ -4115,6 +4125,7 @@ static noinline int push_for_double_split(struct btrfs_trans_handle *trans, struct btrfs_path *path, int data_size) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; int progress = 0; int slot; @@ -4123,7 +4134,7 @@ static noinline int push_for_double_split(struct btrfs_trans_handle *trans, slot = path->slots[0]; if (slot < btrfs_header_nritems(path->nodes[0])) - space_needed -= btrfs_leaf_free_space(root, path->nodes[0]); + space_needed -= btrfs_leaf_free_space(fs_info, path->nodes[0]); /* * try to push all the items after our slot into the @@ -4144,7 +4155,7 @@ static noinline int push_for_double_split(struct btrfs_trans_handle *trans, if (path->slots[0] == 0 || path->slots[0] == nritems) return 0; - if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) + if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= data_size) return 0; /* try to push all the items before our slot into the next leaf */ @@ -4189,7 +4200,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, l = path->nodes[0]; slot = path->slots[0]; if (extend && data_size + btrfs_item_size_nr(l, slot) + - sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root)) + sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(fs_info)) return -EOVERFLOW; /* first try to make some room by pushing left and right */ @@ -4197,7 +4208,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, int space_needed = data_size; if (slot < btrfs_header_nritems(l)) - space_needed -= btrfs_leaf_free_space(root, l); + space_needed -= btrfs_leaf_free_space(fs_info, l); wret = push_leaf_right(trans, root, path, space_needed, space_needed, 0, 0); @@ -4212,7 +4223,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, l = path->nodes[0]; /* did the pushes work? */ - if (btrfs_leaf_free_space(root, l) >= data_size) + if (btrfs_leaf_free_space(fs_info, l) >= data_size) return 0; } @@ -4231,14 +4242,14 @@ again: if (mid <= slot) { if (nritems == 1 || leaf_space_used(l, mid, nritems - mid) + data_size > - BTRFS_LEAF_DATA_SIZE(root)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { if (slot >= nritems) { split = 0; } else { mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - data_size > BTRFS_LEAF_DATA_SIZE(root)) { + data_size > BTRFS_LEAF_DATA_SIZE(fs_info)) { if (data_size && !tried_avoid_double) goto push_for_double; split = 2; @@ -4247,7 +4258,7 @@ again: } } else { if (leaf_space_used(l, 0, mid) + data_size > - BTRFS_LEAF_DATA_SIZE(root)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { if (!extend && data_size && slot == 0) { split = 0; } else if ((extend || !data_size) && slot == 0) { @@ -4256,7 +4267,7 @@ again: mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - data_size > BTRFS_LEAF_DATA_SIZE(root)) { + data_size > BTRFS_LEAF_DATA_SIZE(fs_info)) { if (data_size && !tried_avoid_double) goto push_for_double; split = 2; @@ -4275,26 +4286,22 @@ again: if (IS_ERR(right)) return PTR_ERR(right); - root_add_used(root, root->nodesize); + root_add_used(root, fs_info->nodesize); - memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); + memzero_extent_buffer(right, 0, sizeof(struct btrfs_header)); btrfs_set_header_bytenr(right, right->start); btrfs_set_header_generation(right, trans->transid); btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(right, root->root_key.objectid); btrfs_set_header_level(right, 0); - write_extent_buffer(right, fs_info->fsid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - - write_extent_buffer(right, fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(right), - BTRFS_UUID_SIZE); + write_extent_buffer_fsid(right, fs_info->fsid); + write_extent_buffer_chunk_tree_uuid(right, fs_info->chunk_tree_uuid); if (split == 0) { if (mid <= slot) { btrfs_set_header_nritems(right, 0); - insert_ptr(trans, root, path, &disk_key, right->start, - path->slots[1] + 1, 1); + insert_ptr(trans, fs_info, path, &disk_key, + right->start, path->slots[1] + 1, 1); btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; @@ -4302,8 +4309,8 @@ again: path->slots[1] += 1; } else { btrfs_set_header_nritems(right, 0); - insert_ptr(trans, root, path, &disk_key, right->start, - path->slots[1], 1); + insert_ptr(trans, fs_info, path, &disk_key, + right->start, path->slots[1], 1); btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; @@ -4319,7 +4326,7 @@ again: return ret; } - copy_for_split(trans, root, path, l, right, slot, mid, nritems); + copy_for_split(trans, fs_info, path, l, right, slot, mid, nritems); if (split == 2) { BUG_ON(num_doubles != 0); @@ -4332,7 +4339,7 @@ again: push_for_double: push_for_double_split(trans, root, path, data_size); tried_avoid_double = 1; - if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) + if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= data_size) return 0; goto again; } @@ -4341,6 +4348,7 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int ins_len) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; @@ -4354,7 +4362,7 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && key.type != BTRFS_EXTENT_CSUM_KEY); - if (btrfs_leaf_free_space(root, leaf) >= ins_len) + if (btrfs_leaf_free_space(fs_info, leaf) >= ins_len) return 0; item_size = btrfs_item_size_nr(leaf, path->slots[0]); @@ -4381,7 +4389,7 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, goto err; /* the leaf has changed, it now has room. return now */ - if (btrfs_leaf_free_space(root, path->nodes[0]) >= ins_len) + if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= ins_len) goto err; if (key.type == BTRFS_EXTENT_DATA_KEY) { @@ -4405,7 +4413,7 @@ err: } static noinline int split_item(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, struct btrfs_key *new_key, unsigned long split_offset) @@ -4421,7 +4429,7 @@ static noinline int split_item(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; leaf = path->nodes[0]; - BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); + BUG_ON(btrfs_leaf_free_space(fs_info, leaf) < sizeof(struct btrfs_item)); btrfs_set_path_blocking(path); @@ -4470,7 +4478,7 @@ static noinline int split_item(struct btrfs_trans_handle *trans, item_size - split_offset); btrfs_mark_buffer_dirty(leaf); - BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); + BUG_ON(btrfs_leaf_free_space(fs_info, leaf) < 0); kfree(buf); return 0; } @@ -4502,7 +4510,7 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, if (ret) return ret; - ret = split_item(trans, root, path, new_key, split_offset); + ret = split_item(trans, root->fs_info, path, new_key, split_offset); return ret; } @@ -4548,8 +4556,8 @@ int btrfs_duplicate_item(struct btrfs_trans_handle *trans, * off the end of the item or if we shift the item to chop bytes off * the front. */ -void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, - u32 new_size, int from_end) +void btrfs_truncate_item(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, u32 new_size, int from_end) { int slot; struct extent_buffer *leaf; @@ -4572,7 +4580,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, return; nritems = btrfs_header_nritems(leaf); - data_end = leaf_data_end(root, leaf); + data_end = leaf_data_end(fs_info, leaf); old_data_start = btrfs_item_offset_nr(leaf, slot); @@ -4631,15 +4639,15 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, btrfs_set_disk_key_offset(&disk_key, offset + size_diff); btrfs_set_item_key(leaf, &disk_key, slot); if (slot == 0) - fixup_low_keys(root->fs_info, path, &disk_key, 1); + fixup_low_keys(fs_info, path, &disk_key, 1); } item = btrfs_item_nr(slot); btrfs_set_item_size(leaf, item, new_size); btrfs_mark_buffer_dirty(leaf); - if (btrfs_leaf_free_space(root, leaf) < 0) { - btrfs_print_leaf(root, leaf); + if (btrfs_leaf_free_space(fs_info, leaf) < 0) { + btrfs_print_leaf(fs_info, leaf); BUG(); } } @@ -4647,7 +4655,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, /* * make the item pointed to by the path bigger, data_size is the added size. */ -void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, +void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path, u32 data_size) { int slot; @@ -4665,10 +4673,10 @@ void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, leaf = path->nodes[0]; nritems = btrfs_header_nritems(leaf); - data_end = leaf_data_end(root, leaf); + data_end = leaf_data_end(fs_info, leaf); - if (btrfs_leaf_free_space(root, leaf) < data_size) { - btrfs_print_leaf(root, leaf); + if (btrfs_leaf_free_space(fs_info, leaf) < data_size) { + btrfs_print_leaf(fs_info, leaf); BUG(); } slot = path->slots[0]; @@ -4676,9 +4684,9 @@ void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, BUG_ON(slot < 0); if (slot >= nritems) { - btrfs_print_leaf(root, leaf); - btrfs_crit(root->fs_info, "slot %d too large, nritems %d", - slot, nritems); + btrfs_print_leaf(fs_info, leaf); + btrfs_crit(fs_info, "slot %d too large, nritems %d", + slot, nritems); BUG_ON(1); } @@ -4706,8 +4714,8 @@ void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, btrfs_set_item_size(leaf, item, old_size + data_size); btrfs_mark_buffer_dirty(leaf); - if (btrfs_leaf_free_space(root, leaf) < 0) { - btrfs_print_leaf(root, leaf); + if (btrfs_leaf_free_space(fs_info, leaf) < 0) { + btrfs_print_leaf(fs_info, leaf); BUG(); } } @@ -4721,6 +4729,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *cpu_key, u32 *data_size, u32 total_data, u32 total_size, int nr) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_item *item; int i; u32 nritems; @@ -4732,7 +4741,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, if (path->slots[0] == 0) { btrfs_cpu_key_to_disk(&disk_key, cpu_key); - fixup_low_keys(root->fs_info, path, &disk_key, 1); + fixup_low_keys(fs_info, path, &disk_key, 1); } btrfs_unlock_up_safe(path, 1); @@ -4742,13 +4751,12 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, slot = path->slots[0]; nritems = btrfs_header_nritems(leaf); - data_end = leaf_data_end(root, leaf); + data_end = leaf_data_end(fs_info, leaf); - if (btrfs_leaf_free_space(root, leaf) < total_size) { - btrfs_print_leaf(root, leaf); - btrfs_crit(root->fs_info, - "not enough freespace need %u have %d", - total_size, btrfs_leaf_free_space(root, leaf)); + if (btrfs_leaf_free_space(fs_info, leaf) < total_size) { + btrfs_print_leaf(fs_info, leaf); + btrfs_crit(fs_info, "not enough freespace need %u have %d", + total_size, btrfs_leaf_free_space(fs_info, leaf)); BUG(); } @@ -4756,9 +4764,8 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, unsigned int old_data = btrfs_item_end_nr(leaf, slot); if (old_data < data_end) { - btrfs_print_leaf(root, leaf); - btrfs_crit(root->fs_info, - "slot %d old_data %d data_end %d", + btrfs_print_leaf(fs_info, leaf); + btrfs_crit(fs_info, "slot %d old_data %d data_end %d", slot, old_data, data_end); BUG_ON(1); } @@ -4800,8 +4807,8 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, btrfs_set_header_nritems(leaf, nritems + nr); btrfs_mark_buffer_dirty(leaf); - if (btrfs_leaf_free_space(root, leaf) < 0) { - btrfs_print_leaf(root, leaf); + if (btrfs_leaf_free_space(fs_info, leaf) < 0) { + btrfs_print_leaf(fs_info, leaf); BUG(); } } @@ -4876,6 +4883,7 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *parent = path->nodes[level]; u32 nritems; int ret; @@ -4883,7 +4891,7 @@ static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, nritems = btrfs_header_nritems(parent); if (slot != nritems - 1) { if (level) - tree_mod_log_eb_move(root->fs_info, parent, slot, + tree_mod_log_eb_move(fs_info, parent, slot, slot + 1, nritems - slot - 1); memmove_extent_buffer(parent, btrfs_node_key_ptr_offset(slot), @@ -4891,7 +4899,7 @@ static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, sizeof(struct btrfs_key_ptr) * (nritems - slot - 1)); } else if (level) { - ret = tree_mod_log_insert_key(root->fs_info, parent, slot, + ret = tree_mod_log_insert_key(fs_info, parent, slot, MOD_LOG_KEY_REMOVE, GFP_NOFS); BUG_ON(ret < 0); } @@ -4906,7 +4914,7 @@ static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_disk_key disk_key; btrfs_node_key(parent, &disk_key, 0); - fixup_low_keys(root->fs_info, path, &disk_key, level + 1); + fixup_low_keys(fs_info, path, &disk_key, level + 1); } btrfs_mark_buffer_dirty(parent); } @@ -4948,6 +4956,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans, int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *leaf; struct btrfs_item *item; u32 last_off; @@ -4969,7 +4978,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, nritems = btrfs_header_nritems(leaf); if (slot + nr != nritems) { - int data_end = leaf_data_end(root, leaf); + int data_end = leaf_data_end(fs_info, leaf); memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + data_end + dsize, @@ -4999,7 +5008,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, btrfs_set_header_level(leaf, 0); } else { btrfs_set_path_blocking(path); - clean_tree_block(trans, root->fs_info, leaf); + clean_tree_block(trans, fs_info, leaf); btrfs_del_leaf(trans, root, path, leaf); } } else { @@ -5008,11 +5017,11 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_disk_key disk_key; btrfs_item_key(leaf, &disk_key, 0); - fixup_low_keys(root->fs_info, path, &disk_key, 1); + fixup_low_keys(fs_info, path, &disk_key, 1); } /* delete the leaf if it is mostly empty */ - if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { + if (used < BTRFS_LEAF_DATA_SIZE(fs_info) / 3) { /* push_leaf_left fixes the path. * make sure the path still points to our leaf * for possible call to del_ptr below @@ -5132,6 +5141,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, struct btrfs_path *path, u64 min_trans) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *cur; struct btrfs_key found_key; int slot; @@ -5208,7 +5218,7 @@ find_next_key: goto out; } btrfs_set_path_blocking(path); - cur = read_node_slot(root, cur, slot); + cur = read_node_slot(fs_info, cur, slot); if (IS_ERR(cur)) { ret = PTR_ERR(cur); goto out; @@ -5231,14 +5241,14 @@ out: return ret; } -static int tree_move_down(struct btrfs_root *root, +static int tree_move_down(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int *level, int root_level) { struct extent_buffer *eb; BUG_ON(*level == 0); - eb = read_node_slot(root, path->nodes[*level], path->slots[*level]); + eb = read_node_slot(fs_info, path->nodes[*level], path->slots[*level]); if (IS_ERR(eb)) return PTR_ERR(eb); @@ -5248,7 +5258,7 @@ static int tree_move_down(struct btrfs_root *root, return 0; } -static int tree_move_next_or_upnext(struct btrfs_root *root, +static int tree_move_next_or_upnext(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int *level, int root_level) { @@ -5279,7 +5289,7 @@ static int tree_move_next_or_upnext(struct btrfs_root *root, * Returns 1 if it had to move up and next. 0 is returned if it moved only next * or down. */ -static int tree_advance(struct btrfs_root *root, +static int tree_advance(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int *level, int root_level, int allow_down, @@ -5288,9 +5298,10 @@ static int tree_advance(struct btrfs_root *root, int ret; if (*level == 0 || !allow_down) { - ret = tree_move_next_or_upnext(root, path, level, root_level); + ret = tree_move_next_or_upnext(fs_info, path, level, + root_level); } else { - ret = tree_move_down(root, path, level, root_level); + ret = tree_move_down(fs_info, path, level, root_level); } if (ret >= 0) { if (*level == 0) @@ -5303,8 +5314,7 @@ static int tree_advance(struct btrfs_root *root, return ret; } -static int tree_compare_item(struct btrfs_root *left_root, - struct btrfs_path *left_path, +static int tree_compare_item(struct btrfs_path *left_path, struct btrfs_path *right_path, char *tmp_buf) { @@ -5349,6 +5359,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, struct btrfs_root *right_root, btrfs_changed_cb_t changed_cb, void *ctx) { + struct btrfs_fs_info *fs_info = left_root->fs_info; int ret; int cmp; struct btrfs_path *left_path = NULL; @@ -5380,9 +5391,9 @@ int btrfs_compare_trees(struct btrfs_root *left_root, goto out; } - tmp_buf = kmalloc(left_root->nodesize, GFP_KERNEL | __GFP_NOWARN); + tmp_buf = kmalloc(fs_info->nodesize, GFP_KERNEL | __GFP_NOWARN); if (!tmp_buf) { - tmp_buf = vmalloc(left_root->nodesize); + tmp_buf = vmalloc(fs_info->nodesize); if (!tmp_buf) { ret = -ENOMEM; goto out; @@ -5430,7 +5441,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, * the right if possible or go up and right. */ - down_read(&left_root->fs_info->commit_root_sem); + down_read(&fs_info->commit_root_sem); left_level = btrfs_header_level(left_root->commit_root); left_root_level = left_level; left_path->nodes[left_level] = left_root->commit_root; @@ -5440,7 +5451,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, right_root_level = right_level; right_path->nodes[right_level] = right_root->commit_root; extent_buffer_get(right_path->nodes[right_level]); - up_read(&left_root->fs_info->commit_root_sem); + up_read(&fs_info->commit_root_sem); if (left_level == 0) btrfs_item_key_to_cpu(left_path->nodes[left_level], @@ -5460,7 +5471,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, while (1) { if (advance_left && !left_end_reached) { - ret = tree_advance(left_root, left_path, &left_level, + ret = tree_advance(fs_info, left_path, &left_level, left_root_level, advance_left != ADVANCE_ONLY_NEXT, &left_key); @@ -5471,7 +5482,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, advance_left = 0; } if (advance_right && !right_end_reached) { - ret = tree_advance(right_root, right_path, &right_level, + ret = tree_advance(fs_info, right_path, &right_level, right_root_level, advance_right != ADVANCE_ONLY_NEXT, &right_key); @@ -5535,8 +5546,8 @@ int btrfs_compare_trees(struct btrfs_root *left_root, enum btrfs_compare_tree_result result; WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); - ret = tree_compare_item(left_root, left_path, - right_path, tmp_buf); + ret = tree_compare_item(left_path, right_path, + tmp_buf); if (ret) result = BTRFS_COMPARE_TREE_CHANGED; else diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0b8ce2b9f7d0..6a823719b6c5 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -90,9 +90,6 @@ static const int btrfs_csum_sizes[] = { 4 }; /* four bytes for CRC32 */ #define BTRFS_EMPTY_DIR_SIZE 0 -/* specific to btrfs_map_block(), therefore not in include/linux/blk_types.h */ -#define REQ_GET_READ_MIRRORS (1 << 30) - /* ioprio of readahead is set to idle */ #define BTRFS_IOPRIO_READA (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)) @@ -340,7 +337,7 @@ struct btrfs_path { unsigned int need_commit_sem:1; unsigned int skip_release_on_error:1; }; -#define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r) >> 4) - \ +#define BTRFS_MAX_EXTENT_ITEM_SIZE(r) ((BTRFS_LEAF_DATA_SIZE(r->fs_info) >> 4) - \ sizeof(struct btrfs_item)) struct btrfs_dev_replace { u64 replace_state; /* see #define above */ @@ -429,6 +426,10 @@ struct btrfs_space_info { struct list_head ro_bgs; struct list_head priority_tickets; struct list_head tickets; + /* + * tickets_id just indicates the next ticket will be handled, so note + * it's not stored per ticket. + */ u64 tickets_id; struct rw_semaphore groups_sem; @@ -518,7 +519,7 @@ struct btrfs_io_ctl { void *cur, *orig; struct page *page; struct page **pages; - struct btrfs_root *root; + struct btrfs_fs_info *fs_info; struct inode *inode; unsigned long size; int index; @@ -798,7 +799,6 @@ struct btrfs_fs_info { spinlock_t super_lock; struct btrfs_super_block *super_copy; struct btrfs_super_block *super_for_commit; - struct block_device *__bdev; struct super_block *sb; struct inode *btree_inode; struct backing_dev_info bdi; @@ -1084,8 +1084,18 @@ struct btrfs_fs_info { /* Used to record internally whether fs has been frozen */ int fs_frozen; + + /* Cached block sizes */ + u32 nodesize; + u32 sectorsize; + u32 stripesize; }; +static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb) +{ + return sb->s_fs_info; +} + struct btrfs_subvolume_writers { struct percpu_counter counter; wait_queue_head_t wait; @@ -1159,14 +1169,6 @@ struct btrfs_root { u64 objectid; u64 last_trans; - /* data allocations are done in sectorsize units */ - u32 sectorsize; - - /* node allocations are done in nodesize units */ - u32 nodesize; - - u32 stripesize; - u32 type; u64 highest_objectid; @@ -1250,38 +1252,42 @@ struct btrfs_root { /* For qgroup metadata space reserve */ atomic_t qgroup_meta_rsv; }; +static inline u32 btrfs_inode_sectorsize(const struct inode *inode) +{ + return btrfs_sb(inode->i_sb)->sectorsize; +} static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 blocksize) { return blocksize - sizeof(struct btrfs_header); } -static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_root *root) +static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info) { - return __BTRFS_LEAF_DATA_SIZE(root->nodesize); + return __BTRFS_LEAF_DATA_SIZE(info->nodesize); } -static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_root *root) +static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_fs_info *info) { - return BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item); + return BTRFS_LEAF_DATA_SIZE(info) - sizeof(struct btrfs_item); } -static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_root *root) +static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_fs_info *info) { - return BTRFS_LEAF_DATA_SIZE(root) / sizeof(struct btrfs_key_ptr); + return BTRFS_LEAF_DATA_SIZE(info) / sizeof(struct btrfs_key_ptr); } #define BTRFS_FILE_EXTENT_INLINE_DATA_START \ (offsetof(struct btrfs_file_extent_item, disk_bytenr)) -static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_root *root) +static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_fs_info *info) { - return BTRFS_MAX_ITEM_SIZE(root) - + return BTRFS_MAX_ITEM_SIZE(info) - BTRFS_FILE_EXTENT_INLINE_DATA_START; } -static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_root *root) +static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_fs_info *info) { - return BTRFS_MAX_ITEM_SIZE(root) - sizeof(struct btrfs_dir_item); + return BTRFS_MAX_ITEM_SIZE(info) - sizeof(struct btrfs_dir_item); } /* @@ -1343,12 +1349,13 @@ static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_root *root) #ifdef CONFIG_BTRFS_DEBUG static inline int -btrfs_should_fragment_free_space(struct btrfs_root *root, - struct btrfs_block_group_cache *block_group) +btrfs_should_fragment_free_space(struct btrfs_block_group_cache *block_group) { - return (btrfs_test_opt(root->fs_info, FRAGMENT_METADATA) && + struct btrfs_fs_info *fs_info = block_group->fs_info; + + return (btrfs_test_opt(fs_info, FRAGMENT_METADATA) && block_group->flags & BTRFS_BLOCK_GROUP_METADATA) || - (btrfs_test_opt(root->fs_info, FRAGMENT_DATA) && + (btrfs_test_opt(fs_info, FRAGMENT_DATA) && block_group->flags & BTRFS_BLOCK_GROUP_DATA); } #endif @@ -2210,6 +2217,8 @@ btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu, cpu->target = le64_to_cpu(disk->target); cpu->flags = le64_to_cpu(disk->flags); cpu->limit = le64_to_cpu(disk->limit); + cpu->stripes_min = le32_to_cpu(disk->stripes_min); + cpu->stripes_max = le32_to_cpu(disk->stripes_max); } static inline void @@ -2228,6 +2237,8 @@ btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk, disk->target = cpu_to_le64(cpu->target); disk->flags = cpu_to_le64(cpu->flags); disk->limit = cpu_to_le64(cpu->limit); + disk->stripes_min = cpu_to_le32(cpu->stripes_min); + disk->stripes_max = cpu_to_le32(cpu->stripes_max); } /* struct btrfs_super_block */ @@ -2299,13 +2310,13 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l) * this returns the address of the start of the last item, * which is the stop of the leaf data stack */ -static inline unsigned int leaf_data_end(struct btrfs_root *root, +static inline unsigned int leaf_data_end(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf) { u32 nr = btrfs_header_nritems(leaf); if (nr == 0) - return BTRFS_LEAF_DATA_SIZE(root); + return BTRFS_LEAF_DATA_SIZE(fs_info); return btrfs_item_offset_nr(leaf, nr - 1); } @@ -2501,11 +2512,6 @@ BTRFS_SETGET_STACK_FUNCS(stack_dev_replace_cursor_left, BTRFS_SETGET_STACK_FUNCS(stack_dev_replace_cursor_right, struct btrfs_dev_replace_item, cursor_right, 64); -static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb) -{ - return sb->s_fs_info; -} - /* helper function to cast into the data area of the leaf. */ #define btrfs_item_ptr(leaf, slot, type) \ ((type *)(btrfs_leaf_data(leaf) + \ @@ -2528,28 +2534,28 @@ static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping) /* extent-tree.c */ -u64 btrfs_csum_bytes_to_leaves(struct btrfs_root *root, u64 csum_bytes); +u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes); -static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_root *root, +static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info, unsigned num_items) { - return root->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; + return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items; } /* * Doing a truncate won't result in new nodes or leaves, just what we need for * COW. */ -static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_root *root, +static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info, unsigned num_items) { - return root->nodesize * BTRFS_MAX_LEVEL * num_items; + return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items; } int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); void btrfs_dec_block_group_reservations(struct btrfs_fs_info *fs_info, const u64 start); void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg); @@ -2558,18 +2564,18 @@ void btrfs_dec_nocow_writers(struct btrfs_fs_info *fs_info, u64 bytenr); void btrfs_wait_nocow_writers(struct btrfs_block_group_cache *bg); void btrfs_put_block_group(struct btrfs_block_group_cache *cache); int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root, unsigned long count); -int btrfs_async_run_delayed_refs(struct btrfs_root *root, + struct btrfs_fs_info *fs_info, unsigned long count); +int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, unsigned long count, u64 transid, int wait); -int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len); +int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len); int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 offset, int metadata, u64 *refs, u64 *flags); -int btrfs_pin_extent(struct btrfs_root *root, +int btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num, int reserved); -int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, +int btrfs_pin_extent_for_log_replay(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes); -int btrfs_exclude_logged_extents(struct btrfs_root *root, +int btrfs_exclude_logged_extents(struct btrfs_fs_info *fs_info, struct extent_buffer *eb); int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -2590,12 +2596,11 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct extent_buffer *buf, u64 parent, int last_ref); int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 root_objectid, u64 owner, u64 offset, u64 ram_bytes, struct btrfs_key *ins); int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 root_objectid, u64 owner, u64 offset, struct btrfs_key *ins); int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, u64 num_bytes, @@ -2606,52 +2611,52 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int full_backref); int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 flags, int level, int is_data); int btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset); -int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len, - int delalloc); -int btrfs_free_and_pin_reserved_extent(struct btrfs_root *root, +int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, + u64 start, u64 len, int delalloc); +int btrfs_free_and_pin_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len); void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset); int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_setup_space_cache(struct btrfs_trans_handle *trans, - struct btrfs_root *root); -int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr); + struct btrfs_fs_info *fs_info); +int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr); int btrfs_free_block_groups(struct btrfs_fs_info *info); -int btrfs_read_block_groups(struct btrfs_root *root); -int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr); +int btrfs_read_block_groups(struct btrfs_fs_info *info); +int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr); int btrfs_make_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytes_used, + struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type, u64 chunk_objectid, u64 chunk_offset, u64 size); struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( struct btrfs_fs_info *fs_info, const u64 chunk_offset); int btrfs_remove_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 group_start, + struct btrfs_fs_info *fs_info, u64 group_start, struct extent_map *em); void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info); void btrfs_get_block_group_trimming(struct btrfs_block_group_cache *cache); void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *cache); void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data); void btrfs_clear_space_info_full(struct btrfs_fs_info *info); @@ -2681,7 +2686,7 @@ void btrfs_free_reserved_data_space(struct inode *inode, u64 start, u64 len); void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, u64 len); void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans); int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, struct inode *inode); @@ -2690,7 +2695,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, struct btrfs_block_rsv *rsv, int nitems, u64 *qgroup_reserved, bool use_global_rsv); -void btrfs_subvolume_release_metadata(struct btrfs_root *root, +void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv, u64 qgroup_reserved); int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes); @@ -2698,16 +2703,15 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes); int btrfs_delalloc_reserve_space(struct inode *inode, u64 start, u64 len); void btrfs_delalloc_release_space(struct inode *inode, u64 start, u64 len); void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type); -struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root, +struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, unsigned short type); -void btrfs_free_block_rsv(struct btrfs_root *root, +void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv); void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv); int btrfs_block_rsv_add(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, u64 num_bytes, enum btrfs_reserve_flush_enum flush); -int btrfs_block_rsv_check(struct btrfs_root *root, - struct btrfs_block_rsv *block_rsv, int min_factor); +int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor); int btrfs_block_rsv_refill(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, u64 min_reserved, enum btrfs_reserve_flush_enum flush); @@ -2717,22 +2721,21 @@ int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv, int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *dest, u64 num_bytes, int min_factor); -void btrfs_block_rsv_release(struct btrfs_root *root, +void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *block_rsv, u64 num_bytes); int btrfs_inc_block_group_ro(struct btrfs_root *root, struct btrfs_block_group_cache *cache); -void btrfs_dec_block_group_ro(struct btrfs_root *root, - struct btrfs_block_group_cache *cache); +void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache); void btrfs_put_block_group_cache(struct btrfs_fs_info *info); u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); -int btrfs_error_unpin_extent_range(struct btrfs_root *root, +int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, u64 start, u64 end); -int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, +int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 *actual_bytes); int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 type); -int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range); + struct btrfs_fs_info *fs_info, u64 type); +int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range); int btrfs_init_space_info(struct btrfs_fs_info *fs_info); int btrfs_delayed_refs_qgroup_accounting(struct btrfs_trans_handle *trans, @@ -2742,8 +2745,7 @@ int btrfs_start_write_no_snapshoting(struct btrfs_root *root); void btrfs_end_write_no_snapshoting(struct btrfs_root *root); void btrfs_wait_for_snapshot_creation(struct btrfs_root *root); void check_system_chunk(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - const u64 type); + struct btrfs_fs_info *fs_info, const u64 type); u64 add_new_free_space(struct btrfs_block_group_cache *block_group, struct btrfs_fs_info *info, u64 start, u64 end); @@ -2793,10 +2795,10 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, struct extent_buffer **cow_ret, u64 new_root_objectid); int btrfs_block_can_be_shared(struct btrfs_root *root, struct extent_buffer *buf); -void btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, +void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path, u32 data_size); -void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path, - u32 new_size, int from_end); +void btrfs_truncate_item(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, @@ -2872,7 +2874,8 @@ static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p) { return btrfs_next_old_item(root, p, 0); } -int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); +int btrfs_leaf_free_space(struct btrfs_fs_info *fs_info, + struct extent_buffer *leaf); int __must_check btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_block_rsv *block_rsv, int update_ref, int for_reloc); @@ -2898,10 +2901,9 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info) * anything except sleeping. This function is used to check the status of * the fs. */ -static inline int btrfs_need_cleaner_sleep(struct btrfs_root *root) +static inline int btrfs_need_cleaner_sleep(struct btrfs_fs_info *fs_info) { - return (root->fs_info->sb->s_flags & MS_RDONLY || - btrfs_fs_closing(root->fs_info)); + return fs_info->sb->s_flags & MS_RDONLY || btrfs_fs_closing(fs_info); } static inline void free_fs_info(struct btrfs_fs_info *fs_info) @@ -2931,11 +2933,11 @@ int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq); /* root-item.c */ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *tree_root, + struct btrfs_fs_info *fs_info, u64 root_id, u64 ref_id, u64 dirid, u64 sequence, const char *name, int name_len); int btrfs_del_root_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *tree_root, + struct btrfs_fs_info *fs_info, u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, const char *name, int name_len); int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -2950,7 +2952,7 @@ int __must_check btrfs_update_root(struct btrfs_trans_handle *trans, int btrfs_find_root(struct btrfs_root *root, struct btrfs_key *search_key, struct btrfs_path *path, struct btrfs_root_item *root_item, struct btrfs_key *root_key); -int btrfs_find_orphan_roots(struct btrfs_root *tree_root); +int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info); void btrfs_set_root_node(struct btrfs_root_item *item, struct extent_buffer *node); void btrfs_check_and_init_root_item(struct btrfs_root_item *item); @@ -2959,10 +2961,10 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans, /* uuid-tree.c */ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, - struct btrfs_root *uuid_root, u8 *uuid, u8 type, + struct btrfs_fs_info *fs_info, u8 *uuid, u8 type, u64 subid); int btrfs_uuid_tree_rem(struct btrfs_trans_handle *trans, - struct btrfs_root *uuid_root, u8 *uuid, u8 type, + struct btrfs_fs_info *fs_info, u8 *uuid, u8 type, u64 subid); int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info, int (*check_func)(struct btrfs_fs_info *, u8 *, u8, @@ -3004,10 +3006,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 dir, const char *name, u16 name_len, int mod); -int verify_dir_item(struct btrfs_root *root, +int verify_dir_item(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, struct btrfs_dir_item *dir_item); -struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, struct btrfs_path *path, const char *name, int name_len); @@ -3051,11 +3053,10 @@ int btrfs_find_name_in_ext_backref(struct btrfs_path *path, /* file-item.c */ struct btrfs_dio_private; int btrfs_del_csums(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 len); -int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u32 *dst); -int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 logical_offset); + struct btrfs_fs_info *fs_info, u64 bytenr, u64 len); +int btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst); +int btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, + u64 logical_offset); int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 objectid, u64 pos, @@ -3069,8 +3070,8 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_ordered_sum *sums); -int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 file_start, int contig); +int btrfs_csum_one_bio(struct inode *inode, struct bio *bio, + u64 file_start, int contig); int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, struct list_head *list, int search_commit); void btrfs_extent_item_to_extent_map(struct inode *inode, @@ -3173,7 +3174,7 @@ void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size); void btrfs_invalidate_inodes(struct btrfs_root *root); void btrfs_add_delayed_iput(struct inode *inode); -void btrfs_run_delayed_iputs(struct btrfs_root *root); +void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info); int btrfs_prealloc_file_range(struct inode *inode, int mode, u64 start, u64 num_bytes, u64 min_size, loff_t actual_len, u64 *alloc_hint); @@ -3227,14 +3228,10 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, struct inode *inode, u64 start, u64 end); int btrfs_release_file(struct inode *inode, struct file *file); -int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, - struct page **pages, size_t num_pages, - loff_t pos, size_t write_bytes, +int btrfs_dirty_pages(struct inode *inode, struct page **pages, + size_t num_pages, loff_t pos, size_t write_bytes, struct extent_state **cached); int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end); -ssize_t btrfs_copy_file_range(struct file *file_in, loff_t pos_in, - struct file *file_out, loff_t pos_out, - size_t len, unsigned int flags); int btrfs_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 len); @@ -3252,7 +3249,7 @@ void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info); ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size); /* super.c */ -int btrfs_parse_options(struct btrfs_root *root, char *options, +int btrfs_parse_options(struct btrfs_fs_info *info, char *options, unsigned long new_flags); int btrfs_sync_fs(struct super_block *sb, int wait); @@ -3445,9 +3442,14 @@ do { \ /* Report first abort since mount */ \ if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED, \ &((trans)->fs_info->fs_state))) { \ - WARN(1, KERN_DEBUG \ - "BTRFS: Transaction aborted (error %d)\n", \ - (errno)); \ + if ((errno) != -EIO) { \ + WARN(1, KERN_DEBUG \ + "BTRFS: Transaction aborted (error %d)\n", \ + (errno)); \ + } else { \ + pr_debug("BTRFS: Transaction aborted (error %d)\n", \ + (errno)); \ + } \ } \ __btrfs_abort_transaction((trans), __func__, \ __LINE__, (errno)); \ @@ -3609,7 +3611,7 @@ static inline int btrfs_init_acl(struct btrfs_trans_handle *trans, #endif /* relocation.c */ -int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start); +int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start); int btrfs_init_reloc_root(struct btrfs_trans_handle *trans, struct btrfs_root *root); int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, @@ -3628,12 +3630,12 @@ int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans, int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, u64 end, struct btrfs_scrub_progress *progress, int readonly, int is_dev_replace); -void btrfs_scrub_pause(struct btrfs_root *root); -void btrfs_scrub_continue(struct btrfs_root *root); +void btrfs_scrub_pause(struct btrfs_fs_info *fs_info); +void btrfs_scrub_continue(struct btrfs_fs_info *fs_info); int btrfs_scrub_cancel(struct btrfs_fs_info *info); int btrfs_scrub_cancel_dev(struct btrfs_fs_info *info, struct btrfs_device *dev); -int btrfs_scrub_progress(struct btrfs_root *root, u64 devid, +int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid, struct btrfs_scrub_progress *progress); /* dev-replace.c */ @@ -3648,7 +3650,7 @@ static inline void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info) /* reada.c */ struct reada_control { - struct btrfs_root *root; /* tree to prefetch */ + struct btrfs_fs_info *fs_info; /* tree to prefetch */ struct btrfs_key key_start; struct btrfs_key key_end; /* exclusive */ atomic_t elems; @@ -3660,7 +3662,7 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root, int btrfs_reada_wait(void *handle); void btrfs_reada_detach(void *handle); int btree_readahead_hook(struct btrfs_fs_info *fs_info, - struct extent_buffer *eb, u64 start, int err); + struct extent_buffer *eb, int err); static inline int is_fstree(u64 rootid) { diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 0fcf5f25d524..80982a83c9fd 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -72,12 +72,6 @@ static inline int btrfs_is_continuous_delayed_item( return 0; } -static inline struct btrfs_delayed_root *btrfs_get_delayed_root( - struct btrfs_root *root) -{ - return root->fs_info->delayed_root; -} - static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode) { struct btrfs_inode *btrfs_inode = BTRFS_I(inode); @@ -535,7 +529,7 @@ static struct btrfs_delayed_item *__btrfs_next_delayed_item( } static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_item *item) { struct btrfs_block_rsv *src_rsv; @@ -547,12 +541,12 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, return 0; src_rsv = trans->block_rsv; - dst_rsv = &root->fs_info->delayed_block_rsv; + dst_rsv = &fs_info->delayed_block_rsv; - num_bytes = btrfs_calc_trans_metadata_size(root, 1); + num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); if (!ret) { - trace_btrfs_space_reservation(root->fs_info, "delayed_item", + trace_btrfs_space_reservation(fs_info, "delayed_item", item->key.objectid, num_bytes, 1); item->bytes_reserved = num_bytes; @@ -561,7 +555,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, return ret; } -static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, +static void btrfs_delayed_item_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_delayed_item *item) { struct btrfs_block_rsv *rsv; @@ -569,11 +563,11 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, if (!item->bytes_reserved) return; - rsv = &root->fs_info->delayed_block_rsv; - trace_btrfs_space_reservation(root->fs_info, "delayed_item", + rsv = &fs_info->delayed_block_rsv; + trace_btrfs_space_reservation(fs_info, "delayed_item", item->key.objectid, item->bytes_reserved, 0); - btrfs_block_rsv_release(root, rsv, + btrfs_block_rsv_release(fs_info, rsv, item->bytes_reserved); } @@ -583,6 +577,7 @@ static int btrfs_delayed_inode_reserve_metadata( struct inode *inode, struct btrfs_delayed_node *node) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_rsv *src_rsv; struct btrfs_block_rsv *dst_rsv; u64 num_bytes; @@ -590,9 +585,9 @@ static int btrfs_delayed_inode_reserve_metadata( bool release = false; src_rsv = trans->block_rsv; - dst_rsv = &root->fs_info->delayed_block_rsv; + dst_rsv = &fs_info->delayed_block_rsv; - num_bytes = btrfs_calc_trans_metadata_size(root, 1); + num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); /* * If our block_rsv is the delalloc block reserve then check and see if @@ -640,7 +635,7 @@ static int btrfs_delayed_inode_reserve_metadata( ret = -ENOSPC; if (!ret) { node->bytes_reserved = num_bytes; - trace_btrfs_space_reservation(root->fs_info, + trace_btrfs_space_reservation(fs_info, "delayed_inode", btrfs_ino(inode), num_bytes, 1); @@ -664,21 +659,21 @@ static int btrfs_delayed_inode_reserve_metadata( * how block rsvs. work. */ if (!ret) { - trace_btrfs_space_reservation(root->fs_info, "delayed_inode", + trace_btrfs_space_reservation(fs_info, "delayed_inode", btrfs_ino(inode), num_bytes, 1); node->bytes_reserved = num_bytes; } if (release) { - trace_btrfs_space_reservation(root->fs_info, "delalloc", + trace_btrfs_space_reservation(fs_info, "delalloc", btrfs_ino(inode), num_bytes, 0); - btrfs_block_rsv_release(root, src_rsv, num_bytes); + btrfs_block_rsv_release(fs_info, src_rsv, num_bytes); } return ret; } -static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root, +static void btrfs_delayed_inode_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_delayed_node *node) { struct btrfs_block_rsv *rsv; @@ -686,10 +681,10 @@ static void btrfs_delayed_inode_release_metadata(struct btrfs_root *root, if (!node->bytes_reserved) return; - rsv = &root->fs_info->delayed_block_rsv; - trace_btrfs_space_reservation(root->fs_info, "delayed_inode", + rsv = &fs_info->delayed_block_rsv; + trace_btrfs_space_reservation(fs_info, "delayed_inode", node->inode_id, node->bytes_reserved, 0); - btrfs_block_rsv_release(root, rsv, + btrfs_block_rsv_release(fs_info, rsv, node->bytes_reserved); node->bytes_reserved = 0; } @@ -702,6 +697,7 @@ static int btrfs_batch_insert_items(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_delayed_item *item) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_delayed_item *curr, *next; int free_space; int total_data_size = 0, total_size = 0; @@ -718,7 +714,7 @@ static int btrfs_batch_insert_items(struct btrfs_root *root, BUG_ON(!path->nodes[0]); leaf = path->nodes[0]; - free_space = btrfs_leaf_free_space(root, leaf); + free_space = btrfs_leaf_free_space(fs_info, leaf); INIT_LIST_HEAD(&head); next = item; @@ -791,7 +787,7 @@ static int btrfs_batch_insert_items(struct btrfs_root *root, curr->data_len); slot++; - btrfs_delayed_item_release_metadata(root, curr); + btrfs_delayed_item_release_metadata(fs_info, curr); list_del(&curr->tree_list); btrfs_release_delayed_item(curr); @@ -813,6 +809,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_delayed_item *delayed_item) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *leaf; char *ptr; int ret; @@ -830,7 +827,7 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, delayed_item->data_len); btrfs_mark_buffer_dirty(leaf); - btrfs_delayed_item_release_metadata(root, delayed_item); + btrfs_delayed_item_release_metadata(fs_info, delayed_item); return 0; } @@ -882,6 +879,7 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_delayed_item *item) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_delayed_item *curr, *next; struct extent_buffer *leaf; struct btrfs_key key; @@ -931,7 +929,7 @@ static int btrfs_batch_delete_items(struct btrfs_trans_handle *trans, goto out; list_for_each_entry_safe(curr, next, &head, tree_list) { - btrfs_delayed_item_release_metadata(root, curr); + btrfs_delayed_item_release_metadata(fs_info, curr); list_del(&curr->tree_list); btrfs_release_delayed_item(curr); } @@ -1017,6 +1015,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct btrfs_delayed_node *node) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; struct btrfs_inode_item *inode_item; struct extent_buffer *leaf; @@ -1073,7 +1072,7 @@ out: no_iref: btrfs_release_path(path); err_out: - btrfs_delayed_inode_release_metadata(root, node); + btrfs_delayed_inode_release_metadata(fs_info, node); btrfs_release_delayed_inode(node); return ret; @@ -1138,7 +1137,7 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, * outstanding delayed items cleaned up. */ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int nr) + struct btrfs_fs_info *fs_info, int nr) { struct btrfs_delayed_root *delayed_root; struct btrfs_delayed_node *curr_node, *prev_node; @@ -1156,9 +1155,9 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, path->leave_spinning = 1; block_rsv = trans->block_rsv; - trans->block_rsv = &root->fs_info->delayed_block_rsv; + trans->block_rsv = &fs_info->delayed_block_rsv; - delayed_root = btrfs_get_delayed_root(root); + delayed_root = fs_info->delayed_root; curr_node = btrfs_first_delayed_node(delayed_root); while (curr_node && (!count || (count && nr--))) { @@ -1185,15 +1184,15 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, } int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { - return __btrfs_run_delayed_items(trans, root, -1); + return __btrfs_run_delayed_items(trans, fs_info, -1); } int btrfs_run_delayed_items_nr(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int nr) + struct btrfs_fs_info *fs_info, int nr) { - return __btrfs_run_delayed_items(trans, root, nr); + return __btrfs_run_delayed_items(trans, fs_info, nr); } int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, @@ -1236,6 +1235,7 @@ int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, int btrfs_commit_inode_delayed_inode(struct inode *inode) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_trans_handle *trans; struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); struct btrfs_path *path; @@ -1267,7 +1267,7 @@ int btrfs_commit_inode_delayed_inode(struct inode *inode) path->leave_spinning = 1; block_rsv = trans->block_rsv; - trans->block_rsv = &delayed_node->root->fs_info->delayed_block_rsv; + trans->block_rsv = &fs_info->delayed_block_rsv; mutex_lock(&delayed_node->mutex); if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) @@ -1280,8 +1280,8 @@ int btrfs_commit_inode_delayed_inode(struct inode *inode) btrfs_free_path(path); trans->block_rsv = block_rsv; trans_out: - btrfs_end_transaction(trans, delayed_node->root); - btrfs_btree_balance_dirty(delayed_node->root); + btrfs_end_transaction(trans); + btrfs_btree_balance_dirty(fs_info); out: btrfs_release_delayed_node(delayed_node); @@ -1345,15 +1345,16 @@ again: __btrfs_commit_inode_delayed_items(trans, path, delayed_node); trans->block_rsv = block_rsv; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty_nodelay(root); + btrfs_end_transaction(trans); + btrfs_btree_balance_dirty_nodelay(root->fs_info); release_path: btrfs_release_path(path); total_done++; btrfs_release_prepared_delayed_node(delayed_node); - if (async_work->nr == 0 || total_done < async_work->nr) + if ((async_work->nr == 0 && total_done < BTRFS_DELAYED_WRITEBACK) || + total_done < async_work->nr) goto again; free_path: @@ -1369,7 +1370,8 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root, { struct btrfs_async_delayed_work *async_work; - if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND) + if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND || + btrfs_workqueue_normal_congested(fs_info->delayed_workers)) return 0; async_work = kmalloc(sizeof(*async_work), GFP_NOFS); @@ -1385,11 +1387,9 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root, return 0; } -void btrfs_assert_delayed_root_empty(struct btrfs_root *root) +void btrfs_assert_delayed_root_empty(struct btrfs_fs_info *fs_info) { - struct btrfs_delayed_root *delayed_root; - delayed_root = btrfs_get_delayed_root(root); - WARN_ON(btrfs_first_delayed_node(delayed_root)); + WARN_ON(btrfs_first_delayed_node(fs_info->delayed_root)); } static int could_end_wait(struct btrfs_delayed_root *delayed_root, int seq) @@ -1405,12 +1405,9 @@ static int could_end_wait(struct btrfs_delayed_root *delayed_root, int seq) return 0; } -void btrfs_balance_delayed_items(struct btrfs_root *root) +void btrfs_balance_delayed_items(struct btrfs_fs_info *fs_info) { - struct btrfs_delayed_root *delayed_root; - struct btrfs_fs_info *fs_info = root->fs_info; - - delayed_root = btrfs_get_delayed_root(root); + struct btrfs_delayed_root *delayed_root = fs_info->delayed_root; if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND) return; @@ -1435,8 +1432,9 @@ void btrfs_balance_delayed_items(struct btrfs_root *root) /* Will return 0 or -ENOMEM */ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, - struct btrfs_root *root, const char *name, - int name_len, struct inode *dir, + struct btrfs_fs_info *fs_info, + const char *name, int name_len, + struct inode *dir, struct btrfs_disk_key *disk_key, u8 type, u64 index) { @@ -1467,7 +1465,7 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, btrfs_set_stack_dir_type(dir_item, type); memcpy((char *)(dir_item + 1), name, name_len); - ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item); + ret = btrfs_delayed_item_reserve_metadata(trans, fs_info, delayed_item); /* * we have reserved enough space when we start a new transaction, * so reserving metadata failure is impossible @@ -1478,7 +1476,7 @@ int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, mutex_lock(&delayed_node->mutex); ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item); if (unlikely(ret)) { - btrfs_err(root->fs_info, + btrfs_err(fs_info, "err add delayed dir index item(name: %.*s) into the insertion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)", name_len, name, delayed_node->root->objectid, delayed_node->inode_id, ret); @@ -1491,7 +1489,7 @@ release_node: return ret; } -static int btrfs_delete_delayed_insertion_item(struct btrfs_root *root, +static int btrfs_delete_delayed_insertion_item(struct btrfs_fs_info *fs_info, struct btrfs_delayed_node *node, struct btrfs_key *key) { @@ -1504,15 +1502,15 @@ static int btrfs_delete_delayed_insertion_item(struct btrfs_root *root, return 1; } - btrfs_delayed_item_release_metadata(root, item); + btrfs_delayed_item_release_metadata(fs_info, item); btrfs_release_delayed_item(item); mutex_unlock(&node->mutex); return 0; } int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *dir, - u64 index) + struct btrfs_fs_info *fs_info, + struct inode *dir, u64 index) { struct btrfs_delayed_node *node; struct btrfs_delayed_item *item; @@ -1527,7 +1525,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, item_key.type = BTRFS_DIR_INDEX_KEY; item_key.offset = index; - ret = btrfs_delete_delayed_insertion_item(root, node, &item_key); + ret = btrfs_delete_delayed_insertion_item(fs_info, node, &item_key); if (!ret) goto end; @@ -1539,7 +1537,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, item->key = item_key; - ret = btrfs_delayed_item_reserve_metadata(trans, root, item); + ret = btrfs_delayed_item_reserve_metadata(trans, fs_info, item); /* * we have reserved enough space when we start a new transaction, * so reserving metadata failure is impossible. @@ -1549,7 +1547,7 @@ int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, mutex_lock(&node->mutex); ret = __btrfs_add_delayed_deletion_item(node, item); if (unlikely(ret)) { - btrfs_err(root->fs_info, + btrfs_err(fs_info, "err add delayed dir index item(index: %llu) into the deletion tree of the delayed node(root id: %llu, inode id: %llu, errno: %d)", index, node->root->objectid, node->inode_id, ret); BUG(); @@ -1686,7 +1684,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list, * */ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, - struct list_head *ins_list, bool *emitted) + struct list_head *ins_list) { struct btrfs_dir_item *di; struct btrfs_delayed_item *curr, *next; @@ -1730,7 +1728,6 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, if (over) return 1; - *emitted = true; } return 0; } @@ -1861,6 +1858,7 @@ release_node: int btrfs_delayed_delete_inode_ref(struct inode *inode) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_delayed_node *delayed_node; /* @@ -1868,8 +1866,7 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode) * leads to enospc problems. This means we also can't do * delayed inode refs */ - if (test_bit(BTRFS_FS_LOG_RECOVERING, - &BTRFS_I(inode)->root->fs_info->flags)) + if (test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) return -EAGAIN; delayed_node = btrfs_get_or_create_delayed_node(inode); @@ -1896,7 +1893,7 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode) set_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags); delayed_node->count++; - atomic_inc(&BTRFS_I(inode)->root->fs_info->delayed_root->items); + atomic_inc(&fs_info->delayed_root->items); release_node: mutex_unlock(&delayed_node->mutex); btrfs_release_delayed_node(delayed_node); @@ -1906,12 +1903,13 @@ release_node: static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) { struct btrfs_root *root = delayed_node->root; + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_delayed_item *curr_item, *prev_item; mutex_lock(&delayed_node->mutex); curr_item = __btrfs_first_delayed_insertion_item(delayed_node); while (curr_item) { - btrfs_delayed_item_release_metadata(root, curr_item); + btrfs_delayed_item_release_metadata(fs_info, curr_item); prev_item = curr_item; curr_item = __btrfs_next_delayed_item(prev_item); btrfs_release_delayed_item(prev_item); @@ -1919,7 +1917,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) curr_item = __btrfs_first_delayed_deletion_item(delayed_node); while (curr_item) { - btrfs_delayed_item_release_metadata(root, curr_item); + btrfs_delayed_item_release_metadata(fs_info, curr_item); prev_item = curr_item; curr_item = __btrfs_next_delayed_item(prev_item); btrfs_release_delayed_item(prev_item); @@ -1929,7 +1927,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node) btrfs_release_delayed_iref(delayed_node); if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) { - btrfs_delayed_inode_release_metadata(root, delayed_node); + btrfs_delayed_inode_release_metadata(fs_info, delayed_node); btrfs_release_delayed_inode(delayed_node); } mutex_unlock(&delayed_node->mutex); @@ -1976,14 +1974,11 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root) } } -void btrfs_destroy_delayed_inodes(struct btrfs_root *root) +void btrfs_destroy_delayed_inodes(struct btrfs_fs_info *fs_info) { - struct btrfs_delayed_root *delayed_root; struct btrfs_delayed_node *curr_node, *prev_node; - delayed_root = btrfs_get_delayed_root(root); - - curr_node = btrfs_first_delayed_node(delayed_root); + curr_node = btrfs_first_delayed_node(fs_info->delayed_root); while (curr_node) { __btrfs_kill_delayed_node(curr_node); diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 2495b3d4075f..8a2bf5e3e4cf 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -99,23 +99,24 @@ static inline void btrfs_init_delayed_root( } int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans, - struct btrfs_root *root, const char *name, - int name_len, struct inode *dir, + struct btrfs_fs_info *fs_info, + const char *name, int name_len, + struct inode *dir, struct btrfs_disk_key *disk_key, u8 type, u64 index); int btrfs_delete_delayed_dir_index(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *dir, - u64 index); + struct btrfs_fs_info *fs_info, + struct inode *dir, u64 index); int btrfs_inode_delayed_dir_index_count(struct inode *inode); int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); int btrfs_run_delayed_items_nr(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int nr); + struct btrfs_fs_info *fs_info, int nr); -void btrfs_balance_delayed_items(struct btrfs_root *root); +void btrfs_balance_delayed_items(struct btrfs_fs_info *fs_info); int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, struct inode *inode); @@ -134,7 +135,7 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode); void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); /* Used for clean the transaction */ -void btrfs_destroy_delayed_inodes(struct btrfs_root *root); +void btrfs_destroy_delayed_inodes(struct btrfs_fs_info *fs_info); /* Used for readdir() */ bool btrfs_readdir_get_delayed_items(struct inode *inode, @@ -146,13 +147,13 @@ void btrfs_readdir_put_delayed_items(struct inode *inode, int btrfs_should_delete_dir_index(struct list_head *del_list, u64 index); int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, - struct list_head *ins_list, bool *emitted); + struct list_head *ins_list); /* for init */ int __init btrfs_delayed_inode_init(void); void btrfs_delayed_inode_exit(void); /* for debugging */ -void btrfs_assert_delayed_root_empty(struct btrfs_root *root); +void btrfs_assert_delayed_root_empty(struct btrfs_fs_info *fs_info); #endif diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index 8d93854a4b4f..ef724a5fc30e 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -189,6 +189,8 @@ static inline void drop_delayed_ref(struct btrfs_trans_handle *trans, } else { assert_spin_locked(&head->lock); list_del(&ref->list); + if (!list_empty(&ref->add_list)) + list_del(&ref->add_list); } ref->in_tree = 0; btrfs_put_delayed_ref(ref); @@ -431,6 +433,15 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans, exist->action = ref->action; mod = -exist->ref_mod; exist->ref_mod = ref->ref_mod; + if (ref->action == BTRFS_ADD_DELAYED_REF) + list_add_tail(&exist->add_list, + &href->ref_add_list); + else if (ref->action == BTRFS_DROP_DELAYED_REF) { + ASSERT(!list_empty(&exist->add_list)); + list_del(&exist->add_list); + } else { + ASSERT(0); + } } else mod = -ref->ref_mod; } @@ -444,6 +455,8 @@ add_delayed_ref_tail_merge(struct btrfs_trans_handle *trans, add_tail: list_add_tail(&ref->list, &href->ref_list); + if (ref->action == BTRFS_ADD_DELAYED_REF) + list_add_tail(&ref->add_list, &href->ref_add_list); atomic_inc(&root->num_entries); trans->delayed_ref_updates++; spin_unlock(&href->lock); @@ -590,6 +603,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info, head_ref->must_insert_reserved = must_insert_reserved; head_ref->is_data = is_data; INIT_LIST_HEAD(&head_ref->ref_list); + INIT_LIST_HEAD(&head_ref->ref_add_list); head_ref->processing = 0; head_ref->total_ref_mod = count_mod; head_ref->qgroup_reserved = 0; @@ -606,7 +620,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info, qrecord->num_bytes = num_bytes; qrecord->old_roots = NULL; - if(btrfs_qgroup_insert_dirty_extent_nolock(fs_info, + if(btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord)) kfree(qrecord); } @@ -671,6 +685,8 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info, ref->is_head = 0; ref->in_tree = 1; ref->seq = seq; + INIT_LIST_HEAD(&ref->list); + INIT_LIST_HEAD(&ref->add_list); full_ref = btrfs_delayed_node_to_tree_ref(ref); full_ref->parent = parent; @@ -726,6 +742,8 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info, ref->is_head = 0; ref->in_tree = 1; ref->seq = seq; + INIT_LIST_HEAD(&ref->list); + INIT_LIST_HEAD(&ref->add_list); full_ref = btrfs_delayed_node_to_data_ref(ref); full_ref->parent = parent; diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index 43f3629760e9..50947b5a9152 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h @@ -34,14 +34,14 @@ * ref_head. Must clean this mess up later. */ struct btrfs_delayed_ref_node { - /* - * ref_head use rb tree, stored in ref_root->href. - * indexed by bytenr - */ - struct rb_node rb_node; - /*data/tree ref use list, stored in ref_head->ref_list. */ struct list_head list; + /* + * If action is BTRFS_ADD_DELAYED_REF, also link this node to + * ref_head->ref_add_list, then we do not need to iterate the + * whole ref_head->ref_list to find BTRFS_ADD_DELAYED_REF nodes. + */ + struct list_head add_list; /* the starting bytenr of the extent */ u64 bytenr; @@ -99,6 +99,8 @@ struct btrfs_delayed_ref_head { spinlock_t lock; struct list_head ref_list; + /* accumulate add BTRFS_ADD_DELAYED_REF nodes to this ref_add_list. */ + struct list_head ref_add_list; struct rb_node href_node; diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 05169ef30596..5de280b9ad73 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -142,7 +142,7 @@ no_valid_dev_replace_entry_found: * missing */ if (!dev_replace->srcdev && - !btrfs_test_opt(dev_root->fs_info, DEGRADED)) { + !btrfs_test_opt(fs_info, DEGRADED)) { ret = -EIO; btrfs_warn(fs_info, "cannot mount because device replace operation is ongoing and"); @@ -151,7 +151,7 @@ no_valid_dev_replace_entry_found: src_devid); } if (!dev_replace->tgtdev && - !btrfs_test_opt(dev_root->fs_info, DEGRADED)) { + !btrfs_test_opt(fs_info, DEGRADED)) { ret = -EIO; btrfs_warn(fs_info, "cannot mount because device replace operation is ongoing and"); @@ -304,11 +304,11 @@ void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info) dev_replace->cursor_left_last_write_of_item; } -int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, +int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info, char *tgtdev_name, u64 srcdevid, char *srcdev_name, int read_src) { + struct btrfs_root *root = fs_info->dev_root; struct btrfs_trans_handle *trans; - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; int ret; struct btrfs_device *tgt_device = NULL; @@ -316,14 +316,14 @@ int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, /* the disk copy procedure reuses the scrub code */ mutex_lock(&fs_info->volume_mutex); - ret = btrfs_find_device_by_devspec(root, srcdevid, + ret = btrfs_find_device_by_devspec(fs_info, srcdevid, srcdev_name, &src_device); if (ret) { mutex_unlock(&fs_info->volume_mutex); return ret; } - ret = btrfs_init_dev_replace_tgtdev(root, tgtdev_name, + ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name, src_device, &tgt_device); mutex_unlock(&fs_info->volume_mutex); if (ret) @@ -335,7 +335,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, */ trans = btrfs_attach_transaction(root); if (!IS_ERR(trans)) { - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); if (ret) return ret; } else if (PTR_ERR(trans) != -ENOENT) { @@ -387,7 +387,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, if (ret) btrfs_err(fs_info, "kobj add dev failed %d", ret); - btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); /* force writing the updated state information to disk */ trans = btrfs_start_transaction(root, 0); @@ -397,7 +397,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, goto leave; } - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); WARN_ON(ret); /* the disk copy procedure reuses the scrub code */ @@ -422,7 +422,7 @@ leave: return ret; } -int btrfs_dev_replace_by_ioctl(struct btrfs_root *root, +int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_dev_replace_args *args) { int ret; @@ -439,7 +439,7 @@ int btrfs_dev_replace_by_ioctl(struct btrfs_root *root, args->start.tgtdev_name[0] == '\0') return -EINVAL; - ret = btrfs_dev_replace_start(root, args->start.tgtdev_name, + ret = btrfs_dev_replace_start(fs_info, args->start.tgtdev_name, args->start.srcdevid, args->start.srcdev_name, args->start.cont_reading_from_srcdev_mode); @@ -501,25 +501,25 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, * flush all outstanding I/O and inode extent mappings before the * copy operation is declared as being finished */ - ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1); + ret = btrfs_start_delalloc_roots(fs_info, 0, -1); if (ret) { mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); return ret; } - btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); return PTR_ERR(trans); } - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); WARN_ON(ret); mutex_lock(&uuid_mutex); /* keep away write_all_supers() during the finishing procedure */ - mutex_lock(&root->fs_info->fs_devices->device_list_mutex); - mutex_lock(&root->fs_info->chunk_mutex); + mutex_lock(&fs_info->fs_devices->device_list_mutex); + mutex_lock(&fs_info->chunk_mutex); btrfs_dev_replace_lock(dev_replace, 1); dev_replace->replace_state = scrub_ret ? BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED @@ -535,15 +535,15 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, src_device, tgt_device); } else { - btrfs_err_in_rcu(root->fs_info, - "btrfs_scrub_dev(%s, %llu, %s) failed %d", - src_device->missing ? "<missing disk>" : - rcu_str_deref(src_device->name), - src_device->devid, - rcu_str_deref(tgt_device->name), scrub_ret); + btrfs_err_in_rcu(fs_info, + "btrfs_scrub_dev(%s, %llu, %s) failed %d", + src_device->missing ? "<missing disk>" : + rcu_str_deref(src_device->name), + src_device->devid, + rcu_str_deref(tgt_device->name), scrub_ret); btrfs_dev_replace_unlock(dev_replace, 1); - mutex_unlock(&root->fs_info->chunk_mutex); - mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); mutex_unlock(&uuid_mutex); if (tgt_device) btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device); @@ -552,12 +552,12 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, return scrub_ret; } - btrfs_info_in_rcu(root->fs_info, - "dev_replace from %s (devid %llu) to %s finished", - src_device->missing ? "<missing disk>" : - rcu_str_deref(src_device->name), - src_device->devid, - rcu_str_deref(tgt_device->name)); + btrfs_info_in_rcu(fs_info, + "dev_replace from %s (devid %llu) to %s finished", + src_device->missing ? "<missing disk>" : + rcu_str_deref(src_device->name), + src_device->devid, + rcu_str_deref(tgt_device->name)); tgt_device->is_tgtdev_for_dev_replace = 0; tgt_device->devid = src_device->devid; src_device->devid = BTRFS_DEV_REPLACE_DEVID; @@ -592,8 +592,8 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, * superblock is scratched out so that it is no longer marked to * belong to this filesystem. */ - mutex_unlock(&root->fs_info->chunk_mutex); - mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); mutex_unlock(&uuid_mutex); /* replace the sysfs entry */ @@ -603,7 +603,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, /* write back the superblocks */ trans = btrfs_start_transaction(root, 0); if (!IS_ERR(trans)) - btrfs_commit_transaction(trans, root); + btrfs_commit_transaction(trans); mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); @@ -718,7 +718,7 @@ static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info) mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); return PTR_ERR(trans); } - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); WARN_ON(ret); if (tgt_device) btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device); diff --git a/fs/btrfs/dev-replace.h b/fs/btrfs/dev-replace.h index e922b42d91df..54ea12bda15b 100644 --- a/fs/btrfs/dev-replace.h +++ b/fs/btrfs/dev-replace.h @@ -25,9 +25,9 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info); int btrfs_run_dev_replace(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info); -int btrfs_dev_replace_by_ioctl(struct btrfs_root *root, +int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_dev_replace_args *args); -int btrfs_dev_replace_start(struct btrfs_root *root, char *tgtdev_name, +int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info, char *tgtdev_name, u64 srcdevid, char *srcdev_name, int read_src); void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info, struct btrfs_ioctl_dev_replace_args *args); diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 0dc1a033275e..b039fe0c751a 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -38,6 +38,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle const char *name, int name_len) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; char *ptr; struct btrfs_item *item; @@ -46,10 +47,10 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); if (ret == -EEXIST) { struct btrfs_dir_item *di; - di = btrfs_match_dir_item_name(root, path, name, name_len); + di = btrfs_match_dir_item_name(fs_info, path, name, name_len); if (di) return ERR_PTR(-EEXIST); - btrfs_extend_item(root, path, data_size); + btrfs_extend_item(fs_info, path, data_size); } else if (ret < 0) return ERR_PTR(ret); WARN_ON(ret > 0); @@ -79,7 +80,7 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; u32 data_size; - BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root)); + BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root->fs_info)); key.objectid = objectid; key.type = BTRFS_XATTR_ITEM_KEY; @@ -172,8 +173,9 @@ second_insert: } btrfs_release_path(path); - ret2 = btrfs_insert_delayed_dir_index(trans, root, name, name_len, dir, - &disk_key, type, index); + ret2 = btrfs_insert_delayed_dir_index(trans, root->fs_info, name, + name_len, dir, &disk_key, type, + index); out_free: btrfs_free_path(path); if (ret) @@ -210,7 +212,7 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, if (ret > 0) return NULL; - return btrfs_match_dir_item_name(root, path, name, name_len); + return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); } int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, @@ -246,7 +248,7 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, } /* we found an item, look for our name in the item */ - di = btrfs_match_dir_item_name(root, path, name, name_len); + di = btrfs_match_dir_item_name(root->fs_info, path, name, name_len); if (di) { /* our exact name was found */ ret = -EEXIST; @@ -261,7 +263,7 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, leaf = path->nodes[0]; slot = path->slots[0]; if (data_size + btrfs_item_size_nr(leaf, slot) + - sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root)) { + sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root->fs_info)) { ret = -EOVERFLOW; } else { /* plenty of insertion room */ @@ -301,7 +303,7 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, return ERR_PTR(ret); if (ret > 0) return ERR_PTR(-ENOENT); - return btrfs_match_dir_item_name(root, path, name, name_len); + return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); } struct btrfs_dir_item * @@ -342,7 +344,8 @@ btrfs_search_dir_index_item(struct btrfs_root *root, if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY) break; - di = btrfs_match_dir_item_name(root, path, name, name_len); + di = btrfs_match_dir_item_name(root->fs_info, path, + name, name_len); if (di) return di; @@ -371,7 +374,7 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, if (ret > 0) return NULL; - return btrfs_match_dir_item_name(root, path, name, name_len); + return btrfs_match_dir_item_name(root->fs_info, path, name, name_len); } /* @@ -379,7 +382,7 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, * this walks through all the entries in a dir item and finds one * for a specific name. */ -struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, struct btrfs_path *path, const char *name, int name_len) { @@ -392,7 +395,7 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, leaf = path->nodes[0]; dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); - if (verify_dir_item(root, leaf, dir_item)) + if (verify_dir_item(fs_info, leaf, dir_item)) return NULL; total_len = btrfs_item_size_nr(leaf, path->slots[0]); @@ -442,12 +445,13 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, start = btrfs_item_ptr_offset(leaf, path->slots[0]); memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, item_len - (ptr + sub_item_len - start)); - btrfs_truncate_item(root, path, item_len - sub_item_len, 1); + btrfs_truncate_item(root->fs_info, path, + item_len - sub_item_len, 1); } return ret; } -int verify_dir_item(struct btrfs_root *root, +int verify_dir_item(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, struct btrfs_dir_item *dir_item) { @@ -455,8 +459,7 @@ int verify_dir_item(struct btrfs_root *root, u8 type = btrfs_dir_type(leaf, dir_item); if (type >= BTRFS_FT_MAX) { - btrfs_crit(root->fs_info, "invalid dir item type: %d", - (int)type); + btrfs_crit(fs_info, "invalid dir item type: %d", (int)type); return 1; } @@ -464,16 +467,16 @@ int verify_dir_item(struct btrfs_root *root, namelen = XATTR_NAME_MAX; if (btrfs_dir_name_len(leaf, dir_item) > namelen) { - btrfs_crit(root->fs_info, "invalid dir item name len: %u", + btrfs_crit(fs_info, "invalid dir item name len: %u", (unsigned)btrfs_dir_data_len(leaf, dir_item)); return 1; } /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */ if ((btrfs_dir_data_len(leaf, dir_item) + - btrfs_dir_name_len(leaf, dir_item)) > BTRFS_MAX_XATTR_SIZE(root)) { - btrfs_crit(root->fs_info, - "invalid dir item name + data len: %u + %u", + btrfs_dir_name_len(leaf, dir_item)) > + BTRFS_MAX_XATTR_SIZE(fs_info)) { + btrfs_crit(fs_info, "invalid dir item name + data len: %u + %u", (unsigned)btrfs_dir_name_len(leaf, dir_item), (unsigned)btrfs_dir_data_len(leaf, dir_item)); return 1; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3a57f99d96aa..18004169552c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -68,15 +68,15 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, int read_only); static void btrfs_destroy_ordered_extents(struct btrfs_root *root); static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); -static int btrfs_destroy_marked_extents(struct btrfs_root *root, +static int btrfs_destroy_marked_extents(struct btrfs_fs_info *fs_info, struct extent_io_tree *dirty_pages, int mark); -static int btrfs_destroy_pinned_extent(struct btrfs_root *root, +static int btrfs_destroy_pinned_extent(struct btrfs_fs_info *fs_info, struct extent_io_tree *pinned_extents); -static int btrfs_cleanup_transaction(struct btrfs_root *root); -static void btrfs_error_commit_super(struct btrfs_root *root); +static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info); +static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info); /* * btrfs_end_io_wq structs are used to do processing in task context when an IO @@ -224,6 +224,7 @@ static struct extent_map *btree_get_extent(struct inode *inode, struct page *page, size_t pg_offset, u64 start, u64 len, int create) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; struct extent_map *em; int ret; @@ -231,8 +232,7 @@ static struct extent_map *btree_get_extent(struct inode *inode, read_lock(&em_tree->lock); em = lookup_extent_mapping(em_tree, start, len); if (em) { - em->bdev = - BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; + em->bdev = fs_info->fs_devices->latest_bdev; read_unlock(&em_tree->lock); goto out; } @@ -247,7 +247,7 @@ static struct extent_map *btree_get_extent(struct inode *inode, em->len = (u64)-1; em->block_len = (u64)-1; em->block_start = 0; - em->bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; + em->bdev = fs_info->fs_devices->latest_bdev; write_lock(&em_tree->lock); ret = add_extent_mapping(em_tree, em, 0); @@ -271,7 +271,7 @@ u32 btrfs_csum_data(char *data, u32 seed, size_t len) return btrfs_crc32c(seed, data, len); } -void btrfs_csum_final(u32 crc, char *result) +void btrfs_csum_final(u32 crc, u8 *result) { put_unaligned_le32(~crc, result); } @@ -440,7 +440,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, * helper to read a given tree block, doing retries as required when * the checksums don't match and we have alternate mirrors to try. */ -static int btree_read_extent_buffer_pages(struct btrfs_root *root, +static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, u64 parent_transid) { @@ -452,7 +452,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, int failed_mirror = 0; clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); - io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; + io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree; while (1) { ret = read_extent_buffer_pages(io_tree, eb, WAIT_COMPLETE, btree_get_extent, mirror_num); @@ -472,7 +472,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) break; - num_copies = btrfs_num_copies(root->fs_info, + num_copies = btrfs_num_copies(fs_info, eb->start, eb->len); if (num_copies == 1) break; @@ -491,7 +491,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, } if (failed && !ret && failed_mirror) - repair_eb_io_failure(root, eb, failed_mirror); + repair_eb_io_failure(fs_info, eb, failed_mirror); return ret; } @@ -545,47 +545,63 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info, return ret; } -#define CORRUPT(reason, eb, root, slot) \ - btrfs_crit(root->fs_info, "corrupt %s, %s: block=%llu," \ - " root=%llu, slot=%d", \ - btrfs_header_level(eb) == 0 ? "leaf" : "node",\ +#define CORRUPT(reason, eb, root, slot) \ + btrfs_crit(root->fs_info, \ + "corrupt %s, %s: block=%llu, root=%llu, slot=%d", \ + btrfs_header_level(eb) == 0 ? "leaf" : "node", \ reason, btrfs_header_bytenr(eb), root->objectid, slot) static noinline int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; struct btrfs_key leaf_key; u32 nritems = btrfs_header_nritems(leaf); int slot; - if (nritems == 0) { + /* + * Extent buffers from a relocation tree have a owner field that + * corresponds to the subvolume tree they are based on. So just from an + * extent buffer alone we can not find out what is the id of the + * corresponding subvolume tree, so we can not figure out if the extent + * buffer corresponds to the root of the relocation tree or not. So skip + * this check for relocation trees. + */ + if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { struct btrfs_root *check_root; key.objectid = btrfs_header_owner(leaf); key.type = BTRFS_ROOT_ITEM_KEY; key.offset = (u64)-1; - check_root = btrfs_get_fs_root(root->fs_info, &key, false); + check_root = btrfs_get_fs_root(fs_info, &key, false); /* * The only reason we also check NULL here is that during * open_ctree() some roots has not yet been set up. */ if (!IS_ERR_OR_NULL(check_root)) { + struct extent_buffer *eb; + + eb = btrfs_root_node(check_root); /* if leaf is the root, then it's fine */ - if (leaf->start != - btrfs_root_bytenr(&check_root->root_item)) { + if (leaf != eb) { CORRUPT("non-root leaf's nritems is 0", - leaf, root, 0); + leaf, check_root, 0); + free_extent_buffer(eb); return -EIO; } + free_extent_buffer(eb); } return 0; } + if (nritems == 0) + return 0; + /* Check the 0 item */ if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) != - BTRFS_LEAF_DATA_SIZE(root)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { CORRUPT("invalid item offset size pair", leaf, root, 0); return -EIO; } @@ -624,7 +640,7 @@ static noinline int check_leaf(struct btrfs_root *root, * all point outside of the leaf. */ if (btrfs_item_end_nr(leaf, slot) > - BTRFS_LEAF_DATA_SIZE(root)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { CORRUPT("slot end outside of leaf", leaf, root, slot); return -EIO; } @@ -641,7 +657,7 @@ static int check_node(struct btrfs_root *root, struct extent_buffer *node) u64 bytenr; int ret = 0; - if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) { + if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root->fs_info)) { btrfs_crit(root->fs_info, "corrupt node: block %llu root %llu nritems %lu", node->start, root->objectid, nr); @@ -747,7 +763,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, err: if (reads_done && test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) - btree_readahead_hook(fs_info, eb, eb->start, ret); + btree_readahead_hook(fs_info, eb, ret); if (ret) { /* @@ -772,7 +788,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror) eb->read_mirror = failed_mirror; atomic_dec(&eb->io_pages); if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) - btree_readahead_hook(eb->fs_info, eb, eb->start, -EIO); + btree_readahead_hook(eb->fs_info, eb, -EIO); return -EIO; /* we fixed nothing */ } @@ -930,7 +946,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, atomic_inc(&fs_info->nr_async_submits); - if (bio->bi_opf & REQ_SYNC) + if (op_is_sync(bio->bi_opf)) btrfs_set_work_high_priority(&async->work); btrfs_queue_work(fs_info->workers, &async->work); @@ -981,7 +997,7 @@ static int __btree_submit_bio_done(struct inode *inode, struct bio *bio, * when we're called for a write, we're already in the async * submission context. Just jump into btrfs_map_bio */ - ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 1); + ret = btrfs_map_bio(btrfs_sb(inode->i_sb), bio, mirror_num, 1); if (ret) { bio->bi_error = ret; bio_endio(bio); @@ -1004,6 +1020,7 @@ static int btree_submit_bio_hook(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); int async = check_async_write(inode, bio_flags); int ret; @@ -1012,23 +1029,22 @@ static int btree_submit_bio_hook(struct inode *inode, struct bio *bio, * called for a read, do the setup so that checksum validation * can happen in the async kernel threads */ - ret = btrfs_bio_wq_end_io(BTRFS_I(inode)->root->fs_info, - bio, BTRFS_WQ_ENDIO_METADATA); + ret = btrfs_bio_wq_end_io(fs_info, bio, + BTRFS_WQ_ENDIO_METADATA); if (ret) goto out_w_error; - ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0); + ret = btrfs_map_bio(fs_info, bio, mirror_num, 0); } else if (!async) { ret = btree_csum_one_bio(bio); if (ret) goto out_w_error; - ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0); + ret = btrfs_map_bio(fs_info, bio, mirror_num, 0); } else { /* * kthread helpers are used to submit writes so that * checksumming can happen in parallel across all CPUs */ - ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, - inode, bio, mirror_num, 0, + ret = btrfs_wq_submit_bio(fs_info, inode, bio, mirror_num, 0, bio_offset, __btree_submit_bio_start, __btree_submit_bio_done); @@ -1146,12 +1162,12 @@ static const struct address_space_operations btree_aops = { .set_page_dirty = btree_set_page_dirty, }; -void readahead_tree_block(struct btrfs_root *root, u64 bytenr) +void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr) { struct extent_buffer *buf = NULL; - struct inode *btree_inode = root->fs_info->btree_inode; + struct inode *btree_inode = fs_info->btree_inode; - buf = btrfs_find_create_tree_block(root, bytenr); + buf = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(buf)) return; read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, @@ -1159,15 +1175,15 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr) free_extent_buffer(buf); } -int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, +int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr, int mirror_num, struct extent_buffer **eb) { struct extent_buffer *buf = NULL; - struct inode *btree_inode = root->fs_info->btree_inode; + struct inode *btree_inode = fs_info->btree_inode; struct extent_io_tree *io_tree = &BTRFS_I(btree_inode)->io_tree; int ret; - buf = btrfs_find_create_tree_block(root, bytenr); + buf = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(buf)) return 0; @@ -1191,19 +1207,13 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, return 0; } -struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info, - u64 bytenr) -{ - return find_extent_buffer(fs_info, bytenr); -} - -struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, - u64 bytenr) +struct extent_buffer *btrfs_find_create_tree_block( + struct btrfs_fs_info *fs_info, + u64 bytenr) { - if (btrfs_is_testing(root->fs_info)) - return alloc_test_extent_buffer(root->fs_info, bytenr, - root->nodesize); - return alloc_extent_buffer(root->fs_info, bytenr); + if (btrfs_is_testing(fs_info)) + return alloc_test_extent_buffer(fs_info, bytenr); + return alloc_extent_buffer(fs_info, bytenr); } @@ -1219,17 +1229,17 @@ int btrfs_wait_tree_block_writeback(struct extent_buffer *buf) buf->start, buf->start + buf->len - 1); } -struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, +struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, u64 parent_transid) { struct extent_buffer *buf = NULL; int ret; - buf = btrfs_find_create_tree_block(root, bytenr); + buf = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(buf)) return buf; - ret = btree_read_extent_buffer_pages(root, buf, parent_transid); + ret = btree_read_extent_buffer_pages(fs_info, buf, parent_transid); if (ret) { free_extent_buffer(buf); return ERR_PTR(ret); @@ -1283,16 +1293,12 @@ btrfs_free_subvolume_writers(struct btrfs_subvolume_writers *writers) kfree(writers); } -static void __setup_root(u32 nodesize, u32 sectorsize, u32 stripesize, - struct btrfs_root *root, struct btrfs_fs_info *fs_info, +static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, u64 objectid) { bool dummy = test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state); root->node = NULL; root->commit_root = NULL; - root->sectorsize = sectorsize; - root->nodesize = nodesize; - root->stripesize = stripesize; root->state = 0; root->orphan_cleanup_state = 0; @@ -1370,8 +1376,7 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info, #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS /* Should only be used by the testing infrastructure */ -struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info, - u32 sectorsize, u32 nodesize) +struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info) { struct btrfs_root *root; @@ -1381,9 +1386,9 @@ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info, root = btrfs_alloc_root(fs_info, GFP_KERNEL); if (!root) return ERR_PTR(-ENOMEM); + /* We don't use the stripesize in selftest, set it as sectorsize */ - __setup_root(nodesize, sectorsize, sectorsize, root, fs_info, - BTRFS_ROOT_TREE_OBJECTID); + __setup_root(root, fs_info, BTRFS_ROOT_TREE_OBJECTID); root->alloc_bytenr = 0; return root; @@ -1405,8 +1410,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, if (!root) return ERR_PTR(-ENOMEM); - __setup_root(tree_root->nodesize, tree_root->sectorsize, - tree_root->stripesize, root, fs_info, objectid); + __setup_root(root, fs_info, objectid); root->root_key.objectid = objectid; root->root_key.type = BTRFS_ROOT_ITEM_KEY; root->root_key.offset = 0; @@ -1418,18 +1422,15 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, goto fail; } - memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header)); + memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header)); btrfs_set_header_bytenr(leaf, leaf->start); btrfs_set_header_generation(leaf, trans->transid); btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(leaf, objectid); root->node = leaf; - write_extent_buffer(leaf, fs_info->fsid, btrfs_header_fsid(), - BTRFS_FSID_SIZE); - write_extent_buffer(leaf, fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(leaf), - BTRFS_UUID_SIZE); + write_extent_buffer_fsid(leaf, fs_info->fsid); + write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid); btrfs_mark_buffer_dirty(leaf); root->commit_root = btrfs_root_node(root); @@ -1474,16 +1475,13 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info) { struct btrfs_root *root; - struct btrfs_root *tree_root = fs_info->tree_root; struct extent_buffer *leaf; root = btrfs_alloc_root(fs_info, GFP_NOFS); if (!root) return ERR_PTR(-ENOMEM); - __setup_root(tree_root->nodesize, tree_root->sectorsize, - tree_root->stripesize, root, fs_info, - BTRFS_TREE_LOG_OBJECTID); + __setup_root(root, fs_info, BTRFS_TREE_LOG_OBJECTID); root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; root->root_key.type = BTRFS_ROOT_ITEM_KEY; @@ -1505,15 +1503,14 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, return ERR_CAST(leaf); } - memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header)); + memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header)); btrfs_set_header_bytenr(leaf, leaf->start); btrfs_set_header_generation(leaf, trans->transid); btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV); btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); root->node = leaf; - write_extent_buffer(root->node, root->fs_info->fsid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); + write_extent_buffer_fsid(root->node, fs_info->fsid); btrfs_mark_buffer_dirty(root->node); btrfs_tree_unlock(root->node); return root; @@ -1535,10 +1532,11 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, int btrfs_add_log_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *log_root; struct btrfs_inode_item *inode_item; - log_root = alloc_log_tree(trans, root->fs_info); + log_root = alloc_log_tree(trans, fs_info); if (IS_ERR(log_root)) return PTR_ERR(log_root); @@ -1549,7 +1547,8 @@ int btrfs_add_log_tree(struct btrfs_trans_handle *trans, btrfs_set_stack_inode_generation(inode_item, 1); btrfs_set_stack_inode_size(inode_item, 3); btrfs_set_stack_inode_nlink(inode_item, 1); - btrfs_set_stack_inode_nbytes(inode_item, root->nodesize); + btrfs_set_stack_inode_nbytes(inode_item, + fs_info->nodesize); btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755); btrfs_set_root_node(&log_root->root_item, log_root->node); @@ -1581,8 +1580,7 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, goto alloc_fail; } - __setup_root(tree_root->nodesize, tree_root->sectorsize, - tree_root->stripesize, root, fs_info, key->objectid); + __setup_root(root, fs_info, key->objectid); ret = btrfs_find_root(tree_root, key, path, &root->root_item, &root->root_key); @@ -1593,7 +1591,8 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, } generation = btrfs_root_generation(&root->root_item); - root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), + root->node = read_tree_block(fs_info, + btrfs_root_bytenr(&root->root_item), generation); if (IS_ERR(root->node)) { ret = PTR_ERR(root->node); @@ -1848,6 +1847,7 @@ static void end_workqueue_fn(struct btrfs_work *work) static int cleaner_kthread(void *arg) { struct btrfs_root *root = arg; + struct btrfs_fs_info *fs_info = root->fs_info; int again; struct btrfs_trans_handle *trans; @@ -1855,40 +1855,40 @@ static int cleaner_kthread(void *arg) again = 0; /* Make the cleaner go to sleep early. */ - if (btrfs_need_cleaner_sleep(root)) + if (btrfs_need_cleaner_sleep(fs_info)) goto sleep; /* * Do not do anything if we might cause open_ctree() to block * before we have finished mounting the filesystem. */ - if (!test_bit(BTRFS_FS_OPEN, &root->fs_info->flags)) + if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags)) goto sleep; - if (!mutex_trylock(&root->fs_info->cleaner_mutex)) + if (!mutex_trylock(&fs_info->cleaner_mutex)) goto sleep; /* * Avoid the problem that we change the status of the fs * during the above check and trylock. */ - if (btrfs_need_cleaner_sleep(root)) { - mutex_unlock(&root->fs_info->cleaner_mutex); + if (btrfs_need_cleaner_sleep(fs_info)) { + mutex_unlock(&fs_info->cleaner_mutex); goto sleep; } - mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex); - btrfs_run_delayed_iputs(root); - mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex); + mutex_lock(&fs_info->cleaner_delayed_iput_mutex); + btrfs_run_delayed_iputs(fs_info); + mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); again = btrfs_clean_one_deleted_snapshot(root); - mutex_unlock(&root->fs_info->cleaner_mutex); + mutex_unlock(&fs_info->cleaner_mutex); /* * The defragger has dealt with the R/O remount and umount, * needn't do anything special here. */ - btrfs_run_defrag_inodes(root->fs_info); + btrfs_run_defrag_inodes(fs_info); /* * Acquires fs_info->delete_unused_bgs_mutex to avoid racing @@ -1898,7 +1898,7 @@ static int cleaner_kthread(void *arg) * can't hold, nor need to, fs_info->cleaner_mutex when deleting * unused block groups. */ - btrfs_delete_unused_bgs(root->fs_info); + btrfs_delete_unused_bgs(fs_info); sleep: if (!again) { set_current_state(TASK_INTERRUPTIBLE); @@ -1922,15 +1922,15 @@ sleep: trans = btrfs_attach_transaction(root); if (IS_ERR(trans)) { if (PTR_ERR(trans) != -ENOENT) - btrfs_err(root->fs_info, + btrfs_err(fs_info, "cleaner transaction attach returned %ld", PTR_ERR(trans)); } else { int ret; - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); if (ret) - btrfs_err(root->fs_info, + btrfs_err(fs_info, "cleaner open transaction commit returned %d", ret); } @@ -1941,6 +1941,7 @@ sleep: static int transaction_kthread(void *arg) { struct btrfs_root *root = arg; + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_trans_handle *trans; struct btrfs_transaction *cur; u64 transid; @@ -1950,26 +1951,26 @@ static int transaction_kthread(void *arg) do { cannot_commit = false; - delay = HZ * root->fs_info->commit_interval; - mutex_lock(&root->fs_info->transaction_kthread_mutex); + delay = HZ * fs_info->commit_interval; + mutex_lock(&fs_info->transaction_kthread_mutex); - spin_lock(&root->fs_info->trans_lock); - cur = root->fs_info->running_transaction; + spin_lock(&fs_info->trans_lock); + cur = fs_info->running_transaction; if (!cur) { - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); goto sleep; } now = get_seconds(); if (cur->state < TRANS_STATE_BLOCKED && (now < cur->start_time || - now - cur->start_time < root->fs_info->commit_interval)) { - spin_unlock(&root->fs_info->trans_lock); + now - cur->start_time < fs_info->commit_interval)) { + spin_unlock(&fs_info->trans_lock); delay = HZ * 5; goto sleep; } transid = cur->transid; - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); /* If the file system is aborted, this will always fail. */ trans = btrfs_attach_transaction(root); @@ -1979,20 +1980,20 @@ static int transaction_kthread(void *arg) goto sleep; } if (transid == trans->transid) { - btrfs_commit_transaction(trans, root); + btrfs_commit_transaction(trans); } else { - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); } sleep: - wake_up_process(root->fs_info->cleaner_kthread); - mutex_unlock(&root->fs_info->transaction_kthread_mutex); + wake_up_process(fs_info->cleaner_kthread); + mutex_unlock(&fs_info->transaction_kthread_mutex); if (unlikely(test_bit(BTRFS_FS_STATE_ERROR, - &root->fs_info->fs_state))) - btrfs_cleanup_transaction(root); + &fs_info->fs_state))) + btrfs_cleanup_transaction(fs_info); set_current_state(TASK_INTERRUPTIBLE); if (!kthread_should_stop() && - (!btrfs_transaction_blocked(root->fs_info) || + (!btrfs_transaction_blocked(fs_info) || cannot_commit)) schedule_timeout(delay); __set_current_state(TASK_RUNNING); @@ -2279,8 +2280,7 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info) if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { btrfs_free_log_root_tree(NULL, fs_info); - btrfs_destroy_pinned_extent(fs_info->tree_root, - fs_info->pinned_extents); + btrfs_destroy_pinned_extent(fs_info, fs_info->pinned_extents); } } @@ -2306,33 +2306,31 @@ static void btrfs_init_balance(struct btrfs_fs_info *fs_info) init_waitqueue_head(&fs_info->balance_wait_q); } -static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info, - struct btrfs_root *tree_root) +static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info) { - fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID; - set_nlink(fs_info->btree_inode, 1); + struct inode *inode = fs_info->btree_inode; + + inode->i_ino = BTRFS_BTREE_INODE_OBJECTID; + set_nlink(inode, 1); /* * we set the i_size on the btree inode to the max possible int. * the real end of the address space is determined by all of * the devices in the system */ - fs_info->btree_inode->i_size = OFFSET_MAX; - fs_info->btree_inode->i_mapping->a_ops = &btree_aops; + inode->i_size = OFFSET_MAX; + inode->i_mapping->a_ops = &btree_aops; - RB_CLEAR_NODE(&BTRFS_I(fs_info->btree_inode)->rb_node); - extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree, - fs_info->btree_inode->i_mapping); - BTRFS_I(fs_info->btree_inode)->io_tree.track_uptodate = 0; - extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree); + RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); + extent_io_tree_init(&BTRFS_I(inode)->io_tree, inode->i_mapping); + BTRFS_I(inode)->io_tree.track_uptodate = 0; + extent_map_tree_init(&BTRFS_I(inode)->extent_tree); - BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops; + BTRFS_I(inode)->io_tree.ops = &btree_extent_io_ops; - BTRFS_I(fs_info->btree_inode)->root = tree_root; - memset(&BTRFS_I(fs_info->btree_inode)->location, 0, - sizeof(struct btrfs_key)); - set_bit(BTRFS_INODE_DUMMY, - &BTRFS_I(fs_info->btree_inode)->runtime_flags); - btrfs_insert_inode_hash(fs_info->btree_inode); + BTRFS_I(inode)->root = fs_info->tree_root; + memset(&BTRFS_I(inode)->location, 0, sizeof(struct btrfs_key)); + set_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags); + btrfs_insert_inode_hash(inode); } static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info) @@ -2453,7 +2451,6 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, struct btrfs_fs_devices *fs_devices) { int ret; - struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *log_tree_root; struct btrfs_super_block *disk_super = fs_info->super_copy; u64 bytenr = btrfs_super_log_root(disk_super); @@ -2467,12 +2464,10 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, if (!log_tree_root) return -ENOMEM; - __setup_root(tree_root->nodesize, tree_root->sectorsize, - tree_root->stripesize, log_tree_root, fs_info, - BTRFS_TREE_LOG_OBJECTID); + __setup_root(log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID); - log_tree_root->node = read_tree_block(tree_root, bytenr, - fs_info->generation + 1); + log_tree_root->node = read_tree_block(fs_info, bytenr, + fs_info->generation + 1); if (IS_ERR(log_tree_root->node)) { btrfs_warn(fs_info, "failed to read log tree"); ret = PTR_ERR(log_tree_root->node); @@ -2487,15 +2482,15 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, /* returns with log_tree_root freed on success */ ret = btrfs_recover_log_trees(log_tree_root); if (ret) { - btrfs_handle_fs_error(tree_root->fs_info, ret, - "Failed to recover log tree"); + btrfs_handle_fs_error(fs_info, ret, + "Failed to recover log tree"); free_extent_buffer(log_tree_root->node); kfree(log_tree_root); return ret; } if (fs_info->sb->s_flags & MS_RDONLY) { - ret = btrfs_commit_super(tree_root); + ret = btrfs_commit_super(fs_info); if (ret) return ret; } @@ -2503,13 +2498,15 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, return 0; } -static int btrfs_read_roots(struct btrfs_fs_info *fs_info, - struct btrfs_root *tree_root) +static int btrfs_read_roots(struct btrfs_fs_info *fs_info) { + struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *root; struct btrfs_key location; int ret; + BUG_ON(!fs_info->tree_root); + location.objectid = BTRFS_EXTENT_TREE_OBJECTID; location.type = BTRFS_ROOT_ITEM_KEY; location.offset = 0; @@ -2720,7 +2717,7 @@ int open_ctree(struct super_block *sb, sb->s_blocksize_bits = blksize_bits(4096); sb->s_bdi = &fs_info->bdi; - btrfs_init_btree_inode(fs_info, tree_root); + btrfs_init_btree_inode(fs_info); spin_lock_init(&fs_info->block_group_cache_lock); fs_info->block_group_cache_tree = RB_ROOT; @@ -2758,14 +2755,18 @@ int open_ctree(struct super_block *sb, INIT_LIST_HEAD(&fs_info->pinned_chunks); + /* Usable values until the real ones are cached from the superblock */ + fs_info->nodesize = 4096; + fs_info->sectorsize = 4096; + fs_info->stripesize = 4096; + ret = btrfs_alloc_stripe_hash_table(fs_info); if (ret) { err = ret; goto fail_alloc; } - __setup_root(4096, 4096, 4096, tree_root, - fs_info, BTRFS_ROOT_TREE_OBJECTID); + __setup_root(tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); invalidate_bdev(fs_devices->latest_bdev); @@ -2829,7 +2830,7 @@ int open_ctree(struct super_block *sb, */ fs_info->compress_type = BTRFS_COMPRESS_ZLIB; - ret = btrfs_parse_options(tree_root, options, sb->s_flags); + ret = btrfs_parse_options(fs_info, options, sb->s_flags); if (ret) { err = ret; goto fail_alloc; @@ -2847,7 +2848,7 @@ int open_ctree(struct super_block *sb, features = btrfs_super_incompat_flags(disk_super); features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; - if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO) + if (fs_info->compress_type == BTRFS_COMPRESS_LZO) features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) @@ -2870,6 +2871,11 @@ int open_ctree(struct super_block *sb, fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids)); fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids)); + /* Cache block sizes */ + fs_info->nodesize = nodesize; + fs_info->sectorsize = sectorsize; + fs_info->stripesize = stripesize; + /* * mixed block groups end up with duplicate but slightly offset * extent buffers for the same range. It leads to corruptions @@ -2910,15 +2916,11 @@ int open_ctree(struct super_block *sb, fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, SZ_4M / PAGE_SIZE); - tree_root->nodesize = nodesize; - tree_root->sectorsize = sectorsize; - tree_root->stripesize = stripesize; - sb->s_blocksize = sectorsize; sb->s_blocksize_bits = blksize_bits(sectorsize); mutex_lock(&fs_info->chunk_mutex); - ret = btrfs_read_sys_array(tree_root); + ret = btrfs_read_sys_array(fs_info); mutex_unlock(&fs_info->chunk_mutex); if (ret) { btrfs_err(fs_info, "failed to read the system array: %d", ret); @@ -2927,10 +2929,9 @@ int open_ctree(struct super_block *sb, generation = btrfs_super_chunk_root_generation(disk_super); - __setup_root(nodesize, sectorsize, stripesize, chunk_root, - fs_info, BTRFS_CHUNK_TREE_OBJECTID); + __setup_root(chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID); - chunk_root->node = read_tree_block(chunk_root, + chunk_root->node = read_tree_block(fs_info, btrfs_super_chunk_root(disk_super), generation); if (IS_ERR(chunk_root->node) || @@ -2947,7 +2948,7 @@ int open_ctree(struct super_block *sb, read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid, btrfs_header_chunk_tree_uuid(chunk_root->node), BTRFS_UUID_SIZE); - ret = btrfs_read_chunk_tree(chunk_root); + ret = btrfs_read_chunk_tree(fs_info); if (ret) { btrfs_err(fs_info, "failed to read chunk tree: %d", ret); goto fail_tree_roots; @@ -2967,7 +2968,7 @@ int open_ctree(struct super_block *sb, retry_root_backup: generation = btrfs_super_generation(disk_super); - tree_root->node = read_tree_block(tree_root, + tree_root->node = read_tree_block(fs_info, btrfs_super_root(disk_super), generation); if (IS_ERR(tree_root->node) || @@ -2995,7 +2996,7 @@ retry_root_backup: mutex_unlock(&tree_root->objectid_mutex); - ret = btrfs_read_roots(fs_info, tree_root); + ret = btrfs_read_roots(fs_info); if (ret) goto recovery_tree_root; @@ -3048,7 +3049,7 @@ retry_root_backup: goto fail_sysfs; } - ret = btrfs_read_block_groups(fs_info->extent_root); + ret = btrfs_read_block_groups(fs_info); if (ret) { btrfs_err(fs_info, "failed to read block groups: %d", ret); goto fail_sysfs; @@ -3076,8 +3077,8 @@ retry_root_backup: if (IS_ERR(fs_info->transaction_kthread)) goto fail_cleaner; - if (!btrfs_test_opt(tree_root->fs_info, SSD) && - !btrfs_test_opt(tree_root->fs_info, NOSSD) && + if (!btrfs_test_opt(fs_info, SSD) && + !btrfs_test_opt(fs_info, NOSSD) && !fs_info->fs_devices->rotating) { btrfs_info(fs_info, "detected SSD devices, enabling SSD mode"); btrfs_set_opt(fs_info->mount_opt, SSD); @@ -3090,9 +3091,9 @@ retry_root_backup: btrfs_apply_pending_changes(fs_info); #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY - if (btrfs_test_opt(tree_root->fs_info, CHECK_INTEGRITY)) { - ret = btrfsic_mount(tree_root, fs_devices, - btrfs_test_opt(tree_root->fs_info, + if (btrfs_test_opt(fs_info, CHECK_INTEGRITY)) { + ret = btrfsic_mount(fs_info, fs_devices, + btrfs_test_opt(fs_info, CHECK_INTEGRITY_INCLUDING_EXTENT_DATA) ? 1 : 0, fs_info->check_integrity_print_mask); @@ -3108,7 +3109,7 @@ retry_root_backup: /* do not make disk changes in broken FS or nologreplay is given */ if (btrfs_super_log_root(disk_super) != 0 && - !btrfs_test_opt(tree_root->fs_info, NOLOGREPLAY)) { + !btrfs_test_opt(fs_info, NOLOGREPLAY)) { ret = btrfs_replay_log(fs_info, fs_devices); if (ret) { err = ret; @@ -3116,7 +3117,7 @@ retry_root_backup: } } - ret = btrfs_find_orphan_roots(tree_root); + ret = btrfs_find_orphan_roots(fs_info); if (ret) goto fail_qgroup; @@ -3164,19 +3165,19 @@ retry_root_backup: if (ret) { btrfs_warn(fs_info, "failed to clear free space tree: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } } - if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) && + if (btrfs_test_opt(fs_info, FREE_SPACE_TREE) && !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { btrfs_info(fs_info, "creating free space tree"); ret = btrfs_create_free_space_tree(fs_info); if (ret) { btrfs_warn(fs_info, "failed to create free space tree: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } } @@ -3185,7 +3186,7 @@ retry_root_backup: if ((ret = btrfs_orphan_cleanup(fs_info->fs_root)) || (ret = btrfs_orphan_cleanup(fs_info->tree_root))) { up_read(&fs_info->cleanup_work_sem); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } up_read(&fs_info->cleanup_work_sem); @@ -3193,14 +3194,14 @@ retry_root_backup: ret = btrfs_resume_balance_async(fs_info); if (ret) { btrfs_warn(fs_info, "failed to resume balance: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } ret = btrfs_resume_dev_replace_async(fs_info); if (ret) { btrfs_warn(fs_info, "failed to resume device replace: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } @@ -3212,10 +3213,10 @@ retry_root_backup: if (ret) { btrfs_warn(fs_info, "failed to create the UUID tree: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } - } else if (btrfs_test_opt(tree_root->fs_info, RESCAN_UUID_TREE) || + } else if (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) || fs_info->generation != btrfs_super_uuid_tree_generation(disk_super)) { btrfs_info(fs_info, "checking UUID tree"); @@ -3223,7 +3224,7 @@ retry_root_backup: if (ret) { btrfs_warn(fs_info, "failed to check the UUID tree: %d", ret); - close_ctree(tree_root); + close_ctree(fs_info); return ret; } } else { @@ -3243,7 +3244,7 @@ fail_qgroup: btrfs_free_qgroup_config(fs_info); fail_trans_kthread: kthread_stop(fs_info->transaction_kthread); - btrfs_cleanup_transaction(fs_info->tree_root); + btrfs_cleanup_transaction(fs_info); btrfs_free_fs_roots(fs_info); fail_cleaner: kthread_stop(fs_info->cleaner_kthread); @@ -3291,7 +3292,7 @@ fail: return err; recovery_tree_root: - if (!btrfs_test_opt(tree_root->fs_info, USEBACKUPROOT)) + if (!btrfs_test_opt(fs_info, USEBACKUPROOT)) goto fail_tree_roots; free_root_pointers(fs_info, 0); @@ -3317,7 +3318,7 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) struct btrfs_device *device = (struct btrfs_device *) bh->b_private; - btrfs_warn_rl_in_rcu(device->dev_root->fs_info, + btrfs_warn_rl_in_rcu(device->fs_info, "lost page write due to IO error on %s", rcu_str_deref(device->name)); /* note, we don't set_buffer_write_io_error because we have @@ -3462,7 +3463,7 @@ static int write_dev_supers(struct btrfs_device *device, bh = __getblk(device->bdev, bytenr / 4096, BTRFS_SUPER_INFO_SIZE); if (!bh) { - btrfs_err(device->dev_root->fs_info, + btrfs_err(device->fs_info, "couldn't get super buffer head for bytenr %llu", bytenr); errors++; @@ -3485,9 +3486,9 @@ static int write_dev_supers(struct btrfs_device *device, * to go down lazy. */ if (i == 0) - ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_FUA, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh); else - ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); if (ret) errors++; } @@ -3551,7 +3552,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait) bio->bi_end_io = btrfs_end_empty_barrier; bio->bi_bdev = device->bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; init_completion(&device->flush_wait); bio->bi_private = &device->flush_wait; device->flush_bio = bio; @@ -3695,7 +3696,7 @@ int btrfs_calc_num_tolerated_disk_barrier_failures( return num_tolerated_disk_barrier_failures; } -static int write_all_supers(struct btrfs_root *root, int max_mirrors) +static int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors) { struct list_head *head; struct btrfs_device *dev; @@ -3707,23 +3708,23 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) int total_errors = 0; u64 flags; - do_barriers = !btrfs_test_opt(root->fs_info, NOBARRIER); - backup_super_roots(root->fs_info); + do_barriers = !btrfs_test_opt(fs_info, NOBARRIER); + backup_super_roots(fs_info); - sb = root->fs_info->super_for_commit; + sb = fs_info->super_for_commit; dev_item = &sb->dev_item; - mutex_lock(&root->fs_info->fs_devices->device_list_mutex); - head = &root->fs_info->fs_devices->devices; - max_errors = btrfs_super_num_devices(root->fs_info->super_copy) - 1; + mutex_lock(&fs_info->fs_devices->device_list_mutex); + head = &fs_info->fs_devices->devices; + max_errors = btrfs_super_num_devices(fs_info->super_copy) - 1; if (do_barriers) { - ret = barrier_all_devices(root->fs_info); + ret = barrier_all_devices(fs_info); if (ret) { mutex_unlock( - &root->fs_info->fs_devices->device_list_mutex); - btrfs_handle_fs_error(root->fs_info, ret, - "errors while submitting device barriers."); + &fs_info->fs_devices->device_list_mutex); + btrfs_handle_fs_error(fs_info, ret, + "errors while submitting device barriers."); return ret; } } @@ -3757,13 +3758,14 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) total_errors++; } if (total_errors > max_errors) { - btrfs_err(root->fs_info, "%d errors while writing supers", - total_errors); - mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + btrfs_err(fs_info, "%d errors while writing supers", + total_errors); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); /* FUA is masked off if unsupported and can't be the reason */ - btrfs_handle_fs_error(root->fs_info, -EIO, - "%d errors while writing supers", total_errors); + btrfs_handle_fs_error(fs_info, -EIO, + "%d errors while writing supers", + total_errors); return -EIO; } @@ -3778,19 +3780,20 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors) if (ret) total_errors++; } - mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); if (total_errors > max_errors) { - btrfs_handle_fs_error(root->fs_info, -EIO, - "%d errors while writing supers", total_errors); + btrfs_handle_fs_error(fs_info, -EIO, + "%d errors while writing supers", + total_errors); return -EIO; } return 0; } int write_ctree_super(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int max_mirrors) + struct btrfs_fs_info *fs_info, int max_mirrors) { - return write_all_supers(root, max_mirrors); + return write_all_supers(fs_info, max_mirrors); } /* Drop a fs root from the radix tree and free it. */ @@ -3826,7 +3829,7 @@ static void free_fs_root(struct btrfs_root *root) { iput(root->ino_cache_inode); WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); - btrfs_free_block_rsv(root, root->orphan_block_rsv); + btrfs_free_block_rsv(root->fs_info, root->orphan_block_rsv); root->orphan_block_rsv = NULL; if (root->anon_dev) free_anon_bdev(root->anon_dev); @@ -3896,28 +3899,29 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) return err; } -int btrfs_commit_super(struct btrfs_root *root) +int btrfs_commit_super(struct btrfs_fs_info *fs_info) { + struct btrfs_root *root = fs_info->tree_root; struct btrfs_trans_handle *trans; - mutex_lock(&root->fs_info->cleaner_mutex); - btrfs_run_delayed_iputs(root); - mutex_unlock(&root->fs_info->cleaner_mutex); - wake_up_process(root->fs_info->cleaner_kthread); + mutex_lock(&fs_info->cleaner_mutex); + btrfs_run_delayed_iputs(fs_info); + mutex_unlock(&fs_info->cleaner_mutex); + wake_up_process(fs_info->cleaner_kthread); /* wait until ongoing cleanup work done */ - down_write(&root->fs_info->cleanup_work_sem); - up_write(&root->fs_info->cleanup_work_sem); + down_write(&fs_info->cleanup_work_sem); + up_write(&fs_info->cleanup_work_sem); trans = btrfs_join_transaction(root); if (IS_ERR(trans)) return PTR_ERR(trans); - return btrfs_commit_transaction(trans, root); + return btrfs_commit_transaction(trans); } -void close_ctree(struct btrfs_root *root) +void close_ctree(struct btrfs_fs_info *fs_info) { - struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_root *root = fs_info->tree_root; int ret; set_bit(BTRFS_FS_CLOSING_START, &fs_info->flags); @@ -3952,15 +3956,15 @@ void close_ctree(struct btrfs_root *root) * block groups queued for removal, the deletion will be * skipped when we quit the cleaner thread. */ - btrfs_delete_unused_bgs(root->fs_info); + btrfs_delete_unused_bgs(fs_info); - ret = btrfs_commit_super(root); + ret = btrfs_commit_super(fs_info); if (ret) btrfs_err(fs_info, "commit super ret %d", ret); } if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) - btrfs_error_commit_super(root); + btrfs_error_commit_super(fs_info); kthread_stop(fs_info->transaction_kthread); kthread_stop(fs_info->cleaner_kthread); @@ -3996,8 +4000,8 @@ void close_ctree(struct btrfs_root *root) iput(fs_info->btree_inode); #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY - if (btrfs_test_opt(root->fs_info, CHECK_INTEGRITY)) - btrfsic_unmount(root, fs_info->fs_devices); + if (btrfs_test_opt(fs_info, CHECK_INTEGRITY)) + btrfsic_unmount(fs_info->fs_devices); #endif btrfs_close_devices(fs_info->fs_devices); @@ -4014,7 +4018,7 @@ void close_ctree(struct btrfs_root *root) __btrfs_free_block_rsv(root->orphan_block_rsv); root->orphan_block_rsv = NULL; - lock_chunks(root); + mutex_lock(&fs_info->chunk_mutex); while (!list_empty(&fs_info->pinned_chunks)) { struct extent_map *em; @@ -4023,7 +4027,7 @@ void close_ctree(struct btrfs_root *root) list_del_init(&em->list); free_extent_map(em); } - unlock_chunks(root); + mutex_unlock(&fs_info->chunk_mutex); } int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, @@ -4045,6 +4049,7 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, void btrfs_mark_buffer_dirty(struct extent_buffer *buf) { + struct btrfs_fs_info *fs_info; struct btrfs_root *root; u64 transid = btrfs_header_generation(buf); int was_dirty; @@ -4059,24 +4064,25 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) return; #endif root = BTRFS_I(buf->pages[0]->mapping->host)->root; + fs_info = root->fs_info; btrfs_assert_tree_locked(buf); - if (transid != root->fs_info->generation) + if (transid != fs_info->generation) WARN(1, KERN_CRIT "btrfs transid mismatch buffer %llu, found %llu running %llu\n", - buf->start, transid, root->fs_info->generation); + buf->start, transid, fs_info->generation); was_dirty = set_extent_buffer_dirty(buf); if (!was_dirty) - __percpu_counter_add(&root->fs_info->dirty_metadata_bytes, + __percpu_counter_add(&fs_info->dirty_metadata_bytes, buf->len, - root->fs_info->dirty_metadata_batch); + fs_info->dirty_metadata_batch); #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) { - btrfs_print_leaf(root, buf); + btrfs_print_leaf(fs_info, buf); ASSERT(0); } #endif } -static void __btrfs_btree_balance_dirty(struct btrfs_root *root, +static void __btrfs_btree_balance_dirty(struct btrfs_fs_info *fs_info, int flush_delayed) { /* @@ -4089,30 +4095,31 @@ static void __btrfs_btree_balance_dirty(struct btrfs_root *root, return; if (flush_delayed) - btrfs_balance_delayed_items(root); + btrfs_balance_delayed_items(fs_info); - ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes, + ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, BTRFS_DIRTY_METADATA_THRESH); if (ret > 0) { - balance_dirty_pages_ratelimited( - root->fs_info->btree_inode->i_mapping); + balance_dirty_pages_ratelimited(fs_info->btree_inode->i_mapping); } } -void btrfs_btree_balance_dirty(struct btrfs_root *root) +void btrfs_btree_balance_dirty(struct btrfs_fs_info *fs_info) { - __btrfs_btree_balance_dirty(root, 1); + __btrfs_btree_balance_dirty(fs_info, 1); } -void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root) +void btrfs_btree_balance_dirty_nodelay(struct btrfs_fs_info *fs_info) { - __btrfs_btree_balance_dirty(root, 0); + __btrfs_btree_balance_dirty(fs_info, 0); } int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) { struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root; - return btree_read_extent_buffer_pages(root, buf, parent_transid); + struct btrfs_fs_info *fs_info = root->fs_info; + + return btree_read_extent_buffer_pages(fs_info, buf, parent_transid); } static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, @@ -4263,17 +4270,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, return ret; } -static void btrfs_error_commit_super(struct btrfs_root *root) +static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) { - mutex_lock(&root->fs_info->cleaner_mutex); - btrfs_run_delayed_iputs(root); - mutex_unlock(&root->fs_info->cleaner_mutex); + mutex_lock(&fs_info->cleaner_mutex); + btrfs_run_delayed_iputs(fs_info); + mutex_unlock(&fs_info->cleaner_mutex); - down_write(&root->fs_info->cleanup_work_sem); - up_write(&root->fs_info->cleanup_work_sem); + down_write(&fs_info->cleanup_work_sem); + up_write(&fs_info->cleanup_work_sem); /* cleanup FS via transaction */ - btrfs_cleanup_transaction(root); + btrfs_cleanup_transaction(fs_info); } static void btrfs_destroy_ordered_extents(struct btrfs_root *root) @@ -4316,7 +4323,7 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info) } static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct rb_node *node; struct btrfs_delayed_ref_root *delayed_refs; @@ -4328,7 +4335,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, spin_lock(&delayed_refs->lock); if (atomic_read(&delayed_refs->num_entries) == 0) { spin_unlock(&delayed_refs->lock); - btrfs_info(root->fs_info, "delayed_refs has NO entry"); + btrfs_info(fs_info, "delayed_refs has NO entry"); return ret; } @@ -4354,6 +4361,8 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, list) { ref->in_tree = 0; list_del(&ref->list); + if (!list_empty(&ref->add_list)) + list_del(&ref->add_list); atomic_dec(&delayed_refs->num_entries); btrfs_put_delayed_ref(ref); } @@ -4371,7 +4380,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, mutex_unlock(&head->mutex); if (pin_bytes) - btrfs_pin_extent(root, head->node.bytenr, + btrfs_pin_extent(fs_info, head->node.bytenr, head->node.num_bytes, 1); btrfs_put_delayed_ref(&head->node); cond_resched(); @@ -4435,7 +4444,7 @@ static void btrfs_destroy_all_delalloc_inodes(struct btrfs_fs_info *fs_info) spin_unlock(&fs_info->delalloc_root_lock); } -static int btrfs_destroy_marked_extents(struct btrfs_root *root, +static int btrfs_destroy_marked_extents(struct btrfs_fs_info *fs_info, struct extent_io_tree *dirty_pages, int mark) { @@ -4452,8 +4461,8 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, clear_extent_bits(dirty_pages, start, end, mark); while (start <= end) { - eb = btrfs_find_tree_block(root->fs_info, start); - start += root->nodesize; + eb = find_extent_buffer(fs_info, start); + start += fs_info->nodesize; if (!eb) continue; wait_on_extent_buffer_writeback(eb); @@ -4468,7 +4477,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, return ret; } -static int btrfs_destroy_pinned_extent(struct btrfs_root *root, +static int btrfs_destroy_pinned_extent(struct btrfs_fs_info *fs_info, struct extent_io_tree *pinned_extents) { struct extent_io_tree *unpin; @@ -4486,15 +4495,15 @@ again: break; clear_extent_dirty(unpin, start, end); - btrfs_error_unpin_extent_range(root, start, end); + btrfs_error_unpin_extent_range(fs_info, start, end); cond_resched(); } if (loop) { - if (unpin == &root->fs_info->freed_extents[0]) - unpin = &root->fs_info->freed_extents[1]; + if (unpin == &fs_info->freed_extents[0]) + unpin = &fs_info->freed_extents[1]; else - unpin = &root->fs_info->freed_extents[0]; + unpin = &fs_info->freed_extents[0]; loop = false; goto again; } @@ -4517,7 +4526,7 @@ static void btrfs_cleanup_bg_io(struct btrfs_block_group_cache *cache) } void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *cache; @@ -4527,8 +4536,7 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans, struct btrfs_block_group_cache, dirty_list); if (!cache) { - btrfs_err(root->fs_info, - "orphan block group dirty_bgs list"); + btrfs_err(fs_info, "orphan block group dirty_bgs list"); spin_unlock(&cur_trans->dirty_bgs_lock); return; } @@ -4556,8 +4564,7 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans, struct btrfs_block_group_cache, io_list); if (!cache) { - btrfs_err(root->fs_info, - "orphan block group on io_bgs list"); + btrfs_err(fs_info, "orphan block group on io_bgs list"); return; } @@ -4570,27 +4577,27 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans, } void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { - btrfs_cleanup_dirty_bgs(cur_trans, root); + btrfs_cleanup_dirty_bgs(cur_trans, fs_info); ASSERT(list_empty(&cur_trans->dirty_bgs)); ASSERT(list_empty(&cur_trans->io_bgs)); - btrfs_destroy_delayed_refs(cur_trans, root); + btrfs_destroy_delayed_refs(cur_trans, fs_info); cur_trans->state = TRANS_STATE_COMMIT_START; - wake_up(&root->fs_info->transaction_blocked_wait); + wake_up(&fs_info->transaction_blocked_wait); cur_trans->state = TRANS_STATE_UNBLOCKED; - wake_up(&root->fs_info->transaction_wait); + wake_up(&fs_info->transaction_wait); - btrfs_destroy_delayed_inodes(root); - btrfs_assert_delayed_root_empty(root); + btrfs_destroy_delayed_inodes(fs_info); + btrfs_assert_delayed_root_empty(fs_info); - btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, + btrfs_destroy_marked_extents(fs_info, &cur_trans->dirty_pages, EXTENT_DIRTY); - btrfs_destroy_pinned_extent(root, - root->fs_info->pinned_extents); + btrfs_destroy_pinned_extent(fs_info, + fs_info->pinned_extents); cur_trans->state =TRANS_STATE_COMPLETED; wake_up(&cur_trans->commit_wait); @@ -4601,27 +4608,27 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, */ } -static int btrfs_cleanup_transaction(struct btrfs_root *root) +static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info) { struct btrfs_transaction *t; - mutex_lock(&root->fs_info->transaction_kthread_mutex); + mutex_lock(&fs_info->transaction_kthread_mutex); - spin_lock(&root->fs_info->trans_lock); - while (!list_empty(&root->fs_info->trans_list)) { - t = list_first_entry(&root->fs_info->trans_list, + spin_lock(&fs_info->trans_lock); + while (!list_empty(&fs_info->trans_list)) { + t = list_first_entry(&fs_info->trans_list, struct btrfs_transaction, list); if (t->state >= TRANS_STATE_COMMIT_START) { atomic_inc(&t->use_count); - spin_unlock(&root->fs_info->trans_lock); - btrfs_wait_for_commit(root, t->transid); + spin_unlock(&fs_info->trans_lock); + btrfs_wait_for_commit(fs_info, t->transid); btrfs_put_transaction(t); - spin_lock(&root->fs_info->trans_lock); + spin_lock(&fs_info->trans_lock); continue; } - if (t == root->fs_info->running_transaction) { + if (t == fs_info->running_transaction) { t->state = TRANS_STATE_COMMIT_DOING; - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); /* * We wait for 0 num_writers since we don't hold a trans * handle open currently for this transaction. @@ -4629,27 +4636,27 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) wait_event(t->writer_wait, atomic_read(&t->num_writers) == 0); } else { - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); } - btrfs_cleanup_one_transaction(t, root); + btrfs_cleanup_one_transaction(t, fs_info); - spin_lock(&root->fs_info->trans_lock); - if (t == root->fs_info->running_transaction) - root->fs_info->running_transaction = NULL; + spin_lock(&fs_info->trans_lock); + if (t == fs_info->running_transaction) + fs_info->running_transaction = NULL; list_del_init(&t->list); - spin_unlock(&root->fs_info->trans_lock); + spin_unlock(&fs_info->trans_lock); btrfs_put_transaction(t); - trace_btrfs_transaction_commit(root); - spin_lock(&root->fs_info->trans_lock); - } - spin_unlock(&root->fs_info->trans_lock); - btrfs_destroy_all_ordered_extents(root->fs_info); - btrfs_destroy_delayed_inodes(root); - btrfs_assert_delayed_root_empty(root); - btrfs_destroy_pinned_extent(root, root->fs_info->pinned_extents); - btrfs_destroy_all_delalloc_inodes(root->fs_info); - mutex_unlock(&root->fs_info->transaction_kthread_mutex); + trace_btrfs_transaction_commit(fs_info->tree_root); + spin_lock(&fs_info->trans_lock); + } + spin_unlock(&fs_info->trans_lock); + btrfs_destroy_all_ordered_extents(fs_info); + btrfs_destroy_delayed_inodes(fs_info); + btrfs_assert_delayed_root_empty(fs_info); + btrfs_destroy_pinned_extent(fs_info, fs_info->pinned_extents); + btrfs_destroy_all_delalloc_inodes(fs_info); + mutex_unlock(&fs_info->transaction_kthread_mutex); return 0; } diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 1a3237e5700f..44dcd9af6b7c 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -44,27 +44,26 @@ static inline u64 btrfs_sb_offset(int mirror) struct btrfs_device; struct btrfs_fs_devices; -struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, - u64 parent_transid); -void readahead_tree_block(struct btrfs_root *root, u64 bytenr); -int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, +struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, + u64 bytenr, u64 parent_transid); +void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr); +int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr, int mirror_num, struct extent_buffer **eb); -struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, - u64 bytenr); +struct extent_buffer *btrfs_find_create_tree_block( + struct btrfs_fs_info *fs_info, + u64 bytenr); void clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct extent_buffer *buf); int open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_devices, char *options); -void close_ctree(struct btrfs_root *root); +void close_ctree(struct btrfs_fs_info *fs_info); int write_ctree_super(struct btrfs_trans_handle *trans, - struct btrfs_root *root, int max_mirrors); + struct btrfs_fs_info *fs_info, int max_mirrors); struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num, struct buffer_head **bh_ret); -int btrfs_commit_super(struct btrfs_root *root); -struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info, - u64 bytenr); +int btrfs_commit_super(struct btrfs_fs_info *fs_info); struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, struct btrfs_key *location); int btrfs_init_fs_root(struct btrfs_root *root); @@ -85,15 +84,14 @@ btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, } int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); -void btrfs_btree_balance_dirty(struct btrfs_root *root); -void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); +void btrfs_btree_balance_dirty(struct btrfs_fs_info *fs_info); +void btrfs_btree_balance_dirty_nodelay(struct btrfs_fs_info *fs_info); void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); void btrfs_free_fs_root(struct btrfs_root *root); #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS -struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info, - u32 sectorsize, u32 nodesize); +struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info); #endif /* @@ -121,7 +119,7 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, int atomic); int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid); u32 btrfs_csum_data(char *data, u32 seed, size_t len); -void btrfs_csum_final(u32 crc, char *result); +void btrfs_csum_final(u32 crc, u8 *result); int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, enum btrfs_wq_endio_type metadata); int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, @@ -137,9 +135,9 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, int btrfs_add_log_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root); void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); void btrfs_cleanup_one_transaction(struct btrfs_transaction *trans, - struct btrfs_root *root); + struct btrfs_fs_info *fs_info); struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 objectid); diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 2513a7f53334..340d90751263 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c @@ -153,6 +153,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh, static struct dentry *btrfs_get_parent(struct dentry *child) { struct inode *dir = d_inode(child); + struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb); struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_path *path; struct extent_buffer *leaf; @@ -169,7 +170,7 @@ static struct dentry *btrfs_get_parent(struct dentry *child) key.objectid = root->root_key.objectid; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = (u64)-1; - root = root->fs_info->tree_root; + root = fs_info->tree_root; } else { key.objectid = btrfs_ino(dir); key.type = BTRFS_INODE_REF_KEY; @@ -205,13 +206,13 @@ static struct dentry *btrfs_get_parent(struct dentry *child) btrfs_free_path(path); if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { - return btrfs_get_dentry(root->fs_info->sb, key.objectid, + return btrfs_get_dentry(fs_info->sb, key.objectid, found_key.offset, 0, 0); } key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - return d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL)); + return d_obtain_alias(btrfs_iget(fs_info->sb, &key, root, NULL)); fail: btrfs_free_path(path); return ERR_PTR(ret); @@ -222,6 +223,7 @@ static int btrfs_get_name(struct dentry *parent, char *name, { struct inode *inode = d_inode(child); struct inode *dir = d_inode(parent); + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_path *path; struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_inode_ref *iref; @@ -250,7 +252,7 @@ static int btrfs_get_name(struct dentry *parent, char *name, key.objectid = BTRFS_I(inode)->root->root_key.objectid; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = (u64)-1; - root = root->fs_info->tree_root; + root = fs_info->tree_root; } else { key.objectid = ino; key.offset = btrfs_ino(dir); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4607af38c72e..e97302f437a1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -61,10 +61,10 @@ enum { }; static int update_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, int alloc); static int __btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, u64 parent, u64 root_objectid, u64 owner_objectid, u64 owner_offset, int refs_to_drop, @@ -73,17 +73,17 @@ static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, struct extent_buffer *leaf, struct btrfs_extent_item *ei); static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 parent, u64 root_objectid, u64 flags, u64 owner, u64 offset, struct btrfs_key *ins, int ref_mod); static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 parent, u64 root_objectid, u64 flags, struct btrfs_disk_key *key, int level, struct btrfs_key *ins); static int do_chunk_alloc(struct btrfs_trans_handle *trans, - struct btrfs_root *extent_root, u64 flags, + struct btrfs_fs_info *fs_info, u64 flags, int force); static int find_next_key(struct btrfs_path *path, int level, struct btrfs_key *key); @@ -96,8 +96,6 @@ static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, u64 num_bytes, int delalloc); static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv, u64 num_bytes); -int btrfs_pin_extent(struct btrfs_root *root, - u64 bytenr, u64 num_bytes, int reserved); static int __reserve_metadata_bytes(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 orig_bytes, @@ -223,18 +221,18 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr, return ret; } -static int add_excluded_extent(struct btrfs_root *root, +static int add_excluded_extent(struct btrfs_fs_info *fs_info, u64 start, u64 num_bytes) { u64 end = start + num_bytes - 1; - set_extent_bits(&root->fs_info->freed_extents[0], + set_extent_bits(&fs_info->freed_extents[0], start, end, EXTENT_UPTODATE); - set_extent_bits(&root->fs_info->freed_extents[1], + set_extent_bits(&fs_info->freed_extents[1], start, end, EXTENT_UPTODATE); return 0; } -static void free_excluded_extents(struct btrfs_root *root, +static void free_excluded_extents(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache) { u64 start, end; @@ -242,13 +240,13 @@ static void free_excluded_extents(struct btrfs_root *root, start = cache->key.objectid; end = start + cache->key.offset - 1; - clear_extent_bits(&root->fs_info->freed_extents[0], + clear_extent_bits(&fs_info->freed_extents[0], start, end, EXTENT_UPTODATE); - clear_extent_bits(&root->fs_info->freed_extents[1], + clear_extent_bits(&fs_info->freed_extents[1], start, end, EXTENT_UPTODATE); } -static int exclude_super_stripes(struct btrfs_root *root, +static int exclude_super_stripes(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache) { u64 bytenr; @@ -259,7 +257,7 @@ static int exclude_super_stripes(struct btrfs_root *root, if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) { stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid; cache->bytes_super += stripe_len; - ret = add_excluded_extent(root, cache->key.objectid, + ret = add_excluded_extent(fs_info, cache->key.objectid, stripe_len); if (ret) return ret; @@ -267,7 +265,7 @@ static int exclude_super_stripes(struct btrfs_root *root, for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { bytenr = btrfs_sb_offset(i); - ret = btrfs_rmap_block(root->fs_info, cache->key.objectid, + ret = btrfs_rmap_block(fs_info, cache->key.objectid, bytenr, 0, &logical, &nr, &stripe_len); if (ret) return ret; @@ -293,7 +291,7 @@ static int exclude_super_stripes(struct btrfs_root *root, } cache->bytes_super += len; - ret = add_excluded_extent(root, start, len); + ret = add_excluded_extent(fs_info, start, len); if (ret) { kfree(logical); return ret; @@ -329,13 +327,13 @@ static void put_caching_control(struct btrfs_caching_control *ctl) } #ifdef CONFIG_BTRFS_DEBUG -static void fragment_free_space(struct btrfs_root *root, - struct btrfs_block_group_cache *block_group) +static void fragment_free_space(struct btrfs_block_group_cache *block_group) { + struct btrfs_fs_info *fs_info = block_group->fs_info; u64 start = block_group->key.objectid; u64 len = block_group->key.offset; u64 chunk = block_group->flags & BTRFS_BLOCK_GROUP_METADATA ? - root->nodesize : root->sectorsize; + fs_info->nodesize : fs_info->sectorsize; u64 step = chunk << 1; while (len > chunk) { @@ -394,9 +392,9 @@ u64 add_new_free_space(struct btrfs_block_group_cache *block_group, static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) { - struct btrfs_block_group_cache *block_group; - struct btrfs_fs_info *fs_info; - struct btrfs_root *extent_root; + struct btrfs_block_group_cache *block_group = caching_ctl->block_group; + struct btrfs_fs_info *fs_info = block_group->fs_info; + struct btrfs_root *extent_root = fs_info->extent_root; struct btrfs_path *path; struct extent_buffer *leaf; struct btrfs_key key; @@ -406,10 +404,6 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) int ret; bool wakeup = true; - block_group = caching_ctl->block_group; - fs_info = block_group->fs_info; - extent_root = fs_info->extent_root; - path = btrfs_alloc_path(); if (!path) return -ENOMEM; @@ -422,7 +416,7 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) * allocate from this block group until we've had a chance to fragment * the free space. */ - if (btrfs_should_fragment_free_space(extent_root, block_group)) + if (btrfs_should_fragment_free_space(block_group)) wakeup = false; #endif /* @@ -510,7 +504,7 @@ next: key.objectid); if (key.type == BTRFS_METADATA_ITEM_KEY) last = key.objectid + - fs_info->tree_root->nodesize; + fs_info->nodesize; else last = key.objectid + key.offset; @@ -561,7 +555,7 @@ static noinline void caching_thread(struct btrfs_work *work) spin_unlock(&block_group->lock); #ifdef CONFIG_BTRFS_DEBUG - if (btrfs_should_fragment_free_space(extent_root, block_group)) { + if (btrfs_should_fragment_free_space(block_group)) { u64 bytes_used; spin_lock(&block_group->space_info->lock); @@ -571,14 +565,14 @@ static noinline void caching_thread(struct btrfs_work *work) block_group->space_info->bytes_used += bytes_used >> 1; spin_unlock(&block_group->lock); spin_unlock(&block_group->space_info->lock); - fragment_free_space(extent_root, block_group); + fragment_free_space(block_group); } #endif caching_ctl->progress = (u64)-1; up_read(&fs_info->commit_root_sem); - free_excluded_extents(fs_info->extent_root, block_group); + free_excluded_extents(fs_info, block_group); mutex_unlock(&caching_ctl->mutex); wake_up(&caching_ctl->wait); @@ -668,8 +662,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, spin_unlock(&cache->lock); #ifdef CONFIG_BTRFS_DEBUG if (ret == 1 && - btrfs_should_fragment_free_space(fs_info->extent_root, - cache)) { + btrfs_should_fragment_free_space(cache)) { u64 bytes_used; spin_lock(&cache->space_info->lock); @@ -679,7 +672,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, cache->space_info->bytes_used += bytes_used >> 1; spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - fragment_free_space(fs_info->extent_root, cache); + fragment_free_space(cache); } #endif mutex_unlock(&caching_ctl->mutex); @@ -687,7 +680,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, wake_up(&caching_ctl->wait); if (ret == 1) { put_caching_control(caching_ctl); - free_excluded_extents(fs_info->extent_root, cache); + free_excluded_extents(fs_info, cache); return 0; } } else { @@ -778,7 +771,7 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info *info) } /* simple helper to search for an existing data extent at a given offset */ -int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len) +int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) { int ret; struct btrfs_key key; @@ -791,8 +784,7 @@ int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len) key.objectid = start; key.offset = len; key.type = BTRFS_EXTENT_ITEM_KEY; - ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path, - 0, 0); + ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); btrfs_free_path(path); return ret; } @@ -807,7 +799,7 @@ int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len) * the delayed refs are not processed. */ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 offset, int metadata, u64 *refs, u64 *flags) { struct btrfs_delayed_ref_head *head; @@ -825,8 +817,8 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, * If we don't have skinny metadata, don't bother doing anything * different */ - if (metadata && !btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) { - offset = root->nodesize; + if (metadata && !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) { + offset = fs_info->nodesize; metadata = 0; } @@ -847,8 +839,7 @@ search_again: else key.type = BTRFS_EXTENT_ITEM_KEY; - ret = btrfs_search_slot(trans, root->fs_info->extent_root, - &key, path, 0, 0); + ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0); if (ret < 0) goto out_free; @@ -859,7 +850,7 @@ search_again: path->slots[0]); if (key.objectid == bytenr && key.type == BTRFS_EXTENT_ITEM_KEY && - key.offset == root->nodesize) + key.offset == fs_info->nodesize) ret = 0; } } @@ -1101,7 +1092,7 @@ static int convert_extent_item_v0(struct btrfs_trans_handle *trans, return ret; BUG_ON(ret); /* Corruption */ - btrfs_extend_item(root, path, new_size); + btrfs_extend_item(root->fs_info, path, new_size); leaf = path->nodes[0]; item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); @@ -1114,7 +1105,7 @@ static int convert_extent_item_v0(struct btrfs_trans_handle *trans, BTRFS_BLOCK_FLAG_FULL_BACKREF); bi = (struct btrfs_tree_block_info *)(item + 1); /* FIXME: get first key of the block */ - memset_extent_buffer(leaf, 0, (unsigned long)bi, sizeof(*bi)); + memzero_extent_buffer(leaf, (unsigned long)bi, sizeof(*bi)); btrfs_set_tree_block_level(leaf, bi, (int)owner); } else { btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_DATA); @@ -1540,6 +1531,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, u64 parent, u64 root_objectid, u64 owner, u64 offset, int insert) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; struct extent_buffer *leaf; struct btrfs_extent_item *ei; @@ -1553,8 +1545,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, int want; int ret; int err = 0; - bool skinny_metadata = btrfs_fs_incompat(root->fs_info, - SKINNY_METADATA); + bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); key.objectid = bytenr; key.type = BTRFS_EXTENT_ITEM_KEY; @@ -1748,7 +1739,7 @@ void setup_inline_extent_backref(struct btrfs_root *root, type = extent_ref_type(parent, owner); size = btrfs_extent_inline_ref_size(type); - btrfs_extend_item(root, path, size); + btrfs_extend_item(root->fs_info, path, size); ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); refs = btrfs_extent_refs(leaf, ei); @@ -1875,7 +1866,7 @@ void update_inline_extent_backref(struct btrfs_root *root, memmove_extent_buffer(leaf, ptr, ptr + size, end - ptr - size); item_size -= size; - btrfs_truncate_item(root, path, item_size, 1); + btrfs_truncate_item(root->fs_info, path, item_size, 1); } btrfs_mark_buffer_dirty(leaf); } @@ -2022,7 +2013,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, return ret; } -int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, +int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 *actual_bytes) { int ret; @@ -2034,10 +2025,10 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, * Avoid races with device replace and make sure our bbio has devices * associated to its stripes that don't go away while we are discarding. */ - btrfs_bio_counter_inc_blocked(root->fs_info); + btrfs_bio_counter_inc_blocked(fs_info); /* Tell the block device(s) that the sectors can be discarded */ - ret = btrfs_map_block(root->fs_info, REQ_OP_DISCARD, - bytenr, &num_bytes, &bbio, 0); + ret = btrfs_map_block(fs_info, BTRFS_MAP_DISCARD, bytenr, &num_bytes, + &bbio, 0); /* Error condition is -ENOMEM */ if (!ret) { struct btrfs_bio_stripe *stripe = bbio->stripes; @@ -2067,7 +2058,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, } btrfs_put_bbio(bbio); } - btrfs_bio_counter_dec(root->fs_info); + btrfs_bio_counter_dec(fs_info); if (actual_bytes) *actual_bytes = discarded_bytes; @@ -2080,12 +2071,11 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, /* Can return -ENOMEM */ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset) { int ret; - struct btrfs_fs_info *fs_info = root->fs_info; BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID && root_objectid == BTRFS_TREE_LOG_OBJECTID); @@ -2105,13 +2095,12 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, } static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, u64 parent, u64 root_objectid, u64 owner, u64 offset, int refs_to_add, struct btrfs_delayed_extent_op *extent_op) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; struct extent_buffer *leaf; struct btrfs_extent_item *item; @@ -2154,7 +2143,7 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, path->reada = READA_FORWARD; path->leave_spinning = 1; /* now insert the actual backref */ - ret = insert_extent_backref(trans, root->fs_info->extent_root, + ret = insert_extent_backref(trans, fs_info->extent_root, path, bytenr, parent, root_objectid, owner, offset, refs_to_add); if (ret) @@ -2165,7 +2154,7 @@ out: } static int run_delayed_data_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, struct btrfs_delayed_extent_op *extent_op, int insert_reserved) @@ -2182,7 +2171,7 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans, ins.type = BTRFS_EXTENT_ITEM_KEY; ref = btrfs_delayed_node_to_data_ref(node); - trace_run_delayed_data_ref(root->fs_info, node, ref, node->action); + trace_run_delayed_data_ref(fs_info, node, ref, node->action); if (node->type == BTRFS_SHARED_DATA_REF_KEY) parent = ref->parent; @@ -2191,17 +2180,17 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans, if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { if (extent_op) flags |= extent_op->flags_to_set; - ret = alloc_reserved_file_extent(trans, root, + ret = alloc_reserved_file_extent(trans, fs_info, parent, ref_root, flags, ref->objectid, ref->offset, &ins, node->ref_mod); } else if (node->action == BTRFS_ADD_DELAYED_REF) { - ret = __btrfs_inc_extent_ref(trans, root, node, parent, + ret = __btrfs_inc_extent_ref(trans, fs_info, node, parent, ref_root, ref->objectid, ref->offset, node->ref_mod, extent_op); } else if (node->action == BTRFS_DROP_DELAYED_REF) { - ret = __btrfs_free_extent(trans, root, node, parent, + ret = __btrfs_free_extent(trans, fs_info, node, parent, ref_root, ref->objectid, ref->offset, node->ref_mod, extent_op); @@ -2230,7 +2219,7 @@ static void __run_delayed_extent_op(struct btrfs_delayed_extent_op *extent_op, } static int run_delayed_extent_op(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, struct btrfs_delayed_extent_op *extent_op) { @@ -2246,7 +2235,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, if (trans->aborted) return 0; - if (metadata && !btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) + if (metadata && !btrfs_fs_incompat(fs_info, SKINNY_METADATA)) metadata = 0; path = btrfs_alloc_path(); @@ -2266,8 +2255,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, again: path->reada = READA_FORWARD; path->leave_spinning = 1; - ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, - path, 0, 1); + ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 1); if (ret < 0) { err = ret; goto out; @@ -2302,7 +2290,7 @@ again: item_size = btrfs_item_size_nr(leaf, path->slots[0]); #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 if (item_size < sizeof(*ei)) { - ret = convert_extent_item_v0(trans, root->fs_info->extent_root, + ret = convert_extent_item_v0(trans, fs_info->extent_root, path, (u64)-1, 0); if (ret < 0) { err = ret; @@ -2323,7 +2311,7 @@ out: } static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, struct btrfs_delayed_extent_op *extent_op, int insert_reserved) @@ -2333,11 +2321,10 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, struct btrfs_key ins; u64 parent = 0; u64 ref_root = 0; - bool skinny_metadata = btrfs_fs_incompat(root->fs_info, - SKINNY_METADATA); + bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); ref = btrfs_delayed_node_to_tree_ref(node); - trace_run_delayed_tree_ref(root->fs_info, node, ref, node->action); + trace_run_delayed_tree_ref(fs_info, node, ref, node->action); if (node->type == BTRFS_SHARED_BLOCK_REF_KEY) parent = ref->parent; @@ -2353,7 +2340,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, } if (node->ref_mod != 1) { - btrfs_err(root->fs_info, + btrfs_err(fs_info, "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu", node->bytenr, node->ref_mod, node->action, ref_root, parent); @@ -2361,18 +2348,18 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, } if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { BUG_ON(!extent_op || !extent_op->update_flags); - ret = alloc_reserved_tree_block(trans, root, + ret = alloc_reserved_tree_block(trans, fs_info, parent, ref_root, extent_op->flags_to_set, &extent_op->key, ref->level, &ins); } else if (node->action == BTRFS_ADD_DELAYED_REF) { - ret = __btrfs_inc_extent_ref(trans, root, node, + ret = __btrfs_inc_extent_ref(trans, fs_info, node, parent, ref_root, ref->level, 0, 1, extent_op); } else if (node->action == BTRFS_DROP_DELAYED_REF) { - ret = __btrfs_free_extent(trans, root, node, + ret = __btrfs_free_extent(trans, fs_info, node, parent, ref_root, ref->level, 0, 1, extent_op); } else { @@ -2383,7 +2370,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, /* helper function to actually process a single delayed ref entry */ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_delayed_ref_node *node, struct btrfs_delayed_extent_op *extent_op, int insert_reserved) @@ -2392,7 +2379,7 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, if (trans->aborted) { if (insert_reserved) - btrfs_pin_extent(root, node->bytenr, + btrfs_pin_extent(fs_info, node->bytenr, node->num_bytes, 1); return 0; } @@ -2407,33 +2394,31 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, */ BUG_ON(extent_op); head = btrfs_delayed_node_to_head(node); - trace_run_delayed_ref_head(root->fs_info, node, head, - node->action); + trace_run_delayed_ref_head(fs_info, node, head, node->action); if (insert_reserved) { - btrfs_pin_extent(root, node->bytenr, + btrfs_pin_extent(fs_info, node->bytenr, node->num_bytes, 1); if (head->is_data) { - ret = btrfs_del_csums(trans, root, + ret = btrfs_del_csums(trans, fs_info, node->bytenr, node->num_bytes); } } /* Also free its reserved qgroup space */ - btrfs_qgroup_free_delayed_ref(root->fs_info, - head->qgroup_ref_root, + btrfs_qgroup_free_delayed_ref(fs_info, head->qgroup_ref_root, head->qgroup_reserved); return ret; } if (node->type == BTRFS_TREE_BLOCK_REF_KEY || node->type == BTRFS_SHARED_BLOCK_REF_KEY) - ret = run_delayed_tree_ref(trans, root, node, extent_op, + ret = run_delayed_tree_ref(trans, fs_info, node, extent_op, insert_reserved); else if (node->type == BTRFS_EXTENT_DATA_REF_KEY || node->type == BTRFS_SHARED_DATA_REF_KEY) - ret = run_delayed_data_ref(trans, root, node, extent_op, + ret = run_delayed_data_ref(trans, fs_info, node, extent_op, insert_reserved); else BUG(); @@ -2454,13 +2439,14 @@ select_delayed_ref(struct btrfs_delayed_ref_head *head) * the extent item from the extent tree, when there still are references * to add, which would fail because they would not find the extent item. */ - list_for_each_entry(ref, &head->ref_list, list) { - if (ref->action == BTRFS_ADD_DELAYED_REF) - return ref; - } + if (!list_empty(&head->ref_add_list)) + return list_first_entry(&head->ref_add_list, + struct btrfs_delayed_ref_node, add_list); - return list_entry(head->ref_list.next, struct btrfs_delayed_ref_node, - list); + ref = list_first_entry(&head->ref_list, struct btrfs_delayed_ref_node, + list); + ASSERT(list_empty(&ref->add_list)); + return ref; } /* @@ -2468,14 +2454,13 @@ select_delayed_ref(struct btrfs_delayed_ref_head *head) * Returns -ENOMEM or -EIO on failure and will abort the transaction. */ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, unsigned long nr) { struct btrfs_delayed_ref_root *delayed_refs; struct btrfs_delayed_ref_node *ref; struct btrfs_delayed_ref_head *locked_ref = NULL; struct btrfs_delayed_extent_op *extent_op; - struct btrfs_fs_info *fs_info = root->fs_info; ktime_t start = ktime_get(); int ret; unsigned long count = 0; @@ -2574,7 +2559,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, if (extent_op) { spin_unlock(&locked_ref->lock); - ret = run_delayed_extent_op(trans, root, + ret = run_delayed_extent_op(trans, fs_info, ref, extent_op); btrfs_free_delayed_extent_op(extent_op); @@ -2620,6 +2605,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, actual_count++; ref->in_tree = 0; list_del(&ref->list); + if (!list_empty(&ref->add_list)) + list_del(&ref->add_list); } atomic_dec(&delayed_refs->num_entries); @@ -2642,7 +2629,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, } spin_unlock(&locked_ref->lock); - ret = run_one_delayed_ref(trans, root, ref, extent_op, + ret = run_one_delayed_ref(trans, fs_info, ref, extent_op, must_insert_reserved); btrfs_free_delayed_extent_op(extent_op); @@ -2743,43 +2730,43 @@ static u64 find_middle(struct rb_root *root) } #endif -static inline u64 heads_to_leaves(struct btrfs_root *root, u64 heads) +static inline u64 heads_to_leaves(struct btrfs_fs_info *fs_info, u64 heads) { u64 num_bytes; num_bytes = heads * (sizeof(struct btrfs_extent_item) + sizeof(struct btrfs_extent_inline_ref)); - if (!btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) + if (!btrfs_fs_incompat(fs_info, SKINNY_METADATA)) num_bytes += heads * sizeof(struct btrfs_tree_block_info); /* * We don't ever fill up leaves all the way so multiply by 2 just to be * closer to what we're really going to want to use. */ - return div_u64(num_bytes, BTRFS_LEAF_DATA_SIZE(root)); + return div_u64(num_bytes, BTRFS_LEAF_DATA_SIZE(fs_info)); } /* * Takes the number of bytes to be csumm'ed and figures out how many leaves it * would require to store the csums for that many bytes. */ -u64 btrfs_csum_bytes_to_leaves(struct btrfs_root *root, u64 csum_bytes) +u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes) { u64 csum_size; u64 num_csums_per_leaf; u64 num_csums; - csum_size = BTRFS_MAX_ITEM_SIZE(root); + csum_size = BTRFS_MAX_ITEM_SIZE(fs_info); num_csums_per_leaf = div64_u64(csum_size, - (u64)btrfs_super_csum_size(root->fs_info->super_copy)); - num_csums = div64_u64(csum_bytes, root->sectorsize); + (u64)btrfs_super_csum_size(fs_info->super_copy)); + num_csums = div64_u64(csum_bytes, fs_info->sectorsize); num_csums += num_csums_per_leaf - 1; num_csums = div64_u64(num_csums, num_csums_per_leaf); return num_csums; } int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_rsv *global_rsv; u64 num_heads = trans->transaction->delayed_refs.num_heads_ready; @@ -2788,15 +2775,16 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, u64 num_bytes, num_dirty_bgs_bytes; int ret = 0; - num_bytes = btrfs_calc_trans_metadata_size(root, 1); - num_heads = heads_to_leaves(root, num_heads); + num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); + num_heads = heads_to_leaves(fs_info, num_heads); if (num_heads > 1) - num_bytes += (num_heads - 1) * root->nodesize; + num_bytes += (num_heads - 1) * fs_info->nodesize; num_bytes <<= 1; - num_bytes += btrfs_csum_bytes_to_leaves(root, csum_bytes) * root->nodesize; - num_dirty_bgs_bytes = btrfs_calc_trans_metadata_size(root, + num_bytes += btrfs_csum_bytes_to_leaves(fs_info, csum_bytes) * + fs_info->nodesize; + num_dirty_bgs_bytes = btrfs_calc_trans_metadata_size(fs_info, num_dirty_bgs); - global_rsv = &root->fs_info->global_block_rsv; + global_rsv = &fs_info->global_block_rsv; /* * If we can't allocate any more chunks lets make sure we have _lots_ of @@ -2815,9 +2803,8 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans, } int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { - struct btrfs_fs_info *fs_info = root->fs_info; u64 num_entries = atomic_read(&trans->transaction->delayed_refs.num_entries); u64 avg_runtime; @@ -2826,12 +2813,12 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, smp_mb(); avg_runtime = fs_info->avg_delayed_ref_runtime; val = num_entries * avg_runtime; - if (num_entries * avg_runtime >= NSEC_PER_SEC) + if (val >= NSEC_PER_SEC) return 1; if (val >= NSEC_PER_SEC / 2) return 2; - return btrfs_check_space_for_delayed_refs(trans, root); + return btrfs_check_space_for_delayed_refs(trans, fs_info); } struct async_delayed_refs { @@ -2844,16 +2831,21 @@ struct async_delayed_refs { struct btrfs_work work; }; +static inline struct async_delayed_refs * +to_async_delayed_refs(struct btrfs_work *work) +{ + return container_of(work, struct async_delayed_refs, work); +} + static void delayed_ref_async_start(struct btrfs_work *work) { - struct async_delayed_refs *async; + struct async_delayed_refs *async = to_async_delayed_refs(work); struct btrfs_trans_handle *trans; + struct btrfs_fs_info *fs_info = async->root->fs_info; int ret; - async = container_of(work, struct async_delayed_refs, work); - /* if the commit is already started, we don't need to wait here */ - if (btrfs_transaction_blocked(async->root->fs_info)) + if (btrfs_transaction_blocked(fs_info)) goto done; trans = btrfs_join_transaction(async->root); @@ -2872,11 +2864,11 @@ static void delayed_ref_async_start(struct btrfs_work *work) if (trans->transid > async->transid) goto end; - ret = btrfs_run_delayed_refs(trans, async->root, async->count); + ret = btrfs_run_delayed_refs(trans, fs_info, async->count); if (ret) async->error = ret; end: - ret = btrfs_end_transaction(trans, async->root); + ret = btrfs_end_transaction(trans); if (ret && !async->error) async->error = ret; done: @@ -2886,7 +2878,7 @@ done: kfree(async); } -int btrfs_async_run_delayed_refs(struct btrfs_root *root, +int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info, unsigned long count, u64 transid, int wait) { struct async_delayed_refs *async; @@ -2896,7 +2888,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root, if (!async) return -ENOMEM; - async->root = root->fs_info->tree_root; + async->root = fs_info->tree_root; async->count = count; async->error = 0; async->transid = transid; @@ -2909,7 +2901,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root, btrfs_init_work(&async->work, btrfs_extent_refs_helper, delayed_ref_async_start, NULL, NULL); - btrfs_queue_work(root->fs_info->extent_workers, &async->work); + btrfs_queue_work(fs_info->extent_workers, &async->work); if (wait) { wait_for_completion(&async->wait); @@ -2931,7 +2923,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root, * Returns <0 on error and aborts the transaction */ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, - struct btrfs_root *root, unsigned long count) + struct btrfs_fs_info *fs_info, unsigned long count) { struct rb_node *node; struct btrfs_delayed_ref_root *delayed_refs; @@ -2944,12 +2936,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, if (trans->aborted) return 0; - if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &root->fs_info->flags)) + if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags)) return 0; - if (root == root->fs_info->extent_root) - root = root->fs_info->tree_root; - delayed_refs = &trans->transaction->delayed_refs; if (count == 0) count = atomic_read(&delayed_refs->num_entries) * 2; @@ -2959,7 +2948,7 @@ again: delayed_refs->run_delayed_start = find_middle(&delayed_refs->root); #endif trans->can_flush_pending_bgs = false; - ret = __btrfs_run_delayed_refs(trans, root, count); + ret = __btrfs_run_delayed_refs(trans, fs_info, count); if (ret < 0) { btrfs_abort_transaction(trans, ret); return ret; @@ -2967,7 +2956,7 @@ again: if (run_all) { if (!list_empty(&trans->new_bgs)) - btrfs_create_pending_block_groups(trans, root); + btrfs_create_pending_block_groups(trans, fs_info); spin_lock(&delayed_refs->lock); node = rb_first(&delayed_refs->href_root); @@ -3012,7 +3001,7 @@ out: } int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 flags, int level, int is_data) { @@ -3029,7 +3018,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, extent_op->is_data = is_data ? true : false; extent_op->level = level; - ret = btrfs_add_delayed_extent_op(root->fs_info, trans, bytenr, + ret = btrfs_add_delayed_extent_op(fs_info, trans, bytenr, num_bytes, extent_op); if (ret) btrfs_free_delayed_extent_op(extent_op); @@ -3103,7 +3092,8 @@ static noinline int check_committed_ref(struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 objectid, u64 offset, u64 bytenr) { - struct btrfs_root *extent_root = root->fs_info->extent_root; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_root *extent_root = fs_info->extent_root; struct extent_buffer *leaf; struct btrfs_extent_data_ref *ref; struct btrfs_extent_inline_ref *iref; @@ -3210,6 +3200,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, struct extent_buffer *buf, int full_backref, int inc) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 bytenr; u64 num_bytes; u64 parent; @@ -3220,11 +3211,12 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, int i; int level; int ret = 0; - int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *, + int (*process_func)(struct btrfs_trans_handle *, + struct btrfs_fs_info *, u64, u64, u64, u64, u64, u64); - if (btrfs_is_testing(root->fs_info)) + if (btrfs_is_testing(fs_info)) return 0; ref_root = btrfs_header_owner(buf); @@ -3260,15 +3252,15 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); key.offset -= btrfs_file_extent_offset(buf, fi); - ret = process_func(trans, root, bytenr, num_bytes, + ret = process_func(trans, fs_info, bytenr, num_bytes, parent, ref_root, key.objectid, key.offset); if (ret) goto fail; } else { bytenr = btrfs_node_blockptr(buf, i); - num_bytes = root->nodesize; - ret = process_func(trans, root, bytenr, num_bytes, + num_bytes = fs_info->nodesize; + ret = process_func(trans, fs_info, bytenr, num_bytes, parent, ref_root, level - 1, 0); if (ret) goto fail; @@ -3292,12 +3284,12 @@ int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, } static int write_one_cache_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, struct btrfs_path *path, struct btrfs_block_group_cache *cache) { int ret; - struct btrfs_root *extent_root = root->fs_info->extent_root; + struct btrfs_root *extent_root = fs_info->extent_root; unsigned long bi; struct extent_buffer *leaf; @@ -3319,22 +3311,20 @@ fail: } static struct btrfs_block_group_cache * -next_block_group(struct btrfs_root *root, +next_block_group(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache) { struct rb_node *node; - spin_lock(&root->fs_info->block_group_cache_lock); + spin_lock(&fs_info->block_group_cache_lock); /* If our block group was removed, we need a full search. */ if (RB_EMPTY_NODE(&cache->cache_node)) { const u64 next_bytenr = cache->key.objectid + cache->key.offset; - spin_unlock(&root->fs_info->block_group_cache_lock); + spin_unlock(&fs_info->block_group_cache_lock); btrfs_put_block_group(cache); - cache = btrfs_lookup_first_block_group(root->fs_info, - next_bytenr); - return cache; + cache = btrfs_lookup_first_block_group(fs_info, next_bytenr); return cache; } node = rb_next(&cache->cache_node); btrfs_put_block_group(cache); @@ -3344,7 +3334,7 @@ next_block_group(struct btrfs_root *root, btrfs_get_block_group(cache); } else cache = NULL; - spin_unlock(&root->fs_info->block_group_cache_lock); + spin_unlock(&fs_info->block_group_cache_lock); return cache; } @@ -3352,7 +3342,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, struct btrfs_trans_handle *trans, struct btrfs_path *path) { - struct btrfs_root *root = block_group->fs_info->tree_root; + struct btrfs_fs_info *fs_info = block_group->fs_info; + struct btrfs_root *root = fs_info->tree_root; struct inode *inode = NULL; u64 alloc_hint = 0; int dcs = BTRFS_DC_ERROR; @@ -3425,8 +3416,8 @@ again: WARN_ON(ret); if (i_size_read(inode) > 0) { - ret = btrfs_check_trunc_cache_free_space(root, - &root->fs_info->global_block_rsv); + ret = btrfs_check_trunc_cache_free_space(fs_info, + &fs_info->global_block_rsv); if (ret) goto out_put; @@ -3437,7 +3428,7 @@ again: spin_lock(&block_group->lock); if (block_group->cached != BTRFS_CACHE_FINISHED || - !btrfs_test_opt(root->fs_info, SPACE_CACHE)) { + !btrfs_test_opt(fs_info, SPACE_CACHE)) { /* * don't bother trying to write stuff out _if_ * a) we're not cached, @@ -3506,14 +3497,14 @@ out: } int btrfs_setup_space_cache(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *cache, *tmp; struct btrfs_transaction *cur_trans = trans->transaction; struct btrfs_path *path; if (list_empty(&cur_trans->dirty_bgs) || - !btrfs_test_opt(root->fs_info, SPACE_CACHE)) + !btrfs_test_opt(fs_info, SPACE_CACHE)) return 0; path = btrfs_alloc_path(); @@ -3544,7 +3535,7 @@ int btrfs_setup_space_cache(struct btrfs_trans_handle *trans, * we're still allowing others to join the commit. */ int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *cache; struct btrfs_transaction *cur_trans = trans->transaction; @@ -3569,7 +3560,7 @@ again: * make sure all the block groups on our dirty list actually * exist */ - btrfs_create_pending_block_groups(trans, root); + btrfs_create_pending_block_groups(trans, fs_info); if (!path) { path = btrfs_alloc_path(); @@ -3594,9 +3585,7 @@ again: */ if (!list_empty(&cache->io_list)) { list_del_init(&cache->io_list); - btrfs_wait_cache_io(root, trans, cache, - &cache->io_ctl, path, - cache->key.objectid); + btrfs_wait_cache_io(trans, cache, path); btrfs_put_block_group(cache); } @@ -3619,7 +3608,8 @@ again: if (cache->disk_cache_state == BTRFS_DC_SETUP) { cache->io_ctl.inode = NULL; - ret = btrfs_write_out_cache(root, trans, cache, path); + ret = btrfs_write_out_cache(fs_info, trans, + cache, path); if (ret == 0 && cache->io_ctl.inode) { num_started++; should_put = 0; @@ -3638,7 +3628,8 @@ again: } } if (!ret) { - ret = write_one_cache_group(trans, root, path, cache); + ret = write_one_cache_group(trans, fs_info, + path, cache); /* * Our block group might still be attached to the list * of new block groups in the transaction handle of some @@ -3683,7 +3674,7 @@ again: * go through delayed refs for all the stuff we've just kicked off * and then loop back (just once) */ - ret = btrfs_run_delayed_refs(trans, root, 0); + ret = btrfs_run_delayed_refs(trans, fs_info, 0); if (!ret && loops == 0) { loops++; spin_lock(&cur_trans->dirty_bgs_lock); @@ -3698,7 +3689,7 @@ again: } spin_unlock(&cur_trans->dirty_bgs_lock); } else if (ret < 0) { - btrfs_cleanup_dirty_bgs(cur_trans, root); + btrfs_cleanup_dirty_bgs(cur_trans, fs_info); } btrfs_free_path(path); @@ -3706,7 +3697,7 @@ again: } int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *cache; struct btrfs_transaction *cur_trans = trans->transaction; @@ -3749,9 +3740,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, if (!list_empty(&cache->io_list)) { spin_unlock(&cur_trans->dirty_bgs_lock); list_del_init(&cache->io_list); - btrfs_wait_cache_io(root, trans, cache, - &cache->io_ctl, path, - cache->key.objectid); + btrfs_wait_cache_io(trans, cache, path); btrfs_put_block_group(cache); spin_lock(&cur_trans->dirty_bgs_lock); } @@ -3767,11 +3756,13 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, cache_save_setup(cache, trans, path); if (!ret) - ret = btrfs_run_delayed_refs(trans, root, (unsigned long) -1); + ret = btrfs_run_delayed_refs(trans, fs_info, + (unsigned long) -1); if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) { cache->io_ctl.inode = NULL; - ret = btrfs_write_out_cache(root, trans, cache, path); + ret = btrfs_write_out_cache(fs_info, trans, + cache, path); if (ret == 0 && cache->io_ctl.inode) { num_started++; should_put = 0; @@ -3785,7 +3776,8 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, } } if (!ret) { - ret = write_one_cache_group(trans, root, path, cache); + ret = write_one_cache_group(trans, fs_info, + path, cache); /* * One of the free space endio workers might have * created a new block group while updating a free space @@ -3802,8 +3794,8 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, if (ret == -ENOENT) { wait_event(cur_trans->writer_wait, atomic_read(&cur_trans->num_writers) == 1); - ret = write_one_cache_group(trans, root, path, - cache); + ret = write_one_cache_group(trans, fs_info, + path, cache); } if (ret) btrfs_abort_transaction(trans, ret); @@ -3820,8 +3812,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, cache = list_first_entry(io, struct btrfs_block_group_cache, io_list); list_del_init(&cache->io_list); - btrfs_wait_cache_io(root, trans, cache, - &cache->io_ctl, path, cache->key.objectid); + btrfs_wait_cache_io(trans, cache, path); btrfs_put_block_group(cache); } @@ -3829,12 +3820,12 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, return ret; } -int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) +int btrfs_extent_readonly(struct btrfs_fs_info *fs_info, u64 bytenr) { struct btrfs_block_group_cache *block_group; int readonly = 0; - block_group = btrfs_lookup_block_group(root->fs_info, bytenr); + block_group = btrfs_lookup_block_group(fs_info, bytenr); if (!block_group || block_group->ro) readonly = 1; if (block_group) @@ -4043,9 +4034,9 @@ static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags) * progress (either running or paused) picks the target profile (if it's * already available), otherwise falls back to plain reducing. */ -static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) +static u64 btrfs_reduce_alloc_profile(struct btrfs_fs_info *fs_info, u64 flags) { - u64 num_devices = root->fs_info->fs_devices->rw_devices; + u64 num_devices = fs_info->fs_devices->rw_devices; u64 target; u64 raid_type; u64 allowed = 0; @@ -4054,16 +4045,16 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) * see if restripe for this chunk_type is in progress, if so * try to reduce to the target profile */ - spin_lock(&root->fs_info->balance_lock); - target = get_restripe_target(root->fs_info, flags); + spin_lock(&fs_info->balance_lock); + target = get_restripe_target(fs_info, flags); if (target) { /* pick target profile only if it's already available */ if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) { - spin_unlock(&root->fs_info->balance_lock); + spin_unlock(&fs_info->balance_lock); return extended_to_chunk(target); } } - spin_unlock(&root->fs_info->balance_lock); + spin_unlock(&fs_info->balance_lock); /* First, mask out the RAID levels which aren't possible */ for (raid_type = 0; raid_type < BTRFS_NR_RAID_TYPES; raid_type++) { @@ -4088,39 +4079,40 @@ static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) return extended_to_chunk(flags | allowed); } -static u64 get_alloc_profile(struct btrfs_root *root, u64 orig_flags) +static u64 get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags) { unsigned seq; u64 flags; do { flags = orig_flags; - seq = read_seqbegin(&root->fs_info->profiles_lock); + seq = read_seqbegin(&fs_info->profiles_lock); if (flags & BTRFS_BLOCK_GROUP_DATA) - flags |= root->fs_info->avail_data_alloc_bits; + flags |= fs_info->avail_data_alloc_bits; else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) - flags |= root->fs_info->avail_system_alloc_bits; + flags |= fs_info->avail_system_alloc_bits; else if (flags & BTRFS_BLOCK_GROUP_METADATA) - flags |= root->fs_info->avail_metadata_alloc_bits; - } while (read_seqretry(&root->fs_info->profiles_lock, seq)); + flags |= fs_info->avail_metadata_alloc_bits; + } while (read_seqretry(&fs_info->profiles_lock, seq)); - return btrfs_reduce_alloc_profile(root, flags); + return btrfs_reduce_alloc_profile(fs_info, flags); } u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 flags; u64 ret; if (data) flags = BTRFS_BLOCK_GROUP_DATA; - else if (root == root->fs_info->chunk_root) + else if (root == fs_info->chunk_root) flags = BTRFS_BLOCK_GROUP_SYSTEM; else flags = BTRFS_BLOCK_GROUP_METADATA; - ret = get_alloc_profile(root, flags); + ret = get_alloc_profile(fs_info, flags); return ret; } @@ -4135,7 +4127,7 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes) int have_pinned_space; /* make sure bytes are sectorsize aligned */ - bytes = ALIGN(bytes, root->sectorsize); + bytes = ALIGN(bytes, fs_info->sectorsize); if (btrfs_is_free_space_inode(inode)) { need_commit = 0; @@ -4181,10 +4173,9 @@ alloc: if (IS_ERR(trans)) return PTR_ERR(trans); - ret = do_chunk_alloc(trans, root->fs_info->extent_root, - alloc_target, + ret = do_chunk_alloc(trans, fs_info, alloc_target, CHUNK_ALLOC_NO_FORCE); - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); if (ret < 0) { if (ret != -ENOSPC) return ret; @@ -4213,12 +4204,13 @@ alloc: /* commit the current transaction and try again */ commit_trans: if (need_commit && - !atomic_read(&root->fs_info->open_ioctl_trans)) { + !atomic_read(&fs_info->open_ioctl_trans)) { need_commit--; if (need_commit > 0) { btrfs_start_delalloc_roots(fs_info, 0, -1); - btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, -1, 0, + (u64)-1); } trans = btrfs_join_transaction(root); @@ -4228,7 +4220,7 @@ commit_trans: test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || need_commit > 0) { - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); if (ret) return ret; /* @@ -4236,21 +4228,21 @@ commit_trans: * operations. Wait for it to finish so that * more space is released. */ - mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex); - mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex); + mutex_lock(&fs_info->cleaner_delayed_iput_mutex); + mutex_unlock(&fs_info->cleaner_delayed_iput_mutex); goto again; } else { - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); } } - trace_btrfs_space_reservation(root->fs_info, + trace_btrfs_space_reservation(fs_info, "space_info:enospc", data_sinfo->flags, bytes, 1); return -ENOSPC; } data_sinfo->bytes_may_use += bytes; - trace_btrfs_space_reservation(root->fs_info, "space_info", + trace_btrfs_space_reservation(fs_info, "space_info", data_sinfo->flags, bytes, 1); spin_unlock(&data_sinfo->lock); @@ -4264,13 +4256,13 @@ commit_trans: */ int btrfs_check_data_free_space(struct inode *inode, u64 start, u64 len) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); int ret; /* align the range */ - len = round_up(start + len, root->sectorsize) - - round_down(start, root->sectorsize); - start = round_down(start, root->sectorsize); + len = round_up(start + len, fs_info->sectorsize) - + round_down(start, fs_info->sectorsize); + start = round_down(start, fs_info->sectorsize); ret = btrfs_alloc_data_chunk_ondemand(inode, len); if (ret < 0) @@ -4294,21 +4286,21 @@ int btrfs_check_data_free_space(struct inode *inode, u64 start, u64 len) void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, u64 len) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_space_info *data_sinfo; /* Make sure the range is aligned to sectorsize */ - len = round_up(start + len, root->sectorsize) - - round_down(start, root->sectorsize); - start = round_down(start, root->sectorsize); + len = round_up(start + len, fs_info->sectorsize) - + round_down(start, fs_info->sectorsize); + start = round_down(start, fs_info->sectorsize); - data_sinfo = root->fs_info->data_sinfo; + data_sinfo = fs_info->data_sinfo; spin_lock(&data_sinfo->lock); if (WARN_ON(data_sinfo->bytes_may_use < len)) data_sinfo->bytes_may_use = 0; else data_sinfo->bytes_may_use -= len; - trace_btrfs_space_reservation(root->fs_info, "space_info", + trace_btrfs_space_reservation(fs_info, "space_info", data_sinfo->flags, len, 0); spin_unlock(&data_sinfo->lock); } @@ -4322,6 +4314,13 @@ void btrfs_free_reserved_data_space_noquota(struct inode *inode, u64 start, */ void btrfs_free_reserved_data_space(struct inode *inode, u64 start, u64 len) { + struct btrfs_root *root = BTRFS_I(inode)->root; + + /* Make sure the range is aligned to sectorsize */ + len = round_up(start + len, root->fs_info->sectorsize) - + round_down(start, root->fs_info->sectorsize); + start = round_down(start, root->fs_info->sectorsize); + btrfs_free_reserved_data_space_noquota(inode, start, len); btrfs_qgroup_free_data(inode, start, len); } @@ -4344,10 +4343,10 @@ static inline u64 calc_global_rsv_need_space(struct btrfs_block_rsv *global) return (global->size << 1); } -static int should_alloc_chunk(struct btrfs_root *root, +static int should_alloc_chunk(struct btrfs_fs_info *fs_info, struct btrfs_space_info *sinfo, int force) { - struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved; u64 thresh; @@ -4368,7 +4367,7 @@ static int should_alloc_chunk(struct btrfs_root *root, * about 1% of the FS size. */ if (force == CHUNK_ALLOC_LIMITED) { - thresh = btrfs_super_total_bytes(root->fs_info->super_copy); + thresh = btrfs_super_total_bytes(fs_info->super_copy); thresh = max_t(u64, SZ_64M, div_factor_fine(thresh, 1)); if (num_bytes - num_allocated < thresh) @@ -4380,7 +4379,7 @@ static int should_alloc_chunk(struct btrfs_root *root, return 1; } -static u64 get_profile_num_devs(struct btrfs_root *root, u64 type) +static u64 get_profile_num_devs(struct btrfs_fs_info *fs_info, u64 type) { u64 num_dev; @@ -4388,7 +4387,7 @@ static u64 get_profile_num_devs(struct btrfs_root *root, u64 type) BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) - num_dev = root->fs_info->fs_devices->rw_devices; + num_dev = fs_info->fs_devices->rw_devices; else if (type & BTRFS_BLOCK_GROUP_RAID1) num_dev = 2; else @@ -4403,8 +4402,7 @@ static u64 get_profile_num_devs(struct btrfs_root *root, u64 type) * removing a chunk. */ void check_system_chunk(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - u64 type) + struct btrfs_fs_info *fs_info, u64 type) { struct btrfs_space_info *info; u64 left; @@ -4416,43 +4414,43 @@ void check_system_chunk(struct btrfs_trans_handle *trans, * Needed because we can end up allocating a system chunk and for an * atomic and race free space reservation in the chunk block reserve. */ - ASSERT(mutex_is_locked(&root->fs_info->chunk_mutex)); + ASSERT(mutex_is_locked(&fs_info->chunk_mutex)); - info = __find_space_info(root->fs_info, BTRFS_BLOCK_GROUP_SYSTEM); + info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM); spin_lock(&info->lock); left = info->total_bytes - info->bytes_used - info->bytes_pinned - info->bytes_reserved - info->bytes_readonly - info->bytes_may_use; spin_unlock(&info->lock); - num_devs = get_profile_num_devs(root, type); + num_devs = get_profile_num_devs(fs_info, type); /* num_devs device items to update and 1 chunk item to add or remove */ - thresh = btrfs_calc_trunc_metadata_size(root, num_devs) + - btrfs_calc_trans_metadata_size(root, 1); + thresh = btrfs_calc_trunc_metadata_size(fs_info, num_devs) + + btrfs_calc_trans_metadata_size(fs_info, 1); - if (left < thresh && btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) { - btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu", - left, thresh, type); - dump_space_info(root->fs_info, info, 0, 0); + if (left < thresh && btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { + btrfs_info(fs_info, "left=%llu, need=%llu, flags=%llu", + left, thresh, type); + dump_space_info(fs_info, info, 0, 0); } if (left < thresh) { u64 flags; - flags = btrfs_get_alloc_profile(root->fs_info->chunk_root, 0); + flags = btrfs_get_alloc_profile(fs_info->chunk_root, 0); /* * Ignore failure to create system chunk. We might end up not * needing it, as we might not need to COW all nodes/leafs from * the paths we visit in the chunk tree (they were already COWed * or created in the current transaction for example). */ - ret = btrfs_alloc_chunk(trans, root, flags); + ret = btrfs_alloc_chunk(trans, fs_info, flags); } if (!ret) { - ret = btrfs_block_rsv_add(root->fs_info->chunk_root, - &root->fs_info->chunk_block_rsv, + ret = btrfs_block_rsv_add(fs_info->chunk_root, + &fs_info->chunk_block_rsv, thresh, BTRFS_RESERVE_NO_FLUSH); if (!ret) trans->chunk_bytes_reserved += thresh; @@ -4469,10 +4467,9 @@ void check_system_chunk(struct btrfs_trans_handle *trans, * - return errors including -ENOSPC otherwise. */ static int do_chunk_alloc(struct btrfs_trans_handle *trans, - struct btrfs_root *extent_root, u64 flags, int force) + struct btrfs_fs_info *fs_info, u64 flags, int force) { struct btrfs_space_info *space_info; - struct btrfs_fs_info *fs_info = extent_root->fs_info; int wait_for_alloc = 0; int ret = 0; @@ -4480,10 +4477,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, if (trans->allocating_chunk) return -ENOSPC; - space_info = __find_space_info(extent_root->fs_info, flags); + space_info = __find_space_info(fs_info, flags); if (!space_info) { - ret = update_space_info(extent_root->fs_info, flags, - 0, 0, 0, &space_info); + ret = update_space_info(fs_info, flags, 0, 0, 0, &space_info); BUG_ON(ret); /* -ENOMEM */ } BUG_ON(!space_info); /* Logic error */ @@ -4493,7 +4489,7 @@ again: if (force < space_info->force_alloc) force = space_info->force_alloc; if (space_info->full) { - if (should_alloc_chunk(extent_root, space_info, force)) + if (should_alloc_chunk(fs_info, space_info, force)) ret = -ENOSPC; else ret = 0; @@ -4501,7 +4497,7 @@ again: return ret; } - if (!should_alloc_chunk(extent_root, space_info, force)) { + if (!should_alloc_chunk(fs_info, space_info, force)) { spin_unlock(&space_info->lock); return 0; } else if (space_info->chunk_alloc) { @@ -4551,9 +4547,9 @@ again: * Check if we have enough space in SYSTEM chunk because we may need * to update devices. */ - check_system_chunk(trans, extent_root, flags); + check_system_chunk(trans, fs_info, flags); - ret = btrfs_alloc_chunk(trans, extent_root, flags); + ret = btrfs_alloc_chunk(trans, fs_info, flags); trans->allocating_chunk = false; spin_lock(&space_info->lock); @@ -4585,7 +4581,7 @@ out: */ if (trans->can_flush_pending_bgs && trans->chunk_bytes_reserved >= (u64)SZ_2M) { - btrfs_create_pending_block_groups(trans, extent_root); + btrfs_create_pending_block_groups(trans, fs_info); btrfs_trans_release_chunk_metadata(trans); } return ret; @@ -4595,7 +4591,8 @@ static int can_overcommit(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 bytes, enum btrfs_reserve_flush_enum flush) { - struct btrfs_block_rsv *global_rsv; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; u64 profile; u64 space_size; u64 avail; @@ -4605,8 +4602,6 @@ static int can_overcommit(struct btrfs_root *root, if (space_info->flags & BTRFS_BLOCK_GROUP_DATA) return 0; - BUG_ON(root->fs_info == NULL); - global_rsv = &root->fs_info->global_block_rsv; profile = btrfs_get_alloc_profile(root, 0); used = space_info->bytes_used + space_info->bytes_reserved + space_info->bytes_pinned + space_info->bytes_readonly; @@ -4625,9 +4620,9 @@ static int can_overcommit(struct btrfs_root *root, used += space_info->bytes_may_use; - spin_lock(&root->fs_info->free_chunk_lock); - avail = root->fs_info->free_chunk_space; - spin_unlock(&root->fs_info->free_chunk_lock); + spin_lock(&fs_info->free_chunk_lock); + avail = fs_info->free_chunk_space; + spin_unlock(&fs_info->free_chunk_lock); /* * If we have dup, raid1 or raid10 then only half of the free @@ -4655,10 +4650,10 @@ static int can_overcommit(struct btrfs_root *root, return 0; } -static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, +static void btrfs_writeback_inodes_sb_nr(struct btrfs_fs_info *fs_info, unsigned long nr_pages, int nr_items) { - struct super_block *sb = root->fs_info->sb; + struct super_block *sb = fs_info->sb; if (down_read_trylock(&sb->s_umount)) { writeback_inodes_sb_nr(sb, nr_pages, WB_REASON_FS_FREE_SPACE); @@ -4671,19 +4666,19 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root, * the filesystem is readonly(all dirty pages are written to * the disk). */ - btrfs_start_delalloc_roots(root->fs_info, 0, nr_items); + btrfs_start_delalloc_roots(fs_info, 0, nr_items); if (!current->journal_info) - btrfs_wait_ordered_roots(root->fs_info, nr_items, - 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, nr_items, 0, (u64)-1); } } -static inline int calc_reclaim_items_nr(struct btrfs_root *root, u64 to_reclaim) +static inline int calc_reclaim_items_nr(struct btrfs_fs_info *fs_info, + u64 to_reclaim) { u64 bytes; int nr; - bytes = btrfs_calc_trans_metadata_size(root, 1); + bytes = btrfs_calc_trans_metadata_size(fs_info, 1); nr = (int)div64_u64(to_reclaim, bytes); if (!nr) nr = 1; @@ -4698,6 +4693,7 @@ static inline int calc_reclaim_items_nr(struct btrfs_root *root, u64 to_reclaim) static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, bool wait_ordered) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_rsv *block_rsv; struct btrfs_space_info *space_info; struct btrfs_trans_handle *trans; @@ -4710,21 +4706,20 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, enum btrfs_reserve_flush_enum flush; /* Calc the number of the pages we need flush for space reservation */ - items = calc_reclaim_items_nr(root, to_reclaim); + items = calc_reclaim_items_nr(fs_info, to_reclaim); to_reclaim = (u64)items * EXTENT_SIZE_PER_ITEM; trans = (struct btrfs_trans_handle *)current->journal_info; - block_rsv = &root->fs_info->delalloc_block_rsv; + block_rsv = &fs_info->delalloc_block_rsv; space_info = block_rsv->space_info; delalloc_bytes = percpu_counter_sum_positive( - &root->fs_info->delalloc_bytes); + &fs_info->delalloc_bytes); if (delalloc_bytes == 0) { if (trans) return; if (wait_ordered) - btrfs_wait_ordered_roots(root->fs_info, items, - 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); return; } @@ -4732,12 +4727,12 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, while (delalloc_bytes && loops < 3) { max_reclaim = min(delalloc_bytes, to_reclaim); nr_pages = max_reclaim >> PAGE_SHIFT; - btrfs_writeback_inodes_sb_nr(root, nr_pages, items); + btrfs_writeback_inodes_sb_nr(fs_info, nr_pages, items); /* * We need to wait for the async pages to actually start before * we do anything. */ - max_reclaim = atomic_read(&root->fs_info->async_delalloc_pages); + max_reclaim = atomic_read(&fs_info->async_delalloc_pages); if (!max_reclaim) goto skip_async; @@ -4746,8 +4741,8 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, else max_reclaim -= nr_pages; - wait_event(root->fs_info->async_submit_wait, - atomic_read(&root->fs_info->async_delalloc_pages) <= + wait_event(fs_info->async_submit_wait, + atomic_read(&fs_info->async_delalloc_pages) <= (int)max_reclaim); skip_async: if (!trans) @@ -4768,15 +4763,14 @@ skip_async: loops++; if (wait_ordered && !trans) { - btrfs_wait_ordered_roots(root->fs_info, items, - 0, (u64)-1); + btrfs_wait_ordered_roots(fs_info, items, 0, (u64)-1); } else { time_left = schedule_timeout_killable(1); if (time_left) break; } delalloc_bytes = percpu_counter_sum_positive( - &root->fs_info->delalloc_bytes); + &fs_info->delalloc_bytes); } } @@ -4794,7 +4788,8 @@ static int may_commit_transaction(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 bytes, int force) { - struct btrfs_block_rsv *delayed_rsv = &root->fs_info->delayed_block_rsv; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv; struct btrfs_trans_handle *trans; trans = (struct btrfs_trans_handle *)current->journal_info; @@ -4829,7 +4824,7 @@ commit: if (IS_ERR(trans)) return -ENOSPC; - return btrfs_commit_transaction(trans, root); + return btrfs_commit_transaction(trans); } struct reserve_ticket { @@ -4843,6 +4838,7 @@ static int flush_space(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 num_bytes, u64 orig_bytes, int state) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_trans_handle *trans; int nr; int ret = 0; @@ -4851,7 +4847,7 @@ static int flush_space(struct btrfs_root *root, case FLUSH_DELAYED_ITEMS_NR: case FLUSH_DELAYED_ITEMS: if (state == FLUSH_DELAYED_ITEMS_NR) - nr = calc_reclaim_items_nr(root, num_bytes) * 2; + nr = calc_reclaim_items_nr(fs_info, num_bytes) * 2; else nr = -1; @@ -4860,8 +4856,8 @@ static int flush_space(struct btrfs_root *root, ret = PTR_ERR(trans); break; } - ret = btrfs_run_delayed_items_nr(trans, root, nr); - btrfs_end_transaction(trans, root); + ret = btrfs_run_delayed_items_nr(trans, fs_info, nr); + btrfs_end_transaction(trans); break; case FLUSH_DELALLOC: case FLUSH_DELALLOC_WAIT: @@ -4874,10 +4870,10 @@ static int flush_space(struct btrfs_root *root, ret = PTR_ERR(trans); break; } - ret = do_chunk_alloc(trans, root->fs_info->extent_root, + ret = do_chunk_alloc(trans, fs_info, btrfs_get_alloc_profile(root, 0), CHUNK_ALLOC_NO_FORCE); - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); if (ret > 0 || ret == -ENOSPC) ret = 0; break; @@ -4889,7 +4885,7 @@ static int flush_space(struct btrfs_root *root, break; } - trace_btrfs_flush_space(root->fs_info, space_info->flags, num_bytes, + trace_btrfs_flush_space(fs_info, space_info->flags, num_bytes, orig_bytes, state, ret); return ret; } @@ -4935,6 +4931,7 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_root *root, static inline int need_do_async_reclaim(struct btrfs_space_info *space_info, struct btrfs_root *root, u64 used) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 thresh = div_factor_fine(space_info->total_bytes, 98); /* If we're just plain full then async reclaim just slows us down. */ @@ -4944,9 +4941,8 @@ static inline int need_do_async_reclaim(struct btrfs_space_info *space_info, if (!btrfs_calc_reclaim_metadata_size(root, space_info)) return 0; - return (used >= thresh && !btrfs_fs_closing(root->fs_info) && - !test_bit(BTRFS_FS_STATE_REMOUNTING, - &root->fs_info->fs_state)); + return (used >= thresh && !btrfs_fs_closing(fs_info) && + !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state)); } static void wake_all_tickets(struct list_head *head) @@ -5126,6 +5122,7 @@ static int __reserve_metadata_bytes(struct btrfs_root *root, u64 orig_bytes, enum btrfs_reserve_flush_enum flush) { + struct btrfs_fs_info *fs_info = root->fs_info; struct reserve_ticket ticket; u64 used; int ret = 0; @@ -5146,15 +5143,13 @@ static int __reserve_metadata_bytes(struct btrfs_root *root, */ if (used + orig_bytes <= space_info->total_bytes) { space_info->bytes_may_use += orig_bytes; - trace_btrfs_space_reservation(root->fs_info, "space_info", - space_info->flags, orig_bytes, - 1); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); ret = 0; } else if (can_overcommit(root, space_info, orig_bytes, flush)) { space_info->bytes_may_use += orig_bytes; - trace_btrfs_space_reservation(root->fs_info, "space_info", - space_info->flags, orig_bytes, - 1); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, orig_bytes, 1); ret = 0; } @@ -5173,7 +5168,7 @@ static int __reserve_metadata_bytes(struct btrfs_root *root, list_add_tail(&ticket.list, &space_info->tickets); if (!space_info->flush) { space_info->flush = 1; - trace_btrfs_trigger_flush(root->fs_info, + trace_btrfs_trigger_flush(fs_info, space_info->flags, orig_bytes, flush, "enospc"); @@ -5191,15 +5186,13 @@ static int __reserve_metadata_bytes(struct btrfs_root *root, * which means we won't have fs_info->fs_root set, so don't do * the async reclaim as we will panic. */ - if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags) && + if (!test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags) && need_do_async_reclaim(space_info, root, used) && - !work_busy(&root->fs_info->async_reclaim_work)) { - trace_btrfs_trigger_flush(root->fs_info, - space_info->flags, - orig_bytes, flush, - "preempt"); + !work_busy(&fs_info->async_reclaim_work)) { + trace_btrfs_trigger_flush(fs_info, space_info->flags, + orig_bytes, flush, "preempt"); queue_work(system_unbound_wq, - &root->fs_info->async_reclaim_work); + &fs_info->async_reclaim_work); } } spin_unlock(&space_info->lock); @@ -5207,19 +5200,19 @@ static int __reserve_metadata_bytes(struct btrfs_root *root, return ret; if (flush == BTRFS_RESERVE_FLUSH_ALL) - return wait_reserve_ticket(root->fs_info, space_info, &ticket, + return wait_reserve_ticket(fs_info, space_info, &ticket, orig_bytes); ret = 0; - priority_reclaim_metadata_space(root->fs_info, space_info, &ticket); + priority_reclaim_metadata_space(fs_info, space_info, &ticket); spin_lock(&space_info->lock); if (ticket.bytes) { if (ticket.bytes < orig_bytes) { u64 num_bytes = orig_bytes - ticket.bytes; space_info->bytes_may_use -= num_bytes; - trace_btrfs_space_reservation(root->fs_info, - "space_info", space_info->flags, - num_bytes, 0); + trace_btrfs_space_reservation(fs_info, "space_info", + space_info->flags, + num_bytes, 0); } list_del_init(&ticket.list); @@ -5249,22 +5242,20 @@ static int reserve_metadata_bytes(struct btrfs_root *root, u64 orig_bytes, enum btrfs_reserve_flush_enum flush) { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; int ret; ret = __reserve_metadata_bytes(root, block_rsv->space_info, orig_bytes, flush); if (ret == -ENOSPC && unlikely(root->orphan_cleanup_state == ORPHAN_CLEANUP_STARTED)) { - struct btrfs_block_rsv *global_rsv = - &root->fs_info->global_block_rsv; - if (block_rsv != global_rsv && !block_rsv_use_bytes(global_rsv, orig_bytes)) ret = 0; } if (ret == -ENOSPC) - trace_btrfs_space_reservation(root->fs_info, - "space_info:enospc", + trace_btrfs_space_reservation(fs_info, "space_info:enospc", block_rsv->space_info->flags, orig_bytes, 1); return ret; @@ -5274,18 +5265,19 @@ static struct btrfs_block_rsv *get_block_rsv( const struct btrfs_trans_handle *trans, const struct btrfs_root *root) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_rsv *block_rsv = NULL; if (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || - (root == root->fs_info->csum_root && trans->adding_csums) || - (root == root->fs_info->uuid_root)) + (root == fs_info->csum_root && trans->adding_csums) || + (root == fs_info->uuid_root)) block_rsv = trans->block_rsv; if (!block_rsv) block_rsv = root->block_rsv; if (!block_rsv) - block_rsv = &root->fs_info->empty_block_rsv; + block_rsv = &fs_info->empty_block_rsv; return block_rsv; } @@ -5507,11 +5499,10 @@ void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type) rsv->type = type; } -struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root, +struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info, unsigned short type) { struct btrfs_block_rsv *block_rsv; - struct btrfs_fs_info *fs_info = root->fs_info; block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS); if (!block_rsv) @@ -5523,12 +5514,12 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root, return block_rsv; } -void btrfs_free_block_rsv(struct btrfs_root *root, +void btrfs_free_block_rsv(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv) { if (!rsv) return; - btrfs_block_rsv_release(root, rsv, (u64)-1); + btrfs_block_rsv_release(fs_info, rsv, (u64)-1); kfree(rsv); } @@ -5555,8 +5546,7 @@ int btrfs_block_rsv_add(struct btrfs_root *root, return ret; } -int btrfs_block_rsv_check(struct btrfs_root *root, - struct btrfs_block_rsv *block_rsv, int min_factor) +int btrfs_block_rsv_check(struct btrfs_block_rsv *block_rsv, int min_factor) { u64 num_bytes = 0; int ret = -ENOSPC; @@ -5603,16 +5593,16 @@ int btrfs_block_rsv_refill(struct btrfs_root *root, return ret; } -void btrfs_block_rsv_release(struct btrfs_root *root, +void btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *block_rsv, u64 num_bytes) { - struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; + if (global_rsv == block_rsv || block_rsv->space_info != global_rsv->space_info) global_rsv = NULL; - block_rsv_release_bytes(root->fs_info, block_rsv, global_rsv, - num_bytes); + block_rsv_release_bytes(fs_info, block_rsv, global_rsv, num_bytes); } static void update_global_block_rsv(struct btrfs_fs_info *fs_info) @@ -5707,7 +5697,7 @@ static void release_global_block_rsv(struct btrfs_fs_info *fs_info) } void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { if (!trans->block_rsv) return; @@ -5715,9 +5705,10 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans, if (!trans->bytes_reserved) return; - trace_btrfs_space_reservation(root->fs_info, "transaction", + trace_btrfs_space_reservation(fs_info, "transaction", trans->transid, trans->bytes_reserved, 0); - btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved); + btrfs_block_rsv_release(fs_info, trans->block_rsv, + trans->bytes_reserved); trans->bytes_reserved = 0; } @@ -5743,6 +5734,7 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans) int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, struct inode *inode) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; /* * We always use trans->block_rsv here as we will have reserved space @@ -5758,19 +5750,22 @@ int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans, * added it, so this takes the reservation so we can release it later * when we are truly done with the orphan item. */ - u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); - trace_btrfs_space_reservation(root->fs_info, "orphan", + u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); + + trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), num_bytes, 1); return btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1); } void btrfs_orphan_release_metadata(struct inode *inode) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; - u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); - trace_btrfs_space_reservation(root->fs_info, "orphan", + u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, 1); + + trace_btrfs_space_reservation(fs_info, "orphan", btrfs_ino(inode), num_bytes, 0); - btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); + btrfs_block_rsv_release(fs_info, root->orphan_block_rsv, num_bytes); } /* @@ -5795,11 +5790,12 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, { u64 num_bytes; int ret; - struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; - if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) { + if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { /* One for parent inode, two for dir entries */ - num_bytes = 3 * root->nodesize; + num_bytes = 3 * fs_info->nodesize; ret = btrfs_qgroup_reserve_meta(root, num_bytes); if (ret) return ret; @@ -5809,8 +5805,8 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, *qgroup_reserved = num_bytes; - num_bytes = btrfs_calc_trans_metadata_size(root, items); - rsv->space_info = __find_space_info(root->fs_info, + num_bytes = btrfs_calc_trans_metadata_size(fs_info, items); + rsv->space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); ret = btrfs_block_rsv_add(root, rsv, num_bytes, BTRFS_RESERVE_FLUSH_ALL); @@ -5824,11 +5820,11 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, return ret; } -void btrfs_subvolume_release_metadata(struct btrfs_root *root, +void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info, struct btrfs_block_rsv *rsv, u64 qgroup_reserved) { - btrfs_block_rsv_release(root, rsv, (u64)-1); + btrfs_block_rsv_release(fs_info, rsv, (u64)-1); } /** @@ -5894,35 +5890,38 @@ static unsigned drop_outstanding_extent(struct inode *inode, u64 num_bytes) static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes, int reserve) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); u64 old_csums, num_csums; if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM && BTRFS_I(inode)->csum_bytes == 0) return 0; - old_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes); + old_csums = btrfs_csum_bytes_to_leaves(fs_info, + BTRFS_I(inode)->csum_bytes); if (reserve) BTRFS_I(inode)->csum_bytes += num_bytes; else BTRFS_I(inode)->csum_bytes -= num_bytes; - num_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes); + num_csums = btrfs_csum_bytes_to_leaves(fs_info, + BTRFS_I(inode)->csum_bytes); /* No change, no need to reserve more */ if (old_csums == num_csums) return 0; if (reserve) - return btrfs_calc_trans_metadata_size(root, + return btrfs_calc_trans_metadata_size(fs_info, num_csums - old_csums); - return btrfs_calc_trans_metadata_size(root, old_csums - num_csums); + return btrfs_calc_trans_metadata_size(fs_info, old_csums - num_csums); } int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; - struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; + struct btrfs_block_rsv *block_rsv = &fs_info->delalloc_block_rsv; u64 to_reserve = 0; u64 csum_bytes; unsigned nr_extents = 0; @@ -5949,13 +5948,13 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) } if (flush != BTRFS_RESERVE_NO_FLUSH && - btrfs_transaction_in_commit(root->fs_info)) + btrfs_transaction_in_commit(fs_info)) schedule_timeout(1); if (delalloc_lock) mutex_lock(&BTRFS_I(inode)->delalloc_mutex); - num_bytes = ALIGN(num_bytes, root->sectorsize); + num_bytes = ALIGN(num_bytes, fs_info->sectorsize); spin_lock(&BTRFS_I(inode)->lock); nr_extents = (unsigned)div64_u64(num_bytes + @@ -5970,28 +5969,29 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) BTRFS_I(inode)->reserved_extents; /* We always want to reserve a slot for updating the inode. */ - to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents + 1); + to_reserve = btrfs_calc_trans_metadata_size(fs_info, nr_extents + 1); to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); csum_bytes = BTRFS_I(inode)->csum_bytes; spin_unlock(&BTRFS_I(inode)->lock); - if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) { + if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { ret = btrfs_qgroup_reserve_meta(root, - nr_extents * root->nodesize); + nr_extents * fs_info->nodesize); if (ret) goto out_fail; } ret = btrfs_block_rsv_add(root, block_rsv, to_reserve, flush); if (unlikely(ret)) { - btrfs_qgroup_free_meta(root, nr_extents * root->nodesize); + btrfs_qgroup_free_meta(root, + nr_extents * fs_info->nodesize); goto out_fail; } spin_lock(&BTRFS_I(inode)->lock); if (test_and_set_bit(BTRFS_INODE_DELALLOC_META_RESERVED, &BTRFS_I(inode)->runtime_flags)) { - to_reserve -= btrfs_calc_trans_metadata_size(root, 1); + to_reserve -= btrfs_calc_trans_metadata_size(fs_info, 1); release_extra = true; } BTRFS_I(inode)->reserved_extents += nr_extents; @@ -6001,12 +6001,11 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) mutex_unlock(&BTRFS_I(inode)->delalloc_mutex); if (to_reserve) - trace_btrfs_space_reservation(root->fs_info, "delalloc", + trace_btrfs_space_reservation(fs_info, "delalloc", btrfs_ino(inode), to_reserve, 1); if (release_extra) - btrfs_block_rsv_release(root, block_rsv, - btrfs_calc_trans_metadata_size(root, - 1)); + btrfs_block_rsv_release(fs_info, block_rsv, + btrfs_calc_trans_metadata_size(fs_info, 1)); return 0; out_fail: @@ -6061,11 +6060,11 @@ out_fail: } spin_unlock(&BTRFS_I(inode)->lock); if (dropped) - to_free += btrfs_calc_trans_metadata_size(root, dropped); + to_free += btrfs_calc_trans_metadata_size(fs_info, dropped); if (to_free) { - btrfs_block_rsv_release(root, block_rsv, to_free); - trace_btrfs_space_reservation(root->fs_info, "delalloc", + btrfs_block_rsv_release(fs_info, block_rsv, to_free); + trace_btrfs_space_reservation(fs_info, "delalloc", btrfs_ino(inode), to_free, 0); } if (delalloc_lock) @@ -6084,11 +6083,11 @@ out_fail: */ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); u64 to_free = 0; unsigned dropped; - num_bytes = ALIGN(num_bytes, root->sectorsize); + num_bytes = ALIGN(num_bytes, fs_info->sectorsize); spin_lock(&BTRFS_I(inode)->lock); dropped = drop_outstanding_extent(inode, num_bytes); @@ -6096,16 +6095,15 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) to_free = calc_csum_metadata_size(inode, num_bytes, 0); spin_unlock(&BTRFS_I(inode)->lock); if (dropped > 0) - to_free += btrfs_calc_trans_metadata_size(root, dropped); + to_free += btrfs_calc_trans_metadata_size(fs_info, dropped); - if (btrfs_is_testing(root->fs_info)) + if (btrfs_is_testing(fs_info)) return; - trace_btrfs_space_reservation(root->fs_info, "delalloc", + trace_btrfs_space_reservation(fs_info, "delalloc", btrfs_ino(inode), to_free, 0); - btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv, - to_free); + btrfs_block_rsv_release(fs_info, &fs_info->delalloc_block_rsv, to_free); } /** @@ -6166,11 +6164,10 @@ void btrfs_delalloc_release_space(struct inode *inode, u64 start, u64 len) } static int update_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, + struct btrfs_fs_info *info, u64 bytenr, u64 num_bytes, int alloc) { struct btrfs_block_group_cache *cache = NULL; - struct btrfs_fs_info *info = root->fs_info; u64 total = num_bytes; u64 old_val; u64 byte_in_group; @@ -6211,7 +6208,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, spin_lock(&cache->space_info->lock); spin_lock(&cache->lock); - if (btrfs_test_opt(root->fs_info, SPACE_CACHE) && + if (btrfs_test_opt(info, SPACE_CACHE) && cache->disk_cache_state < BTRFS_DC_CLEAR) cache->disk_cache_state = BTRFS_DC_CLEAR; @@ -6236,7 +6233,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - trace_btrfs_space_reservation(root->fs_info, "pinned", + trace_btrfs_space_reservation(info, "pinned", cache->space_info->flags, num_bytes, 1); set_extent_dirty(info->pinned_extents, @@ -6276,19 +6273,19 @@ static int update_block_group(struct btrfs_trans_handle *trans, return 0; } -static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) +static u64 first_logical_byte(struct btrfs_fs_info *fs_info, u64 search_start) { struct btrfs_block_group_cache *cache; u64 bytenr; - spin_lock(&root->fs_info->block_group_cache_lock); - bytenr = root->fs_info->first_logical_byte; - spin_unlock(&root->fs_info->block_group_cache_lock); + spin_lock(&fs_info->block_group_cache_lock); + bytenr = fs_info->first_logical_byte; + spin_unlock(&fs_info->block_group_cache_lock); if (bytenr < (u64)-1) return bytenr; - cache = btrfs_lookup_first_block_group(root->fs_info, search_start); + cache = btrfs_lookup_first_block_group(fs_info, search_start); if (!cache) return 0; @@ -6298,7 +6295,7 @@ static u64 first_logical_byte(struct btrfs_root *root, u64 search_start) return bytenr; } -static int pin_down_extent(struct btrfs_root *root, +static int pin_down_extent(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *cache, u64 bytenr, u64 num_bytes, int reserved) { @@ -6313,9 +6310,9 @@ static int pin_down_extent(struct btrfs_root *root, spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); - trace_btrfs_space_reservation(root->fs_info, "pinned", + trace_btrfs_space_reservation(fs_info, "pinned", cache->space_info->flags, num_bytes, 1); - set_extent_dirty(root->fs_info->pinned_extents, bytenr, + set_extent_dirty(fs_info->pinned_extents, bytenr, bytenr + num_bytes - 1, GFP_NOFS | __GFP_NOFAIL); return 0; } @@ -6323,15 +6320,15 @@ static int pin_down_extent(struct btrfs_root *root, /* * this function must be called within transaction */ -int btrfs_pin_extent(struct btrfs_root *root, +int btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, int reserved) { struct btrfs_block_group_cache *cache; - cache = btrfs_lookup_block_group(root->fs_info, bytenr); + cache = btrfs_lookup_block_group(fs_info, bytenr); BUG_ON(!cache); /* Logic error */ - pin_down_extent(root, cache, bytenr, num_bytes, reserved); + pin_down_extent(fs_info, cache, bytenr, num_bytes, reserved); btrfs_put_block_group(cache); return 0; @@ -6340,13 +6337,13 @@ int btrfs_pin_extent(struct btrfs_root *root, /* * this function must be called within transaction */ -int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, +int btrfs_pin_extent_for_log_replay(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes) { struct btrfs_block_group_cache *cache; int ret; - cache = btrfs_lookup_block_group(root->fs_info, bytenr); + cache = btrfs_lookup_block_group(fs_info, bytenr); if (!cache) return -EINVAL; @@ -6358,7 +6355,7 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, */ cache_block_group(cache, 1); - pin_down_extent(root, cache, bytenr, num_bytes, 0); + pin_down_extent(fs_info, cache, bytenr, num_bytes, 0); /* remove us from the free space cache (if we're there at all) */ ret = btrfs_remove_free_space(cache, bytenr, num_bytes); @@ -6366,13 +6363,14 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, return ret; } -static int __exclude_logged_extent(struct btrfs_root *root, u64 start, u64 num_bytes) +static int __exclude_logged_extent(struct btrfs_fs_info *fs_info, + u64 start, u64 num_bytes) { int ret; struct btrfs_block_group_cache *block_group; struct btrfs_caching_control *caching_ctl; - block_group = btrfs_lookup_block_group(root->fs_info, start); + block_group = btrfs_lookup_block_group(fs_info, start); if (!block_group) return -EINVAL; @@ -6387,7 +6385,7 @@ static int __exclude_logged_extent(struct btrfs_root *root, u64 start, u64 num_b mutex_lock(&caching_ctl->mutex); if (start >= caching_ctl->progress) { - ret = add_excluded_extent(root, start, num_bytes); + ret = add_excluded_extent(fs_info, start, num_bytes); } else if (start + num_bytes <= caching_ctl->progress) { ret = btrfs_remove_free_space(block_group, start, num_bytes); @@ -6401,7 +6399,7 @@ static int __exclude_logged_extent(struct btrfs_root *root, u64 start, u64 num_b num_bytes = (start + num_bytes) - caching_ctl->progress; start = caching_ctl->progress; - ret = add_excluded_extent(root, start, num_bytes); + ret = add_excluded_extent(fs_info, start, num_bytes); } out_lock: mutex_unlock(&caching_ctl->mutex); @@ -6411,7 +6409,7 @@ out_lock: return ret; } -int btrfs_exclude_logged_extents(struct btrfs_root *log, +int btrfs_exclude_logged_extents(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) { struct btrfs_file_extent_item *item; @@ -6419,7 +6417,7 @@ int btrfs_exclude_logged_extents(struct btrfs_root *log, int found_type; int i; - if (!btrfs_fs_incompat(log->fs_info, MIXED_GROUPS)) + if (!btrfs_fs_incompat(fs_info, MIXED_GROUPS)) return 0; for (i = 0; i < btrfs_header_nritems(eb); i++) { @@ -6434,7 +6432,7 @@ int btrfs_exclude_logged_extents(struct btrfs_root *log, continue; key.objectid = btrfs_file_extent_disk_bytenr(eb, item); key.offset = btrfs_file_extent_disk_num_bytes(eb, item); - __exclude_logged_extent(log, key.objectid, key.offset); + __exclude_logged_extent(fs_info, key.objectid, key.offset); } return 0; @@ -6499,16 +6497,9 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg) * @num_bytes: The number of bytes in question * @delalloc: The blocks are allocated for the delalloc write * - * This is called by the allocator when it reserves space. Metadata - * reservations should be called with RESERVE_ALLOC so we do the proper - * ENOSPC accounting. For data we handle the reservation through clearing the - * delalloc bits in the io_tree. We have to do this since we could end up - * allocating less disk space for the amount of data we have reserved in the - * case of compression. - * - * If this is a reservation and the block group has become read only we cannot - * make the reservation and return -EAGAIN, otherwise this function always - * succeeds. + * This is called by the allocator when it reserves space. If this is a + * reservation and the block group has become read only we cannot make the + * reservation and return -EAGAIN, otherwise this function always succeeds. */ static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, u64 ram_bytes, u64 num_bytes, int delalloc) @@ -6568,9 +6559,8 @@ static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, return ret; } void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_caching_control *next; struct btrfs_caching_control *caching_ctl; struct btrfs_block_group_cache *cache; @@ -6604,11 +6594,11 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, * what it should be based on the mount options. */ static struct btrfs_free_cluster * -fetch_cluster_info(struct btrfs_root *root, struct btrfs_space_info *space_info, - u64 *empty_cluster) +fetch_cluster_info(struct btrfs_fs_info *fs_info, + struct btrfs_space_info *space_info, u64 *empty_cluster) { struct btrfs_free_cluster *ret = NULL; - bool ssd = btrfs_test_opt(root->fs_info, SSD); + bool ssd = btrfs_test_opt(fs_info, SSD); *empty_cluster = 0; if (btrfs_mixed_space_info(space_info)) @@ -6617,20 +6607,20 @@ fetch_cluster_info(struct btrfs_root *root, struct btrfs_space_info *space_info, if (ssd) *empty_cluster = SZ_2M; if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { - ret = &root->fs_info->meta_alloc_cluster; + ret = &fs_info->meta_alloc_cluster; if (!ssd) *empty_cluster = SZ_64K; } else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) && ssd) { - ret = &root->fs_info->data_alloc_cluster; + ret = &fs_info->data_alloc_cluster; } return ret; } -static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, +static int unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end, const bool return_free_space) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_group_cache *cache = NULL; struct btrfs_space_info *space_info; struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; @@ -6650,7 +6640,7 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, cache = btrfs_lookup_block_group(fs_info, start); BUG_ON(!cache); /* Logic error */ - cluster = fetch_cluster_info(root, + cluster = fetch_cluster_info(fs_info, cache->space_info, &empty_cluster); empty_cluster <<= 1; @@ -6729,9 +6719,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, } int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_group_cache *block_group, *tmp; struct list_head *deleted_bgs; struct extent_io_tree *unpin; @@ -6753,12 +6742,12 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, break; } - if (btrfs_test_opt(root->fs_info, DISCARD)) - ret = btrfs_discard_extent(root, start, + if (btrfs_test_opt(fs_info, DISCARD)) + ret = btrfs_discard_extent(fs_info, start, end + 1 - start, NULL); clear_extent_dirty(unpin, start, end); - unpin_extent_range(root, start, end, true); + unpin_extent_range(fs_info, start, end, true); mutex_unlock(&fs_info->unused_bg_unpin_mutex); cond_resched(); } @@ -6774,7 +6763,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, ret = -EROFS; if (!trans->aborted) - ret = btrfs_discard_extent(root, + ret = btrfs_discard_extent(fs_info, block_group->key.objectid, block_group->key.offset, &trimmed); @@ -6816,7 +6805,7 @@ static void add_pinned_bytes(struct btrfs_fs_info *fs_info, u64 num_bytes, static int __btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *info, struct btrfs_delayed_ref_node *node, u64 parent, u64 root_objectid, u64 owner_objectid, u64 owner_offset, int refs_to_drop, @@ -6824,7 +6813,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, { struct btrfs_key key; struct btrfs_path *path; - struct btrfs_fs_info *info = root->fs_info; struct btrfs_root *extent_root = info->extent_root; struct extent_buffer *leaf; struct btrfs_extent_item *ei; @@ -6839,8 +6827,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, u64 bytenr = node->bytenr; u64 num_bytes = node->num_bytes; int last_ref = 0; - bool skinny_metadata = btrfs_fs_incompat(root->fs_info, - SKINNY_METADATA); + bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA); path = btrfs_alloc_path(); if (!path) @@ -6937,8 +6924,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, "umm, got %d back from search, was looking for %llu", ret, bytenr); if (ret > 0) - btrfs_print_leaf(extent_root, - path->nodes[0]); + btrfs_print_leaf(info, path->nodes[0]); } if (ret < 0) { btrfs_abort_transaction(trans, ret); @@ -6947,7 +6933,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, extent_slot = path->slots[0]; } } else if (WARN_ON(ret == -ENOENT)) { - btrfs_print_leaf(extent_root, path->nodes[0]); + btrfs_print_leaf(info, path->nodes[0]); btrfs_err(info, "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", bytenr, parent, root_objectid, owner_objectid, @@ -6984,7 +6970,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, btrfs_err(info, "umm, got %d back from search, was looking for %llu", ret, bytenr); - btrfs_print_leaf(extent_root, path->nodes[0]); + btrfs_print_leaf(info, path->nodes[0]); } if (ret < 0) { btrfs_abort_transaction(trans, ret); @@ -7040,7 +7026,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, goto out; } } - add_pinned_bytes(root->fs_info, -num_bytes, owner_objectid, + add_pinned_bytes(info, -num_bytes, owner_objectid, root_objectid); } else { if (found_extent) { @@ -7065,21 +7051,20 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, btrfs_release_path(path); if (is_data) { - ret = btrfs_del_csums(trans, root, bytenr, num_bytes); + ret = btrfs_del_csums(trans, info, bytenr, num_bytes); if (ret) { btrfs_abort_transaction(trans, ret); goto out; } } - ret = add_to_free_space_tree(trans, root->fs_info, bytenr, - num_bytes); + ret = add_to_free_space_tree(trans, info, bytenr, num_bytes); if (ret) { btrfs_abort_transaction(trans, ret); goto out; } - ret = update_block_group(trans, root, bytenr, num_bytes, 0); + ret = update_block_group(trans, info, bytenr, num_bytes, 0); if (ret) { btrfs_abort_transaction(trans, ret); goto out; @@ -7099,7 +7084,7 @@ out: * removes it from the tree. */ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr) + u64 bytenr) { struct btrfs_delayed_ref_head *head; struct btrfs_delayed_ref_root *delayed_refs; @@ -7169,15 +7154,17 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct extent_buffer *buf, u64 parent, int last_ref) { + struct btrfs_fs_info *fs_info = root->fs_info; int pin = 1; int ret; if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { - ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, - buf->start, buf->len, - parent, root->root_key.objectid, - btrfs_header_level(buf), - BTRFS_DROP_DELAYED_REF, NULL); + ret = btrfs_add_delayed_tree_ref(fs_info, trans, + buf->start, buf->len, + parent, + root->root_key.objectid, + btrfs_header_level(buf), + BTRFS_DROP_DELAYED_REF, NULL); BUG_ON(ret); /* -ENOMEM */ } @@ -7188,15 +7175,16 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct btrfs_block_group_cache *cache; if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) { - ret = check_ref_cleanup(trans, root, buf->start); + ret = check_ref_cleanup(trans, buf->start); if (!ret) goto out; } - cache = btrfs_lookup_block_group(root->fs_info, buf->start); + cache = btrfs_lookup_block_group(fs_info, buf->start); if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { - pin_down_extent(root, cache, buf->start, buf->len, 1); + pin_down_extent(fs_info, cache, buf->start, + buf->len, 1); btrfs_put_block_group(cache); goto out; } @@ -7206,13 +7194,12 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, btrfs_add_free_space(cache, buf->start, buf->len); btrfs_free_reserved_bytes(cache, buf->len, 0); btrfs_put_block_group(cache); - trace_btrfs_reserved_extent_free(root, buf->start, buf->len); + trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); pin = 0; } out: if (pin) - add_pinned_bytes(root->fs_info, buf->len, - btrfs_header_level(buf), + add_pinned_bytes(fs_info, buf->len, btrfs_header_level(buf), root->root_key.objectid); /* @@ -7223,17 +7210,17 @@ out: } /* Can return -ENOMEM */ -int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, +int btrfs_free_extent(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset) { int ret; - struct btrfs_fs_info *fs_info = root->fs_info; if (btrfs_is_testing(fs_info)) return 0; - add_pinned_bytes(root->fs_info, num_bytes, owner, root_objectid); + add_pinned_bytes(fs_info, num_bytes, owner, root_objectid); /* * tree log blocks never actually go into the extent allocation @@ -7242,7 +7229,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, if (root_objectid == BTRFS_TREE_LOG_OBJECTID) { WARN_ON(owner >= BTRFS_FIRST_FREE_OBJECTID); /* unlocks the pinned mutex */ - btrfs_pin_extent(root, bytenr, num_bytes, 1); + btrfs_pin_extent(fs_info, bytenr, num_bytes, 1); ret = 0; } else if (owner < BTRFS_FIRST_FREE_OBJECTID) { ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr, @@ -7433,8 +7420,9 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, u64 hint_byte, struct btrfs_key *ins, u64 flags, int delalloc) { + struct btrfs_fs_info *fs_info = orig_root->fs_info; int ret = 0; - struct btrfs_root *root = orig_root->fs_info->extent_root; + struct btrfs_root *root = fs_info->extent_root; struct btrfs_free_cluster *last_ptr = NULL; struct btrfs_block_group_cache *block_group = NULL; u64 search_start = 0; @@ -7450,16 +7438,16 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, bool orig_have_caching_bg = false; bool full_search = false; - WARN_ON(num_bytes < root->sectorsize); + WARN_ON(num_bytes < fs_info->sectorsize); ins->type = BTRFS_EXTENT_ITEM_KEY; ins->objectid = 0; ins->offset = 0; - trace_find_free_extent(orig_root, num_bytes, empty_size, flags); + trace_find_free_extent(fs_info, num_bytes, empty_size, flags); - space_info = __find_space_info(root->fs_info, flags); + space_info = __find_space_info(fs_info, flags); if (!space_info) { - btrfs_err(root->fs_info, "No space info for %llu", flags); + btrfs_err(fs_info, "No space info for %llu", flags); return -ENOSPC; } @@ -7486,7 +7474,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, spin_unlock(&space_info->lock); } - last_ptr = fetch_cluster_info(orig_root, space_info, &empty_cluster); + last_ptr = fetch_cluster_info(fs_info, space_info, &empty_cluster); if (last_ptr) { spin_lock(&last_ptr->lock); if (last_ptr->block_group) @@ -7503,11 +7491,10 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, spin_unlock(&last_ptr->lock); } - search_start = max(search_start, first_logical_byte(root, 0)); + search_start = max(search_start, first_logical_byte(fs_info, 0)); search_start = max(search_start, hint_byte); if (search_start == hint_byte) { - block_group = btrfs_lookup_block_group(root->fs_info, - search_start); + block_group = btrfs_lookup_block_group(fs_info, search_start); /* * we don't want to use the block group if it doesn't match our * allocation bits, or if its not cached. @@ -7615,7 +7602,7 @@ have_block_group: if (offset) { /* we have a block, we're done */ spin_unlock(&last_ptr->refill_lock); - trace_btrfs_reserve_extent_cluster(root, + trace_btrfs_reserve_extent_cluster(fs_info, used_block_group, search_start, num_bytes); if (used_block_group != block_group) { @@ -7671,7 +7658,7 @@ refill_cluster: block_group->full_stripe_len); /* allocate a cluster in this block group */ - ret = btrfs_find_space_cluster(root, block_group, + ret = btrfs_find_space_cluster(fs_info, block_group, last_ptr, search_start, num_bytes, aligned_cluster); @@ -7688,7 +7675,7 @@ refill_cluster: if (offset) { /* we found one, proceed */ spin_unlock(&last_ptr->refill_lock); - trace_btrfs_reserve_extent_cluster(root, + trace_btrfs_reserve_extent_cluster(fs_info, block_group, search_start, num_bytes); goto checks; @@ -7760,7 +7747,7 @@ unclustered_alloc: goto loop; } checks: - search_start = ALIGN(offset, root->stripesize); + search_start = ALIGN(offset, fs_info->stripesize); /* move on to the next group */ if (search_start + num_bytes > @@ -7786,7 +7773,7 @@ checks: ins->objectid = search_start; ins->offset = num_bytes; - trace_btrfs_reserve_extent(orig_root, block_group, + trace_btrfs_reserve_extent(fs_info, block_group, search_start, num_bytes); btrfs_release_block_group(block_group, delalloc); break; @@ -7847,7 +7834,7 @@ loop: goto out; } - ret = do_chunk_alloc(trans, root, flags, + ret = do_chunk_alloc(trans, fs_info, flags, CHUNK_ALLOC_FORCE); /* @@ -7867,7 +7854,7 @@ loop: else ret = 0; if (!exist) - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); if (ret) goto out; } @@ -7959,7 +7946,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, flags = btrfs_get_alloc_profile(root, is_data); again: - WARN_ON(num_bytes < root->sectorsize); + WARN_ON(num_bytes < fs_info->sectorsize); ret = find_free_extent(root, ram_bytes, num_bytes, empty_size, hint_byte, ins, flags, delalloc); if (!ret && !is_data) { @@ -7967,7 +7954,8 @@ again: } else if (ret == -ENOSPC) { if (!final_tried && ins->offset) { num_bytes = min(num_bytes >> 1, ins->offset); - num_bytes = round_down(num_bytes, root->sectorsize); + num_bytes = round_down(num_bytes, + fs_info->sectorsize); num_bytes = max(num_bytes, min_alloc_size); ram_bytes = num_bytes; if (num_bytes == min_alloc_size) @@ -7977,7 +7965,7 @@ again: struct btrfs_space_info *sinfo; sinfo = __find_space_info(fs_info, flags); - btrfs_err(root->fs_info, + btrfs_err(fs_info, "allocation failed flags %llu, wanted %llu", flags, num_bytes); if (sinfo) @@ -7988,54 +7976,53 @@ again: return ret; } -static int __btrfs_free_reserved_extent(struct btrfs_root *root, +static int __btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len, int pin, int delalloc) { struct btrfs_block_group_cache *cache; int ret = 0; - cache = btrfs_lookup_block_group(root->fs_info, start); + cache = btrfs_lookup_block_group(fs_info, start); if (!cache) { - btrfs_err(root->fs_info, "Unable to find block group for %llu", - start); + btrfs_err(fs_info, "Unable to find block group for %llu", + start); return -ENOSPC; } if (pin) - pin_down_extent(root, cache, start, len, 1); + pin_down_extent(fs_info, cache, start, len, 1); else { - if (btrfs_test_opt(root->fs_info, DISCARD)) - ret = btrfs_discard_extent(root, start, len, NULL); + if (btrfs_test_opt(fs_info, DISCARD)) + ret = btrfs_discard_extent(fs_info, start, len, NULL); btrfs_add_free_space(cache, start, len); btrfs_free_reserved_bytes(cache, len, delalloc); - trace_btrfs_reserved_extent_free(root, start, len); + trace_btrfs_reserved_extent_free(fs_info, start, len); } btrfs_put_block_group(cache); return ret; } -int btrfs_free_reserved_extent(struct btrfs_root *root, +int btrfs_free_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len, int delalloc) { - return __btrfs_free_reserved_extent(root, start, len, 0, delalloc); + return __btrfs_free_reserved_extent(fs_info, start, len, 0, delalloc); } -int btrfs_free_and_pin_reserved_extent(struct btrfs_root *root, +int btrfs_free_and_pin_reserved_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) { - return __btrfs_free_reserved_extent(root, start, len, 1, 0); + return __btrfs_free_reserved_extent(fs_info, start, len, 1, 0); } static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 parent, u64 root_objectid, u64 flags, u64 owner, u64 offset, struct btrfs_key *ins, int ref_mod) { int ret; - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_extent_item *extent_item; struct btrfs_extent_inline_ref *iref; struct btrfs_path *path; @@ -8094,24 +8081,23 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, if (ret) return ret; - ret = update_block_group(trans, root, ins->objectid, ins->offset, 1); + ret = update_block_group(trans, fs_info, ins->objectid, ins->offset, 1); if (ret) { /* -ENOENT, logic error */ btrfs_err(fs_info, "update block group failed for %llu %llu", ins->objectid, ins->offset); BUG(); } - trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset); + trace_btrfs_reserved_extent_alloc(fs_info, ins->objectid, ins->offset); return ret; } static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 parent, u64 root_objectid, u64 flags, struct btrfs_disk_key *key, int level, struct btrfs_key *ins) { int ret; - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_extent_item *extent_item; struct btrfs_tree_block_info *block_info; struct btrfs_extent_inline_ref *iref; @@ -8119,16 +8105,15 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; u32 size = sizeof(*extent_item) + sizeof(*iref); u64 num_bytes = ins->offset; - bool skinny_metadata = btrfs_fs_incompat(root->fs_info, - SKINNY_METADATA); + bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); if (!skinny_metadata) size += sizeof(*block_info); path = btrfs_alloc_path(); if (!path) { - btrfs_free_and_pin_reserved_extent(root, ins->objectid, - root->nodesize); + btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid, + fs_info->nodesize); return -ENOMEM; } @@ -8137,8 +8122,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, ins, size); if (ret) { btrfs_free_path(path); - btrfs_free_and_pin_reserved_extent(root, ins->objectid, - root->nodesize); + btrfs_free_and_pin_reserved_extent(fs_info, ins->objectid, + fs_info->nodesize); return ret; } @@ -8152,7 +8137,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, if (skinny_metadata) { iref = (struct btrfs_extent_inline_ref *)(extent_item + 1); - num_bytes = root->nodesize; + num_bytes = fs_info->nodesize; } else { block_info = (struct btrfs_tree_block_info *)(extent_item + 1); btrfs_set_tree_block_key(leaf, block_info, key); @@ -8179,29 +8164,30 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, if (ret) return ret; - ret = update_block_group(trans, root, ins->objectid, root->nodesize, - 1); + ret = update_block_group(trans, fs_info, ins->objectid, + fs_info->nodesize, 1); if (ret) { /* -ENOENT, logic error */ btrfs_err(fs_info, "update block group failed for %llu %llu", ins->objectid, ins->offset); BUG(); } - trace_btrfs_reserved_extent_alloc(root, ins->objectid, root->nodesize); + trace_btrfs_reserved_extent_alloc(fs_info, ins->objectid, + fs_info->nodesize); return ret; } int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 root_objectid, u64 owner, u64 offset, u64 ram_bytes, struct btrfs_key *ins) { + struct btrfs_fs_info *fs_info = trans->fs_info; int ret; BUG_ON(root_objectid == BTRFS_TREE_LOG_OBJECTID); - ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid, + ret = btrfs_add_delayed_data_ref(fs_info, trans, ins->objectid, ins->offset, 0, root_objectid, owner, offset, ram_bytes, BTRFS_ADD_DELAYED_EXTENT, @@ -8215,7 +8201,7 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, * space cache bits as well */ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, + struct btrfs_fs_info *fs_info, u64 root_objectid, u64 owner, u64 offset, struct btrfs_key *ins) { @@ -8227,13 +8213,14 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, * Mixed block groups will exclude before processing the log so we only * need to do the exclude dance if this fs isn't mixed. */ - if (!btrfs_fs_incompat(root->fs_info, MIXED_GROUPS)) { - ret = __exclude_logged_extent(root, ins->objectid, ins->offset); + if (!btrfs_fs_incompat(fs_info, MIXED_GROUPS)) { + ret = __exclude_logged_extent(fs_info, ins->objectid, + ins->offset); if (ret) return ret; } - block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); + block_group = btrfs_lookup_block_group(fs_info, ins->objectid); if (!block_group) return -EINVAL; @@ -8245,7 +8232,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, spin_unlock(&block_group->lock); spin_unlock(&space_info->lock); - ret = alloc_reserved_file_extent(trans, root, 0, root_objectid, + ret = alloc_reserved_file_extent(trans, fs_info, 0, root_objectid, 0, owner, offset, ins, 1); btrfs_put_block_group(block_group); return ret; @@ -8255,16 +8242,17 @@ static struct extent_buffer * btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *buf; - buf = btrfs_find_create_tree_block(root, bytenr); + buf = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(buf)) return buf; btrfs_set_header_generation(buf, trans->transid); btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level); btrfs_tree_lock(buf); - clean_tree_block(trans, root->fs_info, buf); + clean_tree_block(trans, fs_info, buf); clear_bit(EXTENT_BUFFER_STALE, &buf->bflags); btrfs_set_lock_blocking(buf); @@ -8296,8 +8284,9 @@ static struct btrfs_block_rsv * use_block_rsv(struct btrfs_trans_handle *trans, struct btrfs_root *root, u32 blocksize) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_rsv *block_rsv; - struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv; + struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; int ret; bool global_updated = false; @@ -8315,11 +8304,11 @@ again: if (block_rsv->type == BTRFS_BLOCK_RSV_GLOBAL && !global_updated) { global_updated = true; - update_global_block_rsv(root->fs_info); + update_global_block_rsv(fs_info); goto again; } - if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) { + if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL * 10, /*DEFAULT_RATELIMIT_BURST*/ 1); @@ -8363,18 +8352,18 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key ins; struct btrfs_block_rsv *block_rsv; struct extent_buffer *buf; struct btrfs_delayed_extent_op *extent_op; u64 flags = 0; int ret; - u32 blocksize = root->nodesize; - bool skinny_metadata = btrfs_fs_incompat(root->fs_info, - SKINNY_METADATA); + u32 blocksize = fs_info->nodesize; + bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS - if (btrfs_is_testing(root->fs_info)) { + if (btrfs_is_testing(fs_info)) { buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr, level); if (!IS_ERR(buf)) @@ -8421,7 +8410,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, extent_op->is_data = false; extent_op->level = level; - ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, + ret = btrfs_add_delayed_tree_ref(fs_info, trans, ins.objectid, ins.offset, parent, root_objectid, level, BTRFS_ADD_DELAYED_EXTENT, @@ -8436,9 +8425,9 @@ out_free_delayed: out_free_buf: free_extent_buffer(buf); out_free_reserved: - btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 0); + btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 0); out_unuse: - unuse_block_rsv(root->fs_info, block_rsv, blocksize); + unuse_block_rsv(fs_info, block_rsv, blocksize); return ERR_PTR(ret); } @@ -8464,6 +8453,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans, struct walk_control *wc, struct btrfs_path *path) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 bytenr; u64 generation; u64 refs; @@ -8481,7 +8471,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans, } else { wc->reada_count = wc->reada_count * 3 / 2; wc->reada_count = min_t(int, wc->reada_count, - BTRFS_NODEPTRS_PER_BLOCK(root)); + BTRFS_NODEPTRS_PER_BLOCK(fs_info)); } eb = path->nodes[wc->level]; @@ -8503,7 +8493,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans, continue; /* We don't lock the tree block, it's OK to be racy here */ - ret = btrfs_lookup_extent_info(trans, root, bytenr, + ret = btrfs_lookup_extent_info(trans, fs_info, bytenr, wc->level - 1, 1, &refs, &flags); /* We don't care about errors in readahead. */ @@ -8532,226 +8522,12 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans, continue; } reada: - readahead_tree_block(root, bytenr); + readahead_tree_block(fs_info, bytenr); nread++; } wc->reada_slot = slot; } -static int account_leaf_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct extent_buffer *eb) -{ - int nr = btrfs_header_nritems(eb); - int i, extent_type, ret; - struct btrfs_key key; - struct btrfs_file_extent_item *fi; - u64 bytenr, num_bytes; - - /* We can be called directly from walk_up_proc() */ - if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) - return 0; - - for (i = 0; i < nr; i++) { - btrfs_item_key_to_cpu(eb, &key, i); - - if (key.type != BTRFS_EXTENT_DATA_KEY) - continue; - - fi = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item); - /* filter out non qgroup-accountable extents */ - extent_type = btrfs_file_extent_type(eb, fi); - - if (extent_type == BTRFS_FILE_EXTENT_INLINE) - continue; - - bytenr = btrfs_file_extent_disk_bytenr(eb, fi); - if (!bytenr) - continue; - - num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); - - ret = btrfs_qgroup_insert_dirty_extent(trans, root->fs_info, - bytenr, num_bytes, GFP_NOFS); - if (ret) - return ret; - } - return 0; -} - -/* - * Walk up the tree from the bottom, freeing leaves and any interior - * nodes which have had all slots visited. If a node (leaf or - * interior) is freed, the node above it will have it's slot - * incremented. The root node will never be freed. - * - * At the end of this function, we should have a path which has all - * slots incremented to the next position for a search. If we need to - * read a new node it will be NULL and the node above it will have the - * correct slot selected for a later read. - * - * If we increment the root nodes slot counter past the number of - * elements, 1 is returned to signal completion of the search. - */ -static int adjust_slots_upwards(struct btrfs_root *root, - struct btrfs_path *path, int root_level) -{ - int level = 0; - int nr, slot; - struct extent_buffer *eb; - - if (root_level == 0) - return 1; - - while (level <= root_level) { - eb = path->nodes[level]; - nr = btrfs_header_nritems(eb); - path->slots[level]++; - slot = path->slots[level]; - if (slot >= nr || level == 0) { - /* - * Don't free the root - we will detect this - * condition after our loop and return a - * positive value for caller to stop walking the tree. - */ - if (level != root_level) { - btrfs_tree_unlock_rw(eb, path->locks[level]); - path->locks[level] = 0; - - free_extent_buffer(eb); - path->nodes[level] = NULL; - path->slots[level] = 0; - } - } else { - /* - * We have a valid slot to walk back down - * from. Stop here so caller can process these - * new nodes. - */ - break; - } - - level++; - } - - eb = path->nodes[root_level]; - if (path->slots[root_level] >= btrfs_header_nritems(eb)) - return 1; - - return 0; -} - -/* - * root_eb is the subtree root and is locked before this function is called. - */ -static int account_shared_subtree(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct extent_buffer *root_eb, - u64 root_gen, - int root_level) -{ - int ret = 0; - int level; - struct extent_buffer *eb = root_eb; - struct btrfs_path *path = NULL; - - BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL); - BUG_ON(root_eb == NULL); - - if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) - return 0; - - if (!extent_buffer_uptodate(root_eb)) { - ret = btrfs_read_buffer(root_eb, root_gen); - if (ret) - goto out; - } - - if (root_level == 0) { - ret = account_leaf_items(trans, root, root_eb); - goto out; - } - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - - /* - * Walk down the tree. Missing extent blocks are filled in as - * we go. Metadata is accounted every time we read a new - * extent block. - * - * When we reach a leaf, we account for file extent items in it, - * walk back up the tree (adjusting slot pointers as we go) - * and restart the search process. - */ - extent_buffer_get(root_eb); /* For path */ - path->nodes[root_level] = root_eb; - path->slots[root_level] = 0; - path->locks[root_level] = 0; /* so release_path doesn't try to unlock */ -walk_down: - level = root_level; - while (level >= 0) { - if (path->nodes[level] == NULL) { - int parent_slot; - u64 child_gen; - u64 child_bytenr; - - /* We need to get child blockptr/gen from - * parent before we can read it. */ - eb = path->nodes[level + 1]; - parent_slot = path->slots[level + 1]; - child_bytenr = btrfs_node_blockptr(eb, parent_slot); - child_gen = btrfs_node_ptr_generation(eb, parent_slot); - - eb = read_tree_block(root, child_bytenr, child_gen); - if (IS_ERR(eb)) { - ret = PTR_ERR(eb); - goto out; - } else if (!extent_buffer_uptodate(eb)) { - free_extent_buffer(eb); - ret = -EIO; - goto out; - } - - path->nodes[level] = eb; - path->slots[level] = 0; - - btrfs_tree_read_lock(eb); - btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); - path->locks[level] = BTRFS_READ_LOCK_BLOCKING; - - ret = btrfs_qgroup_insert_dirty_extent(trans, - root->fs_info, child_bytenr, - root->nodesize, GFP_NOFS); - if (ret) - goto out; - } - - if (level == 0) { - ret = account_leaf_items(trans, root, path->nodes[level]); - if (ret) - goto out; - - /* Nonzero return here means we completed our search */ - ret = adjust_slots_upwards(root, path, root_level); - if (ret) - break; - - /* Restart search with new slots */ - goto walk_down; - } - - level--; - } - - ret = 0; -out: - btrfs_free_path(path); - - return ret; -} - /* * helper to process tree block while walking down the tree. * @@ -8765,6 +8541,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct walk_control *wc, int lookup_info) { + struct btrfs_fs_info *fs_info = root->fs_info; int level = wc->level; struct extent_buffer *eb = path->nodes[level]; u64 flag = BTRFS_BLOCK_FLAG_FULL_BACKREF; @@ -8782,7 +8559,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) || (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag)))) { BUG_ON(!path->locks[level]); - ret = btrfs_lookup_extent_info(trans, root, + ret = btrfs_lookup_extent_info(trans, fs_info, eb->start, level, 1, &wc->refs[level], &wc->flags[level]); @@ -8810,7 +8587,7 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans, BUG_ON(ret); /* -ENOMEM */ ret = btrfs_dec_ref(trans, root, eb, 0); BUG_ON(ret); /* -ENOMEM */ - ret = btrfs_set_disk_extent_flags(trans, root, eb->start, + ret = btrfs_set_disk_extent_flags(trans, fs_info, eb->start, eb->len, flag, btrfs_header_level(eb), 0); BUG_ON(ret); /* -ENOMEM */ @@ -8846,6 +8623,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct walk_control *wc, int *lookup_info) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 bytenr; u64 generation; u64 parent; @@ -8871,11 +8649,11 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, } bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]); - blocksize = root->nodesize; + blocksize = fs_info->nodesize; - next = btrfs_find_tree_block(root->fs_info, bytenr); + next = find_extent_buffer(fs_info, bytenr); if (!next) { - next = btrfs_find_create_tree_block(root, bytenr); + next = btrfs_find_create_tree_block(fs_info, bytenr); if (IS_ERR(next)) return PTR_ERR(next); @@ -8886,14 +8664,14 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, btrfs_tree_lock(next); btrfs_set_lock_blocking(next); - ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1, + ret = btrfs_lookup_extent_info(trans, fs_info, bytenr, level - 1, 1, &wc->refs[level - 1], &wc->flags[level - 1]); if (ret < 0) goto out_unlock; if (unlikely(wc->refs[level - 1] == 0)) { - btrfs_err(root->fs_info, "Missing references."); + btrfs_err(fs_info, "Missing references."); ret = -EIO; goto out_unlock; } @@ -8935,7 +8713,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, if (!next) { if (reada && level == 1) reada_walk_down(trans, root, wc, path); - next = read_tree_block(root, bytenr, generation); + next = read_tree_block(fs_info, bytenr, generation); if (IS_ERR(next)) { return PTR_ERR(next); } else if (!extent_buffer_uptodate(next)) { @@ -8980,16 +8758,17 @@ skip: } if (need_account) { - ret = account_shared_subtree(trans, root, next, - generation, level - 1); + ret = btrfs_qgroup_trace_subtree(trans, root, next, + generation, level - 1); if (ret) { - btrfs_err_rl(root->fs_info, + btrfs_err_rl(fs_info, "Error %d accounting shared subtree. Quota is out of sync, rescan required.", ret); } } - ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, - root->root_key.objectid, level - 1, 0); + ret = btrfs_free_extent(trans, fs_info, bytenr, blocksize, + parent, root->root_key.objectid, + level - 1, 0); if (ret) goto out_unlock; } @@ -9021,6 +8800,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, struct btrfs_path *path, struct walk_control *wc) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; int level = wc->level; struct extent_buffer *eb = path->nodes[level]; @@ -9050,7 +8830,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, btrfs_set_lock_blocking(eb); path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; - ret = btrfs_lookup_extent_info(trans, root, + ret = btrfs_lookup_extent_info(trans, fs_info, eb->start, level, 1, &wc->refs[level], &wc->flags[level]); @@ -9078,9 +8858,9 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, else ret = btrfs_dec_ref(trans, root, eb, 0); BUG_ON(ret); /* -ENOMEM */ - ret = account_leaf_items(trans, root, eb); + ret = btrfs_qgroup_trace_leaf_items(trans, fs_info, eb); if (ret) { - btrfs_err_rl(root->fs_info, + btrfs_err_rl(fs_info, "error %d accounting leaf items. Quota is out of sync, rescan required.", ret); } @@ -9092,7 +8872,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, btrfs_set_lock_blocking(eb); path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; } - clean_tree_block(trans, root->fs_info, eb); + clean_tree_block(trans, fs_info, eb); } if (eb == root->node) { @@ -9270,7 +9050,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, btrfs_set_lock_blocking(path->nodes[level]); path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; - ret = btrfs_lookup_extent_info(trans, root, + ret = btrfs_lookup_extent_info(trans, fs_info, path->nodes[level]->start, level, 1, &wc->refs[level], &wc->flags[level]); @@ -9296,7 +9076,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, wc->update_ref = update_ref; wc->keep_locks = 0; wc->for_reloc = for_reloc; - wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); + wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info); while (1) { @@ -9326,8 +9106,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, } BUG_ON(wc->level == 0); - if (btrfs_should_end_transaction(trans, tree_root) || - (!for_reloc && btrfs_need_cleaner_sleep(root))) { + if (btrfs_should_end_transaction(trans) || + (!for_reloc && btrfs_need_cleaner_sleep(fs_info))) { ret = btrfs_update_root(trans, tree_root, &root->root_key, root_item); @@ -9337,8 +9117,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, goto out_end_trans; } - btrfs_end_transaction_throttle(trans, tree_root); - if (!for_reloc && btrfs_need_cleaner_sleep(root)) { + btrfs_end_transaction_throttle(trans); + if (!for_reloc && btrfs_need_cleaner_sleep(fs_info)) { btrfs_debug(fs_info, "drop snapshot early exit"); err = -EAGAIN; @@ -9391,7 +9171,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, } root_dropped = true; out_end_trans: - btrfs_end_transaction_throttle(trans, tree_root); + btrfs_end_transaction_throttle(trans); out_free: kfree(wc); btrfs_free_path(path); @@ -9421,6 +9201,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, struct extent_buffer *node, struct extent_buffer *parent) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_path *path; struct walk_control *wc; int level; @@ -9460,7 +9241,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, wc->update_ref = 0; wc->keep_locks = 1; wc->for_reloc = 1; - wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); + wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(fs_info); while (1) { wret = walk_down_tree(trans, root, path, wc); @@ -9481,7 +9262,7 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, return ret; } -static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) +static u64 update_block_group_flags(struct btrfs_fs_info *fs_info, u64 flags) { u64 num_devices; u64 stripped; @@ -9490,11 +9271,11 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags) * if restripe for this chunk_type is on pick target profile and * return, otherwise do the usual balance */ - stripped = get_restripe_target(root->fs_info, flags); + stripped = get_restripe_target(fs_info, flags); if (stripped) return extended_to_chunk(stripped); - num_devices = root->fs_info->fs_devices->rw_devices; + num_devices = fs_info->fs_devices->rw_devices; stripped = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 | @@ -9579,6 +9360,7 @@ int btrfs_inc_block_group_ro(struct btrfs_root *root, struct btrfs_block_group_cache *cache) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_trans_handle *trans; u64 alloc_flags; int ret; @@ -9593,14 +9375,14 @@ again: * block groups cache has started writing. If it already started, * back off and let this transaction commit */ - mutex_lock(&root->fs_info->ro_block_group_mutex); + mutex_lock(&fs_info->ro_block_group_mutex); if (test_bit(BTRFS_TRANS_DIRTY_BG_RUN, &trans->transaction->flags)) { u64 transid = trans->transid; - mutex_unlock(&root->fs_info->ro_block_group_mutex); - btrfs_end_transaction(trans, root); + mutex_unlock(&fs_info->ro_block_group_mutex); + btrfs_end_transaction(trans); - ret = btrfs_wait_for_commit(root, transid); + ret = btrfs_wait_for_commit(fs_info, transid); if (ret) return ret; goto again; @@ -9610,9 +9392,9 @@ again: * if we are changing raid levels, try to allocate a corresponding * block group with the new raid level. */ - alloc_flags = update_block_group_flags(root, cache->flags); + alloc_flags = update_block_group_flags(fs_info, cache->flags); if (alloc_flags != cache->flags) { - ret = do_chunk_alloc(trans, root, alloc_flags, + ret = do_chunk_alloc(trans, fs_info, alloc_flags, CHUNK_ALLOC_FORCE); /* * ENOSPC is allowed here, we may have enough space @@ -9628,31 +9410,31 @@ again: ret = inc_block_group_ro(cache, 0); if (!ret) goto out; - alloc_flags = get_alloc_profile(root, cache->space_info->flags); - ret = do_chunk_alloc(trans, root, alloc_flags, + alloc_flags = get_alloc_profile(fs_info, cache->space_info->flags); + ret = do_chunk_alloc(trans, fs_info, alloc_flags, CHUNK_ALLOC_FORCE); if (ret < 0) goto out; ret = inc_block_group_ro(cache, 0); out: if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { - alloc_flags = update_block_group_flags(root, cache->flags); - lock_chunks(root->fs_info->chunk_root); - check_system_chunk(trans, root, alloc_flags); - unlock_chunks(root->fs_info->chunk_root); + alloc_flags = update_block_group_flags(fs_info, cache->flags); + mutex_lock(&fs_info->chunk_mutex); + check_system_chunk(trans, fs_info, alloc_flags); + mutex_unlock(&fs_info->chunk_mutex); } - mutex_unlock(&root->fs_info->ro_block_group_mutex); + mutex_unlock(&fs_info->ro_block_group_mutex); - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); return ret; } int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 type) + struct btrfs_fs_info *fs_info, u64 type) { - u64 alloc_flags = get_alloc_profile(root, type); - return do_chunk_alloc(trans, root, alloc_flags, - CHUNK_ALLOC_FORCE); + u64 alloc_flags = get_alloc_profile(fs_info, type); + + return do_chunk_alloc(trans, fs_info, alloc_flags, CHUNK_ALLOC_FORCE); } /* @@ -9696,8 +9478,7 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo) return free_bytes; } -void btrfs_dec_block_group_ro(struct btrfs_root *root, - struct btrfs_block_group_cache *cache) +void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache) { struct btrfs_space_info *sinfo = cache->space_info; u64 num_bytes; @@ -9723,11 +9504,12 @@ void btrfs_dec_block_group_ro(struct btrfs_root *root, * @return - -1 if it's not a good idea to relocate this block group, 0 if its * ok to go ahead and try. */ -int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) +int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr) { + struct btrfs_root *root = fs_info->extent_root; struct btrfs_block_group_cache *block_group; struct btrfs_space_info *space_info; - struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; struct btrfs_device *device; struct btrfs_trans_handle *trans; u64 min_free; @@ -9739,14 +9521,14 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) int full = 0; int ret = 0; - debug = btrfs_test_opt(root->fs_info, ENOSPC_DEBUG); + debug = btrfs_test_opt(fs_info, ENOSPC_DEBUG); - block_group = btrfs_lookup_block_group(root->fs_info, bytenr); + block_group = btrfs_lookup_block_group(fs_info, bytenr); /* odd, couldn't find the block group, leave it alone */ if (!block_group) { if (debug) - btrfs_warn(root->fs_info, + btrfs_warn(fs_info, "can't find block group for bytenr %llu", bytenr); return -1; @@ -9796,7 +9578,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) * 3: raid0 * 4: single */ - target = get_restripe_target(root->fs_info, block_group->flags); + target = get_restripe_target(fs_info, block_group->flags); if (target) { index = __get_raid_index(extended_to_chunk(target)); } else { @@ -9806,9 +9588,9 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) */ if (full) { if (debug) - btrfs_warn(root->fs_info, - "no space to alloc new chunk for block group %llu", - block_group->key.objectid); + btrfs_warn(fs_info, + "no space to alloc new chunk for block group %llu", + block_group->key.objectid); goto out; } @@ -9836,7 +9618,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) goto out; } - mutex_lock(&root->fs_info->chunk_mutex); + mutex_lock(&fs_info->chunk_mutex); list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) { u64 dev_offset; @@ -9858,19 +9640,21 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) } } if (debug && ret == -1) - btrfs_warn(root->fs_info, - "no space to allocate a new chunk for block group %llu", - block_group->key.objectid); - mutex_unlock(&root->fs_info->chunk_mutex); - btrfs_end_transaction(trans, root); + btrfs_warn(fs_info, + "no space to allocate a new chunk for block group %llu", + block_group->key.objectid); + mutex_unlock(&fs_info->chunk_mutex); + btrfs_end_transaction(trans); out: btrfs_put_block_group(block_group); return ret; } -static int find_first_block_group(struct btrfs_root *root, - struct btrfs_path *path, struct btrfs_key *key) +static int find_first_block_group(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + struct btrfs_key *key) { + struct btrfs_root *root = fs_info->extent_root; int ret = 0; struct btrfs_key found_key; struct extent_buffer *leaf; @@ -9904,7 +9688,7 @@ static int find_first_block_group(struct btrfs_root *root, found_key.offset); read_unlock(&em_tree->lock); if (!em) { - btrfs_err(root->fs_info, + btrfs_err(fs_info, "logical %llu len %llu found bg but no related chunk", found_key.objectid, found_key.offset); ret = -ENOENT; @@ -9934,8 +9718,7 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info) if (block_group->iref) break; spin_unlock(&block_group->lock); - block_group = next_block_group(info->tree_root, - block_group); + block_group = next_block_group(info, block_group); } if (!block_group) { if (last == 0) @@ -10003,7 +9786,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) */ if (block_group->cached == BTRFS_CACHE_NO || block_group->cached == BTRFS_CACHE_ERROR) - free_excluded_extents(info->extent_root, block_group); + free_excluded_extents(info, block_group); btrfs_remove_free_space_cache(block_group); ASSERT(list_empty(&block_group->dirty_list)); @@ -10094,7 +9877,8 @@ out_err: } static struct btrfs_block_group_cache * -btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size) +btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info, + u64 start, u64 size) { struct btrfs_block_group_cache *cache; @@ -10113,11 +9897,11 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size) cache->key.offset = size; cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; - cache->sectorsize = root->sectorsize; - cache->fs_info = root->fs_info; - cache->full_stripe_len = btrfs_full_stripe_len(root, - &root->fs_info->mapping_tree, - start); + cache->sectorsize = fs_info->sectorsize; + cache->fs_info = fs_info; + cache->full_stripe_len = btrfs_full_stripe_len(fs_info, + &fs_info->mapping_tree, + start); set_free_space_tree_thresholds(cache); atomic_set(&cache->count, 1); @@ -10136,12 +9920,11 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size) return cache; } -int btrfs_read_block_groups(struct btrfs_root *root) +int btrfs_read_block_groups(struct btrfs_fs_info *info) { struct btrfs_path *path; int ret; struct btrfs_block_group_cache *cache; - struct btrfs_fs_info *info = root->fs_info; struct btrfs_space_info *space_info; struct btrfs_key key; struct btrfs_key found_key; @@ -10154,7 +9937,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) feature = btrfs_super_incompat_flags(info->super_copy); mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS); - root = info->extent_root; key.objectid = 0; key.offset = 0; key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; @@ -10163,15 +9945,15 @@ int btrfs_read_block_groups(struct btrfs_root *root) return -ENOMEM; path->reada = READA_FORWARD; - cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy); - if (btrfs_test_opt(root->fs_info, SPACE_CACHE) && - btrfs_super_generation(root->fs_info->super_copy) != cache_gen) + cache_gen = btrfs_super_cache_generation(info->super_copy); + if (btrfs_test_opt(info, SPACE_CACHE) && + btrfs_super_generation(info->super_copy) != cache_gen) need_clear = 1; - if (btrfs_test_opt(root->fs_info, CLEAR_CACHE)) + if (btrfs_test_opt(info, CLEAR_CACHE)) need_clear = 1; while (1) { - ret = find_first_block_group(root, path, &key); + ret = find_first_block_group(info, path, &key); if (ret > 0) break; if (ret != 0) @@ -10180,7 +9962,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); - cache = btrfs_create_block_group_cache(root, found_key.objectid, + cache = btrfs_create_block_group_cache(info, found_key.objectid, found_key.offset); if (!cache) { ret = -ENOMEM; @@ -10198,7 +9980,7 @@ int btrfs_read_block_groups(struct btrfs_root *root) * b) Setting 'dirty flag' makes sure that we flush * the new space cache info onto disk. */ - if (btrfs_test_opt(root->fs_info, SPACE_CACHE)) + if (btrfs_test_opt(info, SPACE_CACHE)) cache->disk_cache_state = BTRFS_DC_CLEAR; } @@ -10224,13 +10006,13 @@ int btrfs_read_block_groups(struct btrfs_root *root) * info has super bytes accounted for, otherwise we'll think * we have more space than we actually do. */ - ret = exclude_super_stripes(root, cache); + ret = exclude_super_stripes(info, cache); if (ret) { /* * We may have excluded something, so call this just in * case. */ - free_excluded_extents(root, cache); + free_excluded_extents(info, cache); btrfs_put_block_group(cache); goto error; } @@ -10245,25 +10027,25 @@ int btrfs_read_block_groups(struct btrfs_root *root) if (found_key.offset == btrfs_block_group_used(&cache->item)) { cache->last_byte_to_unpin = (u64)-1; cache->cached = BTRFS_CACHE_FINISHED; - free_excluded_extents(root, cache); + free_excluded_extents(info, cache); } else if (btrfs_block_group_used(&cache->item) == 0) { cache->last_byte_to_unpin = (u64)-1; cache->cached = BTRFS_CACHE_FINISHED; - add_new_free_space(cache, root->fs_info, + add_new_free_space(cache, info, found_key.objectid, found_key.objectid + found_key.offset); - free_excluded_extents(root, cache); + free_excluded_extents(info, cache); } - ret = btrfs_add_block_group_cache(root->fs_info, cache); + ret = btrfs_add_block_group_cache(info, cache); if (ret) { btrfs_remove_free_space_cache(cache); btrfs_put_block_group(cache); goto error; } - trace_btrfs_add_block_group(root->fs_info, cache, 0); + trace_btrfs_add_block_group(info, cache, 0); ret = update_space_info(info, cache->flags, found_key.offset, btrfs_block_group_used(&cache->item), cache->bytes_super, &space_info); @@ -10282,8 +10064,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) __link_block_group(space_info, cache); - set_avail_alloc_bits(root->fs_info, cache->flags); - if (btrfs_chunk_readonly(root, cache->key.objectid)) { + set_avail_alloc_bits(info, cache->flags); + if (btrfs_chunk_readonly(info, cache->key.objectid)) { inc_block_group_ro(cache, 1); } else if (btrfs_block_group_used(&cache->item) == 0) { spin_lock(&info->unused_bgs_lock); @@ -10297,8 +10079,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) } } - list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) { - if (!(get_alloc_profile(root, space_info->flags) & + list_for_each_entry_rcu(space_info, &info->space_info, list) { + if (!(get_alloc_profile(info, space_info->flags) & (BTRFS_BLOCK_GROUP_RAID10 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID5 | @@ -10327,10 +10109,10 @@ error: } void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, - struct btrfs_root *root) + struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *block_group, *tmp; - struct btrfs_root *extent_root = root->fs_info->extent_root; + struct btrfs_root *extent_root = fs_info->extent_root; struct btrfs_block_group_item item; struct btrfs_key key; int ret = 0; @@ -10350,11 +10132,11 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans, sizeof(item)); if (ret) btrfs_abort_transaction(trans, ret); - ret = btrfs_finish_chunk_alloc(trans, extent_root, - key.objectid, key.offset); + ret = btrfs_finish_chunk_alloc(trans, fs_info, key.objectid, + key.offset); if (ret) btrfs_abort_transaction(trans, ret); - add_block_group_free_space(trans, root->fs_info, block_group); + add_block_group_free_space(trans, fs_info, block_group); /* already aborted the transaction if it failed. */ next: list_del_init(&block_group->bg_list); @@ -10363,18 +10145,16 @@ next: } int btrfs_make_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytes_used, + struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type, u64 chunk_objectid, u64 chunk_offset, u64 size) { - int ret; - struct btrfs_root *extent_root; struct btrfs_block_group_cache *cache; - extent_root = root->fs_info->extent_root; + int ret; - btrfs_set_log_full_commit(root->fs_info, trans); + btrfs_set_log_full_commit(fs_info, trans); - cache = btrfs_create_block_group_cache(root, chunk_offset, size); + cache = btrfs_create_block_group_cache(fs_info, chunk_offset, size); if (!cache) return -ENOMEM; @@ -10386,28 +10166,27 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, cache->last_byte_to_unpin = (u64)-1; cache->cached = BTRFS_CACHE_FINISHED; cache->needs_free_space = 1; - ret = exclude_super_stripes(root, cache); + ret = exclude_super_stripes(fs_info, cache); if (ret) { /* * We may have excluded something, so call this just in * case. */ - free_excluded_extents(root, cache); + free_excluded_extents(fs_info, cache); btrfs_put_block_group(cache); return ret; } - add_new_free_space(cache, root->fs_info, chunk_offset, - chunk_offset + size); + add_new_free_space(cache, fs_info, chunk_offset, chunk_offset + size); - free_excluded_extents(root, cache); + free_excluded_extents(fs_info, cache); #ifdef CONFIG_BTRFS_DEBUG - if (btrfs_should_fragment_free_space(root, cache)) { + if (btrfs_should_fragment_free_space(cache)) { u64 new_bytes_used = size - bytes_used; bytes_used += new_bytes_used >> 1; - fragment_free_space(root, cache); + fragment_free_space(cache); } #endif /* @@ -10415,7 +10194,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, * assigned to our block group, but don't update its counters just yet. * We want our bg to be added to the rbtree with its ->space_info set. */ - ret = update_space_info(root->fs_info, cache->flags, 0, 0, 0, + ret = update_space_info(fs_info, cache->flags, 0, 0, 0, &cache->space_info); if (ret) { btrfs_remove_free_space_cache(cache); @@ -10423,7 +10202,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, return ret; } - ret = btrfs_add_block_group_cache(root->fs_info, cache); + ret = btrfs_add_block_group_cache(fs_info, cache); if (ret) { btrfs_remove_free_space_cache(cache); btrfs_put_block_group(cache); @@ -10434,26 +10213,26 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, * Now that our block group has its ->space_info set and is inserted in * the rbtree, update the space info's counters. */ - trace_btrfs_add_block_group(root->fs_info, cache, 1); - ret = update_space_info(root->fs_info, cache->flags, size, bytes_used, + trace_btrfs_add_block_group(fs_info, cache, 1); + ret = update_space_info(fs_info, cache->flags, size, bytes_used, cache->bytes_super, &cache->space_info); if (ret) { btrfs_remove_free_space_cache(cache); - spin_lock(&root->fs_info->block_group_cache_lock); + spin_lock(&fs_info->block_group_cache_lock); rb_erase(&cache->cache_node, - &root->fs_info->block_group_cache_tree); + &fs_info->block_group_cache_tree); RB_CLEAR_NODE(&cache->cache_node); - spin_unlock(&root->fs_info->block_group_cache_lock); + spin_unlock(&fs_info->block_group_cache_lock); btrfs_put_block_group(cache); return ret; } - update_global_block_rsv(root->fs_info); + update_global_block_rsv(fs_info); __link_block_group(cache->space_info, cache); list_add_tail(&cache->bg_list, &trans->new_bgs); - set_avail_alloc_bits(extent_root->fs_info, type); + set_avail_alloc_bits(fs_info, type); return 0; } @@ -10473,13 +10252,14 @@ static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) } int btrfs_remove_block_group(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 group_start, + struct btrfs_fs_info *fs_info, u64 group_start, struct extent_map *em) { + struct btrfs_root *root = fs_info->extent_root; struct btrfs_path *path; struct btrfs_block_group_cache *block_group; struct btrfs_free_cluster *cluster; - struct btrfs_root *tree_root = root->fs_info->tree_root; + struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_key key; struct inode *inode; struct kobject *kobj = NULL; @@ -10489,9 +10269,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, struct btrfs_caching_control *caching_ctl = NULL; bool remove_em; - root = root->fs_info->extent_root; - - block_group = btrfs_lookup_block_group(root->fs_info, group_start); + block_group = btrfs_lookup_block_group(fs_info, group_start); BUG_ON(!block_group); BUG_ON(!block_group->ro); @@ -10499,7 +10277,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, * Free the reserved super bytes from this block group before * remove it. */ - free_excluded_extents(root, block_group); + free_excluded_extents(fs_info, block_group); memcpy(&key, &block_group->key, sizeof(key)); index = get_block_group_index(block_group); @@ -10511,7 +10289,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, factor = 1; /* make sure this block group isn't part of an allocation cluster */ - cluster = &root->fs_info->data_alloc_cluster; + cluster = &fs_info->data_alloc_cluster; spin_lock(&cluster->refill_lock); btrfs_return_cluster_to_free_space(block_group, cluster); spin_unlock(&cluster->refill_lock); @@ -10520,7 +10298,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, * make sure this block group isn't part of a metadata * allocation cluster */ - cluster = &root->fs_info->meta_alloc_cluster; + cluster = &fs_info->meta_alloc_cluster; spin_lock(&cluster->refill_lock); btrfs_return_cluster_to_free_space(block_group, cluster); spin_unlock(&cluster->refill_lock); @@ -10549,9 +10327,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, WARN_ON(!IS_ERR(inode) && inode != block_group->io_ctl.inode); spin_unlock(&trans->transaction->dirty_bgs_lock); - btrfs_wait_cache_io(root, trans, block_group, - &block_group->io_ctl, path, - block_group->key.objectid); + btrfs_wait_cache_io(trans, block_group, path); btrfs_put_block_group(block_group); spin_lock(&trans->transaction->dirty_bgs_lock); } @@ -10600,14 +10376,14 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, btrfs_release_path(path); } - spin_lock(&root->fs_info->block_group_cache_lock); + spin_lock(&fs_info->block_group_cache_lock); rb_erase(&block_group->cache_node, - &root->fs_info->block_group_cache_tree); + &fs_info->block_group_cache_tree); RB_CLEAR_NODE(&block_group->cache_node); - if (root->fs_info->first_logical_byte == block_group->key.objectid) - root->fs_info->first_logical_byte = (u64)-1; - spin_unlock(&root->fs_info->block_group_cache_lock); + if (fs_info->first_logical_byte == block_group->key.objectid) + fs_info->first_logical_byte = (u64)-1; + spin_unlock(&fs_info->block_group_cache_lock); down_write(&block_group->space_info->groups_sem); /* @@ -10618,7 +10394,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, if (list_empty(&block_group->space_info->block_groups[index])) { kobj = block_group->space_info->block_group_kobjs[index]; block_group->space_info->block_group_kobjs[index] = NULL; - clear_avail_alloc_bits(root->fs_info, block_group->flags); + clear_avail_alloc_bits(fs_info, block_group->flags); } up_write(&block_group->space_info->groups_sem); if (kobj) { @@ -10631,12 +10407,12 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, if (block_group->cached == BTRFS_CACHE_STARTED) wait_block_group_cache_done(block_group); if (block_group->has_caching_ctl) { - down_write(&root->fs_info->commit_root_sem); + down_write(&fs_info->commit_root_sem); if (!caching_ctl) { struct btrfs_caching_control *ctl; list_for_each_entry(ctl, - &root->fs_info->caching_block_groups, list) + &fs_info->caching_block_groups, list) if (ctl->block_group == block_group) { caching_ctl = ctl; atomic_inc(&caching_ctl->count); @@ -10645,7 +10421,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, } if (caching_ctl) list_del_init(&caching_ctl->list); - up_write(&root->fs_info->commit_root_sem); + up_write(&fs_info->commit_root_sem); if (caching_ctl) { /* Once for the caching bgs list and once for us. */ put_caching_control(caching_ctl); @@ -10666,7 +10442,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, spin_lock(&block_group->space_info->lock); list_del_init(&block_group->ro_list); - if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) { + if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) { WARN_ON(block_group->space_info->total_bytes < block_group->key.offset); WARN_ON(block_group->space_info->bytes_readonly @@ -10682,7 +10458,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, memcpy(&key, &block_group->key, sizeof(key)); - lock_chunks(root); + mutex_lock(&fs_info->chunk_mutex); if (!list_empty(&em->list)) { /* We're in the transaction->pending_chunks list. */ free_extent_map(em); @@ -10730,14 +10506,14 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, * sees the em, either in the pending_chunks list or in the * pinned_chunks list. */ - list_move_tail(&em->list, &root->fs_info->pinned_chunks); + list_move_tail(&em->list, &fs_info->pinned_chunks); } spin_unlock(&block_group->lock); if (remove_em) { struct extent_map_tree *em_tree; - em_tree = &root->fs_info->mapping_tree.map_tree; + em_tree = &fs_info->mapping_tree.map_tree; write_lock(&em_tree->lock); /* * The em might be in the pending_chunks list, so make sure the @@ -10750,9 +10526,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, free_extent_map(em); } - unlock_chunks(root); + mutex_unlock(&fs_info->chunk_mutex); - ret = remove_block_group_free_space(trans, root->fs_info, block_group); + ret = remove_block_group_free_space(trans, fs_info, block_group); if (ret) goto out; @@ -10820,7 +10596,6 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) { struct btrfs_block_group_cache *block_group; struct btrfs_space_info *space_info; - struct btrfs_root *root = fs_info->extent_root; struct btrfs_trans_handle *trans; int ret = 0; @@ -10881,7 +10656,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) trans = btrfs_start_trans_remove_block_group(fs_info, block_group->key.objectid); if (IS_ERR(trans)) { - btrfs_dec_block_group_ro(root, block_group); + btrfs_dec_block_group_ro(block_group); ret = PTR_ERR(trans); goto next; } @@ -10908,14 +10683,14 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) EXTENT_DIRTY); if (ret) { mutex_unlock(&fs_info->unused_bg_unpin_mutex); - btrfs_dec_block_group_ro(root, block_group); + btrfs_dec_block_group_ro(block_group); goto end_trans; } ret = clear_extent_bits(&fs_info->freed_extents[1], start, end, EXTENT_DIRTY); if (ret) { mutex_unlock(&fs_info->unused_bg_unpin_mutex); - btrfs_dec_block_group_ro(root, block_group); + btrfs_dec_block_group_ro(block_group); goto end_trans; } mutex_unlock(&fs_info->unused_bg_unpin_mutex); @@ -10934,7 +10709,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) spin_unlock(&space_info->lock); /* DISCARD can flip during remount */ - trimming = btrfs_test_opt(root->fs_info, DISCARD); + trimming = btrfs_test_opt(fs_info, DISCARD); /* Implicit trim during transaction commit. */ if (trimming) @@ -10944,7 +10719,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) * Btrfs_remove_chunk will abort the transaction if things go * horribly wrong. */ - ret = btrfs_remove_chunk(trans, root, + ret = btrfs_remove_chunk(trans, fs_info, block_group->key.objectid); if (ret) { @@ -10971,7 +10746,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) btrfs_get_block_group(block_group); } end_trans: - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); next: mutex_unlock(&fs_info->delete_unused_bgs_mutex); btrfs_put_block_group(block_group); @@ -11018,9 +10793,10 @@ out: return ret; } -int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) +int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + u64 start, u64 end) { - return unpin_extent_range(root, start, end, false); + return unpin_extent_range(fs_info, start, end, false); } /* @@ -11060,7 +10836,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, ret = 0; while (1) { - struct btrfs_fs_info *fs_info = device->dev_root->fs_info; + struct btrfs_fs_info *fs_info = device->fs_info; struct btrfs_transaction *trans; u64 bytes; @@ -11110,9 +10886,8 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, return ret; } -int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) +int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) { - struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_block_group_cache *cache = NULL; struct btrfs_device *device; struct list_head *devices; @@ -11167,11 +10942,11 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) } } - cache = next_block_group(fs_info->tree_root, cache); + cache = next_block_group(fs_info, cache); } - mutex_lock(&root->fs_info->fs_devices->device_list_mutex); - devices = &root->fs_info->fs_devices->alloc_list; + mutex_lock(&fs_info->fs_devices->device_list_mutex); + devices = &fs_info->fs_devices->alloc_list; list_for_each_entry(device, devices, dev_alloc_list) { ret = btrfs_trim_free_extents(device, range->minlen, &group_trimmed); @@ -11180,7 +10955,7 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) trimmed += group_trimmed; } - mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); range->len = trimmed; return ret; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8ed05d95584a..4ac383a3a649 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -127,7 +127,7 @@ struct extent_page_data { */ unsigned int extent_locked:1; - /* tells the submit_bio code to use a WRITE_SYNC */ + /* tells the submit_bio code to use REQ_SYNC */ unsigned int sync_io:1; }; @@ -2029,7 +2029,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, * read repair operation. */ btrfs_bio_counter_inc_blocked(fs_info); - ret = btrfs_map_block(fs_info, WRITE, logical, + ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, logical, &map_length, &bbio, mirror_num); if (ret) { btrfs_bio_counter_dec(fs_info); @@ -2047,7 +2047,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, return -EIO; } bio->bi_bdev = dev->bdev; - bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); + bio->bi_opf = REQ_OP_WRITE | REQ_SYNC; bio_add_page(bio, page, length, pg_offset); if (btrfsic_submit_bio_wait(bio)) { @@ -2067,20 +2067,20 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, return 0; } -int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb, - int mirror_num) +int repair_eb_io_failure(struct btrfs_fs_info *fs_info, + struct extent_buffer *eb, int mirror_num) { u64 start = eb->start; unsigned long i, num_pages = num_extent_pages(eb->start, eb->len); int ret = 0; - if (root->fs_info->sb->s_flags & MS_RDONLY) + if (fs_info->sb->s_flags & MS_RDONLY) return -EROFS; for (i = 0; i < num_pages; i++) { struct page *p = eb->pages[i]; - ret = repair_io_failure(root->fs_info->btree_inode, start, + ret = repair_io_failure(fs_info->btree_inode, start, PAGE_SIZE, start, p, start - page_offset(p), mirror_num); if (ret) @@ -2341,6 +2341,7 @@ struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio, struct page *page, int pg_offset, int icsum, bio_end_io_t *endio_func, void *data) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct bio *bio; struct btrfs_io_bio *btrfs_failed_bio; struct btrfs_io_bio *btrfs_bio; @@ -2351,13 +2352,12 @@ struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio, bio->bi_end_io = endio_func; bio->bi_iter.bi_sector = failrec->logical >> 9; - bio->bi_bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; + bio->bi_bdev = fs_info->fs_devices->latest_bdev; bio->bi_iter.bi_size = 0; bio->bi_private = data; btrfs_failed_bio = btrfs_io_bio(failed_bio); if (btrfs_failed_bio->csum) { - struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); btrfs_bio = btrfs_io_bio(bio); @@ -2388,7 +2388,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, struct inode *inode = page->mapping->host; struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; struct bio *bio; - int read_mode; + int read_mode = 0; int ret; BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE); @@ -2404,9 +2404,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, } if (failed_bio->bi_vcnt > 1) - read_mode = READ_SYNC | REQ_FAILFAST_DEV; - else - read_mode = READ_SYNC; + read_mode |= REQ_FAILFAST_DEV; phy_offset >>= inode->i_sb->s_blocksize_bits; bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, @@ -2476,6 +2474,8 @@ static void end_bio_extent_writepage(struct bio *bio) bio_for_each_segment_all(bvec, bio, i) { struct page *page = bvec->bv_page; + struct inode *inode = page->mapping->host; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); /* We always issue full-page reads, but if some block * in a page fails to read, blk_update_request() will @@ -2484,11 +2484,11 @@ static void end_bio_extent_writepage(struct bio *bio) * if they don't add up to a full page. */ if (bvec->bv_offset || bvec->bv_len != PAGE_SIZE) { if (bvec->bv_offset + bvec->bv_len != PAGE_SIZE) - btrfs_err(BTRFS_I(page->mapping->host)->root->fs_info, + btrfs_err(fs_info, "partial page write in btrfs with offset %u and length %u", bvec->bv_offset, bvec->bv_len); else - btrfs_info(BTRFS_I(page->mapping->host)->root->fs_info, + btrfs_info(fs_info, "incomplete page write in btrfs with offset %u and length %u", bvec->bv_offset, bvec->bv_len); } @@ -3484,7 +3484,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, unsigned long nr_written = 0; if (wbc->sync_mode == WB_SYNC_ALL) - write_flags = WRITE_SYNC; + write_flags = REQ_SYNC; trace___extent_writepage(page, inode, wbc); @@ -3729,7 +3729,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, unsigned long i, num_pages; unsigned long bio_flags = 0; unsigned long start, end; - int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META; + int write_flags = (epd->sync_io ? REQ_SYNC : 0) | REQ_META; int ret = 0; clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); @@ -3743,16 +3743,15 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, if (btrfs_header_level(eb) > 0) { end = btrfs_node_key_ptr_offset(nritems); - memset_extent_buffer(eb, 0, end, eb->len - end); + memzero_extent_buffer(eb, end, eb->len - end); } else { /* * leaf: * header 0 1 2 .. N ... data_N .. data_2 data_1 data_0 */ start = btrfs_item_nr_offset(nritems); - end = btrfs_leaf_data(eb) + - leaf_data_end(fs_info->tree_root, eb); - memset_extent_buffer(eb, 0, start, end - start); + end = btrfs_leaf_data(eb) + leaf_data_end(fs_info, eb); + memzero_extent_buffer(eb, start, end - start); } for (i = 0; i < num_pages; i++) { @@ -4076,7 +4075,7 @@ static void flush_epd_write_bio(struct extent_page_data *epd) int ret; bio_set_op_attrs(epd->bio, REQ_OP_WRITE, - epd->sync_io ? WRITE_SYNC : 0); + epd->sync_io ? REQ_SYNC : 0); ret = submit_one_bio(epd->bio, 0, epd->bio_flags); BUG_ON(ret < 0); /* -ENOMEM */ @@ -4343,7 +4342,7 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode, u64 last, get_extent_t *get_extent) { - u64 sectorsize = BTRFS_I(inode)->root->sectorsize; + u64 sectorsize = btrfs_inode_sectorsize(inode); struct extent_map *em; u64 len; @@ -4404,8 +4403,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, return -ENOMEM; path->leave_spinning = 1; - start = round_down(start, BTRFS_I(inode)->root->sectorsize); - len = round_up(max, BTRFS_I(inode)->root->sectorsize) - start; + start = round_down(start, btrfs_inode_sectorsize(inode)); + len = round_up(max, btrfs_inode_sectorsize(inode)) - start; /* * lookup the last file extent. We're not using i_size here @@ -4539,7 +4538,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, root->objectid, btrfs_ino(inode), bytenr); if (trans) - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); if (ret < 0) goto out_free; if (ret) @@ -4720,9 +4719,9 @@ struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src) WARN_ON(PageDirty(p)); SetPageUptodate(p); new->pages[i] = p; + copy_page(page_address(p), page_address(src->pages[i])); } - copy_extent_buffer(new, src, 0, 0, src->len); set_bit(EXTENT_BUFFER_UPTODATE, &new->bflags); set_bit(EXTENT_BUFFER_DUMMY, &new->bflags); @@ -4760,21 +4759,9 @@ err: } struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, - u64 start, u32 nodesize) + u64 start) { - unsigned long len; - - if (!fs_info) { - /* - * Called only from tests that don't always have a fs_info - * available - */ - len = nodesize; - } else { - len = fs_info->tree_root->nodesize; - } - - return __alloc_dummy_extent_buffer(fs_info, start, len); + return __alloc_dummy_extent_buffer(fs_info, start, fs_info->nodesize); } static void check_buffer_tree_ref(struct extent_buffer *eb) @@ -4865,7 +4852,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, - u64 start, u32 nodesize) + u64 start) { struct extent_buffer *eb, *exists = NULL; int ret; @@ -4873,7 +4860,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, eb = find_extent_buffer(fs_info, start); if (eb) return eb; - eb = alloc_dummy_extent_buffer(fs_info, start, nodesize); + eb = alloc_dummy_extent_buffer(fs_info, start); if (!eb) return NULL; eb->fs_info = fs_info; @@ -4913,7 +4900,7 @@ free_eb: struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start) { - unsigned long len = fs_info->tree_root->nodesize; + unsigned long len = fs_info->nodesize; unsigned long num_pages = num_extent_pages(start, len); unsigned long i; unsigned long index = start >> PAGE_SHIFT; @@ -4924,7 +4911,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, int uptodate = 1; int ret; - if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) { + if (!IS_ALIGNED(start, fs_info->sectorsize)) { btrfs_err(fs_info, "bad tree block start %llu", start); return ERR_PTR(-EINVAL); } @@ -5465,6 +5452,27 @@ int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv, return ret; } +void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb, + const void *srcv) +{ + char *kaddr; + + WARN_ON(!PageUptodate(eb->pages[0])); + kaddr = page_address(eb->pages[0]); + memcpy(kaddr + offsetof(struct btrfs_header, chunk_tree_uuid), srcv, + BTRFS_FSID_SIZE); +} + +void write_extent_buffer_fsid(struct extent_buffer *eb, const void *srcv) +{ + char *kaddr; + + WARN_ON(!PageUptodate(eb->pages[0])); + kaddr = page_address(eb->pages[0]); + memcpy(kaddr + offsetof(struct btrfs_header, fsid), srcv, + BTRFS_FSID_SIZE); +} + void write_extent_buffer(struct extent_buffer *eb, const void *srcv, unsigned long start, unsigned long len) { @@ -5496,8 +5504,8 @@ void write_extent_buffer(struct extent_buffer *eb, const void *srcv, } } -void memset_extent_buffer(struct extent_buffer *eb, char c, - unsigned long start, unsigned long len) +void memzero_extent_buffer(struct extent_buffer *eb, unsigned long start, + unsigned long len) { size_t cur; size_t offset; @@ -5517,7 +5525,7 @@ void memset_extent_buffer(struct extent_buffer *eb, char c, cur = min(len, PAGE_SIZE - offset); kaddr = page_address(page); - memset(kaddr + offset, c, cur); + memset(kaddr + offset, 0, cur); len -= cur; offset = 0; @@ -5525,6 +5533,20 @@ void memset_extent_buffer(struct extent_buffer *eb, char c, } } +void copy_extent_buffer_full(struct extent_buffer *dst, + struct extent_buffer *src) +{ + int i; + unsigned num_pages; + + ASSERT(dst->len == src->len); + + num_pages = num_extent_pages(dst->start, dst->len); + for (i = 0; i < num_pages; i++) + copy_page(page_address(dst->pages[i]), + page_address(src->pages[i])); +} + void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, unsigned long dst_offset, unsigned long src_offset, unsigned long len) @@ -5766,6 +5788,7 @@ static void copy_pages(struct page *dst_page, struct page *src_page, void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_offset, unsigned long len) { + struct btrfs_fs_info *fs_info = dst->fs_info; size_t cur; size_t dst_off_in_page; size_t src_off_in_page; @@ -5774,13 +5797,13 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_i; if (src_offset + len > dst->len) { - btrfs_err(dst->fs_info, + btrfs_err(fs_info, "memmove bogus src_offset %lu move len %lu dst len %lu", src_offset, len, dst->len); BUG_ON(1); } if (dst_offset + len > dst->len) { - btrfs_err(dst->fs_info, + btrfs_err(fs_info, "memmove bogus dst_offset %lu move len %lu dst len %lu", dst_offset, len, dst->len); BUG_ON(1); @@ -5812,6 +5835,7 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_offset, unsigned long len) { + struct btrfs_fs_info *fs_info = dst->fs_info; size_t cur; size_t dst_off_in_page; size_t src_off_in_page; @@ -5822,13 +5846,13 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_i; if (src_offset + len > dst->len) { - btrfs_err(dst->fs_info, + btrfs_err(fs_info, "memmove bogus src_offset %lu move len %lu len %lu", src_offset, len, dst->len); BUG_ON(1); } if (dst_offset + len > dst->len) { - btrfs_err(dst->fs_info, + btrfs_err(fs_info, "memmove bogus dst_offset %lu move len %lu len %lu", dst_offset, len, dst->len); BUG_ON(1); diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index ab31d145227e..17f9ce479ed7 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -371,7 +371,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, u64 start, unsigned long len); struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, - u64 start, u32 nodesize); + u64 start); struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src); struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, u64 start); @@ -405,8 +405,13 @@ void read_extent_buffer(struct extent_buffer *eb, void *dst, int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dst, unsigned long start, unsigned long len); +void write_extent_buffer_fsid(struct extent_buffer *eb, const void *src); +void write_extent_buffer_chunk_tree_uuid(struct extent_buffer *eb, + const void *src); void write_extent_buffer(struct extent_buffer *eb, const void *src, unsigned long start, unsigned long len); +void copy_extent_buffer_full(struct extent_buffer *dst, + struct extent_buffer *src); void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src, unsigned long dst_offset, unsigned long src_offset, unsigned long len); @@ -414,8 +419,8 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_offset, unsigned long len); void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_offset, unsigned long len); -void memset_extent_buffer(struct extent_buffer *eb, char c, - unsigned long start, unsigned long len); +void memzero_extent_buffer(struct extent_buffer *eb, unsigned long start, + unsigned long len); int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start, unsigned long pos); void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, @@ -452,8 +457,8 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, int clean_io_failure(struct inode *inode, u64 start, struct page *page, unsigned int pg_offset); void end_extent_writepage(struct page *page, int err, u64 start, u64 end); -int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb, - int mirror_num); +int repair_eb_io_failure(struct btrfs_fs_info *fs_info, + struct extent_buffer *eb, int mirror_num); /* * When IO fails, either with EIO or csum verification fails, we @@ -491,5 +496,5 @@ noinline u64 find_lock_delalloc_range(struct inode *inode, u64 *end, u64 max_bytes); #endif struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, - u64 start, u32 nodesize); + u64 start); #endif diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index d0d571c47d33..e97e322c28f0 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -34,9 +34,9 @@ #define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \ PAGE_SIZE)) -#define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ +#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \ sizeof(struct btrfs_ordered_sum)) / \ - sizeof(u32) * (r)->sectorsize) + sizeof(u32) * (fs_info)->sectorsize) int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -90,13 +90,14 @@ btrfs_lookup_csum(struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 bytenr, int cow) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; struct btrfs_key file_key; struct btrfs_key found_key; struct btrfs_csum_item *item; struct extent_buffer *leaf; u64 csum_offset = 0; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); int csums_in_item; file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; @@ -116,7 +117,7 @@ btrfs_lookup_csum(struct btrfs_trans_handle *trans, goto fail; csum_offset = (bytenr - found_key.offset) >> - root->fs_info->sb->s_blocksize_bits; + fs_info->sb->s_blocksize_bits; csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); csums_in_item /= csum_size; @@ -159,11 +160,11 @@ static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err) kfree(bio->csum_allocated); } -static int __btrfs_lookup_bio_sums(struct btrfs_root *root, - struct inode *inode, struct bio *bio, +static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u64 logical_offset, u32 *dst, int dio) { - struct bio_vec *bvec = bio->bi_io_vec; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + struct bio_vec *bvec; struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio); struct btrfs_csum_item *item = NULL; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; @@ -176,9 +177,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, u64 page_bytes_left; u32 diff; int nblocks; - int bio_index = 0; - int count; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + int count = 0, i; + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); path = btrfs_alloc_path(); if (!path) @@ -223,8 +223,11 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, if (dio) offset = logical_offset; - page_bytes_left = bvec->bv_len; - while (bio_index < bio->bi_vcnt) { + bio_for_each_segment_all(bvec, bio, i) { + page_bytes_left = bvec->bv_len; + if (count) + goto next; + if (!dio) offset = page_offset(bvec->bv_page) + bvec->bv_offset; count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, @@ -239,7 +242,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, if (item) btrfs_release_path(path); - item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, + item = btrfs_lookup_csum(NULL, fs_info->csum_root, path, disk_bytenr, 0); if (IS_ERR(item)) { count = 1; @@ -247,10 +250,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, if (BTRFS_I(inode)->root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) { set_extent_bits(io_tree, offset, - offset + root->sectorsize - 1, + offset + fs_info->sectorsize - 1, EXTENT_NODATASUM); } else { - btrfs_info_rl(BTRFS_I(inode)->root->fs_info, + btrfs_info_rl(fs_info, "no csum found for inode %llu start %llu", btrfs_ino(inode), offset); } @@ -266,7 +269,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, path->slots[0]); item_last_offset = item_start_offset + (item_size / csum_size) * - root->sectorsize; + fs_info->sectorsize; item = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_csum_item); } @@ -275,7 +278,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, * a single leaf so it will also fit inside a u32 */ diff = disk_bytenr - item_start_offset; - diff = diff / root->sectorsize; + diff = diff / fs_info->sectorsize; diff = diff * csum_size; count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >> inode->i_sb->s_blocksize_bits); @@ -285,48 +288,35 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, found: csum += count * csum_size; nblocks -= count; - +next: while (count--) { - disk_bytenr += root->sectorsize; - offset += root->sectorsize; - page_bytes_left -= root->sectorsize; - if (!page_bytes_left) { - bio_index++; - /* - * make sure we're still inside the - * bio before we update page_bytes_left - */ - if (bio_index >= bio->bi_vcnt) { - WARN_ON_ONCE(count); - goto done; - } - bvec++; - page_bytes_left = bvec->bv_len; - } - + disk_bytenr += fs_info->sectorsize; + offset += fs_info->sectorsize; + page_bytes_left -= fs_info->sectorsize; + if (!page_bytes_left) + break; /* move to next bio */ } } -done: + WARN_ON_ONCE(count); btrfs_free_path(path); return 0; } -int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u32 *dst) +int btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst) { - return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0); + return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0); } -int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 offset) +int btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, u64 offset) { - return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1); + return __btrfs_lookup_bio_sums(inode, bio, offset, NULL, 1); } int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, struct list_head *list, int search_commit) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; struct btrfs_path *path; struct extent_buffer *leaf; @@ -337,10 +327,10 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, int ret; size_t size; u64 csum_end; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); - ASSERT(IS_ALIGNED(start, root->sectorsize) && - IS_ALIGNED(end + 1, root->sectorsize)); + ASSERT(IS_ALIGNED(start, fs_info->sectorsize) && + IS_ALIGNED(end + 1, fs_info->sectorsize)); path = btrfs_alloc_path(); if (!path) @@ -365,7 +355,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID && key.type == BTRFS_EXTENT_CSUM_KEY) { offset = (start - key.offset) >> - root->fs_info->sb->s_blocksize_bits; + fs_info->sb->s_blocksize_bits; if (offset * csum_size < btrfs_item_size_nr(leaf, path->slots[0] - 1)) path->slots[0]--; @@ -393,7 +383,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, start = key.offset; size = btrfs_item_size_nr(leaf, path->slots[0]); - csum_end = key.offset + (size / csum_size) * root->sectorsize; + csum_end = key.offset + (size / csum_size) * fs_info->sectorsize; if (csum_end <= start) { path->slots[0]++; continue; @@ -404,8 +394,8 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, struct btrfs_csum_item); while (start < csum_end) { size = min_t(size_t, csum_end - start, - MAX_ORDERED_SUM_BYTES(root)); - sums = kzalloc(btrfs_ordered_sum_size(root, size), + MAX_ORDERED_SUM_BYTES(fs_info)); + sums = kzalloc(btrfs_ordered_sum_size(fs_info, size), GFP_NOFS); if (!sums) { ret = -ENOMEM; @@ -416,16 +406,16 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, sums->len = (int)size; offset = (start - key.offset) >> - root->fs_info->sb->s_blocksize_bits; + fs_info->sb->s_blocksize_bits; offset *= csum_size; - size >>= root->fs_info->sb->s_blocksize_bits; + size >>= fs_info->sb->s_blocksize_bits; read_extent_buffer(path->nodes[0], sums->sums, ((unsigned long)item) + offset, csum_size * size); - start += root->sectorsize * size; + start += fs_info->sectorsize * size; list_add_tail(&sums->list, &tmplist); } path->slots[0]++; @@ -443,23 +433,23 @@ fail: return ret; } -int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, - struct bio *bio, u64 file_start, int contig) +int btrfs_csum_one_bio(struct inode *inode, struct bio *bio, + u64 file_start, int contig) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_ordered_sum *sums; - struct btrfs_ordered_extent *ordered; + struct btrfs_ordered_extent *ordered = NULL; char *data; - struct bio_vec *bvec = bio->bi_io_vec; - int bio_index = 0; + struct bio_vec *bvec; int index; int nr_sectors; - int i; + int i, j; unsigned long total_bytes = 0; unsigned long this_sum_bytes = 0; u64 offset; WARN_ON(bio->bi_vcnt <= 0); - sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_iter.bi_size), + sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size), GFP_NOFS); if (!sums) return -ENOMEM; @@ -470,22 +460,25 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, if (contig) offset = file_start; else - offset = page_offset(bvec->bv_page) + bvec->bv_offset; + offset = 0; /* shut up gcc */ - ordered = btrfs_lookup_ordered_extent(inode, offset); - BUG_ON(!ordered); /* Logic error */ sums->bytenr = (u64)bio->bi_iter.bi_sector << 9; index = 0; - while (bio_index < bio->bi_vcnt) { + bio_for_each_segment_all(bvec, bio, j) { if (!contig) offset = page_offset(bvec->bv_page) + bvec->bv_offset; + if (!ordered) { + ordered = btrfs_lookup_ordered_extent(inode, offset); + BUG_ON(!ordered); /* Logic error */ + } + data = kmap_atomic(bvec->bv_page); - nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, - bvec->bv_len + root->sectorsize - - 1); + nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, + bvec->bv_len + fs_info->sectorsize + - 1); for (i = 0; i < nr_sectors; i++) { if (offset >= ordered->file_offset + ordered->len || @@ -500,8 +493,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, bytes_left = bio->bi_iter.bi_size - total_bytes; - sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), - GFP_NOFS); + sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left), + GFP_NOFS); BUG_ON(!sums); /* -ENOMEM */ sums->len = bytes_left; ordered = btrfs_lookup_ordered_extent(inode, @@ -517,21 +510,18 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, sums->sums[index] = ~(u32)0; sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset - + (i * root->sectorsize), + + (i * fs_info->sectorsize), sums->sums[index], - root->sectorsize); + fs_info->sectorsize); btrfs_csum_final(sums->sums[index], (char *)(sums->sums + index)); index++; - offset += root->sectorsize; - this_sum_bytes += root->sectorsize; - total_bytes += root->sectorsize; + offset += fs_info->sectorsize; + this_sum_bytes += fs_info->sectorsize; + total_bytes += fs_info->sectorsize; } kunmap_atomic(data); - - bio_index++; - bvec++; } this_sum_bytes = 0; btrfs_add_ordered_sum(inode, ordered, sums); @@ -550,20 +540,20 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, * This calls btrfs_truncate_item with the correct args based on the * overlap, and fixes up the key as required. */ -static noinline void truncate_one_csum(struct btrfs_root *root, +static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info, struct btrfs_path *path, struct btrfs_key *key, u64 bytenr, u64 len) { struct extent_buffer *leaf; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); u64 csum_end; u64 end_byte = bytenr + len; - u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits; + u32 blocksize_bits = fs_info->sb->s_blocksize_bits; leaf = path->nodes[0]; csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; - csum_end <<= root->fs_info->sb->s_blocksize_bits; + csum_end <<= fs_info->sb->s_blocksize_bits; csum_end += key->offset; if (key->offset < bytenr && csum_end <= end_byte) { @@ -575,7 +565,7 @@ static noinline void truncate_one_csum(struct btrfs_root *root, */ u32 new_size = (bytenr - key->offset) >> blocksize_bits; new_size *= csum_size; - btrfs_truncate_item(root, path, new_size, 1); + btrfs_truncate_item(fs_info, path, new_size, 1); } else if (key->offset >= bytenr && csum_end > end_byte && end_byte > key->offset) { /* @@ -587,10 +577,10 @@ static noinline void truncate_one_csum(struct btrfs_root *root, u32 new_size = (csum_end - end_byte) >> blocksize_bits; new_size *= csum_size; - btrfs_truncate_item(root, path, new_size, 0); + btrfs_truncate_item(fs_info, path, new_size, 0); key->offset = end_byte; - btrfs_set_item_key_safe(root->fs_info, path, key); + btrfs_set_item_key_safe(fs_info, path, key); } else { BUG(); } @@ -601,18 +591,17 @@ static noinline void truncate_one_csum(struct btrfs_root *root, * range of bytes. */ int btrfs_del_csums(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 len) + struct btrfs_fs_info *fs_info, u64 bytenr, u64 len) { + struct btrfs_root *root = fs_info->csum_root; struct btrfs_path *path; struct btrfs_key key; u64 end_byte = bytenr + len; u64 csum_end; struct extent_buffer *leaf; int ret; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); - int blocksize_bits = root->fs_info->sb->s_blocksize_bits; - - root = root->fs_info->csum_root; + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); + int blocksize_bits = fs_info->sb->s_blocksize_bits; path = btrfs_alloc_path(); if (!path) @@ -689,7 +678,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, item_offset = btrfs_item_ptr_offset(leaf, path->slots[0]); - memset_extent_buffer(leaf, 0, item_offset + offset, + memzero_extent_buffer(leaf, item_offset + offset, shift_len); key.offset = bytenr; @@ -705,7 +694,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, key.offset = end_byte - 1; } else { - truncate_one_csum(root, path, &key, bytenr, len); + truncate_one_csum(fs_info, path, &key, bytenr, len); if (key.offset < bytenr) break; } @@ -721,6 +710,7 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_ordered_sum *sums) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key file_key; struct btrfs_key found_key; struct btrfs_path *path; @@ -736,7 +726,7 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, int index = 0; int found_next; int ret; - u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); path = btrfs_alloc_path(); if (!path) @@ -769,7 +759,7 @@ again: leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, path->slots[0]); if ((item_size / csum_size) >= - MAX_CSUM_ITEMS(root, csum_size)) { + MAX_CSUM_ITEMS(fs_info, csum_size)) { /* already at max size, make a new one */ goto insert; } @@ -815,11 +805,11 @@ again: leaf = path->nodes[0]; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); csum_offset = (bytenr - found_key.offset) >> - root->fs_info->sb->s_blocksize_bits; + fs_info->sb->s_blocksize_bits; if (found_key.type != BTRFS_EXTENT_CSUM_KEY || found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || - csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { + csum_offset >= MAX_CSUM_ITEMS(fs_info, csum_size)) { goto insert; } @@ -830,26 +820,27 @@ again: u32 diff; u32 free_space; - if (btrfs_leaf_free_space(root, leaf) < + if (btrfs_leaf_free_space(fs_info, leaf) < sizeof(struct btrfs_item) + csum_size * 2) goto insert; - free_space = btrfs_leaf_free_space(root, leaf) - + free_space = btrfs_leaf_free_space(fs_info, leaf) - sizeof(struct btrfs_item) - csum_size; tmp = sums->len - total_bytes; - tmp >>= root->fs_info->sb->s_blocksize_bits; + tmp >>= fs_info->sb->s_blocksize_bits; WARN_ON(tmp < 1); extend_nr = max_t(int, 1, (int)tmp); diff = (csum_offset + extend_nr) * csum_size; - diff = min(diff, MAX_CSUM_ITEMS(root, csum_size) * csum_size); + diff = min(diff, + MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size); diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); diff = min(free_space, diff); diff /= csum_size; diff *= csum_size; - btrfs_extend_item(root, path, diff); + btrfs_extend_item(fs_info, path, diff); ret = 0; goto csum; } @@ -861,12 +852,12 @@ insert: u64 tmp; tmp = sums->len - total_bytes; - tmp >>= root->fs_info->sb->s_blocksize_bits; + tmp >>= fs_info->sb->s_blocksize_bits; tmp = min(tmp, (next_offset - file_key.offset) >> - root->fs_info->sb->s_blocksize_bits); + fs_info->sb->s_blocksize_bits); tmp = max((u64)1, tmp); - tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); + tmp = min(tmp, (u64)MAX_CSUM_ITEMS(fs_info, csum_size)); ins_size = csum_size * tmp; } else { ins_size = csum_size; @@ -888,7 +879,7 @@ csum: csum_offset * csum_size); found: ins_size = (u32)(sums->len - total_bytes) >> - root->fs_info->sb->s_blocksize_bits; + fs_info->sb->s_blocksize_bits; ins_size *= csum_size; ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item, ins_size); @@ -896,7 +887,7 @@ found: ins_size); ins_size /= csum_size; - total_bytes += ins_size * root->sectorsize; + total_bytes += ins_size * fs_info->sectorsize; index += ins_size; btrfs_mark_buffer_dirty(path->nodes[0]); @@ -919,6 +910,7 @@ void btrfs_extent_item_to_extent_map(struct inode *inode, const bool new_inline, struct extent_map *em) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_buffer *leaf = path->nodes[0]; const int slot = path->slots[0]; @@ -928,7 +920,7 @@ void btrfs_extent_item_to_extent_map(struct inode *inode, u8 type = btrfs_file_extent_type(leaf, fi); int compress_type = btrfs_file_extent_compression(leaf, fi); - em->bdev = root->fs_info->fs_devices->latest_bdev; + em->bdev = fs_info->fs_devices->latest_bdev; btrfs_item_key_to_cpu(leaf, &key, slot); extent_start = key.offset; @@ -939,7 +931,8 @@ void btrfs_extent_item_to_extent_map(struct inode *inode, } else if (type == BTRFS_FILE_EXTENT_INLINE) { size_t size; size = btrfs_file_extent_inline_len(leaf, slot, fi); - extent_end = ALIGN(extent_start + size, root->sectorsize); + extent_end = ALIGN(extent_start + size, + fs_info->sectorsize); } em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); @@ -982,7 +975,7 @@ void btrfs_extent_item_to_extent_map(struct inode *inode, em->compress_type = compress_type; } } else { - btrfs_err(root->fs_info, + btrfs_err(fs_info, "unknown file extent item type %d, inode %llu, offset %llu, root %llu", type, btrfs_ino(inode), extent_start, root->root_key.objectid); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 3a14c87d9c92..b5c5da215d05 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -27,7 +27,6 @@ #include <linux/falloc.h> #include <linux/swap.h> #include <linux/writeback.h> -#include <linux/statfs.h> #include <linux/compat.h> #include <linux/slab.h> #include <linux/btrfs.h> @@ -96,13 +95,13 @@ static int __compare_inode_defrag(struct inode_defrag *defrag1, static int __btrfs_add_inode_defrag(struct inode *inode, struct inode_defrag *defrag) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct inode_defrag *entry; struct rb_node **p; struct rb_node *parent = NULL; int ret; - p = &root->fs_info->defrag_inodes.rb_node; + p = &fs_info->defrag_inodes.rb_node; while (*p) { parent = *p; entry = rb_entry(parent, struct inode_defrag, rb_node); @@ -126,16 +125,16 @@ static int __btrfs_add_inode_defrag(struct inode *inode, } set_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); rb_link_node(&defrag->rb_node, parent, p); - rb_insert_color(&defrag->rb_node, &root->fs_info->defrag_inodes); + rb_insert_color(&defrag->rb_node, &fs_info->defrag_inodes); return 0; } -static inline int __need_auto_defrag(struct btrfs_root *root) +static inline int __need_auto_defrag(struct btrfs_fs_info *fs_info) { - if (!btrfs_test_opt(root->fs_info, AUTO_DEFRAG)) + if (!btrfs_test_opt(fs_info, AUTO_DEFRAG)) return 0; - if (btrfs_fs_closing(root->fs_info)) + if (btrfs_fs_closing(fs_info)) return 0; return 1; @@ -148,12 +147,13 @@ static inline int __need_auto_defrag(struct btrfs_root *root) int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, struct inode *inode) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct inode_defrag *defrag; u64 transid; int ret; - if (!__need_auto_defrag(root)) + if (!__need_auto_defrag(fs_info)) return 0; if (test_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags)) @@ -172,7 +172,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, defrag->transid = transid; defrag->root = root->root_key.objectid; - spin_lock(&root->fs_info->defrag_inodes_lock); + spin_lock(&fs_info->defrag_inodes_lock); if (!test_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags)) { /* * If we set IN_DEFRAG flag and evict the inode from memory, @@ -185,7 +185,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, } else { kmem_cache_free(btrfs_inode_defrag_cachep, defrag); } - spin_unlock(&root->fs_info->defrag_inodes_lock); + spin_unlock(&fs_info->defrag_inodes_lock); return 0; } @@ -197,19 +197,19 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, static void btrfs_requeue_inode_defrag(struct inode *inode, struct inode_defrag *defrag) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); int ret; - if (!__need_auto_defrag(root)) + if (!__need_auto_defrag(fs_info)) goto out; /* * Here we don't check the IN_DEFRAG flag, because we need merge * them together. */ - spin_lock(&root->fs_info->defrag_inodes_lock); + spin_lock(&fs_info->defrag_inodes_lock); ret = __btrfs_add_inode_defrag(inode, defrag); - spin_unlock(&root->fs_info->defrag_inodes_lock); + spin_unlock(&fs_info->defrag_inodes_lock); if (ret) goto out; return; @@ -373,7 +373,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) &fs_info->fs_state)) break; - if (!__need_auto_defrag(fs_info->tree_root)) + if (!__need_auto_defrag(fs_info)) break; /* find an inode to defrag */ @@ -485,11 +485,11 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) * this also makes the decision about creating an inline extent vs * doing real data extents, marking pages dirty and delalloc as required. */ -int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, - struct page **pages, size_t num_pages, - loff_t pos, size_t write_bytes, - struct extent_state **cached) +int btrfs_dirty_pages(struct inode *inode, struct page **pages, + size_t num_pages, loff_t pos, size_t write_bytes, + struct extent_state **cached) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); int err = 0; int i; u64 num_bytes; @@ -498,8 +498,9 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, u64 end_pos = pos + write_bytes; loff_t isize = i_size_read(inode); - start_pos = pos & ~((u64)root->sectorsize - 1); - num_bytes = round_up(write_bytes + pos - start_pos, root->sectorsize); + start_pos = pos & ~((u64) fs_info->sectorsize - 1); + num_bytes = round_up(write_bytes + pos - start_pos, + fs_info->sectorsize); end_of_last_block = start_pos + num_bytes - 1; err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, @@ -696,6 +697,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, u32 extent_item_size, int *key_inserted) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; struct btrfs_key key; @@ -706,6 +708,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, u64 num_bytes = 0; u64 extent_offset = 0; u64 extent_end = 0; + u64 last_end = start; int del_nr = 0; int del_slot = 0; int extent_type; @@ -723,7 +726,7 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, modify_tree = 0; update_refs = (test_bit(BTRFS_ROOT_REF_COWS, &root->state) || - root == root->fs_info->tree_root); + root == fs_info->tree_root); while (1) { recow = 0; ret = btrfs_lookup_file_extent(trans, root, path, ino, @@ -797,8 +800,10 @@ next_slot: * extent item in the call to setup_items_for_insert() later * in this function. */ - if (extent_end == key.offset && extent_end >= search_start) + if (extent_end == key.offset && extent_end >= search_start) { + last_end = extent_end; goto delete_extent_item; + } if (extent_end <= search_start) { path->slots[0]++; @@ -851,7 +856,7 @@ next_slot: btrfs_mark_buffer_dirty(leaf); if (update_refs && disk_bytenr > 0) { - ret = btrfs_inc_extent_ref(trans, root, + ret = btrfs_inc_extent_ref(trans, fs_info, disk_bytenr, num_bytes, 0, root->root_key.objectid, new_key.objectid, @@ -861,6 +866,12 @@ next_slot: key.offset = start; } /* + * From here on out we will have actually dropped something, so + * last_end can be updated. + */ + last_end = extent_end; + + /* * | ---- range to drop ----- | * | -------- extent -------- | */ @@ -872,7 +883,7 @@ next_slot: memcpy(&new_key, &key, sizeof(new_key)); new_key.offset = end; - btrfs_set_item_key_safe(root->fs_info, path, &new_key); + btrfs_set_item_key_safe(fs_info, path, &new_key); extent_offset += end - key.offset; btrfs_set_file_extent_offset(leaf, fi, extent_offset); @@ -927,9 +938,9 @@ delete_extent_item: inode_sub_bytes(inode, extent_end - key.offset); extent_end = ALIGN(extent_end, - root->sectorsize); + fs_info->sectorsize); } else if (update_refs && disk_bytenr > 0) { - ret = btrfs_free_extent(trans, root, + ret = btrfs_free_extent(trans, fs_info, disk_bytenr, num_bytes, 0, root->root_key.objectid, key.objectid, key.offset - @@ -986,7 +997,7 @@ delete_extent_item: if (!ret && replace_extent && leafs_visited == 1 && (path->locks[0] == BTRFS_WRITE_LOCK_BLOCKING || path->locks[0] == BTRFS_WRITE_LOCK) && - btrfs_leaf_free_space(root, leaf) >= + btrfs_leaf_free_space(fs_info, leaf) >= sizeof(struct btrfs_item) + extent_item_size) { key.objectid = ino; @@ -1010,7 +1021,7 @@ delete_extent_item: if (!replace_extent || !(*key_inserted)) btrfs_release_path(path); if (drop_end) - *drop_end = found ? min(end, extent_end) : end; + *drop_end = found ? min(end, last_end) : end; return ret; } @@ -1073,6 +1084,7 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot, int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, struct inode *inode, u64 start, u64 end) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_buffer *leaf; struct btrfs_path *path; @@ -1142,7 +1154,7 @@ again: ino, bytenr, orig_offset, &other_start, &other_end)) { new_key.offset = end; - btrfs_set_item_key_safe(root->fs_info, path, &new_key); + btrfs_set_item_key_safe(fs_info, path, &new_key); fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); btrfs_set_file_extent_generation(leaf, fi, @@ -1176,7 +1188,7 @@ again: trans->transid); path->slots[0]++; new_key.offset = start; - btrfs_set_item_key_safe(root->fs_info, path, &new_key); + btrfs_set_item_key_safe(fs_info, path, &new_key); fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); @@ -1222,8 +1234,8 @@ again: extent_end - split); btrfs_mark_buffer_dirty(leaf); - ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0, - root->root_key.objectid, + ret = btrfs_inc_extent_ref(trans, fs_info, bytenr, num_bytes, + 0, root->root_key.objectid, ino, orig_offset); if (ret) { btrfs_abort_transaction(trans, ret); @@ -1256,7 +1268,7 @@ again: extent_end = other_end; del_slot = path->slots[0] + 1; del_nr++; - ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, 0, root->root_key.objectid, ino, orig_offset); if (ret) { @@ -1276,7 +1288,7 @@ again: key.offset = other_start; del_slot = path->slots[0]; del_nr++; - ret = btrfs_free_extent(trans, root, bytenr, num_bytes, + ret = btrfs_free_extent(trans, fs_info, bytenr, num_bytes, 0, root->root_key.objectid, ino, orig_offset); if (ret) { @@ -1409,15 +1421,16 @@ lock_and_cleanup_extent_if_need(struct inode *inode, struct page **pages, u64 *lockstart, u64 *lockend, struct extent_state **cached_state) { - struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); u64 start_pos; u64 last_pos; int i; int ret = 0; - start_pos = round_down(pos, root->sectorsize); + start_pos = round_down(pos, fs_info->sectorsize); last_pos = start_pos - + round_up(pos + write_bytes - start_pos, root->sectorsize) - 1; + + round_up(pos + write_bytes - start_pos, + fs_info->sectorsize) - 1; if (start_pos < inode->i_size) { struct btrfs_ordered_extent *ordered; @@ -1464,6 +1477,7 @@ lock_and_cleanup_extent_if_need(struct inode *inode, struct page **pages, static noinline int check_can_nocow(struct inode *inode, loff_t pos, size_t *write_bytes) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_ordered_extent *ordered; u64 lockstart, lockend; @@ -1474,8 +1488,9 @@ static noinline int check_can_nocow(struct inode *inode, loff_t pos, if (!ret) return -ENOSPC; - lockstart = round_down(pos, root->sectorsize); - lockend = round_up(pos + *write_bytes, root->sectorsize) - 1; + lockstart = round_down(pos, fs_info->sectorsize); + lockend = round_up(pos + *write_bytes, + fs_info->sectorsize) - 1; while (1) { lock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend); @@ -1509,6 +1524,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, loff_t pos) { struct inode *inode = file_inode(file); + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct page **pages = NULL; struct extent_state *cached_state = NULL; @@ -1555,9 +1571,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, break; } - sector_offset = pos & (root->sectorsize - 1); + sector_offset = pos & (fs_info->sectorsize - 1); reserve_bytes = round_up(write_bytes + sector_offset, - root->sectorsize); + fs_info->sectorsize); ret = btrfs_check_data_free_space(inode, pos, write_bytes); if (ret < 0) { @@ -1577,7 +1593,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, PAGE_SIZE); reserve_bytes = round_up(write_bytes + sector_offset, - root->sectorsize); + fs_info->sectorsize); } else { break; } @@ -1621,12 +1637,10 @@ again: copied = btrfs_copy_from_user(pos, write_bytes, pages, i); - num_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, - reserve_bytes); + num_sectors = BTRFS_BYTES_TO_BLKS(fs_info, reserve_bytes); dirty_sectors = round_up(copied + sector_offset, - root->sectorsize); - dirty_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, - dirty_sectors); + fs_info->sectorsize); + dirty_sectors = BTRFS_BYTES_TO_BLKS(fs_info, dirty_sectors); /* * if we have trouble faulting in the pages, fall @@ -1654,11 +1668,9 @@ again: * managed to copy. */ if (num_sectors > dirty_sectors) { - /* release everything except the sectors we dirtied */ release_bytes -= dirty_sectors << - root->fs_info->sb->s_blocksize_bits; - + fs_info->sb->s_blocksize_bits; if (copied > 0) { spin_lock(&BTRFS_I(inode)->lock); BTRFS_I(inode)->outstanding_extents++; @@ -1670,7 +1682,8 @@ again: } else { u64 __pos; - __pos = round_down(pos, root->sectorsize) + + __pos = round_down(pos, + fs_info->sectorsize) + (dirty_pages << PAGE_SHIFT); btrfs_delalloc_release_space(inode, __pos, release_bytes); @@ -1678,12 +1691,11 @@ again: } release_bytes = round_up(copied + sector_offset, - root->sectorsize); + fs_info->sectorsize); if (copied > 0) - ret = btrfs_dirty_pages(root, inode, pages, - dirty_pages, pos, copied, - NULL); + ret = btrfs_dirty_pages(inode, pages, dirty_pages, + pos, copied, NULL); if (need_unlock) unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, &cached_state, @@ -1698,8 +1710,10 @@ again: btrfs_end_write_no_snapshoting(root); if (only_release_metadata && copied > 0) { - lockstart = round_down(pos, root->sectorsize); - lockend = round_up(pos + copied, root->sectorsize) - 1; + lockstart = round_down(pos, + fs_info->sectorsize); + lockend = round_up(pos + copied, + fs_info->sectorsize) - 1; set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend, EXTENT_NORESERVE, NULL, @@ -1712,8 +1726,8 @@ again: cond_resched(); balance_dirty_pages_ratelimited(inode->i_mapping); - if (dirty_pages < (root->nodesize >> PAGE_SHIFT) + 1) - btrfs_btree_balance_dirty(root); + if (dirty_pages < (fs_info->nodesize >> PAGE_SHIFT) + 1) + btrfs_btree_balance_dirty(fs_info); pos += copied; num_written += copied; @@ -1727,7 +1741,7 @@ again: btrfs_delalloc_release_metadata(inode, release_bytes); } else { btrfs_delalloc_release_space(inode, - round_down(pos, root->sectorsize), + round_down(pos, fs_info->sectorsize), release_bytes); } } @@ -1798,6 +1812,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; u64 start_pos; u64 end_pos; @@ -1829,7 +1844,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, * although we have opened a file as writable, we have * to stop this write operation to ensure FS consistency. */ - if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) { + if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { inode_unlock(inode); err = -EROFS; goto out; @@ -1845,17 +1860,18 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, pos = iocb->ki_pos; count = iov_iter_count(from); - start_pos = round_down(pos, root->sectorsize); + start_pos = round_down(pos, fs_info->sectorsize); oldsize = i_size_read(inode); if (start_pos > oldsize) { /* Expand hole size to cover write data, preventing empty gap */ - end_pos = round_up(pos + count, root->sectorsize); + end_pos = round_up(pos + count, + fs_info->sectorsize); err = btrfs_cont_expand(inode, oldsize, end_pos); if (err) { inode_unlock(inode); goto out; } - if (start_pos > round_up(oldsize, root->sectorsize)) + if (start_pos > round_up(oldsize, fs_info->sectorsize)) clean_page = 1; } @@ -1935,6 +1951,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) { struct dentry *dentry = file_dentry(file); struct inode *inode = d_inode(dentry); + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; struct btrfs_log_ctx ctx; @@ -2045,12 +2062,12 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) * commit does not start nor waits for ordered extents to complete. */ smp_mb(); - if (btrfs_inode_in_log(inode, root->fs_info->generation) || + if (btrfs_inode_in_log(inode, fs_info->generation) || (full_sync && BTRFS_I(inode)->last_trans <= - root->fs_info->last_trans_committed) || + fs_info->last_trans_committed) || (!btrfs_have_ordered_extents_in_range(inode, start, len) && BTRFS_I(inode)->last_trans - <= root->fs_info->last_trans_committed)) { + <= fs_info->last_trans_committed)) { /* * We've had everything committed since the last time we were * modified so clear this flag in case it was set for whatever @@ -2129,7 +2146,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) * which are indicated by ctx.io_err. */ if (ctx.io_err) { - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); ret = ctx.io_err; goto out; } @@ -2138,20 +2155,20 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) if (!ret) { ret = btrfs_sync_log(trans, root, &ctx); if (!ret) { - ret = btrfs_end_transaction(trans, root); + ret = btrfs_end_transaction(trans); goto out; } } if (!full_sync) { ret = btrfs_wait_ordered_range(inode, start, len); if (ret) { - btrfs_end_transaction(trans, root); + btrfs_end_transaction(trans); goto out; } } - ret = btrfs_commit_transaction(trans, root); + ret = btrfs_commit_transaction(trans); } else { - ret = btrfs_end_transaction(trans, root); + ret = btrfs_end_transaction(trans); } out: return ret > 0 ? -EIO : ret; @@ -2208,6 +2225,7 @@ static int hole_mergeable(struct inode *inode, struct extent_buffer *leaf, static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode, struct btrfs_path *path, u64 offset, u64 end) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; @@ -2216,7 +2234,7 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode, struct btrfs_key key; int ret; - if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) + if (btrfs_fs_incompat(fs_info, NO_HOLES)) goto out; key.objectid = btrfs_ino(inode); @@ -2224,9 +2242,15 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode, key.offset = offset; ret = btrfs_search_slot(trans, root, &key, path, 0, 1); - if (ret < 0) + if (ret <= 0) { + /* + * We should have dropped this offset, so if we find it then + * something has gone horribly wrong. + */ + if (ret == 0) + ret = -EINVAL; return ret; - BUG_ON(!ret); + } leaf = path->nodes[0]; if (hole_mergeable(inode, leaf, path->slots[0]-1, offset, end)) { @@ -2248,7 +2272,7 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode, u64 num_bytes; key.offset = offset; - btrfs_set_item_key_safe(root->fs_info, path, &key); + btrfs_set_item_key_safe(fs_info, path, &key); fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item); num_bytes = btrfs_file_extent_num_bytes(leaf, fi) + end - @@ -2284,7 +2308,7 @@ out: hole_em->block_start = EXTENT_MAP_HOLE; hole_em->block_len = 0; hole_em->orig_block_len = 0; - hole_em->bdev = root->fs_info->fs_devices->latest_bdev; + hole_em->bdev = fs_info->fs_devices->latest_bdev; hole_em->compress_type = BTRFS_COMPRESS_NONE; hole_em->generation = trans->transid; @@ -2336,6 +2360,7 @@ static int find_first_non_hole(struct inode *inode, u64 *start, u64 *len) static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_state *cached_state = NULL; struct btrfs_path *path; @@ -2347,13 +2372,13 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) u64 tail_len; u64 orig_start = offset; u64 cur_offset; - u64 min_size = btrfs_calc_trunc_metadata_size(root, 1); + u64 min_size = btrfs_calc_trans_metadata_size(fs_info, 1); u64 drop_end; int ret = 0; int err = 0; unsigned int rsv_count; bool same_block; - bool no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES); + bool no_holes = btrfs_fs_incompat(fs_info, NO_HOLES); u64 ino_size; bool truncated_block = false; bool updated_inode = false; @@ -2363,7 +2388,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) return ret; inode_lock(inode); - ino_size = round_up(inode->i_size, root->sectorsize); + ino_size = round_up(inode->i_size, fs_info->sectorsize); ret = find_first_non_hole(inode, &offset, &len); if (ret < 0) goto out_only_mutex; @@ -2373,11 +2398,11 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) goto out_only_mutex; } - lockstart = round_up(offset, BTRFS_I(inode)->root->sectorsize); + lockstart = round_up(offset, btrfs_inode_sectorsize(inode)); lockend = round_down(offset + len, - BTRFS_I(inode)->root->sectorsize) - 1; - same_block = (BTRFS_BYTES_TO_BLKS(root->fs_info, offset)) - == (BTRFS_BYTES_TO_BLKS(root->fs_info, offset + len - 1)); + btrfs_inode_sectorsize(inode)) - 1; + same_block = (BTRFS_BYTES_TO_BLKS(fs_info, offset)) + == (BTRFS_BYTES_TO_BLKS(fs_info, offset + len - 1)); /* * We needn't truncate any block which is beyond the end of the file * because we are sure there is no data there. @@ -2386,7 +2411,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) * Only do this if we are in the same block and we aren't doing the * entire block. */ - if (same_block && len < root->sectorsize) { + if (same_block && len < fs_info->sectorsize) { if (offset < ino_size) { truncated_block = true; ret = btrfs_truncate_block(inode, offset, len, 0); @@ -2489,12 +2514,12 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) goto out; } - rsv = btrfs_alloc_block_rsv(root, BTRFS_BLOCK_RSV_TEMP); + rsv = btrfs_alloc_block_rsv(fs_info, BTRFS_BLOCK_RSV_TEMP); if (!rsv) { ret = -ENOMEM; goto out_free; } - rsv->size = btrfs_calc_trunc_metadata_size(root, 1); + rsv->size = btrfs_calc_trans_metadata_size(fs_info, 1); rsv->failfast = 1; /* @@ -2509,7 +2534,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) goto out_free; } - ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv, + ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv, rsv, min_size, 0); BUG_ON(ret); trans->block_rsv = rsv; @@ -2523,12 +2548,19 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) if (ret != -ENOSPC) break; - trans->block_rsv = &root->fs_info->trans_block_rsv; + trans->block_rsv = &fs_info->trans_block_rsv; - if (cur_offset < ino_size) { + if (cur_offset < drop_end && cur_offset < ino_size) { ret = fill_holes(trans, inode, path, cur_offset, drop_end); if (ret) { + /* + * If we failed then we didn't insert our hole + * entries for the area we dropped, so now the + * fs is corrupted, so we must abort the + * transaction. + */ + btrfs_abort_transaction(trans, ret); err = ret; break; } @@ -2542,8 +2574,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) break; } - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root); + btrfs_end_transactio |