@@ -532,6 +532,7 @@ xfs_attr_set(
int valuelen)
{
struct xfs_mount *mp = dp->i_mount;
+ struct xfs_sb *sbp = &mp->m_sb;
struct xfs_da_args args;
struct xfs_trans_res tres;
int rsvd = (name->type & ATTR_ROOT) != 0;
@@ -590,7 +591,34 @@ xfs_attr_set(
goto out_trans_cancel;
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_set_args(&args);
+ if (xfs_sb_version_hasdelattr(sbp)) {
+ error = xfs_has_attr(&args);
+
+ if (error == -EEXIST) {
+ if (name->type & ATTR_CREATE)
+ goto out_trans_cancel;
+ else
+ name->type |= ATTR_REPLACE;
+ }
+
+ if (error == -ENOATTR && (name->type & ATTR_REPLACE))
+ goto out_trans_cancel;
+
+ if (name->type & ATTR_REPLACE) {
+ name->type &= ~ATTR_REPLACE;
+ error = xfs_attr_remove_deferred(dp, args.trans, name);
+ if (error)
+ goto out_trans_cancel;
+
+ name->type |= ATTR_CREATE;
+ }
+
+ error = xfs_attr_set_deferred(dp, args.trans, name, value,
+ valuelen);
+ } else {
+ error = xfs_attr_set_args(&args);
+ }
+
if (error)
goto out_trans_cancel;
if (!args.trans) {
@@ -697,6 +725,7 @@ xfs_attr_remove(
struct xfs_name *name)
{
struct xfs_mount *mp = dp->i_mount;
+ struct xfs_sb *sbp = &mp->m_sb;
struct xfs_da_args args;
int error;
@@ -738,7 +767,14 @@ xfs_attr_remove(
*/
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_remove_args(&args);
+ error = xfs_has_attr(&args);
+ if (error == -ENOATTR)
+ goto out;
+
+ if (xfs_sb_version_hasdelattr(sbp))
+ error = xfs_attr_remove_deferred(dp, args.trans, name);
+ else
+ error = xfs_attr_remove_args(&args);
if (error)
goto out;
Finally enable delayed attributes in xfs_attr_set and xfs_attr_remove. We only do this for new filesystems that have the feature bit enabled because we cant add new log entries to older filesystems Signed-off-by: Allison Collins <allison.henderson@oracle.com> --- fs/xfs/libxfs/xfs_attr.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)