119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o/* 219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * icount.c --- an efficient inode count abstraction 319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1997 Theodore Ts'o. 519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 124cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <unistd.h> 144cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h> 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <stdio.h> 171b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o#include <sys/stat.h> 181b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o#include <fcntl.h> 191b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o#include <errno.h> 2019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 21b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 2219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include "ext2fs.h" 231b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o#include "tdb.h" 2419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o/* 2619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * The data storage strategy used by icount relies on the observation 2719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * that most inode counts are either zero (for non-allocated inodes), 2819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * one (for most files), and only a few that are two or more 2919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * (directories and files that are linked to more than one directory). 3019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 3119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Also, e2fsck tends to load the icount data sequentially. 3219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 3319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * So, we use an inode bitmap to indicate which inodes have a count of 3419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * one, and then use a sorted list to store the counts for inodes 3519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * which are greater than one. 3619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 3719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * We also use an optional bitmap to indicate which inodes are already 3819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * in the sorted list, to speed up the use of this abstraction by 3919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * e2fsck's pass 2. Pass 2 increments inode counts as it finds them, 4019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * so this extra bitmap avoids searching the sorted list to see if a 4119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * particular inode is on the sorted list already. 4219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 4319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 4419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostruct ext2_icount_el { 4531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino; 4660bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 count; 4719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o}; 4819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 4919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostruct ext2_icount { 503cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o errcode_t magic; 5119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2fs_inode_bitmap single; 5219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2fs_inode_bitmap multiple; 5331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t count; 5431dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t size; 5531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t num_inodes; 56544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_ino_t cursor; 5719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o struct ext2_icount_el *list; 581b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o struct ext2_icount_el *last_lookup; 591b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o char *tdb_fn; 601b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o TDB_CONTEXT *tdb; 6119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o}; 6219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 6360bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o/* 6460bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o * We now use a 32-bit counter field because it doesn't cost us 6560bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o * anything extra for the in-memory data structure, due to alignment 6660bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o * padding. But there's no point changing the interface if most of 6760bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o * the time we only care if the number is bigger than 65,000 or not. 6860bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o * So use the following translation function to return a 16-bit count. 6960bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o */ 7060bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o#define icount_16_xlate(x) (((x) > 65500) ? 65500 : (x)) 7160bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o 7219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ovoid ext2fs_free_icount(ext2_icount_t icount) 7319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 7419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!icount) 7519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 7619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 7719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->magic = 0; 7819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->list) 79c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&icount->list); 8019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->single) 8119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2fs_free_inode_bitmap(icount->single); 8219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) 8319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2fs_free_inode_bitmap(icount->multiple); 841b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->tdb) 851b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tdb_close(icount->tdb); 861b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->tdb_fn) { 871b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o unlink(icount->tdb_fn); 881b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o free(icount->tdb_fn); 891b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 901b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 91c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&icount); 9219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 9319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 941b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostatic errcode_t alloc_icount(ext2_filsys fs, int flags, ext2_icount_t *ret) 9519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 9619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2_icount_t icount; 9719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o errcode_t retval; 9819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 991b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *ret = 0; 1001b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 101c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount); 1027b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1037b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 10419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(icount, 0, sizeof(struct ext2_icount)); 10519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_allocate_inode_bitmap(fs, "icount", &icount->single); 10719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (retval) 10819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 10919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 11019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (flags & EXT2_ICOUNT_OPT_INCREMENT) { 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_allocate_inode_bitmap(fs, "icount_inc", 11219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o &icount->multiple); 11319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (retval) 11419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 11519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } else 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->multiple = 0; 11719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1181b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o icount->magic = EXT2_ET_MAGIC_ICOUNT; 1191b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o icount->num_inodes = fs->super->s_inodes_count; 1201b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1211b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *ret = icount; 1221b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 1231b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1241b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oerrout: 1251b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2fs_free_icount(icount); 1261b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return(retval); 1271b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 1281b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1291b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostruct uuid { 1301b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u32 time_low; 1311b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u16 time_mid; 1321b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u16 time_hi_and_version; 1331b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u16 clock_seq; 1341b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u8 node[6]; 1351b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o}; 1361b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1371b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostatic void unpack_uuid(void *in, struct uuid *uu) 1381b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 1391b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u8 *ptr = in; 1401b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o __u32 tmp; 1411b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1421b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = *ptr++; 1431b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1441b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1451b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1461b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uu->time_low = tmp; 1471b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1481b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = *ptr++; 1491b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1501b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uu->time_mid = tmp; 1511b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1521b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = *ptr++; 1531b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1541b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uu->time_hi_and_version = tmp; 1551b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1561b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = *ptr++; 1571b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o tmp = (tmp << 8) | *ptr++; 1581b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uu->clock_seq = tmp; 1591b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1601b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o memcpy(uu->node, ptr, 6); 1611b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 1621b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1631b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostatic void uuid_unparse(void *uu, char *out) 1641b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 1651b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o struct uuid uuid; 1661b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1671b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o unpack_uuid(uu, &uuid); 1681b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o sprintf(out, 1691b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 1701b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, 1711b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, 1721b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uuid.node[0], uuid.node[1], uuid.node[2], 1731b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uuid.node[3], uuid.node[4], uuid.node[5]); 1741b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 1751b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1761b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oerrcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, 1771b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o int flags, ext2_icount_t *ret) 1781b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 1791b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2_icount_t icount; 1801b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o errcode_t retval; 1811b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o char *fn, uuid[40]; 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t num_inodes; 1831b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o int fd; 1841b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1851b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = alloc_icount(fs, flags, &icount); 1861b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (retval) 1871b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return retval; 1881b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 1891b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &fn); 1901b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (retval) 1911b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o goto errout; 1921b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o uuid_unparse(fs->super->s_uuid, uuid); 1931b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid); 1941b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o fd = mkstemp(fn); 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fd < 0) 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return fd; 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * This is an overestimate of the size that we will need; the 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * ideal value is the number of used inodes with a count 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * greater than 1. OTOH the times when we really need this is 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * with the backup programs that use lots of hard links, in 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * which case the number of inodes in use approaches the ideal 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * value. 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count; 2074e523bbe00cfa0240b4581eeca0c097b05c9fe3eTheodore Ts'o 2081b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o icount->tdb_fn = fn; 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC, 2101b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o O_RDWR | O_CREAT | O_TRUNC, 0600); 2111b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->tdb) { 2121b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o close(fd); 2131b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *ret = icount; 2141b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 2151b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 2161b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2171b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = errno; 2181b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o close(fd); 2191b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2201b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oerrout: 2211b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2fs_free_icount(icount); 2221b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return(retval); 2231b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 2241b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2251b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oerrcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size, 2261b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2_icount_t hint, ext2_icount_t *ret) 2271b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 2281b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2_icount_t icount; 2291b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o errcode_t retval; 2301b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o size_t bytes; 2311b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2_ino_t i; 2321b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2331b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (hint) { 2341b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); 2351b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (hint->size > size) 2361b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o size = (size_t) hint->size; 2371b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 2381b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2391b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = alloc_icount(fs, flags, &icount); 2401b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (retval) 2411b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return retval; 2421b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 24319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (size) { 24419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->size = size; 24519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } else { 24619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 24719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Figure out how many special case inode counts we will 24819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * have. We know we will need one for each directory; 24919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * we also need to reserve some extra room for file links 25019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 25119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o retval = ext2fs_get_num_dirs(fs, &icount->size); 25219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (retval) 25319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 25419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->size += fs->super->s_inodes_count / 50; 25519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 2561b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 2573cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el)); 25819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#if 0 259d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen printf("Icount allocated %u entries, %d bytes.\n", 26019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->size, bytes); 26119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#endif 262ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(icount->size, sizeof(struct ext2_icount_el), 263ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o &icount->list); 2647b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 26519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto errout; 26619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o memset(icount->list, 0, bytes); 26719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 26819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->count = 0; 26919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->cursor = 0; 27019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 271521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o /* 272521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * Populate the sorted list with those entries which were 273521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * found in the hint icount (since those are ones which will 274521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * likely need to be in the sorted list this time around). 275521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o */ 276521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (hint) { 277521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o for (i=0; i < hint->count; i++) 278521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o icount->list[i].ino = hint->list[i].ino; 279521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o icount->count = hint->count; 280521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 28119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 282521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o *ret = icount; 28319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 28419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 28519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'oerrout: 28619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o ext2fs_free_icount(icount); 28719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return(retval); 28819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 28919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 2901b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oerrcode_t ext2fs_create_icount(ext2_filsys fs, int flags, 291544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int size, 292521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o ext2_icount_t *ret) 29319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 294521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return ext2fs_create_icount2(fs, flags, size, 0, ret); 29519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 29619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 29719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o/* 298521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * insert_icount_el() --- Insert a new entry into the sorted list at a 299521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * specified position. 30019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 301521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'ostatic struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, 30231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino, int pos) 30319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 3047b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o struct ext2_icount_el *el; 3057b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o errcode_t retval; 3061b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o ext2_ino_t new_size = 0; 307521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o int num; 30819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 3091b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->last_lookup && icount->last_lookup->ino == ino) 3101b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return icount->last_lookup; 3111b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 31219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->count >= icount->size) { 31319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->count) { 3143cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o new_size = icount->list[(unsigned)icount->count-1].ino; 3151b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o new_size = (ext2_ino_t) (icount->count * 31630e50b7cdd6f5bbd5f2d6a2ee8ce0d4522336397Theodore Ts'o ((float) icount->num_inodes / new_size)); 31719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 31819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (new_size < (icount->size + 100)) 31919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o new_size = icount->size + 100; 32019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#if 0 321d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen printf("Reallocating icount %u entries...\n", new_size); 3221b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o#endif 32376f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o retval = ext2fs_resize_mem((size_t) icount->size * 32476f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o sizeof(struct ext2_icount_el), 32576f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o (size_t) new_size * 3267b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o sizeof(struct ext2_icount_el), 327c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &icount->list); 3287b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 32919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 33019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o icount->size = new_size; 33119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 3323cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o num = (int) icount->count - pos; 333521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (num < 0) 334521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; /* should never happen */ 335521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (num) { 336521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o memmove(&icount->list[pos+1], &icount->list[pos], 337521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o sizeof(struct ext2_icount_el) * num); 338521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 339521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o icount->count++; 340521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o el = &icount->list[pos]; 341521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o el->count = 0; 342521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o el->ino = ino; 3431b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o icount->last_lookup = el; 344521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return el; 345521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o} 346521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 347521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o/* 348521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * get_icount_el() --- given an inode number, try to find icount 349521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * information in the sorted list. If the create flag is set, 350521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * and we can't find an entry, create one in the sorted list. 351521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o */ 352521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'ostatic struct ext2_icount_el *get_icount_el(ext2_icount_t icount, 35331dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o ext2_ino_t ino, int create) 354521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o{ 355521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o int low, high, mid; 356521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 357521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (!icount || !icount->list) 358521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; 35919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 360521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (create && ((icount->count == 0) || 3613cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o (ino > icount->list[(unsigned)icount->count-1].ino))) { 3623cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o return insert_icount_el(icount, ino, (unsigned) icount->count); 363521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 364521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->count == 0) 365521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; 3661b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 367521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->cursor >= icount->count) 368521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o icount->cursor = 0; 369521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (ino == icount->list[icount->cursor].ino) 370521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return &icount->list[icount->cursor++]; 371521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#if 0 372521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o printf("Non-cursor get_icount_el: %u\n", ino); 373521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o#endif 374521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o low = 0; 3753cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o high = (int) icount->count-1; 376521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o while (low <= high) { 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mid = ((unsigned)low + (unsigned)high) >> 1; 378521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (ino == icount->list[mid].ino) { 379521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o icount->cursor = mid+1; 380521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return &icount->list[mid]; 381521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 382521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (ino < icount->list[mid].ino) 383521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o high = mid-1; 384521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o else 385521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o low = mid+1; 386521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 38719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 388521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * If we need to create a new entry, it should be right at 389521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * low (where high will be left at low-1). 39019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 391521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (create) 392521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return insert_icount_el(icount, ino, low); 393521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; 394521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o} 395521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 3961b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostatic errcode_t set_inode_count(ext2_icount_t icount, ext2_ino_t ino, 39760bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 count) 3981b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 3991b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o struct ext2_icount_el *el; 4001b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o TDB_DATA key, data; 4011b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4021b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->tdb) { 4031b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o key.dptr = (unsigned char *) &ino; 4041b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o key.dsize = sizeof(ext2_ino_t); 4051b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o data.dptr = (unsigned char *) &count; 40660bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o data.dsize = sizeof(__u32); 4071b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (count) { 4081b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (tdb_store(icount->tdb, key, data, TDB_REPLACE)) 4091b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return tdb_error(icount->tdb) + 4101b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o EXT2_ET_TDB_SUCCESS; 4111b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } else { 4121b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (tdb_delete(icount->tdb, key)) 4131b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return tdb_error(icount->tdb) + 4141b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o EXT2_ET_TDB_SUCCESS; 4151b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 4161b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 4171b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 4181b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4191b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o el = get_icount_el(icount, ino, 1); 4201b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (!el) 4211b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return EXT2_ET_NO_MEMORY; 4221b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4231b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o el->count = count; 4241b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 4251b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 4261b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4271b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'ostatic errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino, 42860bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 *count) 4291b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o{ 4301b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o struct ext2_icount_el *el; 4311b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o TDB_DATA key, data; 4321b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4331b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (icount->tdb) { 4341b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o key.dptr = (unsigned char *) &ino; 4351b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o key.dsize = sizeof(ext2_ino_t); 4361b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4371b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o data = tdb_fetch(icount->tdb, key); 4381b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (data.dptr == NULL) { 4391b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *count = 0; 4401b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return tdb_error(icount->tdb) + EXT2_ET_TDB_SUCCESS; 4411b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 4421b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 44360bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o *count = *((__u32 *) data.dptr); 444a1f642728fe6fd2c361343fec349808ea8a524f4Theodore Ts'o free(data.dptr); 4451b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 4461b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 4471b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o el = get_icount_el(icount, ino, 0); 4481b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (!el) { 4491b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *count = 0; 4501b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return ENOENT; 4511b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 4521b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 4531b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o *count = el->count; 4541b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return 0; 4551b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o} 4561b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 457521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'oerrcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) 458521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o{ 459521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o errcode_t ret = 0; 460544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int i; 461521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o const char *bad = "bad icount"; 4621b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 463521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); 464521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 465521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->count > icount->size) { 466521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o fprintf(out, "%s: count > size\n", bad); 4671f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 468521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 469521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o for (i=1; i < icount->count; i++) { 470521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->list[i-1].ino >= icount->list[i].ino) { 47131dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", 472521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o bad, i-1, icount->list[i-1].ino, 473521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o i, icount->list[i].ino); 4741f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o ret = EXT2_ET_INVALID_ARGUMENT; 47519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 47619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 477521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return ret; 47819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 47919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 48031dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) 48119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 48260bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 val; 48319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); 48419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 485521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (!ino || (ino > icount->num_inodes)) 4861f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 487521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_inode_bitmap2(icount->single, ino)) { 48919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *ret = 1; 49019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 49119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 492521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->multiple && 493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_inode_bitmap2(icount->multiple, ino)) { 494521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o *ret = 0; 495521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o return 0; 496521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 49760bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o get_inode_count(icount, ino, &val); 49860bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o *ret = icount_16_xlate(val); 49919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 50019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 50119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 50231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, 50319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o __u16 *ret) 50419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 50560bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 curr_value; 50619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 50719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); 50819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 509521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (!ino || (ino > icount->num_inodes)) 5101f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 511521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_inode_bitmap2(icount->single, ino)) { 51319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 51419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * If the existing count is 1, then we know there is 515521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o * no entry in the list. 51619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 5171b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (set_inode_count(icount, ino, 2)) 5181f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_NO_MEMORY; 5191b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o curr_value = 2; 520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->single, ino); 52119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } else if (icount->multiple) { 52219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 52319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * The count is either zero or greater than 1; if the 52419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * inode is set in icount->multiple, then there should 5251b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o * be an entry in the list, so we need to fix it. 52619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_inode_bitmap2(icount->multiple, ino)) { 5281b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o get_inode_count(icount, ino, &curr_value); 5291b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o curr_value++; 5301b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (set_inode_count(icount, ino, curr_value)) 5311f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_NO_MEMORY; 53219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } else { 53319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 53419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * The count was zero; mark the single bitmap 53519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * and return. 53619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_inode_bitmap2(icount->single, ino); 53819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ret) 53919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *ret = 1; 54019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 54119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 54219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } else { 54319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 54419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * The count is either zero or greater than 1; try to 54519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * find an entry in the list to determine which. 54619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 5471b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o get_inode_count(icount, ino, &curr_value); 5481b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o curr_value++; 5491b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (set_inode_count(icount, ino, curr_value)) 5501f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_NO_MEMORY; 551521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o } 55219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) 553e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_inode_bitmap2(icount->multiple, ino); 55419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ret) 55560bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o *ret = icount_16_xlate(curr_value); 55619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 55719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 55819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 55931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, 56019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o __u16 *ret) 56119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 56260bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o __u32 curr_value; 56319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 564521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (!ino || (ino > icount->num_inodes)) 5651f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 566521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 56719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); 56819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 569e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_inode_bitmap2(icount->single, ino)) { 570e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->single, ino); 57119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) 572e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->multiple, ino); 57319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o else { 5741b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o set_inode_count(icount, ino, 0); 57519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 57619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ret) 57719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *ret = 0; 57819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 57919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 58019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 581521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (icount->multiple && 582e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_inode_bitmap2(icount->multiple, ino)) 5831f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 5841b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o 5851b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o get_inode_count(icount, ino, &curr_value); 5861b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (!curr_value) 5871f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 5881b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o curr_value--; 5891b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (set_inode_count(icount, ino, curr_value)) 5901b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o return EXT2_ET_NO_MEMORY; 59119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 5921b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (curr_value == 1) 593e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_inode_bitmap2(icount->single, ino); 5941b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if ((curr_value == 0) && icount->multiple) 595e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->multiple, ino); 59619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 59719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ret) 59860bbd1af533daf8c726d6e5e4f17b293494bd939Theodore Ts'o *ret = icount_16_xlate(curr_value); 59919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 60019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 60119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 60231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, 60319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o __u16 count) 60419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 605521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o if (!ino || (ino > icount->num_inodes)) 6061f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_INVALID_ARGUMENT; 607521e36857227b21e7ab47b0a97f788d2af9f9717Theodore Ts'o 60819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); 60919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 61019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (count == 1) { 611e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_inode_bitmap2(icount->single, ino); 61219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) 613e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->multiple, ino); 61419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 61519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 61619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (count == 0) { 617e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->single, ino); 61819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) { 61919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 62019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * If the icount->multiple bitmap is enabled, 62119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * we can just clear both bitmaps and we're done 62219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 623e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->multiple, ino); 6241b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } else 6251b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o set_inode_count(icount, ino, 0); 62619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 62719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 62819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 6291b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (set_inode_count(icount, ino, count)) 6301f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o return EXT2_ET_NO_MEMORY; 631e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_inode_bitmap2(icount->single, ino); 63219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (icount->multiple) 633e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_inode_bitmap2(icount->multiple, ino); 63419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 63519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 63619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 63731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount) 63819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 63919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT) 64019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return 0; 64119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 64219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return icount->size; 64319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 6441cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6451cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#ifdef DEBUG 6461cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6471cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'oext2_filsys test_fs; 6481cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'oext2_icount_t icount; 6491cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6501cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#define EXIT 0x00 6511cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#define FETCH 0x01 6521cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#define STORE 0x02 6531cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#define INCREMENT 0x03 6541cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#define DECREMENT 0x04 6551cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6561cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'ostruct test_program { 6571cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o int cmd; 6581cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o ext2_ino_t ino; 6591cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o __u16 arg; 6601cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o __u16 expected; 6611cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o}; 6621cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6631cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'ostruct test_program prog[] = { 6641cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 42, 42, 42 }, 6651cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 1, 1, 1 }, 6661cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 2, 2, 2 }, 6671cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 3, 3, 3 }, 6681cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 10, 1, 1 }, 6691cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 42, 0, 0 }, 6701cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { INCREMENT, 5, 0, 1 }, 6711cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { INCREMENT, 5, 0, 2 }, 6721cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { INCREMENT, 5, 0, 3 }, 6731cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { INCREMENT, 5, 0, 4 }, 6741cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 5, 0, 3 }, 6751cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 5, 0, 2 }, 6761cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 5, 0, 1 }, 6771cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 5, 0, 0 }, 6781cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { FETCH, 10, 0, 1 }, 6791cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { FETCH, 1, 0, 1 }, 6801cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { FETCH, 2, 0, 2 }, 6811cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { FETCH, 3, 0, 3 }, 6821cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { INCREMENT, 1, 0, 2 }, 6831cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 2, 0, 1 }, 6841cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { DECREMENT, 2, 0, 0 }, 6851cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { FETCH, 12, 0, 0 }, 6861cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { EXIT, 0, 0, 0 } 6871cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o}; 6881cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 6891cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'ostruct test_program extended[] = { 6901cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 1, 1, 1 }, 6911cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 2, 2, 2 }, 6921cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 3, 3, 3 }, 6931cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 4, 4, 4 }, 6941cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 5, 5, 5 }, 6951cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 6, 1, 1 }, 6961cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 7, 2, 2 }, 6971cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 8, 3, 3 }, 6981cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 9, 4, 4 }, 6991cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 10, 5, 5 }, 7001cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 11, 1, 1 }, 7011cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 12, 2, 2 }, 7021cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 13, 3, 3 }, 7031cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 14, 4, 4 }, 7041cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 15, 5, 5 }, 7051cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 16, 1, 1 }, 7061cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 17, 2, 2 }, 7071cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 18, 3, 3 }, 7081cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 19, 4, 4 }, 7091cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 20, 5, 5 }, 7101cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 21, 1, 1 }, 7111cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 22, 2, 2 }, 7121cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 23, 3, 3 }, 7131cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 24, 4, 4 }, 7141cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 25, 5, 5 }, 7151cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 26, 1, 1 }, 7161cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 27, 2, 2 }, 7171cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 28, 3, 3 }, 7181cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 29, 4, 4 }, 7191cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { STORE, 30, 5, 5 }, 7201cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o { EXIT, 0, 0, 0 } 7211cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o}; 7221cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 7231cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o/* 7241cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o * Setup the variables for doing the inode scan test. 7251cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o */ 7261cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'ostatic void setup(void) 7271cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o{ 7281cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o errcode_t retval; 7291cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o struct ext2_super_block param; 7301cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 7311cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o initialize_ext2_error_table(); 7321cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 7331cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o memset(¶m, 0, sizeof(param)); 734e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count_set(¶m, 12000); 7351cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 736e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, 7371cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o test_io_manager, &test_fs); 7381cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 7391cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("setup", retval, 7401cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while initializing filesystem"); 7411cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 7421cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 7431cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_allocate_tables(test_fs); 7441cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 7451cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("setup", retval, 7461cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while allocating tables for test filesystem"); 7471cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 7481cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 7491cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o} 7501cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 7511b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'oint run_test(int flags, int size, char *dir, struct test_program *prog) 7521cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o{ 7531cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o errcode_t retval; 7541cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o ext2_icount_t icount; 7551cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o struct test_program *pc; 7561cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o __u16 result; 7571cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o int problem = 0; 7581cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 7591b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (dir) { 7601b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = ext2fs_create_icount_tdb(test_fs, dir, 7611b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o flags, &icount); 7621b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (retval) { 7631b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o com_err("run_test", retval, 7641b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o "while creating icount using tdb"); 7651b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o exit(1); 7661b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 7671b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } else { 7681b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o retval = ext2fs_create_icount2(test_fs, flags, size, 0, 7691b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o &icount); 7701b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (retval) { 7711b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o com_err("run_test", retval, "while creating icount"); 7721b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o exit(1); 7731b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o } 7741cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 7751cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o for (pc = prog; pc->cmd != EXIT; pc++) { 7761cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o switch (pc->cmd) { 7771cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o case FETCH: 7781cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("icount_fetch(%u) = ", pc->ino); 7791cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o break; 7801cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o case STORE: 7811cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_icount_store(icount, pc->ino, pc->arg); 7821cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 7831cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("run_test", retval, 7841cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while calling icount_store"); 7851cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 7861cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 7871cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("icount_store(%u, %u) = ", pc->ino, pc->arg); 7881cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o break; 7891cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o case INCREMENT: 7901cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_icount_increment(icount, pc->ino, 0); 7911cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 7921cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("run_test", retval, 7931cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while calling icount_increment"); 7941cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 7951cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 7961cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("icount_increment(%u) = ", pc->ino); 7971cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o break; 7981cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o case DECREMENT: 7991cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_icount_decrement(icount, pc->ino, 0); 8001cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 8011cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("run_test", retval, 8021cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while calling icount_decrement"); 8031cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 8041cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 8051cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("icount_decrement(%u) = ", pc->ino); 8061cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o break; 8071cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 8081cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_icount_fetch(icount, pc->ino, &result); 8091cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 8101cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("run_test", retval, 8111cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "while calling icount_fetch"); 8121cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 8131cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 8141cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("%u (%s)\n", result, (result == pc->expected) ? 8151cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o "OK" : "NOT OK"); 8161cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (result != pc->expected) 8171cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o problem++; 8181cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 8191cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("icount size is %u\n", ext2fs_get_icount_size(icount)); 8201cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o retval = ext2fs_icount_validate(icount, stdout); 8211cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o if (retval) { 8221cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o com_err("run_test", retval, "while calling icount_validate"); 8231cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o exit(1); 8241cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o } 8251cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o ext2fs_free_icount(icount); 8261cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o return problem; 8271cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o} 8281cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 8291cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 8301cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'oint main(int argc, char **argv) 8311cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o{ 8321cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o int failed = 0; 8331cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o 8341cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o setup(); 8351cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("Standard icount run:\n"); 8361b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o failed += run_test(0, 0, 0, prog); 8371cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("\nMultiple bitmap test:\n"); 8381b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, 0, prog); 8391cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("\nResizing icount:\n"); 8401b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o failed += run_test(0, 3, 0, extended); 8411b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o printf("\nStandard icount run with tdb:\n"); 8421b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o failed += run_test(0, 0, ".", prog); 8431b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o printf("\nMultiple bitmap test with tdb:\n"); 8441b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o failed += run_test(EXT2_ICOUNT_OPT_INCREMENT, 0, ".", prog); 8451b9d8cb7057387afae106ffa662613205f07e131Theodore Ts'o if (failed) 8461cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o printf("FAILED!\n"); 8471cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o return failed; 8481cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o} 8491cb78d8433af774864c9d62a246e5edbc612b123Theodore Ts'o#endif 850