xfs_iomap.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,001 行 · 第 1/2 页
C
1,001 行
/* * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 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. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */#include "xfs.h"#include "xfs_fs.h"#include "xfs_inum.h"#include "xfs_log.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dir.h"#include "xfs_dir2.h"#include "xfs_alloc.h"#include "xfs_dmapi.h"#include "xfs_quota.h"#include "xfs_mount.h"#include "xfs_alloc_btree.h"#include "xfs_bmap_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_btree.h"#include "xfs_ialloc.h"#include "xfs_attr_sf.h"#include "xfs_dir_sf.h"#include "xfs_dir2_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_bmap.h"#include "xfs_bit.h"#include "xfs_rtalloc.h"#include "xfs_error.h"#include "xfs_itable.h"#include "xfs_rw.h"#include "xfs_acl.h"#include "xfs_cap.h"#include "xfs_mac.h"#include "xfs_attr.h"#include "xfs_buf_item.h"#include "xfs_trans_space.h"#include "xfs_utils.h"#include "xfs_iomap.h"#if defined(XFS_RW_TRACE)voidxfs_iomap_enter_trace( int tag, xfs_iocore_t *io, xfs_off_t offset, ssize_t count){ xfs_inode_t *ip = XFS_IO_INODE(io); if (!ip->i_rwtrace) return; ktrace_enter(ip->i_rwtrace, (void *)((unsigned long)tag), (void *)ip, (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)), (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)), (void *)((unsigned long)((offset >> 32) & 0xffffffff)), (void *)((unsigned long)(offset & 0xffffffff)), (void *)((unsigned long)count), (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)), (void *)((unsigned long)(io->io_new_size & 0xffffffff)), (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL);}voidxfs_iomap_map_trace( int tag, xfs_iocore_t *io, xfs_off_t offset, ssize_t count, xfs_iomap_t *iomapp, xfs_bmbt_irec_t *imapp, int flags){ xfs_inode_t *ip = XFS_IO_INODE(io); if (!ip->i_rwtrace) return; ktrace_enter(ip->i_rwtrace, (void *)((unsigned long)tag), (void *)ip, (void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)), (void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)), (void *)((unsigned long)((offset >> 32) & 0xffffffff)), (void *)((unsigned long)(offset & 0xffffffff)), (void *)((unsigned long)count), (void *)((unsigned long)flags), (void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)), (void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)), (void *)((unsigned long)(iomapp->iomap_delta)), (void *)((unsigned long)(iomapp->iomap_bsize)), (void *)((unsigned long)(iomapp->iomap_bn)), (void *)(__psint_t)(imapp->br_startoff), (void *)((unsigned long)(imapp->br_blockcount)), (void *)(__psint_t)(imapp->br_startblock));}#else#define xfs_iomap_enter_trace(tag, io, offset, count)#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)#endif#define XFS_WRITEIO_ALIGN(mp,off) (((off) >> mp->m_writeio_log) \ << mp->m_writeio_log)#define XFS_STRAT_WRITE_IMAPS 2#define XFS_WRITE_IMAPS XFS_BMAP_MAX_NMAPSTATIC intxfs_imap_to_bmap( xfs_iocore_t *io, xfs_off_t offset, xfs_bmbt_irec_t *imap, xfs_iomap_t *iomapp, int imaps, /* Number of imap entries */ int iomaps, /* Number of iomap entries */ int flags){ xfs_mount_t *mp; xfs_fsize_t nisize; int pbm; xfs_fsblock_t start_block; mp = io->io_mount; nisize = XFS_SIZE(mp, io); if (io->io_new_size > nisize) nisize = io->io_new_size; for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); iomapp->iomap_delta = offset - iomapp->iomap_offset; iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); iomapp->iomap_flags = flags; if (io->io_flags & XFS_IOCORE_RT) { iomapp->iomap_flags |= IOMAP_REALTIME; iomapp->iomap_target = mp->m_rtdev_targp; } else { iomapp->iomap_target = mp->m_ddev_targp; } start_block = imap->br_startblock; if (start_block == HOLESTARTBLOCK) { iomapp->iomap_bn = IOMAP_DADDR_NULL; iomapp->iomap_flags |= IOMAP_HOLE; } else if (start_block == DELAYSTARTBLOCK) { iomapp->iomap_bn = IOMAP_DADDR_NULL; iomapp->iomap_flags |= IOMAP_DELAY; } else { iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); if (ISUNWRITTEN(imap)) iomapp->iomap_flags |= IOMAP_UNWRITTEN; } if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) { iomapp->iomap_flags |= IOMAP_EOF; } offset += iomapp->iomap_bsize - iomapp->iomap_delta; } return pbm; /* Return the number filled */}intxfs_iomap( xfs_iocore_t *io, xfs_off_t offset, ssize_t count, int flags, xfs_iomap_t *iomapp, int *niomaps){ xfs_mount_t *mp = io->io_mount; xfs_fileoff_t offset_fsb, end_fsb; int error = 0; int lockmode = 0; xfs_bmbt_irec_t imap; int nimaps = 1; int bmapi_flags = 0; int iomap_flags = 0; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); switch (flags & (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | BMAPI_UNWRITTEN | BMAPI_DEVICE)) { case BMAPI_READ: xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count); lockmode = XFS_LCK_MAP_SHARED(mp, io); bmapi_flags = XFS_BMAPI_ENTIRE; if (flags & BMAPI_IGNSTATE) bmapi_flags |= XFS_BMAPI_IGSTATE; break; case BMAPI_WRITE: xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count); lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; bmapi_flags = 0; XFS_ILOCK(mp, io, lockmode); break; case BMAPI_ALLOCATE: xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count); lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; bmapi_flags = XFS_BMAPI_ENTIRE; /* Attempt non-blocking lock */ if (flags & BMAPI_TRYLOCK) { if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) return XFS_ERROR(EAGAIN); } else { XFS_ILOCK(mp, io, lockmode); } break; case BMAPI_UNWRITTEN: goto phase2; case BMAPI_DEVICE: lockmode = XFS_LCK_MAP_SHARED(mp, io); iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? mp->m_rtdev_targp : mp->m_ddev_targp; error = 0; *niomaps = 1; goto out; default: BUG(); } ASSERT(offset <= mp->m_maxioffset); if ((xfs_fsize_t)offset + count > mp->m_maxioffset) count = mp->m_maxioffset - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); offset_fsb = XFS_B_TO_FSBT(mp, offset); error = XFS_BMAPI(mp, NULL, io, offset_fsb, (xfs_filblks_t)(end_fsb - offset_fsb), bmapi_flags, NULL, 0, &imap, &nimaps, NULL); if (error) goto out;phase2: switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { case BMAPI_WRITE: /* If we found an extent, return it */ if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) { xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, offset, count, iomapp, &imap, flags); break; } if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, &imap, &nimaps, nimaps); } else { error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, &imap, &nimaps); } if (!error) { xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io, offset, count, iomapp, &imap, flags); } iomap_flags = IOMAP_NEW; break; case BMAPI_ALLOCATE: /* If we found an extent, return it */ XFS_IUNLOCK(mp, io, lockmode); lockmode = 0; if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) { xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, offset, count, iomapp, &imap, flags); break; } error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); break; case BMAPI_UNWRITTEN: lockmode = 0; error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); nimaps = 0; break; } if (nimaps) { *niomaps = xfs_imap_to_bmap(io, offset, &imap, iomapp, nimaps, *niomaps, iomap_flags); } else if (niomaps) { *niomaps = 0; }out: if (lockmode) XFS_IUNLOCK(mp, io, lockmode); return XFS_ERROR(error);}STATIC intxfs_flush_space( xfs_inode_t *ip, int *fsynced, int *ioflags){ switch (*fsynced) { case 0: if (ip->i_delayed_blks) { xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_flush_inode(ip); xfs_ilock(ip, XFS_ILOCK_EXCL); *fsynced = 1; } else { *ioflags |= BMAPI_SYNC; *fsynced = 2; } return 0; case 1: *fsynced = 2; *ioflags |= BMAPI_SYNC; return 0; case 2: xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_flush_device(ip); xfs_ilock(ip, XFS_ILOCK_EXCL); *fsynced = 3; return 0; } return 1;}intxfs_iomap_write_direct( xfs_inode_t *ip, loff_t offset, size_t count, int flags, xfs_bmbt_irec_t *ret_imap, int *nmaps, int found){ xfs_mount_t *mp = ip->i_mount; xfs_iocore_t *io = &ip->i_iocore; xfs_fileoff_t offset_fsb; xfs_fileoff_t last_fsb; xfs_filblks_t count_fsb; xfs_fsize_t isize; xfs_fsblock_t firstfsb; int nimaps, maps; int error; int bmapi_flag; int rt; xfs_trans_t *tp; xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; xfs_bmap_free_t free_list; int aeof; xfs_filblks_t datablocks; int committed; int numrtextents; uint resblks; /* * Make sure that the dquots are there. This doesn't hold * the ilock across a disk read. */ error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED); if (error) return XFS_ERROR(error); maps = min(XFS_WRITE_IMAPS, *nmaps); nimaps = maps; isize = ip->i_d.di_size; aeof = (offset + count) > isize; if (io->io_new_size > isize) isize = io->io_new_size; offset_fsb = XFS_B_TO_FSBT(mp, offset); last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); count_fsb = last_fsb - offset_fsb; if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { xfs_fileoff_t map_last_fsb; map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; if (map_last_fsb < last_fsb) { last_fsb = map_last_fsb; count_fsb = last_fsb - offset_fsb; } ASSERT(count_fsb > 0); } /* * determine if reserving space on * the data or realtime partition. */ if ((rt = XFS_IS_REALTIME_INODE(ip))) { int sbrtextsize, iprtextsize; sbrtextsize = mp->m_sb.sb_rextsize; iprtextsize = ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; numrtextents = (count_fsb + iprtextsize - 1); do_div(numrtextents, sbrtextsize); datablocks = 0; } else { datablocks = count_fsb; numrtextents = 0; } /* * allocate and setup the transaction */ xfs_iunlock(ip, XFS_ILOCK_EXCL); tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); error = xfs_trans_reserve(tp, resblks, XFS_WRITE_LOG_RES(mp), numrtextents, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); /* * check for running out of space */ if (error) /* * Free the transaction structure. */ xfs_trans_cancel(tp, 0); xfs_ilock(ip, XFS_ILOCK_EXCL); if (error) goto error_out; /* Don't return in above if .. trans .., need lock to return */ if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { error = (EDQUOT); goto error1; } nimaps = 1; bmapi_flag = XFS_BMAPI_WRITE; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) bmapi_flag |= XFS_BMAPI_PREALLOC; /* * issue the bmapi() call to allocate the blocks */ XFS_BMAP_INIT(&free_list, &firstfsb); imapp = &imap[0]; error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); if (error) { goto error0; } /* * complete the transaction */ error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?