]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs: move symlink target write function to libxfs
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 17:01:14 +0000 (10:01 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 3 Jun 2024 18:37:41 +0000 (11:37 -0700)
Source kernel commit: b8102b61f7b8929ad8043e4574a1e26276398041

Move xfs_symlink_write_target to xfs_symlink_remote.c so that kernel and
mkfs can share the same function.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
libxfs/xfs_symlink_remote.c
libxfs/xfs_symlink_remote.h

index f2e591ea9c9ca584cada4c3e940085f8e5dded32..875e03bcbc9048934cbca56bafaf4369da25cae5 100644 (file)
@@ -18,7 +18,6 @@
 #include "xfs_bmap.h"
 #include "xfs_health.h"
 
-
 /*
  * Each contiguous block has a header, so it is not just a simple pathlen
  * to FSB conversion.
@@ -302,3 +301,79 @@ xfs_symlink_remote_read(
  out:
        return error;
 }
+
+/* Write the symlink target into the inode. */
+int
+xfs_symlink_write_target(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       const char              *target_path,
+       int                     pathlen,
+       xfs_fsblock_t           fs_blocks,
+       uint                    resblks)
+{
+       struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
+       struct xfs_mount        *mp = tp->t_mountp;
+       const char              *cur_chunk;
+       struct xfs_buf          *bp;
+       xfs_daddr_t             d;
+       int                     byte_cnt;
+       int                     nmaps;
+       int                     offset = 0;
+       int                     n;
+       int                     error;
+
+       /*
+        * If the symlink will fit into the inode, write it inline.
+        */
+       if (pathlen <= xfs_inode_data_fork_size(ip)) {
+               xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
+
+               ip->i_disk_size = pathlen;
+               ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
+               xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
+               return 0;
+       }
+
+       nmaps = XFS_SYMLINK_MAPS;
+       error = xfs_bmapi_write(tp, ip, 0, fs_blocks, XFS_BMAPI_METADATA,
+                       resblks, mval, &nmaps);
+       if (error)
+               return error;
+
+       ip->i_disk_size = pathlen;
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+       cur_chunk = target_path;
+       offset = 0;
+       for (n = 0; n < nmaps; n++) {
+               char    *buf;
+
+               d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
+               byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
+               error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
+                               BTOBB(byte_cnt), 0, &bp);
+               if (error)
+                       return error;
+               bp->b_ops = &xfs_symlink_buf_ops;
+
+               byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
+               byte_cnt = min(byte_cnt, pathlen);
+
+               buf = bp->b_addr;
+               buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, byte_cnt,
+                               bp);
+
+               memcpy(buf, cur_chunk, byte_cnt);
+
+               cur_chunk += byte_cnt;
+               pathlen -= byte_cnt;
+               offset += byte_cnt;
+
+               xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
+               xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
+                                               (char *)bp->b_addr);
+       }
+       ASSERT(pathlen == 0);
+       return 0;
+}
index bb83a8b8dfa66ddb3ed0b9a3a946f7dd51a32720..a63bd38ae4faf463876b2954c851cb2f1c0a3467 100644 (file)
@@ -19,5 +19,8 @@ void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
                                 struct xfs_inode *ip, struct xfs_ifork *ifp);
 xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
 int xfs_symlink_remote_read(struct xfs_inode *ip, char *link);
+int xfs_symlink_write_target(struct xfs_trans *tp, struct xfs_inode *ip,
+               const char *target_path, int pathlen, xfs_fsblock_t fs_blocks,
+               uint resblks);
 
 #endif /* __XFS_SYMLINK_REMOTE_H */