/kern_oII/fs/xfs/xfs_dir2.c

http://omnia2droid.googlecode.com/ · C · 765 lines · 557 code · 61 blank · 147 comment · 133 complexity · 291824db7fb09ca25ddf567e4f0bbda0 MD5 · raw file

  1. /*
  2. * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. #include "xfs_fs.h"
  20. #include "xfs_types.h"
  21. #include "xfs_bit.h"
  22. #include "xfs_log.h"
  23. #include "xfs_inum.h"
  24. #include "xfs_trans.h"
  25. #include "xfs_sb.h"
  26. #include "xfs_ag.h"
  27. #include "xfs_dir2.h"
  28. #include "xfs_dmapi.h"
  29. #include "xfs_mount.h"
  30. #include "xfs_da_btree.h"
  31. #include "xfs_bmap_btree.h"
  32. #include "xfs_alloc_btree.h"
  33. #include "xfs_dir2_sf.h"
  34. #include "xfs_attr_sf.h"
  35. #include "xfs_dinode.h"
  36. #include "xfs_inode.h"
  37. #include "xfs_inode_item.h"
  38. #include "xfs_bmap.h"
  39. #include "xfs_dir2_data.h"
  40. #include "xfs_dir2_leaf.h"
  41. #include "xfs_dir2_block.h"
  42. #include "xfs_dir2_node.h"
  43. #include "xfs_dir2_trace.h"
  44. #include "xfs_error.h"
  45. #include "xfs_vnodeops.h"
  46. struct xfs_name xfs_name_dotdot = {"..", 2};
  47. /*
  48. * ASCII case-insensitive (ie. A-Z) support for directories that was
  49. * used in IRIX.
  50. */
  51. STATIC xfs_dahash_t
  52. xfs_ascii_ci_hashname(
  53. struct xfs_name *name)
  54. {
  55. xfs_dahash_t hash;
  56. int i;
  57. for (i = 0, hash = 0; i < name->len; i++)
  58. hash = tolower(name->name[i]) ^ rol32(hash, 7);
  59. return hash;
  60. }
  61. STATIC enum xfs_dacmp
  62. xfs_ascii_ci_compname(
  63. struct xfs_da_args *args,
  64. const char *name,
  65. int len)
  66. {
  67. enum xfs_dacmp result;
  68. int i;
  69. if (args->namelen != len)
  70. return XFS_CMP_DIFFERENT;
  71. result = XFS_CMP_EXACT;
  72. for (i = 0; i < len; i++) {
  73. if (args->name[i] == name[i])
  74. continue;
  75. if (tolower(args->name[i]) != tolower(name[i]))
  76. return XFS_CMP_DIFFERENT;
  77. result = XFS_CMP_CASE;
  78. }
  79. return result;
  80. }
  81. static struct xfs_nameops xfs_ascii_ci_nameops = {
  82. .hashname = xfs_ascii_ci_hashname,
  83. .compname = xfs_ascii_ci_compname,
  84. };
  85. void
  86. xfs_dir_mount(
  87. xfs_mount_t *mp)
  88. {
  89. ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb));
  90. ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
  91. XFS_MAX_BLOCKSIZE);
  92. mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
  93. mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
  94. mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
  95. mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
  96. mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
  97. mp->m_attr_node_ents =
  98. (mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
  99. (uint)sizeof(xfs_da_node_entry_t);
  100. mp->m_dir_node_ents =
  101. (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
  102. (uint)sizeof(xfs_da_node_entry_t);
  103. mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
  104. if (xfs_sb_version_hasasciici(&mp->m_sb))
  105. mp->m_dirnameops = &xfs_ascii_ci_nameops;
  106. else
  107. mp->m_dirnameops = &xfs_default_nameops;
  108. }
  109. /*
  110. * Return 1 if directory contains only "." and "..".
  111. */
  112. int
  113. xfs_dir_isempty(
  114. xfs_inode_t *dp)
  115. {
  116. xfs_dir2_sf_t *sfp;
  117. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  118. if (dp->i_d.di_size == 0) /* might happen during shutdown. */
  119. return 1;
  120. if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
  121. return 0;
  122. sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
  123. return !sfp->hdr.count;
  124. }
  125. /*
  126. * Validate a given inode number.
  127. */
  128. int
  129. xfs_dir_ino_validate(
  130. xfs_mount_t *mp,
  131. xfs_ino_t ino)
  132. {
  133. xfs_agblock_t agblkno;
  134. xfs_agino_t agino;
  135. xfs_agnumber_t agno;
  136. int ino_ok;
  137. int ioff;
  138. agno = XFS_INO_TO_AGNO(mp, ino);
  139. agblkno = XFS_INO_TO_AGBNO(mp, ino);
  140. ioff = XFS_INO_TO_OFFSET(mp, ino);
  141. agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
  142. ino_ok =
  143. agno < mp->m_sb.sb_agcount &&
  144. agblkno < mp->m_sb.sb_agblocks &&
  145. agblkno != 0 &&
  146. ioff < (1 << mp->m_sb.sb_inopblog) &&
  147. XFS_AGINO_TO_INO(mp, agno, agino) == ino;
  148. if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
  149. XFS_RANDOM_DIR_INO_VALIDATE))) {
  150. xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
  151. (unsigned long long) ino);
  152. XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
  153. return XFS_ERROR(EFSCORRUPTED);
  154. }
  155. return 0;
  156. }
  157. /*
  158. * Initialize a directory with its "." and ".." entries.
  159. */
  160. int
  161. xfs_dir_init(
  162. xfs_trans_t *tp,
  163. xfs_inode_t *dp,
  164. xfs_inode_t *pdp)
  165. {
  166. xfs_da_args_t args;
  167. int error;
  168. memset((char *)&args, 0, sizeof(args));
  169. args.dp = dp;
  170. args.trans = tp;
  171. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  172. if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
  173. return error;
  174. return xfs_dir2_sf_create(&args, pdp->i_ino);
  175. }
  176. /*
  177. Enter a name in a directory.
  178. */
  179. int
  180. xfs_dir_createname(
  181. xfs_trans_t *tp,
  182. xfs_inode_t *dp,
  183. struct xfs_name *name,
  184. xfs_ino_t inum, /* new entry inode number */
  185. xfs_fsblock_t *first, /* bmap's firstblock */
  186. xfs_bmap_free_t *flist, /* bmap's freeblock list */
  187. xfs_extlen_t total) /* bmap's total block count */
  188. {
  189. xfs_da_args_t args;
  190. int rval;
  191. int v; /* type-checking value */
  192. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  193. if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
  194. return rval;
  195. XFS_STATS_INC(xs_dir_create);
  196. memset(&args, 0, sizeof(xfs_da_args_t));
  197. args.name = name->name;
  198. args.namelen = name->len;
  199. args.hashval = dp->i_mount->m_dirnameops->hashname(name);
  200. args.inumber = inum;
  201. args.dp = dp;
  202. args.firstblock = first;
  203. args.flist = flist;
  204. args.total = total;
  205. args.whichfork = XFS_DATA_FORK;
  206. args.trans = tp;
  207. args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
  208. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  209. rval = xfs_dir2_sf_addname(&args);
  210. else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
  211. return rval;
  212. else if (v)
  213. rval = xfs_dir2_block_addname(&args);
  214. else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
  215. return rval;
  216. else if (v)
  217. rval = xfs_dir2_leaf_addname(&args);
  218. else
  219. rval = xfs_dir2_node_addname(&args);
  220. return rval;
  221. }
  222. /*
  223. * If doing a CI lookup and case-insensitive match, dup actual name into
  224. * args.value. Return EEXIST for success (ie. name found) or an error.
  225. */
  226. int
  227. xfs_dir_cilookup_result(
  228. struct xfs_da_args *args,
  229. const char *name,
  230. int len)
  231. {
  232. if (args->cmpresult == XFS_CMP_DIFFERENT)
  233. return ENOENT;
  234. if (args->cmpresult != XFS_CMP_CASE ||
  235. !(args->op_flags & XFS_DA_OP_CILOOKUP))
  236. return EEXIST;
  237. args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
  238. if (!args->value)
  239. return ENOMEM;
  240. memcpy(args->value, name, len);
  241. args->valuelen = len;
  242. return EEXIST;
  243. }
  244. /*
  245. * Lookup a name in a directory, give back the inode number.
  246. * If ci_name is not NULL, returns the actual name in ci_name if it differs
  247. * to name, or ci_name->name is set to NULL for an exact match.
  248. */
  249. int
  250. xfs_dir_lookup(
  251. xfs_trans_t *tp,
  252. xfs_inode_t *dp,
  253. struct xfs_name *name,
  254. xfs_ino_t *inum, /* out: inode number */
  255. struct xfs_name *ci_name) /* out: actual name if CI match */
  256. {
  257. xfs_da_args_t args;
  258. int rval;
  259. int v; /* type-checking value */
  260. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  261. XFS_STATS_INC(xs_dir_lookup);
  262. memset(&args, 0, sizeof(xfs_da_args_t));
  263. args.name = name->name;
  264. args.namelen = name->len;
  265. args.hashval = dp->i_mount->m_dirnameops->hashname(name);
  266. args.dp = dp;
  267. args.whichfork = XFS_DATA_FORK;
  268. args.trans = tp;
  269. args.op_flags = XFS_DA_OP_OKNOENT;
  270. if (ci_name)
  271. args.op_flags |= XFS_DA_OP_CILOOKUP;
  272. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  273. rval = xfs_dir2_sf_lookup(&args);
  274. else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
  275. return rval;
  276. else if (v)
  277. rval = xfs_dir2_block_lookup(&args);
  278. else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
  279. return rval;
  280. else if (v)
  281. rval = xfs_dir2_leaf_lookup(&args);
  282. else
  283. rval = xfs_dir2_node_lookup(&args);
  284. if (rval == EEXIST)
  285. rval = 0;
  286. if (!rval) {
  287. *inum = args.inumber;
  288. if (ci_name) {
  289. ci_name->name = args.value;
  290. ci_name->len = args.valuelen;
  291. }
  292. }
  293. return rval;
  294. }
  295. /*
  296. * Remove an entry from a directory.
  297. */
  298. int
  299. xfs_dir_removename(
  300. xfs_trans_t *tp,
  301. xfs_inode_t *dp,
  302. struct xfs_name *name,
  303. xfs_ino_t ino,
  304. xfs_fsblock_t *first, /* bmap's firstblock */
  305. xfs_bmap_free_t *flist, /* bmap's freeblock list */
  306. xfs_extlen_t total) /* bmap's total block count */
  307. {
  308. xfs_da_args_t args;
  309. int rval;
  310. int v; /* type-checking value */
  311. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  312. XFS_STATS_INC(xs_dir_remove);
  313. memset(&args, 0, sizeof(xfs_da_args_t));
  314. args.name = name->name;
  315. args.namelen = name->len;
  316. args.hashval = dp->i_mount->m_dirnameops->hashname(name);
  317. args.inumber = ino;
  318. args.dp = dp;
  319. args.firstblock = first;
  320. args.flist = flist;
  321. args.total = total;
  322. args.whichfork = XFS_DATA_FORK;
  323. args.trans = tp;
  324. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  325. rval = xfs_dir2_sf_removename(&args);
  326. else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
  327. return rval;
  328. else if (v)
  329. rval = xfs_dir2_block_removename(&args);
  330. else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
  331. return rval;
  332. else if (v)
  333. rval = xfs_dir2_leaf_removename(&args);
  334. else
  335. rval = xfs_dir2_node_removename(&args);
  336. return rval;
  337. }
  338. /*
  339. * Read a directory.
  340. */
  341. int
  342. xfs_readdir(
  343. xfs_inode_t *dp,
  344. void *dirent,
  345. size_t bufsize,
  346. xfs_off_t *offset,
  347. filldir_t filldir)
  348. {
  349. int rval; /* return value */
  350. int v; /* type-checking value */
  351. xfs_itrace_entry(dp);
  352. if (XFS_FORCED_SHUTDOWN(dp->i_mount))
  353. return XFS_ERROR(EIO);
  354. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  355. XFS_STATS_INC(xs_dir_getdents);
  356. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  357. rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
  358. else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
  359. ;
  360. else if (v)
  361. rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
  362. else
  363. rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
  364. filldir);
  365. return rval;
  366. }
  367. /*
  368. * Replace the inode number of a directory entry.
  369. */
  370. int
  371. xfs_dir_replace(
  372. xfs_trans_t *tp,
  373. xfs_inode_t *dp,
  374. struct xfs_name *name, /* name of entry to replace */
  375. xfs_ino_t inum, /* new inode number */
  376. xfs_fsblock_t *first, /* bmap's firstblock */
  377. xfs_bmap_free_t *flist, /* bmap's freeblock list */
  378. xfs_extlen_t total) /* bmap's total block count */
  379. {
  380. xfs_da_args_t args;
  381. int rval;
  382. int v; /* type-checking value */
  383. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  384. if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
  385. return rval;
  386. memset(&args, 0, sizeof(xfs_da_args_t));
  387. args.name = name->name;
  388. args.namelen = name->len;
  389. args.hashval = dp->i_mount->m_dirnameops->hashname(name);
  390. args.inumber = inum;
  391. args.dp = dp;
  392. args.firstblock = first;
  393. args.flist = flist;
  394. args.total = total;
  395. args.whichfork = XFS_DATA_FORK;
  396. args.trans = tp;
  397. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  398. rval = xfs_dir2_sf_replace(&args);
  399. else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
  400. return rval;
  401. else if (v)
  402. rval = xfs_dir2_block_replace(&args);
  403. else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
  404. return rval;
  405. else if (v)
  406. rval = xfs_dir2_leaf_replace(&args);
  407. else
  408. rval = xfs_dir2_node_replace(&args);
  409. return rval;
  410. }
  411. /*
  412. * See if this entry can be added to the directory without allocating space.
  413. * First checks that the caller couldn't reserve enough space (resblks = 0).
  414. */
  415. int
  416. xfs_dir_canenter(
  417. xfs_trans_t *tp,
  418. xfs_inode_t *dp,
  419. struct xfs_name *name, /* name of entry to add */
  420. uint resblks)
  421. {
  422. xfs_da_args_t args;
  423. int rval;
  424. int v; /* type-checking value */
  425. if (resblks)
  426. return 0;
  427. ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
  428. memset(&args, 0, sizeof(xfs_da_args_t));
  429. args.name = name->name;
  430. args.namelen = name->len;
  431. args.hashval = dp->i_mount->m_dirnameops->hashname(name);
  432. args.dp = dp;
  433. args.whichfork = XFS_DATA_FORK;
  434. args.trans = tp;
  435. args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME |
  436. XFS_DA_OP_OKNOENT;
  437. if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
  438. rval = xfs_dir2_sf_addname(&args);
  439. else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
  440. return rval;
  441. else if (v)
  442. rval = xfs_dir2_block_addname(&args);
  443. else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
  444. return rval;
  445. else if (v)
  446. rval = xfs_dir2_leaf_addname(&args);
  447. else
  448. rval = xfs_dir2_node_addname(&args);
  449. return rval;
  450. }
  451. /*
  452. * Utility routines.
  453. */
  454. /*
  455. * Add a block to the directory.
  456. * This routine is for data and free blocks, not leaf/node blocks
  457. * which are handled by xfs_da_grow_inode.
  458. */
  459. int
  460. xfs_dir2_grow_inode(
  461. xfs_da_args_t *args,
  462. int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
  463. xfs_dir2_db_t *dbp) /* out: block number added */
  464. {
  465. xfs_fileoff_t bno; /* directory offset of new block */
  466. int count; /* count of filesystem blocks */
  467. xfs_inode_t *dp; /* incore directory inode */
  468. int error;
  469. int got; /* blocks actually mapped */
  470. int i;
  471. xfs_bmbt_irec_t map; /* single structure for bmap */
  472. int mapi; /* mapping index */
  473. xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
  474. xfs_mount_t *mp;
  475. int nmap; /* number of bmap entries */
  476. xfs_trans_t *tp;
  477. xfs_drfsbno_t nblks;
  478. xfs_dir2_trace_args_s("grow_inode", args, space);
  479. dp = args->dp;
  480. tp = args->trans;
  481. mp = dp->i_mount;
  482. nblks = dp->i_d.di_nblocks;
  483. /*
  484. * Set lowest possible block in the space requested.
  485. */
  486. bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
  487. count = mp->m_dirblkfsbs;
  488. /*
  489. * Find the first hole for our block.
  490. */
  491. if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
  492. return error;
  493. nmap = 1;
  494. ASSERT(args->firstblock != NULL);
  495. /*
  496. * Try mapping the new block contiguously (one extent).
  497. */
  498. if ((error = xfs_bmapi(tp, dp, bno, count,
  499. XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
  500. args->firstblock, args->total, &map, &nmap,
  501. args->flist, NULL)))
  502. return error;
  503. ASSERT(nmap <= 1);
  504. if (nmap == 1) {
  505. mapp = &map;
  506. mapi = 1;
  507. }
  508. /*
  509. * Didn't work and this is a multiple-fsb directory block.
  510. * Try again with contiguous flag turned on.
  511. */
  512. else if (nmap == 0 && count > 1) {
  513. xfs_fileoff_t b; /* current file offset */
  514. /*
  515. * Space for maximum number of mappings.
  516. */
  517. mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
  518. /*
  519. * Iterate until we get to the end of our block.
  520. */
  521. for (b = bno, mapi = 0; b < bno + count; ) {
  522. int c; /* current fsb count */
  523. /*
  524. * Can't map more than MAX_NMAP at once.
  525. */
  526. nmap = MIN(XFS_BMAP_MAX_NMAP, count);
  527. c = (int)(bno + count - b);
  528. if ((error = xfs_bmapi(tp, dp, b, c,
  529. XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
  530. args->firstblock, args->total,
  531. &mapp[mapi], &nmap, args->flist,
  532. NULL))) {
  533. kmem_free(mapp);
  534. return error;
  535. }
  536. if (nmap < 1)
  537. break;
  538. /*
  539. * Add this bunch into our table, go to the next offset.
  540. */
  541. mapi += nmap;
  542. b = mapp[mapi - 1].br_startoff +
  543. mapp[mapi - 1].br_blockcount;
  544. }
  545. }
  546. /*
  547. * Didn't work.
  548. */
  549. else {
  550. mapi = 0;
  551. mapp = NULL;
  552. }
  553. /*
  554. * See how many fsb's we got.
  555. */
  556. for (i = 0, got = 0; i < mapi; i++)
  557. got += mapp[i].br_blockcount;
  558. /*
  559. * Didn't get enough fsb's, or the first/last block's are wrong.
  560. */
  561. if (got != count || mapp[0].br_startoff != bno ||
  562. mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
  563. bno + count) {
  564. if (mapp != &map)
  565. kmem_free(mapp);
  566. return XFS_ERROR(ENOSPC);
  567. }
  568. /*
  569. * Done with the temporary mapping table.
  570. */
  571. if (mapp != &map)
  572. kmem_free(mapp);
  573. /* account for newly allocated blocks in reserved blocks total */
  574. args->total -= dp->i_d.di_nblocks - nblks;
  575. *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
  576. /*
  577. * Update file's size if this is the data space and it grew.
  578. */
  579. if (space == XFS_DIR2_DATA_SPACE) {
  580. xfs_fsize_t size; /* directory file (data) size */
  581. size = XFS_FSB_TO_B(mp, bno + count);
  582. if (size > dp->i_d.di_size) {
  583. dp->i_d.di_size = size;
  584. xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
  585. }
  586. }
  587. return 0;
  588. }
  589. /*
  590. * See if the directory is a single-block form directory.
  591. */
  592. int
  593. xfs_dir2_isblock(
  594. xfs_trans_t *tp,
  595. xfs_inode_t *dp,
  596. int *vp) /* out: 1 is block, 0 is not block */
  597. {
  598. xfs_fileoff_t last; /* last file offset */
  599. xfs_mount_t *mp;
  600. int rval;
  601. mp = dp->i_mount;
  602. if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
  603. return rval;
  604. rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
  605. ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
  606. *vp = rval;
  607. return 0;
  608. }
  609. /*
  610. * See if the directory is a single-leaf form directory.
  611. */
  612. int
  613. xfs_dir2_isleaf(
  614. xfs_trans_t *tp,
  615. xfs_inode_t *dp,
  616. int *vp) /* out: 1 is leaf, 0 is not leaf */
  617. {
  618. xfs_fileoff_t last; /* last file offset */
  619. xfs_mount_t *mp;
  620. int rval;
  621. mp = dp->i_mount;
  622. if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
  623. return rval;
  624. *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
  625. return 0;
  626. }
  627. /*
  628. * Remove the given block from the directory.
  629. * This routine is used for data and free blocks, leaf/node are done
  630. * by xfs_da_shrink_inode.
  631. */
  632. int
  633. xfs_dir2_shrink_inode(
  634. xfs_da_args_t *args,
  635. xfs_dir2_db_t db,
  636. xfs_dabuf_t *bp)
  637. {
  638. xfs_fileoff_t bno; /* directory file offset */
  639. xfs_dablk_t da; /* directory file offset */
  640. int done; /* bunmap is finished */
  641. xfs_inode_t *dp;
  642. int error;
  643. xfs_mount_t *mp;
  644. xfs_trans_t *tp;
  645. xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
  646. dp = args->dp;
  647. mp = dp->i_mount;
  648. tp = args->trans;
  649. da = xfs_dir2_db_to_da(mp, db);
  650. /*
  651. * Unmap the fsblock(s).
  652. */
  653. if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
  654. XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
  655. NULL, &done))) {
  656. /*
  657. * ENOSPC actually can happen if we're in a removename with
  658. * no space reservation, and the resulting block removal
  659. * would cause a bmap btree split or conversion from extents
  660. * to btree. This can only happen for un-fragmented
  661. * directory blocks, since you need to be punching out
  662. * the middle of an extent.
  663. * In this case we need to leave the block in the file,
  664. * and not binval it.
  665. * So the block has to be in a consistent empty state
  666. * and appropriately logged.
  667. * We don't free up the buffer, the caller can tell it
  668. * hasn't happened since it got an error back.
  669. */
  670. return error;
  671. }
  672. ASSERT(done);
  673. /*
  674. * Invalidate the buffer from the transaction.
  675. */
  676. xfs_da_binval(tp, bp);
  677. /*
  678. * If it's not a data block, we're done.
  679. */
  680. if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))
  681. return 0;
  682. /*
  683. * If the block isn't the last one in the directory, we're done.
  684. */
  685. if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))
  686. return 0;
  687. bno = da;
  688. if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
  689. /*
  690. * This can't really happen unless there's kernel corruption.
  691. */
  692. return error;
  693. }
  694. if (db == mp->m_dirdatablk)
  695. ASSERT(bno == 0);
  696. else
  697. ASSERT(bno > 0);
  698. /*
  699. * Set the size to the new last block.
  700. */
  701. dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
  702. xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
  703. return 0;
  704. }