[PATCH 1/3] xfs: add agskip=value mount option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The agskip mount option specifies  the allocation group, (AG) for a new
file, relative to the start of the last created file. agskip has the
opposite effect of the rotorstep  system tunable  parameter.   Each
new  file  to  be placed in the location lastAG + agskipValue,
where lastAG is the allocation group of the last created file.

For example, agskip=3 means each new file will be  allocated  three  AGs  away
from the starting AG of the most recently created file.

The agskip mount option disables the rotorstep system tunable parameter.

Signed-off-by: Rich Johnston <rjohnston@xxxxxxx> 
---
 fs/xfs/xfs_alloc.c      |   35 ++++++++++++++++++++++++++++-------
 fs/xfs/xfs_filestream.c |    8 +++++++-
 fs/xfs/xfs_mount.c      |    1 +
 fs/xfs/xfs_mount.h      |    4 +++-
 fs/xfs/xfs_super.c      |   13 ++++++++++++-
 5 files changed, 51 insertions(+), 10 deletions(-)

Index: b/fs/xfs/xfs_alloc.c
===================================================================
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2365,12 +2365,20 @@ xfs_alloc_vextent(
 		 * Try near allocation first, then anywhere-in-ag after
 		 * the first a.g. fails.
 		 */
-		if ((args->userdata  == XFS_ALLOC_INITIAL_USER_DATA) &&
-		    (mp->m_flags & XFS_MOUNT_32BITINODES)) {
-			args->fsbno = XFS_AGB_TO_FSB(mp,
-					((mp->m_agfrotor / rotorstep) %
-					mp->m_sb.sb_agcount), 0);
-			bump_rotor = 1;
+		if (args->userdata == XFS_ALLOC_INITIAL_USER_DATA) {
+			if (mp->m_flags & XFS_MOUNT_AGSKIP) {
+				spin_lock(&mp->m_agfrotor_lock);
+				args->fsbno = XFS_AGB_TO_FSB(mp,
+					mp->m_agfrotor, 0);
+				mp->m_agfrotor = (mp->m_agfrotor + mp->m_agskip)
+					% mp->m_sb.sb_agcount;
+				spin_unlock(&mp->m_agfrotor_lock);
+			} else if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+				args->fsbno = XFS_AGB_TO_FSB(mp,
+						((mp->m_agfrotor / rotorstep) %
+						mp->m_sb.sb_agcount), 0);
+				bump_rotor = 1;
+			}
 		}
 		args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
 		args->type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -2385,8 +2393,21 @@ xfs_alloc_vextent(
 			/*
 			 * Start with the last place we left off.
 			 */
-			args->agno = sagno = (mp->m_agfrotor / rotorstep) %
+                        if (mp->m_flags & XFS_MOUNT_AGSKIP) {
+				/*
+				 * The spinlock makes the combined assignment
+				 * of args->fsbno and mp->m_agfrotor atomic.
+				 * mp->m_agfrotor can not be advanced until
+				 * args->fsbno is assigned.
+				*/
+                                spin_lock(&mp->m_agfrotor_lock);
+                                sagno = mp->m_agfrotor;
+                                spin_unlock(&mp->m_agfrotor_lock);
+                        } else {
+				sagno = (mp->m_agfrotor / rotorstep) %
 					mp->m_sb.sb_agcount;
+			}
+			args->agno = sagno;
 			args->type = XFS_ALLOCTYPE_THIS_AG;
 			flags = XFS_ALLOC_FLAG_TRYLOCK;
 		} else if (type == XFS_ALLOCTYPE_FIRST_AG) {
Index: b/fs/xfs/xfs_filestream.c
===================================================================
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -622,7 +622,13 @@ xfs_filestream_associate(
 	 * Set the starting AG using the rotor for inode32, otherwise
 	 * use the directory inode's AG.
 	 */
-	if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+	if (mp->m_flags & XFS_MOUNT_AGSKIP) {
+		spin_lock(&mp->m_agfrotor_lock);
+		startag = mp->m_agfrotor;
+		mp->m_agfrotor = (mp->m_agfrotor + mp->m_agskip)
+			% mp->m_sb.sb_agcount;
+		spin_unlock(&mp->m_agfrotor_lock);
+	} else if (mp->m_flags & XFS_MOUNT_32BITINODES) {
 		rotorstep = xfs_rotorstep;
 		startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
 		mp->m_agfrotor = (mp->m_agfrotor + 1) %
Index: b/fs/xfs/xfs_mount.c
===================================================================
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -768,6 +768,7 @@ STATIC void
 xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
 {
 	mp->m_agfrotor = mp->m_agirotor = 0;
+	spin_lock_init(&mp->m_agfrotor_lock);
 	spin_lock_init(&mp->m_agirotor_lock);
 	mp->m_maxagi = mp->m_sb.sb_agcount;
 	mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
Index: b/fs/xfs/xfs_mount.h
===================================================================
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -119,6 +119,7 @@ typedef struct xfs_mount {
 	char			*m_logname;	/* external log device name */
 	int			m_bsize;	/* fs logical block size */
 	xfs_agnumber_t		m_agfrotor;	/* last ag where space found */
+	spinlock_t		m_agfrotor_lock;/* .. and lock protecting it */
 	xfs_agnumber_t		m_agirotor;	/* last ag dir inode alloced */
 	spinlock_t		m_agirotor_lock;/* .. and lock protecting it */
 	xfs_agnumber_t		m_maxagi;	/* highest inode alloc group */
@@ -203,6 +204,7 @@ typedef struct xfs_mount {
 	struct shrinker		m_inode_shrink;	/* inode reclaim shrinker */
 	int64_t			m_low_space[XFS_LOWSP_MAX];
 						/* low free space thresholds */
+	int			m_agskip;	/* extent allocation stride */
 
 	struct workqueue_struct	*m_data_workqueue;
 	struct workqueue_struct	*m_unwritten_workqueue;
@@ -246,7 +248,7 @@ typedef struct xfs_mount {
 #define XFS_MOUNT_FILESTREAMS	(1ULL << 24)	/* enable the filestreams
 						   allocator */
 #define XFS_MOUNT_NOATTR2	(1ULL << 25)	/* disable use of attr2 format */
-
+#define XFS_MOUNT_AGSKIP	(1ULL << 26)	/* extent allocation stride */
 
 /*
  * Default minimum read and write sizes.
Index: b/fs/xfs/xfs_super.c
===================================================================
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -114,7 +114,7 @@ mempool_t *xfs_ioend_pool;
 #define MNTOPT_NODELAYLOG  "nodelaylog"	/* Delayed logging disabled */
 #define MNTOPT_DISCARD	   "discard"	/* Discard unused blocks */
 #define MNTOPT_NODISCARD   "nodiscard"	/* Do not discard unused blocks */
-
+#define MNTOPT_AGSKIP      "agskip"	/* initial extent allocation stride */
 /*
  * Table driven mount option parser.
  *
@@ -383,6 +383,15 @@ xfs_parseargs(
 		} else if (!strcmp(this_char, "irixsgid")) {
 			xfs_warn(mp,
 	"irixsgid is now a sysctl(2) variable, option is deprecated.");
+		} else if (!strcmp(this_char, MNTOPT_AGSKIP)) {
+			if (!value || !*value) {
+				xfs_warn(mp,
+					"%s option requires an argument",
+					this_char);
+				return EINVAL;
+			}
+			mp->m_flags |= XFS_MOUNT_AGSKIP;
+			mp->m_agskip = simple_strtoul(value, &eov, 10);
 		} else {
 			xfs_warn(mp, "unknown mount option [%s].", this_char);
 			return EINVAL;
@@ -567,6 +576,8 @@ xfs_showargs(
 
 	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
 		seq_puts(m, "," MNTOPT_NOQUOTA);
+	if (mp->m_flags & XFS_MOUNT_AGSKIP)
+		seq_printf(m, "," MNTOPT_AGSKIP "=%d", mp->m_agskip);
 
 	return 0;
 }

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs


[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux