PageRenderTime 113ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 1ms

/fs/xfs/xfs_attr.c

https://bitbucket.org/evzijst/gittest
C | 2660 lines | 1750 code | 268 blank | 642 comment | 377 complexity | 3a9f8f69ef4e0203c1cddc99f3952426 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of version 2 of the GNU General Public License as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it would be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. *
  12. * Further, this software is distributed without any warranty that it is
  13. * free of the rightful claim of any third person regarding infringement
  14. * or the like. Any license provided herein, whether implied or
  15. * otherwise, applies only to this software file. Patent licenses, if
  16. * any, provided herein do not apply to combinations of this program with
  17. * other software, or any other product whatsoever.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write the Free Software Foundation, Inc., 59
  21. * Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22. *
  23. * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
  24. * Mountain View, CA 94043, or:
  25. *
  26. * http://www.sgi.com
  27. *
  28. * For further information regarding this notice, see:
  29. *
  30. * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  31. */
  32. #include "xfs.h"
  33. #include "xfs_macros.h"
  34. #include "xfs_types.h"
  35. #include "xfs_inum.h"
  36. #include "xfs_log.h"
  37. #include "xfs_trans.h"
  38. #include "xfs_sb.h"
  39. #include "xfs_ag.h"
  40. #include "xfs_dir.h"
  41. #include "xfs_dir2.h"
  42. #include "xfs_dmapi.h"
  43. #include "xfs_mount.h"
  44. #include "xfs_alloc_btree.h"
  45. #include "xfs_bmap_btree.h"
  46. #include "xfs_ialloc_btree.h"
  47. #include "xfs_alloc.h"
  48. #include "xfs_btree.h"
  49. #include "xfs_attr_sf.h"
  50. #include "xfs_dir_sf.h"
  51. #include "xfs_dir2_sf.h"
  52. #include "xfs_dinode.h"
  53. #include "xfs_inode_item.h"
  54. #include "xfs_inode.h"
  55. #include "xfs_bmap.h"
  56. #include "xfs_da_btree.h"
  57. #include "xfs_attr.h"
  58. #include "xfs_attr_leaf.h"
  59. #include "xfs_error.h"
  60. #include "xfs_bit.h"
  61. #include "xfs_quota.h"
  62. #include "xfs_rw.h"
  63. #include "xfs_trans_space.h"
  64. #include "xfs_acl.h"
  65. /*
  66. * xfs_attr.c
  67. *
  68. * Provide the external interfaces to manage attribute lists.
  69. */
  70. /*========================================================================
  71. * Function prototypes for the kernel.
  72. *========================================================================*/
  73. /*
  74. * Internal routines when attribute list fits inside the inode.
  75. */
  76. STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
  77. /*
  78. * Internal routines when attribute list is one block.
  79. */
  80. STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
  81. STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
  82. STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
  83. /*
  84. * Internal routines when attribute list is more than one block.
  85. */
  86. STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
  87. STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
  88. STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
  89. STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
  90. STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
  91. /*
  92. * Routines to manipulate out-of-line attribute values.
  93. */
  94. STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args);
  95. STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
  96. STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
  97. #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */
  98. #if defined(XFS_ATTR_TRACE)
  99. ktrace_t *xfs_attr_trace_buf;
  100. #endif
  101. /*========================================================================
  102. * Overall external interface routines.
  103. *========================================================================*/
  104. int
  105. xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen,
  106. char *value, int *valuelenp, int flags, struct cred *cred)
  107. {
  108. xfs_da_args_t args;
  109. int error;
  110. if ((XFS_IFORK_Q(ip) == 0) ||
  111. (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  112. ip->i_d.di_anextents == 0))
  113. return(ENOATTR);
  114. if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) {
  115. if ((error = xfs_iaccess(ip, S_IRUSR, cred)))
  116. return(XFS_ERROR(error));
  117. }
  118. /*
  119. * Fill in the arg structure for this request.
  120. */
  121. memset((char *)&args, 0, sizeof(args));
  122. args.name = name;
  123. args.namelen = namelen;
  124. args.value = value;
  125. args.valuelen = *valuelenp;
  126. args.flags = flags;
  127. args.hashval = xfs_da_hashname(args.name, args.namelen);
  128. args.dp = ip;
  129. args.whichfork = XFS_ATTR_FORK;
  130. /*
  131. * Decide on what work routines to call based on the inode size.
  132. */
  133. if (XFS_IFORK_Q(ip) == 0 ||
  134. (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  135. ip->i_d.di_anextents == 0)) {
  136. error = XFS_ERROR(ENOATTR);
  137. } else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
  138. error = xfs_attr_shortform_getvalue(&args);
  139. } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
  140. error = xfs_attr_leaf_get(&args);
  141. } else {
  142. error = xfs_attr_node_get(&args);
  143. }
  144. /*
  145. * Return the number of bytes in the value to the caller.
  146. */
  147. *valuelenp = args.valuelen;
  148. if (error == EEXIST)
  149. error = 0;
  150. return(error);
  151. }
  152. int
  153. xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
  154. int flags, struct cred *cred)
  155. {
  156. xfs_inode_t *ip = XFS_BHVTOI(bdp);
  157. int error, namelen;
  158. XFS_STATS_INC(xs_attr_get);
  159. if (!name)
  160. return(EINVAL);
  161. namelen = strlen(name);
  162. if (namelen >= MAXNAMELEN)
  163. return(EFAULT); /* match IRIX behaviour */
  164. if (XFS_FORCED_SHUTDOWN(ip->i_mount))
  165. return(EIO);
  166. xfs_ilock(ip, XFS_ILOCK_SHARED);
  167. error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
  168. xfs_iunlock(ip, XFS_ILOCK_SHARED);
  169. return(error);
  170. }
  171. /*ARGSUSED*/
  172. int /* error */
  173. xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
  174. struct cred *cred)
  175. {
  176. xfs_da_args_t args;
  177. xfs_inode_t *dp;
  178. xfs_fsblock_t firstblock;
  179. xfs_bmap_free_t flist;
  180. int error, err2, committed;
  181. int local, size;
  182. uint nblks;
  183. xfs_mount_t *mp;
  184. int rsvd = (flags & ATTR_ROOT) != 0;
  185. int namelen;
  186. namelen = strlen(name);
  187. if (namelen >= MAXNAMELEN)
  188. return EFAULT; /* match IRIX behaviour */
  189. XFS_STATS_INC(xs_attr_set);
  190. dp = XFS_BHVTOI(bdp);
  191. mp = dp->i_mount;
  192. if (XFS_FORCED_SHUTDOWN(mp))
  193. return (EIO);
  194. xfs_ilock(dp, XFS_ILOCK_SHARED);
  195. if (!(flags & ATTR_SECURE) &&
  196. (error = xfs_iaccess(dp, S_IWUSR, cred))) {
  197. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  198. return(XFS_ERROR(error));
  199. }
  200. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  201. /*
  202. * Attach the dquots to the inode.
  203. */
  204. if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
  205. return (error);
  206. /*
  207. * If the inode doesn't have an attribute fork, add one.
  208. * (inode must not be locked when we call this routine)
  209. */
  210. if (XFS_IFORK_Q(dp) == 0) {
  211. error = xfs_bmap_add_attrfork(dp, rsvd);
  212. if (error)
  213. return(error);
  214. }
  215. /*
  216. * Fill in the arg structure for this request.
  217. */
  218. memset((char *)&args, 0, sizeof(args));
  219. args.name = name;
  220. args.namelen = namelen;
  221. args.value = value;
  222. args.valuelen = valuelen;
  223. args.flags = flags;
  224. args.hashval = xfs_da_hashname(args.name, args.namelen);
  225. args.dp = dp;
  226. args.firstblock = &firstblock;
  227. args.flist = &flist;
  228. args.whichfork = XFS_ATTR_FORK;
  229. args.oknoent = 1;
  230. /* Determine space new attribute will use, and if it will be inline
  231. * or out of line.
  232. */
  233. size = xfs_attr_leaf_newentsize(&args, mp->m_sb.sb_blocksize, &local);
  234. nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
  235. if (local) {
  236. if (size > (mp->m_sb.sb_blocksize >> 1)) {
  237. /* Double split possible */
  238. nblks <<= 1;
  239. }
  240. } else {
  241. uint dblocks = XFS_B_TO_FSB(mp, valuelen);
  242. /* Out of line attribute, cannot double split, but make
  243. * room for the attribute value itself.
  244. */
  245. nblks += dblocks;
  246. nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
  247. }
  248. /* Size is now blocks for attribute data */
  249. args.total = nblks;
  250. /*
  251. * Start our first transaction of the day.
  252. *
  253. * All future transactions during this code must be "chained" off
  254. * this one via the trans_dup() call. All transactions will contain
  255. * the inode, and the inode will always be marked with trans_ihold().
  256. * Since the inode will be locked in all transactions, we must log
  257. * the inode in every transaction to let it float upward through
  258. * the log.
  259. */
  260. args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET);
  261. /*
  262. * Root fork attributes can use reserved data blocks for this
  263. * operation if necessary
  264. */
  265. if (rsvd)
  266. args.trans->t_flags |= XFS_TRANS_RESERVE;
  267. if ((error = xfs_trans_reserve(args.trans, (uint) nblks,
  268. XFS_ATTRSET_LOG_RES(mp, nblks),
  269. 0, XFS_TRANS_PERM_LOG_RES,
  270. XFS_ATTRSET_LOG_COUNT))) {
  271. xfs_trans_cancel(args.trans, 0);
  272. return(error);
  273. }
  274. xfs_ilock(dp, XFS_ILOCK_EXCL);
  275. error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0,
  276. rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
  277. XFS_QMOPT_RES_REGBLKS);
  278. if (error) {
  279. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  280. xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
  281. return (error);
  282. }
  283. xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
  284. xfs_trans_ihold(args.trans, dp);
  285. /*
  286. * If the attribute list is non-existant or a shortform list,
  287. * upgrade it to a single-leaf-block attribute list.
  288. */
  289. if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
  290. ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) &&
  291. (dp->i_d.di_anextents == 0))) {
  292. /*
  293. * Build initial attribute list (if required).
  294. */
  295. if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
  296. (void)xfs_attr_shortform_create(&args);
  297. /*
  298. * Try to add the attr to the attribute list in
  299. * the inode.
  300. */
  301. error = xfs_attr_shortform_addname(&args);
  302. if (error != ENOSPC) {
  303. /*
  304. * Commit the shortform mods, and we're done.
  305. * NOTE: this is also the error path (EEXIST, etc).
  306. */
  307. ASSERT(args.trans != NULL);
  308. /*
  309. * If this is a synchronous mount, make sure that
  310. * the transaction goes to disk before returning
  311. * to the user.
  312. */
  313. if (mp->m_flags & XFS_MOUNT_WSYNC) {
  314. xfs_trans_set_sync(args.trans);
  315. }
  316. err2 = xfs_trans_commit(args.trans,
  317. XFS_TRANS_RELEASE_LOG_RES,
  318. NULL);
  319. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  320. /*
  321. * Hit the inode change time.
  322. */
  323. if (!error && (flags & ATTR_KERNOTIME) == 0) {
  324. xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
  325. }
  326. return(error == 0 ? err2 : error);
  327. }
  328. /*
  329. * It won't fit in the shortform, transform to a leaf block.
  330. * GROT: another possible req'mt for a double-split btree op.
  331. */
  332. XFS_BMAP_INIT(args.flist, args.firstblock);
  333. error = xfs_attr_shortform_to_leaf(&args);
  334. if (!error) {
  335. error = xfs_bmap_finish(&args.trans, args.flist,
  336. *args.firstblock, &committed);
  337. }
  338. if (error) {
  339. ASSERT(committed);
  340. args.trans = NULL;
  341. xfs_bmap_cancel(&flist);
  342. goto out;
  343. }
  344. /*
  345. * bmap_finish() may have committed the last trans and started
  346. * a new one. We need the inode to be in all transactions.
  347. */
  348. if (committed) {
  349. xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
  350. xfs_trans_ihold(args.trans, dp);
  351. }
  352. /*
  353. * Commit the leaf transformation. We'll need another (linked)
  354. * transaction to add the new attribute to the leaf.
  355. */
  356. if ((error = xfs_attr_rolltrans(&args.trans, dp)))
  357. goto out;
  358. }
  359. if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
  360. error = xfs_attr_leaf_addname(&args);
  361. } else {
  362. error = xfs_attr_node_addname(&args);
  363. }
  364. if (error) {
  365. goto out;
  366. }
  367. /*
  368. * If this is a synchronous mount, make sure that the
  369. * transaction goes to disk before returning to the user.
  370. */
  371. if (mp->m_flags & XFS_MOUNT_WSYNC) {
  372. xfs_trans_set_sync(args.trans);
  373. }
  374. /*
  375. * Commit the last in the sequence of transactions.
  376. */
  377. xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
  378. error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
  379. NULL);
  380. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  381. /*
  382. * Hit the inode change time.
  383. */
  384. if (!error && (flags & ATTR_KERNOTIME) == 0) {
  385. xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
  386. }
  387. return(error);
  388. out:
  389. if (args.trans)
  390. xfs_trans_cancel(args.trans,
  391. XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
  392. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  393. return(error);
  394. }
  395. /*
  396. * Generic handler routine to remove a name from an attribute list.
  397. * Transitions attribute list from Btree to shortform as necessary.
  398. */
  399. /*ARGSUSED*/
  400. int /* error */
  401. xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred)
  402. {
  403. xfs_da_args_t args;
  404. xfs_inode_t *dp;
  405. xfs_fsblock_t firstblock;
  406. xfs_bmap_free_t flist;
  407. int error;
  408. xfs_mount_t *mp;
  409. int namelen;
  410. ASSERT(MAXNAMELEN-1<=0xff); /* length is stored in uint8 */
  411. namelen = strlen(name);
  412. if (namelen>=MAXNAMELEN)
  413. return EFAULT; /* match irix behaviour */
  414. XFS_STATS_INC(xs_attr_remove);
  415. dp = XFS_BHVTOI(bdp);
  416. mp = dp->i_mount;
  417. if (XFS_FORCED_SHUTDOWN(mp))
  418. return (EIO);
  419. xfs_ilock(dp, XFS_ILOCK_SHARED);
  420. if (!(flags & ATTR_SECURE) &&
  421. (error = xfs_iaccess(dp, S_IWUSR, cred))) {
  422. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  423. return(XFS_ERROR(error));
  424. } else if (XFS_IFORK_Q(dp) == 0 ||
  425. (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  426. dp->i_d.di_anextents == 0)) {
  427. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  428. return(XFS_ERROR(ENOATTR));
  429. }
  430. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  431. /*
  432. * Fill in the arg structure for this request.
  433. */
  434. memset((char *)&args, 0, sizeof(args));
  435. args.name = name;
  436. args.namelen = namelen;
  437. args.flags = flags;
  438. args.hashval = xfs_da_hashname(args.name, args.namelen);
  439. args.dp = dp;
  440. args.firstblock = &firstblock;
  441. args.flist = &flist;
  442. args.total = 0;
  443. args.whichfork = XFS_ATTR_FORK;
  444. /*
  445. * Attach the dquots to the inode.
  446. */
  447. if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
  448. return (error);
  449. /*
  450. * Start our first transaction of the day.
  451. *
  452. * All future transactions during this code must be "chained" off
  453. * this one via the trans_dup() call. All transactions will contain
  454. * the inode, and the inode will always be marked with trans_ihold().
  455. * Since the inode will be locked in all transactions, we must log
  456. * the inode in every transaction to let it float upward through
  457. * the log.
  458. */
  459. args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
  460. /*
  461. * Root fork attributes can use reserved data blocks for this
  462. * operation if necessary
  463. */
  464. if (flags & ATTR_ROOT)
  465. args.trans->t_flags |= XFS_TRANS_RESERVE;
  466. if ((error = xfs_trans_reserve(args.trans,
  467. XFS_ATTRRM_SPACE_RES(mp),
  468. XFS_ATTRRM_LOG_RES(mp),
  469. 0, XFS_TRANS_PERM_LOG_RES,
  470. XFS_ATTRRM_LOG_COUNT))) {
  471. xfs_trans_cancel(args.trans, 0);
  472. return(error);
  473. }
  474. xfs_ilock(dp, XFS_ILOCK_EXCL);
  475. /*
  476. * No need to make quota reservations here. We expect to release some
  477. * blocks not allocate in the common case.
  478. */
  479. xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
  480. xfs_trans_ihold(args.trans, dp);
  481. /*
  482. * Decide on what work routines to call based on the inode size.
  483. */
  484. if (XFS_IFORK_Q(dp) == 0 ||
  485. (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  486. dp->i_d.di_anextents == 0)) {
  487. error = XFS_ERROR(ENOATTR);
  488. goto out;
  489. }
  490. if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
  491. ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
  492. error = xfs_attr_shortform_remove(&args);
  493. if (error) {
  494. goto out;
  495. }
  496. } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
  497. error = xfs_attr_leaf_removename(&args);
  498. } else {
  499. error = xfs_attr_node_removename(&args);
  500. }
  501. if (error) {
  502. goto out;
  503. }
  504. /*
  505. * If this is a synchronous mount, make sure that the
  506. * transaction goes to disk before returning to the user.
  507. */
  508. if (mp->m_flags & XFS_MOUNT_WSYNC) {
  509. xfs_trans_set_sync(args.trans);
  510. }
  511. /*
  512. * Commit the last in the sequence of transactions.
  513. */
  514. xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
  515. error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
  516. NULL);
  517. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  518. /*
  519. * Hit the inode change time.
  520. */
  521. if (!error && (flags & ATTR_KERNOTIME) == 0) {
  522. xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
  523. }
  524. return(error);
  525. out:
  526. if (args.trans)
  527. xfs_trans_cancel(args.trans,
  528. XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
  529. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  530. return(error);
  531. }
  532. /*
  533. * Generate a list of extended attribute names and optionally
  534. * also value lengths. Positive return value follows the XFS
  535. * convention of being an error, zero or negative return code
  536. * is the length of the buffer returned (negated), indicating
  537. * success.
  538. */
  539. int
  540. xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
  541. attrlist_cursor_kern_t *cursor, struct cred *cred)
  542. {
  543. xfs_attr_list_context_t context;
  544. xfs_inode_t *dp;
  545. int error;
  546. XFS_STATS_INC(xs_attr_list);
  547. /*
  548. * Validate the cursor.
  549. */
  550. if (cursor->pad1 || cursor->pad2)
  551. return(XFS_ERROR(EINVAL));
  552. if ((cursor->initted == 0) &&
  553. (cursor->hashval || cursor->blkno || cursor->offset))
  554. return(XFS_ERROR(EINVAL));
  555. /*
  556. * Check for a properly aligned buffer.
  557. */
  558. if (((long)buffer) & (sizeof(int)-1))
  559. return(XFS_ERROR(EFAULT));
  560. if (flags & ATTR_KERNOVAL)
  561. bufsize = 0;
  562. /*
  563. * Initialize the output buffer.
  564. */
  565. context.dp = dp = XFS_BHVTOI(bdp);
  566. context.cursor = cursor;
  567. context.count = 0;
  568. context.dupcnt = 0;
  569. context.resynch = 1;
  570. context.flags = flags;
  571. if (!(flags & ATTR_KERNAMELS)) {
  572. context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
  573. context.firstu = context.bufsize;
  574. context.alist = (attrlist_t *)buffer;
  575. context.alist->al_count = 0;
  576. context.alist->al_more = 0;
  577. context.alist->al_offset[0] = context.bufsize;
  578. }
  579. else {
  580. context.bufsize = bufsize;
  581. context.firstu = context.bufsize;
  582. context.alist = (attrlist_t *)buffer;
  583. }
  584. if (XFS_FORCED_SHUTDOWN(dp->i_mount))
  585. return (EIO);
  586. xfs_ilock(dp, XFS_ILOCK_SHARED);
  587. if (!(flags & ATTR_SECURE) &&
  588. (error = xfs_iaccess(dp, S_IRUSR, cred))) {
  589. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  590. return(XFS_ERROR(error));
  591. }
  592. /*
  593. * Decide on what work routines to call based on the inode size.
  594. */
  595. xfs_attr_trace_l_c("syscall start", &context);
  596. if (XFS_IFORK_Q(dp) == 0 ||
  597. (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  598. dp->i_d.di_anextents == 0)) {
  599. error = 0;
  600. } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
  601. error = xfs_attr_shortform_list(&context);
  602. } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
  603. error = xfs_attr_leaf_list(&context);
  604. } else {
  605. error = xfs_attr_node_list(&context);
  606. }
  607. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  608. xfs_attr_trace_l_c("syscall end", &context);
  609. if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) {
  610. ASSERT(error >= 0);
  611. }
  612. else { /* must return negated buffer size or the error */
  613. if (context.count < 0)
  614. error = XFS_ERROR(ERANGE);
  615. else
  616. error = -context.count;
  617. }
  618. return(error);
  619. }
  620. int /* error */
  621. xfs_attr_inactive(xfs_inode_t *dp)
  622. {
  623. xfs_trans_t *trans;
  624. xfs_mount_t *mp;
  625. int error;
  626. mp = dp->i_mount;
  627. ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
  628. xfs_ilock(dp, XFS_ILOCK_SHARED);
  629. if ((XFS_IFORK_Q(dp) == 0) ||
  630. (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
  631. (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  632. dp->i_d.di_anextents == 0)) {
  633. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  634. return(0);
  635. }
  636. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  637. /*
  638. * Start our first transaction of the day.
  639. *
  640. * All future transactions during this code must be "chained" off
  641. * this one via the trans_dup() call. All transactions will contain
  642. * the inode, and the inode will always be marked with trans_ihold().
  643. * Since the inode will be locked in all transactions, we must log
  644. * the inode in every transaction to let it float upward through
  645. * the log.
  646. */
  647. trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
  648. if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0,
  649. XFS_TRANS_PERM_LOG_RES,
  650. XFS_ATTRINVAL_LOG_COUNT))) {
  651. xfs_trans_cancel(trans, 0);
  652. return(error);
  653. }
  654. xfs_ilock(dp, XFS_ILOCK_EXCL);
  655. /*
  656. * No need to make quota reservations here. We expect to release some
  657. * blocks, not allocate, in the common case.
  658. */
  659. xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL);
  660. xfs_trans_ihold(trans, dp);
  661. /*
  662. * Decide on what work routines to call based on the inode size.
  663. */
  664. if ((XFS_IFORK_Q(dp) == 0) ||
  665. (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
  666. (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
  667. dp->i_d.di_anextents == 0)) {
  668. error = 0;
  669. goto out;
  670. }
  671. error = xfs_attr_root_inactive(&trans, dp);
  672. if (error)
  673. goto out;
  674. /*
  675. * signal synchronous inactive transactions unless this
  676. * is a synchronous mount filesystem in which case we
  677. * know that we're here because we've been called out of
  678. * xfs_inactive which means that the last reference is gone
  679. * and the unlink transaction has already hit the disk so
  680. * async inactive transactions are safe.
  681. */
  682. if ((error = xfs_itruncate_finish(&trans, dp, 0LL, XFS_ATTR_FORK,
  683. (!(mp->m_flags & XFS_MOUNT_WSYNC)
  684. ? 1 : 0))))
  685. goto out;
  686. /*
  687. * Commit the last in the sequence of transactions.
  688. */
  689. xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
  690. error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES,
  691. NULL);
  692. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  693. return(error);
  694. out:
  695. xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
  696. xfs_iunlock(dp, XFS_ILOCK_EXCL);
  697. return(error);
  698. }
  699. /*========================================================================
  700. * External routines when attribute list is inside the inode
  701. *========================================================================*/
  702. /*
  703. * Add a name to the shortform attribute list structure
  704. * This is the external routine.
  705. */
  706. STATIC int
  707. xfs_attr_shortform_addname(xfs_da_args_t *args)
  708. {
  709. int newsize, retval;
  710. retval = xfs_attr_shortform_lookup(args);
  711. if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
  712. return(retval);
  713. } else if (retval == EEXIST) {
  714. if (args->flags & ATTR_CREATE)
  715. return(retval);
  716. retval = xfs_attr_shortform_remove(args);
  717. ASSERT(retval == 0);
  718. }
  719. newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
  720. newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
  721. if ((newsize <= XFS_IFORK_ASIZE(args->dp)) &&
  722. (args->namelen < XFS_ATTR_SF_ENTSIZE_MAX) &&
  723. (args->valuelen < XFS_ATTR_SF_ENTSIZE_MAX)) {
  724. retval = xfs_attr_shortform_add(args);
  725. ASSERT(retval == 0);
  726. } else {
  727. return(XFS_ERROR(ENOSPC));
  728. }
  729. return(0);
  730. }
  731. /*========================================================================
  732. * External routines when attribute list is one block
  733. *========================================================================*/
  734. /*
  735. * Add a name to the leaf attribute list structure
  736. *
  737. * This leaf block cannot have a "remote" value, we only call this routine
  738. * if bmap_one_block() says there is only one block (ie: no remote blks).
  739. */
  740. int
  741. xfs_attr_leaf_addname(xfs_da_args_t *args)
  742. {
  743. xfs_inode_t *dp;
  744. xfs_dabuf_t *bp;
  745. int retval, error, committed;
  746. /*
  747. * Read the (only) block in the attribute list in.
  748. */
  749. dp = args->dp;
  750. args->blkno = 0;
  751. error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
  752. XFS_ATTR_FORK);
  753. if (error)
  754. return(error);
  755. ASSERT(bp != NULL);
  756. /*
  757. * Look up the given attribute in the leaf block. Figure out if
  758. * the given flags produce an error or call for an atomic rename.
  759. */
  760. retval = xfs_attr_leaf_lookup_int(bp, args);
  761. if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
  762. xfs_da_brelse(args->trans, bp);
  763. return(retval);
  764. } else if (retval == EEXIST) {
  765. if (args->flags & ATTR_CREATE) { /* pure create op */
  766. xfs_da_brelse(args->trans, bp);
  767. return(retval);
  768. }
  769. args->rename = 1; /* an atomic rename */
  770. args->blkno2 = args->blkno; /* set 2nd entry info*/
  771. args->index2 = args->index;
  772. args->rmtblkno2 = args->rmtblkno;
  773. args->rmtblkcnt2 = args->rmtblkcnt;
  774. }
  775. /*
  776. * Add the attribute to the leaf block, transitioning to a Btree
  777. * if required.
  778. */
  779. retval = xfs_attr_leaf_add(bp, args);
  780. xfs_da_buf_done(bp);
  781. if (retval == ENOSPC) {
  782. /*
  783. * Promote the attribute list to the Btree format, then
  784. * Commit that transaction so that the node_addname() call
  785. * can manage its own transactions.
  786. */
  787. XFS_BMAP_INIT(args->flist, args->firstblock);
  788. error = xfs_attr_leaf_to_node(args);
  789. if (!error) {
  790. error = xfs_bmap_finish(&args->trans, args->flist,
  791. *args->firstblock, &committed);
  792. }
  793. if (error) {
  794. ASSERT(committed);
  795. args->trans = NULL;
  796. xfs_bmap_cancel(args->flist);
  797. return(error);
  798. }
  799. /*
  800. * bmap_finish() may have committed the last trans and started
  801. * a new one. We need the inode to be in all transactions.
  802. */
  803. if (committed) {
  804. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  805. xfs_trans_ihold(args->trans, dp);
  806. }
  807. /*
  808. * Commit the current trans (including the inode) and start
  809. * a new one.
  810. */
  811. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  812. return (error);
  813. /*
  814. * Fob the whole rest of the problem off on the Btree code.
  815. */
  816. error = xfs_attr_node_addname(args);
  817. return(error);
  818. }
  819. /*
  820. * Commit the transaction that added the attr name so that
  821. * later routines can manage their own transactions.
  822. */
  823. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  824. return (error);
  825. /*
  826. * If there was an out-of-line value, allocate the blocks we
  827. * identified for its storage and copy the value. This is done
  828. * after we create the attribute so that we don't overflow the
  829. * maximum size of a transaction and/or hit a deadlock.
  830. */
  831. if (args->rmtblkno > 0) {
  832. error = xfs_attr_rmtval_set(args);
  833. if (error)
  834. return(error);
  835. }
  836. /*
  837. * If this is an atomic rename operation, we must "flip" the
  838. * incomplete flags on the "new" and "old" attribute/value pairs
  839. * so that one disappears and one appears atomically. Then we
  840. * must remove the "old" attribute/value pair.
  841. */
  842. if (args->rename) {
  843. /*
  844. * In a separate transaction, set the incomplete flag on the
  845. * "old" attr and clear the incomplete flag on the "new" attr.
  846. */
  847. error = xfs_attr_leaf_flipflags(args);
  848. if (error)
  849. return(error);
  850. /*
  851. * Dismantle the "old" attribute/value pair by removing
  852. * a "remote" value (if it exists).
  853. */
  854. args->index = args->index2;
  855. args->blkno = args->blkno2;
  856. args->rmtblkno = args->rmtblkno2;
  857. args->rmtblkcnt = args->rmtblkcnt2;
  858. if (args->rmtblkno) {
  859. error = xfs_attr_rmtval_remove(args);
  860. if (error)
  861. return(error);
  862. }
  863. /*
  864. * Read in the block containing the "old" attr, then
  865. * remove the "old" attr from that block (neat, huh!)
  866. */
  867. error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
  868. &bp, XFS_ATTR_FORK);
  869. if (error)
  870. return(error);
  871. ASSERT(bp != NULL);
  872. (void)xfs_attr_leaf_remove(bp, args);
  873. /*
  874. * If the result is small enough, shrink it all into the inode.
  875. */
  876. if (xfs_attr_shortform_allfit(bp, dp)) {
  877. XFS_BMAP_INIT(args->flist, args->firstblock);
  878. error = xfs_attr_leaf_to_shortform(bp, args);
  879. /* bp is gone due to xfs_da_shrink_inode */
  880. if (!error) {
  881. error = xfs_bmap_finish(&args->trans,
  882. args->flist,
  883. *args->firstblock,
  884. &committed);
  885. }
  886. if (error) {
  887. ASSERT(committed);
  888. args->trans = NULL;
  889. xfs_bmap_cancel(args->flist);
  890. return(error);
  891. }
  892. /*
  893. * bmap_finish() may have committed the last trans
  894. * and started a new one. We need the inode to be
  895. * in all transactions.
  896. */
  897. if (committed) {
  898. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  899. xfs_trans_ihold(args->trans, dp);
  900. }
  901. } else
  902. xfs_da_buf_done(bp);
  903. /*
  904. * Commit the remove and start the next trans in series.
  905. */
  906. error = xfs_attr_rolltrans(&args->trans, dp);
  907. } else if (args->rmtblkno > 0) {
  908. /*
  909. * Added a "remote" value, just clear the incomplete flag.
  910. */
  911. error = xfs_attr_leaf_clearflag(args);
  912. }
  913. return(error);
  914. }
  915. /*
  916. * Remove a name from the leaf attribute list structure
  917. *
  918. * This leaf block cannot have a "remote" value, we only call this routine
  919. * if bmap_one_block() says there is only one block (ie: no remote blks).
  920. */
  921. STATIC int
  922. xfs_attr_leaf_removename(xfs_da_args_t *args)
  923. {
  924. xfs_inode_t *dp;
  925. xfs_dabuf_t *bp;
  926. int committed;
  927. int error;
  928. /*
  929. * Remove the attribute.
  930. */
  931. dp = args->dp;
  932. args->blkno = 0;
  933. error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
  934. XFS_ATTR_FORK);
  935. if (error) {
  936. return(error);
  937. }
  938. ASSERT(bp != NULL);
  939. error = xfs_attr_leaf_lookup_int(bp, args);
  940. if (error == ENOATTR) {
  941. xfs_da_brelse(args->trans, bp);
  942. return(error);
  943. }
  944. (void)xfs_attr_leaf_remove(bp, args);
  945. /*
  946. * If the result is small enough, shrink it all into the inode.
  947. */
  948. if (xfs_attr_shortform_allfit(bp, dp)) {
  949. XFS_BMAP_INIT(args->flist, args->firstblock);
  950. error = xfs_attr_leaf_to_shortform(bp, args);
  951. /* bp is gone due to xfs_da_shrink_inode */
  952. if (!error) {
  953. error = xfs_bmap_finish(&args->trans, args->flist,
  954. *args->firstblock, &committed);
  955. }
  956. if (error) {
  957. ASSERT(committed);
  958. args->trans = NULL;
  959. xfs_bmap_cancel(args->flist);
  960. return(error);
  961. }
  962. /*
  963. * bmap_finish() may have committed the last trans and started
  964. * a new one. We need the inode to be in all transactions.
  965. */
  966. if (committed) {
  967. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  968. xfs_trans_ihold(args->trans, dp);
  969. }
  970. } else
  971. xfs_da_buf_done(bp);
  972. return(0);
  973. }
  974. /*
  975. * Look up a name in a leaf attribute list structure.
  976. *
  977. * This leaf block cannot have a "remote" value, we only call this routine
  978. * if bmap_one_block() says there is only one block (ie: no remote blks).
  979. */
  980. int
  981. xfs_attr_leaf_get(xfs_da_args_t *args)
  982. {
  983. xfs_dabuf_t *bp;
  984. int error;
  985. args->blkno = 0;
  986. error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
  987. XFS_ATTR_FORK);
  988. if (error)
  989. return(error);
  990. ASSERT(bp != NULL);
  991. error = xfs_attr_leaf_lookup_int(bp, args);
  992. if (error != EEXIST) {
  993. xfs_da_brelse(args->trans, bp);
  994. return(error);
  995. }
  996. error = xfs_attr_leaf_getvalue(bp, args);
  997. xfs_da_brelse(args->trans, bp);
  998. if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
  999. error = xfs_attr_rmtval_get(args);
  1000. }
  1001. return(error);
  1002. }
  1003. /*
  1004. * Copy out attribute entries for attr_list(), for leaf attribute lists.
  1005. */
  1006. STATIC int
  1007. xfs_attr_leaf_list(xfs_attr_list_context_t *context)
  1008. {
  1009. xfs_attr_leafblock_t *leaf;
  1010. int error;
  1011. xfs_dabuf_t *bp;
  1012. context->cursor->blkno = 0;
  1013. error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
  1014. if (error)
  1015. return(error);
  1016. ASSERT(bp != NULL);
  1017. leaf = bp->data;
  1018. if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
  1019. != XFS_ATTR_LEAF_MAGIC)) {
  1020. XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
  1021. context->dp->i_mount, leaf);
  1022. xfs_da_brelse(NULL, bp);
  1023. return(XFS_ERROR(EFSCORRUPTED));
  1024. }
  1025. (void)xfs_attr_leaf_list_int(bp, context);
  1026. xfs_da_brelse(NULL, bp);
  1027. return(0);
  1028. }
  1029. /*========================================================================
  1030. * External routines when attribute list size > XFS_LBSIZE(mp).
  1031. *========================================================================*/
  1032. /*
  1033. * Add a name to a Btree-format attribute list.
  1034. *
  1035. * This will involve walking down the Btree, and may involve splitting
  1036. * leaf nodes and even splitting intermediate nodes up to and including
  1037. * the root node (a special case of an intermediate node).
  1038. *
  1039. * "Remote" attribute values confuse the issue and atomic rename operations
  1040. * add a whole extra layer of confusion on top of that.
  1041. */
  1042. STATIC int
  1043. xfs_attr_node_addname(xfs_da_args_t *args)
  1044. {
  1045. xfs_da_state_t *state;
  1046. xfs_da_state_blk_t *blk;
  1047. xfs_inode_t *dp;
  1048. xfs_mount_t *mp;
  1049. int committed, retval, error;
  1050. /*
  1051. * Fill in bucket of arguments/results/context to carry around.
  1052. */
  1053. dp = args->dp;
  1054. mp = dp->i_mount;
  1055. restart:
  1056. state = xfs_da_state_alloc();
  1057. state->args = args;
  1058. state->mp = mp;
  1059. state->blocksize = state->mp->m_sb.sb_blocksize;
  1060. state->node_ents = state->mp->m_attr_node_ents;
  1061. /*
  1062. * Search to see if name already exists, and get back a pointer
  1063. * to where it should go.
  1064. */
  1065. error = xfs_da_node_lookup_int(state, &retval);
  1066. if (error)
  1067. goto out;
  1068. blk = &state->path.blk[ state->path.active-1 ];
  1069. ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
  1070. if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
  1071. goto out;
  1072. } else if (retval == EEXIST) {
  1073. if (args->flags & ATTR_CREATE)
  1074. goto out;
  1075. args->rename = 1; /* atomic rename op */
  1076. args->blkno2 = args->blkno; /* set 2nd entry info*/
  1077. args->index2 = args->index;
  1078. args->rmtblkno2 = args->rmtblkno;
  1079. args->rmtblkcnt2 = args->rmtblkcnt;
  1080. args->rmtblkno = 0;
  1081. args->rmtblkcnt = 0;
  1082. }
  1083. retval = xfs_attr_leaf_add(blk->bp, state->args);
  1084. if (retval == ENOSPC) {
  1085. if (state->path.active == 1) {
  1086. /*
  1087. * Its really a single leaf node, but it had
  1088. * out-of-line values so it looked like it *might*
  1089. * have been a b-tree.
  1090. */
  1091. xfs_da_state_free(state);
  1092. XFS_BMAP_INIT(args->flist, args->firstblock);
  1093. error = xfs_attr_leaf_to_node(args);
  1094. if (!error) {
  1095. error = xfs_bmap_finish(&args->trans,
  1096. args->flist,
  1097. *args->firstblock,
  1098. &committed);
  1099. }
  1100. if (error) {
  1101. ASSERT(committed);
  1102. args->trans = NULL;
  1103. xfs_bmap_cancel(args->flist);
  1104. goto out;
  1105. }
  1106. /*
  1107. * bmap_finish() may have committed the last trans
  1108. * and started a new one. We need the inode to be
  1109. * in all transactions.
  1110. */
  1111. if (committed) {
  1112. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  1113. xfs_trans_ihold(args->trans, dp);
  1114. }
  1115. /*
  1116. * Commit the node conversion and start the next
  1117. * trans in the chain.
  1118. */
  1119. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  1120. goto out;
  1121. goto restart;
  1122. }
  1123. /*
  1124. * Split as many Btree elements as required.
  1125. * This code tracks the new and old attr's location
  1126. * in the index/blkno/rmtblkno/rmtblkcnt fields and
  1127. * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
  1128. */
  1129. XFS_BMAP_INIT(args->flist, args->firstblock);
  1130. error = xfs_da_split(state);
  1131. if (!error) {
  1132. error = xfs_bmap_finish(&args->trans, args->flist,
  1133. *args->firstblock, &committed);
  1134. }
  1135. if (error) {
  1136. ASSERT(committed);
  1137. args->trans = NULL;
  1138. xfs_bmap_cancel(args->flist);
  1139. goto out;
  1140. }
  1141. /*
  1142. * bmap_finish() may have committed the last trans and started
  1143. * a new one. We need the inode to be in all transactions.
  1144. */
  1145. if (committed) {
  1146. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  1147. xfs_trans_ihold(args->trans, dp);
  1148. }
  1149. } else {
  1150. /*
  1151. * Addition succeeded, update Btree hashvals.
  1152. */
  1153. xfs_da_fixhashpath(state, &state->path);
  1154. }
  1155. /*
  1156. * Kill the state structure, we're done with it and need to
  1157. * allow the buffers to come back later.
  1158. */
  1159. xfs_da_state_free(state);
  1160. state = NULL;
  1161. /*
  1162. * Commit the leaf addition or btree split and start the next
  1163. * trans in the chain.
  1164. */
  1165. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  1166. goto out;
  1167. /*
  1168. * If there was an out-of-line value, allocate the blocks we
  1169. * identified for its storage and copy the value. This is done
  1170. * after we create the attribute so that we don't overflow the
  1171. * maximum size of a transaction and/or hit a deadlock.
  1172. */
  1173. if (args->rmtblkno > 0) {
  1174. error = xfs_attr_rmtval_set(args);
  1175. if (error)
  1176. return(error);
  1177. }
  1178. /*
  1179. * If this is an atomic rename operation, we must "flip" the
  1180. * incomplete flags on the "new" and "old" attribute/value pairs
  1181. * so that one disappears and one appears atomically. Then we
  1182. * must remove the "old" attribute/value pair.
  1183. */
  1184. if (args->rename) {
  1185. /*
  1186. * In a separate transaction, set the incomplete flag on the
  1187. * "old" attr and clear the incomplete flag on the "new" attr.
  1188. */
  1189. error = xfs_attr_leaf_flipflags(args);
  1190. if (error)
  1191. goto out;
  1192. /*
  1193. * Dismantle the "old" attribute/value pair by removing
  1194. * a "remote" value (if it exists).
  1195. */
  1196. args->index = args->index2;
  1197. args->blkno = args->blkno2;
  1198. args->rmtblkno = args->rmtblkno2;
  1199. args->rmtblkcnt = args->rmtblkcnt2;
  1200. if (args->rmtblkno) {
  1201. error = xfs_attr_rmtval_remove(args);
  1202. if (error)
  1203. return(error);
  1204. }
  1205. /*
  1206. * Re-find the "old" attribute entry after any split ops.
  1207. * The INCOMPLETE flag means that we will find the "old"
  1208. * attr, not the "new" one.
  1209. */
  1210. args->flags |= XFS_ATTR_INCOMPLETE;
  1211. state = xfs_da_state_alloc();
  1212. state->args = args;
  1213. state->mp = mp;
  1214. state->blocksize = state->mp->m_sb.sb_blocksize;
  1215. state->node_ents = state->mp->m_attr_node_ents;
  1216. state->inleaf = 0;
  1217. error = xfs_da_node_lookup_int(state, &retval);
  1218. if (error)
  1219. goto out;
  1220. /*
  1221. * Remove the name and update the hashvals in the tree.
  1222. */
  1223. blk = &state->path.blk[ state->path.active-1 ];
  1224. ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
  1225. error = xfs_attr_leaf_remove(blk->bp, args);
  1226. xfs_da_fixhashpath(state, &state->path);
  1227. /*
  1228. * Check to see if the tree needs to be collapsed.
  1229. */
  1230. if (retval && (state->path.active > 1)) {
  1231. XFS_BMAP_INIT(args->flist, args->firstblock);
  1232. error = xfs_da_join(state);
  1233. if (!error) {
  1234. error = xfs_bmap_finish(&args->trans,
  1235. args->flist,
  1236. *args->firstblock,
  1237. &committed);
  1238. }
  1239. if (error) {
  1240. ASSERT(committed);
  1241. args->trans = NULL;
  1242. xfs_bmap_cancel(args->flist);
  1243. goto out;
  1244. }
  1245. /*
  1246. * bmap_finish() may have committed the last trans
  1247. * and started a new one. We need the inode to be
  1248. * in all transactions.
  1249. */
  1250. if (committed) {
  1251. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  1252. xfs_trans_ihold(args->trans, dp);
  1253. }
  1254. }
  1255. /*
  1256. * Commit and start the next trans in the chain.
  1257. */
  1258. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  1259. goto out;
  1260. } else if (args->rmtblkno > 0) {
  1261. /*
  1262. * Added a "remote" value, just clear the incomplete flag.
  1263. */
  1264. error = xfs_attr_leaf_clearflag(args);
  1265. if (error)
  1266. goto out;
  1267. }
  1268. retval = error = 0;
  1269. out:
  1270. if (state)
  1271. xfs_da_state_free(state);
  1272. if (error)
  1273. return(error);
  1274. return(retval);
  1275. }
  1276. /*
  1277. * Remove a name from a B-tree attribute list.
  1278. *
  1279. * This will involve walking down the Btree, and may involve joining
  1280. * leaf nodes and even joining intermediate nodes up to and including
  1281. * the root node (a special case of an intermediate node).
  1282. */
  1283. STATIC int
  1284. xfs_attr_node_removename(xfs_da_args_t *args)
  1285. {
  1286. xfs_da_state_t *state;
  1287. xfs_da_state_blk_t *blk;
  1288. xfs_inode_t *dp;
  1289. xfs_dabuf_t *bp;
  1290. int retval, error, committed;
  1291. /*
  1292. * Tie a string around our finger to remind us where we are.
  1293. */
  1294. dp = args->dp;
  1295. state = xfs_da_state_alloc();
  1296. state->args = args;
  1297. state->mp = dp->i_mount;
  1298. state->blocksize = state->mp->m_sb.sb_blocksize;
  1299. state->node_ents = state->mp->m_attr_node_ents;
  1300. /*
  1301. * Search to see if name exists, and get back a pointer to it.
  1302. */
  1303. error = xfs_da_node_lookup_int(state, &retval);
  1304. if (error || (retval != EEXIST)) {
  1305. if (error == 0)
  1306. error = retval;
  1307. goto out;
  1308. }
  1309. /*
  1310. * If there is an out-of-line value, de-allocate the blocks.
  1311. * This is done before we remove the attribute so that we don't
  1312. * overflow the maximum size of a transaction and/or hit a deadlock.
  1313. */
  1314. blk = &state->path.blk[ state->path.active-1 ];
  1315. ASSERT(blk->bp != NULL);
  1316. ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
  1317. if (args->rmtblkno > 0) {
  1318. /*
  1319. * Fill in disk block numbers in the state structure
  1320. * so that we can get the buffers back after we commit
  1321. * several transactions in the following calls.
  1322. */
  1323. error = xfs_attr_fillstate(state);
  1324. if (error)
  1325. goto out;
  1326. /*
  1327. * Mark the attribute as INCOMPLETE, then bunmapi() the
  1328. * remote value.
  1329. */
  1330. error = xfs_attr_leaf_setflag(args);
  1331. if (error)
  1332. goto out;
  1333. error = xfs_attr_rmtval_remove(args);
  1334. if (error)
  1335. goto out;
  1336. /*
  1337. * Refill the state structure with buffers, the prior calls
  1338. * released our buffers.
  1339. */
  1340. error = xfs_attr_refillstate(state);
  1341. if (error)
  1342. goto out;
  1343. }
  1344. /*
  1345. * Remove the name and update the hashvals in the tree.
  1346. */
  1347. blk = &state->path.blk[ state->path.active-1 ];
  1348. ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
  1349. retval = xfs_attr_leaf_remove(blk->bp, args);
  1350. xfs_da_fixhashpath(state, &state->path);
  1351. /*
  1352. * Check to see if the tree needs to be collapsed.
  1353. */
  1354. if (retval && (state->path.active > 1)) {
  1355. XFS_BMAP_INIT(args->flist, args->firstblock);
  1356. error = xfs_da_join(state);
  1357. if (!error) {
  1358. error = xfs_bmap_finish(&args->trans, args->flist,
  1359. *args->firstblock, &committed);
  1360. }
  1361. if (error) {
  1362. ASSERT(committed);
  1363. args->trans = NULL;
  1364. xfs_bmap_cancel(args->flist);
  1365. goto out;
  1366. }
  1367. /*
  1368. * bmap_finish() may have committed the last trans and started
  1369. * a new one. We need the inode to be in all transactions.
  1370. */
  1371. if (committed) {
  1372. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  1373. xfs_trans_ihold(args->trans, dp);
  1374. }
  1375. /*
  1376. * Commit the Btree join operation and start a new trans.
  1377. */
  1378. if ((error = xfs_attr_rolltrans(&args->trans, dp)))
  1379. goto out;
  1380. }
  1381. /*
  1382. * If the result is small enough, push it all into the inode.
  1383. */
  1384. if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
  1385. /*
  1386. * Have to get rid of the copy of this dabuf in the state.
  1387. */
  1388. ASSERT(state->path.active == 1);
  1389. ASSERT(state->path.blk[0].bp);
  1390. xfs_da_buf_done(state->path.blk[0].bp);
  1391. state->path.blk[0].bp = NULL;
  1392. error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
  1393. XFS_ATTR_FORK);
  1394. if (error)
  1395. goto out;
  1396. ASSERT(INT_GET(((xfs_attr_leafblock_t *)
  1397. bp->data)->hdr.info.magic, ARCH_CONVERT)
  1398. == XFS_ATTR_LEAF_MAGIC);
  1399. if (xfs_attr_shortform_allfit(bp, dp)) {
  1400. XFS_BMAP_INIT(args->flist, args->firstblock);
  1401. error = xfs_attr_leaf_to_shortform(bp, args);
  1402. /* bp is gone due to xfs_da_shrink_inode */
  1403. if (!error) {
  1404. error = xfs_bmap_finish(&args->trans,
  1405. args->flist,
  1406. *args->firstblock,
  1407. &committed);
  1408. }
  1409. if (error) {
  1410. ASSERT(committed);
  1411. args->trans = NULL;
  1412. xfs_bmap_cancel(args->flist);
  1413. goto out;
  1414. }
  1415. /*
  1416. * bmap_finish() may have committed the last trans
  1417. * and started a new one. We need the inode to be
  1418. * in all transactions.
  1419. */
  1420. if (committed) {
  1421. xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
  1422. xfs_trans_ihold(args->trans, dp);
  1423. }
  1424. } else
  1425. xfs_da_brelse(args->trans, bp);
  1426. }
  1427. error = 0;
  1428. out:
  1429. xfs_da_state_free(state);
  1430. return(error);
  1431. }
  1432. /*
  1433. * Fill in the disk block numbers in the state structure for the buffers
  1434. * that are attached to the state structure.
  1435. * This is done so that we can quickly reattach ourselves to those buffers
  1436. * after some set of transaction commit's has released these buffers.
  1437. */
  1438. STATIC int
  1439. xfs_attr_fillstate(xfs_da_state_t *state)
  1440. {
  1441. xfs_da_state_path_t *path;
  1442. xfs_da_state_blk_t *blk;
  1443. int level;
  1444. /*
  1445. * Roll down the "path" in the state structure, storing the on-disk
  1446. * block number for those buffers in the "path".
  1447. */
  1448. path = &state->path;
  1449. ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
  1450. for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
  1451. if (blk->bp) {
  1452. blk->disk_blkno = xfs_da_blkno(blk->bp);
  1453. xfs_da_buf_done(blk->bp);
  1454. blk->bp = NULL;
  1455. } else {
  1456. blk->disk_blkno = 0;
  1457. }
  1458. }
  1459. /*
  1460. * Roll down the "altpath" in the state structure, storing the on-disk
  1461. * block number for those buffers in the "altpath".
  1462. */
  1463. path = &state->altpath;
  1464. ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
  1465. for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
  1466. if (blk->bp) {
  1467. blk->disk_blkno = xfs_da_blkno(blk->bp);
  1468. xfs_da_buf_done(blk->bp);
  1469. blk->bp = NULL;
  1470. } else {
  1471. blk->disk_blkno = 0;
  1472. }
  1473. }
  1474. return(0);
  1475. }
  1476. /*
  1477. * Reattach the buffers to the state structure based on the disk block
  1478. * numbers stored in the state structure.
  1479. * This is done after some set of transaction commit's has released those
  1480. * buffers from our grip.
  1481. */
  1482. STATIC int
  1483. xfs_attr_refillstate(xfs_da_state_t *state)
  1484. {
  1485. xfs_da_state_path_t *path;
  1486. xfs_da_state_blk_t *blk;
  1487. int level, error;
  1488. /*
  1489. * Roll down the "path" in the state structure, storing the on-disk
  1490. * block number for those buffers in the "path".
  1491. */
  1492. path = &state->path;
  1493. ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
  1494. for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
  1495. if (blk->disk_blkno) {
  1496. error = xfs_da_read_buf(state->args->trans,
  1497. state->args->dp,
  1498. blk->blkno, blk->disk_blkno,
  1499. &blk->bp, XFS_ATTR_FORK);
  1500. if (error)
  1501. return(error);
  1502. } else {
  1503. blk->bp = NULL;
  1504. }
  1505. }
  1506. /*
  1507. * Roll down the "altpath" in the state structure, storing the on-disk
  1508. * block number for those buffers in the "altpath".
  1509. */
  1510. path = &state->altpath;
  1511. ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
  1512. for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
  1513. if (blk->disk_blkno) {
  1514. error = xfs_da_read_buf(state->args->trans,
  1515. state->args->dp,
  1516. blk->blkno, blk->disk_blkno,
  1517. &blk->bp, XFS_ATTR_FORK);
  1518. if (error)
  1519. return(error);
  1520. } else {
  1521. blk->bp = NULL;
  1522. }
  1523. }
  1524. return(0);
  1525. }
  1526. /*
  1527. * Look up a filename in a node attribute list.
  1528. *
  1529. * This routine gets called for any attribute fork that has more than one
  1530. * block, ie: both true Btree attr lists and for single-leaf-blocks with
  1531. * "remote" values taking up more blocks.
  1532. */
  1533. int
  1534. xfs_attr_node_get(xfs_da_args_t *args)
  1535. {
  1536. xfs_da_state_t *state;
  1537. xfs_da_state_blk_t *blk;
  1538. int error, retval;
  1539. int i;
  1540. state = xfs_da_state_alloc();
  1541. state->args = args;
  1542. state->mp = args->dp->i_mount;
  1543. state->blocksize = state->mp->m_sb.sb_blocksize;
  1544. state->node_ents = state->mp->m_attr_node_ents;
  1545. /*
  1546. * Search to see if name exists, and get back a pointer to it.
  1547. */
  1548. error = xfs_da_node_lookup_int(state, &retval);
  1549. if (error) {
  1550. retval = error;
  1551. } else if (retval == EEXIST) {
  1552. blk = &state->path.blk[ state->path.active-1 ];
  1553. ASSERT(blk->bp != NULL);
  1554. ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
  1555. /*
  1556. * Get the value, local or "remote"
  1557. */
  1558. retval = xfs_attr_leaf_getvalue(blk->bp, args);
  1559. if (!retval && (args->rmtblkno > 0)
  1560. && !(args->flags & ATTR_KERNOVAL)) {
  1561. retval = xfs_attr_rmtval_get(args);
  1562. }
  1563. }
  1564. /*
  1565. * If not in a transaction, we have to release all the buffers.
  1566. */
  1567. for (i = 0; i < state->path.active; i++) {
  1568. xfs_da_brelse(args->trans, state->path.blk[i].bp);
  1569. state->path.blk[i].bp = NULL;
  1570. }
  1571. xfs_da_state_free(state);
  1572. return(retval);
  1573. }
  1574. STATIC int /* error */
  1575. xfs_attr_node_list(xfs_attr_list_context_t *context)
  1576. {
  1577. attrlist_cursor_kern_t *cursor;
  1578. xfs_attr_leafblock_t *leaf;
  1579. xfs_da_intnode_t *node;
  1580. xfs_da_node_entry_t *btree;
  1581. int error, i;
  1582. xfs_dabuf_t *bp;
  1583. cursor = context->cursor;
  1584. cursor->initted = 1;
  1585. /*
  1586. * Do all sorts of validation on the passed-in cursor structure.
  1587. * If anything is amiss, ignore the cursor and look up the hashval
  1588. * starting from the btree root.
  1589. */
  1590. bp = NULL;
  1591. if (cursor->blkno > 0) {
  1592. error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
  1593. &bp, XFS_ATTR_FORK);
  1594. if ((error != 0) && (error != EFSCORRUPTED))
  1595. return(error);
  1596. if (bp) {
  1597. node = bp->data;
  1598. switch (INT_GET(node->hdr.info.magic, ARCH_CONVERT)) {
  1599. case XFS_DA_NODE_MAGIC:
  1600. xfs_attr_trace_l_cn("wrong blk", context, node);
  1601. xfs_da_brelse(NULL, bp);
  1602. bp = NULL;
  1603. break;
  1604. case XFS_ATTR_LEAF_MAGIC:
  1605. leaf = bp->data;
  1606. if (cursor->hashval >
  1607. INT_GET(leaf->entries[
  1608. INT_GET(leaf->hdr.count,
  1609. ARCH_CONVERT)-1].hashval,
  1610. ARCH_CONVERT)) {
  1611. xfs_attr_trace_l_cl("wrong blk",
  1612. context, leaf);
  1613. xfs_da_brelse(NULL, bp);
  1614. bp = NULL;
  1615. } else if (cursor->hashval <=
  1616. INT_GET(leaf->entries[0].hashval,
  1617. ARCH_CONVERT)) {
  1618. xfs_attr_trace_l_cl("maybe wrong blk",
  1619. context, leaf);
  1620. xfs_da_brelse(NULL, bp);
  1621. bp = NULL;
  1622. }
  1623. break;
  1624. default:
  1625. xfs_attr_trace_l_c("wrong blk - ??", context);
  1626. xfs_da_brelse(NULL, bp);
  1627. bp = NULL;
  1628. }
  1629. }
  1630. }
  1631. /*
  1632. * We did not find what we expected given the cursor's contents,
  1633. * so we start from the top and work down based on the hash value.
  1634. * Note that start of node block is same as start of leaf block.
  1635. */
  1636. if (bp == NULL) {
  1637. cursor->blkno = 0;
  1638. for (;;) {
  1639. error = xfs_da_read_buf(NULL, context->dp,
  1640. cursor->blkno, -1, &bp,
  1641. XFS_ATTR_FORK);
  1642. if (error)
  1643. return(error);
  1644. if (unlikely(bp == NULL)) {
  1645. XFS_ERROR_REPORT("xfs_attr_node_list(2)",
  1646. XFS_ERRLEVEL_LOW,
  1647. context->dp->i_mount);
  1648. return(XFS_ERROR(EFSCORRUPTED));
  1649. }
  1650. node = bp->data;
  1651. if (INT_GET(node->hdr.info.magic, ARCH_CONVERT)
  1652. == XFS_ATTR_LEAF_MAGIC)
  1653. break;
  1654. if (unlikely(INT_GET(node->hdr.info.magic, ARCH_CONVERT)
  1655. != XFS_DA_NODE_MAGIC)) {
  1656. XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
  1657. XFS_ERRLEVEL_LOW,
  1658. context->dp->i_mount,
  1659. node);
  1660. xfs_da_brelse(NULL, bp);
  1661. return(XFS_ERROR(EFSCORRUPTED));
  1662. }
  1663. btree = node->btree;
  1664. for (i = 0;
  1665. i < INT_GET(node->hdr.count, ARCH_CONVERT);
  1666. btree++, i++) {
  1667. if (cursor->hashval
  1668. <= INT_GET(btree->hashval,
  1669. ARCH_CONVERT)) {
  1670. cursor->blkno = INT_GET(btree->before, ARCH_CONVERT);
  1671. xfs_attr_trace_l_cb("descending",
  1672. context, btree);
  1673. break;
  1674. }
  1675. }
  1676. if (i == INT_GET(node->hdr.count, ARCH_CONVERT)) {
  1677. xfs_da_brelse(NULL, bp);
  1678. return(0);
  1679. }
  1680. xfs_da_brelse(NULL, bp);
  1681. }
  1682. }
  1683. ASSERT(bp != NULL);
  1684. /*
  1685. * Roll upward through the blocks, processing each leaf block in
  1686. * order. As long as there is space in the result buffer, keep
  1687. * adding the information.
  1688. */
  1689. for (;;) {
  1690. leaf = bp->data;
  1691. if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT)
  1692. != XFS_ATTR_LEAF_MAGIC)) {
  1693. XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
  1694. XFS_ERRLEVEL_LOW,
  1695. context->dp->i_mount, leaf);
  1696. xfs_da_brelse(NULL, bp);
  1697. return(XFS_ERROR(EFSCORRUPTED));
  1698. }
  1699. error = xfs_attr_leaf_list_int(bp, context);
  1700. if (error || !leaf->hdr.info.forw)
  1701. break; /* not really an error, buffer full or EOF */
  1702. cursor->blkno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
  1703. xfs_da_brelse(NULL, bp);
  1704. error = xfs_da_read_buf(NULL, context->dp, cursor->blk

Large files files are truncated, but you can click here to view the full file