From: Darrick J. Wong <djwong@xxxxxxxxxx> Use the file write helper to write files into the filesystem. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- include/libxfs.h | 2 ++ libxfs/util.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/proto.c | 26 ++++---------------- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/include/libxfs.h b/include/libxfs.h index d4985a5769f..0949bbd39a5 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -169,6 +169,8 @@ extern int libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t, extern int libxfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len, int alloc_type); +extern int libxfs_file_write(struct xfs_trans *tp, struct xfs_inode *ip, + void *buf, size_t len, bool logit); /* XXX: this is messy and needs fixing */ #ifndef __LIBXFS_INTERNAL_XFS_H__ diff --git a/libxfs/util.c b/libxfs/util.c index bb6867c21af..5643da72570 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -534,3 +534,72 @@ libxfs_imeta_ensure_dirpath( return error == -EEXIST ? 0 : error; } + +/* + * Write a buffer to a file on the data device. We assume there are no holes + * and no unwritten extents. + */ +int +libxfs_file_write( + struct xfs_trans *tp, + struct xfs_inode *ip, + void *buf, + size_t len, + bool logit) +{ + struct xfs_bmbt_irec map; + struct xfs_mount *mp = ip->i_mount; + struct xfs_buf *bp; + xfs_fileoff_t bno = 0; + xfs_fileoff_t end_bno = XFS_B_TO_FSB(mp, len); + size_t count; + size_t bcount; + int nmap; + int error = 0; + + /* Write up to 1MB at a time. */ + while (bno < end_bno) { + xfs_filblks_t maplen; + + maplen = min(end_bno - bno, XFS_B_TO_FSBT(mp, 1048576)); + nmap = 1; + error = libxfs_bmapi_read(ip, bno, maplen, &map, &nmap, 0); + if (error) + return error; + if (nmap != 1) + return -ENOSPC; + + if (map.br_startblock == HOLESTARTBLOCK || + map.br_state == XFS_EXT_UNWRITTEN) + return -EINVAL; + + error = libxfs_trans_get_buf(tp, mp->m_dev, + XFS_FSB_TO_DADDR(mp, map.br_startblock), + XFS_FSB_TO_BB(mp, map.br_blockcount), + 0, &bp); + if (error) + break; + bp->b_ops = NULL; + + count = min(len, XFS_FSB_TO_B(mp, map.br_blockcount)); + memmove(bp->b_addr, buf, count); + bcount = BBTOB(bp->b_length); + if (count < bcount) + memset((char *)bp->b_addr + count, 0, bcount - count); + + if (tp) { + libxfs_trans_log_buf(tp, bp, 0, bcount - 1); + } else { + libxfs_buf_mark_dirty(bp); + libxfs_buf_relse(bp); + } + if (error) + break; + + buf += count; + len -= count; + bno += map.br_blockcount; + } + + return error; +} diff --git a/mkfs/proto.c b/mkfs/proto.c index c62918a2f7d..96eab25da45 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -244,16 +244,12 @@ writefile( { struct xfs_bmbt_irec map; struct xfs_mount *mp; - struct xfs_buf *bp; - xfs_daddr_t d; xfs_extlen_t nb; int nmap; int error; mp = ip->i_mount; if (len > 0) { - int bcount; - nb = XFS_B_TO_FSB(mp, len); nmap = 1; error = -libxfs_bmapi_write(tp, ip, 0, nb, 0, nb, &map, &nmap); @@ -263,30 +259,18 @@ writefile( progname); exit(1); } - if (error) { + if (error) fail(_("error allocating space for a file"), error); - } if (nmap != 1) { fprintf(stderr, _("%s: cannot allocate space for file\n"), progname); exit(1); } - d = XFS_FSB_TO_DADDR(mp, map.br_startblock); - error = -libxfs_trans_get_buf(NULL, mp->m_dev, d, - nb << mp->m_blkbb_log, 0, &bp); - if (error) { - fprintf(stderr, - _("%s: cannot allocate buffer for file\n"), - progname); - exit(1); - } - memmove(bp->b_addr, buf, len); - bcount = BBTOB(bp->b_length); - if (len < bcount) - memset((char *)bp->b_addr + len, 0, bcount - len); - libxfs_buf_mark_dirty(bp); - libxfs_buf_relse(bp); + + error = -libxfs_file_write(tp, ip, buf, len, false); + if (error) + fail(_("error writing file"), error); } ip->i_disk_size = len; }