162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/string.h> 662306a36Sopenharmony_ci#include <linux/time.h> 762306a36Sopenharmony_ci#include <linux/uuid.h> 862306a36Sopenharmony_ci#include "reiserfs.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* find where objectid map starts */ 1162306a36Sopenharmony_ci#define objectid_map(s,rs) (old_format_only (s) ? \ 1262306a36Sopenharmony_ci (__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ 1362306a36Sopenharmony_ci (__le32 *)((rs) + 1)) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic void check_objectid_map(struct super_block *s, __le32 * map) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci if (le32_to_cpu(map[0]) != 1) 2062306a36Sopenharmony_ci reiserfs_panic(s, "vs-15010", "map corrupted: %lx", 2162306a36Sopenharmony_ci (long unsigned int)le32_to_cpu(map[0])); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci /* FIXME: add something else here */ 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#else 2762306a36Sopenharmony_cistatic void check_objectid_map(struct super_block *s, __le32 * map) 2862306a36Sopenharmony_ci{; 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci#endif 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * When we allocate objectids we allocate the first unused objectid. 3462306a36Sopenharmony_ci * Each sequence of objectids in use (the odd sequences) is followed 3562306a36Sopenharmony_ci * by a sequence of objectids not in use (the even sequences). We 3662306a36Sopenharmony_ci * only need to record the last objectid in each of these sequences 3762306a36Sopenharmony_ci * (both the odd and even sequences) in order to fully define the 3862306a36Sopenharmony_ci * boundaries of the sequences. A consequence of allocating the first 3962306a36Sopenharmony_ci * objectid not in use is that under most conditions this scheme is 4062306a36Sopenharmony_ci * extremely compact. The exception is immediately after a sequence 4162306a36Sopenharmony_ci * of operations which deletes a large number of objects of 4262306a36Sopenharmony_ci * non-sequential objectids, and even then it will become compact 4362306a36Sopenharmony_ci * again as soon as more objects are created. Note that many 4462306a36Sopenharmony_ci * interesting optimizations of layout could result from complicating 4562306a36Sopenharmony_ci * objectid assignment, but we have deferred making them for now. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* get unique object identifier */ 4962306a36Sopenharmony_ci__u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct super_block *s = th->t_super; 5262306a36Sopenharmony_ci struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); 5362306a36Sopenharmony_ci __le32 *map = objectid_map(s, rs); 5462306a36Sopenharmony_ci __u32 unused_objectid; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci check_objectid_map(s, map); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 6162306a36Sopenharmony_ci /* comment needed -Hans */ 6262306a36Sopenharmony_ci unused_objectid = le32_to_cpu(map[1]); 6362306a36Sopenharmony_ci if (unused_objectid == U32_MAX) { 6462306a36Sopenharmony_ci reiserfs_warning(s, "reiserfs-15100", "no more object ids"); 6562306a36Sopenharmony_ci reiserfs_restore_prepared_buffer(s, SB_BUFFER_WITH_SB(s)); 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* 7062306a36Sopenharmony_ci * This incrementation allocates the first unused objectid. That 7162306a36Sopenharmony_ci * is to say, the first entry on the objectid map is the first 7262306a36Sopenharmony_ci * unused objectid, and by incrementing it we use it. See below 7362306a36Sopenharmony_ci * where we check to see if we eliminated a sequence of unused 7462306a36Sopenharmony_ci * objectids.... 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci map[1] = cpu_to_le32(unused_objectid + 1); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* 7962306a36Sopenharmony_ci * Now we check to see if we eliminated the last remaining member of 8062306a36Sopenharmony_ci * the first even sequence (and can eliminate the sequence by 8162306a36Sopenharmony_ci * eliminating its last objectid from oids), and can collapse the 8262306a36Sopenharmony_ci * first two odd sequences into one sequence. If so, then the net 8362306a36Sopenharmony_ci * result is to eliminate a pair of objectids from oids. We do this 8462306a36Sopenharmony_ci * by shifting the entire map to the left. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ci if (sb_oid_cursize(rs) > 2 && map[1] == map[2]) { 8762306a36Sopenharmony_ci memmove(map + 1, map + 3, 8862306a36Sopenharmony_ci (sb_oid_cursize(rs) - 3) * sizeof(__u32)); 8962306a36Sopenharmony_ci set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci journal_mark_dirty(th, SB_BUFFER_WITH_SB(s)); 9362306a36Sopenharmony_ci return unused_objectid; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* makes object identifier unused */ 9762306a36Sopenharmony_civoid reiserfs_release_objectid(struct reiserfs_transaction_handle *th, 9862306a36Sopenharmony_ci __u32 objectid_to_release) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct super_block *s = th->t_super; 10162306a36Sopenharmony_ci struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); 10262306a36Sopenharmony_ci __le32 *map = objectid_map(s, rs); 10362306a36Sopenharmony_ci int i = 0; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci BUG_ON(!th->t_trans_id); 10662306a36Sopenharmony_ci /*return; */ 10762306a36Sopenharmony_ci check_objectid_map(s, map); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 11062306a36Sopenharmony_ci journal_mark_dirty(th, SB_BUFFER_WITH_SB(s)); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* 11362306a36Sopenharmony_ci * start at the beginning of the objectid map (i = 0) and go to 11462306a36Sopenharmony_ci * the end of it (i = disk_sb->s_oid_cursize). Linear search is 11562306a36Sopenharmony_ci * what we use, though it is possible that binary search would be 11662306a36Sopenharmony_ci * more efficient after performing lots of deletions (which is 11762306a36Sopenharmony_ci * when oids is large.) We only check even i's. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci while (i < sb_oid_cursize(rs)) { 12062306a36Sopenharmony_ci if (objectid_to_release == le32_to_cpu(map[i])) { 12162306a36Sopenharmony_ci /* This incrementation unallocates the objectid. */ 12262306a36Sopenharmony_ci le32_add_cpu(&map[i], 1); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci /* 12562306a36Sopenharmony_ci * Did we unallocate the last member of an 12662306a36Sopenharmony_ci * odd sequence, and can shrink oids? 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci if (map[i] == map[i + 1]) { 12962306a36Sopenharmony_ci /* shrink objectid map */ 13062306a36Sopenharmony_ci memmove(map + i, map + i + 2, 13162306a36Sopenharmony_ci (sb_oid_cursize(rs) - i - 13262306a36Sopenharmony_ci 2) * sizeof(__u32)); 13362306a36Sopenharmony_ci set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci RFALSE(sb_oid_cursize(rs) < 2 || 13662306a36Sopenharmony_ci sb_oid_cursize(rs) > sb_oid_maxsize(rs), 13762306a36Sopenharmony_ci "vs-15005: objectid map corrupted cur_size == %d (max == %d)", 13862306a36Sopenharmony_ci sb_oid_cursize(rs), sb_oid_maxsize(rs)); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci return; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (objectid_to_release > le32_to_cpu(map[i]) && 14462306a36Sopenharmony_ci objectid_to_release < le32_to_cpu(map[i + 1])) { 14562306a36Sopenharmony_ci /* size of objectid map is not changed */ 14662306a36Sopenharmony_ci if (objectid_to_release + 1 == le32_to_cpu(map[i + 1])) { 14762306a36Sopenharmony_ci le32_add_cpu(&map[i + 1], -1); 14862306a36Sopenharmony_ci return; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * JDM comparing two little-endian values for 15362306a36Sopenharmony_ci * equality -- safe 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci /* 15662306a36Sopenharmony_ci * objectid map must be expanded, but 15762306a36Sopenharmony_ci * there is no space 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci if (sb_oid_cursize(rs) == sb_oid_maxsize(rs)) { 16062306a36Sopenharmony_ci PROC_INFO_INC(s, leaked_oid); 16162306a36Sopenharmony_ci return; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* expand the objectid map */ 16562306a36Sopenharmony_ci memmove(map + i + 3, map + i + 1, 16662306a36Sopenharmony_ci (sb_oid_cursize(rs) - i - 1) * sizeof(__u32)); 16762306a36Sopenharmony_ci map[i + 1] = cpu_to_le32(objectid_to_release); 16862306a36Sopenharmony_ci map[i + 2] = cpu_to_le32(objectid_to_release + 1); 16962306a36Sopenharmony_ci set_sb_oid_cursize(rs, sb_oid_cursize(rs) + 2); 17062306a36Sopenharmony_ci return; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci i += 2; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci reiserfs_error(s, "vs-15011", "tried to free free object id (%lu)", 17662306a36Sopenharmony_ci (long unsigned)objectid_to_release); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciint reiserfs_convert_objectid_map_v1(struct super_block *s) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct reiserfs_super_block *disk_sb = SB_DISK_SUPER_BLOCK(s); 18262306a36Sopenharmony_ci int cur_size = sb_oid_cursize(disk_sb); 18362306a36Sopenharmony_ci int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2; 18462306a36Sopenharmony_ci int old_max = sb_oid_maxsize(disk_sb); 18562306a36Sopenharmony_ci struct reiserfs_super_block_v1 *disk_sb_v1; 18662306a36Sopenharmony_ci __le32 *objectid_map; 18762306a36Sopenharmony_ci int i; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci disk_sb_v1 = 19062306a36Sopenharmony_ci (struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data); 19162306a36Sopenharmony_ci objectid_map = (__le32 *) (disk_sb_v1 + 1); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (cur_size > new_size) { 19462306a36Sopenharmony_ci /* 19562306a36Sopenharmony_ci * mark everyone used that was listed as free at 19662306a36Sopenharmony_ci * the end of the objectid map 19762306a36Sopenharmony_ci */ 19862306a36Sopenharmony_ci objectid_map[new_size - 1] = objectid_map[cur_size - 1]; 19962306a36Sopenharmony_ci set_sb_oid_cursize(disk_sb, new_size); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci /* move the smaller objectid map past the end of the new super */ 20262306a36Sopenharmony_ci for (i = new_size - 1; i >= 0; i--) { 20362306a36Sopenharmony_ci objectid_map[i + (old_max - new_size)] = objectid_map[i]; 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* set the max size so we don't overflow later */ 20762306a36Sopenharmony_ci set_sb_oid_maxsize(disk_sb, new_size); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /* Zero out label and generate random UUID */ 21062306a36Sopenharmony_ci memset(disk_sb->s_label, 0, sizeof(disk_sb->s_label)); 21162306a36Sopenharmony_ci generate_random_uuid(disk_sb->s_uuid); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* finally, zero out the unused chunk of the new super */ 21462306a36Sopenharmony_ci memset(disk_sb->s_unused, 0, sizeof(disk_sb->s_unused)); 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci} 217