|
@@ -16,6 +16,7 @@
|
|
|
#include <linux/prefetch.h>
|
|
|
#include <linux/blkdev.h>
|
|
|
#include <linux/rbtree.h>
|
|
|
+#include <linux/random.h>
|
|
|
|
|
|
#include "gfs2.h"
|
|
|
#include "incore.h"
|
|
@@ -1763,6 +1764,15 @@ static bool gfs2_rgrp_used_recently(const struct gfs2_blkreserv *rs,
|
|
|
return tdiff > (msecs * 1000 * 1000);
|
|
|
}
|
|
|
|
|
|
+static u32 gfs2_orlov_skip(const struct gfs2_inode *ip)
|
|
|
+{
|
|
|
+ const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
+ u32 skip;
|
|
|
+
|
|
|
+ get_random_bytes(&skip, sizeof(skip));
|
|
|
+ return skip % sdp->sd_rgrps;
|
|
|
+}
|
|
|
+
|
|
|
static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin)
|
|
|
{
|
|
|
struct gfs2_rgrpd *rgd = *pos;
|
|
@@ -1784,7 +1794,7 @@ static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *b
|
|
|
* Returns: errno
|
|
|
*/
|
|
|
|
|
|
-int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
|
|
|
+int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
|
|
|
{
|
|
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
|
|
struct gfs2_rgrpd *begin = NULL;
|
|
@@ -1792,6 +1802,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
|
|
|
int error = 0, rg_locked, flags = 0;
|
|
|
u64 last_unlinked = NO_BLOCK;
|
|
|
int loops = 0;
|
|
|
+ u32 skip = 0;
|
|
|
|
|
|
if (sdp->sd_args.ar_rgrplvb)
|
|
|
flags |= GL_SKIP;
|
|
@@ -1805,6 +1816,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
|
|
|
} else {
|
|
|
rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1);
|
|
|
}
|
|
|
+ if (S_ISDIR(ip->i_inode.i_mode) && (aflags & GFS2_AF_ORLOV))
|
|
|
+ skip = gfs2_orlov_skip(ip);
|
|
|
if (rs->rs_rbm.rgd == NULL)
|
|
|
return -EBADSLT;
|
|
|
|
|
@@ -1813,6 +1826,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
|
|
|
|
|
|
if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) {
|
|
|
rg_locked = 0;
|
|
|
+ if (skip && skip--)
|
|
|
+ goto next_rgrp;
|
|
|
if (!gfs2_rs_active(rs) && (loops < 2) &&
|
|
|
gfs2_rgrp_used_recently(rs, 1000) &&
|
|
|
gfs2_rgrp_congested(rs->rs_rbm.rgd, loops))
|
|
@@ -1871,6 +1886,8 @@ next_rgrp:
|
|
|
/* Find the next rgrp, and continue looking */
|
|
|
if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin))
|
|
|
continue;
|
|
|
+ if (skip)
|
|
|
+ continue;
|
|
|
|
|
|
/* If we've scanned all the rgrps, but found no free blocks
|
|
|
* then this checks for some less likely conditions before
|