int m_bsize; /* fs logical block size */
xfs_agnumber_t m_agfrotor; /* last ag where space found */
xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */
+ xfs_agnumber_t m_maxagi; /* highest inode alloc group */
uint m_rsumlevels; /* rt summary levels */
uint m_rsumsize; /* size of rt summary, bytes */
struct xfs_inode *m_rbmip; /* pointer to bitmap inode */
{
char pagf_init; /* this agf's entry is initialized */
char pagi_init; /* this agi's entry is initialized */
+ char pagf_metadata; /* the agf is prefered to be metadata */
+ char pagi_inodeok; /* The agi is ok for inodes */
__uint8_t pagf_levels[XFS_BTNUM_AGF];
/* # of levels in bno & cnt btree */
__uint32_t pagf_flcount; /* count of blocks in freelist */
char userdata; /* set if this is user data */
} xfs_alloc_arg_t;
+/*
+ * Defines for userdata
+ */
+#define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/
+#define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */
+
#ifdef __KERNEL__
return 0;
}
+#define XFS_MOUNT_32BITINODES 0x1
/*
* Mount structure initialization, provides a filled-in xfs_mount_t
* such that the numerous XFS_* macros can be used. If dev is zero,
mp->m_dev = dev;
mp->m_rtdev = rtdev;
mp->m_logdev = logdev;
+ mp->m_flags = XFS_MOUNT_32BITINODES;
mp->m_sb = *sb;
sbp = &(mp->m_sb);
manage_zones(0);
#define TRACE_ALLOC(s,a) ((void) 0)
#define TRACE_MODAGF(a,b,c) ((void) 0)
#define XFS_FORCED_SHUTDOWN(mp) 0
-#define XFS_MOUNT_WSYNC 0
-#define XFS_MOUNT_NOALIGN 0
+#define XFS_MOUNT_WSYNC 0 /* ignored in userspace */
+#define XFS_MOUNT_NOALIGN 0 /* ignored in userspace */
+#define XFS_MOUNT_32BITINODES 0x1 /* enforce in userspace */
#define XFS_ILOCK_EXCL 0
#define mrlock(a,b,c) ((void) 0)
#define mraccunlock(a) ((void) 0)
}
} else
agbp = NULL;
+
+ /* If this is a metadata prefered pag and we are user data
+ * then try somewhere else if we are not being asked to
+ * try harder at this point
+ */
+ if (pag->pagf_metadata && args->userdata && flags) {
+ args->agbp = NULL;
+ return 0;
+ }
+
need = XFS_MIN_FREELIST_PAG(pag, mp);
delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
/*
xfs_mount_t *mp; /* mount structure pointer */
xfs_agnumber_t sagno; /* starting allocation group number */
xfs_alloctype_t type; /* input allocation type */
+ int bump_rotor = 0;
mp = args->mp;
type = args->otype = args->type;
* 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, 0);
+ bump_rotor = 1;
+ }
args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
args->type = XFS_ALLOCTYPE_NEAR_BNO;
/* FALLTHROUGH */
}
}
}
- mp->m_agfrotor = (args->agno + 1) % mp->m_sb.sb_agcount;
+ if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG))
+ mp->m_agfrotor = (args->agno + 1) % mp->m_sb.sb_agcount;
break;
default:
ASSERT(0);
bma.prevp = &prev;
bma.gotp = &got;
bma.total = total;
- bma.userdata = userdata;
+ bma.userdata = 0;
+ }
+ /* Indicate if this is the first user data
+ * in the file, or just any user data.
+ */
+ if (userdata) {
+ bma.userdata = (aoff == 0) ?
+ XFS_ALLOC_INITIAL_USER_DATA :
+ XFS_ALLOC_USERDATA;
}
/*
* Fill in changeable bma fields.
*/
needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
mp = tp->t_mountp;
- agcount = mp->m_sb.sb_agcount;
+ agcount = mp->m_maxagi;
if (S_ISDIR(mode))
pagno = atomicIncWithWrap((int *)&mp->m_agirotor, agcount);
else
}
} else
agbp = NULL;
+
+ if (!pag->pagi_inodeok) {
+ atomicIncWithWrap((int *)&mp->m_agirotor, agcount);
+ goto unlock_nextag;
+ }
+
/*
* Is there enough free space for the file plus a block
* of inodes (if we need to allocate some)?
return agbp;
}
}
+unlock_nextag:
mraccunlock(&mp->m_peraglock);
if (agbp)
xfs_trans_brelse(tp, agbp);
return noroom ? ENOSPC : 0;
}
mraccess(&mp->m_peraglock);
+ if (mp->m_perag[tagno].pagi_inodeok == 0) {
+ mraccunlock(&mp->m_peraglock);
+ goto nextag;
+ }
error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp);
mraccunlock(&mp->m_peraglock);
if (error)
int i;
mp->m_agfrotor = mp->m_agirotor = 0;
+ mp->m_maxagi = mp->m_sb.sb_agcount;
mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;