diff options
| -rw-r--r-- | fs/xfs/xfs_ialloc.c | 129 | ||||
| -rw-r--r-- | fs/xfs/xfs_ialloc.h | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_imap.h | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 60 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.h | 2 |
5 files changed, 88 insertions, 120 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0ce56d6a492..348ac30174c 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*/ | ||
| 1202 | int | 1202 | int |
| 1203 | xfs_dilocate( | 1203 | xfs_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; |
| 1338 | error0: | ||
| 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 ccf554a6e0a..50f558a4e0a 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | struct xfs_buf; | 21 | struct xfs_buf; |
| 22 | struct xfs_dinode; | 22 | struct xfs_dinode; |
| 23 | struct xfs_imap; | ||
| 23 | struct xfs_mount; | 24 | struct xfs_mount; |
| 24 | struct xfs_trans; | 25 | struct 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 | */ |
| 110 | int | 110 | int |
| 111 | xfs_dilocate( | 111 | xfs_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 f9ce62890ea..08690005739 100644 --- a/fs/xfs/xfs_imap.h +++ b/fs/xfs/xfs_imap.h | |||
| @@ -25,14 +25,7 @@ | |||
| 25 | typedef struct xfs_imap { | 25 | typedef 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 | ||
| 33 | struct xfs_mount; | ||
| 34 | struct xfs_trans; | ||
| 35 | int 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 663ff9e517f..bf528b725ae 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 | */ |
| 271 | int | 271 | int |
| 272 | xfs_itobp( | 272 | xfs_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 | */ | ||
| 2525 | int | ||
| 2526 | xfs_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 | |||
| 2569 | void | 2511 | void |
| 2570 | xfs_idestroy_fork( | 2512 | xfs_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 db1f6884072..0a9ad1c56a8 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 | ||
