aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2007-07-10 21:09:12 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-07-14 01:40:53 -0400
commit2a82b8be8a8dacb48cb7371449a7a9daa558b4a8 (patch)
tree44e6a81dd0e7d7dc634e04b9230b5262a254c5ee /fs/xfs/xfs_bmap.c
parent0892ccd6fe13e08ad9e57007afbb78fe02d66005 (diff)
[XFS] Concurrent Multi-File Data Streams
In media spaces, video is often stored in a frame-per-file format. When dealing with uncompressed realtime HD video streams in this format, it is crucial that files do not get fragmented and that multiple files a placed contiguously on disk. When multiple streams are being ingested and played out at the same time, it is critical that the filesystem does not cross the streams and interleave them together as this creates seek and readahead cache miss latency and prevents both ingest and playout from meeting frame rate targets. This patch set creates a "stream of files" concept into the allocator to place all the data from a single stream contiguously on disk so that RAID array readahead can be used effectively. Each additional stream gets placed in different allocation groups within the filesystem, thereby ensuring that we don't cross any streams. When an AG fills up, we select a new AG for the stream that is not in use. The core of the functionality is the stream tracking - each inode that we create in a directory needs to be associated with the directories' stream. Hence every time we create a file, we look up the directories' stream object and associate the new file with that object. Once we have a stream object for a file, we use the AG that the stream object point to for allocations. If we can't allocate in that AG (e.g. it is full) we move the entire stream to another AG. Other inodes in the same stream are moved to the new AG on their next allocation (i.e. lazy update). Stream objects are kept in a cache and hold a reference on the inode. Hence the inode cannot be reclaimed while there is an outstanding stream reference. This means that on unlink we need to remove the stream association and we also need to flush all the associations on certain events that want to reclaim all unreferenced inodes (e.g. filesystem freeze). SGI-PV: 964469 SGI-Modid: xfs-linux-melb:xfs-kern:29096a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Barry Naujok <bnaujok@sgi.com> Signed-off-by: Donald Douwsma <donaldd@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Tim Shimmin <tes@sgi.com> Signed-off-by: Vlad Apostolov <vapo@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c69
1 files changed, 62 insertions, 7 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 09d86388bb71..51ba689a4552 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -52,6 +52,7 @@
52#include "xfs_quota.h" 52#include "xfs_quota.h"
53#include "xfs_trans_space.h" 53#include "xfs_trans_space.h"
54#include "xfs_buf_item.h" 54#include "xfs_buf_item.h"
55#include "xfs_filestream.h"
55 56
56 57
57#ifdef DEBUG 58#ifdef DEBUG
@@ -2725,9 +2726,15 @@ xfs_bmap_btalloc(
2725 } 2726 }
2726 nullfb = ap->firstblock == NULLFSBLOCK; 2727 nullfb = ap->firstblock == NULLFSBLOCK;
2727 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); 2728 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2728 if (nullfb) 2729 if (nullfb) {
2729 ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); 2730 if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
2730 else 2731 ag = xfs_filestream_lookup_ag(ap->ip);
2732 ag = (ag != NULLAGNUMBER) ? ag : 0;
2733 ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
2734 } else {
2735 ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2736 }
2737 } else
2731 ap->rval = ap->firstblock; 2738 ap->rval = ap->firstblock;
2732 2739
2733 xfs_bmap_adjacent(ap); 2740 xfs_bmap_adjacent(ap);
@@ -2751,13 +2758,22 @@ xfs_bmap_btalloc(
2751 args.firstblock = ap->firstblock; 2758 args.firstblock = ap->firstblock;
2752 blen = 0; 2759 blen = 0;
2753 if (nullfb) { 2760 if (nullfb) {
2754 args.type = XFS_ALLOCTYPE_START_BNO; 2761 if (ap->userdata && xfs_inode_is_filestream(ap->ip))
2762 args.type = XFS_ALLOCTYPE_NEAR_BNO;
2763 else
2764 args.type = XFS_ALLOCTYPE_START_BNO;
2755 args.total = ap->total; 2765 args.total = ap->total;
2766
2756 /* 2767 /*
2757 * Find the longest available space. 2768 * Search for an allocation group with a single extent
2758 * We're going to try for the whole allocation at once. 2769 * large enough for the request.
2770 *
2771 * If one isn't found, then adjust the minimum allocation
2772 * size to the largest space found.
2759 */ 2773 */
2760 startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno); 2774 startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2775 if (startag == NULLAGNUMBER)
2776 startag = ag = 0;
2761 notinit = 0; 2777 notinit = 0;
2762 down_read(&mp->m_peraglock); 2778 down_read(&mp->m_peraglock);
2763 while (blen < ap->alen) { 2779 while (blen < ap->alen) {
@@ -2783,6 +2799,35 @@ xfs_bmap_btalloc(
2783 blen = longest; 2799 blen = longest;
2784 } else 2800 } else
2785 notinit = 1; 2801 notinit = 1;
2802
2803 if (xfs_inode_is_filestream(ap->ip)) {
2804 if (blen >= ap->alen)
2805 break;
2806
2807 if (ap->userdata) {
2808 /*
2809 * If startag is an invalid AG, we've
2810 * come here once before and
2811 * xfs_filestream_new_ag picked the
2812 * best currently available.
2813 *
2814 * Don't continue looping, since we
2815 * could loop forever.
2816 */
2817 if (startag == NULLAGNUMBER)
2818 break;
2819
2820 error = xfs_filestream_new_ag(ap, &ag);
2821 if (error) {
2822 up_read(&mp->m_peraglock);
2823 return error;
2824 }
2825
2826 /* loop again to set 'blen'*/
2827 startag = NULLAGNUMBER;
2828 continue;
2829 }
2830 }
2786 if (++ag == mp->m_sb.sb_agcount) 2831 if (++ag == mp->m_sb.sb_agcount)
2787 ag = 0; 2832 ag = 0;
2788 if (ag == startag) 2833 if (ag == startag)
@@ -2807,8 +2852,18 @@ xfs_bmap_btalloc(
2807 */ 2852 */
2808 else 2853 else
2809 args.minlen = ap->alen; 2854 args.minlen = ap->alen;
2855
2856 /*
2857 * set the failure fallback case to look in the selected
2858 * AG as the stream may have moved.
2859 */
2860 if (xfs_inode_is_filestream(ap->ip))
2861 ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
2810 } else if (ap->low) { 2862 } else if (ap->low) {
2811 args.type = XFS_ALLOCTYPE_START_BNO; 2863 if (xfs_inode_is_filestream(ap->ip))
2864 args.type = XFS_ALLOCTYPE_FIRST_AG;
2865 else
2866 args.type = XFS_ALLOCTYPE_START_BNO;
2812 args.total = args.minlen = ap->minlen; 2867 args.total = args.minlen = ap->minlen;
2813 } else { 2868 } else {
2814 args.type = XFS_ALLOCTYPE_NEAR_BNO; 2869 args.type = XFS_ALLOCTYPE_NEAR_BNO;