aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-11-27 22:23:41 -0500
committerNiv Sardi <xaiki@sgi.com>2008-11-30 19:38:03 -0500
commit94e1b69d1abd108d306e926c3012ec89e481c0da (patch)
treed7fb02a0c855729831dcddbef6afcb518d3ed870 /fs/xfs
parenta1941895034cda2bffa23ba845607c82138ccf52 (diff)
[XFS] merge xfs_imap into xfs_dilocate
xfs_imap is the only caller of xfs_dilocate and doesn't add any significant value. Merge the two functions and document the various cases we have for inode cluster lookup in the new xfs_imap. Also remove the unused im_agblkno and im_ioffset fields from struct xfs_imap while we're at it. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Niv Sardi <xaiki@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_ialloc.c129
-rw-r--r--fs/xfs/xfs_ialloc.h10
-rw-r--r--fs/xfs/xfs_imap.h7
-rw-r--r--fs/xfs/xfs_inode.c60
-rw-r--r--fs/xfs/xfs_inode.h2
5 files changed, 88 insertions, 120 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 0ce56d6a4922..348ac30174c5 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -40,6 +40,7 @@
40#include "xfs_rtalloc.h" 40#include "xfs_rtalloc.h"
41#include "xfs_error.h" 41#include "xfs_error.h"
42#include "xfs_bmap.h" 42#include "xfs_bmap.h"
43#include "xfs_imap.h"
43 44
44 45
45/* 46/*
@@ -1196,36 +1197,28 @@ error0:
1196} 1197}
1197 1198
1198/* 1199/*
1199 * Return the location of the inode in bno/off, for mapping it into a buffer. 1200 * Return the location of the inode in imap, for mapping it into a buffer.
1200 */ 1201 */
1201/*ARGSUSED*/
1202int 1202int
1203xfs_dilocate( 1203xfs_imap(
1204 xfs_mount_t *mp, /* file system mount structure */ 1204 xfs_mount_t *mp, /* file system mount structure */
1205 xfs_trans_t *tp, /* transaction pointer */ 1205 xfs_trans_t *tp, /* transaction pointer */
1206 xfs_ino_t ino, /* inode to locate */ 1206 xfs_ino_t ino, /* inode to locate */
1207 xfs_fsblock_t *bno, /* output: block containing inode */ 1207 struct xfs_imap *imap, /* location map structure */
1208 int *len, /* output: num blocks in inode cluster */ 1208 uint flags) /* flags for inode btree lookup */
1209 int *off, /* output: index in block of inode */
1210 uint flags) /* flags concerning inode lookup */
1211{ 1209{
1212 xfs_agblock_t agbno; /* block number of inode in the alloc group */ 1210 xfs_agblock_t agbno; /* block number of inode in the alloc group */
1213 xfs_buf_t *agbp; /* agi buffer */
1214 xfs_agino_t agino; /* inode number within alloc group */ 1211 xfs_agino_t agino; /* inode number within alloc group */
1215 xfs_agnumber_t agno; /* allocation group number */ 1212 xfs_agnumber_t agno; /* allocation group number */
1216 int blks_per_cluster; /* num blocks per inode cluster */ 1213 int blks_per_cluster; /* num blocks per inode cluster */
1217 xfs_agblock_t chunk_agbno; /* first block in inode chunk */ 1214 xfs_agblock_t chunk_agbno; /* first block in inode chunk */
1218 xfs_agino_t chunk_agino; /* first agino in inode chunk */
1219 __int32_t chunk_cnt; /* count of free inodes in chunk */
1220 xfs_inofree_t chunk_free; /* mask of free inodes in chunk */
1221 xfs_agblock_t cluster_agbno; /* first block in inode cluster */ 1215 xfs_agblock_t cluster_agbno; /* first block in inode cluster */
1222 xfs_btree_cur_t *cur; /* inode btree cursor */
1223 int error; /* error code */ 1216 int error; /* error code */
1224 int i; /* temp state */
1225 int offset; /* index of inode in its buffer */ 1217 int offset; /* index of inode in its buffer */
1226 int offset_agbno; /* blks from chunk start to inode */ 1218 int offset_agbno; /* blks from chunk start to inode */
1227 1219
1228 ASSERT(ino != NULLFSINO); 1220 ASSERT(ino != NULLFSINO);
1221
1229 /* 1222 /*
1230 * Split up the inode number into its parts. 1223 * Split up the inode number into its parts.
1231 */ 1224 */
@@ -1240,20 +1233,20 @@ xfs_dilocate(
1240 return XFS_ERROR(EINVAL); 1233 return XFS_ERROR(EINVAL);
1241 if (agno >= mp->m_sb.sb_agcount) { 1234 if (agno >= mp->m_sb.sb_agcount) {
1242 xfs_fs_cmn_err(CE_ALERT, mp, 1235 xfs_fs_cmn_err(CE_ALERT, mp,
1243 "xfs_dilocate: agno (%d) >= " 1236 "xfs_imap: agno (%d) >= "
1244 "mp->m_sb.sb_agcount (%d)", 1237 "mp->m_sb.sb_agcount (%d)",
1245 agno, mp->m_sb.sb_agcount); 1238 agno, mp->m_sb.sb_agcount);
1246 } 1239 }
1247 if (agbno >= mp->m_sb.sb_agblocks) { 1240 if (agbno >= mp->m_sb.sb_agblocks) {
1248 xfs_fs_cmn_err(CE_ALERT, mp, 1241 xfs_fs_cmn_err(CE_ALERT, mp,
1249 "xfs_dilocate: agbno (0x%llx) >= " 1242 "xfs_imap: agbno (0x%llx) >= "
1250 "mp->m_sb.sb_agblocks (0x%lx)", 1243 "mp->m_sb.sb_agblocks (0x%lx)",
1251 (unsigned long long) agbno, 1244 (unsigned long long) agbno,
1252 (unsigned long) mp->m_sb.sb_agblocks); 1245 (unsigned long) mp->m_sb.sb_agblocks);
1253 } 1246 }
1254 if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) { 1247 if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
1255 xfs_fs_cmn_err(CE_ALERT, mp, 1248 xfs_fs_cmn_err(CE_ALERT, mp,
1256 "xfs_dilocate: ino (0x%llx) != " 1249 "xfs_imap: ino (0x%llx) != "
1257 "XFS_AGINO_TO_INO(mp, agno, agino) " 1250 "XFS_AGINO_TO_INO(mp, agno, agino) "
1258 "(0x%llx)", 1251 "(0x%llx)",
1259 ino, XFS_AGINO_TO_INO(mp, agno, agino)); 1252 ino, XFS_AGINO_TO_INO(mp, agno, agino));
@@ -1262,63 +1255,89 @@ xfs_dilocate(
1262#endif /* DEBUG */ 1255#endif /* DEBUG */
1263 return XFS_ERROR(EINVAL); 1256 return XFS_ERROR(EINVAL);
1264 } 1257 }
1265 if ((mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp))) { 1258
1259 /*
1260 * If the inode cluster size is the same as the blocksize or
1261 * smaller we get to the buffer by simple arithmetics.
1262 */
1263 if (XFS_INODE_CLUSTER_SIZE(mp) <= mp->m_sb.sb_blocksize) {
1266 offset = XFS_INO_TO_OFFSET(mp, ino); 1264 offset = XFS_INO_TO_OFFSET(mp, ino);
1267 ASSERT(offset < mp->m_sb.sb_inopblock); 1265 ASSERT(offset < mp->m_sb.sb_inopblock);
1268 *bno = XFS_AGB_TO_FSB(mp, agno, agbno); 1266
1269 *off = offset; 1267 imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
1270 *len = 1; 1268 imap->im_len = XFS_FSB_TO_BB(mp, 1);
1269 imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
1271 return 0; 1270 return 0;
1272 } 1271 }
1272
1273 blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog; 1273 blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
1274 if (*bno != NULLFSBLOCK) { 1274
1275 /*
1276 * If we get a block number passed from bulkstat we can use it to
1277 * find the buffer easily.
1278 */
1279 if (imap->im_blkno) {
1275 offset = XFS_INO_TO_OFFSET(mp, ino); 1280 offset = XFS_INO_TO_OFFSET(mp, ino);
1276 ASSERT(offset < mp->m_sb.sb_inopblock); 1281 ASSERT(offset < mp->m_sb.sb_inopblock);
1277 cluster_agbno = XFS_FSB_TO_AGBNO(mp, *bno); 1282
1278 *off = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) + 1283 cluster_agbno = XFS_DADDR_TO_AGBNO(mp, imap->im_blkno);
1279 offset; 1284 offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock;
1280 *len = blks_per_cluster; 1285
1286 imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
1287 imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
1281 return 0; 1288 return 0;
1282 } 1289 }
1290
1291 /*
1292 * If the inode chunks are aligned then use simple maths to
1293 * find the location. Otherwise we have to do a btree
1294 * lookup to find the location.
1295 */
1283 if (mp->m_inoalign_mask) { 1296 if (mp->m_inoalign_mask) {
1284 offset_agbno = agbno & mp->m_inoalign_mask; 1297 offset_agbno = agbno & mp->m_inoalign_mask;
1285 chunk_agbno = agbno - offset_agbno; 1298 chunk_agbno = agbno - offset_agbno;
1286 } else { 1299 } else {
1300 xfs_btree_cur_t *cur; /* inode btree cursor */
1301 xfs_agino_t chunk_agino; /* first agino in inode chunk */
1302 __int32_t chunk_cnt; /* count of free inodes in chunk */
1303 xfs_inofree_t chunk_free; /* mask of free inodes in chunk */
1304 xfs_buf_t *agbp; /* agi buffer */
1305 int i; /* temp state */
1306
1287 down_read(&mp->m_peraglock); 1307 down_read(&mp->m_peraglock);
1288 error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); 1308 error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
1289 up_read(&mp->m_peraglock); 1309 up_read(&mp->m_peraglock);
1290 if (error) { 1310 if (error) {
1291#ifdef DEBUG 1311 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
1292 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
1293 "xfs_ialloc_read_agi() returned " 1312 "xfs_ialloc_read_agi() returned "
1294 "error %d, agno %d", 1313 "error %d, agno %d",
1295 error, agno); 1314 error, agno);
1296#endif /* DEBUG */
1297 return error; 1315 return error;
1298 } 1316 }
1317
1299 cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); 1318 cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
1300 if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) { 1319 error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i);
1301#ifdef DEBUG 1320 if (error) {
1302 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: " 1321 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
1303 "xfs_inobt_lookup_le() failed"); 1322 "xfs_inobt_lookup_le() failed");
1304#endif /* DEBUG */
1305 goto error0; 1323 goto error0;
1306 } 1324 }
1307 if ((error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt, 1325
1308 &chunk_free, &i))) { 1326 error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,
1309#ifdef DEBUG 1327 &chunk_free, &i);
1310 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: " 1328 if (error) {
1329 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
1311 "xfs_inobt_get_rec() failed"); 1330 "xfs_inobt_get_rec() failed");
1312#endif /* DEBUG */
1313 goto error0; 1331 goto error0;
1314 } 1332 }
1315 if (i == 0) { 1333 if (i == 0) {
1316#ifdef DEBUG 1334#ifdef DEBUG
1317 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: " 1335 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
1318 "xfs_inobt_get_rec() failed"); 1336 "xfs_inobt_get_rec() failed");
1319#endif /* DEBUG */ 1337#endif /* DEBUG */
1320 error = XFS_ERROR(EINVAL); 1338 error = XFS_ERROR(EINVAL);
1321 } 1339 }
1340 error0:
1322 xfs_trans_brelse(tp, agbp); 1341 xfs_trans_brelse(tp, agbp);
1323 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 1342 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
1324 if (error) 1343 if (error)
@@ -1326,19 +1345,35 @@ xfs_dilocate(
1326 chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino); 1345 chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino);
1327 offset_agbno = agbno - chunk_agbno; 1346 offset_agbno = agbno - chunk_agbno;
1328 } 1347 }
1348
1329 ASSERT(agbno >= chunk_agbno); 1349 ASSERT(agbno >= chunk_agbno);
1330 cluster_agbno = chunk_agbno + 1350 cluster_agbno = chunk_agbno +
1331 ((offset_agbno / blks_per_cluster) * blks_per_cluster); 1351 ((offset_agbno / blks_per_cluster) * blks_per_cluster);
1332 offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) + 1352 offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
1333 XFS_INO_TO_OFFSET(mp, ino); 1353 XFS_INO_TO_OFFSET(mp, ino);
1334 *bno = XFS_AGB_TO_FSB(mp, agno, cluster_agbno); 1354
1335 *off = offset; 1355 imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
1336 *len = blks_per_cluster; 1356 imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
1357 imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
1358
1359 /*
1360 * If the inode number maps to a block outside the bounds
1361 * of the file system then return NULL rather than calling
1362 * read_buf and panicing when we get an error from the
1363 * driver.
1364 */
1365 if ((imap->im_blkno + imap->im_len) >
1366 XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
1367 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
1368 "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
1369 " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
1370 (unsigned long long) imap->im_blkno,
1371 (unsigned long long) imap->im_len,
1372 XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
1373 return XFS_ERROR(EINVAL);
1374 }
1375
1337 return 0; 1376 return 0;
1338error0:
1339 xfs_trans_brelse(tp, agbp);
1340 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
1341 return error;
1342} 1377}
1343 1378
1344/* 1379/*
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index ccf554a6e0a1..50f558a4e0a8 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -20,6 +20,7 @@
20 20
21struct xfs_buf; 21struct xfs_buf;
22struct xfs_dinode; 22struct xfs_dinode;
23struct xfs_imap;
23struct xfs_mount; 24struct xfs_mount;
24struct xfs_trans; 25struct xfs_trans;
25 26
@@ -104,17 +105,14 @@ xfs_difree(
104 xfs_ino_t *first_ino); /* first inode in deleted cluster */ 105 xfs_ino_t *first_ino); /* first inode in deleted cluster */
105 106
106/* 107/*
107 * Return the location of the inode in bno/len/off, 108 * Return the location of the inode in imap, for mapping it into a buffer.
108 * for mapping it into a buffer.
109 */ 109 */
110int 110int
111xfs_dilocate( 111xfs_imap(
112 struct xfs_mount *mp, /* file system mount structure */ 112 struct xfs_mount *mp, /* file system mount structure */
113 struct xfs_trans *tp, /* transaction pointer */ 113 struct xfs_trans *tp, /* transaction pointer */
114 xfs_ino_t ino, /* inode to locate */ 114 xfs_ino_t ino, /* inode to locate */
115 xfs_fsblock_t *bno, /* output: block containing inode */ 115 struct xfs_imap *imap, /* location map structure */
116 int *len, /* output: num blocks in cluster*/
117 int *off, /* output: index in block of inode */
118 uint flags); /* flags for inode btree lookup */ 116 uint flags); /* flags for inode btree lookup */
119 117
120/* 118/*
diff --git a/fs/xfs/xfs_imap.h b/fs/xfs/xfs_imap.h
index f9ce62890ea5..08690005739e 100644
--- a/fs/xfs/xfs_imap.h
+++ b/fs/xfs/xfs_imap.h
@@ -25,14 +25,7 @@
25typedef struct xfs_imap { 25typedef struct xfs_imap {
26 xfs_daddr_t im_blkno; /* starting BB of inode chunk */ 26 xfs_daddr_t im_blkno; /* starting BB of inode chunk */
27 uint im_len; /* length in BBs of inode chunk */ 27 uint im_len; /* length in BBs of inode chunk */
28 xfs_agblock_t im_agblkno; /* logical block of inode chunk in ag */
29 ushort im_ioffset; /* inode offset in block in "inodes" */
30 ushort im_boffset; /* inode offset in block in bytes */ 28 ushort im_boffset; /* inode offset in block in bytes */
31} xfs_imap_t; 29} xfs_imap_t;
32 30
33struct xfs_mount;
34struct xfs_trans;
35int xfs_imap(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
36 xfs_imap_t *, uint);
37
38#endif /* __XFS_IMAP_H__ */ 31#endif /* __XFS_IMAP_H__ */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 663ff9e517fd..bf528b725ae1 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -266,7 +266,7 @@ xfs_inotobp(
266 * in once, thus we can use the mapping information stored in the inode 266 * in once, thus we can use the mapping information stored in the inode
267 * rather than calling xfs_imap(). This allows us to avoid the overhead 267 * rather than calling xfs_imap(). This allows us to avoid the overhead
268 * of looking at the inode btree for small block file systems 268 * of looking at the inode btree for small block file systems
269 * (see xfs_dilocate()). 269 * (see xfs_imap()).
270 */ 270 */
271int 271int
272xfs_itobp( 272xfs_itobp(
@@ -2508,64 +2508,6 @@ xfs_idata_realloc(
2508 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); 2508 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
2509} 2509}
2510 2510
2511
2512
2513
2514/*
2515 * Map inode to disk block and offset.
2516 *
2517 * mp -- the mount point structure for the current file system
2518 * tp -- the current transaction
2519 * ino -- the inode number of the inode to be located
2520 * imap -- this structure is filled in with the information necessary
2521 * to retrieve the given inode from disk
2522 * flags -- flags to pass to xfs_dilocate indicating whether or not
2523 * lookups in the inode btree were OK or not
2524 */
2525int
2526xfs_imap(
2527 xfs_mount_t *mp,
2528 xfs_trans_t *tp,
2529 xfs_ino_t ino,
2530 xfs_imap_t *imap,
2531 uint flags)
2532{
2533 xfs_fsblock_t fsbno;
2534 int len;
2535 int off;
2536 int error;
2537
2538 fsbno = imap->im_blkno ?
2539 XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
2540 error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
2541 if (error)
2542 return error;
2543
2544 imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
2545 imap->im_len = XFS_FSB_TO_BB(mp, len);
2546 imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
2547 imap->im_ioffset = (ushort)off;
2548 imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
2549
2550 /*
2551 * If the inode number maps to a block outside the bounds
2552 * of the file system then return NULL rather than calling
2553 * read_buf and panicing when we get an error from the
2554 * driver.
2555 */
2556 if ((imap->im_blkno + imap->im_len) >
2557 XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
2558 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
2559 "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
2560 " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
2561 (unsigned long long) imap->im_blkno,
2562 (unsigned long long) imap->im_len,
2563 XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
2564 return EINVAL;
2565 }
2566 return 0;
2567}
2568
2569void 2511void
2570xfs_idestroy_fork( 2512xfs_idestroy_fork(
2571 xfs_inode_t *ip, 2513 xfs_inode_t *ip,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index db1f68840727..0a9ad1c56a87 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -157,7 +157,7 @@ typedef struct xfs_icdinode {
157#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */ 157#define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */
158 158
159/* 159/*
160 * Flags for xfs_inotobp, xfs_imap() and xfs_dilocate(). 160 * Flags for xfs_inotobp and xfs_imap().
161 */ 161 */
162#define XFS_IMAP_BULKSTAT 0x1 162#define XFS_IMAP_BULKSTAT 0x1
163 163