diff options
author | David Chinner <dgc@sgi.com> | 2007-07-10 21:09:12 -0400 |
---|---|---|
committer | Tim Shimmin <tes@chook.melbourne.sgi.com> | 2007-07-14 01:40:53 -0400 |
commit | 2a82b8be8a8dacb48cb7371449a7a9daa558b4a8 (patch) | |
tree | 44e6a81dd0e7d7dc634e04b9230b5262a254c5ee /fs/xfs/xfs_vnodeops.c | |
parent | 0892ccd6fe13e08ad9e57007afbb78fe02d66005 (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_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 2067d0b0a10e..60fd0be90a16 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "xfs_refcache.h" | 51 | #include "xfs_refcache.h" |
52 | #include "xfs_trans_space.h" | 52 | #include "xfs_trans_space.h" |
53 | #include "xfs_log_priv.h" | 53 | #include "xfs_log_priv.h" |
54 | #include "xfs_filestream.h" | ||
54 | 55 | ||
55 | STATIC int | 56 | STATIC int |
56 | xfs_open( | 57 | xfs_open( |
@@ -783,6 +784,8 @@ xfs_setattr( | |||
783 | di_flags |= XFS_DIFLAG_PROJINHERIT; | 784 | di_flags |= XFS_DIFLAG_PROJINHERIT; |
784 | if (vap->va_xflags & XFS_XFLAG_NODEFRAG) | 785 | if (vap->va_xflags & XFS_XFLAG_NODEFRAG) |
785 | di_flags |= XFS_DIFLAG_NODEFRAG; | 786 | di_flags |= XFS_DIFLAG_NODEFRAG; |
787 | if (vap->va_xflags & XFS_XFLAG_FILESTREAM) | ||
788 | di_flags |= XFS_DIFLAG_FILESTREAM; | ||
786 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { | 789 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { |
787 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) | 790 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) |
788 | di_flags |= XFS_DIFLAG_RTINHERIT; | 791 | di_flags |= XFS_DIFLAG_RTINHERIT; |
@@ -1536,7 +1539,17 @@ xfs_release( | |||
1536 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) | 1539 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) |
1537 | return 0; | 1540 | return 0; |
1538 | 1541 | ||
1539 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 1542 | if (!XFS_FORCED_SHUTDOWN(mp)) { |
1543 | /* | ||
1544 | * If we are using filestreams, and we have an unlinked | ||
1545 | * file that we are processing the last close on, then nothing | ||
1546 | * will be able to reopen and write to this file. Purge this | ||
1547 | * inode from the filestreams cache so that it doesn't delay | ||
1548 | * teardown of the inode. | ||
1549 | */ | ||
1550 | if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip)) | ||
1551 | xfs_filestream_deassociate(ip); | ||
1552 | |||
1540 | /* | 1553 | /* |
1541 | * If we previously truncated this file and removed old data | 1554 | * If we previously truncated this file and removed old data |
1542 | * in the process, we want to initiate "early" writeout on | 1555 | * in the process, we want to initiate "early" writeout on |
@@ -1551,7 +1564,6 @@ xfs_release( | |||
1551 | bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); | 1564 | bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); |
1552 | } | 1565 | } |
1553 | 1566 | ||
1554 | |||
1555 | #ifdef HAVE_REFCACHE | 1567 | #ifdef HAVE_REFCACHE |
1556 | /* If we are in the NFS reference cache then don't do this now */ | 1568 | /* If we are in the NFS reference cache then don't do this now */ |
1557 | if (ip->i_refcache) | 1569 | if (ip->i_refcache) |
@@ -2541,6 +2553,15 @@ xfs_remove( | |||
2541 | */ | 2553 | */ |
2542 | xfs_refcache_purge_ip(ip); | 2554 | xfs_refcache_purge_ip(ip); |
2543 | 2555 | ||
2556 | /* | ||
2557 | * If we are using filestreams, kill the stream association. | ||
2558 | * If the file is still open it may get a new one but that | ||
2559 | * will get killed on last close in xfs_close() so we don't | ||
2560 | * have to worry about that. | ||
2561 | */ | ||
2562 | if (link_zero && xfs_inode_is_filestream(ip)) | ||
2563 | xfs_filestream_deassociate(ip); | ||
2564 | |||
2544 | vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); | 2565 | vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); |
2545 | 2566 | ||
2546 | /* | 2567 | /* |