mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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 <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
1fa2e81957
commit
c1f0bad423
@ -22,6 +22,7 @@
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_trans_space.h"
|
||||
#include "xfs_parent.h"
|
||||
#include "xfs_ag.h"
|
||||
|
||||
const struct xfs_name xfs_name_dotdot = {
|
||||
.name = (const unsigned char *)"..",
|
||||
@ -587,9 +588,9 @@ xfs_dir_replace(
|
||||
*/
|
||||
int
|
||||
xfs_dir_canenter(
|
||||
xfs_trans_t *tp,
|
||||
xfs_inode_t *dp,
|
||||
struct xfs_name *name) /* name of entry to add */
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
const struct xfs_name *name) /* name of entry to add */
|
||||
{
|
||||
return xfs_dir_createname(tp, dp, name, 0, 0);
|
||||
}
|
||||
@ -809,3 +810,67 @@ xfs_dir_create_child(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a directory @dp, an existing non-directory inode @ip, and a @name,
|
||||
* link @ip into @dp under the given @name. Both inodes must have the ILOCK
|
||||
* held.
|
||||
*/
|
||||
int
|
||||
xfs_dir_add_child(
|
||||
struct xfs_trans *tp,
|
||||
unsigned int resblks,
|
||||
struct xfs_dir_update *du)
|
||||
{
|
||||
struct xfs_inode *dp = du->dp;
|
||||
const struct xfs_name *name = du->name;
|
||||
struct xfs_inode *ip = du->ip;
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
int error;
|
||||
|
||||
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
|
||||
xfs_assert_ilocked(dp, XFS_ILOCK_EXCL);
|
||||
ASSERT(!S_ISDIR(VFS_I(ip)->i_mode));
|
||||
|
||||
if (!resblks) {
|
||||
error = xfs_dir_canenter(tp, dp, name);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle initial link state of O_TMPFILE inode
|
||||
*/
|
||||
if (VFS_I(ip)->i_nlink == 0) {
|
||||
struct xfs_perag *pag;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
|
||||
error = xfs_iunlink_remove(tp, pag, ip);
|
||||
xfs_perag_put(pag);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
||||
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
|
||||
|
||||
xfs_bumplink(tp, ip);
|
||||
|
||||
/*
|
||||
* If we have parent pointers, we now need to add the parent record to
|
||||
* the attribute fork of the inode. If this is the initial parent
|
||||
* attribute, we need to create it correctly, otherwise we can just add
|
||||
* the parent to the inode.
|
||||
*/
|
||||
if (du->ppargs) {
|
||||
error = xfs_parent_addname(tp, du->ppargs, dp, name, ip);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
const struct xfs_name *name, xfs_ino_t inum,
|
||||
xfs_extlen_t tot);
|
||||
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
struct xfs_name *name);
|
||||
const struct xfs_name *name);
|
||||
|
||||
int xfs_dir_lookup_args(struct xfs_da_args *args);
|
||||
int xfs_dir_createname_args(struct xfs_da_args *args);
|
||||
@ -320,5 +320,7 @@ struct xfs_dir_update {
|
||||
|
||||
int xfs_dir_create_child(struct xfs_trans *tp, unsigned int resblks,
|
||||
struct xfs_dir_update *du);
|
||||
int xfs_dir_add_child(struct xfs_trans *tp, unsigned int resblks,
|
||||
struct xfs_dir_update *du);
|
||||
|
||||
#endif /* __XFS_DIR2_H__ */
|
||||
|
@ -952,11 +952,15 @@ xfs_link(
|
||||
struct xfs_inode *sip,
|
||||
struct xfs_name *target_name)
|
||||
{
|
||||
struct xfs_dir_update du = {
|
||||
.dp = tdp,
|
||||
.name = target_name,
|
||||
.ip = sip,
|
||||
};
|
||||
struct xfs_mount *mp = tdp->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
int error, nospace_error = 0;
|
||||
int resblks;
|
||||
struct xfs_parent_args *ppargs;
|
||||
|
||||
trace_xfs_link(tdp, target_name);
|
||||
|
||||
@ -975,7 +979,7 @@ xfs_link(
|
||||
if (error)
|
||||
goto std_return;
|
||||
|
||||
error = xfs_parent_start(mp, &ppargs);
|
||||
error = xfs_parent_start(mp, &du.ppargs);
|
||||
if (error)
|
||||
goto std_return;
|
||||
|
||||
@ -990,7 +994,7 @@ xfs_link(
|
||||
* pointers are enabled because we can't back out if the xattrs must
|
||||
* grow.
|
||||
*/
|
||||
if (ppargs && nospace_error) {
|
||||
if (du.ppargs && nospace_error) {
|
||||
error = nospace_error;
|
||||
goto error_return;
|
||||
}
|
||||
@ -1017,45 +1021,9 @@ xfs_link(
|
||||
}
|
||||
}
|
||||
|
||||
if (!resblks) {
|
||||
error = xfs_dir_canenter(tp, tdp, target_name);
|
||||
if (error)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle initial link state of O_TMPFILE inode
|
||||
*/
|
||||
if (VFS_I(sip)->i_nlink == 0) {
|
||||
struct xfs_perag *pag;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sip->i_ino));
|
||||
error = xfs_iunlink_remove(tp, pag, sip);
|
||||
xfs_perag_put(pag);
|
||||
if (error)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
|
||||
resblks);
|
||||
error = xfs_dir_add_child(tp, resblks, &du);
|
||||
if (error)
|
||||
goto error_return;
|
||||
xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
|
||||
xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
|
||||
|
||||
xfs_bumplink(tp, sip);
|
||||
|
||||
/*
|
||||
* If we have parent pointers, we now need to add the parent record to
|
||||
* the attribute fork of the inode. If this is the initial parent
|
||||
* attribute, we need to create it correctly, otherwise we can just add
|
||||
* the parent to the inode.
|
||||
*/
|
||||
if (ppargs) {
|
||||
error = xfs_parent_addname(tp, ppargs, tdp, target_name, sip);
|
||||
if (error)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
xfs_dir_update_hook(tdp, sip, 1, target_name);
|
||||
|
||||
@ -1070,7 +1038,7 @@ xfs_link(
|
||||
error = xfs_trans_commit(tp);
|
||||
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
|
||||
xfs_iunlock(sip, XFS_ILOCK_EXCL);
|
||||
xfs_parent_finish(mp, ppargs);
|
||||
xfs_parent_finish(mp, du.ppargs);
|
||||
return error;
|
||||
|
||||
error_return:
|
||||
@ -1078,7 +1046,7 @@ xfs_link(
|
||||
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
|
||||
xfs_iunlock(sip, XFS_ILOCK_EXCL);
|
||||
out_parent:
|
||||
xfs_parent_finish(mp, ppargs);
|
||||
xfs_parent_finish(mp, du.ppargs);
|
||||
std_return:
|
||||
if (error == -ENOSPC && nospace_error)
|
||||
error = nospace_error;
|
||||
|
Loading…
Reference in New Issue
Block a user