diff options
-rw-r--r-- | fs/xfs/xfs_alloc.c | 42 | ||||
-rw-r--r-- | fs/xfs/xfs_alloc.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.c | 60 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.h | 4 |
4 files changed, 54 insertions, 56 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 43f791bcd8b1..335206a9c698 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -2208,7 +2208,7 @@ xfs_alloc_read_agf( | |||
2208 | * group or loop over the allocation groups to find the result. | 2208 | * group or loop over the allocation groups to find the result. |
2209 | */ | 2209 | */ |
2210 | int /* error */ | 2210 | int /* error */ |
2211 | __xfs_alloc_vextent( | 2211 | xfs_alloc_vextent( |
2212 | xfs_alloc_arg_t *args) /* allocation argument structure */ | 2212 | xfs_alloc_arg_t *args) /* allocation argument structure */ |
2213 | { | 2213 | { |
2214 | xfs_agblock_t agsize; /* allocation group size */ | 2214 | xfs_agblock_t agsize; /* allocation group size */ |
@@ -2418,46 +2418,6 @@ error0: | |||
2418 | return error; | 2418 | return error; |
2419 | } | 2419 | } |
2420 | 2420 | ||
2421 | static void | ||
2422 | xfs_alloc_vextent_worker( | ||
2423 | struct work_struct *work) | ||
2424 | { | ||
2425 | struct xfs_alloc_arg *args = container_of(work, | ||
2426 | struct xfs_alloc_arg, work); | ||
2427 | unsigned long pflags; | ||
2428 | |||
2429 | /* we are in a transaction context here */ | ||
2430 | current_set_flags_nested(&pflags, PF_FSTRANS); | ||
2431 | |||
2432 | args->result = __xfs_alloc_vextent(args); | ||
2433 | complete(args->done); | ||
2434 | |||
2435 | current_restore_flags_nested(&pflags, PF_FSTRANS); | ||
2436 | } | ||
2437 | |||
2438 | /* | ||
2439 | * Data allocation requests often come in with little stack to work on. Push | ||
2440 | * them off to a worker thread so there is lots of stack to use. Metadata | ||
2441 | * requests, OTOH, are generally from low stack usage paths, so avoid the | ||
2442 | * context switch overhead here. | ||
2443 | */ | ||
2444 | int | ||
2445 | xfs_alloc_vextent( | ||
2446 | struct xfs_alloc_arg *args) | ||
2447 | { | ||
2448 | DECLARE_COMPLETION_ONSTACK(done); | ||
2449 | |||
2450 | if (!args->stack_switch) | ||
2451 | return __xfs_alloc_vextent(args); | ||
2452 | |||
2453 | |||
2454 | args->done = &done; | ||
2455 | INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker); | ||
2456 | queue_work(xfs_alloc_wq, &args->work); | ||
2457 | wait_for_completion(&done); | ||
2458 | return args->result; | ||
2459 | } | ||
2460 | |||
2461 | /* | 2421 | /* |
2462 | * Free an extent. | 2422 | * Free an extent. |
2463 | * Just break up the extent address and hand off to xfs_free_ag_extent | 2423 | * Just break up the extent address and hand off to xfs_free_ag_extent |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index ef7d4885dc2d..feacb061bab7 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -120,10 +120,6 @@ typedef struct xfs_alloc_arg { | |||
120 | char isfl; /* set if is freelist blocks - !acctg */ | 120 | char isfl; /* set if is freelist blocks - !acctg */ |
121 | char userdata; /* set if this is user data */ | 121 | char userdata; /* set if this is user data */ |
122 | xfs_fsblock_t firstblock; /* io first block allocated */ | 122 | xfs_fsblock_t firstblock; /* io first block allocated */ |
123 | struct completion *done; | ||
124 | struct work_struct work; | ||
125 | int result; | ||
126 | char stack_switch; | ||
127 | } xfs_alloc_arg_t; | 123 | } xfs_alloc_arg_t; |
128 | 124 | ||
129 | /* | 125 | /* |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 91259554df8b..83d0cf3df930 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -2441,7 +2441,6 @@ xfs_bmap_btalloc( | |||
2441 | args.tp = ap->tp; | 2441 | args.tp = ap->tp; |
2442 | args.mp = mp; | 2442 | args.mp = mp; |
2443 | args.fsbno = ap->blkno; | 2443 | args.fsbno = ap->blkno; |
2444 | args.stack_switch = ap->stack_switch; | ||
2445 | 2444 | ||
2446 | /* Trim the allocation back to the maximum an AG can fit. */ | 2445 | /* Trim the allocation back to the maximum an AG can fit. */ |
2447 | args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); | 2446 | args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); |
@@ -4620,12 +4619,11 @@ xfs_bmapi_delay( | |||
4620 | 4619 | ||
4621 | 4620 | ||
4622 | STATIC int | 4621 | STATIC int |
4623 | xfs_bmapi_allocate( | 4622 | __xfs_bmapi_allocate( |
4624 | struct xfs_bmalloca *bma, | 4623 | struct xfs_bmalloca *bma) |
4625 | int flags) | ||
4626 | { | 4624 | { |
4627 | struct xfs_mount *mp = bma->ip->i_mount; | 4625 | struct xfs_mount *mp = bma->ip->i_mount; |
4628 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | 4626 | int whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ? |
4629 | XFS_ATTR_FORK : XFS_DATA_FORK; | 4627 | XFS_ATTR_FORK : XFS_DATA_FORK; |
4630 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); | 4628 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); |
4631 | int tmp_logflags = 0; | 4629 | int tmp_logflags = 0; |
@@ -4658,25 +4656,25 @@ xfs_bmapi_allocate( | |||
4658 | * Indicate if this is the first user data in the file, or just any | 4656 | * Indicate if this is the first user data in the file, or just any |
4659 | * user data. | 4657 | * user data. |
4660 | */ | 4658 | */ |
4661 | if (!(flags & XFS_BMAPI_METADATA)) { | 4659 | if (!(bma->flags & XFS_BMAPI_METADATA)) { |
4662 | bma->userdata = (bma->offset == 0) ? | 4660 | bma->userdata = (bma->offset == 0) ? |
4663 | XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; | 4661 | XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; |
4664 | } | 4662 | } |
4665 | 4663 | ||
4666 | bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1; | 4664 | bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1; |
4667 | 4665 | ||
4668 | /* | 4666 | /* |
4669 | * Only want to do the alignment at the eof if it is userdata and | 4667 | * Only want to do the alignment at the eof if it is userdata and |
4670 | * allocation length is larger than a stripe unit. | 4668 | * allocation length is larger than a stripe unit. |
4671 | */ | 4669 | */ |
4672 | if (mp->m_dalign && bma->length >= mp->m_dalign && | 4670 | if (mp->m_dalign && bma->length >= mp->m_dalign && |
4673 | !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { | 4671 | !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { |
4674 | error = xfs_bmap_isaeof(bma, whichfork); | 4672 | error = xfs_bmap_isaeof(bma, whichfork); |
4675 | if (error) | 4673 | if (error) |
4676 | return error; | 4674 | return error; |
4677 | } | 4675 | } |
4678 | 4676 | ||
4679 | if (flags & XFS_BMAPI_STACK_SWITCH) | 4677 | if (bma->flags & XFS_BMAPI_STACK_SWITCH) |
4680 | bma->stack_switch = 1; | 4678 | bma->stack_switch = 1; |
4681 | 4679 | ||
4682 | error = xfs_bmap_alloc(bma); | 4680 | error = xfs_bmap_alloc(bma); |
@@ -4713,7 +4711,7 @@ xfs_bmapi_allocate( | |||
4713 | * A wasdelay extent has been initialized, so shouldn't be flagged | 4711 | * A wasdelay extent has been initialized, so shouldn't be flagged |
4714 | * as unwritten. | 4712 | * as unwritten. |
4715 | */ | 4713 | */ |
4716 | if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) && | 4714 | if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) && |
4717 | xfs_sb_version_hasextflgbit(&mp->m_sb)) | 4715 | xfs_sb_version_hasextflgbit(&mp->m_sb)) |
4718 | bma->got.br_state = XFS_EXT_UNWRITTEN; | 4716 | bma->got.br_state = XFS_EXT_UNWRITTEN; |
4719 | 4717 | ||
@@ -4741,6 +4739,45 @@ xfs_bmapi_allocate( | |||
4741 | return 0; | 4739 | return 0; |
4742 | } | 4740 | } |
4743 | 4741 | ||
4742 | static void | ||
4743 | xfs_bmapi_allocate_worker( | ||
4744 | struct work_struct *work) | ||
4745 | { | ||
4746 | struct xfs_bmalloca *args = container_of(work, | ||
4747 | struct xfs_bmalloca, work); | ||
4748 | unsigned long pflags; | ||
4749 | |||
4750 | /* we are in a transaction context here */ | ||
4751 | current_set_flags_nested(&pflags, PF_FSTRANS); | ||
4752 | |||
4753 | args->result = __xfs_bmapi_allocate(args); | ||
4754 | complete(args->done); | ||
4755 | |||
4756 | current_restore_flags_nested(&pflags, PF_FSTRANS); | ||
4757 | } | ||
4758 | |||
4759 | /* | ||
4760 | * Some allocation requests often come in with little stack to work on. Push | ||
4761 | * them off to a worker thread so there is lots of stack to use. Otherwise just | ||
4762 | * call directly to avoid the context switch overhead here. | ||
4763 | */ | ||
4764 | int | ||
4765 | xfs_bmapi_allocate( | ||
4766 | struct xfs_bmalloca *args) | ||
4767 | { | ||
4768 | DECLARE_COMPLETION_ONSTACK(done); | ||
4769 | |||
4770 | if (!args->stack_switch) | ||
4771 | return __xfs_bmapi_allocate(args); | ||
4772 | |||
4773 | |||
4774 | args->done = &done; | ||
4775 | INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); | ||
4776 | queue_work(xfs_alloc_wq, &args->work); | ||
4777 | wait_for_completion(&done); | ||
4778 | return args->result; | ||
4779 | } | ||
4780 | |||
4744 | STATIC int | 4781 | STATIC int |
4745 | xfs_bmapi_convert_unwritten( | 4782 | xfs_bmapi_convert_unwritten( |
4746 | struct xfs_bmalloca *bma, | 4783 | struct xfs_bmalloca *bma, |
@@ -4926,6 +4963,7 @@ xfs_bmapi_write( | |||
4926 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); | 4963 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); |
4927 | bma.wasdel = wasdelay; | 4964 | bma.wasdel = wasdelay; |
4928 | bma.offset = bno; | 4965 | bma.offset = bno; |
4966 | bma.flags = flags; | ||
4929 | 4967 | ||
4930 | /* | 4968 | /* |
4931 | * There's a 32/64 bit type mismatch between the | 4969 | * There's a 32/64 bit type mismatch between the |
@@ -4941,7 +4979,7 @@ xfs_bmapi_write( | |||
4941 | 4979 | ||
4942 | ASSERT(len > 0); | 4980 | ASSERT(len > 0); |
4943 | ASSERT(bma.length > 0); | 4981 | ASSERT(bma.length > 0); |
4944 | error = xfs_bmapi_allocate(&bma, flags); | 4982 | error = xfs_bmapi_allocate(&bma); |
4945 | if (error) | 4983 | if (error) |
4946 | goto error0; | 4984 | goto error0; |
4947 | if (bma.blkno == NULLFSBLOCK) | 4985 | if (bma.blkno == NULLFSBLOCK) |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index b68c598034c1..5f469c3516eb 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -136,6 +136,10 @@ typedef struct xfs_bmalloca { | |||
136 | char aeof; /* allocated space at eof */ | 136 | char aeof; /* allocated space at eof */ |
137 | char conv; /* overwriting unwritten extents */ | 137 | char conv; /* overwriting unwritten extents */ |
138 | char stack_switch; | 138 | char stack_switch; |
139 | int flags; | ||
140 | struct completion *done; | ||
141 | struct work_struct work; | ||
142 | int result; | ||
139 | } xfs_bmalloca_t; | 143 | } xfs_bmalloca_t; |
140 | 144 | ||
141 | /* | 145 | /* |