Skip to content

Commit c1f0bad

Browse files
author
Darrick J. Wong
committed
xfs: create libxfs helper to link an existing inode into a directory
Create a new libxfs function to link an existing inode into a directory. The upcoming metadata directory feature will need this to create a metadata directory tree. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 1fa2e81 commit c1f0bad

File tree

3 files changed

+81
-46
lines changed

3 files changed

+81
-46
lines changed

fs/xfs/libxfs/xfs_dir2.c

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "xfs_bmap_btree.h"
2323
#include "xfs_trans_space.h"
2424
#include "xfs_parent.h"
25+
#include "xfs_ag.h"
2526

2627
const struct xfs_name xfs_name_dotdot = {
2728
.name = (const unsigned char *)"..",
@@ -587,9 +588,9 @@ xfs_dir_replace(
587588
*/
588589
int
589590
xfs_dir_canenter(
590-
xfs_trans_t *tp,
591-
xfs_inode_t *dp,
592-
struct xfs_name *name) /* name of entry to add */
591+
struct xfs_trans *tp,
592+
struct xfs_inode *dp,
593+
const struct xfs_name *name) /* name of entry to add */
593594
{
594595
return xfs_dir_createname(tp, dp, name, 0, 0);
595596
}
@@ -809,3 +810,67 @@ xfs_dir_create_child(
809810

810811
return 0;
811812
}
813+
814+
/*
815+
* Given a directory @dp, an existing non-directory inode @ip, and a @name,
816+
* link @ip into @dp under the given @name. Both inodes must have the ILOCK
817+
* held.
818+
*/
819+
int
820+
xfs_dir_add_child(
821+
struct xfs_trans *tp,
822+
unsigned int resblks,
823+
struct xfs_dir_update *du)
824+
{
825+
struct xfs_inode *dp = du->dp;
826+
const struct xfs_name *name = du->name;
827+
struct xfs_inode *ip = du->ip;
828+
struct xfs_mount *mp = tp->t_mountp;
829+
int error;
830+
831+
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
832+
xfs_assert_ilocked(dp, XFS_ILOCK_EXCL);
833+
ASSERT(!S_ISDIR(VFS_I(ip)->i_mode));
834+
835+
if (!resblks) {
836+
error = xfs_dir_canenter(tp, dp, name);
837+
if (error)
838+
return error;
839+
}
840+
841+
/*
842+
* Handle initial link state of O_TMPFILE inode
843+
*/
844+
if (VFS_I(ip)->i_nlink == 0) {
845+
struct xfs_perag *pag;
846+
847+
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
848+
error = xfs_iunlink_remove(tp, pag, ip);
849+
xfs_perag_put(pag);
850+
if (error)
851+
return error;
852+
}
853+
854+
error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
855+
if (error)
856+
return error;
857+
858+
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
859+
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
860+
861+
xfs_bumplink(tp, ip);
862+
863+
/*
864+
* If we have parent pointers, we now need to add the parent record to
865+
* the attribute fork of the inode. If this is the initial parent
866+
* attribute, we need to create it correctly, otherwise we can just add
867+
* the parent to the inode.
868+
*/
869+
if (du->ppargs) {
870+
error = xfs_parent_addname(tp, du->ppargs, dp, name, ip);
871+
if (error)
872+
return error;
873+
}
874+
875+
return 0;
876+
}

fs/xfs/libxfs/xfs_dir2.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
7474
const struct xfs_name *name, xfs_ino_t inum,
7575
xfs_extlen_t tot);
7676
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
77-
struct xfs_name *name);
77+
const struct xfs_name *name);
7878

7979
int xfs_dir_lookup_args(struct xfs_da_args *args);
8080
int xfs_dir_createname_args(struct xfs_da_args *args);
@@ -320,5 +320,7 @@ struct xfs_dir_update {
320320

321321
int xfs_dir_create_child(struct xfs_trans *tp, unsigned int resblks,
322322
struct xfs_dir_update *du);
323+
int xfs_dir_add_child(struct xfs_trans *tp, unsigned int resblks,
324+
struct xfs_dir_update *du);
323325

324326
#endif /* __XFS_DIR2_H__ */

fs/xfs/xfs_inode.c

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,15 @@ xfs_link(
952952
struct xfs_inode *sip,
953953
struct xfs_name *target_name)
954954
{
955+
struct xfs_dir_update du = {
956+
.dp = tdp,
957+
.name = target_name,
958+
.ip = sip,
959+
};
955960
struct xfs_mount *mp = tdp->i_mount;
956961
struct xfs_trans *tp;
957962
int error, nospace_error = 0;
958963
int resblks;
959-
struct xfs_parent_args *ppargs;
960964

961965
trace_xfs_link(tdp, target_name);
962966

@@ -975,7 +979,7 @@ xfs_link(
975979
if (error)
976980
goto std_return;
977981

978-
error = xfs_parent_start(mp, &ppargs);
982+
error = xfs_parent_start(mp, &du.ppargs);
979983
if (error)
980984
goto std_return;
981985

@@ -990,7 +994,7 @@ xfs_link(
990994
* pointers are enabled because we can't back out if the xattrs must
991995
* grow.
992996
*/
993-
if (ppargs && nospace_error) {
997+
if (du.ppargs && nospace_error) {
994998
error = nospace_error;
995999
goto error_return;
9961000
}
@@ -1017,45 +1021,9 @@ xfs_link(
10171021
}
10181022
}
10191023

1020-
if (!resblks) {
1021-
error = xfs_dir_canenter(tp, tdp, target_name);
1022-
if (error)
1023-
goto error_return;
1024-
}
1025-
1026-
/*
1027-
* Handle initial link state of O_TMPFILE inode
1028-
*/
1029-
if (VFS_I(sip)->i_nlink == 0) {
1030-
struct xfs_perag *pag;
1031-
1032-
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sip->i_ino));
1033-
error = xfs_iunlink_remove(tp, pag, sip);
1034-
xfs_perag_put(pag);
1035-
if (error)
1036-
goto error_return;
1037-
}
1038-
1039-
error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
1040-
resblks);
1024+
error = xfs_dir_add_child(tp, resblks, &du);
10411025
if (error)
10421026
goto error_return;
1043-
xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1044-
xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
1045-
1046-
xfs_bumplink(tp, sip);
1047-
1048-
/*
1049-
* If we have parent pointers, we now need to add the parent record to
1050-
* the attribute fork of the inode. If this is the initial parent
1051-
* attribute, we need to create it correctly, otherwise we can just add
1052-
* the parent to the inode.
1053-
*/
1054-
if (ppargs) {
1055-
error = xfs_parent_addname(tp, ppargs, tdp, target_name, sip);
1056-
if (error)
1057-
goto error_return;
1058-
}
10591027

10601028
xfs_dir_update_hook(tdp, sip, 1, target_name);
10611029

@@ -1070,15 +1038,15 @@ xfs_link(
10701038
error = xfs_trans_commit(tp);
10711039
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
10721040
xfs_iunlock(sip, XFS_ILOCK_EXCL);
1073-
xfs_parent_finish(mp, ppargs);
1041+
xfs_parent_finish(mp, du.ppargs);
10741042
return error;
10751043

10761044
error_return:
10771045
xfs_trans_cancel(tp);
10781046
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
10791047
xfs_iunlock(sip, XFS_ILOCK_EXCL);
10801048
out_parent:
1081-
xfs_parent_finish(mp, ppargs);
1049+
xfs_parent_finish(mp, du.ppargs);
10821050
std_return:
10831051
if (error == -ENOSPC && nospace_error)
10841052
error = nospace_error;

0 commit comments

Comments
 (0)