xfs_attr_item.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Oracle. All Rights Reserved.
  4. * Author: Allison Henderson <[email protected]>
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_format.h"
  9. #include "xfs_trans_resv.h"
  10. #include "xfs_shared.h"
  11. #include "xfs_mount.h"
  12. #include "xfs_defer.h"
  13. #include "xfs_log_format.h"
  14. #include "xfs_trans.h"
  15. #include "xfs_bmap_btree.h"
  16. #include "xfs_trans_priv.h"
  17. #include "xfs_log.h"
  18. #include "xfs_inode.h"
  19. #include "xfs_da_format.h"
  20. #include "xfs_da_btree.h"
  21. #include "xfs_attr.h"
  22. #include "xfs_attr_item.h"
  23. #include "xfs_trace.h"
  24. #include "xfs_trans_space.h"
  25. #include "xfs_errortag.h"
  26. #include "xfs_error.h"
  27. #include "xfs_log_priv.h"
  28. #include "xfs_log_recover.h"
  29. struct kmem_cache *xfs_attri_cache;
  30. struct kmem_cache *xfs_attrd_cache;
  31. static const struct xfs_item_ops xfs_attri_item_ops;
  32. static const struct xfs_item_ops xfs_attrd_item_ops;
  33. static struct xfs_attrd_log_item *xfs_trans_get_attrd(struct xfs_trans *tp,
  34. struct xfs_attri_log_item *attrip);
  35. static inline struct xfs_attri_log_item *ATTRI_ITEM(struct xfs_log_item *lip)
  36. {
  37. return container_of(lip, struct xfs_attri_log_item, attri_item);
  38. }
  39. /*
  40. * Shared xattr name/value buffers for logged extended attribute operations
  41. *
  42. * When logging updates to extended attributes, we can create quite a few
  43. * attribute log intent items for a single xattr update. To avoid cycling the
  44. * memory allocator and memcpy overhead, the name (and value, for setxattr)
  45. * are kept in a refcounted object that is shared across all related log items
  46. * and the upper-level deferred work state structure. The shared buffer has
  47. * a control structure, followed by the name, and then the value.
  48. */
  49. static inline struct xfs_attri_log_nameval *
  50. xfs_attri_log_nameval_get(
  51. struct xfs_attri_log_nameval *nv)
  52. {
  53. if (!refcount_inc_not_zero(&nv->refcount))
  54. return NULL;
  55. return nv;
  56. }
  57. static inline void
  58. xfs_attri_log_nameval_put(
  59. struct xfs_attri_log_nameval *nv)
  60. {
  61. if (!nv)
  62. return;
  63. if (refcount_dec_and_test(&nv->refcount))
  64. kvfree(nv);
  65. }
  66. static inline struct xfs_attri_log_nameval *
  67. xfs_attri_log_nameval_alloc(
  68. const void *name,
  69. unsigned int name_len,
  70. const void *value,
  71. unsigned int value_len)
  72. {
  73. struct xfs_attri_log_nameval *nv;
  74. /*
  75. * This could be over 64kB in length, so we have to use kvmalloc() for
  76. * this. But kvmalloc() utterly sucks, so we use our own version.
  77. */
  78. nv = xlog_kvmalloc(sizeof(struct xfs_attri_log_nameval) +
  79. name_len + value_len);
  80. nv->name.i_addr = nv + 1;
  81. nv->name.i_len = name_len;
  82. nv->name.i_type = XLOG_REG_TYPE_ATTR_NAME;
  83. memcpy(nv->name.i_addr, name, name_len);
  84. if (value_len) {
  85. nv->value.i_addr = nv->name.i_addr + name_len;
  86. nv->value.i_len = value_len;
  87. memcpy(nv->value.i_addr, value, value_len);
  88. } else {
  89. nv->value.i_addr = NULL;
  90. nv->value.i_len = 0;
  91. }
  92. nv->value.i_type = XLOG_REG_TYPE_ATTR_VALUE;
  93. refcount_set(&nv->refcount, 1);
  94. return nv;
  95. }
  96. STATIC void
  97. xfs_attri_item_free(
  98. struct xfs_attri_log_item *attrip)
  99. {
  100. kmem_free(attrip->attri_item.li_lv_shadow);
  101. xfs_attri_log_nameval_put(attrip->attri_nameval);
  102. kmem_cache_free(xfs_attri_cache, attrip);
  103. }
  104. /*
  105. * Freeing the attrip requires that we remove it from the AIL if it has already
  106. * been placed there. However, the ATTRI may not yet have been placed in the
  107. * AIL when called by xfs_attri_release() from ATTRD processing due to the
  108. * ordering of committed vs unpin operations in bulk insert operations. Hence
  109. * the reference count to ensure only the last caller frees the ATTRI.
  110. */
  111. STATIC void
  112. xfs_attri_release(
  113. struct xfs_attri_log_item *attrip)
  114. {
  115. ASSERT(atomic_read(&attrip->attri_refcount) > 0);
  116. if (!atomic_dec_and_test(&attrip->attri_refcount))
  117. return;
  118. xfs_trans_ail_delete(&attrip->attri_item, 0);
  119. xfs_attri_item_free(attrip);
  120. }
  121. STATIC void
  122. xfs_attri_item_size(
  123. struct xfs_log_item *lip,
  124. int *nvecs,
  125. int *nbytes)
  126. {
  127. struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
  128. struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
  129. *nvecs += 2;
  130. *nbytes += sizeof(struct xfs_attri_log_format) +
  131. xlog_calc_iovec_len(nv->name.i_len);
  132. if (!nv->value.i_len)
  133. return;
  134. *nvecs += 1;
  135. *nbytes += xlog_calc_iovec_len(nv->value.i_len);
  136. }
  137. /*
  138. * This is called to fill in the log iovecs for the given attri log
  139. * item. We use 1 iovec for the attri_format_item, 1 for the name, and
  140. * another for the value if it is present
  141. */
  142. STATIC void
  143. xfs_attri_item_format(
  144. struct xfs_log_item *lip,
  145. struct xfs_log_vec *lv)
  146. {
  147. struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
  148. struct xfs_log_iovec *vecp = NULL;
  149. struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
  150. attrip->attri_format.alfi_type = XFS_LI_ATTRI;
  151. attrip->attri_format.alfi_size = 1;
  152. /*
  153. * This size accounting must be done before copying the attrip into the
  154. * iovec. If we do it after, the wrong size will be recorded to the log
  155. * and we trip across assertion checks for bad region sizes later during
  156. * the log recovery.
  157. */
  158. ASSERT(nv->name.i_len > 0);
  159. attrip->attri_format.alfi_size++;
  160. if (nv->value.i_len > 0)
  161. attrip->attri_format.alfi_size++;
  162. xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRI_FORMAT,
  163. &attrip->attri_format,
  164. sizeof(struct xfs_attri_log_format));
  165. xlog_copy_from_iovec(lv, &vecp, &nv->name);
  166. if (nv->value.i_len > 0)
  167. xlog_copy_from_iovec(lv, &vecp, &nv->value);
  168. }
  169. /*
  170. * The unpin operation is the last place an ATTRI is manipulated in the log. It
  171. * is either inserted in the AIL or aborted in the event of a log I/O error. In
  172. * either case, the ATTRI transaction has been successfully committed to make
  173. * it this far. Therefore, we expect whoever committed the ATTRI to either
  174. * construct and commit the ATTRD or drop the ATTRD's reference in the event of
  175. * error. Simply drop the log's ATTRI reference now that the log is done with
  176. * it.
  177. */
  178. STATIC void
  179. xfs_attri_item_unpin(
  180. struct xfs_log_item *lip,
  181. int remove)
  182. {
  183. xfs_attri_release(ATTRI_ITEM(lip));
  184. }
  185. STATIC void
  186. xfs_attri_item_release(
  187. struct xfs_log_item *lip)
  188. {
  189. xfs_attri_release(ATTRI_ITEM(lip));
  190. }
  191. /*
  192. * Allocate and initialize an attri item. Caller may allocate an additional
  193. * trailing buffer for name and value
  194. */
  195. STATIC struct xfs_attri_log_item *
  196. xfs_attri_init(
  197. struct xfs_mount *mp,
  198. struct xfs_attri_log_nameval *nv)
  199. {
  200. struct xfs_attri_log_item *attrip;
  201. attrip = kmem_cache_zalloc(xfs_attri_cache, GFP_NOFS | __GFP_NOFAIL);
  202. /*
  203. * Grab an extra reference to the name/value buffer for this log item.
  204. * The caller retains its own reference!
  205. */
  206. attrip->attri_nameval = xfs_attri_log_nameval_get(nv);
  207. ASSERT(attrip->attri_nameval);
  208. xfs_log_item_init(mp, &attrip->attri_item, XFS_LI_ATTRI,
  209. &xfs_attri_item_ops);
  210. attrip->attri_format.alfi_id = (uintptr_t)(void *)attrip;
  211. atomic_set(&attrip->attri_refcount, 2);
  212. return attrip;
  213. }
  214. static inline struct xfs_attrd_log_item *ATTRD_ITEM(struct xfs_log_item *lip)
  215. {
  216. return container_of(lip, struct xfs_attrd_log_item, attrd_item);
  217. }
  218. STATIC void
  219. xfs_attrd_item_free(struct xfs_attrd_log_item *attrdp)
  220. {
  221. kmem_free(attrdp->attrd_item.li_lv_shadow);
  222. kmem_cache_free(xfs_attrd_cache, attrdp);
  223. }
  224. STATIC void
  225. xfs_attrd_item_size(
  226. struct xfs_log_item *lip,
  227. int *nvecs,
  228. int *nbytes)
  229. {
  230. *nvecs += 1;
  231. *nbytes += sizeof(struct xfs_attrd_log_format);
  232. }
  233. /*
  234. * This is called to fill in the log iovecs for the given attrd log item. We use
  235. * only 1 iovec for the attrd_format, and we point that at the attr_log_format
  236. * structure embedded in the attrd item.
  237. */
  238. STATIC void
  239. xfs_attrd_item_format(
  240. struct xfs_log_item *lip,
  241. struct xfs_log_vec *lv)
  242. {
  243. struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip);
  244. struct xfs_log_iovec *vecp = NULL;
  245. attrdp->attrd_format.alfd_type = XFS_LI_ATTRD;
  246. attrdp->attrd_format.alfd_size = 1;
  247. xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTRD_FORMAT,
  248. &attrdp->attrd_format,
  249. sizeof(struct xfs_attrd_log_format));
  250. }
  251. /*
  252. * The ATTRD is either committed or aborted if the transaction is canceled. If
  253. * the transaction is canceled, drop our reference to the ATTRI and free the
  254. * ATTRD.
  255. */
  256. STATIC void
  257. xfs_attrd_item_release(
  258. struct xfs_log_item *lip)
  259. {
  260. struct xfs_attrd_log_item *attrdp = ATTRD_ITEM(lip);
  261. xfs_attri_release(attrdp->attrd_attrip);
  262. xfs_attrd_item_free(attrdp);
  263. }
  264. static struct xfs_log_item *
  265. xfs_attrd_item_intent(
  266. struct xfs_log_item *lip)
  267. {
  268. return &ATTRD_ITEM(lip)->attrd_attrip->attri_item;
  269. }
  270. /*
  271. * Performs one step of an attribute update intent and marks the attrd item
  272. * dirty.. An attr operation may be a set or a remove. Note that the
  273. * transaction is marked dirty regardless of whether the operation succeeds or
  274. * fails to support the ATTRI/ATTRD lifecycle rules.
  275. */
  276. STATIC int
  277. xfs_xattri_finish_update(
  278. struct xfs_attr_intent *attr,
  279. struct xfs_attrd_log_item *attrdp)
  280. {
  281. struct xfs_da_args *args = attr->xattri_da_args;
  282. int error;
  283. if (XFS_TEST_ERROR(false, args->dp->i_mount, XFS_ERRTAG_LARP)) {
  284. error = -EIO;
  285. goto out;
  286. }
  287. error = xfs_attr_set_iter(attr);
  288. if (!error && attr->xattri_dela_state != XFS_DAS_DONE)
  289. error = -EAGAIN;
  290. out:
  291. /*
  292. * Mark the transaction dirty, even on error. This ensures the
  293. * transaction is aborted, which:
  294. *
  295. * 1.) releases the ATTRI and frees the ATTRD
  296. * 2.) shuts down the filesystem
  297. */
  298. args->trans->t_flags |= XFS_TRANS_DIRTY | XFS_TRANS_HAS_INTENT_DONE;
  299. /*
  300. * attr intent/done items are null when logged attributes are disabled
  301. */
  302. if (attrdp)
  303. set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
  304. return error;
  305. }
  306. /* Log an attr to the intent item. */
  307. STATIC void
  308. xfs_attr_log_item(
  309. struct xfs_trans *tp,
  310. struct xfs_attri_log_item *attrip,
  311. const struct xfs_attr_intent *attr)
  312. {
  313. struct xfs_attri_log_format *attrp;
  314. tp->t_flags |= XFS_TRANS_DIRTY;
  315. set_bit(XFS_LI_DIRTY, &attrip->attri_item.li_flags);
  316. /*
  317. * At this point the xfs_attr_intent has been constructed, and we've
  318. * created the log intent. Fill in the attri log item and log format
  319. * structure with fields from this xfs_attr_intent
  320. */
  321. attrp = &attrip->attri_format;
  322. attrp->alfi_ino = attr->xattri_da_args->dp->i_ino;
  323. ASSERT(!(attr->xattri_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK));
  324. attrp->alfi_op_flags = attr->xattri_op_flags;
  325. attrp->alfi_value_len = attr->xattri_nameval->value.i_len;
  326. attrp->alfi_name_len = attr->xattri_nameval->name.i_len;
  327. ASSERT(!(attr->xattri_da_args->attr_filter & ~XFS_ATTRI_FILTER_MASK));
  328. attrp->alfi_attr_filter = attr->xattri_da_args->attr_filter;
  329. }
  330. /* Get an ATTRI. */
  331. static struct xfs_log_item *
  332. xfs_attr_create_intent(
  333. struct xfs_trans *tp,
  334. struct list_head *items,
  335. unsigned int count,
  336. bool sort)
  337. {
  338. struct xfs_mount *mp = tp->t_mountp;
  339. struct xfs_attri_log_item *attrip;
  340. struct xfs_attr_intent *attr;
  341. struct xfs_da_args *args;
  342. ASSERT(count == 1);
  343. /*
  344. * Each attr item only performs one attribute operation at a time, so
  345. * this is a list of one
  346. */
  347. attr = list_first_entry_or_null(items, struct xfs_attr_intent,
  348. xattri_list);
  349. args = attr->xattri_da_args;
  350. if (!(args->op_flags & XFS_DA_OP_LOGGED))
  351. return NULL;
  352. /*
  353. * Create a buffer to store the attribute name and value. This buffer
  354. * will be shared between the higher level deferred xattr work state
  355. * and the lower level xattr log items.
  356. */
  357. if (!attr->xattri_nameval) {
  358. /*
  359. * Transfer our reference to the name/value buffer to the
  360. * deferred work state structure.
  361. */
  362. attr->xattri_nameval = xfs_attri_log_nameval_alloc(args->name,
  363. args->namelen, args->value, args->valuelen);
  364. }
  365. attrip = xfs_attri_init(mp, attr->xattri_nameval);
  366. xfs_trans_add_item(tp, &attrip->attri_item);
  367. xfs_attr_log_item(tp, attrip, attr);
  368. return &attrip->attri_item;
  369. }
  370. static inline void
  371. xfs_attr_free_item(
  372. struct xfs_attr_intent *attr)
  373. {
  374. if (attr->xattri_da_state)
  375. xfs_da_state_free(attr->xattri_da_state);
  376. xfs_attri_log_nameval_put(attr->xattri_nameval);
  377. if (attr->xattri_da_args->op_flags & XFS_DA_OP_RECOVERY)
  378. kmem_free(attr);
  379. else
  380. kmem_cache_free(xfs_attr_intent_cache, attr);
  381. }
  382. /* Process an attr. */
  383. STATIC int
  384. xfs_attr_finish_item(
  385. struct xfs_trans *tp,
  386. struct xfs_log_item *done,
  387. struct list_head *item,
  388. struct xfs_btree_cur **state)
  389. {
  390. struct xfs_attr_intent *attr;
  391. struct xfs_attrd_log_item *done_item = NULL;
  392. int error;
  393. attr = container_of(item, struct xfs_attr_intent, xattri_list);
  394. if (done)
  395. done_item = ATTRD_ITEM(done);
  396. /*
  397. * Always reset trans after EAGAIN cycle
  398. * since the transaction is new
  399. */
  400. attr->xattri_da_args->trans = tp;
  401. error = xfs_xattri_finish_update(attr, done_item);
  402. if (error != -EAGAIN)
  403. xfs_attr_free_item(attr);
  404. return error;
  405. }
  406. /* Abort all pending ATTRs. */
  407. STATIC void
  408. xfs_attr_abort_intent(
  409. struct xfs_log_item *intent)
  410. {
  411. xfs_attri_release(ATTRI_ITEM(intent));
  412. }
  413. /* Cancel an attr */
  414. STATIC void
  415. xfs_attr_cancel_item(
  416. struct list_head *item)
  417. {
  418. struct xfs_attr_intent *attr;
  419. attr = container_of(item, struct xfs_attr_intent, xattri_list);
  420. xfs_attr_free_item(attr);
  421. }
  422. STATIC bool
  423. xfs_attri_item_match(
  424. struct xfs_log_item *lip,
  425. uint64_t intent_id)
  426. {
  427. return ATTRI_ITEM(lip)->attri_format.alfi_id == intent_id;
  428. }
  429. /* Is this recovered ATTRI format ok? */
  430. static inline bool
  431. xfs_attri_validate(
  432. struct xfs_mount *mp,
  433. struct xfs_attri_log_format *attrp)
  434. {
  435. unsigned int op = attrp->alfi_op_flags &
  436. XFS_ATTRI_OP_FLAGS_TYPE_MASK;
  437. if (attrp->__pad != 0)
  438. return false;
  439. if (attrp->alfi_op_flags & ~XFS_ATTRI_OP_FLAGS_TYPE_MASK)
  440. return false;
  441. if (attrp->alfi_attr_filter & ~XFS_ATTRI_FILTER_MASK)
  442. return false;
  443. /* alfi_op_flags should be either a set or remove */
  444. switch (op) {
  445. case XFS_ATTRI_OP_FLAGS_SET:
  446. case XFS_ATTRI_OP_FLAGS_REPLACE:
  447. case XFS_ATTRI_OP_FLAGS_REMOVE:
  448. break;
  449. default:
  450. return false;
  451. }
  452. if (attrp->alfi_value_len > XATTR_SIZE_MAX)
  453. return false;
  454. if ((attrp->alfi_name_len > XATTR_NAME_MAX) ||
  455. (attrp->alfi_name_len == 0))
  456. return false;
  457. return xfs_verify_ino(mp, attrp->alfi_ino);
  458. }
  459. /*
  460. * Process an attr intent item that was recovered from the log. We need to
  461. * delete the attr that it describes.
  462. */
  463. STATIC int
  464. xfs_attri_item_recover(
  465. struct xfs_log_item *lip,
  466. struct list_head *capture_list)
  467. {
  468. struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip);
  469. struct xfs_attr_intent *attr;
  470. struct xfs_mount *mp = lip->li_log->l_mp;
  471. struct xfs_inode *ip;
  472. struct xfs_da_args *args;
  473. struct xfs_trans *tp;
  474. struct xfs_trans_res tres;
  475. struct xfs_attri_log_format *attrp;
  476. struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
  477. int error;
  478. int total;
  479. int local;
  480. struct xfs_attrd_log_item *done_item = NULL;
  481. /*
  482. * First check the validity of the attr described by the ATTRI. If any
  483. * are bad, then assume that all are bad and just toss the ATTRI.
  484. */
  485. attrp = &attrip->attri_format;
  486. if (!xfs_attri_validate(mp, attrp) ||
  487. !xfs_attr_namecheck(nv->name.i_addr, nv->name.i_len))
  488. return -EFSCORRUPTED;
  489. error = xlog_recover_iget(mp, attrp->alfi_ino, &ip);
  490. if (error)
  491. return error;
  492. attr = kmem_zalloc(sizeof(struct xfs_attr_intent) +
  493. sizeof(struct xfs_da_args), KM_NOFS);
  494. args = (struct xfs_da_args *)(attr + 1);
  495. attr->xattri_da_args = args;
  496. attr->xattri_op_flags = attrp->alfi_op_flags &
  497. XFS_ATTRI_OP_FLAGS_TYPE_MASK;
  498. /*
  499. * We're reconstructing the deferred work state structure from the
  500. * recovered log item. Grab a reference to the name/value buffer and
  501. * attach it to the new work state.
  502. */
  503. attr->xattri_nameval = xfs_attri_log_nameval_get(nv);
  504. ASSERT(attr->xattri_nameval);
  505. args->dp = ip;
  506. args->geo = mp->m_attr_geo;
  507. args->whichfork = XFS_ATTR_FORK;
  508. args->name = nv->name.i_addr;
  509. args->namelen = nv->name.i_len;
  510. args->hashval = xfs_da_hashname(args->name, args->namelen);
  511. args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
  512. args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
  513. XFS_DA_OP_LOGGED;
  514. ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
  515. switch (attr->xattri_op_flags) {
  516. case XFS_ATTRI_OP_FLAGS_SET:
  517. case XFS_ATTRI_OP_FLAGS_REPLACE:
  518. args->value = nv->value.i_addr;
  519. args->valuelen = nv->value.i_len;
  520. args->total = xfs_attr_calc_size(args, &local);
  521. if (xfs_inode_hasattr(args->dp))
  522. attr->xattri_dela_state = xfs_attr_init_replace_state(args);
  523. else
  524. attr->xattri_dela_state = xfs_attr_init_add_state(args);
  525. break;
  526. case XFS_ATTRI_OP_FLAGS_REMOVE:
  527. if (!xfs_inode_hasattr(args->dp))
  528. goto out;
  529. attr->xattri_dela_state = xfs_attr_init_remove_state(args);
  530. break;
  531. default:
  532. ASSERT(0);
  533. error = -EFSCORRUPTED;
  534. goto out;
  535. }
  536. xfs_init_attr_trans(args, &tres, &total);
  537. error = xfs_trans_alloc(mp, &tres, total, 0, XFS_TRANS_RESERVE, &tp);
  538. if (error)
  539. goto out;
  540. args->trans = tp;
  541. done_item = xfs_trans_get_attrd(tp, attrip);
  542. xfs_ilock(ip, XFS_ILOCK_EXCL);
  543. xfs_trans_ijoin(tp, ip, 0);
  544. error = xfs_xattri_finish_update(attr, done_item);
  545. if (error == -EAGAIN) {
  546. /*
  547. * There's more work to do, so add the intent item to this
  548. * transaction so that we can continue it later.
  549. */
  550. xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &attr->xattri_list);
  551. error = xfs_defer_ops_capture_and_commit(tp, capture_list);
  552. if (error)
  553. goto out_unlock;
  554. xfs_iunlock(ip, XFS_ILOCK_EXCL);
  555. xfs_irele(ip);
  556. return 0;
  557. }
  558. if (error) {
  559. xfs_trans_cancel(tp);
  560. goto out_unlock;
  561. }
  562. error = xfs_defer_ops_capture_and_commit(tp, capture_list);
  563. out_unlock:
  564. xfs_iunlock(ip, XFS_ILOCK_EXCL);
  565. xfs_irele(ip);
  566. out:
  567. xfs_attr_free_item(attr);
  568. return error;
  569. }
  570. /* Re-log an intent item to push the log tail forward. */
  571. static struct xfs_log_item *
  572. xfs_attri_item_relog(
  573. struct xfs_log_item *intent,
  574. struct xfs_trans *tp)
  575. {
  576. struct xfs_attrd_log_item *attrdp;
  577. struct xfs_attri_log_item *old_attrip;
  578. struct xfs_attri_log_item *new_attrip;
  579. struct xfs_attri_log_format *new_attrp;
  580. struct xfs_attri_log_format *old_attrp;
  581. old_attrip = ATTRI_ITEM(intent);
  582. old_attrp = &old_attrip->attri_format;
  583. tp->t_flags |= XFS_TRANS_DIRTY;
  584. attrdp = xfs_trans_get_attrd(tp, old_attrip);
  585. set_bit(XFS_LI_DIRTY, &attrdp->attrd_item.li_flags);
  586. /*
  587. * Create a new log item that shares the same name/value buffer as the
  588. * old log item.
  589. */
  590. new_attrip = xfs_attri_init(tp->t_mountp, old_attrip->attri_nameval);
  591. new_attrp = &new_attrip->attri_format;
  592. new_attrp->alfi_ino = old_attrp->alfi_ino;
  593. new_attrp->alfi_op_flags = old_attrp->alfi_op_flags;
  594. new_attrp->alfi_value_len = old_attrp->alfi_value_len;
  595. new_attrp->alfi_name_len = old_attrp->alfi_name_len;
  596. new_attrp->alfi_attr_filter = old_attrp->alfi_attr_filter;
  597. xfs_trans_add_item(tp, &new_attrip->attri_item);
  598. set_bit(XFS_LI_DIRTY, &new_attrip->attri_item.li_flags);
  599. return &new_attrip->attri_item;
  600. }
  601. STATIC int
  602. xlog_recover_attri_commit_pass2(
  603. struct xlog *log,
  604. struct list_head *buffer_list,
  605. struct xlog_recover_item *item,
  606. xfs_lsn_t lsn)
  607. {
  608. struct xfs_mount *mp = log->l_mp;
  609. struct xfs_attri_log_item *attrip;
  610. struct xfs_attri_log_format *attri_formatp;
  611. struct xfs_attri_log_nameval *nv;
  612. const void *attr_value = NULL;
  613. const void *attr_name;
  614. size_t len;
  615. attri_formatp = item->ri_buf[0].i_addr;
  616. attr_name = item->ri_buf[1].i_addr;
  617. /* Validate xfs_attri_log_format before the large memory allocation */
  618. len = sizeof(struct xfs_attri_log_format);
  619. if (item->ri_buf[0].i_len != len) {
  620. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
  621. item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
  622. return -EFSCORRUPTED;
  623. }
  624. if (!xfs_attri_validate(mp, attri_formatp)) {
  625. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
  626. item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
  627. return -EFSCORRUPTED;
  628. }
  629. /* Validate the attr name */
  630. if (item->ri_buf[1].i_len !=
  631. xlog_calc_iovec_len(attri_formatp->alfi_name_len)) {
  632. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
  633. item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
  634. return -EFSCORRUPTED;
  635. }
  636. if (!xfs_attr_namecheck(attr_name, attri_formatp->alfi_name_len)) {
  637. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
  638. item->ri_buf[1].i_addr, item->ri_buf[1].i_len);
  639. return -EFSCORRUPTED;
  640. }
  641. /* Validate the attr value, if present */
  642. if (attri_formatp->alfi_value_len != 0) {
  643. if (item->ri_buf[2].i_len != xlog_calc_iovec_len(attri_formatp->alfi_value_len)) {
  644. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
  645. item->ri_buf[0].i_addr,
  646. item->ri_buf[0].i_len);
  647. return -EFSCORRUPTED;
  648. }
  649. attr_value = item->ri_buf[2].i_addr;
  650. }
  651. /*
  652. * Memory alloc failure will cause replay to abort. We attach the
  653. * name/value buffer to the recovered incore log item and drop our
  654. * reference.
  655. */
  656. nv = xfs_attri_log_nameval_alloc(attr_name,
  657. attri_formatp->alfi_name_len, attr_value,
  658. attri_formatp->alfi_value_len);
  659. attrip = xfs_attri_init(mp, nv);
  660. memcpy(&attrip->attri_format, attri_formatp, len);
  661. /*
  662. * The ATTRI has two references. One for the ATTRD and one for ATTRI to
  663. * ensure it makes it into the AIL. Insert the ATTRI into the AIL
  664. * directly and drop the ATTRI reference. Note that
  665. * xfs_trans_ail_update() drops the AIL lock.
  666. */
  667. xfs_trans_ail_insert(log->l_ailp, &attrip->attri_item, lsn);
  668. xfs_attri_release(attrip);
  669. xfs_attri_log_nameval_put(nv);
  670. return 0;
  671. }
  672. /*
  673. * This routine is called to allocate an "attr free done" log item.
  674. */
  675. static struct xfs_attrd_log_item *
  676. xfs_trans_get_attrd(struct xfs_trans *tp,
  677. struct xfs_attri_log_item *attrip)
  678. {
  679. struct xfs_attrd_log_item *attrdp;
  680. ASSERT(tp != NULL);
  681. attrdp = kmem_cache_zalloc(xfs_attrd_cache, GFP_NOFS | __GFP_NOFAIL);
  682. xfs_log_item_init(tp->t_mountp, &attrdp->attrd_item, XFS_LI_ATTRD,
  683. &xfs_attrd_item_ops);
  684. attrdp->attrd_attrip = attrip;
  685. attrdp->attrd_format.alfd_alf_id = attrip->attri_format.alfi_id;
  686. xfs_trans_add_item(tp, &attrdp->attrd_item);
  687. return attrdp;
  688. }
  689. /* Get an ATTRD so we can process all the attrs. */
  690. static struct xfs_log_item *
  691. xfs_attr_create_done(
  692. struct xfs_trans *tp,
  693. struct xfs_log_item *intent,
  694. unsigned int count)
  695. {
  696. if (!intent)
  697. return NULL;
  698. return &xfs_trans_get_attrd(tp, ATTRI_ITEM(intent))->attrd_item;
  699. }
  700. const struct xfs_defer_op_type xfs_attr_defer_type = {
  701. .max_items = 1,
  702. .create_intent = xfs_attr_create_intent,
  703. .abort_intent = xfs_attr_abort_intent,
  704. .create_done = xfs_attr_create_done,
  705. .finish_item = xfs_attr_finish_item,
  706. .cancel_item = xfs_attr_cancel_item,
  707. };
  708. /*
  709. * This routine is called when an ATTRD format structure is found in a committed
  710. * transaction in the log. Its purpose is to cancel the corresponding ATTRI if
  711. * it was still in the log. To do this it searches the AIL for the ATTRI with
  712. * an id equal to that in the ATTRD format structure. If we find it we drop
  713. * the ATTRD reference, which removes the ATTRI from the AIL and frees it.
  714. */
  715. STATIC int
  716. xlog_recover_attrd_commit_pass2(
  717. struct xlog *log,
  718. struct list_head *buffer_list,
  719. struct xlog_recover_item *item,
  720. xfs_lsn_t lsn)
  721. {
  722. struct xfs_attrd_log_format *attrd_formatp;
  723. attrd_formatp = item->ri_buf[0].i_addr;
  724. if (item->ri_buf[0].i_len != sizeof(struct xfs_attrd_log_format)) {
  725. XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, log->l_mp,
  726. item->ri_buf[0].i_addr, item->ri_buf[0].i_len);
  727. return -EFSCORRUPTED;
  728. }
  729. xlog_recover_release_intent(log, XFS_LI_ATTRI,
  730. attrd_formatp->alfd_alf_id);
  731. return 0;
  732. }
  733. static const struct xfs_item_ops xfs_attri_item_ops = {
  734. .flags = XFS_ITEM_INTENT,
  735. .iop_size = xfs_attri_item_size,
  736. .iop_format = xfs_attri_item_format,
  737. .iop_unpin = xfs_attri_item_unpin,
  738. .iop_release = xfs_attri_item_release,
  739. .iop_recover = xfs_attri_item_recover,
  740. .iop_match = xfs_attri_item_match,
  741. .iop_relog = xfs_attri_item_relog,
  742. };
  743. const struct xlog_recover_item_ops xlog_attri_item_ops = {
  744. .item_type = XFS_LI_ATTRI,
  745. .commit_pass2 = xlog_recover_attri_commit_pass2,
  746. };
  747. static const struct xfs_item_ops xfs_attrd_item_ops = {
  748. .flags = XFS_ITEM_RELEASE_WHEN_COMMITTED |
  749. XFS_ITEM_INTENT_DONE,
  750. .iop_size = xfs_attrd_item_size,
  751. .iop_format = xfs_attrd_item_format,
  752. .iop_release = xfs_attrd_item_release,
  753. .iop_intent = xfs_attrd_item_intent,
  754. };
  755. const struct xlog_recover_item_ops xlog_attrd_item_ops = {
  756. .item_type = XFS_LI_ATTRD,
  757. .commit_pass2 = xlog_recover_attrd_commit_pass2,
  758. };