| /* |
| * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it would be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "libxfs_priv.h" |
| #include "xfs_fs.h" |
| #include "xfs_shared.h" |
| #include "xfs_format.h" |
| #include "xfs_log_format.h" |
| #include "xfs_trans_resv.h" |
| #include "xfs_mount.h" |
| #include "xfs_inode_buf.h" |
| #include "xfs_inode_fork.h" |
| #include "xfs_inode.h" |
| #include "xfs_trans.h" |
| |
| kmem_zone_t *xfs_buf_item_zone; |
| kmem_zone_t *xfs_ili_zone; /* inode log item zone */ |
| |
| /* |
| * Following functions from fs/xfs/xfs_trans_buf.c |
| */ |
| |
| /* |
| * Check to see if a buffer matching the given parameters is already |
| * a part of the given transaction. |
| */ |
| xfs_buf_t * |
| xfs_trans_buf_item_match( |
| xfs_trans_t *tp, |
| struct xfs_buftarg *btp, |
| struct xfs_buf_map *map, |
| int nmaps) |
| { |
| struct xfs_log_item_desc *lidp; |
| struct xfs_buf_log_item *blip; |
| int len = 0; |
| int i; |
| |
| for (i = 0; i < nmaps; i++) |
| len += map[i].bm_len; |
| |
| list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
| blip = (struct xfs_buf_log_item *)lidp->lid_item; |
| if (blip->bli_item.li_type == XFS_LI_BUF && |
| blip->bli_buf->b_target->dev == btp->dev && |
| XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && |
| blip->bli_buf->b_bcount == BBTOB(len)) { |
| ASSERT(blip->bli_buf->b_map_count == nmaps); |
| return blip->bli_buf; |
| } |
| } |
| |
| return NULL; |
| } |
| /* |
| * The following are from fs/xfs/xfs_buf_item.c |
| */ |
| |
| /* |
| * Allocate a new buf log item to go with the given buffer. |
| * Set the buffer's b_fsprivate field to point to the new |
| * buf log item. If there are other item's attached to the |
| * buffer (see xfs_buf_attach_iodone() below), then put the |
| * buf log item at the front. |
| */ |
| void |
| xfs_buf_item_init( |
| xfs_buf_t *bp, |
| xfs_mount_t *mp) |
| { |
| xfs_log_item_t *lip; |
| xfs_buf_log_item_t *bip; |
| |
| #ifdef LI_DEBUG |
| fprintf(stderr, "buf_item_init for buffer %p\n", bp); |
| #endif |
| |
| /* |
| * Check to see if there is already a buf log item for |
| * this buffer. If there is, it is guaranteed to be |
| * the first. If we do already have one, there is |
| * nothing to do here so return. |
| */ |
| if (XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *) != mp) |
| XFS_BUF_SET_FSPRIVATE3(bp, mp); |
| XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb); |
| if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) { |
| lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); |
| if (lip->li_type == XFS_LI_BUF) { |
| #ifdef LI_DEBUG |
| fprintf(stderr, |
| "reused buf item %p for pre-logged buffer %p\n", |
| lip, bp); |
| #endif |
| return; |
| } |
| } |
| |
| bip = (xfs_buf_log_item_t *)kmem_zone_zalloc(xfs_buf_item_zone, |
| KM_SLEEP); |
| #ifdef LI_DEBUG |
| fprintf(stderr, "adding buf item %p for not-logged buffer %p\n", |
| bip, bp); |
| #endif |
| bip->bli_item.li_type = XFS_LI_BUF; |
| bip->bli_item.li_mountp = mp; |
| bip->bli_buf = bp; |
| bip->bli_format.blf_type = XFS_LI_BUF; |
| bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); |
| bip->bli_format.blf_len = (unsigned short)BTOBB(XFS_BUF_COUNT(bp)); |
| XFS_BUF_SET_FSPRIVATE(bp, bip); |
| } |
| |
| |
| /* |
| * Mark bytes first through last inclusive as dirty in the buf |
| * item's bitmap. |
| */ |
| void |
| xfs_buf_item_log( |
| xfs_buf_log_item_t *bip, |
| uint first, |
| uint last) |
| { |
| /* |
| * Mark the item as having some dirty data for |
| * quick reference in xfs_buf_item_dirty. |
| */ |
| bip->bli_flags |= XFS_BLI_DIRTY; |
| } |
| |
| /* |
| * Initialize the inode log item for a newly allocated (in-core) inode. |
| */ |
| void |
| xfs_inode_item_init( |
| xfs_inode_t *ip, |
| xfs_mount_t *mp) |
| { |
| xfs_inode_log_item_t *iip; |
| |
| ASSERT(ip->i_itemp == NULL); |
| iip = ip->i_itemp = (xfs_inode_log_item_t *) |
| kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); |
| #ifdef LI_DEBUG |
| fprintf(stderr, "inode_item_init for inode %llu, iip=%p\n", |
| ip->i_ino, iip); |
| #endif |
| |
| iip->ili_item.li_type = XFS_LI_INODE; |
| iip->ili_item.li_mountp = mp; |
| iip->ili_inode = ip; |
| iip->ili_format.ilf_type = XFS_LI_INODE; |
| iip->ili_format.ilf_ino = ip->i_ino; |
| iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; |
| iip->ili_format.ilf_len = ip->i_imap.im_len; |
| iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; |
| } |