├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── compsize.8 ├── compsize.c ├── endianness.h ├── kerncompat.h ├── radix-tree.c └── radix-tree.h /.gitignore: -------------------------------------------------------------------------------- 1 | compsize 2 | *.o 3 | *~ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This program is free software; you can redistribute it and/or modify 2 | it under the terms of the GNU General Public License as published by 3 | the Free Software Foundation; either version 2 of the License, or 4 | (at your option) any later version. 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr 2 | CC ?= gcc 3 | CFLAGS ?= -Wall -std=gnu90 4 | SRC_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 5 | 6 | 7 | BIN := $(SRC_DIR)/compsize 8 | C_FILES := $(wildcard $(SRC_DIR)/*.c) 9 | OBJ_FILES := $(patsubst $(SRC_DIR)/%.c, $(SRC_DIR)/%.o, $(C_FILES)) 10 | 11 | 12 | all: $(BIN) 13 | 14 | debug: CFLAGS += -Wall -DDEBUG -g 15 | debug: $(BIN) 16 | 17 | 18 | $(SRC_DIR)/%.o: $(SRC_DIR)/%.c 19 | $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $^ 20 | 21 | $(BIN): $(OBJ_FILES) 22 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 23 | 24 | BIN_I := $(DESTDIR)$(PREFIX)/bin/compsize 25 | 26 | $(BIN_I): $(BIN) 27 | install -Dm755 $< $@ 28 | 29 | MAN_I := $(DESTDIR)$(PREFIX)/share/man/man8/compsize.8.gz 30 | 31 | $(MAN_I): $(SRC_DIR)/compsize.8 32 | mkdir -p "$$(dirname "$@")" 33 | gzip -9n < $< > $@ 34 | 35 | install: $(BIN_I) $(MAN_I) 36 | 37 | uninstall: 38 | @rm -vf $(BIN_I) $(MAN_I) 39 | 40 | clean: 41 | @rm -vf $(BIN) $(OBJ_FILES) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # compsize 2 | 3 | compsize takes a list of files (given as arguments) on a btrfs filesystem 4 | and measures used compression types and effective compression ratio, 5 | producing a report such as: 6 | 7 | ``` 8 | [~]$ compsize /home 9 | Processed 140058 files, 133128 regular extents (196786 refs), 80886 inline. 10 | Type Perc Disk Usage Uncompressed Referenced 11 | TOTAL 93% 14G 15G 12G 12 | none 100% 13G 13G 10G 13 | zlib 41% 628M 1.4G 1.4G 14 | zstd 28% 42M 148M 148M 15 | ``` 16 | 17 | A directory has no extents but has a (recursive) list of files. A 18 | non-regular file is silently ignored. 19 | 20 | As it makes no sense to talk about compression ratio of a partial extent, 21 | every referenced extent is counted whole, exactly once -- no matter if you 22 | use only a few bytes of a 1GB extent or reflink it a thousand times. Thus, 23 | the uncompressed size will not match the number given by **tar** or **du**. 24 | On the other hand, the space _used_ should be accurate (although obviously 25 | it can be shared with files outside our set). 26 | 27 | The fields are: 28 | * Type: compression algorithm used 29 | * Perc: disk usage/uncompressed -- ie, effective compression ratio 30 | * Disk Usage: blocks actually used on the disk 31 | * Uncompressed: extents before compression 32 | * Referenced: apparent size of files (minus holes) 33 | 34 | The ioctl used requires root. 35 | 36 | # Installation: 37 | 38 | Besides regular C toolchain, you need btrfs userspace headers. On Debian 39 | (incl. derivatives like Ubuntu) they're in libbtrfs-dev, SuSE ships them 40 | inside libbtrfs-devel, they used to come with btrfs-progs before. 41 | Required kernel: 3.16, btrfs-progs: 3.18 (untested!). 42 | -------------------------------------------------------------------------------- /compsize.8: -------------------------------------------------------------------------------- 1 | .TH compsize 8 2017-09-04 btrfs btrfs 2 | .SH NAME 3 | compsize \- calculate compression ratio of a set of files on btrfs 4 | .SH SYNOPSIS 5 | .B compsize 6 | .I file-or-dir 7 | [ 8 | .I file-or-dir 9 | \&... ] 10 | .SH DESCRIPTION 11 | .B compsize 12 | takes a list of files on a btrfs filesystem (recursing directories) 13 | and measures used compression types and the effective compression ratio. 14 | Besides compression, \fBcompsize\fR shows the effect of reflinks (\fIcp 15 | --reflink\fR, snapshots, deduplication), and certain types of btrfs waste. 16 | .P 17 | The program gives a report similar to: 18 | .br 19 | Processed 90319 files. 20 | .br 21 | Type Perc Disk Usage Uncompressed Referenced 22 | .br 23 | TOTAL 79% 1.4G 1.8G 1.9G 24 | .br 25 | none 100% 1.0G 1.0G 1.0G 26 | .br 27 | lzo 53% 446M 833M 843M 28 | .P 29 | The fields above are: 30 | .TP 31 | .B Type 32 | compression algorithm 33 | .TP 34 | .B Perc 35 | disk usage/uncompressed (compression ratio) 36 | .TP 37 | .B Disk Usage 38 | blocks on the disk; this is what storing these files actually costs you 39 | (save for RAID considerations) 40 | .TP 41 | .B Uncompressed 42 | uncompressed extents; what you would need without compression \- includes 43 | deduplication savings and pinned extent waste 44 | .TP 45 | .B Referenced 46 | apparent file sizes (sans holes); this is what a traditional filesystem 47 | that supports holes and efficient tail packing, or 48 | .IR "tar -S" , 49 | would need to store these files 50 | .P 51 | Let's see this on an example: a file 128K big is stored as a single extent A 52 | which compressed to a single 4K page. It then receives a write of 32K at 53 | offset 32K, which also compressed to a single 4K page, stored as extent B. 54 | .P 55 | The file now appears as: 56 | .br 57 | +-------+-------+---------------+ 58 | .br 59 | extent A | used | waste | used | 60 | .br 61 | +-------+-------+---------------+ 62 | .br 63 | extent B | used | 64 | .br 65 | +-------+ 66 | .P 67 | The "waste" inside extent A can't be gotten rid until the whole extent is 68 | rewritten (for example by \fIdefrag\fR). If compressed, the whole extent 69 | needs to be read every time that part of the file is being read, thus the 70 | "waste" is still required. 71 | .P 72 | In this case, we have: \fBDisk Usage\fR: 8KB, \fBUncompressed\fR: 160K, 73 | \fBReferenced\fR: 128K. 74 | .SH OPTIONS 75 | .TP 76 | .BR -b / --bytes 77 | Show raw byte counts rather than human-friendly sizes. 78 | .TP 79 | .BR -x / --one-file-system 80 | Skip files and directories on different file systems. 81 | .SH SIGNALS 82 | .TP 83 | .BR USR1 84 | Displays partial data for files processed so far. 85 | .SH CAVEATS 86 | Recently written files may show as not taking any space until they're 87 | actually allocated and compressed; this happens once they're synced or 88 | on natural writeout, typically on the order of 30 seconds. 89 | .P 90 | The ioctls used by this program require root. 91 | .P 92 | Inline extents are considered to be always unique, even if they share 93 | the same bytes on the disk. 94 | .P 95 | This program doesn't currently support filesystems above 8TB on 32-bit 96 | machines \*- but neither do other btrfs tools. 97 | -------------------------------------------------------------------------------- /compsize.c: -------------------------------------------------------------------------------- 1 | #define _FILE_OFFSET_BITS 64 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "radix-tree.h" 18 | #include "endianness.h" 19 | 20 | #if defined(DEBUG) 21 | #define DPRINTF(fmt, args...) fprintf(stderr, fmt, ##args) 22 | #else 23 | #define DPRINTF(fmt, args...) 24 | #endif 25 | 26 | // We recognize yet-unknown compression types (u8), plus token for prealloc. 27 | #define MAX_ENTRIES (256+1) 28 | #define PREALLOC 256 29 | 30 | #ifndef SZ_16M 31 | // old kernel headers 32 | #define SZ_16M 16777216 33 | #endif 34 | 35 | struct btrfs_sv2_args 36 | { 37 | struct btrfs_ioctl_search_key key; 38 | uint64_t buf_size; 39 | uint8_t buf[65536]; // hardcoded kernel's limit is 16MB 40 | }; 41 | 42 | struct workspace 43 | { 44 | uint64_t disk[MAX_ENTRIES]; 45 | uint64_t uncomp[MAX_ENTRIES]; 46 | uint64_t refd[MAX_ENTRIES]; 47 | uint64_t disk_all; 48 | uint64_t uncomp_all; 49 | uint64_t refd_all; 50 | uint64_t nfiles; 51 | uint64_t nextents, nrefs, ninline, nfrag; 52 | uint64_t fragend; 53 | struct radix_tree_root seen_extents; 54 | }; 55 | 56 | static const char *comp_types[MAX_ENTRIES] = { "none", "zlib", "lzo", "zstd" }; 57 | 58 | static int opt_bytes = 0; 59 | static int opt_one_fs = 0; 60 | static int sig_stats = 0; 61 | 62 | static int print_stats(struct workspace *ws); 63 | 64 | static void die(const char *txt, ...) __attribute__((format (printf, 1, 2))); 65 | static void die(const char *txt, ...) 66 | { 67 | va_list ap; 68 | va_start(ap, txt); 69 | vfprintf(stderr, txt, ap); 70 | va_end(ap); 71 | 72 | exit(1); 73 | } 74 | 75 | static void sigusr1(int dummy) 76 | { 77 | sig_stats = 1; 78 | } 79 | 80 | static void init_sv2_args(ino_t st_ino, struct btrfs_sv2_args *sv2_args) 81 | { 82 | sv2_args->key.tree_id = 0; 83 | sv2_args->key.max_objectid = st_ino; 84 | sv2_args->key.min_objectid = st_ino; 85 | sv2_args->key.min_offset = 0; 86 | sv2_args->key.max_offset = -1; 87 | sv2_args->key.min_transid = 0; 88 | sv2_args->key.max_transid = -1; 89 | // Only search for EXTENT_DATA_KEY 90 | sv2_args->key.min_type = BTRFS_EXTENT_DATA_KEY; 91 | sv2_args->key.max_type = BTRFS_EXTENT_DATA_KEY; 92 | sv2_args->key.nr_items = -1; 93 | sv2_args->buf_size = sizeof(sv2_args->buf); 94 | } 95 | 96 | static inline int is_hole(uint64_t disk_bytenr) 97 | { 98 | return disk_bytenr == 0; 99 | } 100 | 101 | static void parse_file_extent_item(uint8_t *bp, uint32_t hlen, 102 | struct workspace *ws, const char *filename) 103 | { 104 | struct btrfs_file_extent_item *ei; 105 | uint64_t disk_num_bytes, ram_bytes, disk_bytenr, num_bytes; 106 | uint32_t inline_header_sz; 107 | unsigned comp_type; 108 | 109 | DPRINTF("len=%u\n", hlen); 110 | 111 | ei = (struct btrfs_file_extent_item *) bp; 112 | 113 | ram_bytes = get_unaligned_le64(&ei->ram_bytes); 114 | comp_type = ei->compression; 115 | 116 | if (ei->type == BTRFS_FILE_EXTENT_INLINE) 117 | { 118 | inline_header_sz = sizeof(*ei); 119 | inline_header_sz -= sizeof(ei->disk_bytenr); 120 | inline_header_sz -= sizeof(ei->disk_num_bytes); 121 | inline_header_sz -= sizeof(ei->offset); 122 | inline_header_sz -= sizeof(ei->num_bytes); 123 | 124 | disk_num_bytes = hlen-inline_header_sz; 125 | DPRINTF("inline: ram_bytes=%lu compression=%u disk_num_bytes=%lu\n", 126 | ram_bytes, comp_type, disk_num_bytes); 127 | ws->disk[comp_type] += disk_num_bytes; 128 | ws->uncomp[comp_type] += ram_bytes; 129 | ws->refd[comp_type] += ram_bytes; 130 | ws->ninline++; 131 | ws->nfrag++; 132 | ws->fragend = -1; 133 | return; 134 | } 135 | 136 | if (ei->type == BTRFS_FILE_EXTENT_PREALLOC) 137 | comp_type = PREALLOC; 138 | 139 | if (hlen != sizeof(*ei)) 140 | die("%s: Regular extent's header not 53 bytes (%u) long?!?\n", filename, hlen); 141 | 142 | disk_num_bytes = get_unaligned_le64(&ei->disk_num_bytes); 143 | disk_bytenr = get_unaligned_le64(&ei->disk_bytenr); 144 | num_bytes = get_unaligned_le64(&ei->num_bytes); 145 | 146 | if (is_hole(disk_bytenr)) 147 | return; 148 | 149 | DPRINTF("regular: ram_bytes=%lu compression=%u disk_num_bytes=%lu disk_bytenr=%lu\n", 150 | ram_bytes, comp_type, disk_num_bytes, disk_bytenr); 151 | 152 | if (!IS_ALIGNED(disk_bytenr, 1 << 12)) 153 | die("%s: Extent not 4K-aligned at %"PRIu64"?!?\n", filename, disk_bytenr); 154 | 155 | unsigned long pageno = disk_bytenr >> 12; 156 | radix_tree_preload(GFP_KERNEL); 157 | if (radix_tree_insert(&ws->seen_extents, pageno, (void *)pageno) == 0) 158 | { 159 | ws->disk[comp_type] += disk_num_bytes; 160 | ws->uncomp[comp_type] += ram_bytes; 161 | ws->nextents++; 162 | } 163 | radix_tree_preload_end(); 164 | ws->refd[comp_type] += num_bytes; 165 | ws->nrefs++; 166 | 167 | if (disk_bytenr != ws->fragend) 168 | ws->nfrag++; 169 | ws->fragend = disk_bytenr + disk_num_bytes; 170 | } 171 | 172 | static void do_file(int fd, ino_t st_ino, struct workspace *ws, const char *filename) 173 | { 174 | static struct btrfs_sv2_args sv2_args; 175 | struct btrfs_ioctl_search_header *head; 176 | uint32_t nr_items, hlen; 177 | uint8_t *bp; 178 | 179 | DPRINTF("inode = %" PRIu64"\n", st_ino); 180 | ws->nfiles++; 181 | ws->fragend = -1; 182 | 183 | init_sv2_args(st_ino, &sv2_args); 184 | 185 | again: 186 | if (ioctl(fd, BTRFS_IOC_TREE_SEARCH_V2, &sv2_args)) 187 | { 188 | if (errno == ENOTTY) 189 | die("%s: Not btrfs (or SEARCH_V2 unsupported).\n", filename); 190 | else 191 | die("%s: SEARCH_V2: %m\n", filename); 192 | } 193 | 194 | nr_items = sv2_args.key.nr_items; 195 | DPRINTF("nr_items = %u\n", nr_items); 196 | 197 | bp = sv2_args.buf; 198 | for (; nr_items > 0; nr_items--, bp += hlen) 199 | { 200 | head = (struct btrfs_ioctl_search_header*)bp; 201 | hlen = get_unaligned_32(&head->len); 202 | DPRINTF("{ transid=%lu objectid=%lu offset=%lu type=%u len=%u }\n", 203 | get_unaligned_64(&head->transid), 204 | get_unaligned_64(&head->objectid), 205 | get_unaligned_64(&head->offset), 206 | get_unaligned_32(&head->type), 207 | hlen); 208 | bp += sizeof(*head); 209 | 210 | parse_file_extent_item(bp, hlen, ws, filename); 211 | } 212 | 213 | // Will be exactly 197379 (16MB/85) on overflow, but let's play it safe. 214 | // In theory, we're supposed to retry until getting 0, but RTFK says 215 | // there are no short reads (just running out of buffer space), so we 216 | // avoid having to search twice. 217 | if (sv2_args.key.nr_items > 512) 218 | { 219 | sv2_args.key.nr_items = -1; 220 | sv2_args.key.min_offset = get_unaligned_64(&head->offset) + 1; 221 | goto again; 222 | } 223 | } 224 | 225 | static void do_recursive_search(const char *path, struct workspace *ws, const dev_t *dev) 226 | { 227 | int fd; 228 | int path_size; 229 | char *fn; 230 | DIR *dir; 231 | struct dirent *de; 232 | struct stat st; 233 | 234 | if (sig_stats) 235 | { 236 | sig_stats = 0; 237 | print_stats(ws); 238 | } 239 | 240 | fd = open(path, O_RDONLY|O_NOFOLLOW|O_NOCTTY|O_NONBLOCK); 241 | if (fd == -1) 242 | { 243 | if (errno == ELOOP // symlink 244 | || errno == ENXIO // some device nodes 245 | || errno == ENODEV // /dev/ptmx 246 | || errno == ENOMEDIUM// more device nodes 247 | || errno == ENOENT) // something just deleted 248 | return; // ignore, silently 249 | else if (errno == EACCES) 250 | { 251 | fprintf(stderr, "%s: %m\n", path); 252 | return; // warn 253 | } 254 | else 255 | die("open(\"%s\"): %m\n", path); 256 | } 257 | 258 | DPRINTF("%s\n", path); 259 | 260 | if (fstat(fd, &st)) 261 | die("stat(\"%s\"): %m\n", path); 262 | 263 | if (opt_one_fs && dev != NULL && *dev != st.st_dev) 264 | return; 265 | 266 | if (S_ISDIR(st.st_mode)) 267 | { 268 | dir = fdopendir(fd); 269 | if (!dir) 270 | die("opendir(\"%s\"): %m\n", path); 271 | path_size = 2; // slash + \0; 272 | path_size += strlen(path) + NAME_MAX; 273 | fn = (char *) malloc(path_size); 274 | if (!fn) 275 | die("Out of memory.\n"); 276 | while(1) 277 | { 278 | de = readdir(dir); 279 | if (!de) 280 | break; 281 | if (de->d_type != DT_DIR 282 | && de->d_type != DT_REG 283 | && de->d_type != DT_UNKNOWN) 284 | { 285 | continue; 286 | } 287 | if (!strcmp(de->d_name, ".")) 288 | continue; 289 | if (!strcmp(de->d_name, "..")) 290 | continue; 291 | const char *slash = strrchr(path, '/'); 292 | snprintf(fn, path_size, (slash && !slash[1]) ? "%s%s" 293 | : "%s/%s", path, de->d_name); 294 | do_recursive_search(fn, ws, &st.st_dev); 295 | } 296 | free(fn); 297 | closedir(dir); 298 | } 299 | 300 | if (S_ISREG(st.st_mode)) 301 | do_file(fd, st.st_ino, ws, path); 302 | 303 | close(fd); 304 | } 305 | 306 | #define HB 24 /* size of buffers */ 307 | static void human_bytes(uint64_t x, char *output) 308 | { 309 | static const char *units = "BKMGTPE"; 310 | int u = 0; 311 | 312 | if (opt_bytes) 313 | return (void)snprintf(output, HB, "%"PRIu64, x); 314 | 315 | while (x >= 10240) 316 | u++, x>>=10; 317 | if (x >= 1024) 318 | snprintf(output, HB, " %"PRIu64".%"PRIu64"%c", x>>10, x*10/1024%10, units[u+1]); 319 | else 320 | snprintf(output, HB, "%4"PRIu64"%c", x, units[u]); 321 | } 322 | 323 | static void print_table(const char *type, 324 | const char *percentage, 325 | const char *disk_usage, 326 | const char *uncomp_usage, 327 | const char *refd_usage) 328 | { 329 | printf("%-10s %-8s %-12s %-12s %-12s\n", type, percentage, 330 | disk_usage, uncomp_usage, refd_usage); 331 | } 332 | 333 | static void print_help(void) 334 | { 335 | fprintf(stderr, 336 | "Usage: compsize [options] file-or-dir1 [file-or-dir2 ...]\n" 337 | "\n" 338 | "Compsize displays total space used by set of files, taking into account\n" 339 | "compression, reflinks, partially overwritten extents.\n" 340 | "\n" 341 | "Options:\n" 342 | " -h, --help print this help message and exit\n" 343 | " -b, --bytes display raw bytes instead of human-readable sizes\n" 344 | " -x, --one-file-system don't cross filesystem boundaries\n" 345 | "\n" 346 | ); 347 | } 348 | 349 | static void parse_options(int argc, char **argv) 350 | { 351 | static const char *short_options = "bxh"; 352 | static struct option long_options[] = 353 | { 354 | {"bytes", 0, 0, 'b'}, 355 | {"one-file-system", 0, 0, 'x'}, 356 | {"help", 0, 0, 'h'}, 357 | {0}, 358 | }; 359 | 360 | while (1) 361 | { 362 | switch (getopt_long(argc, argv, short_options, long_options, 0)) 363 | { 364 | case 'b': 365 | opt_bytes = 1; 366 | break; 367 | case 'x': 368 | opt_one_fs = 1; 369 | break; 370 | case 'h': 371 | print_help(); 372 | exit(0); 373 | break; // unreachable 374 | case -1: 375 | return; 376 | default: 377 | exit(1); 378 | } 379 | } 380 | } 381 | 382 | static int print_stats(struct workspace *ws) 383 | { 384 | char perc[8], disk_usage[HB], uncomp_usage[HB], refd_usage[HB]; 385 | uint32_t percentage; 386 | int t; 387 | 388 | ws->uncomp_all = ws->disk_all = ws->refd_all = 0; 389 | for (t=0; tuncomp_all += ws->uncomp[t]; 392 | ws->disk_all += ws->disk[t]; 393 | ws->refd_all += ws->refd[t]; 394 | } 395 | 396 | if (!ws->uncomp_all) 397 | { 398 | if (!ws->nfiles) 399 | fprintf(stderr, "No files.\n"); 400 | else 401 | fprintf(stderr, "All empty or still-delalloced files.\n"); 402 | return 1; 403 | } 404 | 405 | printf("Processed %"PRIu64" file%s, %"PRIu64" regular extents " 406 | "(%"PRIu64" refs), %"PRIu64" inline, %"PRIu64" fragments.\n", 407 | ws->nfiles, ws->nfiles>1 ? "s" : "", 408 | ws->nextents, ws->nrefs, ws->ninline, ws->nfrag); 409 | 410 | print_table("Type", "Perc", "Disk Usage", "Uncompressed", "Referenced"); 411 | percentage = ws->disk_all*100/ws->uncomp_all; 412 | snprintf(perc, sizeof(perc), "%3u%%", percentage); 413 | human_bytes(ws->disk_all, disk_usage); 414 | human_bytes(ws->uncomp_all, uncomp_usage); 415 | human_bytes(ws->refd_all, refd_usage); 416 | print_table("TOTAL", perc, disk_usage, uncomp_usage, refd_usage); 417 | 418 | for (t=0; tuncomp[t]) 421 | continue; 422 | const char *ct = t==PREALLOC? "prealloc" : comp_types[t]; 423 | char unkn_comp[12]; 424 | percentage = ws->disk[t]*100/ws->uncomp[t]; 425 | snprintf(perc, sizeof(perc), "%3u%%", percentage); 426 | human_bytes(ws->disk[t], disk_usage); 427 | human_bytes(ws->uncomp[t], uncomp_usage); 428 | human_bytes(ws->refd[t], refd_usage); 429 | if (!ct) 430 | { 431 | snprintf(unkn_comp, sizeof(unkn_comp), "?%u", t); 432 | ct = unkn_comp; 433 | } 434 | print_table(ct, perc, disk_usage, uncomp_usage, refd_usage); 435 | } 436 | 437 | return 0; 438 | } 439 | 440 | int main(int argc, char **argv) 441 | { 442 | struct workspace *ws; 443 | 444 | ws = (struct workspace *) calloc(sizeof(*ws), 1); 445 | 446 | parse_options(argc, argv); 447 | 448 | if (optind >= argc) 449 | { 450 | print_help(); 451 | return 1; 452 | } 453 | 454 | radix_tree_init(); 455 | INIT_RADIX_TREE(&ws->seen_extents, 0); 456 | signal(SIGUSR1, sigusr1); 457 | 458 | for (; argv[optind]; optind++) 459 | do_recursive_search(argv[optind], ws, NULL); 460 | 461 | int ret = print_stats(ws); 462 | 463 | free(ws); 464 | 465 | return ret; 466 | } 467 | -------------------------------------------------------------------------------- /endianness.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __ANDROID__ 5 | #include 6 | #endif 7 | 8 | #ifdef __sun 9 | # include 10 | # define LITTLE_ENDIAN 1234 11 | # define BIG_ENDIAN 4321 12 | # ifdef _LITTLE_ENDIAN 13 | # define BYTE_ORDER LITTLE_ENDIAN 14 | # else 15 | # define BYTE_ORDER BIG_ENDIAN 16 | # endif 17 | #endif 18 | 19 | #ifndef htole32 20 | #if BYTE_ORDER == LITTLE_ENDIAN 21 | #define htole32(x) (x) 22 | #else 23 | #if BYTE_ORDER == BIG_ENDIAN 24 | #define htole32(x) \ 25 | ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ 26 | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) 27 | #else 28 | #error No endianness given. 29 | #endif 30 | #endif 31 | #endif 32 | 33 | #ifndef htole64 34 | #if BYTE_ORDER == LITTLE_ENDIAN 35 | #define htole64(x) (x) 36 | #else 37 | #if BYTE_ORDER == BIG_ENDIAN 38 | #define htole64(x) \ 39 | ( (((x) & 0xff00000000000000ull) >> 56) \ 40 | | (((x) & 0x00ff000000000000ull) >> 40) \ 41 | | (((x) & 0x0000ff0000000000ull) >> 24) \ 42 | | (((x) & 0x000000ff00000000ull) >> 8) \ 43 | | (((x) & 0x00000000ff000000ull) << 8) \ 44 | | (((x) & 0x0000000000ff0000ull) << 24) \ 45 | | (((x) & 0x000000000000ff00ull) << 40) \ 46 | | (((x) & 0x00000000000000ffull) << 56)) 47 | #else 48 | #error No endianness given. 49 | #endif 50 | #endif 51 | #endif 52 | -------------------------------------------------------------------------------- /kerncompat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 Oracle. All rights reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public 6 | * License v2 as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public 14 | * License along with this program; if not, write to the 15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 | * Boston, MA 021110-1307, USA. 17 | */ 18 | 19 | #ifndef __KERNCOMPAT_H__ 20 | #define __KERNCOMPAT_H__ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | #ifndef __GLIBC__ 36 | #ifndef BTRFS_DISABLE_BACKTRACE 37 | #define BTRFS_DISABLE_BACKTRACE 38 | #endif 39 | #define __always_inline __inline __attribute__ ((__always_inline__)) 40 | #endif 41 | 42 | #ifndef BTRFS_DISABLE_BACKTRACE 43 | #include 44 | #endif 45 | 46 | #define ptr_to_u64(x) ((u64)(uintptr_t)x) 47 | #define u64_to_ptr(x) ((void *)(uintptr_t)x) 48 | 49 | #ifndef READ 50 | #define READ 0 51 | #define WRITE 1 52 | #define READA 2 53 | #endif 54 | 55 | #define gfp_t int 56 | #define get_cpu_var(p) (p) 57 | #define __get_cpu_var(p) (p) 58 | #define BITS_PER_BYTE 8 59 | #define BITS_PER_LONG (__SIZEOF_LONG__ * BITS_PER_BYTE) 60 | #define __GFP_BITS_SHIFT 20 61 | #define __GFP_BITS_MASK ((int)((1 << __GFP_BITS_SHIFT) - 1)) 62 | #define GFP_KERNEL 0 63 | #define GFP_NOFS 0 64 | #define __read_mostly 65 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 66 | 67 | #ifndef ULONG_MAX 68 | #define ULONG_MAX (~0UL) 69 | #endif 70 | 71 | #define __token_glue(a,b,c) ___token_glue(a,b,c) 72 | #define ___token_glue(a,b,c) a ## b ## c 73 | #ifdef DEBUG_BUILD_CHECKS 74 | #define BUILD_ASSERT(x) extern int __token_glue(compile_time_assert_,__LINE__,__COUNTER__)[1-2*!(x)] __attribute__((unused)) 75 | #else 76 | #define BUILD_ASSERT(x) 77 | #endif 78 | 79 | #ifndef BTRFS_DISABLE_BACKTRACE 80 | #define MAX_BACKTRACE 16 81 | static inline void print_trace(void) 82 | { 83 | void *array[MAX_BACKTRACE]; 84 | int size; 85 | 86 | size = backtrace(array, MAX_BACKTRACE); 87 | backtrace_symbols_fd(array, size, 2); 88 | } 89 | #endif 90 | 91 | static inline void warning_trace(const char *assertion, const char *filename, 92 | const char *func, unsigned line, long val) 93 | { 94 | if (!val) 95 | return; 96 | fprintf(stderr, 97 | "%s:%d: %s: Warning: assertion `%s` failed, value %ld\n", 98 | filename, line, func, assertion, val); 99 | #ifndef BTRFS_DISABLE_BACKTRACE 100 | print_trace(); 101 | #endif 102 | } 103 | 104 | static inline void bugon_trace(const char *assertion, const char *filename, 105 | const char *func, unsigned line, long val) 106 | { 107 | if (!val) 108 | return; 109 | fprintf(stderr, 110 | "%s:%d: %s: BUG_ON `%s` triggered, value %ld\n", 111 | filename, line, func, assertion, val); 112 | #ifndef BTRFS_DISABLE_BACKTRACE 113 | print_trace(); 114 | #endif 115 | abort(); 116 | exit(1); 117 | } 118 | 119 | #ifdef __CHECKER__ 120 | #define __force __attribute__((force)) 121 | #define __bitwise__ __attribute__((bitwise)) 122 | #else 123 | #define __force 124 | #ifndef __bitwise__ 125 | #define __bitwise__ 126 | #endif 127 | #endif 128 | 129 | #ifndef __CHECKER__ 130 | /* 131 | * Since we're using primitive definitions from kernel-space, we need to 132 | * define __KERNEL__ so that system header files know which definitions 133 | * to use. 134 | */ 135 | #define __KERNEL__ 136 | #include 137 | typedef __u32 u32; 138 | typedef __u64 u64; 139 | typedef __u16 u16; 140 | typedef __u8 u8; 141 | typedef __s64 s64; 142 | typedef __s32 s32; 143 | 144 | /* 145 | * Continuing to define __KERNEL__ breaks others parts of the code, so 146 | * we can just undefine it now that we have the correct headers... 147 | */ 148 | #undef __KERNEL__ 149 | #else 150 | typedef unsigned int u32; 151 | typedef unsigned int __u32; 152 | typedef unsigned long long u64; 153 | typedef unsigned char u8; 154 | typedef unsigned short u16; 155 | typedef long long s64; 156 | typedef int s32; 157 | #endif 158 | 159 | 160 | struct vma_shared { int prio_tree_node; }; 161 | struct vm_area_struct { 162 | unsigned long vm_pgoff; 163 | unsigned long vm_start; 164 | unsigned long vm_end; 165 | struct vma_shared shared; 166 | }; 167 | 168 | struct page { 169 | unsigned long index; 170 | }; 171 | 172 | struct mutex { 173 | unsigned long lock; 174 | }; 175 | 176 | #define mutex_init(m) \ 177 | do { \ 178 | (m)->lock = 1; \ 179 | } while (0) 180 | 181 | static inline void mutex_lock(struct mutex *m) 182 | { 183 | m->lock--; 184 | } 185 | 186 | static inline void mutex_unlock(struct mutex *m) 187 | { 188 | m->lock++; 189 | } 190 | 191 | static inline int mutex_is_locked(struct mutex *m) 192 | { 193 | return (m->lock != 1); 194 | } 195 | 196 | #define cond_resched() do { } while (0) 197 | #define preempt_enable() do { } while (0) 198 | #define preempt_disable() do { } while (0) 199 | 200 | #define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 201 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 202 | 203 | #ifndef __attribute_const__ 204 | #define __attribute_const__ __attribute__((__const__)) 205 | #endif 206 | 207 | /** 208 | * __set_bit - Set a bit in memory 209 | * @nr: the bit to set 210 | * @addr: the address to start counting from 211 | * 212 | * Unlike set_bit(), this function is non-atomic and may be reordered. 213 | * If it's called on the same region of memory simultaneously, the effect 214 | * may be that only one operation succeeds. 215 | */ 216 | static inline void __set_bit(int nr, volatile unsigned long *addr) 217 | { 218 | unsigned long mask = BITOP_MASK(nr); 219 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 220 | 221 | *p |= mask; 222 | } 223 | 224 | static inline void __clear_bit(int nr, volatile unsigned long *addr) 225 | { 226 | unsigned long mask = BITOP_MASK(nr); 227 | unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); 228 | 229 | *p &= ~mask; 230 | } 231 | 232 | /** 233 | * test_bit - Determine whether a bit is set 234 | * @nr: bit number to test 235 | * @addr: Address to start counting from 236 | */ 237 | static inline int test_bit(int nr, const volatile unsigned long *addr) 238 | { 239 | return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); 240 | } 241 | 242 | /* 243 | * error pointer 244 | */ 245 | #define MAX_ERRNO 4095 246 | #define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) 247 | 248 | static inline void *ERR_PTR(long error) 249 | { 250 | return (void *) error; 251 | } 252 | 253 | static inline long PTR_ERR(const void *ptr) 254 | { 255 | return (long) ptr; 256 | } 257 | 258 | static inline int IS_ERR(const void *ptr) 259 | { 260 | return IS_ERR_VALUE((unsigned long)ptr); 261 | } 262 | 263 | static inline int IS_ERR_OR_NULL(const void *ptr) 264 | { 265 | return !ptr || IS_ERR(ptr); 266 | } 267 | 268 | /* 269 | * This looks more complex than it should be. But we need to 270 | * get the type for the ~ right in round_down (it needs to be 271 | * as wide as the result!), and we want to evaluate the macro 272 | * arguments just once each. 273 | */ 274 | #define __round_mask(x, y) ((__typeof__(x))((y)-1)) 275 | #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) 276 | #define round_down(x, y) ((x) & ~__round_mask(x, y)) 277 | 278 | /* 279 | * printk 280 | */ 281 | #define printk(fmt, args...) fprintf(stderr, fmt, ##args) 282 | #define KERN_CRIT "" 283 | #define KERN_ERR "" 284 | 285 | /* 286 | * kmalloc/kfree 287 | */ 288 | #define kmalloc(x, y) malloc(x) 289 | #define kzalloc(x, y) calloc(1, x) 290 | #define kstrdup(x, y) strdup(x) 291 | #define kfree(x) free(x) 292 | #define vmalloc(x) malloc(x) 293 | #define vfree(x) free(x) 294 | 295 | #ifndef BTRFS_DISABLE_BACKTRACE 296 | static inline void assert_trace(const char *assertion, const char *filename, 297 | const char *func, unsigned line, long val) 298 | { 299 | if (val) 300 | return; 301 | fprintf(stderr, 302 | "%s:%d: %s: Assertion `%s` failed, value %ld\n", 303 | filename, line, func, assertion, val); 304 | #ifndef BTRFS_DISABLE_BACKTRACE 305 | print_trace(); 306 | #endif 307 | abort(); 308 | exit(1); 309 | } 310 | #define ASSERT(c) assert_trace(#c, __FILE__, __func__, __LINE__, (long)(c)) 311 | #else 312 | #define ASSERT(c) assert(c) 313 | #endif 314 | 315 | #define BUG_ON(c) bugon_trace(#c, __FILE__, __func__, __LINE__, (long)(c)) 316 | #define BUG() BUG_ON(1) 317 | #define WARN_ON(c) warning_trace(#c, __FILE__, __func__, __LINE__, (long)(c)) 318 | 319 | #define container_of(ptr, type, member) ({ \ 320 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 321 | (type *)( (char *)__mptr - offsetof(type,member) );}) 322 | #ifndef __bitwise 323 | #ifdef __CHECKER__ 324 | #define __bitwise __bitwise__ 325 | #else 326 | #define __bitwise 327 | #endif /* __CHECKER__ */ 328 | #endif /* __bitwise */ 329 | 330 | /* Alignment check */ 331 | #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) 332 | 333 | static inline int is_power_of_2(unsigned long n) 334 | { 335 | return (n != 0 && ((n & (n - 1)) == 0)); 336 | } 337 | 338 | typedef u16 __bitwise __le16; 339 | typedef u16 __bitwise __be16; 340 | typedef u32 __bitwise __le32; 341 | typedef u32 __bitwise __be32; 342 | typedef u64 __bitwise __le64; 343 | typedef u64 __bitwise __be64; 344 | 345 | /* Macros to generate set/get funcs for the struct fields 346 | * assume there is a lefoo_to_cpu for every type, so lets make a simple 347 | * one for u8: 348 | */ 349 | #define le8_to_cpu(v) (v) 350 | #define cpu_to_le8(v) (v) 351 | #define __le8 u8 352 | 353 | #if __BYTE_ORDER == __BIG_ENDIAN 354 | #define cpu_to_le64(x) ((__force __le64)(u64)(bswap_64(x))) 355 | #define le64_to_cpu(x) ((__force u64)(__le64)(bswap_64(x))) 356 | #define cpu_to_le32(x) ((__force __le32)(u32)(bswap_32(x))) 357 | #define le32_to_cpu(x) ((__force u32)(__le32)(bswap_32(x))) 358 | #define cpu_to_le16(x) ((__force __le16)(u16)(bswap_16(x))) 359 | #define le16_to_cpu(x) ((__force u16)(__le16)(bswap_16(x))) 360 | #else 361 | #define cpu_to_le64(x) ((__force __le64)(u64)(x)) 362 | #define le64_to_cpu(x) ((__force u64)(__le64)(x)) 363 | #define cpu_to_le32(x) ((__force __le32)(u32)(x)) 364 | #define le32_to_cpu(x) ((__force u32)(__le32)(x)) 365 | #define cpu_to_le16(x) ((__force __le16)(u16)(x)) 366 | #define le16_to_cpu(x) ((__force u16)(__le16)(x)) 367 | #endif 368 | 369 | struct __una_u16 { __le16 x; } __attribute__((__packed__)); 370 | struct __una_u32 { __le32 x; } __attribute__((__packed__)); 371 | struct __una_u64 { __le64 x; } __attribute__((__packed__)); 372 | 373 | #define get_unaligned_le8(p) (*((u8 *)(p))) 374 | #define get_unaligned_8(p) (*((u8 *)(p))) 375 | #define put_unaligned_le8(val,p) ((*((u8 *)(p))) = (val)) 376 | #define put_unaligned_8(val,p) ((*((u8 *)(p))) = (val)) 377 | #define get_unaligned_le16(p) le16_to_cpu(((const struct __una_u16 *)(p))->x) 378 | #define get_unaligned_16(p) (((const struct __una_u16 *)(p))->x) 379 | #define put_unaligned_le16(val,p) (((struct __una_u16 *)(p))->x = cpu_to_le16(val)) 380 | #define put_unaligned_16(val,p) (((struct __una_u16 *)(p))->x = (val)) 381 | #define get_unaligned_le32(p) le32_to_cpu(((const struct __una_u32 *)(p))->x) 382 | #define get_unaligned_32(p) (((const struct __una_u32 *)(p))->x) 383 | #define put_unaligned_le32(val,p) (((struct __una_u32 *)(p))->x = cpu_to_le32(val)) 384 | #define put_unaligned_32(val,p) (((struct __una_u32 *)(p))->x = (val)) 385 | #define get_unaligned_le64(p) le64_to_cpu(((const struct __una_u64 *)(p))->x) 386 | #define get_unaligned_64(p) (((const struct __una_u64 *)(p))->x) 387 | #define put_unaligned_le64(val,p) (((struct __una_u64 *)(p))->x = cpu_to_le64(val)) 388 | #define put_unaligned_64(val,p) (((struct __una_u64 *)(p))->x = (val)) 389 | 390 | #ifndef true 391 | #define true 1 392 | #define false 0 393 | #endif 394 | 395 | #ifndef noinline 396 | #define noinline 397 | #endif 398 | 399 | #endif 400 | -------------------------------------------------------------------------------- /radix-tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 Oracle. All rights reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public 6 | * License v2 as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public 14 | * License along with this program; if not, write to the 15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 | * Boston, MA 021110-1307, USA. 17 | */ 18 | 19 | /* 20 | * Copyright (C) 2001 Momchil Velikov 21 | * Portions Copyright (C) 2001 Christoph Hellwig 22 | * Copyright (C) 2005 SGI, Christoph Lameter 23 | * 24 | * This program is free software; you can redistribute it and/or 25 | * modify it under the terms of the GNU General Public License as 26 | * published by the Free Software Foundation; either version 2, or (at 27 | * your option) any later version. 28 | * 29 | * This program is distributed in the hope that it will be useful, but 30 | * WITHOUT ANY WARRANTY; without even the implied warranty of 31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32 | * General Public License for more details. 33 | * 34 | * You should have received a copy of the GNU General Public License 35 | * along with this program; if not, write to the Free Software 36 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 37 | */ 38 | 39 | #include "kerncompat.h" 40 | #include "radix-tree.h" 41 | #ifdef __KERNEL__ 42 | #define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) 43 | #else 44 | #define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */ 45 | #endif 46 | 47 | #define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT) 48 | #define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1) 49 | 50 | #define RADIX_TREE_TAG_LONGS \ 51 | ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG) 52 | 53 | struct radix_tree_node { 54 | unsigned int count; 55 | void *slots[RADIX_TREE_MAP_SIZE]; 56 | unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; 57 | }; 58 | 59 | struct radix_tree_path { 60 | struct radix_tree_node *node; 61 | int offset; 62 | }; 63 | 64 | #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) 65 | #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) 66 | 67 | static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly; 68 | 69 | /* 70 | * Per-cpu pool of preloaded nodes 71 | */ 72 | struct radix_tree_preload { 73 | int nr; 74 | struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH]; 75 | }; 76 | static struct radix_tree_preload radix_tree_preloads = { 0, }; 77 | 78 | static int internal_nodes = 0; 79 | /* 80 | * This assumes that the caller has performed appropriate preallocation, and 81 | * that the caller has pinned this thread of control to the current CPU. 82 | */ 83 | static struct radix_tree_node * 84 | radix_tree_node_alloc(struct radix_tree_root *root) 85 | { 86 | struct radix_tree_node *ret; 87 | ret = malloc(sizeof(struct radix_tree_node)); 88 | if (ret) { 89 | memset(ret, 0, sizeof(struct radix_tree_node)); 90 | internal_nodes++; 91 | } 92 | return ret; 93 | } 94 | 95 | static inline void 96 | radix_tree_node_free(struct radix_tree_node *node) 97 | { 98 | internal_nodes--; 99 | free(node); 100 | } 101 | 102 | /* 103 | * Load up this CPU's radix_tree_node buffer with sufficient objects to 104 | * ensure that the addition of a single element in the tree cannot fail. On 105 | * success, return zero, with preemption disabled. On error, return -ENOMEM 106 | * with preemption not disabled. 107 | */ 108 | int radix_tree_preload(gfp_t gfp_mask) 109 | { 110 | struct radix_tree_preload *rtp; 111 | struct radix_tree_node *node; 112 | int ret = -ENOMEM; 113 | 114 | preempt_disable(); 115 | rtp = &__get_cpu_var(radix_tree_preloads); 116 | while (rtp->nr < ARRAY_SIZE(rtp->nodes)) { 117 | preempt_enable(); 118 | node = radix_tree_node_alloc(NULL); 119 | if (node == NULL) 120 | goto out; 121 | preempt_disable(); 122 | rtp = &__get_cpu_var(radix_tree_preloads); 123 | if (rtp->nr < ARRAY_SIZE(rtp->nodes)) 124 | rtp->nodes[rtp->nr++] = node; 125 | else 126 | radix_tree_node_free(node); 127 | } 128 | ret = 0; 129 | out: 130 | return ret; 131 | } 132 | 133 | static inline void tag_set(struct radix_tree_node *node, unsigned int tag, 134 | int offset) 135 | { 136 | __set_bit(offset, node->tags[tag]); 137 | } 138 | 139 | static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, 140 | int offset) 141 | { 142 | __clear_bit(offset, node->tags[tag]); 143 | } 144 | 145 | static inline int tag_get(struct radix_tree_node *node, unsigned int tag, 146 | int offset) 147 | { 148 | return test_bit(offset, node->tags[tag]); 149 | } 150 | 151 | static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) 152 | { 153 | root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); 154 | } 155 | 156 | 157 | static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) 158 | { 159 | root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); 160 | } 161 | 162 | static inline void root_tag_clear_all(struct radix_tree_root *root) 163 | { 164 | root->gfp_mask &= __GFP_BITS_MASK; 165 | } 166 | 167 | static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) 168 | { 169 | return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); 170 | } 171 | 172 | /* 173 | * Returns 1 if any slot in the node has this tag set. 174 | * Otherwise returns 0. 175 | */ 176 | static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) 177 | { 178 | int idx; 179 | for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { 180 | if (node->tags[tag][idx]) 181 | return 1; 182 | } 183 | return 0; 184 | } 185 | 186 | /* 187 | * Return the maximum key which can be store into a 188 | * radix tree with height HEIGHT. 189 | */ 190 | static inline unsigned long radix_tree_maxindex(unsigned int height) 191 | { 192 | return height_to_maxindex[height]; 193 | } 194 | 195 | /* 196 | * Extend a radix tree so it can store key @index. 197 | */ 198 | static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) 199 | { 200 | struct radix_tree_node *node; 201 | unsigned int height; 202 | int tag; 203 | 204 | /* Figure out what the height should be. */ 205 | height = root->height + 1; 206 | while (index > radix_tree_maxindex(height)) 207 | height++; 208 | 209 | if (root->rnode == NULL) { 210 | root->height = height; 211 | goto out; 212 | } 213 | 214 | do { 215 | if (!(node = radix_tree_node_alloc(root))) 216 | return -ENOMEM; 217 | 218 | /* Increase the height. */ 219 | node->slots[0] = root->rnode; 220 | 221 | /* Propagate the aggregated tag info into the new root */ 222 | for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { 223 | if (root_tag_get(root, tag)) 224 | tag_set(node, tag, 0); 225 | } 226 | 227 | node->count = 1; 228 | root->rnode = node; 229 | root->height++; 230 | } while (height > root->height); 231 | out: 232 | return 0; 233 | } 234 | 235 | /** 236 | * radix_tree_insert - insert into a radix tree 237 | * @root: radix tree root 238 | * @index: index key 239 | * @item: item to insert 240 | * 241 | * Insert an item into the radix tree at position @index. 242 | */ 243 | int radix_tree_insert(struct radix_tree_root *root, 244 | unsigned long index, void *item) 245 | { 246 | struct radix_tree_node *node = NULL, *slot; 247 | unsigned int height, shift; 248 | int offset; 249 | int error; 250 | 251 | /* Make sure the tree is high enough. */ 252 | if (index > radix_tree_maxindex(root->height)) { 253 | error = radix_tree_extend(root, index); 254 | if (error) 255 | return error; 256 | } 257 | 258 | slot = root->rnode; 259 | height = root->height; 260 | shift = (height-1) * RADIX_TREE_MAP_SHIFT; 261 | 262 | offset = 0; /* uninitialised var warning */ 263 | while (height > 0) { 264 | if (slot == NULL) { 265 | /* Have to add a child node. */ 266 | if (!(slot = radix_tree_node_alloc(root))) 267 | return -ENOMEM; 268 | if (node) { 269 | node->slots[offset] = slot; 270 | node->count++; 271 | } else 272 | root->rnode = slot; 273 | } 274 | 275 | /* Go a level down */ 276 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; 277 | node = slot; 278 | slot = node->slots[offset]; 279 | shift -= RADIX_TREE_MAP_SHIFT; 280 | height--; 281 | } 282 | 283 | if (slot != NULL) 284 | return -EEXIST; 285 | 286 | if (node) { 287 | node->count++; 288 | node->slots[offset] = item; 289 | BUG_ON(tag_get(node, 0, offset)); 290 | BUG_ON(tag_get(node, 1, offset)); 291 | } else { 292 | root->rnode = item; 293 | BUG_ON(root_tag_get(root, 0)); 294 | BUG_ON(root_tag_get(root, 1)); 295 | } 296 | 297 | return 0; 298 | } 299 | 300 | static inline void **__lookup_slot(struct radix_tree_root *root, 301 | unsigned long index) 302 | { 303 | unsigned int height, shift; 304 | struct radix_tree_node **slot; 305 | 306 | height = root->height; 307 | 308 | if (index > radix_tree_maxindex(height)) 309 | return NULL; 310 | 311 | if (height == 0 && root->rnode) 312 | return (void *)&root->rnode; 313 | 314 | shift = (height-1) * RADIX_TREE_MAP_SHIFT; 315 | slot = &root->rnode; 316 | 317 | while (height > 0) { 318 | if (*slot == NULL) 319 | return NULL; 320 | 321 | slot = (struct radix_tree_node **) 322 | ((*slot)->slots + 323 | ((index >> shift) & RADIX_TREE_MAP_MASK)); 324 | shift -= RADIX_TREE_MAP_SHIFT; 325 | height--; 326 | } 327 | 328 | return (void **)slot; 329 | } 330 | 331 | /** 332 | * radix_tree_lookup_slot - lookup a slot in a radix tree 333 | * @root: radix tree root 334 | * @index: index key 335 | * 336 | * Lookup the slot corresponding to the position @index in the radix tree 337 | * @root. This is useful for update-if-exists operations. 338 | */ 339 | void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) 340 | { 341 | return __lookup_slot(root, index); 342 | } 343 | 344 | /** 345 | * radix_tree_lookup - perform lookup operation on a radix tree 346 | * @root: radix tree root 347 | * @index: index key 348 | * 349 | * Lookup the item at the position @index in the radix tree @root. 350 | */ 351 | void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) 352 | { 353 | void **slot; 354 | 355 | slot = __lookup_slot(root, index); 356 | return slot != NULL ? *slot : NULL; 357 | } 358 | 359 | /** 360 | * radix_tree_tag_set - set a tag on a radix tree node 361 | * @root: radix tree root 362 | * @index: index key 363 | * @tag: tag index 364 | * 365 | * Set the search tag (which must be < RADIX_TREE_MAX_TAGS) 366 | * corresponding to @index in the radix tree. From 367 | * the root all the way down to the leaf node. 368 | * 369 | * Returns the address of the tagged item. Setting a tag on a not-present 370 | * item is a bug. 371 | */ 372 | void *radix_tree_tag_set(struct radix_tree_root *root, 373 | unsigned long index, unsigned int tag) 374 | { 375 | unsigned int height, shift; 376 | struct radix_tree_node *slot; 377 | 378 | height = root->height; 379 | BUG_ON(index > radix_tree_maxindex(height)); 380 | 381 | slot = root->rnode; 382 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 383 | 384 | while (height > 0) { 385 | int offset; 386 | 387 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; 388 | if (!tag_get(slot, tag, offset)) 389 | tag_set(slot, tag, offset); 390 | slot = slot->slots[offset]; 391 | BUG_ON(slot == NULL); 392 | shift -= RADIX_TREE_MAP_SHIFT; 393 | height--; 394 | } 395 | 396 | /* set the root's tag bit */ 397 | if (slot && !root_tag_get(root, tag)) 398 | root_tag_set(root, tag); 399 | 400 | return slot; 401 | } 402 | 403 | /** 404 | * radix_tree_tag_clear - clear a tag on a radix tree node 405 | * @root: radix tree root 406 | * @index: index key 407 | * @tag: tag index 408 | * 409 | * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS) 410 | * corresponding to @index in the radix tree. If 411 | * this causes the leaf node to have no tags set then clear the tag in the 412 | * next-to-leaf node, etc. 413 | * 414 | * Returns the address of the tagged item on success, else NULL. ie: 415 | * has the same return value and semantics as radix_tree_lookup(). 416 | */ 417 | void *radix_tree_tag_clear(struct radix_tree_root *root, 418 | unsigned long index, unsigned int tag) 419 | { 420 | struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; 421 | struct radix_tree_node *slot = NULL; 422 | unsigned int height, shift; 423 | 424 | height = root->height; 425 | if (index > radix_tree_maxindex(height)) 426 | goto out; 427 | 428 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 429 | pathp->node = NULL; 430 | slot = root->rnode; 431 | 432 | while (height > 0) { 433 | int offset; 434 | 435 | if (slot == NULL) 436 | goto out; 437 | 438 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; 439 | pathp[1].offset = offset; 440 | pathp[1].node = slot; 441 | slot = slot->slots[offset]; 442 | pathp++; 443 | shift -= RADIX_TREE_MAP_SHIFT; 444 | height--; 445 | } 446 | 447 | if (slot == NULL) 448 | goto out; 449 | 450 | while (pathp->node) { 451 | if (!tag_get(pathp->node, tag, pathp->offset)) 452 | goto out; 453 | tag_clear(pathp->node, tag, pathp->offset); 454 | if (any_tag_set(pathp->node, tag)) 455 | goto out; 456 | pathp--; 457 | } 458 | 459 | /* clear the root's tag bit */ 460 | if (root_tag_get(root, tag)) 461 | root_tag_clear(root, tag); 462 | 463 | out: 464 | return slot; 465 | } 466 | 467 | #ifndef __KERNEL__ /* Only the test harness uses this at present */ 468 | /** 469 | * radix_tree_tag_get - get a tag on a radix tree node 470 | * @root: radix tree root 471 | * @index: index key 472 | * @tag: tag index (< RADIX_TREE_MAX_TAGS) 473 | * 474 | * Return values: 475 | * 476 | * 0: tag not present or not set 477 | * 1: tag set 478 | */ 479 | int radix_tree_tag_get(struct radix_tree_root *root, 480 | unsigned long index, unsigned int tag) 481 | { 482 | unsigned int height, shift; 483 | struct radix_tree_node *slot; 484 | int saw_unset_tag = 0; 485 | 486 | height = root->height; 487 | if (index > radix_tree_maxindex(height)) 488 | return 0; 489 | 490 | /* check the root's tag bit */ 491 | if (!root_tag_get(root, tag)) 492 | return 0; 493 | 494 | if (height == 0) 495 | return 1; 496 | 497 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 498 | slot = root->rnode; 499 | 500 | for ( ; ; ) { 501 | int offset; 502 | 503 | if (slot == NULL) 504 | return 0; 505 | 506 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; 507 | 508 | /* 509 | * This is just a debug check. Later, we can bale as soon as 510 | * we see an unset tag. 511 | */ 512 | if (!tag_get(slot, tag, offset)) 513 | saw_unset_tag = 1; 514 | if (height == 1) { 515 | int ret = tag_get(slot, tag, offset); 516 | 517 | BUG_ON(ret && saw_unset_tag); 518 | return !!ret; 519 | } 520 | slot = slot->slots[offset]; 521 | shift -= RADIX_TREE_MAP_SHIFT; 522 | height--; 523 | } 524 | } 525 | #endif 526 | 527 | static unsigned int 528 | __lookup(struct radix_tree_root *root, void **results, unsigned long index, 529 | unsigned int max_items, unsigned long *next_index) 530 | { 531 | unsigned int nr_found = 0; 532 | unsigned int shift, height; 533 | struct radix_tree_node *slot; 534 | unsigned long i; 535 | 536 | height = root->height; 537 | if (height == 0) { 538 | if (root->rnode && index == 0) 539 | results[nr_found++] = root->rnode; 540 | goto out; 541 | } 542 | 543 | shift = (height-1) * RADIX_TREE_MAP_SHIFT; 544 | slot = root->rnode; 545 | 546 | for ( ; height > 1; height--) { 547 | 548 | for (i = (index >> shift) & RADIX_TREE_MAP_MASK ; 549 | i < RADIX_TREE_MAP_SIZE; i++) { 550 | if (slot->slots[i] != NULL) 551 | break; 552 | index &= ~((1UL << shift) - 1); 553 | index += 1UL << shift; 554 | if (index == 0) 555 | goto out; /* 32-bit wraparound */ 556 | } 557 | if (i == RADIX_TREE_MAP_SIZE) 558 | goto out; 559 | 560 | shift -= RADIX_TREE_MAP_SHIFT; 561 | slot = slot->slots[i]; 562 | } 563 | 564 | /* Bottom level: grab some items */ 565 | for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) { 566 | index++; 567 | if (slot->slots[i]) { 568 | results[nr_found++] = slot->slots[i]; 569 | if (nr_found == max_items) 570 | goto out; 571 | } 572 | } 573 | out: 574 | *next_index = index; 575 | return nr_found; 576 | } 577 | 578 | /** 579 | * radix_tree_gang_lookup - perform multiple lookup on a radix tree 580 | * @root: radix tree root 581 | * @results: where the results of the lookup are placed 582 | * @first_index: start the lookup from this key 583 | * @max_items: place up to this many items at *results 584 | * 585 | * Performs an index-ascending scan of the tree for present items. Places 586 | * them at *@results and returns the number of items which were placed at 587 | * *@results. 588 | * 589 | * The implementation is naive. 590 | */ 591 | unsigned int 592 | radix_tree_gang_lookup(struct radix_tree_root *root, void **results, 593 | unsigned long first_index, unsigned int max_items) 594 | { 595 | const unsigned long max_index = radix_tree_maxindex(root->height); 596 | unsigned long cur_index = first_index; 597 | unsigned int ret = 0; 598 | 599 | while (ret < max_items) { 600 | unsigned int nr_found; 601 | unsigned long next_index; /* Index of next search */ 602 | 603 | if (cur_index > max_index) 604 | break; 605 | nr_found = __lookup(root, results + ret, cur_index, 606 | max_items - ret, &next_index); 607 | ret += nr_found; 608 | if (next_index == 0) 609 | break; 610 | cur_index = next_index; 611 | } 612 | return ret; 613 | } 614 | 615 | /* 616 | * FIXME: the two tag_get()s here should use find_next_bit() instead of 617 | * open-coding the search. 618 | */ 619 | static unsigned int 620 | __lookup_tag(struct radix_tree_root *root, void **results, unsigned long index, 621 | unsigned int max_items, unsigned long *next_index, unsigned int tag) 622 | { 623 | unsigned int nr_found = 0; 624 | unsigned int shift; 625 | unsigned int height = root->height; 626 | struct radix_tree_node *slot; 627 | 628 | if (height == 0) { 629 | if (root->rnode && index == 0) 630 | results[nr_found++] = root->rnode; 631 | goto out; 632 | } 633 | 634 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 635 | slot = root->rnode; 636 | 637 | do { 638 | unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK; 639 | 640 | for ( ; i < RADIX_TREE_MAP_SIZE; i++) { 641 | if (tag_get(slot, tag, i)) { 642 | BUG_ON(slot->slots[i] == NULL); 643 | break; 644 | } 645 | index &= ~((1UL << shift) - 1); 646 | index += 1UL << shift; 647 | if (index == 0) 648 | goto out; /* 32-bit wraparound */ 649 | } 650 | if (i == RADIX_TREE_MAP_SIZE) 651 | goto out; 652 | height--; 653 | if (height == 0) { /* Bottom level: grab some items */ 654 | unsigned long j = index & RADIX_TREE_MAP_MASK; 655 | 656 | for ( ; j < RADIX_TREE_MAP_SIZE; j++) { 657 | index++; 658 | if (tag_get(slot, tag, j)) { 659 | BUG_ON(slot->slots[j] == NULL); 660 | results[nr_found++] = slot->slots[j]; 661 | if (nr_found == max_items) 662 | goto out; 663 | } 664 | } 665 | } 666 | shift -= RADIX_TREE_MAP_SHIFT; 667 | slot = slot->slots[i]; 668 | } while (height > 0); 669 | out: 670 | *next_index = index; 671 | return nr_found; 672 | } 673 | 674 | /** 675 | * radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree 676 | * based on a tag 677 | * @root: radix tree root 678 | * @results: where the results of the lookup are placed 679 | * @first_index: start the lookup from this key 680 | * @max_items: place up to this many items at *results 681 | * @tag: the tag index (< RADIX_TREE_MAX_TAGS) 682 | * 683 | * Performs an index-ascending scan of the tree for present items which 684 | * have the tag indexed by @tag set. Places the items at *@results and 685 | * returns the number of items which were placed at *@results. 686 | */ 687 | unsigned int 688 | radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, 689 | unsigned long first_index, unsigned int max_items, 690 | unsigned int tag) 691 | { 692 | const unsigned long max_index = radix_tree_maxindex(root->height); 693 | unsigned long cur_index = first_index; 694 | unsigned int ret = 0; 695 | 696 | /* check the root's tag bit */ 697 | if (!root_tag_get(root, tag)) 698 | return 0; 699 | 700 | while (ret < max_items) { 701 | unsigned int nr_found; 702 | unsigned long next_index; /* Index of next search */ 703 | 704 | if (cur_index > max_index) 705 | break; 706 | nr_found = __lookup_tag(root, results + ret, cur_index, 707 | max_items - ret, &next_index, tag); 708 | ret += nr_found; 709 | if (next_index == 0) 710 | break; 711 | cur_index = next_index; 712 | } 713 | return ret; 714 | } 715 | 716 | /** 717 | * radix_tree_shrink - shrink height of a radix tree to minimal 718 | * @root radix tree root 719 | */ 720 | static inline void radix_tree_shrink(struct radix_tree_root *root) 721 | { 722 | /* try to shrink tree height */ 723 | while (root->height > 0 && 724 | root->rnode->count == 1 && 725 | root->rnode->slots[0]) { 726 | struct radix_tree_node *to_free = root->rnode; 727 | 728 | root->rnode = to_free->slots[0]; 729 | root->height--; 730 | /* must only free zeroed nodes into the slab */ 731 | tag_clear(to_free, 0, 0); 732 | tag_clear(to_free, 1, 0); 733 | to_free->slots[0] = NULL; 734 | to_free->count = 0; 735 | radix_tree_node_free(to_free); 736 | } 737 | } 738 | 739 | /** 740 | * radix_tree_delete - delete an item from a radix tree 741 | * @root: radix tree root 742 | * @index: index key 743 | * 744 | * Remove the item at @index from the radix tree rooted at @root. 745 | * 746 | * Returns the address of the deleted item, or NULL if it was not present. 747 | */ 748 | void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) 749 | { 750 | struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; 751 | struct radix_tree_node *slot = NULL; 752 | unsigned int height, shift; 753 | int tag; 754 | int offset; 755 | 756 | height = root->height; 757 | if (index > radix_tree_maxindex(height)) 758 | goto out; 759 | 760 | slot = root->rnode; 761 | if (height == 0 && root->rnode) { 762 | root_tag_clear_all(root); 763 | root->rnode = NULL; 764 | goto out; 765 | } 766 | 767 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 768 | pathp->node = NULL; 769 | 770 | do { 771 | if (slot == NULL) 772 | goto out; 773 | 774 | pathp++; 775 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; 776 | pathp->offset = offset; 777 | pathp->node = slot; 778 | slot = slot->slots[offset]; 779 | shift -= RADIX_TREE_MAP_SHIFT; 780 | height--; 781 | } while (height > 0); 782 | 783 | if (slot == NULL) 784 | goto out; 785 | 786 | /* 787 | * Clear all tags associated with the just-deleted item 788 | */ 789 | for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { 790 | if (tag_get(pathp->node, tag, pathp->offset)) 791 | radix_tree_tag_clear(root, index, tag); 792 | } 793 | 794 | /* Now free the nodes we do not need anymore */ 795 | while (pathp->node) { 796 | pathp->node->slots[pathp->offset] = NULL; 797 | pathp->node->count--; 798 | 799 | if (pathp->node->count) { 800 | if (pathp->node == root->rnode) 801 | radix_tree_shrink(root); 802 | goto out; 803 | } 804 | 805 | /* Node with zero slots in use so free it */ 806 | radix_tree_node_free(pathp->node); 807 | 808 | pathp--; 809 | } 810 | root_tag_clear_all(root); 811 | root->height = 0; 812 | root->rnode = NULL; 813 | 814 | out: 815 | return slot; 816 | } 817 | 818 | /** 819 | * radix_tree_tagged - test whether any items in the tree are tagged 820 | * @root: radix tree root 821 | * @tag: tag to test 822 | */ 823 | int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag) 824 | { 825 | return root_tag_get(root, tag); 826 | } 827 | 828 | static unsigned long __maxindex(unsigned int height) 829 | { 830 | unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; 831 | unsigned long index = ~0UL; 832 | 833 | if (tmp < RADIX_TREE_INDEX_BITS) 834 | index = (index >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; 835 | return index; 836 | } 837 | 838 | static void radix_tree_init_maxindex(void) 839 | { 840 | unsigned int i; 841 | 842 | for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) 843 | height_to_maxindex[i] = __maxindex(i); 844 | } 845 | 846 | void radix_tree_init(void) 847 | { 848 | radix_tree_init_maxindex(); 849 | } 850 | -------------------------------------------------------------------------------- /radix-tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 Oracle. All rights reserved. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public 6 | * License v2 as published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | * General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public 14 | * License along with this program; if not, write to the 15 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 | * Boston, MA 021110-1307, USA. 17 | */ 18 | 19 | /* 20 | * Copyright (C) 2001 Momchil Velikov 21 | * Portions Copyright (C) 2001 Christoph Hellwig 22 | * 23 | * This program is free software; you can redistribute it and/or 24 | * modify it under the terms of the GNU General Public License as 25 | * published by the Free Software Foundation; either version 2, or (at 26 | * your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, but 29 | * WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31 | * General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU General Public License 34 | * along with this program; if not, write to the Free Software 35 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 36 | */ 37 | #ifndef _LINUX_RADIX_TREE_H 38 | #define _LINUX_RADIX_TREE_H 39 | 40 | #if BTRFS_FLAT_INCLUDES 41 | #include "kerncompat.h" 42 | #else 43 | #include 44 | #endif /* BTRFS_FLAT_INCLUDES */ 45 | 46 | #define RADIX_TREE_MAX_TAGS 2 47 | 48 | /* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */ 49 | struct radix_tree_root { 50 | unsigned int height; 51 | gfp_t gfp_mask; 52 | struct radix_tree_node *rnode; 53 | }; 54 | 55 | #define RADIX_TREE_INIT(mask) { \ 56 | .height = 0, \ 57 | .gfp_mask = (mask), \ 58 | .rnode = NULL, \ 59 | } 60 | 61 | #define RADIX_TREE(name, mask) \ 62 | struct radix_tree_root name = RADIX_TREE_INIT(mask) 63 | 64 | #define INIT_RADIX_TREE(root, mask) \ 65 | do { \ 66 | (root)->height = 0; \ 67 | (root)->gfp_mask = (mask); \ 68 | (root)->rnode = NULL; \ 69 | } while (0) 70 | 71 | int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); 72 | void *radix_tree_lookup(struct radix_tree_root *, unsigned long); 73 | void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); 74 | void *radix_tree_delete(struct radix_tree_root *, unsigned long); 75 | unsigned int 76 | radix_tree_gang_lookup(struct radix_tree_root *root, void **results, 77 | unsigned long first_index, unsigned int max_items); 78 | int radix_tree_preload(gfp_t gfp_mask); 79 | void radix_tree_init(void); 80 | void *radix_tree_tag_set(struct radix_tree_root *root, 81 | unsigned long index, unsigned int tag); 82 | void *radix_tree_tag_clear(struct radix_tree_root *root, 83 | unsigned long index, unsigned int tag); 84 | int radix_tree_tag_get(struct radix_tree_root *root, 85 | unsigned long index, unsigned int tag); 86 | unsigned int 87 | radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, 88 | unsigned long first_index, unsigned int max_items, 89 | unsigned int tag); 90 | int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag); 91 | 92 | static inline void radix_tree_preload_end(void) 93 | { 94 | preempt_enable(); 95 | } 96 | 97 | #endif /* _LINUX_RADIX_TREE_H */ 98 | --------------------------------------------------------------------------------