+}
+
/*
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
diff --git a/fs/xfs/libxfs/xfs_parent.c b/fs/xfs/libxfs/xfs_parent.c
index 0707336..ca695c4 100644
--- a/fs/xfs/libxfs/xfs_parent.c
+++ b/fs/xfs/libxfs/xfs_parent.c
@@ -139,3 +139,25 @@ xfs_parent_add(
return xfs_parent_add_nrec(tp, child, &nrec, dfops, firstblock);
}
+
+/*
+ * Remove a parent record from a child inode.
+ */
+int
+xfs_parent_remove(
+ struct xfs_trans *tp,
+ struct xfs_inode *parent,
+ struct xfs_inode *child,
+ xfs_dir2_dataptr_t diroffset,
+ struct xfs_defer_ops *dfops,
+ xfs_fsblock_t *firstblock)
+{
+ struct xfs_parent_name_rec rec;
+
+ rec.p_ino = cpu_to_be64(parent->i_ino);
+ rec.p_gen = cpu_to_be32(VFS_I(parent)->i_generation);
+ rec.p_diroffset = cpu_to_be32(diroffset);
+
+ return xfs_attr_remove_parent(tp, child, &rec, sizeof(rec),
+ dfops, firstblock);
+}
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index acb6157..7a3bf8b 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -207,4 +207,11 @@ int xfs_attr_set_parent(struct xfs_trans *tp, struct xfs_inode *ip,
const char *value, int valuelen,
struct xfs_defer_ops *dfops, xfs_fsblock_t *firstblock);
+int xfs_parent_remove(struct xfs_trans *tp, struct xfs_inode *parent,
+ struct xfs_inode *child, xfs_dir2_dataptr_t diroffset,
+ struct xfs_defer_ops *dfops, xfs_fsblock_t *firstblock);
+int xfs_attr_remove_parent(struct xfs_trans *tp, struct xfs_inode *ip,
+ struct xfs_parent_name_rec *rec, int reclen,
+ struct xfs_defer_ops *dfops, xfs_fsblock_t *firstblock);
+
#endif /* __XFS_ATTR_H__ */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 51b623b..a360c3d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2612,6 +2612,7 @@ xfs_remove(
struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
uint resblks;
+ uint32_t dir_offset;
trace_xfs_remove(dp, name);
@@ -2692,12 +2693,19 @@ xfs_remove(
xfs_defer_init(&dfops, &first_block);
error = xfs_dir_removename(tp, dp, name, ip->i_ino, &first_block,
- &dfops, resblks, NULL);
+ &dfops, resblks, &dir_offset);
if (error) {
ASSERT(error != -ENOENT);
goto out_bmap_cancel;
}
+ if (xfs_sb_version_hasparent(&mp->m_sb)) {
+ error = xfs_parent_remove(tp, dp, ip, dir_offset, &dfops,
+ &first_block);
+ if (error)
+ goto out_bmap_cancel;
+ }
+
/*
* If this is a synchronous mount, make sure that the
* remove transaction goes to disk before returning to
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 010a13a..a047f0f 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -307,7 +307,7 @@ xfs_qm_dqattach_one(
return 0;
}
-static bool
+bool
xfs_qm_need_dqattach(
struct xfs_inode *ip)
{
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 2975a82..9976369 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -176,6 +176,7 @@ extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
struct qc_dqblk *);
extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint);
extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
+extern bool xfs_qm_need_dqattach(struct xfs_inode *ip);