]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxfs/logitem.c
2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
35 xfs_zone_t
*xfs_buf_item_zone
;
36 xfs_zone_t
*xfs_ili_zone
; /* inode log item zone */
40 * This is called to add the given log item to the transaction's
41 * list of log items. It must find a free log item descriptor
42 * or allocate a new one and add the item to that descriptor.
43 * The function returns a pointer to item descriptor used to point
44 * to the new item. The log item will now point to its new descriptor
45 * with its li_desc field.
48 xfs_trans_add_item(xfs_trans_t
*tp
, xfs_log_item_t
*lip
)
50 xfs_log_item_desc_t
*lidp
;
51 xfs_log_item_chunk_t
*licp
;
55 * If there are no free descriptors, allocate a new chunk
56 * of them and put it at the front of the chunk list.
58 if (tp
->t_items_free
== 0) {
59 licp
= (xfs_log_item_chunk_t
*)
60 kmem_alloc(sizeof(xfs_log_item_chunk_t
), KM_SLEEP
);
63 * Initialize the chunk, and then
64 * claim the first slot in the newly allocated chunk.
67 XFS_LIC_CLAIM(licp
, 0);
69 XFS_LIC_INIT_SLOT(licp
, 0);
70 lidp
= XFS_LIC_SLOT(licp
, 0);
73 * Link in the new chunk and update the free count.
75 licp
->lic_next
= tp
->t_items
.lic_next
;
76 tp
->t_items
.lic_next
= licp
;
77 tp
->t_items_free
= XFS_LIC_NUM_SLOTS
- 1;
80 * Initialize the descriptor and the generic portion
83 * Point the new slot at this item and return it.
84 * Also point the log item at its currently active
85 * descriptor and set the item's mount pointer.
91 lip
->li_mountp
= tp
->t_mountp
;
96 * Find the free descriptor. It is somewhere in the chunklist
100 while (licp
!= NULL
) {
101 if (XFS_LIC_VACANCY(licp
)) {
102 if (licp
->lic_unused
<= XFS_LIC_MAX_SLOT
) {
103 i
= licp
->lic_unused
;
104 ASSERT(XFS_LIC_ISFREE(licp
, i
));
107 for (i
= 0; i
<= XFS_LIC_MAX_SLOT
; i
++) {
108 if (XFS_LIC_ISFREE(licp
, i
))
111 ASSERT(i
<= XFS_LIC_MAX_SLOT
);
114 licp
= licp
->lic_next
;
116 ASSERT(licp
!= NULL
);
118 * If we find a free descriptor, claim it,
119 * initialize it, and return it.
121 XFS_LIC_CLAIM(licp
, i
);
122 if (licp
->lic_unused
<= i
) {
123 licp
->lic_unused
= i
+ 1;
124 XFS_LIC_INIT_SLOT(licp
, i
);
126 lidp
= XFS_LIC_SLOT(licp
, i
);
128 lidp
->lid_item
= lip
;
132 lip
->li_mountp
= tp
->t_mountp
;
137 * Free the given descriptor.
139 * This requires setting the bit in the chunk's free mask corresponding
143 xfs_trans_free_item(xfs_trans_t
*tp
, xfs_log_item_desc_t
*lidp
)
146 xfs_log_item_chunk_t
*licp
;
147 xfs_log_item_chunk_t
**licpp
;
149 slot
= XFS_LIC_DESC_TO_SLOT(lidp
);
150 licp
= XFS_LIC_DESC_TO_CHUNK(lidp
);
151 XFS_LIC_RELSE(licp
, slot
);
152 lidp
->lid_item
->li_desc
= NULL
;
156 * If there are no more used items in the chunk and this is not
157 * the chunk embedded in the transaction structure, then free
158 * the chunk. First pull it from the chunk list and then
159 * free it back to the heap. We didn't bother with a doubly
160 * linked list here because the lists should be very short
161 * and this is not a performance path. It's better to save
162 * the memory of the extra pointer.
164 * Also decrement the transaction structure's count of free items
165 * by the number in a chunk since we are freeing an empty chunk.
167 if (XFS_LIC_ARE_ALL_FREE(licp
) && (licp
!= &(tp
->t_items
))) {
168 licpp
= &(tp
->t_items
.lic_next
);
169 while (*licpp
!= licp
) {
170 ASSERT(*licpp
!= NULL
);
171 licpp
= &((*licpp
)->lic_next
);
173 *licpp
= licp
->lic_next
;
174 kmem_free(licp
, sizeof(xfs_log_item_chunk_t
));
175 tp
->t_items_free
-= XFS_LIC_NUM_SLOTS
;
180 * This is called to find the descriptor corresponding to the given
181 * log item. It returns a pointer to the descriptor.
182 * The log item MUST have a corresponding descriptor in the given
183 * transaction. This routine does not return NULL, it panics.
185 * The descriptor pointer is kept in the log item's li_desc field.
188 xfs_log_item_desc_t
*
189 xfs_trans_find_item(xfs_trans_t
*tp
, xfs_log_item_t
*lip
)
191 ASSERT(lip
->li_desc
!= NULL
);
193 return (lip
->li_desc
);
197 * This is called to unlock all of the items of a transaction and to free
198 * all the descriptors of that transaction.
200 * It walks the list of descriptors and unlocks each item. It frees
201 * each chunk except that embedded in the transaction as it goes along.
204 xfs_trans_free_items(
208 xfs_log_item_chunk_t
*licp
;
209 xfs_log_item_chunk_t
*next_licp
;
212 abort
= flags
& XFS_TRANS_ABORT
;
215 * Special case the embedded chunk so we don't free it below.
217 if (!XFS_LIC_ARE_ALL_FREE(licp
)) {
218 (void) xfs_trans_unlock_chunk(licp
, 1, abort
, NULLCOMMITLSN
);
219 XFS_LIC_ALL_FREE(licp
);
220 licp
->lic_unused
= 0;
222 licp
= licp
->lic_next
;
225 * Unlock each item in each chunk and free the chunks.
227 while (licp
!= NULL
) {
228 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp
));
229 (void) xfs_trans_unlock_chunk(licp
, 1, abort
, NULLCOMMITLSN
);
230 next_licp
= licp
->lic_next
;
231 kmem_free(licp
, sizeof(xfs_log_item_chunk_t
));
236 * Reset the transaction structure's free item count.
238 tp
->t_items_free
= XFS_LIC_NUM_SLOTS
;
239 tp
->t_items
.lic_next
= NULL
;
243 * Check to see if a buffer matching the given parameters is already
244 * a part of the given transaction. Only check the first, embedded
245 * chunk, since we don't want to spend all day scanning large transactions.
248 xfs_trans_buf_item_match(
254 xfs_log_item_chunk_t
*licp
;
255 xfs_log_item_desc_t
*lidp
;
256 xfs_buf_log_item_t
*blip
;
261 fprintf(stderr
, "buf_item_match (fast) log items for xact %p\n", tp
);
267 if (!XFS_LIC_ARE_ALL_FREE(licp
)) {
268 for (i
= 0; i
< licp
->lic_unused
; i
++) {
270 * Skip unoccupied slots.
272 if (XFS_LIC_ISFREE(licp
, i
)) {
276 lidp
= XFS_LIC_SLOT(licp
, i
);
277 blip
= (xfs_buf_log_item_t
*)lidp
->lid_item
;
280 "\tfound log item, xact %p, blip=%p (%d/%d)\n",
281 tp
, blip
, i
, licp
->lic_unused
);
283 if (blip
->bli_item
.li_type
!= XFS_LI_BUF
) {
290 "\tfound buf %p log item, xact %p, blip=%p (%d)\n",
293 if ((XFS_BUF_TARGET(bp
) == target
->dev
) &&
294 (XFS_BUF_ADDR(bp
) == blkno
) &&
295 (XFS_BUF_COUNT(bp
) == len
)) {
297 * We found it. Break out and
298 * return the pointer to the buffer.
302 "\tfound REAL buf log item, bp=%p\n",
312 if (!bp
) fprintf(stderr
, "\tfast search - got nothing\n");
318 * Check to see if a buffer matching the given parameters is already
319 * a part of the given transaction. Check all the chunks, we
320 * want to be thorough.
323 xfs_trans_buf_item_match_all(
329 xfs_log_item_chunk_t
*licp
;
330 xfs_log_item_desc_t
*lidp
;
331 xfs_buf_log_item_t
*blip
;
336 fprintf(stderr
, "buf_item_match_all (slow) log items for xact %p\n",
342 for (licp
= &tp
->t_items
; licp
!= NULL
; licp
= licp
->lic_next
) {
343 if (XFS_LIC_ARE_ALL_FREE(licp
)) {
344 ASSERT(licp
== &tp
->t_items
);
345 ASSERT(licp
->lic_next
== NULL
);
348 for (i
= 0; i
< licp
->lic_unused
; i
++) {
350 * Skip unoccupied slots.
352 if (XFS_LIC_ISFREE(licp
, i
)) {
356 lidp
= XFS_LIC_SLOT(licp
, i
);
357 blip
= (xfs_buf_log_item_t
*)lidp
->lid_item
;
360 "\tfound log item, xact %p, blip=%p (%d/%d)\n",
361 tp
, blip
, i
, licp
->lic_unused
);
363 if (blip
->bli_item
.li_type
!= XFS_LI_BUF
) {
369 ASSERT(XFS_BUF_ADDR(bp
));
372 "\tfound buf %p log item, xact %p, blip=%p (%d)\n",
375 if ((XFS_BUF_TARGET(bp
) == target
->dev
) &&
376 (XFS_BUF_ADDR(bp
) == blkno
) &&
377 (XFS_BUF_COUNT(bp
) == len
)) {
379 * We found it. Break out and
380 * return the pointer to the buffer.
384 "\tfound REAL buf log item, bp=%p\n",
392 if (!bp
) fprintf(stderr
, "slow search - got nothing\n");
398 * Allocate a new buf log item to go with the given buffer.
399 * Set the buffer's b_fsprivate field to point to the new
400 * buf log item. If there are other item's attached to the
401 * buffer (see xfs_buf_attach_iodone() below), then put the
402 * buf log item at the front.
410 xfs_buf_log_item_t
*bip
;
413 fprintf(stderr
, "buf_item_init for buffer %p\n", bp
);
417 * Check to see if there is already a buf log item for
418 * this buffer. If there is, it is guaranteed to be
419 * the first. If we do already have one, there is
420 * nothing to do here so return.
422 if (XFS_BUF_FSPRIVATE3(bp
, xfs_mount_t
*) != mp
)
423 XFS_BUF_SET_FSPRIVATE3(bp
, mp
);
424 XFS_BUF_SET_BDSTRAT_FUNC(bp
, xfs_bdstrat_cb
);
425 if (XFS_BUF_FSPRIVATE(bp
, void *) != NULL
) {
426 lip
= XFS_BUF_FSPRIVATE(bp
, xfs_log_item_t
*);
427 if (lip
->li_type
== XFS_LI_BUF
) {
430 "reused buf item %p for pre-logged buffer %p\n",
437 bip
= (xfs_buf_log_item_t
*)kmem_zone_zalloc(xfs_buf_item_zone
,
440 fprintf(stderr
, "adding buf item %p for not-logged buffer %p\n",
443 bip
->bli_item
.li_type
= XFS_LI_BUF
;
444 bip
->bli_item
.li_mountp
= mp
;
446 bip
->bli_format
.blf_type
= XFS_LI_BUF
;
447 bip
->bli_format
.blf_blkno
= (__int64_t
)XFS_BUF_ADDR(bp
);
448 bip
->bli_format
.blf_len
= (ushort
)BTOBB(XFS_BUF_COUNT(bp
));
449 XFS_BUF_SET_FSPRIVATE(bp
, bip
);
454 * Mark bytes first through last inclusive as dirty in the buf
459 xfs_buf_log_item_t
*bip
,
464 * Mark the item as having some dirty data for
465 * quick reference in xfs_buf_item_dirty.
467 bip
->bli_flags
|= XFS_BLI_DIRTY
;
471 * Initialize the inode log item for a newly allocated (in-core) inode.
478 xfs_inode_log_item_t
*iip
;
480 ASSERT(ip
->i_itemp
== NULL
);
481 iip
= ip
->i_itemp
= (xfs_inode_log_item_t
*)
482 kmem_zone_zalloc(xfs_ili_zone
, KM_SLEEP
);
484 fprintf(stderr
, "inode_item_init for inode %llu, iip=%p\n",
488 iip
->ili_item
.li_type
= XFS_LI_INODE
;
489 iip
->ili_item
.li_mountp
= mp
;
491 iip
->ili_format
.ilf_type
= XFS_LI_INODE
;
492 iip
->ili_format
.ilf_ino
= ip
->i_ino
;
493 iip
->ili_format
.ilf_blkno
= ip
->i_blkno
;
494 iip
->ili_format
.ilf_len
= ip
->i_len
;
495 iip
->ili_format
.ilf_boffset
= ip
->i_boffset
;