aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorAllison Henderson <allison.henderson@oracle.com>2018-10-18 02:21:16 -0400
committerDave Chinner <david@fromorbit.com>2018-10-18 02:21:16 -0400
commit2f3cd8091963810d85e6a5dd6ed1247e10e9e6f2 (patch)
treeeef93c41ff1cf4ccac705ab04b93e39a07019c43 /fs/xfs/libxfs
parent4c74a56b9de76bb6b581274b76b52535ad77c2a7 (diff)
xfs: Add attibute set and helper functions
This patch adds xfs_attr_set_args and xfs_bmap_set_attrforkoff. These sub-routines set the attributes specified in @args. We will use this later for setting parent pointers as a deferred attribute operation. [dgc: remove attr fork init code from xfs_attr_set_args().] [dgc: xfs_attr_try_sf_addname() NULLs args.trans after commit.] [dgc: correct sf add error handling.] Signed-off-by: Allison Henderson <allison.henderson@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r--fs/xfs/libxfs/xfs_attr.c151
-rw-r--r--fs/xfs/libxfs/xfs_attr.h1
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c49
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h1
4 files changed, 115 insertions, 87 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index c15a1debec90..25431ddba1fa 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -215,9 +215,80 @@ xfs_attr_try_sf_addname(
215 xfs_trans_set_sync(args->trans); 215 xfs_trans_set_sync(args->trans);
216 216
217 error2 = xfs_trans_commit(args->trans); 217 error2 = xfs_trans_commit(args->trans);
218 args->trans = NULL;
218 return error ? error : error2; 219 return error ? error : error2;
219} 220}
220 221
222/*
223 * Set the attribute specified in @args.
224 */
225int
226xfs_attr_set_args(
227 struct xfs_da_args *args,
228 struct xfs_buf **leaf_bp)
229{
230 struct xfs_inode *dp = args->dp;
231 int error;
232
233 /*
234 * If the attribute list is non-existent or a shortform list,
235 * upgrade it to a single-leaf-block attribute list.
236 */
237 if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
238 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
239 dp->i_d.di_anextents == 0)) {
240
241 /*
242 * Build initial attribute list (if required).
243 */
244 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
245 xfs_attr_shortform_create(args);
246
247 /*
248 * Try to add the attr to the attribute list in the inode.
249 */
250 error = xfs_attr_try_sf_addname(dp, args);
251 if (error != -ENOSPC)
252 return error;
253
254 /*
255 * It won't fit in the shortform, transform to a leaf block.
256 * GROT: another possible req'mt for a double-split btree op.
257 */
258 error = xfs_attr_shortform_to_leaf(args, leaf_bp);
259 if (error)
260 return error;
261
262 /*
263 * Prevent the leaf buffer from being unlocked so that a
264 * concurrent AIL push cannot grab the half-baked leaf
265 * buffer and run into problems with the write verifier.
266 */
267 xfs_trans_bhold(args->trans, *leaf_bp);
268
269 error = xfs_defer_finish(&args->trans);
270 if (error)
271 return error;
272
273 /*
274 * Commit the leaf transformation. We'll need another
275 * (linked) transaction to add the new attribute to the
276 * leaf.
277 */
278 error = xfs_trans_roll_inode(&args->trans, dp);
279 if (error)
280 return error;
281 xfs_trans_bjoin(args->trans, *leaf_bp);
282 *leaf_bp = NULL;
283 }
284
285 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
286 error = xfs_attr_leaf_addname(args);
287 else
288 error = xfs_attr_node_addname(args);
289 return error;
290}
291
221int 292int
222xfs_attr_set( 293xfs_attr_set(
223 struct xfs_inode *dp, 294 struct xfs_inode *dp,
@@ -282,73 +353,17 @@ xfs_attr_set(
282 error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, 353 error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
283 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : 354 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
284 XFS_QMOPT_RES_REGBLKS); 355 XFS_QMOPT_RES_REGBLKS);
285 if (error) { 356 if (error)
286 xfs_iunlock(dp, XFS_ILOCK_EXCL); 357 goto out_trans_cancel;
287 xfs_trans_cancel(args.trans);
288 return error;
289 }
290 358
291 xfs_trans_ijoin(args.trans, dp, 0); 359 xfs_trans_ijoin(args.trans, dp, 0);
292 360 error = xfs_attr_set_args(&args, &leaf_bp);
293 /*
294 * If the attribute list is non-existent or a shortform list,
295 * upgrade it to a single-leaf-block attribute list.
296 */
297 if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
298 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
299 dp->i_d.di_anextents == 0)) {
300
301 /*
302 * Build initial attribute list (if required).
303 */
304 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
305 xfs_attr_shortform_create(&args);
306
307 /*
308 * Try to add the attr to the attribute list in
309 * the inode.
310 */
311 error = xfs_attr_try_sf_addname(dp, &args);
312 if (error != -ENOSPC) {
313 xfs_iunlock(dp, XFS_ILOCK_EXCL);
314 return error;
315 }
316
317 /*
318 * It won't fit in the shortform, transform to a leaf block.
319 * GROT: another possible req'mt for a double-split btree op.
320 */
321 error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
322 if (error)
323 goto out;
324 /*
325 * Prevent the leaf buffer from being unlocked so that a
326 * concurrent AIL push cannot grab the half-baked leaf
327 * buffer and run into problems with the write verifier.
328 */
329 xfs_trans_bhold(args.trans, leaf_bp);
330 error = xfs_defer_finish(&args.trans);
331 if (error)
332 goto out;
333
334 /*
335 * Commit the leaf transformation. We'll need another (linked)
336 * transaction to add the new attribute to the leaf, which
337 * means that we have to hold & join the leaf buffer here too.
338 */
339 error = xfs_trans_roll_inode(&args.trans, dp);
340 if (error)
341 goto out;
342 xfs_trans_bjoin(args.trans, leaf_bp);
343 leaf_bp = NULL;
344 }
345
346 if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
347 error = xfs_attr_leaf_addname(&args);
348 else
349 error = xfs_attr_node_addname(&args);
350 if (error) 361 if (error)
351 goto out; 362 goto out_release_leaf;
363 if (!args.trans) {
364 /* shortform attribute has already been committed */
365 goto out_unlock;
366 }
352 367
353 /* 368 /*
354 * If this is a synchronous mount, make sure that the 369 * If this is a synchronous mount, make sure that the
@@ -365,17 +380,17 @@ xfs_attr_set(
365 */ 380 */
366 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE); 381 xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
367 error = xfs_trans_commit(args.trans); 382 error = xfs_trans_commit(args.trans);
383out_unlock:
368 xfs_iunlock(dp, XFS_ILOCK_EXCL); 384 xfs_iunlock(dp, XFS_ILOCK_EXCL);
369
370 return error; 385 return error;
371 386
372out: 387out_release_leaf:
373 if (leaf_bp) 388 if (leaf_bp)
374 xfs_trans_brelse(args.trans, leaf_bp); 389 xfs_trans_brelse(args.trans, leaf_bp);
390out_trans_cancel:
375 if (args.trans) 391 if (args.trans)
376 xfs_trans_cancel(args.trans); 392 xfs_trans_cancel(args.trans);
377 xfs_iunlock(dp, XFS_ILOCK_EXCL); 393 goto out_unlock;
378 return error;
379} 394}
380 395
381/* 396/*
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 033ff8c478e2..f608ac8f306f 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -140,6 +140,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
140 unsigned char *value, int *valuelenp, int flags); 140 unsigned char *value, int *valuelenp, int flags);
141int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name, 141int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
142 unsigned char *value, int valuelen, int flags); 142 unsigned char *value, int valuelen, int flags);
143int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
143int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags); 144int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
144int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize, 145int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
145 int flags, struct attrlist_cursor_kern *cursor); 146 int flags, struct attrlist_cursor_kern *cursor);
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index da6b768664e3..74d7228e755b 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1019,6 +1019,34 @@ xfs_bmap_add_attrfork_local(
1019 return -EFSCORRUPTED; 1019 return -EFSCORRUPTED;
1020} 1020}
1021 1021
1022/* Set an inode attr fork off based on the format */
1023int
1024xfs_bmap_set_attrforkoff(
1025 struct xfs_inode *ip,
1026 int size,
1027 int *version)
1028{
1029 switch (ip->i_d.di_format) {
1030 case XFS_DINODE_FMT_DEV:
1031 ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
1032 break;
1033 case XFS_DINODE_FMT_LOCAL:
1034 case XFS_DINODE_FMT_EXTENTS:
1035 case XFS_DINODE_FMT_BTREE:
1036 ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
1037 if (!ip->i_d.di_forkoff)
1038 ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
1039 else if ((ip->i_mount->m_flags & XFS_MOUNT_ATTR2) && version)
1040 *version = 2;
1041 break;
1042 default:
1043 ASSERT(0);
1044 return -EINVAL;
1045 }
1046
1047 return 0;
1048}
1049
1022/* 1050/*
1023 * Convert inode from non-attributed to attributed. 1051 * Convert inode from non-attributed to attributed.
1024 * Must not be in a transaction, ip must not be locked. 1052 * Must not be in a transaction, ip must not be locked.
@@ -1070,26 +1098,9 @@ xfs_bmap_add_attrfork(
1070 1098
1071 xfs_trans_ijoin(tp, ip, 0); 1099 xfs_trans_ijoin(tp, ip, 0);
1072 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 1100 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1073 1101 error = xfs_bmap_set_attrforkoff(ip, size, &version);
1074 switch (ip->i_d.di_format) { 1102 if (error)
1075 case XFS_DINODE_FMT_DEV:
1076 ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
1077 break;
1078 case XFS_DINODE_FMT_LOCAL:
1079 case XFS_DINODE_FMT_EXTENTS:
1080 case XFS_DINODE_FMT_BTREE:
1081 ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
1082 if (!ip->i_d.di_forkoff)
1083 ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
1084 else if (mp->m_flags & XFS_MOUNT_ATTR2)
1085 version = 2;
1086 break;
1087 default:
1088 ASSERT(0);
1089 error = -EINVAL;
1090 goto trans_cancel; 1103 goto trans_cancel;
1091 }
1092
1093 ASSERT(ip->i_afp == NULL); 1104 ASSERT(ip->i_afp == NULL);
1094 ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); 1105 ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
1095 ip->i_afp->if_flags = XFS_IFEXTENTS; 1106 ip->i_afp->if_flags = XFS_IFEXTENTS;
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index b6e9b639e731..488dc8860fd7 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -183,6 +183,7 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
183 xfs_filblks_t len); 183 xfs_filblks_t len);
184void xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *); 184void xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
185int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); 185int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
186int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
186void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); 187void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
187void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno, 188void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
188 xfs_filblks_t len, struct xfs_owner_info *oinfo, 189 xfs_filblks_t len, struct xfs_owner_info *oinfo,