Use the file write helper to write files into the filesystem.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
extern int libxfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
xfs_off_t len, uint32_t bmapi_flags);
+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__
return ret;
}
#endif
+
+/*
+ * 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;
+}
{
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);
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;
}