read-cache.c: allow unaligned mapping of the index file

Both the on-disk format v2 and v3 pads the "name" field to the multiple of eight to make sure that various quantities in network long/short type can be accessed with ntohl/ntohs without having to worry about alignment, but this forces us to waste disk I/O bandwidth. Introduce ntoh_s()/ntoh_l() macros that the callers can use as if they were the regular ntohs()/ntohl() on a field that may not be aligned correctly. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Apr 3, 2012 at 15:53 UTC d60c49c2d7f683cd24a738533846cd3e34f2073e
1 file changed +32 -12
read-cache.c
+32 -12
@@ -1285,6 +1285,26 @@ int read_index(struct index_state *istate)
1285 return read_index_from(istate, get_index_file());
1286 }
1287
1288 +#ifndef NEEDS_ALIGNED_ACCESS
1289 +#define ntoh_s(var) ntohs(var)
1290 +#define ntoh_l(var) ntohl(var)
1291 +#else
1292 +static inline uint16_t ntoh_s_force_align(void *p)
1293 +{
1294 + uint16_t x;
1295 + memcpy(&x, p, sizeof(x));
1296 + return ntohs(x);
1297 +}
1298 +static inline uint32_t ntoh_l_force_align(void *p)
1299 +{
1300 + uint32_t x;
1301 + memcpy(&x, p, sizeof(x));
1302 + return ntohl(x);
1303 +}
1304 +#define ntoh_s(var) ntoh_s_force_align(&(var))
1305 +#define ntoh_l(var) ntoh_l_force_align(&(var))
1306 +#endif
1307 +
1308 static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
1309 {
1310 struct cache_entry *ce;
@@ -1293,14 +1313,14 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
1313 unsigned int flags;
1314
1315 /* On-disk flags are just 16 bits */
1296 - flags = ntohs(ondisk->flags);
1316 + flags = ntoh_s(ondisk->flags);
1317 len = flags & CE_NAMEMASK;
1318
1319 if (flags & CE_EXTENDED) {
1320 struct ondisk_cache_entry_extended *ondisk2;
1321 int extended_flags;
1322 ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
1303 - extended_flags = ntohs(ondisk2->flags2) << 16;
1323 + extended_flags = ntoh_s(ondisk2->flags2) << 16;
1324 /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
1325 if (extended_flags & ~CE_EXTENDED_FLAGS)
1326 die("Unknown index entry format %08x", extended_flags);
@@ -1315,16 +1335,16 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
1335
1336 ce = xmalloc(cache_entry_size(len));
1337
1318 - ce->ce_ctime.sec = ntohl(ondisk->ctime.sec);
1319 - ce->ce_mtime.sec = ntohl(ondisk->mtime.sec);
1320 - ce->ce_ctime.nsec = ntohl(ondisk->ctime.nsec);
1321 - ce->ce_mtime.nsec = ntohl(ondisk->mtime.nsec);
1322 - ce->ce_dev = ntohl(ondisk->dev);
1323 - ce->ce_ino = ntohl(ondisk->ino);
1324 - ce->ce_mode = ntohl(ondisk->mode);
1325 - ce->ce_uid = ntohl(ondisk->uid);
1326 - ce->ce_gid = ntohl(ondisk->gid);
1327 - ce->ce_size = ntohl(ondisk->size);
1338 + ce->ce_ctime.sec = ntoh_l(ondisk->ctime.sec);
1339 + ce->ce_mtime.sec = ntoh_l(ondisk->mtime.sec);
1340 + ce->ce_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
1341 + ce->ce_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
1342 + ce->ce_dev = ntoh_l(ondisk->dev);
1343 + ce->ce_ino = ntoh_l(ondisk->ino);
1344 + ce->ce_mode = ntoh_l(ondisk->mode);
1345 + ce->ce_uid = ntoh_l(ondisk->uid);
1346 + ce->ce_gid = ntoh_l(ondisk->gid);
1347 + ce->ce_size = ntoh_l(ondisk->size);
1348 ce->ce_flags = flags;
1349
1350 hashcpy(ce->sha1, ondisk->sha1);