Skip to content

Commit 1fa2e81

Browse files
author
Darrick J. Wong
committed
xfs: create libxfs helper to link a new inode into a directory
Create a new libxfs function to link a newly created 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 b11b11e commit 1fa2e81

File tree

4 files changed

+102
-65
lines changed

4 files changed

+102
-65
lines changed

fs/xfs/libxfs/xfs_dir2.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include "xfs_error.h"
2020
#include "xfs_trace.h"
2121
#include "xfs_health.h"
22+
#include "xfs_bmap_btree.h"
23+
#include "xfs_trans_space.h"
24+
#include "xfs_parent.h"
2225

2326
const struct xfs_name xfs_name_dotdot = {
2427
.name = (const unsigned char *)"..",
@@ -756,3 +759,53 @@ xfs_dir2_compname(
756759
return xfs_ascii_ci_compname(args, name, len);
757760
return xfs_da_compname(args, name, len);
758761
}
762+
763+
/*
764+
* Given a directory @dp, a newly allocated inode @ip, and a @name, link @ip
765+
* into @dp under the given @name. If @ip is a directory, it will be
766+
* initialized. Both inodes must have the ILOCK held and the transaction must
767+
* have sufficient blocks reserved.
768+
*/
769+
int
770+
xfs_dir_create_child(
771+
struct xfs_trans *tp,
772+
unsigned int resblks,
773+
struct xfs_dir_update *du)
774+
{
775+
struct xfs_inode *dp = du->dp;
776+
const struct xfs_name *name = du->name;
777+
struct xfs_inode *ip = du->ip;
778+
int error;
779+
780+
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
781+
xfs_assert_ilocked(dp, XFS_ILOCK_EXCL);
782+
783+
error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
784+
if (error) {
785+
ASSERT(error != -ENOSPC);
786+
return error;
787+
}
788+
789+
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
790+
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
791+
792+
if (S_ISDIR(VFS_I(ip)->i_mode)) {
793+
error = xfs_dir_init(tp, ip, dp);
794+
if (error)
795+
return error;
796+
797+
xfs_bumplink(tp, dp);
798+
}
799+
800+
/*
801+
* If we have parent pointers, we need to add the attribute containing
802+
* the parent information now.
803+
*/
804+
if (du->ppargs) {
805+
error = xfs_parent_addname(tp, du->ppargs, dp, name, ip);
806+
if (error)
807+
return error;
808+
}
809+
810+
return 0;
811+
}

fs/xfs/libxfs/xfs_dir2.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,16 @@ static inline unsigned char xfs_ascii_ci_xfrm(unsigned char c)
309309
return c;
310310
}
311311

312+
struct xfs_parent_args;
313+
314+
struct xfs_dir_update {
315+
struct xfs_inode *dp;
316+
const struct xfs_name *name;
317+
struct xfs_inode *ip;
318+
struct xfs_parent_args *ppargs;
319+
};
320+
321+
int xfs_dir_create_child(struct xfs_trans *tp, unsigned int resblks,
322+
struct xfs_dir_update *du);
323+
312324
#endif /* __XFS_DIR2_H__ */

fs/xfs/xfs_inode.c

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -714,14 +714,16 @@ xfs_create(
714714
struct xfs_inode **ipp)
715715
{
716716
struct xfs_inode *dp = args->pip;
717+
struct xfs_dir_update du = {
718+
.dp = dp,
719+
.name = name,
720+
};
717721
struct xfs_mount *mp = dp->i_mount;
718-
struct xfs_inode *ip = NULL;
719722
struct xfs_trans *tp = NULL;
720723
struct xfs_dquot *udqp;
721724
struct xfs_dquot *gdqp;
722725
struct xfs_dquot *pdqp;
723726
struct xfs_trans_res *tres;
724-
struct xfs_parent_args *ppargs;
725727
xfs_ino_t ino;
726728
bool unlock_dp_on_error = false;
727729
bool is_dir = S_ISDIR(args->mode);
@@ -748,7 +750,7 @@ xfs_create(
748750
tres = &M_RES(mp)->tr_create;
749751
}
750752

751-
error = xfs_parent_start(mp, &ppargs);
753+
error = xfs_parent_start(mp, &du.ppargs);
752754
if (error)
753755
goto out_release_dquots;
754756

@@ -779,7 +781,7 @@ xfs_create(
779781
*/
780782
error = xfs_dialloc(&tp, dp->i_ino, args->mode, &ino);
781783
if (!error)
782-
error = xfs_icreate(tp, ino, args, &ip);
784+
error = xfs_icreate(tp, ino, args, &du.ip);
783785
if (error)
784786
goto out_trans_cancel;
785787

@@ -792,38 +794,15 @@ xfs_create(
792794
*/
793795
xfs_trans_ijoin(tp, dp, 0);
794796

795-
error = xfs_dir_createname(tp, dp, name, ip->i_ino,
796-
resblks - XFS_IALLOC_SPACE_RES(mp));
797-
if (error) {
798-
ASSERT(error != -ENOSPC);
797+
error = xfs_dir_create_child(tp, resblks, &du);
798+
if (error)
799799
goto out_trans_cancel;
800-
}
801-
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
802-
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
803-
804-
if (is_dir) {
805-
error = xfs_dir_init(tp, ip, dp);
806-
if (error)
807-
goto out_trans_cancel;
808-
809-
xfs_bumplink(tp, dp);
810-
}
811-
812-
/*
813-
* If we have parent pointers, we need to add the attribute containing
814-
* the parent information now.
815-
*/
816-
if (ppargs) {
817-
error = xfs_parent_addname(tp, ppargs, dp, name, ip);
818-
if (error)
819-
goto out_trans_cancel;
820-
}
821800

822801
/*
823802
* Create ip with a reference from dp, and add '.' and '..' references
824803
* if it's a directory.
825804
*/
826-
xfs_dir_update_hook(dp, ip, 1, name);
805+
xfs_dir_update_hook(dp, du.ip, 1, name);
827806

828807
/*
829808
* If this is a synchronous mount, make sure that the
@@ -838,7 +817,7 @@ xfs_create(
838817
* These ids of the inode couldn't have changed since the new
839818
* inode has been locked ever since it was created.
840819
*/
841-
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
820+
xfs_qm_vop_create_dqattach(tp, du.ip, udqp, gdqp, pdqp);
842821

843822
error = xfs_trans_commit(tp);
844823
if (error)
@@ -848,10 +827,10 @@ xfs_create(
848827
xfs_qm_dqrele(gdqp);
849828
xfs_qm_dqrele(pdqp);
850829

851-
*ipp = ip;
852-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
830+
*ipp = du.ip;
831+
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
853832
xfs_iunlock(dp, XFS_ILOCK_EXCL);
854-
xfs_parent_finish(mp, ppargs);
833+
xfs_parent_finish(mp, du.ppargs);
855834
return 0;
856835

857836
out_trans_cancel:
@@ -862,13 +841,13 @@ xfs_create(
862841
* setup of the inode and release the inode. This prevents recursive
863842
* transactions and deadlocks from xfs_inactive.
864843
*/
865-
if (ip) {
866-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
867-
xfs_finish_inode_setup(ip);
868-
xfs_irele(ip);
844+
if (du.ip) {
845+
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
846+
xfs_finish_inode_setup(du.ip);
847+
xfs_irele(du.ip);
869848
}
870849
out_parent:
871-
xfs_parent_finish(mp, ppargs);
850+
xfs_parent_finish(mp, du.ppargs);
872851
out_release_dquots:
873852
xfs_qm_dqrele(udqp);
874853
xfs_qm_dqrele(gdqp);

fs/xfs/xfs_symlink.c

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,11 @@ xfs_symlink(
9595
.pip = dp,
9696
.mode = S_IFLNK | (mode & ~S_IFMT),
9797
};
98+
struct xfs_dir_update du = {
99+
.dp = dp,
100+
.name = link_name,
101+
};
98102
struct xfs_trans *tp = NULL;
99-
struct xfs_inode *ip = NULL;
100103
int error = 0;
101104
int pathlen;
102105
bool unlock_dp_on_error = false;
@@ -106,7 +109,6 @@ xfs_symlink(
106109
struct xfs_dquot *pdqp;
107110
uint resblks;
108111
xfs_ino_t ino;
109-
struct xfs_parent_args *ppargs;
110112

111113
*ipp = NULL;
112114

@@ -140,7 +142,7 @@ xfs_symlink(
140142
fs_blocks = xfs_symlink_blocks(mp, pathlen);
141143
resblks = xfs_symlink_space_res(mp, link_name->len, fs_blocks);
142144

143-
error = xfs_parent_start(mp, &ppargs);
145+
error = xfs_parent_start(mp, &du.ppargs);
144146
if (error)
145147
goto out_release_dquots;
146148

@@ -165,7 +167,7 @@ xfs_symlink(
165167
*/
166168
error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
167169
if (!error)
168-
error = xfs_icreate(tp, ino, &args, &ip);
170+
error = xfs_icreate(tp, ino, &args, &du.ip);
169171
if (error)
170172
goto out_trans_cancel;
171173

@@ -181,33 +183,24 @@ xfs_symlink(
181183
/*
182184
* Also attach the dquot(s) to it, if applicable.
183185
*/
184-
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
186+
xfs_qm_vop_create_dqattach(tp, du.ip, udqp, gdqp, pdqp);
185187

186188
resblks -= XFS_IALLOC_SPACE_RES(mp);
187-
error = xfs_symlink_write_target(tp, ip, ip->i_ino, target_path,
189+
error = xfs_symlink_write_target(tp, du.ip, du.ip->i_ino, target_path,
188190
pathlen, fs_blocks, resblks);
189191
if (error)
190192
goto out_trans_cancel;
191193
resblks -= fs_blocks;
192-
i_size_write(VFS_I(ip), ip->i_disk_size);
194+
i_size_write(VFS_I(du.ip), du.ip->i_disk_size);
193195

194196
/*
195197
* Create the directory entry for the symlink.
196198
*/
197-
error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
199+
error = xfs_dir_create_child(tp, resblks, &du);
198200
if (error)
199201
goto out_trans_cancel;
200-
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
201-
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
202-
203-
/* Add parent pointer for the new symlink. */
204-
if (ppargs) {
205-
error = xfs_parent_addname(tp, ppargs, dp, link_name, ip);
206-
if (error)
207-
goto out_trans_cancel;
208-
}
209202

210-
xfs_dir_update_hook(dp, ip, 1, link_name);
203+
xfs_dir_update_hook(dp, du.ip, 1, link_name);
211204

212205
/*
213206
* If this is a synchronous mount, make sure that the
@@ -225,10 +218,10 @@ xfs_symlink(
225218
xfs_qm_dqrele(gdqp);
226219
xfs_qm_dqrele(pdqp);
227220

228-
*ipp = ip;
229-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
221+
*ipp = du.ip;
222+
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
230223
xfs_iunlock(dp, XFS_ILOCK_EXCL);
231-
xfs_parent_finish(mp, ppargs);
224+
xfs_parent_finish(mp, du.ppargs);
232225
return 0;
233226

234227
out_trans_cancel:
@@ -239,13 +232,13 @@ xfs_symlink(
239232
* setup of the inode and release the inode. This prevents recursive
240233
* transactions and deadlocks from xfs_inactive.
241234
*/
242-
if (ip) {
243-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
244-
xfs_finish_inode_setup(ip);
245-
xfs_irele(ip);
235+
if (du.ip) {
236+
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
237+
xfs_finish_inode_setup(du.ip);
238+
xfs_irele(du.ip);
246239
}
247240
out_parent:
248-
xfs_parent_finish(mp, ppargs);
241+
xfs_parent_finish(mp, du.ppargs);
249242
out_release_dquots:
250243
xfs_qm_dqrele(udqp);
251244
xfs_qm_dqrele(gdqp);

0 commit comments

Comments
 (0)