diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2012-10-31 06:37:10 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2012-11-07 08:33:17 -0500 |
commit | 9dbe9610b9df4efe0946299804ed46bb8f91dec2 (patch) | |
tree | 8d54797420ed9d0aef1c6bdd8f3b8dd5e9938d0a /fs/gfs2/rgrp.c | |
parent | c9aecf73717f55e41ac11682a50bef8594547025 (diff) |
GFS2: Add Orlov allocator
Just like ext3, this works on the root directory and any directory
with the +T flag set. Also, just like ext3, any subdirectory created
in one of the just mentioned cases will be allocated to a random
resource group (GFS2 equivalent of a block group).
If you are creating a set of directories, each of which will contain a
job running on a different node, then by setting +T on the parent
directory before creating the subdirectories, each will land up in a
different resource group, and thus resource group contention between
nodes will be kept to a minimum.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index bdf3e644baae..99a619788c65 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/prefetch.h> | 16 | #include <linux/prefetch.h> |
17 | #include <linux/blkdev.h> | 17 | #include <linux/blkdev.h> |
18 | #include <linux/rbtree.h> | 18 | #include <linux/rbtree.h> |
19 | #include <linux/random.h> | ||
19 | 20 | ||
20 | #include "gfs2.h" | 21 | #include "gfs2.h" |
21 | #include "incore.h" | 22 | #include "incore.h" |
@@ -1763,6 +1764,15 @@ static bool gfs2_rgrp_used_recently(const struct gfs2_blkreserv *rs, | |||
1763 | return tdiff > (msecs * 1000 * 1000); | 1764 | return tdiff > (msecs * 1000 * 1000); |
1764 | } | 1765 | } |
1765 | 1766 | ||
1767 | static u32 gfs2_orlov_skip(const struct gfs2_inode *ip) | ||
1768 | { | ||
1769 | const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1770 | u32 skip; | ||
1771 | |||
1772 | get_random_bytes(&skip, sizeof(skip)); | ||
1773 | return skip % sdp->sd_rgrps; | ||
1774 | } | ||
1775 | |||
1766 | static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin) | 1776 | static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin) |
1767 | { | 1777 | { |
1768 | struct gfs2_rgrpd *rgd = *pos; | 1778 | struct gfs2_rgrpd *rgd = *pos; |
@@ -1784,7 +1794,7 @@ static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *b | |||
1784 | * Returns: errno | 1794 | * Returns: errno |
1785 | */ | 1795 | */ |
1786 | 1796 | ||
1787 | int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) | 1797 | int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags) |
1788 | { | 1798 | { |
1789 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1799 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1790 | struct gfs2_rgrpd *begin = NULL; | 1800 | struct gfs2_rgrpd *begin = NULL; |
@@ -1792,6 +1802,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) | |||
1792 | int error = 0, rg_locked, flags = 0; | 1802 | int error = 0, rg_locked, flags = 0; |
1793 | u64 last_unlinked = NO_BLOCK; | 1803 | u64 last_unlinked = NO_BLOCK; |
1794 | int loops = 0; | 1804 | int loops = 0; |
1805 | u32 skip = 0; | ||
1795 | 1806 | ||
1796 | if (sdp->sd_args.ar_rgrplvb) | 1807 | if (sdp->sd_args.ar_rgrplvb) |
1797 | flags |= GL_SKIP; | 1808 | flags |= GL_SKIP; |
@@ -1805,6 +1816,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) | |||
1805 | } else { | 1816 | } else { |
1806 | rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1); | 1817 | rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1); |
1807 | } | 1818 | } |
1819 | if (S_ISDIR(ip->i_inode.i_mode) && (aflags & GFS2_AF_ORLOV)) | ||
1820 | skip = gfs2_orlov_skip(ip); | ||
1808 | if (rs->rs_rbm.rgd == NULL) | 1821 | if (rs->rs_rbm.rgd == NULL) |
1809 | return -EBADSLT; | 1822 | return -EBADSLT; |
1810 | 1823 | ||
@@ -1813,6 +1826,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested) | |||
1813 | 1826 | ||
1814 | if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) { | 1827 | if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) { |
1815 | rg_locked = 0; | 1828 | rg_locked = 0; |
1829 | if (skip && skip--) | ||
1830 | goto next_rgrp; | ||
1816 | if (!gfs2_rs_active(rs) && (loops < 2) && | 1831 | if (!gfs2_rs_active(rs) && (loops < 2) && |
1817 | gfs2_rgrp_used_recently(rs, 1000) && | 1832 | gfs2_rgrp_used_recently(rs, 1000) && |
1818 | gfs2_rgrp_congested(rs->rs_rbm.rgd, loops)) | 1833 | gfs2_rgrp_congested(rs->rs_rbm.rgd, loops)) |
@@ -1871,6 +1886,8 @@ next_rgrp: | |||
1871 | /* Find the next rgrp, and continue looking */ | 1886 | /* Find the next rgrp, and continue looking */ |
1872 | if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin)) | 1887 | if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin)) |
1873 | continue; | 1888 | continue; |
1889 | if (skip) | ||
1890 | continue; | ||
1874 | 1891 | ||
1875 | /* If we've scanned all the rgrps, but found no free blocks | 1892 | /* If we've scanned all the rgrps, but found no free blocks |
1876 | * then this checks for some less likely conditions before | 1893 | * then this checks for some less likely conditions before |