@@ -71,18 +71,24 @@ xfs_zero_extent(
7171#ifdef CONFIG_XFS_RT
7272int
7373xfs_bmap_rtalloc (
74- struct xfs_bmalloca * ap ) /* bmap alloc argument struct */
74+ struct xfs_bmalloca * ap )
7575{
76- int error ; /* error return value */
77- xfs_mount_t * mp ; /* mount point structure */
78- xfs_extlen_t prod = 0 ; /* product factor for allocators */
79- xfs_extlen_t mod = 0 ; /* product factor for allocators */
80- xfs_extlen_t ralen = 0 ; /* realtime allocation length */
81- xfs_extlen_t align ; /* minimum allocation alignment */
82- xfs_rtblock_t rtb ;
83-
84- mp = ap -> ip -> i_mount ;
76+ struct xfs_mount * mp = ap -> ip -> i_mount ;
77+ xfs_fileoff_t orig_offset = ap -> offset ;
78+ xfs_rtblock_t rtb ;
79+ xfs_extlen_t prod = 0 ; /* product factor for allocators */
80+ xfs_extlen_t mod = 0 ; /* product factor for allocators */
81+ xfs_extlen_t ralen = 0 ; /* realtime allocation length */
82+ xfs_extlen_t align ; /* minimum allocation alignment */
83+ xfs_extlen_t orig_length = ap -> length ;
84+ xfs_extlen_t minlen = mp -> m_sb .sb_rextsize ;
85+ xfs_extlen_t raminlen ;
86+ bool rtlocked = false;
87+ bool ignore_locality = false;
88+ int error ;
89+
8590 align = xfs_get_extsz_hint (ap -> ip );
91+ retry :
8692 prod = align / mp -> m_sb .sb_rextsize ;
8793 error = xfs_bmap_extsize_align (mp , & ap -> got , & ap -> prev ,
8894 align , 1 , ap -> eof , 0 ,
@@ -92,6 +98,15 @@ xfs_bmap_rtalloc(
9298 ASSERT (ap -> length );
9399 ASSERT (ap -> length % mp -> m_sb .sb_rextsize == 0 );
94100
101+ /*
102+ * If we shifted the file offset downward to satisfy an extent size
103+ * hint, increase minlen by that amount so that the allocator won't
104+ * give us an allocation that's too short to cover at least one of the
105+ * blocks that the caller asked for.
106+ */
107+ if (ap -> offset != orig_offset )
108+ minlen += orig_offset - ap -> offset ;
109+
95110 /*
96111 * If the offset & length are not perfectly aligned
97112 * then kill prod, it will just get us in trouble.
@@ -116,10 +131,13 @@ xfs_bmap_rtalloc(
116131 /*
117132 * Lock out modifications to both the RT bitmap and summary inodes
118133 */
119- xfs_ilock (mp -> m_rbmip , XFS_ILOCK_EXCL |XFS_ILOCK_RTBITMAP );
120- xfs_trans_ijoin (ap -> tp , mp -> m_rbmip , XFS_ILOCK_EXCL );
121- xfs_ilock (mp -> m_rsumip , XFS_ILOCK_EXCL |XFS_ILOCK_RTSUM );
122- xfs_trans_ijoin (ap -> tp , mp -> m_rsumip , XFS_ILOCK_EXCL );
134+ if (!rtlocked ) {
135+ xfs_ilock (mp -> m_rbmip , XFS_ILOCK_EXCL |XFS_ILOCK_RTBITMAP );
136+ xfs_trans_ijoin (ap -> tp , mp -> m_rbmip , XFS_ILOCK_EXCL );
137+ xfs_ilock (mp -> m_rsumip , XFS_ILOCK_EXCL |XFS_ILOCK_RTSUM );
138+ xfs_trans_ijoin (ap -> tp , mp -> m_rsumip , XFS_ILOCK_EXCL );
139+ rtlocked = true;
140+ }
123141
124142 /*
125143 * If it's an allocation to an empty file at offset 0,
@@ -141,33 +159,59 @@ xfs_bmap_rtalloc(
141159 /*
142160 * Realtime allocation, done through xfs_rtallocate_extent.
143161 */
144- do_div (ap -> blkno , mp -> m_sb .sb_rextsize );
162+ if (ignore_locality )
163+ ap -> blkno = 0 ;
164+ else
165+ do_div (ap -> blkno , mp -> m_sb .sb_rextsize );
145166 rtb = ap -> blkno ;
146167 ap -> length = ralen ;
147- error = xfs_rtallocate_extent (ap -> tp , ap -> blkno , 1 , ap -> length ,
148- & ralen , ap -> wasdel , prod , & rtb );
168+ raminlen = max_t (xfs_extlen_t , 1 , minlen / mp -> m_sb .sb_rextsize );
169+ error = xfs_rtallocate_extent (ap -> tp , ap -> blkno , raminlen , ap -> length ,
170+ & ralen , ap -> wasdel , prod , & rtb );
149171 if (error )
150172 return error ;
151173
152- ap -> blkno = rtb ;
153- if (ap -> blkno != NULLFSBLOCK ) {
154- ap -> blkno *= mp -> m_sb .sb_rextsize ;
155- ralen *= mp -> m_sb .sb_rextsize ;
156- ap -> length = ralen ;
157- ap -> ip -> i_nblocks += ralen ;
174+ if (rtb != NULLRTBLOCK ) {
175+ ap -> blkno = rtb * mp -> m_sb .sb_rextsize ;
176+ ap -> length = ralen * mp -> m_sb .sb_rextsize ;
177+ ap -> ip -> i_nblocks += ap -> length ;
158178 xfs_trans_log_inode (ap -> tp , ap -> ip , XFS_ILOG_CORE );
159179 if (ap -> wasdel )
160- ap -> ip -> i_delayed_blks -= ralen ;
180+ ap -> ip -> i_delayed_blks -= ap -> length ;
161181 /*
162182 * Adjust the disk quota also. This was reserved
163183 * earlier.
164184 */
165185 xfs_trans_mod_dquot_byino (ap -> tp , ap -> ip ,
166186 ap -> wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
167- XFS_TRANS_DQ_RTBCOUNT , (long ) ralen );
168- } else {
169- ap -> length = 0 ;
187+ XFS_TRANS_DQ_RTBCOUNT , ap -> length );
188+ return 0 ;
170189 }
190+
191+ if (align > mp -> m_sb .sb_rextsize ) {
192+ /*
193+ * We previously enlarged the request length to try to satisfy
194+ * an extent size hint. The allocator didn't return anything,
195+ * so reset the parameters to the original values and try again
196+ * without alignment criteria.
197+ */
198+ ap -> offset = orig_offset ;
199+ ap -> length = orig_length ;
200+ minlen = align = mp -> m_sb .sb_rextsize ;
201+ goto retry ;
202+ }
203+
204+ if (!ignore_locality && ap -> blkno != 0 ) {
205+ /*
206+ * If we can't allocate near a specific rt extent, try again
207+ * without locality criteria.
208+ */
209+ ignore_locality = true;
210+ goto retry ;
211+ }
212+
213+ ap -> blkno = NULLFSBLOCK ;
214+ ap -> length = 0 ;
171215 return 0 ;
172216}
173217#endif /* CONFIG_XFS_RT */
0 commit comments