diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/afs/dir.c | 37 | ||||
| -rw-r--r-- | fs/afs/inode.c | 4 | ||||
| -rw-r--r-- | fs/afs/rxrpc.c | 2 | ||||
| -rw-r--r-- | fs/afs/write.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/delayed-inode.c | 45 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 1 | ||||
| -rw-r--r-- | fs/exec.c | 9 | ||||
| -rw-r--r-- | fs/super.c | 6 | ||||
| -rw-r--r-- | fs/userfaultfd.c | 20 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.c | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_qm.c | 46 |
12 files changed, 136 insertions, 48 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index ff8d5bf4354f..23c7f395d718 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -895,20 +895,38 @@ error: | |||
| 895 | * However, if we didn't have a callback promise outstanding, or it was | 895 | * However, if we didn't have a callback promise outstanding, or it was |
| 896 | * outstanding on a different server, then it won't break it either... | 896 | * outstanding on a different server, then it won't break it either... |
| 897 | */ | 897 | */ |
| 898 | static int afs_dir_remove_link(struct dentry *dentry, struct key *key) | 898 | static int afs_dir_remove_link(struct dentry *dentry, struct key *key, |
| 899 | unsigned long d_version_before, | ||
| 900 | unsigned long d_version_after) | ||
| 899 | { | 901 | { |
| 902 | bool dir_valid; | ||
| 900 | int ret = 0; | 903 | int ret = 0; |
| 901 | 904 | ||
| 905 | /* There were no intervening changes on the server if the version | ||
| 906 | * number we got back was incremented by exactly 1. | ||
| 907 | */ | ||
| 908 | dir_valid = (d_version_after == d_version_before + 1); | ||
| 909 | |||
| 902 | if (d_really_is_positive(dentry)) { | 910 | if (d_really_is_positive(dentry)) { |
| 903 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); | 911 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); |
| 904 | 912 | ||
| 905 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | 913 | if (dir_valid) { |
| 906 | kdebug("AFS_VNODE_DELETED"); | 914 | drop_nlink(&vnode->vfs_inode); |
| 907 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 915 | if (vnode->vfs_inode.i_nlink == 0) { |
| 908 | 916 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | |
| 909 | ret = afs_validate(vnode, key); | 917 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); |
| 910 | if (ret == -ESTALE) | 918 | } |
| 911 | ret = 0; | 919 | ret = 0; |
| 920 | } else { | ||
| 921 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 922 | |||
| 923 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | ||
| 924 | kdebug("AFS_VNODE_DELETED"); | ||
| 925 | |||
| 926 | ret = afs_validate(vnode, key); | ||
| 927 | if (ret == -ESTALE) | ||
| 928 | ret = 0; | ||
| 929 | } | ||
| 912 | _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret); | 930 | _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret); |
| 913 | } | 931 | } |
| 914 | 932 | ||
| @@ -923,6 +941,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 923 | struct afs_fs_cursor fc; | 941 | struct afs_fs_cursor fc; |
| 924 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode; | 942 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode; |
| 925 | struct key *key; | 943 | struct key *key; |
| 944 | unsigned long d_version = (unsigned long)dentry->d_fsdata; | ||
| 926 | int ret; | 945 | int ret; |
| 927 | 946 | ||
| 928 | _enter("{%x:%u},{%pd}", | 947 | _enter("{%x:%u},{%pd}", |
| @@ -955,7 +974,9 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 955 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 974 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); |
| 956 | ret = afs_end_vnode_operation(&fc); | 975 | ret = afs_end_vnode_operation(&fc); |
| 957 | if (ret == 0) | 976 | if (ret == 0) |
| 958 | ret = afs_dir_remove_link(dentry, key); | 977 | ret = afs_dir_remove_link( |
| 978 | dentry, key, d_version, | ||
| 979 | (unsigned long)dvnode->status.data_version); | ||
| 959 | } | 980 | } |
| 960 | 981 | ||
| 961 | error_key: | 982 | error_key: |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 3415eb7484f6..1e81864ef0b2 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
| @@ -377,6 +377,10 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | read_sequnlock_excl(&vnode->cb_lock); | 379 | read_sequnlock_excl(&vnode->cb_lock); |
| 380 | |||
| 381 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | ||
| 382 | clear_nlink(&vnode->vfs_inode); | ||
| 383 | |||
| 380 | if (valid) | 384 | if (valid) |
| 381 | goto valid; | 385 | goto valid; |
| 382 | 386 | ||
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index ea1460b9b71a..e1126659f043 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -885,7 +885,7 @@ int afs_extract_data(struct afs_call *call, void *buf, size_t count, | |||
| 885 | { | 885 | { |
| 886 | struct afs_net *net = call->net; | 886 | struct afs_net *net = call->net; |
| 887 | enum afs_call_state state; | 887 | enum afs_call_state state; |
| 888 | u32 remote_abort; | 888 | u32 remote_abort = 0; |
| 889 | int ret; | 889 | int ret; |
| 890 | 890 | ||
| 891 | _enter("{%s,%zu},,%zu,%d", | 891 | _enter("{%s,%zu},,%zu,%d", |
diff --git a/fs/afs/write.c b/fs/afs/write.c index cb5f8a3df577..9370e2feb999 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
| @@ -198,7 +198,7 @@ int afs_write_end(struct file *file, struct address_space *mapping, | |||
| 198 | ret = afs_fill_page(vnode, key, pos + copied, | 198 | ret = afs_fill_page(vnode, key, pos + copied, |
| 199 | len - copied, page); | 199 | len - copied, page); |
| 200 | if (ret < 0) | 200 | if (ret < 0) |
| 201 | return ret; | 201 | goto out; |
| 202 | } | 202 | } |
| 203 | SetPageUptodate(page); | 203 | SetPageUptodate(page); |
| 204 | } | 204 | } |
| @@ -206,10 +206,12 @@ int afs_write_end(struct file *file, struct address_space *mapping, | |||
| 206 | set_page_dirty(page); | 206 | set_page_dirty(page); |
| 207 | if (PageDirty(page)) | 207 | if (PageDirty(page)) |
| 208 | _debug("dirtied"); | 208 | _debug("dirtied"); |
| 209 | ret = copied; | ||
| 210 | |||
| 211 | out: | ||
| 209 | unlock_page(page); | 212 | unlock_page(page); |
| 210 | put_page(page); | 213 | put_page(page); |
| 211 | 214 | return ret; | |
| 212 | return copied; | ||
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | /* | 217 | /* |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 5d73f79ded8b..056276101c63 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
| @@ -87,6 +87,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( | |||
| 87 | 87 | ||
| 88 | spin_lock(&root->inode_lock); | 88 | spin_lock(&root->inode_lock); |
| 89 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); | 89 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); |
| 90 | |||
| 90 | if (node) { | 91 | if (node) { |
| 91 | if (btrfs_inode->delayed_node) { | 92 | if (btrfs_inode->delayed_node) { |
| 92 | refcount_inc(&node->refs); /* can be accessed */ | 93 | refcount_inc(&node->refs); /* can be accessed */ |
| @@ -94,9 +95,30 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node( | |||
| 94 | spin_unlock(&root->inode_lock); | 95 | spin_unlock(&root->inode_lock); |
| 95 | return node; | 96 | return node; |
| 96 | } | 97 | } |
| 97 | btrfs_inode->delayed_node = node; | 98 | |
| 98 | /* can be accessed and cached in the inode */ | 99 | /* |
| 99 | refcount_add(2, &node->refs); | 100 | * It's possible that we're racing into the middle of removing |
| 101 | * this node from the radix tree. In this case, the refcount | ||
| 102 | * was zero and it should never go back to one. Just return | ||
| 103 | * NULL like it was never in the radix at all; our release | ||
| 104 | * function is in the process of removing it. | ||
| 105 | * | ||
| 106 | * Some implementations of refcount_inc refuse to bump the | ||
| 107 | * refcount once it has hit zero. If we don't do this dance | ||
| 108 | * here, refcount_inc() may decide to just WARN_ONCE() instead | ||
| 109 | * of actually bumping the refcount. | ||
| 110 | * | ||
| 111 | * If this node is properly in the radix, we want to bump the | ||
| 112 | * refcount twice, once for the inode and once for this get | ||
| 113 | * operation. | ||
| 114 | */ | ||
| 115 | if (refcount_inc_not_zero(&node->refs)) { | ||
| 116 | refcount_inc(&node->refs); | ||
| 117 | btrfs_inode->delayed_node = node; | ||
| 118 | } else { | ||
| 119 | node = NULL; | ||
| 120 | } | ||
| 121 | |||
| 100 | spin_unlock(&root->inode_lock); | 122 | spin_unlock(&root->inode_lock); |
| 101 | return node; | 123 | return node; |
| 102 | } | 124 | } |
| @@ -254,17 +276,18 @@ static void __btrfs_release_delayed_node( | |||
| 254 | mutex_unlock(&delayed_node->mutex); | 276 | mutex_unlock(&delayed_node->mutex); |
| 255 | 277 | ||
| 256 | if (refcount_dec_and_test(&delayed_node->refs)) { | 278 | if (refcount_dec_and_test(&delayed_node->refs)) { |
| 257 | bool free = false; | ||
| 258 | struct btrfs_root *root = delayed_node->root; | 279 | struct btrfs_root *root = delayed_node->root; |
| 280 | |||
| 259 | spin_lock(&root->inode_lock); | 281 | spin_lock(&root->inode_lock); |
| 260 | if (refcount_read(&delayed_node->refs) == 0) { | 282 | /* |
| 261 | radix_tree_delete(&root->delayed_nodes_tree, | 283 | * Once our refcount goes to zero, nobody is allowed to bump it |
| 262 | delayed_node->inode_id); | 284 | * back up. We can delete it now. |
| 263 | free = true; | 285 | */ |
| 264 | } | 286 | ASSERT(refcount_read(&delayed_node->refs) == 0); |
| 287 | radix_tree_delete(&root->delayed_nodes_tree, | ||
| 288 | delayed_node->inode_id); | ||
| 265 | spin_unlock(&root->inode_lock); | 289 | spin_unlock(&root->inode_lock); |
| 266 | if (free) | 290 | kmem_cache_free(delayed_node_cache, delayed_node); |
| 267 | kmem_cache_free(delayed_node_cache, delayed_node); | ||
| 268 | } | 291 | } |
| 269 | } | 292 | } |
| 270 | 293 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 49810b70afd3..a25684287501 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -237,7 +237,6 @@ static struct btrfs_device *__alloc_device(void) | |||
| 237 | kfree(dev); | 237 | kfree(dev); |
| 238 | return ERR_PTR(-ENOMEM); | 238 | return ERR_PTR(-ENOMEM); |
| 239 | } | 239 | } |
| 240 | bio_get(dev->flush_bio); | ||
| 241 | 240 | ||
| 242 | INIT_LIST_HEAD(&dev->dev_list); | 241 | INIT_LIST_HEAD(&dev->dev_list); |
| 243 | INIT_LIST_HEAD(&dev->dev_alloc_list); | 242 | INIT_LIST_HEAD(&dev->dev_alloc_list); |
| @@ -1349,9 +1349,14 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
| 1349 | 1349 | ||
| 1350 | current->sas_ss_sp = current->sas_ss_size = 0; | 1350 | current->sas_ss_sp = current->sas_ss_size = 0; |
| 1351 | 1351 | ||
| 1352 | /* Figure out dumpability. */ | 1352 | /* |
| 1353 | * Figure out dumpability. Note that this checking only of current | ||
| 1354 | * is wrong, but userspace depends on it. This should be testing | ||
| 1355 | * bprm->secureexec instead. | ||
| 1356 | */ | ||
| 1353 | if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP || | 1357 | if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP || |
| 1354 | bprm->secureexec) | 1358 | !(uid_eq(current_euid(), current_uid()) && |
| 1359 | gid_eq(current_egid(), current_gid()))) | ||
| 1355 | set_dumpable(current->mm, suid_dumpable); | 1360 | set_dumpable(current->mm, suid_dumpable); |
| 1356 | else | 1361 | else |
| 1357 | set_dumpable(current->mm, SUID_DUMP_USER); | 1362 | set_dumpable(current->mm, SUID_DUMP_USER); |
diff --git a/fs/super.c b/fs/super.c index 7ff1349609e4..06bd25d90ba5 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -517,7 +517,11 @@ retry: | |||
| 517 | hlist_add_head(&s->s_instances, &type->fs_supers); | 517 | hlist_add_head(&s->s_instances, &type->fs_supers); |
| 518 | spin_unlock(&sb_lock); | 518 | spin_unlock(&sb_lock); |
| 519 | get_filesystem(type); | 519 | get_filesystem(type); |
| 520 | register_shrinker(&s->s_shrink); | 520 | err = register_shrinker(&s->s_shrink); |
| 521 | if (err) { | ||
| 522 | deactivate_locked_super(s); | ||
| 523 | s = ERR_PTR(err); | ||
| 524 | } | ||
| 521 | return s; | 525 | return s; |
| 522 | } | 526 | } |
| 523 | 527 | ||
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index ac9a4e65ca49..41a75f9f23fd 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c | |||
| @@ -570,11 +570,14 @@ out: | |||
| 570 | static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, | 570 | static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, |
| 571 | struct userfaultfd_wait_queue *ewq) | 571 | struct userfaultfd_wait_queue *ewq) |
| 572 | { | 572 | { |
| 573 | struct userfaultfd_ctx *release_new_ctx; | ||
| 574 | |||
| 573 | if (WARN_ON_ONCE(current->flags & PF_EXITING)) | 575 | if (WARN_ON_ONCE(current->flags & PF_EXITING)) |
| 574 | goto out; | 576 | goto out; |
| 575 | 577 | ||
| 576 | ewq->ctx = ctx; | 578 | ewq->ctx = ctx; |
| 577 | init_waitqueue_entry(&ewq->wq, current); | 579 | init_waitqueue_entry(&ewq->wq, current); |
| 580 | release_new_ctx = NULL; | ||
| 578 | 581 | ||
| 579 | spin_lock(&ctx->event_wqh.lock); | 582 | spin_lock(&ctx->event_wqh.lock); |
| 580 | /* | 583 | /* |
| @@ -601,8 +604,7 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, | |||
| 601 | new = (struct userfaultfd_ctx *) | 604 | new = (struct userfaultfd_ctx *) |
| 602 | (unsigned long) | 605 | (unsigned long) |
| 603 | ewq->msg.arg.reserved.reserved1; | 606 | ewq->msg.arg.reserved.reserved1; |
| 604 | 607 | release_new_ctx = new; | |
| 605 | userfaultfd_ctx_put(new); | ||
| 606 | } | 608 | } |
| 607 | break; | 609 | break; |
| 608 | } | 610 | } |
| @@ -617,6 +619,20 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, | |||
| 617 | __set_current_state(TASK_RUNNING); | 619 | __set_current_state(TASK_RUNNING); |
| 618 | spin_unlock(&ctx->event_wqh.lock); | 620 | spin_unlock(&ctx->event_wqh.lock); |
| 619 | 621 | ||
| 622 | if (release_new_ctx) { | ||
| 623 | struct vm_area_struct *vma; | ||
| 624 | struct mm_struct *mm = release_new_ctx->mm; | ||
| 625 | |||
| 626 | /* the various vma->vm_userfaultfd_ctx still points to it */ | ||
| 627 | down_write(&mm->mmap_sem); | ||
| 628 | for (vma = mm->mmap; vma; vma = vma->vm_next) | ||
| 629 | if (vma->vm_userfaultfd_ctx.ctx == release_new_ctx) | ||
| 630 | vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX; | ||
| 631 | up_write(&mm->mmap_sem); | ||
| 632 | |||
| 633 | userfaultfd_ctx_put(release_new_ctx); | ||
| 634 | } | ||
| 635 | |||
| 620 | /* | 636 | /* |
| 621 | * ctx may go away after this if the userfault pseudo fd is | 637 | * ctx may go away after this if the userfault pseudo fd is |
| 622 | * already released. | 638 | * already released. |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 21e2d70884e1..4fc526a27a94 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
| @@ -399,7 +399,7 @@ xfs_map_blocks( | |||
| 399 | (ip->i_df.if_flags & XFS_IFEXTENTS)); | 399 | (ip->i_df.if_flags & XFS_IFEXTENTS)); |
| 400 | ASSERT(offset <= mp->m_super->s_maxbytes); | 400 | ASSERT(offset <= mp->m_super->s_maxbytes); |
| 401 | 401 | ||
| 402 | if ((xfs_ufsize_t)offset + count > mp->m_super->s_maxbytes) | 402 | if (offset > mp->m_super->s_maxbytes - count) |
| 403 | count = mp->m_super->s_maxbytes - offset; | 403 | count = mp->m_super->s_maxbytes - offset; |
| 404 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 404 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
| 405 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 405 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
| @@ -1312,7 +1312,7 @@ xfs_get_blocks( | |||
| 1312 | lockmode = xfs_ilock_data_map_shared(ip); | 1312 | lockmode = xfs_ilock_data_map_shared(ip); |
| 1313 | 1313 | ||
| 1314 | ASSERT(offset <= mp->m_super->s_maxbytes); | 1314 | ASSERT(offset <= mp->m_super->s_maxbytes); |
| 1315 | if ((xfs_ufsize_t)offset + size > mp->m_super->s_maxbytes) | 1315 | if (offset > mp->m_super->s_maxbytes - size) |
| 1316 | size = mp->m_super->s_maxbytes - offset; | 1316 | size = mp->m_super->s_maxbytes - offset; |
| 1317 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); | 1317 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); |
| 1318 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 1318 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 7ab52a8bc0a9..66e1edbfb2b2 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -1006,7 +1006,7 @@ xfs_file_iomap_begin( | |||
| 1006 | } | 1006 | } |
| 1007 | 1007 | ||
| 1008 | ASSERT(offset <= mp->m_super->s_maxbytes); | 1008 | ASSERT(offset <= mp->m_super->s_maxbytes); |
| 1009 | if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes) | 1009 | if (offset > mp->m_super->s_maxbytes - length) |
| 1010 | length = mp->m_super->s_maxbytes - offset; | 1010 | length = mp->m_super->s_maxbytes - offset; |
| 1011 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 1011 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
| 1012 | end_fsb = XFS_B_TO_FSB(mp, offset + length); | 1012 | end_fsb = XFS_B_TO_FSB(mp, offset + length); |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index ec952dfad359..b897b11afb2c 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 48 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
| 49 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 49 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
| 50 | 50 | ||
| 51 | 51 | STATIC void xfs_qm_destroy_quotainos(xfs_quotainfo_t *qi); | |
| 52 | STATIC void xfs_qm_dqfree_one(struct xfs_dquot *dqp); | 52 | STATIC void xfs_qm_dqfree_one(struct xfs_dquot *dqp); |
| 53 | /* | 53 | /* |
| 54 | * We use the batch lookup interface to iterate over the dquots as it | 54 | * We use the batch lookup interface to iterate over the dquots as it |
| @@ -695,9 +695,17 @@ xfs_qm_init_quotainfo( | |||
| 695 | qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan; | 695 | qinf->qi_shrinker.scan_objects = xfs_qm_shrink_scan; |
| 696 | qinf->qi_shrinker.seeks = DEFAULT_SEEKS; | 696 | qinf->qi_shrinker.seeks = DEFAULT_SEEKS; |
| 697 | qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE; | 697 | qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE; |
| 698 | register_shrinker(&qinf->qi_shrinker); | 698 | |
| 699 | error = register_shrinker(&qinf->qi_shrinker); | ||
| 700 | if (error) | ||
| 701 | goto out_free_inos; | ||
| 702 | |||
| 699 | return 0; | 703 | return 0; |
| 700 | 704 | ||
| 705 | out_free_inos: | ||
| 706 | mutex_destroy(&qinf->qi_quotaofflock); | ||
| 707 | mutex_destroy(&qinf->qi_tree_lock); | ||
| 708 | xfs_qm_destroy_quotainos(qinf); | ||
| 701 | out_free_lru: | 709 | out_free_lru: |
| 702 | list_lru_destroy(&qinf->qi_lru); | 710 | list_lru_destroy(&qinf->qi_lru); |
| 703 | out_free_qinf: | 711 | out_free_qinf: |
| @@ -706,7 +714,6 @@ out_free_qinf: | |||
| 706 | return error; | 714 | return error; |
| 707 | } | 715 | } |
| 708 | 716 | ||
| 709 | |||
| 710 | /* | 717 | /* |
| 711 | * Gets called when unmounting a filesystem or when all quotas get | 718 | * Gets called when unmounting a filesystem or when all quotas get |
| 712 | * turned off. | 719 | * turned off. |
| @@ -723,19 +730,8 @@ xfs_qm_destroy_quotainfo( | |||
| 723 | 730 | ||
| 724 | unregister_shrinker(&qi->qi_shrinker); | 731 | unregister_shrinker(&qi->qi_shrinker); |
| 725 | list_lru_destroy(&qi->qi_lru); | 732 | list_lru_destroy(&qi->qi_lru); |
| 726 | 733 | xfs_qm_destroy_quotainos(qi); | |
| 727 | if (qi->qi_uquotaip) { | 734 | mutex_destroy(&qi->qi_tree_lock); |
| 728 | IRELE(qi->qi_uquotaip); | ||
| 729 | qi->qi_uquotaip = NULL; /* paranoia */ | ||
| 730 | } | ||
| 731 | if (qi->qi_gquotaip) { | ||
| 732 | IRELE(qi->qi_gquotaip); | ||
| 733 | qi->qi_gquotaip = NULL; | ||
| 734 | } | ||
| 735 | if (qi->qi_pquotaip) { | ||
| 736 | IRELE(qi->qi_pquotaip); | ||
| 737 | qi->qi_pquotaip = NULL; | ||
| 738 | } | ||
| 739 | mutex_destroy(&qi->qi_quotaofflock); | 735 | mutex_destroy(&qi->qi_quotaofflock); |
| 740 | kmem_free(qi); | 736 | kmem_free(qi); |
| 741 | mp->m_quotainfo = NULL; | 737 | mp->m_quotainfo = NULL; |
| @@ -1600,6 +1596,24 @@ error_rele: | |||
| 1600 | } | 1596 | } |
| 1601 | 1597 | ||
| 1602 | STATIC void | 1598 | STATIC void |
| 1599 | xfs_qm_destroy_quotainos( | ||
| 1600 | xfs_quotainfo_t *qi) | ||
| 1601 | { | ||
| 1602 | if (qi->qi_uquotaip) { | ||
| 1603 | IRELE(qi->qi_uquotaip); | ||
| 1604 | qi->qi_uquotaip = NULL; /* paranoia */ | ||
| 1605 | } | ||
| 1606 | if (qi->qi_gquotaip) { | ||
| 1607 | IRELE(qi->qi_gquotaip); | ||
| 1608 | qi->qi_gquotaip = NULL; | ||
| 1609 | } | ||
| 1610 | if (qi->qi_pquotaip) { | ||
| 1611 | IRELE(qi->qi_pquotaip); | ||
| 1612 | qi->qi_pquotaip = NULL; | ||
| 1613 | } | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | STATIC void | ||
| 1603 | xfs_qm_dqfree_one( | 1617 | xfs_qm_dqfree_one( |
| 1604 | struct xfs_dquot *dqp) | 1618 | struct xfs_dquot *dqp) |
| 1605 | { | 1619 | { |
