13f3b442bSKonstantin Komarov // SPDX-License-Identifier: GPL-2.0 23f3b442bSKonstantin Komarov /* 33f3b442bSKonstantin Komarov * 43f3b442bSKonstantin Komarov * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 53f3b442bSKonstantin Komarov * 63f3b442bSKonstantin Komarov * This code builds two trees of free clusters extents. 73f3b442bSKonstantin Komarov * Trees are sorted by start of extent and by length of extent. 83f3b442bSKonstantin Komarov * NTFS_MAX_WND_EXTENTS defines the maximum number of elements in trees. 9e8b8e97fSKari Argillander * In extreme case code reads on-disk bitmap to find free clusters. 103f3b442bSKonstantin Komarov * 113f3b442bSKonstantin Komarov */ 123f3b442bSKonstantin Komarov 133f3b442bSKonstantin Komarov #include <linux/buffer_head.h> 143f3b442bSKonstantin Komarov #include <linux/fs.h> 156e3331eeSKari Argillander #include <linux/kernel.h> 163f3b442bSKonstantin Komarov 173f3b442bSKonstantin Komarov #include "ntfs.h" 183f3b442bSKonstantin Komarov #include "ntfs_fs.h" 193f3b442bSKonstantin Komarov 203f3b442bSKonstantin Komarov /* 213f3b442bSKonstantin Komarov * Maximum number of extents in tree. 223f3b442bSKonstantin Komarov */ 233f3b442bSKonstantin Komarov #define NTFS_MAX_WND_EXTENTS (32u * 1024u) 243f3b442bSKonstantin Komarov 253f3b442bSKonstantin Komarov struct rb_node_key { 263f3b442bSKonstantin Komarov struct rb_node node; 273f3b442bSKonstantin Komarov size_t key; 283f3b442bSKonstantin Komarov }; 293f3b442bSKonstantin Komarov 303f3b442bSKonstantin Komarov struct e_node { 31e8b8e97fSKari Argillander struct rb_node_key start; /* Tree sorted by start. */ 32e8b8e97fSKari Argillander struct rb_node_key count; /* Tree sorted by len. */ 333f3b442bSKonstantin Komarov }; 343f3b442bSKonstantin Komarov 353f3b442bSKonstantin Komarov static int wnd_rescan(struct wnd_bitmap *wnd); 363f3b442bSKonstantin Komarov static struct buffer_head *wnd_map(struct wnd_bitmap *wnd, size_t iw); 373f3b442bSKonstantin Komarov static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits); 383f3b442bSKonstantin Komarov 393f3b442bSKonstantin Komarov static struct kmem_cache *ntfs_enode_cachep; 403f3b442bSKonstantin Komarov 413f3b442bSKonstantin Komarov int __init ntfs3_init_bitmap(void) 423f3b442bSKonstantin Komarov { 4396de65a9SKonstantin Komarov ntfs_enode_cachep = kmem_cache_create("ntfs3_enode_cache", 4496de65a9SKonstantin Komarov sizeof(struct e_node), 0, 453f3b442bSKonstantin Komarov SLAB_RECLAIM_ACCOUNT, NULL); 463f3b442bSKonstantin Komarov return ntfs_enode_cachep ? 0 : -ENOMEM; 473f3b442bSKonstantin Komarov } 483f3b442bSKonstantin Komarov 493f3b442bSKonstantin Komarov void ntfs3_exit_bitmap(void) 503f3b442bSKonstantin Komarov { 513f3b442bSKonstantin Komarov kmem_cache_destroy(ntfs_enode_cachep); 523f3b442bSKonstantin Komarov } 533f3b442bSKonstantin Komarov 543f3b442bSKonstantin Komarov /* 55e8b8e97fSKari Argillander * wnd_scan 56e8b8e97fSKari Argillander * 57e8b8e97fSKari Argillander * b_pos + b_len - biggest fragment. 58e8b8e97fSKari Argillander * Scan range [wpos wbits) window @buf. 59e8b8e97fSKari Argillander * 60e8b8e97fSKari Argillander * Return: -1 if not found. 613f3b442bSKonstantin Komarov */ 6208811ba5SKonstantin Komarov static size_t wnd_scan(const void *buf, size_t wbit, u32 wpos, u32 wend, 633f3b442bSKonstantin Komarov size_t to_alloc, size_t *prev_tail, size_t *b_pos, 643f3b442bSKonstantin Komarov size_t *b_len) 653f3b442bSKonstantin Komarov { 663f3b442bSKonstantin Komarov while (wpos < wend) { 673f3b442bSKonstantin Komarov size_t free_len; 683f3b442bSKonstantin Komarov u32 free_bits, end; 69095d8ce6SThomas Kühnel u32 used = find_next_zero_bit_le(buf, wend, wpos); 703f3b442bSKonstantin Komarov 713f3b442bSKonstantin Komarov if (used >= wend) { 723f3b442bSKonstantin Komarov if (*b_len < *prev_tail) { 733f3b442bSKonstantin Komarov *b_pos = wbit - *prev_tail; 743f3b442bSKonstantin Komarov *b_len = *prev_tail; 753f3b442bSKonstantin Komarov } 763f3b442bSKonstantin Komarov 773f3b442bSKonstantin Komarov *prev_tail = 0; 783f3b442bSKonstantin Komarov return -1; 793f3b442bSKonstantin Komarov } 803f3b442bSKonstantin Komarov 813f3b442bSKonstantin Komarov if (used > wpos) { 823f3b442bSKonstantin Komarov wpos = used; 833f3b442bSKonstantin Komarov if (*b_len < *prev_tail) { 843f3b442bSKonstantin Komarov *b_pos = wbit - *prev_tail; 853f3b442bSKonstantin Komarov *b_len = *prev_tail; 863f3b442bSKonstantin Komarov } 873f3b442bSKonstantin Komarov 883f3b442bSKonstantin Komarov *prev_tail = 0; 893f3b442bSKonstantin Komarov } 903f3b442bSKonstantin Komarov 913f3b442bSKonstantin Komarov /* 92e8b8e97fSKari Argillander * Now we have a fragment [wpos, wend) staring with 0. 933f3b442bSKonstantin Komarov */ 943f3b442bSKonstantin Komarov end = wpos + to_alloc - *prev_tail; 95095d8ce6SThomas Kühnel free_bits = find_next_bit_le(buf, min(end, wend), wpos); 963f3b442bSKonstantin Komarov 973f3b442bSKonstantin Komarov free_len = *prev_tail + free_bits - wpos; 983f3b442bSKonstantin Komarov 993f3b442bSKonstantin Komarov if (*b_len < free_len) { 1003f3b442bSKonstantin Komarov *b_pos = wbit + wpos - *prev_tail; 1013f3b442bSKonstantin Komarov *b_len = free_len; 1023f3b442bSKonstantin Komarov } 1033f3b442bSKonstantin Komarov 1043f3b442bSKonstantin Komarov if (free_len >= to_alloc) 1053f3b442bSKonstantin Komarov return wbit + wpos - *prev_tail; 1063f3b442bSKonstantin Komarov 1073f3b442bSKonstantin Komarov if (free_bits >= wend) { 1083f3b442bSKonstantin Komarov *prev_tail += free_bits - wpos; 1093f3b442bSKonstantin Komarov return -1; 1103f3b442bSKonstantin Komarov } 1113f3b442bSKonstantin Komarov 1123f3b442bSKonstantin Komarov wpos = free_bits + 1; 1133f3b442bSKonstantin Komarov 1143f3b442bSKonstantin Komarov *prev_tail = 0; 1153f3b442bSKonstantin Komarov } 1163f3b442bSKonstantin Komarov 1173f3b442bSKonstantin Komarov return -1; 1183f3b442bSKonstantin Komarov } 1193f3b442bSKonstantin Komarov 1203f3b442bSKonstantin Komarov /* 121e8b8e97fSKari Argillander * wnd_close - Frees all resources. 1223f3b442bSKonstantin Komarov */ 1233f3b442bSKonstantin Komarov void wnd_close(struct wnd_bitmap *wnd) 1243f3b442bSKonstantin Komarov { 1253f3b442bSKonstantin Komarov struct rb_node *node, *next; 1263f3b442bSKonstantin Komarov 127ddb17dc8SKonstantin Komarov kvfree(wnd->free_bits); 1284ad5c924SKonstantin Komarov wnd->free_bits = NULL; 1293f3b442bSKonstantin Komarov run_close(&wnd->run); 1303f3b442bSKonstantin Komarov 1313f3b442bSKonstantin Komarov node = rb_first(&wnd->start_tree); 1323f3b442bSKonstantin Komarov 1333f3b442bSKonstantin Komarov while (node) { 1343f3b442bSKonstantin Komarov next = rb_next(node); 1353f3b442bSKonstantin Komarov rb_erase(node, &wnd->start_tree); 1363f3b442bSKonstantin Komarov kmem_cache_free(ntfs_enode_cachep, 1373f3b442bSKonstantin Komarov rb_entry(node, struct e_node, start.node)); 1383f3b442bSKonstantin Komarov node = next; 1393f3b442bSKonstantin Komarov } 1403f3b442bSKonstantin Komarov } 1413f3b442bSKonstantin Komarov 1423f3b442bSKonstantin Komarov static struct rb_node *rb_lookup(struct rb_root *root, size_t v) 1433f3b442bSKonstantin Komarov { 1443f3b442bSKonstantin Komarov struct rb_node **p = &root->rb_node; 1453f3b442bSKonstantin Komarov struct rb_node *r = NULL; 1463f3b442bSKonstantin Komarov 1473f3b442bSKonstantin Komarov while (*p) { 1483f3b442bSKonstantin Komarov struct rb_node_key *k; 1493f3b442bSKonstantin Komarov 1503f3b442bSKonstantin Komarov k = rb_entry(*p, struct rb_node_key, node); 1513f3b442bSKonstantin Komarov if (v < k->key) { 1523f3b442bSKonstantin Komarov p = &(*p)->rb_left; 1533f3b442bSKonstantin Komarov } else if (v > k->key) { 1543f3b442bSKonstantin Komarov r = &k->node; 1553f3b442bSKonstantin Komarov p = &(*p)->rb_right; 1563f3b442bSKonstantin Komarov } else { 1573f3b442bSKonstantin Komarov return &k->node; 1583f3b442bSKonstantin Komarov } 1593f3b442bSKonstantin Komarov } 1603f3b442bSKonstantin Komarov 1613f3b442bSKonstantin Komarov return r; 1623f3b442bSKonstantin Komarov } 1633f3b442bSKonstantin Komarov 1643f3b442bSKonstantin Komarov /* 165e8b8e97fSKari Argillander * rb_insert_count - Helper function to insert special kind of 'count' tree. 1663f3b442bSKonstantin Komarov */ 1673f3b442bSKonstantin Komarov static inline bool rb_insert_count(struct rb_root *root, struct e_node *e) 1683f3b442bSKonstantin Komarov { 1693f3b442bSKonstantin Komarov struct rb_node **p = &root->rb_node; 1703f3b442bSKonstantin Komarov struct rb_node *parent = NULL; 1713f3b442bSKonstantin Komarov size_t e_ckey = e->count.key; 1723f3b442bSKonstantin Komarov size_t e_skey = e->start.key; 1733f3b442bSKonstantin Komarov 1743f3b442bSKonstantin Komarov while (*p) { 1753f3b442bSKonstantin Komarov struct e_node *k = 1763f3b442bSKonstantin Komarov rb_entry(parent = *p, struct e_node, count.node); 1773f3b442bSKonstantin Komarov 1783f3b442bSKonstantin Komarov if (e_ckey > k->count.key) { 1793f3b442bSKonstantin Komarov p = &(*p)->rb_left; 1803f3b442bSKonstantin Komarov } else if (e_ckey < k->count.key) { 1813f3b442bSKonstantin Komarov p = &(*p)->rb_right; 1823f3b442bSKonstantin Komarov } else if (e_skey < k->start.key) { 1833f3b442bSKonstantin Komarov p = &(*p)->rb_left; 1843f3b442bSKonstantin Komarov } else if (e_skey > k->start.key) { 1853f3b442bSKonstantin Komarov p = &(*p)->rb_right; 1863f3b442bSKonstantin Komarov } else { 1873f3b442bSKonstantin Komarov WARN_ON(1); 1883f3b442bSKonstantin Komarov return false; 1893f3b442bSKonstantin Komarov } 1903f3b442bSKonstantin Komarov } 1913f3b442bSKonstantin Komarov 1923f3b442bSKonstantin Komarov rb_link_node(&e->count.node, parent, p); 1933f3b442bSKonstantin Komarov rb_insert_color(&e->count.node, root); 1943f3b442bSKonstantin Komarov return true; 1953f3b442bSKonstantin Komarov } 1963f3b442bSKonstantin Komarov 1973f3b442bSKonstantin Komarov /* 198e8b8e97fSKari Argillander * rb_insert_start - Helper function to insert special kind of 'count' tree. 1993f3b442bSKonstantin Komarov */ 2003f3b442bSKonstantin Komarov static inline bool rb_insert_start(struct rb_root *root, struct e_node *e) 2013f3b442bSKonstantin Komarov { 2023f3b442bSKonstantin Komarov struct rb_node **p = &root->rb_node; 2033f3b442bSKonstantin Komarov struct rb_node *parent = NULL; 2043f3b442bSKonstantin Komarov size_t e_skey = e->start.key; 2053f3b442bSKonstantin Komarov 2063f3b442bSKonstantin Komarov while (*p) { 2073f3b442bSKonstantin Komarov struct e_node *k; 2083f3b442bSKonstantin Komarov 2093f3b442bSKonstantin Komarov parent = *p; 2103f3b442bSKonstantin Komarov 2113f3b442bSKonstantin Komarov k = rb_entry(parent, struct e_node, start.node); 2123f3b442bSKonstantin Komarov if (e_skey < k->start.key) { 2133f3b442bSKonstantin Komarov p = &(*p)->rb_left; 2143f3b442bSKonstantin Komarov } else if (e_skey > k->start.key) { 2153f3b442bSKonstantin Komarov p = &(*p)->rb_right; 2163f3b442bSKonstantin Komarov } else { 2173f3b442bSKonstantin Komarov WARN_ON(1); 2183f3b442bSKonstantin Komarov return false; 2193f3b442bSKonstantin Komarov } 2203f3b442bSKonstantin Komarov } 2213f3b442bSKonstantin Komarov 2223f3b442bSKonstantin Komarov rb_link_node(&e->start.node, parent, p); 2233f3b442bSKonstantin Komarov rb_insert_color(&e->start.node, root); 2243f3b442bSKonstantin Komarov return true; 2253f3b442bSKonstantin Komarov } 2263f3b442bSKonstantin Komarov 2273f3b442bSKonstantin Komarov /* 228e8b8e97fSKari Argillander * wnd_add_free_ext - Adds a new extent of free space. 229e8b8e97fSKari Argillander * @build: 1 when building tree. 2303f3b442bSKonstantin Komarov */ 2313f3b442bSKonstantin Komarov static void wnd_add_free_ext(struct wnd_bitmap *wnd, size_t bit, size_t len, 2323f3b442bSKonstantin Komarov bool build) 2333f3b442bSKonstantin Komarov { 2343f3b442bSKonstantin Komarov struct e_node *e, *e0 = NULL; 2353f3b442bSKonstantin Komarov size_t ib, end_in = bit + len; 2363f3b442bSKonstantin Komarov struct rb_node *n; 2373f3b442bSKonstantin Komarov 2383f3b442bSKonstantin Komarov if (build) { 239e8b8e97fSKari Argillander /* Use extent_min to filter too short extents. */ 2403f3b442bSKonstantin Komarov if (wnd->count >= NTFS_MAX_WND_EXTENTS && 2413f3b442bSKonstantin Komarov len <= wnd->extent_min) { 2423f3b442bSKonstantin Komarov wnd->uptodated = -1; 2433f3b442bSKonstantin Komarov return; 2443f3b442bSKonstantin Komarov } 2453f3b442bSKonstantin Komarov } else { 246e8b8e97fSKari Argillander /* Try to find extent before 'bit'. */ 2473f3b442bSKonstantin Komarov n = rb_lookup(&wnd->start_tree, bit); 2483f3b442bSKonstantin Komarov 2493f3b442bSKonstantin Komarov if (!n) { 2503f3b442bSKonstantin Komarov n = rb_first(&wnd->start_tree); 2513f3b442bSKonstantin Komarov } else { 2523f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, start.node); 2533f3b442bSKonstantin Komarov n = rb_next(n); 2543f3b442bSKonstantin Komarov if (e->start.key + e->count.key == bit) { 255e8b8e97fSKari Argillander /* Remove left. */ 2563f3b442bSKonstantin Komarov bit = e->start.key; 2573f3b442bSKonstantin Komarov len += e->count.key; 2583f3b442bSKonstantin Komarov rb_erase(&e->start.node, &wnd->start_tree); 2593f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 2603f3b442bSKonstantin Komarov wnd->count -= 1; 2613f3b442bSKonstantin Komarov e0 = e; 2623f3b442bSKonstantin Komarov } 2633f3b442bSKonstantin Komarov } 2643f3b442bSKonstantin Komarov 2653f3b442bSKonstantin Komarov while (n) { 2663f3b442bSKonstantin Komarov size_t next_end; 2673f3b442bSKonstantin Komarov 2683f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, start.node); 2693f3b442bSKonstantin Komarov next_end = e->start.key + e->count.key; 2703f3b442bSKonstantin Komarov if (e->start.key > end_in) 2713f3b442bSKonstantin Komarov break; 2723f3b442bSKonstantin Komarov 273e8b8e97fSKari Argillander /* Remove right. */ 2743f3b442bSKonstantin Komarov n = rb_next(n); 2753f3b442bSKonstantin Komarov len += next_end - end_in; 2763f3b442bSKonstantin Komarov end_in = next_end; 2773f3b442bSKonstantin Komarov rb_erase(&e->start.node, &wnd->start_tree); 2783f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 2793f3b442bSKonstantin Komarov wnd->count -= 1; 2803f3b442bSKonstantin Komarov 2813f3b442bSKonstantin Komarov if (!e0) 2823f3b442bSKonstantin Komarov e0 = e; 2833f3b442bSKonstantin Komarov else 2843f3b442bSKonstantin Komarov kmem_cache_free(ntfs_enode_cachep, e); 2853f3b442bSKonstantin Komarov } 2863f3b442bSKonstantin Komarov 2873f3b442bSKonstantin Komarov if (wnd->uptodated != 1) { 288e8b8e97fSKari Argillander /* Check bits before 'bit'. */ 2893f3b442bSKonstantin Komarov ib = wnd->zone_bit == wnd->zone_end || 29096de65a9SKonstantin Komarov bit < wnd->zone_end ? 29196de65a9SKonstantin Komarov 0 : 29296de65a9SKonstantin Komarov wnd->zone_end; 2933f3b442bSKonstantin Komarov 2943f3b442bSKonstantin Komarov while (bit > ib && wnd_is_free_hlp(wnd, bit - 1, 1)) { 2953f3b442bSKonstantin Komarov bit -= 1; 2963f3b442bSKonstantin Komarov len += 1; 2973f3b442bSKonstantin Komarov } 2983f3b442bSKonstantin Komarov 299e8b8e97fSKari Argillander /* Check bits after 'end_in'. */ 3003f3b442bSKonstantin Komarov ib = wnd->zone_bit == wnd->zone_end || 30196de65a9SKonstantin Komarov end_in > wnd->zone_bit ? 30296de65a9SKonstantin Komarov wnd->nbits : 30396de65a9SKonstantin Komarov wnd->zone_bit; 3043f3b442bSKonstantin Komarov 3053f3b442bSKonstantin Komarov while (end_in < ib && wnd_is_free_hlp(wnd, end_in, 1)) { 3063f3b442bSKonstantin Komarov end_in += 1; 3073f3b442bSKonstantin Komarov len += 1; 3083f3b442bSKonstantin Komarov } 3093f3b442bSKonstantin Komarov } 3103f3b442bSKonstantin Komarov } 311e8b8e97fSKari Argillander /* Insert new fragment. */ 3123f3b442bSKonstantin Komarov if (wnd->count >= NTFS_MAX_WND_EXTENTS) { 3133f3b442bSKonstantin Komarov if (e0) 3143f3b442bSKonstantin Komarov kmem_cache_free(ntfs_enode_cachep, e0); 3153f3b442bSKonstantin Komarov 3163f3b442bSKonstantin Komarov wnd->uptodated = -1; 3173f3b442bSKonstantin Komarov 318e8b8e97fSKari Argillander /* Compare with smallest fragment. */ 3193f3b442bSKonstantin Komarov n = rb_last(&wnd->count_tree); 3203f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, count.node); 3213f3b442bSKonstantin Komarov if (len <= e->count.key) 322e8b8e97fSKari Argillander goto out; /* Do not insert small fragments. */ 3233f3b442bSKonstantin Komarov 3243f3b442bSKonstantin Komarov if (build) { 3253f3b442bSKonstantin Komarov struct e_node *e2; 3263f3b442bSKonstantin Komarov 3273f3b442bSKonstantin Komarov n = rb_prev(n); 3283f3b442bSKonstantin Komarov e2 = rb_entry(n, struct e_node, count.node); 329e8b8e97fSKari Argillander /* Smallest fragment will be 'e2->count.key'. */ 3303f3b442bSKonstantin Komarov wnd->extent_min = e2->count.key; 3313f3b442bSKonstantin Komarov } 3323f3b442bSKonstantin Komarov 333e8b8e97fSKari Argillander /* Replace smallest fragment by new one. */ 3343f3b442bSKonstantin Komarov rb_erase(&e->start.node, &wnd->start_tree); 3353f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 3363f3b442bSKonstantin Komarov wnd->count -= 1; 3373f3b442bSKonstantin Komarov } else { 3383f3b442bSKonstantin Komarov e = e0 ? e0 : kmem_cache_alloc(ntfs_enode_cachep, GFP_ATOMIC); 3393f3b442bSKonstantin Komarov if (!e) { 3403f3b442bSKonstantin Komarov wnd->uptodated = -1; 3413f3b442bSKonstantin Komarov goto out; 3423f3b442bSKonstantin Komarov } 3433f3b442bSKonstantin Komarov 3443f3b442bSKonstantin Komarov if (build && len <= wnd->extent_min) 3453f3b442bSKonstantin Komarov wnd->extent_min = len; 3463f3b442bSKonstantin Komarov } 3473f3b442bSKonstantin Komarov e->start.key = bit; 3483f3b442bSKonstantin Komarov e->count.key = len; 3493f3b442bSKonstantin Komarov if (len > wnd->extent_max) 3503f3b442bSKonstantin Komarov wnd->extent_max = len; 3513f3b442bSKonstantin Komarov 3523f3b442bSKonstantin Komarov rb_insert_start(&wnd->start_tree, e); 3533f3b442bSKonstantin Komarov rb_insert_count(&wnd->count_tree, e); 3543f3b442bSKonstantin Komarov wnd->count += 1; 3553f3b442bSKonstantin Komarov 3563f3b442bSKonstantin Komarov out:; 3573f3b442bSKonstantin Komarov } 3583f3b442bSKonstantin Komarov 3593f3b442bSKonstantin Komarov /* 360e8b8e97fSKari Argillander * wnd_remove_free_ext - Remove a run from the cached free space. 3613f3b442bSKonstantin Komarov */ 3623f3b442bSKonstantin Komarov static void wnd_remove_free_ext(struct wnd_bitmap *wnd, size_t bit, size_t len) 3633f3b442bSKonstantin Komarov { 3643f3b442bSKonstantin Komarov struct rb_node *n, *n3; 3653f3b442bSKonstantin Komarov struct e_node *e, *e3; 3663f3b442bSKonstantin Komarov size_t end_in = bit + len; 3673f3b442bSKonstantin Komarov size_t end3, end, new_key, new_len, max_new_len; 3683f3b442bSKonstantin Komarov 369e8b8e97fSKari Argillander /* Try to find extent before 'bit'. */ 3703f3b442bSKonstantin Komarov n = rb_lookup(&wnd->start_tree, bit); 3713f3b442bSKonstantin Komarov 3723f3b442bSKonstantin Komarov if (!n) 3733f3b442bSKonstantin Komarov return; 3743f3b442bSKonstantin Komarov 3753f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, start.node); 3763f3b442bSKonstantin Komarov end = e->start.key + e->count.key; 3773f3b442bSKonstantin Komarov 3783f3b442bSKonstantin Komarov new_key = new_len = 0; 3793f3b442bSKonstantin Komarov len = e->count.key; 3803f3b442bSKonstantin Komarov 381e8b8e97fSKari Argillander /* Range [bit,end_in) must be inside 'e' or outside 'e' and 'n'. */ 3823f3b442bSKonstantin Komarov if (e->start.key > bit) 3833f3b442bSKonstantin Komarov ; 3843f3b442bSKonstantin Komarov else if (end_in <= end) { 385e8b8e97fSKari Argillander /* Range [bit,end_in) inside 'e'. */ 3863f3b442bSKonstantin Komarov new_key = end_in; 3873f3b442bSKonstantin Komarov new_len = end - end_in; 3883f3b442bSKonstantin Komarov len = bit - e->start.key; 3893f3b442bSKonstantin Komarov } else if (bit > end) { 3903f3b442bSKonstantin Komarov bool bmax = false; 3913f3b442bSKonstantin Komarov 3923f3b442bSKonstantin Komarov n3 = rb_next(n); 3933f3b442bSKonstantin Komarov 3943f3b442bSKonstantin Komarov while (n3) { 3953f3b442bSKonstantin Komarov e3 = rb_entry(n3, struct e_node, start.node); 3963f3b442bSKonstantin Komarov if (e3->start.key >= end_in) 3973f3b442bSKonstantin Komarov break; 3983f3b442bSKonstantin Komarov 3993f3b442bSKonstantin Komarov if (e3->count.key == wnd->extent_max) 4003f3b442bSKonstantin Komarov bmax = true; 4013f3b442bSKonstantin Komarov 4023f3b442bSKonstantin Komarov end3 = e3->start.key + e3->count.key; 4033f3b442bSKonstantin Komarov if (end3 > end_in) { 4043f3b442bSKonstantin Komarov e3->start.key = end_in; 4053f3b442bSKonstantin Komarov rb_erase(&e3->count.node, &wnd->count_tree); 4063f3b442bSKonstantin Komarov e3->count.key = end3 - end_in; 4073f3b442bSKonstantin Komarov rb_insert_count(&wnd->count_tree, e3); 4083f3b442bSKonstantin Komarov break; 4093f3b442bSKonstantin Komarov } 4103f3b442bSKonstantin Komarov 4113f3b442bSKonstantin Komarov n3 = rb_next(n3); 4123f3b442bSKonstantin Komarov rb_erase(&e3->start.node, &wnd->start_tree); 4133f3b442bSKonstantin Komarov rb_erase(&e3->count.node, &wnd->count_tree); 4143f3b442bSKonstantin Komarov wnd->count -= 1; 4153f3b442bSKonstantin Komarov kmem_cache_free(ntfs_enode_cachep, e3); 4163f3b442bSKonstantin Komarov } 4173f3b442bSKonstantin Komarov if (!bmax) 4183f3b442bSKonstantin Komarov return; 4193f3b442bSKonstantin Komarov n3 = rb_first(&wnd->count_tree); 4203f3b442bSKonstantin Komarov wnd->extent_max = 42196de65a9SKonstantin Komarov n3 ? rb_entry(n3, struct e_node, count.node)->count.key : 42296de65a9SKonstantin Komarov 0; 4233f3b442bSKonstantin Komarov return; 4243f3b442bSKonstantin Komarov } 4253f3b442bSKonstantin Komarov 4263f3b442bSKonstantin Komarov if (e->count.key != wnd->extent_max) { 4273f3b442bSKonstantin Komarov ; 4283f3b442bSKonstantin Komarov } else if (rb_prev(&e->count.node)) { 4293f3b442bSKonstantin Komarov ; 4303f3b442bSKonstantin Komarov } else { 4313f3b442bSKonstantin Komarov n3 = rb_next(&e->count.node); 4326e3331eeSKari Argillander max_new_len = max(len, new_len); 4333f3b442bSKonstantin Komarov if (!n3) { 4343f3b442bSKonstantin Komarov wnd->extent_max = max_new_len; 4353f3b442bSKonstantin Komarov } else { 4363f3b442bSKonstantin Komarov e3 = rb_entry(n3, struct e_node, count.node); 4373f3b442bSKonstantin Komarov wnd->extent_max = max(e3->count.key, max_new_len); 4383f3b442bSKonstantin Komarov } 4393f3b442bSKonstantin Komarov } 4403f3b442bSKonstantin Komarov 4413f3b442bSKonstantin Komarov if (!len) { 4423f3b442bSKonstantin Komarov if (new_len) { 4433f3b442bSKonstantin Komarov e->start.key = new_key; 4443f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 4453f3b442bSKonstantin Komarov e->count.key = new_len; 4463f3b442bSKonstantin Komarov rb_insert_count(&wnd->count_tree, e); 4473f3b442bSKonstantin Komarov } else { 4483f3b442bSKonstantin Komarov rb_erase(&e->start.node, &wnd->start_tree); 4493f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 4503f3b442bSKonstantin Komarov wnd->count -= 1; 4513f3b442bSKonstantin Komarov kmem_cache_free(ntfs_enode_cachep, e); 4523f3b442bSKonstantin Komarov } 4533f3b442bSKonstantin Komarov goto out; 4543f3b442bSKonstantin Komarov } 4553f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 4563f3b442bSKonstantin Komarov e->count.key = len; 4573f3b442bSKonstantin Komarov rb_insert_count(&wnd->count_tree, e); 4583f3b442bSKonstantin Komarov 4593f3b442bSKonstantin Komarov if (!new_len) 4603f3b442bSKonstantin Komarov goto out; 4613f3b442bSKonstantin Komarov 4623f3b442bSKonstantin Komarov if (wnd->count >= NTFS_MAX_WND_EXTENTS) { 4633f3b442bSKonstantin Komarov wnd->uptodated = -1; 4643f3b442bSKonstantin Komarov 465e8b8e97fSKari Argillander /* Get minimal extent. */ 4663f3b442bSKonstantin Komarov e = rb_entry(rb_last(&wnd->count_tree), struct e_node, 4673f3b442bSKonstantin Komarov count.node); 4683f3b442bSKonstantin Komarov if (e->count.key > new_len) 4693f3b442bSKonstantin Komarov goto out; 4703f3b442bSKonstantin Komarov 471e8b8e97fSKari Argillander /* Replace minimum. */ 4723f3b442bSKonstantin Komarov rb_erase(&e->start.node, &wnd->start_tree); 4733f3b442bSKonstantin Komarov rb_erase(&e->count.node, &wnd->count_tree); 4743f3b442bSKonstantin Komarov wnd->count -= 1; 4753f3b442bSKonstantin Komarov } else { 4763f3b442bSKonstantin Komarov e = kmem_cache_alloc(ntfs_enode_cachep, GFP_ATOMIC); 4773f3b442bSKonstantin Komarov if (!e) 4783f3b442bSKonstantin Komarov wnd->uptodated = -1; 4793f3b442bSKonstantin Komarov } 4803f3b442bSKonstantin Komarov 4813f3b442bSKonstantin Komarov if (e) { 4823f3b442bSKonstantin Komarov e->start.key = new_key; 4833f3b442bSKonstantin Komarov e->count.key = new_len; 4843f3b442bSKonstantin Komarov rb_insert_start(&wnd->start_tree, e); 4853f3b442bSKonstantin Komarov rb_insert_count(&wnd->count_tree, e); 4863f3b442bSKonstantin Komarov wnd->count += 1; 4873f3b442bSKonstantin Komarov } 4883f3b442bSKonstantin Komarov 4893f3b442bSKonstantin Komarov out: 4903f3b442bSKonstantin Komarov if (!wnd->count && 1 != wnd->uptodated) 4913f3b442bSKonstantin Komarov wnd_rescan(wnd); 4923f3b442bSKonstantin Komarov } 4933f3b442bSKonstantin Komarov 4943f3b442bSKonstantin Komarov /* 495e8b8e97fSKari Argillander * wnd_rescan - Scan all bitmap. Used while initialization. 4963f3b442bSKonstantin Komarov */ 4973f3b442bSKonstantin Komarov static int wnd_rescan(struct wnd_bitmap *wnd) 4983f3b442bSKonstantin Komarov { 4993f3b442bSKonstantin Komarov int err = 0; 5003f3b442bSKonstantin Komarov size_t prev_tail = 0; 5013f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 5023f3b442bSKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 5033f3b442bSKonstantin Komarov u64 lbo, len = 0; 5043f3b442bSKonstantin Komarov u32 blocksize = sb->s_blocksize; 5053f3b442bSKonstantin Komarov u8 cluster_bits = sbi->cluster_bits; 5063f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 5073f3b442bSKonstantin Komarov u32 used, frb; 5083f3b442bSKonstantin Komarov size_t wpos, wbit, iw, vbo; 5093f3b442bSKonstantin Komarov struct buffer_head *bh = NULL; 5103f3b442bSKonstantin Komarov CLST lcn, clen; 5113f3b442bSKonstantin Komarov 5123f3b442bSKonstantin Komarov wnd->uptodated = 0; 5133f3b442bSKonstantin Komarov wnd->extent_max = 0; 5143f3b442bSKonstantin Komarov wnd->extent_min = MINUS_ONE_T; 5153f3b442bSKonstantin Komarov wnd->total_zeroes = 0; 5163f3b442bSKonstantin Komarov 5173f3b442bSKonstantin Komarov vbo = 0; 5183f3b442bSKonstantin Komarov 5193f3b442bSKonstantin Komarov for (iw = 0; iw < wnd->nwnd; iw++) { 5203f3b442bSKonstantin Komarov if (iw + 1 == wnd->nwnd) 5213f3b442bSKonstantin Komarov wbits = wnd->bits_last; 5223f3b442bSKonstantin Komarov 5233f3b442bSKonstantin Komarov if (wnd->inited) { 5243f3b442bSKonstantin Komarov if (!wnd->free_bits[iw]) { 525e8b8e97fSKari Argillander /* All ones. */ 5263f3b442bSKonstantin Komarov if (prev_tail) { 5273f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, 5283f3b442bSKonstantin Komarov vbo * 8 - prev_tail, 5293f3b442bSKonstantin Komarov prev_tail, true); 5303f3b442bSKonstantin Komarov prev_tail = 0; 5313f3b442bSKonstantin Komarov } 5323f3b442bSKonstantin Komarov goto next_wnd; 5333f3b442bSKonstantin Komarov } 5343f3b442bSKonstantin Komarov if (wbits == wnd->free_bits[iw]) { 535e8b8e97fSKari Argillander /* All zeroes. */ 5363f3b442bSKonstantin Komarov prev_tail += wbits; 5373f3b442bSKonstantin Komarov wnd->total_zeroes += wbits; 5383f3b442bSKonstantin Komarov goto next_wnd; 5393f3b442bSKonstantin Komarov } 5403f3b442bSKonstantin Komarov } 5413f3b442bSKonstantin Komarov 5423f3b442bSKonstantin Komarov if (!len) { 5433f3b442bSKonstantin Komarov u32 off = vbo & sbi->cluster_mask; 5443f3b442bSKonstantin Komarov 5453f3b442bSKonstantin Komarov if (!run_lookup_entry(&wnd->run, vbo >> cluster_bits, 5463f3b442bSKonstantin Komarov &lcn, &clen, NULL)) { 5473f3b442bSKonstantin Komarov err = -ENOENT; 5483f3b442bSKonstantin Komarov goto out; 5493f3b442bSKonstantin Komarov } 5503f3b442bSKonstantin Komarov 5513f3b442bSKonstantin Komarov lbo = ((u64)lcn << cluster_bits) + off; 5523f3b442bSKonstantin Komarov len = ((u64)clen << cluster_bits) - off; 5533f3b442bSKonstantin Komarov } 5543f3b442bSKonstantin Komarov 5553f3b442bSKonstantin Komarov bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits); 5563f3b442bSKonstantin Komarov if (!bh) { 5573f3b442bSKonstantin Komarov err = -EIO; 5583f3b442bSKonstantin Komarov goto out; 5593f3b442bSKonstantin Komarov } 5603f3b442bSKonstantin Komarov 56108811ba5SKonstantin Komarov used = ntfs_bitmap_weight_le(bh->b_data, wbits); 5623f3b442bSKonstantin Komarov if (used < wbits) { 5633f3b442bSKonstantin Komarov frb = wbits - used; 5643f3b442bSKonstantin Komarov wnd->free_bits[iw] = frb; 5653f3b442bSKonstantin Komarov wnd->total_zeroes += frb; 5663f3b442bSKonstantin Komarov } 5673f3b442bSKonstantin Komarov 5683f3b442bSKonstantin Komarov wpos = 0; 5693f3b442bSKonstantin Komarov wbit = vbo * 8; 5703f3b442bSKonstantin Komarov 5713f3b442bSKonstantin Komarov if (wbit + wbits > wnd->nbits) 5723f3b442bSKonstantin Komarov wbits = wnd->nbits - wbit; 5733f3b442bSKonstantin Komarov 5743f3b442bSKonstantin Komarov do { 57508811ba5SKonstantin Komarov used = find_next_zero_bit_le(bh->b_data, wbits, wpos); 5763f3b442bSKonstantin Komarov 5773f3b442bSKonstantin Komarov if (used > wpos && prev_tail) { 5783f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, wbit + wpos - prev_tail, 5793f3b442bSKonstantin Komarov prev_tail, true); 5803f3b442bSKonstantin Komarov prev_tail = 0; 5813f3b442bSKonstantin Komarov } 5823f3b442bSKonstantin Komarov 5833f3b442bSKonstantin Komarov wpos = used; 5843f3b442bSKonstantin Komarov 5853f3b442bSKonstantin Komarov if (wpos >= wbits) { 586e8b8e97fSKari Argillander /* No free blocks. */ 5873f3b442bSKonstantin Komarov prev_tail = 0; 5883f3b442bSKonstantin Komarov break; 5893f3b442bSKonstantin Komarov } 5903f3b442bSKonstantin Komarov 59108811ba5SKonstantin Komarov frb = find_next_bit_le(bh->b_data, wbits, wpos); 5923f3b442bSKonstantin Komarov if (frb >= wbits) { 593e8b8e97fSKari Argillander /* Keep last free block. */ 5943f3b442bSKonstantin Komarov prev_tail += frb - wpos; 5953f3b442bSKonstantin Komarov break; 5963f3b442bSKonstantin Komarov } 5973f3b442bSKonstantin Komarov 5983f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, wbit + wpos - prev_tail, 5993f3b442bSKonstantin Komarov frb + prev_tail - wpos, true); 6003f3b442bSKonstantin Komarov 601e8b8e97fSKari Argillander /* Skip free block and first '1'. */ 6023f3b442bSKonstantin Komarov wpos = frb + 1; 603e8b8e97fSKari Argillander /* Reset previous tail. */ 6043f3b442bSKonstantin Komarov prev_tail = 0; 6053f3b442bSKonstantin Komarov } while (wpos < wbits); 6063f3b442bSKonstantin Komarov 6073f3b442bSKonstantin Komarov next_wnd: 6083f3b442bSKonstantin Komarov 6093f3b442bSKonstantin Komarov if (bh) 6103f3b442bSKonstantin Komarov put_bh(bh); 6113f3b442bSKonstantin Komarov bh = NULL; 6123f3b442bSKonstantin Komarov 6133f3b442bSKonstantin Komarov vbo += blocksize; 6143f3b442bSKonstantin Komarov if (len) { 6153f3b442bSKonstantin Komarov len -= blocksize; 6163f3b442bSKonstantin Komarov lbo += blocksize; 6173f3b442bSKonstantin Komarov } 6183f3b442bSKonstantin Komarov } 6193f3b442bSKonstantin Komarov 620e8b8e97fSKari Argillander /* Add last block. */ 6213f3b442bSKonstantin Komarov if (prev_tail) 6223f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, wnd->nbits - prev_tail, prev_tail, true); 6233f3b442bSKonstantin Komarov 6243f3b442bSKonstantin Komarov /* 625e8b8e97fSKari Argillander * Before init cycle wnd->uptodated was 0. 6263f3b442bSKonstantin Komarov * If any errors or limits occurs while initialization then 627e8b8e97fSKari Argillander * wnd->uptodated will be -1. 628e8b8e97fSKari Argillander * If 'uptodated' is still 0 then Tree is really updated. 6293f3b442bSKonstantin Komarov */ 6303f3b442bSKonstantin Komarov if (!wnd->uptodated) 6313f3b442bSKonstantin Komarov wnd->uptodated = 1; 6323f3b442bSKonstantin Komarov 6333f3b442bSKonstantin Komarov if (wnd->zone_bit != wnd->zone_end) { 6343f3b442bSKonstantin Komarov size_t zlen = wnd->zone_end - wnd->zone_bit; 6353f3b442bSKonstantin Komarov 6363f3b442bSKonstantin Komarov wnd->zone_end = wnd->zone_bit; 6373f3b442bSKonstantin Komarov wnd_zone_set(wnd, wnd->zone_bit, zlen); 6383f3b442bSKonstantin Komarov } 6393f3b442bSKonstantin Komarov 6403f3b442bSKonstantin Komarov out: 6413f3b442bSKonstantin Komarov return err; 6423f3b442bSKonstantin Komarov } 6433f3b442bSKonstantin Komarov 6443f3b442bSKonstantin Komarov int wnd_init(struct wnd_bitmap *wnd, struct super_block *sb, size_t nbits) 6453f3b442bSKonstantin Komarov { 6463f3b442bSKonstantin Komarov int err; 6473f3b442bSKonstantin Komarov u32 blocksize = sb->s_blocksize; 6483f3b442bSKonstantin Komarov u32 wbits = blocksize * 8; 6493f3b442bSKonstantin Komarov 6503f3b442bSKonstantin Komarov init_rwsem(&wnd->rw_lock); 6513f3b442bSKonstantin Komarov 6523f3b442bSKonstantin Komarov wnd->sb = sb; 6533f3b442bSKonstantin Komarov wnd->nbits = nbits; 6543f3b442bSKonstantin Komarov wnd->total_zeroes = nbits; 6553f3b442bSKonstantin Komarov wnd->extent_max = MINUS_ONE_T; 6563f3b442bSKonstantin Komarov wnd->zone_bit = wnd->zone_end = 0; 6573f5ef510SAlexander Lobakin wnd->nwnd = bytes_to_block(sb, ntfs3_bitmap_size(nbits)); 6583f3b442bSKonstantin Komarov wnd->bits_last = nbits & (wbits - 1); 6593f3b442bSKonstantin Komarov if (!wnd->bits_last) 6603f3b442bSKonstantin Komarov wnd->bits_last = wbits; 6613f3b442bSKonstantin Komarov 6626827d50bSKonstantin Komarov wnd->free_bits = 663fc471e39SKonstantin Komarov kvmalloc_array(wnd->nwnd, sizeof(u16), GFP_KERNEL | __GFP_ZERO); 664fc471e39SKonstantin Komarov 6653f3b442bSKonstantin Komarov if (!wnd->free_bits) 6663f3b442bSKonstantin Komarov return -ENOMEM; 6673f3b442bSKonstantin Komarov 6683f3b442bSKonstantin Komarov err = wnd_rescan(wnd); 6693f3b442bSKonstantin Komarov if (err) 6703f3b442bSKonstantin Komarov return err; 6713f3b442bSKonstantin Komarov 6723f3b442bSKonstantin Komarov wnd->inited = true; 6733f3b442bSKonstantin Komarov 6743f3b442bSKonstantin Komarov return 0; 6753f3b442bSKonstantin Komarov } 6763f3b442bSKonstantin Komarov 6773f3b442bSKonstantin Komarov /* 678e8b8e97fSKari Argillander * wnd_map - Call sb_bread for requested window. 6793f3b442bSKonstantin Komarov */ 6803f3b442bSKonstantin Komarov static struct buffer_head *wnd_map(struct wnd_bitmap *wnd, size_t iw) 6813f3b442bSKonstantin Komarov { 6823f3b442bSKonstantin Komarov size_t vbo; 6833f3b442bSKonstantin Komarov CLST lcn, clen; 6843f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 6853f3b442bSKonstantin Komarov struct ntfs_sb_info *sbi; 6863f3b442bSKonstantin Komarov struct buffer_head *bh; 6873f3b442bSKonstantin Komarov u64 lbo; 6883f3b442bSKonstantin Komarov 6893f3b442bSKonstantin Komarov sbi = sb->s_fs_info; 6903f3b442bSKonstantin Komarov vbo = (u64)iw << sb->s_blocksize_bits; 6913f3b442bSKonstantin Komarov 6923f3b442bSKonstantin Komarov if (!run_lookup_entry(&wnd->run, vbo >> sbi->cluster_bits, &lcn, &clen, 6933f3b442bSKonstantin Komarov NULL)) { 6943f3b442bSKonstantin Komarov return ERR_PTR(-ENOENT); 6953f3b442bSKonstantin Komarov } 6963f3b442bSKonstantin Komarov 6973f3b442bSKonstantin Komarov lbo = ((u64)lcn << sbi->cluster_bits) + (vbo & sbi->cluster_mask); 6983f3b442bSKonstantin Komarov 6993f3b442bSKonstantin Komarov bh = ntfs_bread(wnd->sb, lbo >> sb->s_blocksize_bits); 7003f3b442bSKonstantin Komarov if (!bh) 7013f3b442bSKonstantin Komarov return ERR_PTR(-EIO); 7023f3b442bSKonstantin Komarov 7033f3b442bSKonstantin Komarov return bh; 7043f3b442bSKonstantin Komarov } 7053f3b442bSKonstantin Komarov 7063f3b442bSKonstantin Komarov /* 707e8b8e97fSKari Argillander * wnd_set_free - Mark the bits range from bit to bit + bits as free. 7083f3b442bSKonstantin Komarov */ 7093f3b442bSKonstantin Komarov int wnd_set_free(struct wnd_bitmap *wnd, size_t bit, size_t bits) 7103f3b442bSKonstantin Komarov { 7113f3b442bSKonstantin Komarov int err = 0; 7123f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 7133f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 7143f3b442bSKonstantin Komarov size_t iw = bit >> (sb->s_blocksize_bits + 3); 7153f3b442bSKonstantin Komarov u32 wbit = bit & (wbits - 1); 7163f3b442bSKonstantin Komarov struct buffer_head *bh; 717*bac89bb3SKonstantin Komarov u32 op; 7183f3b442bSKonstantin Komarov 719*bac89bb3SKonstantin Komarov for (; iw < wnd->nwnd && bits; iw++, bit += op, bits -= op, wbit = 0) { 7203f3b442bSKonstantin Komarov if (iw + 1 == wnd->nwnd) 7213f3b442bSKonstantin Komarov wbits = wnd->bits_last; 7223f3b442bSKonstantin Komarov 723*bac89bb3SKonstantin Komarov op = min_t(u32, wbits - wbit, bits); 7243f3b442bSKonstantin Komarov 7253f3b442bSKonstantin Komarov bh = wnd_map(wnd, iw); 7263f3b442bSKonstantin Komarov if (IS_ERR(bh)) { 7273f3b442bSKonstantin Komarov err = PTR_ERR(bh); 7283f3b442bSKonstantin Komarov break; 7293f3b442bSKonstantin Komarov } 7303f3b442bSKonstantin Komarov 7313f3b442bSKonstantin Komarov lock_buffer(bh); 7323f3b442bSKonstantin Komarov 73308811ba5SKonstantin Komarov ntfs_bitmap_clear_le(bh->b_data, wbit, op); 7343f3b442bSKonstantin Komarov 7353f3b442bSKonstantin Komarov wnd->free_bits[iw] += op; 736*bac89bb3SKonstantin Komarov wnd->total_zeroes += op; 7373f3b442bSKonstantin Komarov 7383f3b442bSKonstantin Komarov set_buffer_uptodate(bh); 7393f3b442bSKonstantin Komarov mark_buffer_dirty(bh); 7403f3b442bSKonstantin Komarov unlock_buffer(bh); 7413f3b442bSKonstantin Komarov put_bh(bh); 7423f3b442bSKonstantin Komarov 743*bac89bb3SKonstantin Komarov wnd_add_free_ext(wnd, bit, op, false); 7443f3b442bSKonstantin Komarov } 7453f3b442bSKonstantin Komarov return err; 7463f3b442bSKonstantin Komarov } 7473f3b442bSKonstantin Komarov 7483f3b442bSKonstantin Komarov /* 749e8b8e97fSKari Argillander * wnd_set_used - Mark the bits range from bit to bit + bits as used. 7503f3b442bSKonstantin Komarov */ 7513f3b442bSKonstantin Komarov int wnd_set_used(struct wnd_bitmap *wnd, size_t bit, size_t bits) 7523f3b442bSKonstantin Komarov { 7533f3b442bSKonstantin Komarov int err = 0; 7543f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 7553f3b442bSKonstantin Komarov size_t iw = bit >> (sb->s_blocksize_bits + 3); 7563f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 7573f3b442bSKonstantin Komarov u32 wbit = bit & (wbits - 1); 7583f3b442bSKonstantin Komarov struct buffer_head *bh; 759*bac89bb3SKonstantin Komarov u32 op; 7603f3b442bSKonstantin Komarov 761*bac89bb3SKonstantin Komarov for (; iw < wnd->nwnd && bits; iw++, bit += op, bits -= op, wbit = 0) { 7623f3b442bSKonstantin Komarov if (unlikely(iw + 1 == wnd->nwnd)) 7633f3b442bSKonstantin Komarov wbits = wnd->bits_last; 7643f3b442bSKonstantin Komarov 765*bac89bb3SKonstantin Komarov op = min_t(u32, wbits - wbit, bits); 7663f3b442bSKonstantin Komarov 7673f3b442bSKonstantin Komarov bh = wnd_map(wnd, iw); 7683f3b442bSKonstantin Komarov if (IS_ERR(bh)) { 7693f3b442bSKonstantin Komarov err = PTR_ERR(bh); 7703f3b442bSKonstantin Komarov break; 7713f3b442bSKonstantin Komarov } 7723f3b442bSKonstantin Komarov 7733f3b442bSKonstantin Komarov lock_buffer(bh); 7743f3b442bSKonstantin Komarov 77508811ba5SKonstantin Komarov ntfs_bitmap_set_le(bh->b_data, wbit, op); 7763f3b442bSKonstantin Komarov wnd->free_bits[iw] -= op; 777*bac89bb3SKonstantin Komarov wnd->total_zeroes -= op; 7783f3b442bSKonstantin Komarov 7793f3b442bSKonstantin Komarov set_buffer_uptodate(bh); 7803f3b442bSKonstantin Komarov mark_buffer_dirty(bh); 7813f3b442bSKonstantin Komarov unlock_buffer(bh); 7823f3b442bSKonstantin Komarov put_bh(bh); 7833f3b442bSKonstantin Komarov 7843f3b442bSKonstantin Komarov if (!RB_EMPTY_ROOT(&wnd->start_tree)) 785*bac89bb3SKonstantin Komarov wnd_remove_free_ext(wnd, bit, op); 786*bac89bb3SKonstantin Komarov } 7873f3b442bSKonstantin Komarov return err; 7883f3b442bSKonstantin Komarov } 7893f3b442bSKonstantin Komarov 7903f3b442bSKonstantin Komarov /* 791ec5fc720SKonstantin Komarov * wnd_set_used_safe - Mark the bits range from bit to bit + bits as used. 792ec5fc720SKonstantin Komarov * 793ec5fc720SKonstantin Komarov * Unlikely wnd_set_used/wnd_set_free this function is not full trusted. 794ec5fc720SKonstantin Komarov * It scans every bit in bitmap and marks free bit as used. 795ec5fc720SKonstantin Komarov * @done - how many bits were marked as used. 796ec5fc720SKonstantin Komarov * 797ec5fc720SKonstantin Komarov * NOTE: normally *done should be 0. 798ec5fc720SKonstantin Komarov */ 799ec5fc720SKonstantin Komarov int wnd_set_used_safe(struct wnd_bitmap *wnd, size_t bit, size_t bits, 800ec5fc720SKonstantin Komarov size_t *done) 801ec5fc720SKonstantin Komarov { 802ec5fc720SKonstantin Komarov size_t i, from = 0, len = 0; 803ec5fc720SKonstantin Komarov int err = 0; 804ec5fc720SKonstantin Komarov 805ec5fc720SKonstantin Komarov *done = 0; 806ec5fc720SKonstantin Komarov for (i = 0; i < bits; i++) { 807ec5fc720SKonstantin Komarov if (wnd_is_free(wnd, bit + i, 1)) { 808ec5fc720SKonstantin Komarov if (!len) 809ec5fc720SKonstantin Komarov from = bit + i; 810ec5fc720SKonstantin Komarov len += 1; 811ec5fc720SKonstantin Komarov } else if (len) { 812ec5fc720SKonstantin Komarov err = wnd_set_used(wnd, from, len); 813ec5fc720SKonstantin Komarov *done += len; 814ec5fc720SKonstantin Komarov len = 0; 815ec5fc720SKonstantin Komarov if (err) 816ec5fc720SKonstantin Komarov break; 817ec5fc720SKonstantin Komarov } 818ec5fc720SKonstantin Komarov } 819ec5fc720SKonstantin Komarov 820ec5fc720SKonstantin Komarov if (len) { 821ec5fc720SKonstantin Komarov /* last fragment. */ 822ec5fc720SKonstantin Komarov err = wnd_set_used(wnd, from, len); 823ec5fc720SKonstantin Komarov *done += len; 824ec5fc720SKonstantin Komarov } 825ec5fc720SKonstantin Komarov return err; 826ec5fc720SKonstantin Komarov } 827ec5fc720SKonstantin Komarov 828ec5fc720SKonstantin Komarov /* 8293f3b442bSKonstantin Komarov * wnd_is_free_hlp 8303f3b442bSKonstantin Komarov * 831e8b8e97fSKari Argillander * Return: True if all clusters [bit, bit+bits) are free (bitmap only). 8323f3b442bSKonstantin Komarov */ 8333f3b442bSKonstantin Komarov static bool wnd_is_free_hlp(struct wnd_bitmap *wnd, size_t bit, size_t bits) 8343f3b442bSKonstantin Komarov { 8353f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 8363f3b442bSKonstantin Komarov size_t iw = bit >> (sb->s_blocksize_bits + 3); 8373f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 8383f3b442bSKonstantin Komarov u32 wbit = bit & (wbits - 1); 839*bac89bb3SKonstantin Komarov u32 op; 8403f3b442bSKonstantin Komarov 841*bac89bb3SKonstantin Komarov for (; iw < wnd->nwnd && bits; iw++, bits -= op, wbit = 0) { 8423f3b442bSKonstantin Komarov if (unlikely(iw + 1 == wnd->nwnd)) 8433f3b442bSKonstantin Komarov wbits = wnd->bits_last; 8443f3b442bSKonstantin Komarov 845*bac89bb3SKonstantin Komarov op = min_t(u32, wbits - wbit, bits); 8463f3b442bSKonstantin Komarov 8473f3b442bSKonstantin Komarov if (wbits != wnd->free_bits[iw]) { 8483f3b442bSKonstantin Komarov bool ret; 8493f3b442bSKonstantin Komarov struct buffer_head *bh = wnd_map(wnd, iw); 8503f3b442bSKonstantin Komarov 8513f3b442bSKonstantin Komarov if (IS_ERR(bh)) 8523f3b442bSKonstantin Komarov return false; 8533f3b442bSKonstantin Komarov 85408811ba5SKonstantin Komarov ret = are_bits_clear(bh->b_data, wbit, op); 8553f3b442bSKonstantin Komarov 8563f3b442bSKonstantin Komarov put_bh(bh); 8573f3b442bSKonstantin Komarov if (!ret) 8583f3b442bSKonstantin Komarov return false; 8593f3b442bSKonstantin Komarov } 8603f3b442bSKonstantin Komarov } 8613f3b442bSKonstantin Komarov 8623f3b442bSKonstantin Komarov return true; 8633f3b442bSKonstantin Komarov } 8643f3b442bSKonstantin Komarov 8653f3b442bSKonstantin Komarov /* 8663f3b442bSKonstantin Komarov * wnd_is_free 8673f3b442bSKonstantin Komarov * 868e8b8e97fSKari Argillander * Return: True if all clusters [bit, bit+bits) are free. 8693f3b442bSKonstantin Komarov */ 8703f3b442bSKonstantin Komarov bool wnd_is_free(struct wnd_bitmap *wnd, size_t bit, size_t bits) 8713f3b442bSKonstantin Komarov { 8723f3b442bSKonstantin Komarov bool ret; 8733f3b442bSKonstantin Komarov struct rb_node *n; 8743f3b442bSKonstantin Komarov size_t end; 8753f3b442bSKonstantin Komarov struct e_node *e; 8763f3b442bSKonstantin Komarov 8773f3b442bSKonstantin Komarov if (RB_EMPTY_ROOT(&wnd->start_tree)) 8783f3b442bSKonstantin Komarov goto use_wnd; 8793f3b442bSKonstantin Komarov 8803f3b442bSKonstantin Komarov n = rb_lookup(&wnd->start_tree, bit); 8813f3b442bSKonstantin Komarov if (!n) 8823f3b442bSKonstantin Komarov goto use_wnd; 8833f3b442bSKonstantin Komarov 8843f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, start.node); 8853f3b442bSKonstantin Komarov 8863f3b442bSKonstantin Komarov end = e->start.key + e->count.key; 8873f3b442bSKonstantin Komarov 8883f3b442bSKonstantin Komarov if (bit < end && bit + bits <= end) 8893f3b442bSKonstantin Komarov return true; 8903f3b442bSKonstantin Komarov 8913f3b442bSKonstantin Komarov use_wnd: 8923f3b442bSKonstantin Komarov ret = wnd_is_free_hlp(wnd, bit, bits); 8933f3b442bSKonstantin Komarov 8943f3b442bSKonstantin Komarov return ret; 8953f3b442bSKonstantin Komarov } 8963f3b442bSKonstantin Komarov 8973f3b442bSKonstantin Komarov /* 8983f3b442bSKonstantin Komarov * wnd_is_used 8993f3b442bSKonstantin Komarov * 900e8b8e97fSKari Argillander * Return: True if all clusters [bit, bit+bits) are used. 9013f3b442bSKonstantin Komarov */ 9023f3b442bSKonstantin Komarov bool wnd_is_used(struct wnd_bitmap *wnd, size_t bit, size_t bits) 9033f3b442bSKonstantin Komarov { 9043f3b442bSKonstantin Komarov bool ret = false; 9053f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 9063f3b442bSKonstantin Komarov size_t iw = bit >> (sb->s_blocksize_bits + 3); 9073f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 9083f3b442bSKonstantin Komarov u32 wbit = bit & (wbits - 1); 909*bac89bb3SKonstantin Komarov u32 op; 9103f3b442bSKonstantin Komarov size_t end; 9113f3b442bSKonstantin Komarov struct rb_node *n; 9123f3b442bSKonstantin Komarov struct e_node *e; 9133f3b442bSKonstantin Komarov 9143f3b442bSKonstantin Komarov if (RB_EMPTY_ROOT(&wnd->start_tree)) 9153f3b442bSKonstantin Komarov goto use_wnd; 9163f3b442bSKonstantin Komarov 9173f3b442bSKonstantin Komarov end = bit + bits; 9183f3b442bSKonstantin Komarov n = rb_lookup(&wnd->start_tree, end - 1); 9193f3b442bSKonstantin Komarov if (!n) 9203f3b442bSKonstantin Komarov goto use_wnd; 9213f3b442bSKonstantin Komarov 9223f3b442bSKonstantin Komarov e = rb_entry(n, struct e_node, start.node); 9233f3b442bSKonstantin Komarov if (e->start.key + e->count.key > bit) 9243f3b442bSKonstantin Komarov return false; 9253f3b442bSKonstantin Komarov 9263f3b442bSKonstantin Komarov use_wnd: 927*bac89bb3SKonstantin Komarov for (; iw < wnd->nwnd && bits; iw++, bits -= op, wbit = 0) { 9283f3b442bSKonstantin Komarov if (unlikely(iw + 1 == wnd->nwnd)) 9293f3b442bSKonstantin Komarov wbits = wnd->bits_last; 9303f3b442bSKonstantin Komarov 931*bac89bb3SKonstantin Komarov op = min_t(u32, wbits - wbit, bits); 9323f3b442bSKonstantin Komarov 9333f3b442bSKonstantin Komarov if (wnd->free_bits[iw]) { 9343f3b442bSKonstantin Komarov bool ret; 9353f3b442bSKonstantin Komarov struct buffer_head *bh = wnd_map(wnd, iw); 9363f3b442bSKonstantin Komarov 9373f3b442bSKonstantin Komarov if (IS_ERR(bh)) 9383f3b442bSKonstantin Komarov goto out; 9393f3b442bSKonstantin Komarov 94008811ba5SKonstantin Komarov ret = are_bits_set(bh->b_data, wbit, op); 9413f3b442bSKonstantin Komarov put_bh(bh); 9423f3b442bSKonstantin Komarov if (!ret) 9433f3b442bSKonstantin Komarov goto out; 9443f3b442bSKonstantin Komarov } 9453f3b442bSKonstantin Komarov } 9463f3b442bSKonstantin Komarov ret = true; 9473f3b442bSKonstantin Komarov 9483f3b442bSKonstantin Komarov out: 9493f3b442bSKonstantin Komarov return ret; 9503f3b442bSKonstantin Komarov } 9513f3b442bSKonstantin Komarov 9523f3b442bSKonstantin Komarov /* 953e8b8e97fSKari Argillander * wnd_find - Look for free space. 954e8b8e97fSKari Argillander * 9553f3b442bSKonstantin Komarov * - flags - BITMAP_FIND_XXX flags 9563f3b442bSKonstantin Komarov * 957e8b8e97fSKari Argillander * Return: 0 if not found. 9583f3b442bSKonstantin Komarov */ 9593f3b442bSKonstantin Komarov size_t wnd_find(struct wnd_bitmap *wnd, size_t to_alloc, size_t hint, 9603f3b442bSKonstantin Komarov size_t flags, size_t *allocated) 9613f3b442bSKonstantin Komarov { 9623f3b442bSKonstantin Komarov struct super_block *sb; 9633f3b442bSKonstantin Komarov u32 wbits, wpos, wzbit, wzend; 9643f3b442bSKonstantin Komarov size_t fnd, max_alloc, b_len, b_pos; 9653f3b442bSKonstantin Komarov size_t iw, prev_tail, nwnd, wbit, ebit, zbit, zend; 9663f3b442bSKonstantin Komarov size_t to_alloc0 = to_alloc; 9673f3b442bSKonstantin Komarov const struct e_node *e; 9683f3b442bSKonstantin Komarov const struct rb_node *pr, *cr; 9693f3b442bSKonstantin Komarov u8 log2_bits; 9703f3b442bSKonstantin Komarov bool fbits_valid; 9713f3b442bSKonstantin Komarov struct buffer_head *bh; 9723f3b442bSKonstantin Komarov 973e8b8e97fSKari Argillander /* Fast checking for available free space. */ 9743f3b442bSKonstantin Komarov if (flags & BITMAP_FIND_FULL) { 9753f3b442bSKonstantin Komarov size_t zeroes = wnd_zeroes(wnd); 9763f3b442bSKonstantin Komarov 9773f3b442bSKonstantin Komarov zeroes -= wnd->zone_end - wnd->zone_bit; 9783f3b442bSKonstantin Komarov if (zeroes < to_alloc0) 9793f3b442bSKonstantin Komarov goto no_space; 9803f3b442bSKonstantin Komarov 9813f3b442bSKonstantin Komarov if (to_alloc0 > wnd->extent_max) 9823f3b442bSKonstantin Komarov goto no_space; 9833f3b442bSKonstantin Komarov } else { 9843f3b442bSKonstantin Komarov if (to_alloc > wnd->extent_max) 9853f3b442bSKonstantin Komarov to_alloc = wnd->extent_max; 9863f3b442bSKonstantin Komarov } 9873f3b442bSKonstantin Komarov 9883f3b442bSKonstantin Komarov if (wnd->zone_bit <= hint && hint < wnd->zone_end) 9893f3b442bSKonstantin Komarov hint = wnd->zone_end; 9903f3b442bSKonstantin Komarov 9913f3b442bSKonstantin Komarov max_alloc = wnd->nbits; 9923f3b442bSKonstantin Komarov b_len = b_pos = 0; 9933f3b442bSKonstantin Komarov 9943f3b442bSKonstantin Komarov if (hint >= max_alloc) 9953f3b442bSKonstantin Komarov hint = 0; 9963f3b442bSKonstantin Komarov 9973f3b442bSKonstantin Komarov if (RB_EMPTY_ROOT(&wnd->start_tree)) { 9983f3b442bSKonstantin Komarov if (wnd->uptodated == 1) { 999e8b8e97fSKari Argillander /* Extents tree is updated -> No free space. */ 10003f3b442bSKonstantin Komarov goto no_space; 10013f3b442bSKonstantin Komarov } 10023f3b442bSKonstantin Komarov goto scan_bitmap; 10033f3b442bSKonstantin Komarov } 10043f3b442bSKonstantin Komarov 10053f3b442bSKonstantin Komarov e = NULL; 10063f3b442bSKonstantin Komarov if (!hint) 10073f3b442bSKonstantin Komarov goto allocate_biggest; 10083f3b442bSKonstantin Komarov 1009e8b8e97fSKari Argillander /* Use hint: Enumerate extents by start >= hint. */ 10103f3b442bSKonstantin Komarov pr = NULL; 10113f3b442bSKonstantin Komarov cr = wnd->start_tree.rb_node; 10123f3b442bSKonstantin Komarov 10133f3b442bSKonstantin Komarov for (;;) { 10143f3b442bSKonstantin Komarov e = rb_entry(cr, struct e_node, start.node); 10153f3b442bSKonstantin Komarov 10163f3b442bSKonstantin Komarov if (e->start.key == hint) 10173f3b442bSKonstantin Komarov break; 10183f3b442bSKonstantin Komarov 10193f3b442bSKonstantin Komarov if (e->start.key < hint) { 10203f3b442bSKonstantin Komarov pr = cr; 10213f3b442bSKonstantin Komarov cr = cr->rb_right; 10223f3b442bSKonstantin Komarov if (!cr) 10233f3b442bSKonstantin Komarov break; 10243f3b442bSKonstantin Komarov continue; 10253f3b442bSKonstantin Komarov } 10263f3b442bSKonstantin Komarov 10273f3b442bSKonstantin Komarov cr = cr->rb_left; 10283f3b442bSKonstantin Komarov if (!cr) { 10293f3b442bSKonstantin Komarov e = pr ? rb_entry(pr, struct e_node, start.node) : NULL; 10303f3b442bSKonstantin Komarov break; 10313f3b442bSKonstantin Komarov } 10323f3b442bSKonstantin Komarov } 10333f3b442bSKonstantin Komarov 10343f3b442bSKonstantin Komarov if (!e) 10353f3b442bSKonstantin Komarov goto allocate_biggest; 10363f3b442bSKonstantin Komarov 10373f3b442bSKonstantin Komarov if (e->start.key + e->count.key > hint) { 1038e8b8e97fSKari Argillander /* We have found extension with 'hint' inside. */ 10393f3b442bSKonstantin Komarov size_t len = e->start.key + e->count.key - hint; 10403f3b442bSKonstantin Komarov 10413f3b442bSKonstantin Komarov if (len >= to_alloc && hint + to_alloc <= max_alloc) { 10423f3b442bSKonstantin Komarov fnd = hint; 10433f3b442bSKonstantin Komarov goto found; 10443f3b442bSKonstantin Komarov } 10453f3b442bSKonstantin Komarov 10463f3b442bSKonstantin Komarov if (!(flags & BITMAP_FIND_FULL)) { 10473f3b442bSKonstantin Komarov if (len > to_alloc) 10483f3b442bSKonstantin Komarov len = to_alloc; 10493f3b442bSKonstantin Komarov 10503f3b442bSKonstantin Komarov if (hint + len <= max_alloc) { 10513f3b442bSKonstantin Komarov fnd = hint; 10523f3b442bSKonstantin Komarov to_alloc = len; 10533f3b442bSKonstantin Komarov goto found; 10543f3b442bSKonstantin Komarov } 10553f3b442bSKonstantin Komarov } 10563f3b442bSKonstantin Komarov } 10573f3b442bSKonstantin Komarov 10583f3b442bSKonstantin Komarov allocate_biggest: 1059e8b8e97fSKari Argillander /* Allocate from biggest free extent. */ 10603f3b442bSKonstantin Komarov e = rb_entry(rb_first(&wnd->count_tree), struct e_node, count.node); 10613f3b442bSKonstantin Komarov if (e->count.key != wnd->extent_max) 10623f3b442bSKonstantin Komarov wnd->extent_max = e->count.key; 10633f3b442bSKonstantin Komarov 10643f3b442bSKonstantin Komarov if (e->count.key < max_alloc) { 10653f3b442bSKonstantin Komarov if (e->count.key >= to_alloc) { 10663f3b442bSKonstantin Komarov ; 10673f3b442bSKonstantin Komarov } else if (flags & BITMAP_FIND_FULL) { 10683f3b442bSKonstantin Komarov if (e->count.key < to_alloc0) { 1069e8b8e97fSKari Argillander /* Biggest free block is less then requested. */ 10703f3b442bSKonstantin Komarov goto no_space; 10713f3b442bSKonstantin Komarov } 10723f3b442bSKonstantin Komarov to_alloc = e->count.key; 10733f3b442bSKonstantin Komarov } else if (-1 != wnd->uptodated) { 10743f3b442bSKonstantin Komarov to_alloc = e->count.key; 10753f3b442bSKonstantin Komarov } else { 1076e8b8e97fSKari Argillander /* Check if we can use more bits. */ 10773f3b442bSKonstantin Komarov size_t op, max_check; 10783f3b442bSKonstantin Komarov struct rb_root start_tree; 10793f3b442bSKonstantin Komarov 10803f3b442bSKonstantin Komarov memcpy(&start_tree, &wnd->start_tree, 10813f3b442bSKonstantin Komarov sizeof(struct rb_root)); 10823f3b442bSKonstantin Komarov memset(&wnd->start_tree, 0, sizeof(struct rb_root)); 10833f3b442bSKonstantin Komarov 10843f3b442bSKonstantin Komarov max_check = e->start.key + to_alloc; 10853f3b442bSKonstantin Komarov if (max_check > max_alloc) 10863f3b442bSKonstantin Komarov max_check = max_alloc; 10873f3b442bSKonstantin Komarov for (op = e->start.key + e->count.key; op < max_check; 10883f3b442bSKonstantin Komarov op++) { 10893f3b442bSKonstantin Komarov if (!wnd_is_free(wnd, op, 1)) 10903f3b442bSKonstantin Komarov break; 10913f3b442bSKonstantin Komarov } 10923f3b442bSKonstantin Komarov memcpy(&wnd->start_tree, &start_tree, 10933f3b442bSKonstantin Komarov sizeof(struct rb_root)); 10943f3b442bSKonstantin Komarov to_alloc = op - e->start.key; 10953f3b442bSKonstantin Komarov } 10963f3b442bSKonstantin Komarov 1097e8b8e97fSKari Argillander /* Prepare to return. */ 10983f3b442bSKonstantin Komarov fnd = e->start.key; 10993f3b442bSKonstantin Komarov if (e->start.key + to_alloc > max_alloc) 11003f3b442bSKonstantin Komarov to_alloc = max_alloc - e->start.key; 11013f3b442bSKonstantin Komarov goto found; 11023f3b442bSKonstantin Komarov } 11033f3b442bSKonstantin Komarov 11043f3b442bSKonstantin Komarov if (wnd->uptodated == 1) { 1105e8b8e97fSKari Argillander /* Extents tree is updated -> no free space. */ 11063f3b442bSKonstantin Komarov goto no_space; 11073f3b442bSKonstantin Komarov } 11083f3b442bSKonstantin Komarov 11093f3b442bSKonstantin Komarov b_len = e->count.key; 11103f3b442bSKonstantin Komarov b_pos = e->start.key; 11113f3b442bSKonstantin Komarov 11123f3b442bSKonstantin Komarov scan_bitmap: 11133f3b442bSKonstantin Komarov sb = wnd->sb; 11143f3b442bSKonstantin Komarov log2_bits = sb->s_blocksize_bits + 3; 11153f3b442bSKonstantin Komarov 1116d3624466SKonstantin Komarov /* At most two ranges [hint, max_alloc) + [0, hint). */ 11173f3b442bSKonstantin Komarov Again: 11183f3b442bSKonstantin Komarov 1119e8b8e97fSKari Argillander /* TODO: Optimize request for case nbits > wbits. */ 11203f3b442bSKonstantin Komarov iw = hint >> log2_bits; 11213f3b442bSKonstantin Komarov wbits = sb->s_blocksize * 8; 11223f3b442bSKonstantin Komarov wpos = hint & (wbits - 1); 11233f3b442bSKonstantin Komarov prev_tail = 0; 11243f3b442bSKonstantin Komarov fbits_valid = true; 11253f3b442bSKonstantin Komarov 11263f3b442bSKonstantin Komarov if (max_alloc == wnd->nbits) { 11273f3b442bSKonstantin Komarov nwnd = wnd->nwnd; 11283f3b442bSKonstantin Komarov } else { 11293f3b442bSKonstantin Komarov size_t t = max_alloc + wbits - 1; 11303f3b442bSKonstantin Komarov 11313f3b442bSKonstantin Komarov nwnd = likely(t > max_alloc) ? (t >> log2_bits) : wnd->nwnd; 11323f3b442bSKonstantin Komarov } 11333f3b442bSKonstantin Komarov 1134e8b8e97fSKari Argillander /* Enumerate all windows. */ 11353f3b442bSKonstantin Komarov for (; iw < nwnd; iw++) { 11363f3b442bSKonstantin Komarov wbit = iw << log2_bits; 11373f3b442bSKonstantin Komarov 11383f3b442bSKonstantin Komarov if (!wnd->free_bits[iw]) { 11393f3b442bSKonstantin Komarov if (prev_tail > b_len) { 11403f3b442bSKonstantin Komarov b_pos = wbit - prev_tail; 11413f3b442bSKonstantin Komarov b_len = prev_tail; 11423f3b442bSKonstantin Komarov } 11433f3b442bSKonstantin Komarov 1144e8b8e97fSKari Argillander /* Skip full used window. */ 11453f3b442bSKonstantin Komarov prev_tail = 0; 11463f3b442bSKonstantin Komarov wpos = 0; 11473f3b442bSKonstantin Komarov continue; 11483f3b442bSKonstantin Komarov } 11493f3b442bSKonstantin Komarov 11503f3b442bSKonstantin Komarov if (unlikely(iw + 1 == nwnd)) { 11513f3b442bSKonstantin Komarov if (max_alloc == wnd->nbits) { 11523f3b442bSKonstantin Komarov wbits = wnd->bits_last; 11533f3b442bSKonstantin Komarov } else { 11543f3b442bSKonstantin Komarov size_t t = max_alloc & (wbits - 1); 11553f3b442bSKonstantin Komarov 11563f3b442bSKonstantin Komarov if (t) { 11573f3b442bSKonstantin Komarov wbits = t; 11583f3b442bSKonstantin Komarov fbits_valid = false; 11593f3b442bSKonstantin Komarov } 11603f3b442bSKonstantin Komarov } 11613f3b442bSKonstantin Komarov } 11623f3b442bSKonstantin Komarov 11633f3b442bSKonstantin Komarov if (wnd->zone_end > wnd->zone_bit) { 11643f3b442bSKonstantin Komarov ebit = wbit + wbits; 11653f3b442bSKonstantin Komarov zbit = max(wnd->zone_bit, wbit); 11663f3b442bSKonstantin Komarov zend = min(wnd->zone_end, ebit); 11673f3b442bSKonstantin Komarov 1168e8b8e97fSKari Argillander /* Here we have a window [wbit, ebit) and zone [zbit, zend). */ 11693f3b442bSKonstantin Komarov if (zend <= zbit) { 1170e8b8e97fSKari Argillander /* Zone does not overlap window. */ 11713f3b442bSKonstantin Komarov } else { 11723f3b442bSKonstantin Komarov wzbit = zbit - wbit; 11733f3b442bSKonstantin Komarov wzend = zend - wbit; 11743f3b442bSKonstantin Komarov 1175e8b8e97fSKari Argillander /* Zone overlaps window. */ 11763f3b442bSKonstantin Komarov if (wnd->free_bits[iw] == wzend - wzbit) { 11773f3b442bSKonstantin Komarov prev_tail = 0; 11783f3b442bSKonstantin Komarov wpos = 0; 11793f3b442bSKonstantin Komarov continue; 11803f3b442bSKonstantin Komarov } 11813f3b442bSKonstantin Komarov 1182e8b8e97fSKari Argillander /* Scan two ranges window: [wbit, zbit) and [zend, ebit). */ 11833f3b442bSKonstantin Komarov bh = wnd_map(wnd, iw); 11843f3b442bSKonstantin Komarov 11853f3b442bSKonstantin Komarov if (IS_ERR(bh)) { 1186e8b8e97fSKari Argillander /* TODO: Error */ 11873f3b442bSKonstantin Komarov prev_tail = 0; 11883f3b442bSKonstantin Komarov wpos = 0; 11893f3b442bSKonstantin Komarov continue; 11903f3b442bSKonstantin Komarov } 11913f3b442bSKonstantin Komarov 1192e8b8e97fSKari Argillander /* Scan range [wbit, zbit). */ 11933f3b442bSKonstantin Komarov if (wpos < wzbit) { 1194e8b8e97fSKari Argillander /* Scan range [wpos, zbit). */ 119508811ba5SKonstantin Komarov fnd = wnd_scan(bh->b_data, wbit, wpos, 119608811ba5SKonstantin Komarov wzbit, to_alloc, 119708811ba5SKonstantin Komarov &prev_tail, &b_pos, 119808811ba5SKonstantin Komarov &b_len); 11993f3b442bSKonstantin Komarov if (fnd != MINUS_ONE_T) { 12003f3b442bSKonstantin Komarov put_bh(bh); 12013f3b442bSKonstantin Komarov goto found; 12023f3b442bSKonstantin Komarov } 12033f3b442bSKonstantin Komarov } 12043f3b442bSKonstantin Komarov 12053f3b442bSKonstantin Komarov prev_tail = 0; 12063f3b442bSKonstantin Komarov 1207e8b8e97fSKari Argillander /* Scan range [zend, ebit). */ 12083f3b442bSKonstantin Komarov if (wzend < wbits) { 120908811ba5SKonstantin Komarov fnd = wnd_scan(bh->b_data, wbit, 12103f3b442bSKonstantin Komarov max(wzend, wpos), wbits, 12113f3b442bSKonstantin Komarov to_alloc, &prev_tail, 12123f3b442bSKonstantin Komarov &b_pos, &b_len); 12133f3b442bSKonstantin Komarov if (fnd != MINUS_ONE_T) { 12143f3b442bSKonstantin Komarov put_bh(bh); 12153f3b442bSKonstantin Komarov goto found; 12163f3b442bSKonstantin Komarov } 12173f3b442bSKonstantin Komarov } 12183f3b442bSKonstantin Komarov 12193f3b442bSKonstantin Komarov wpos = 0; 12203f3b442bSKonstantin Komarov put_bh(bh); 12213f3b442bSKonstantin Komarov continue; 12223f3b442bSKonstantin Komarov } 12233f3b442bSKonstantin Komarov } 12243f3b442bSKonstantin Komarov 1225e8b8e97fSKari Argillander /* Current window does not overlap zone. */ 12263f3b442bSKonstantin Komarov if (!wpos && fbits_valid && wnd->free_bits[iw] == wbits) { 1227e8b8e97fSKari Argillander /* Window is empty. */ 12283f3b442bSKonstantin Komarov if (prev_tail + wbits >= to_alloc) { 12293f3b442bSKonstantin Komarov fnd = wbit + wpos - prev_tail; 12303f3b442bSKonstantin Komarov goto found; 12313f3b442bSKonstantin Komarov } 12323f3b442bSKonstantin Komarov 1233e8b8e97fSKari Argillander /* Increase 'prev_tail' and process next window. */ 12343f3b442bSKonstantin Komarov prev_tail += wbits; 12353f3b442bSKonstantin Komarov wpos = 0; 12363f3b442bSKonstantin Komarov continue; 12373f3b442bSKonstantin Komarov } 12383f3b442bSKonstantin Komarov 1239d3624466SKonstantin Komarov /* Read window. */ 12403f3b442bSKonstantin Komarov bh = wnd_map(wnd, iw); 12413f3b442bSKonstantin Komarov if (IS_ERR(bh)) { 1242e8b8e97fSKari Argillander // TODO: Error. 12433f3b442bSKonstantin Komarov prev_tail = 0; 12443f3b442bSKonstantin Komarov wpos = 0; 12453f3b442bSKonstantin Komarov continue; 12463f3b442bSKonstantin Komarov } 12473f3b442bSKonstantin Komarov 1248e8b8e97fSKari Argillander /* Scan range [wpos, eBits). */ 124908811ba5SKonstantin Komarov fnd = wnd_scan(bh->b_data, wbit, wpos, wbits, to_alloc, 125008811ba5SKonstantin Komarov &prev_tail, &b_pos, &b_len); 12513f3b442bSKonstantin Komarov put_bh(bh); 12523f3b442bSKonstantin Komarov if (fnd != MINUS_ONE_T) 12533f3b442bSKonstantin Komarov goto found; 12543f3b442bSKonstantin Komarov } 12553f3b442bSKonstantin Komarov 12563f3b442bSKonstantin Komarov if (b_len < prev_tail) { 1257e8b8e97fSKari Argillander /* The last fragment. */ 12583f3b442bSKonstantin Komarov b_len = prev_tail; 12593f3b442bSKonstantin Komarov b_pos = max_alloc - prev_tail; 12603f3b442bSKonstantin Komarov } 12613f3b442bSKonstantin Komarov 12623f3b442bSKonstantin Komarov if (hint) { 12633f3b442bSKonstantin Komarov /* 1264e8b8e97fSKari Argillander * We have scanned range [hint max_alloc). 1265e8b8e97fSKari Argillander * Prepare to scan range [0 hint + to_alloc). 12663f3b442bSKonstantin Komarov */ 12673f3b442bSKonstantin Komarov size_t nextmax = hint + to_alloc; 12683f3b442bSKonstantin Komarov 12693f3b442bSKonstantin Komarov if (likely(nextmax >= hint) && nextmax < max_alloc) 12703f3b442bSKonstantin Komarov max_alloc = nextmax; 12713f3b442bSKonstantin Komarov hint = 0; 12723f3b442bSKonstantin Komarov goto Again; 12733f3b442bSKonstantin Komarov } 12743f3b442bSKonstantin Komarov 12753f3b442bSKonstantin Komarov if (!b_len) 12763f3b442bSKonstantin Komarov goto no_space; 12773f3b442bSKonstantin Komarov 12783f3b442bSKonstantin Komarov wnd->extent_max = b_len; 12793f3b442bSKonstantin Komarov 12803f3b442bSKonstantin Komarov if (flags & BITMAP_FIND_FULL) 12813f3b442bSKonstantin Komarov goto no_space; 12823f3b442bSKonstantin Komarov 12833f3b442bSKonstantin Komarov fnd = b_pos; 12843f3b442bSKonstantin Komarov to_alloc = b_len; 12853f3b442bSKonstantin Komarov 12863f3b442bSKonstantin Komarov found: 12873f3b442bSKonstantin Komarov if (flags & BITMAP_FIND_MARK_AS_USED) { 1288e8b8e97fSKari Argillander /* TODO: Optimize remove extent (pass 'e'?). */ 12893f3b442bSKonstantin Komarov if (wnd_set_used(wnd, fnd, to_alloc)) 12903f3b442bSKonstantin Komarov goto no_space; 12913f3b442bSKonstantin Komarov } else if (wnd->extent_max != MINUS_ONE_T && 12923f3b442bSKonstantin Komarov to_alloc > wnd->extent_max) { 12933f3b442bSKonstantin Komarov wnd->extent_max = to_alloc; 12943f3b442bSKonstantin Komarov } 12953f3b442bSKonstantin Komarov 12963f3b442bSKonstantin Komarov *allocated = fnd; 12973f3b442bSKonstantin Komarov return to_alloc; 12983f3b442bSKonstantin Komarov 12993f3b442bSKonstantin Komarov no_space: 13003f3b442bSKonstantin Komarov return 0; 13013f3b442bSKonstantin Komarov } 13023f3b442bSKonstantin Komarov 13033f3b442bSKonstantin Komarov /* 1304e8b8e97fSKari Argillander * wnd_extend - Extend bitmap ($MFT bitmap). 13053f3b442bSKonstantin Komarov */ 13063f3b442bSKonstantin Komarov int wnd_extend(struct wnd_bitmap *wnd, size_t new_bits) 13073f3b442bSKonstantin Komarov { 13083f3b442bSKonstantin Komarov int err; 13093f3b442bSKonstantin Komarov struct super_block *sb = wnd->sb; 13103f3b442bSKonstantin Komarov struct ntfs_sb_info *sbi = sb->s_fs_info; 13113f3b442bSKonstantin Komarov u32 blocksize = sb->s_blocksize; 13123f3b442bSKonstantin Komarov u32 wbits = blocksize * 8; 13133f3b442bSKonstantin Komarov u32 b0, new_last; 13143f3b442bSKonstantin Komarov size_t bits, iw, new_wnd; 13153f3b442bSKonstantin Komarov size_t old_bits = wnd->nbits; 13163f3b442bSKonstantin Komarov u16 *new_free; 13173f3b442bSKonstantin Komarov 13183f3b442bSKonstantin Komarov if (new_bits <= old_bits) 13193f3b442bSKonstantin Komarov return -EINVAL; 13203f3b442bSKonstantin Komarov 1321e8b8e97fSKari Argillander /* Align to 8 byte boundary. */ 13223f5ef510SAlexander Lobakin new_wnd = bytes_to_block(sb, ntfs3_bitmap_size(new_bits)); 13233f3b442bSKonstantin Komarov new_last = new_bits & (wbits - 1); 13243f3b442bSKonstantin Komarov if (!new_last) 13253f3b442bSKonstantin Komarov new_last = wbits; 13263f3b442bSKonstantin Komarov 13273f3b442bSKonstantin Komarov if (new_wnd != wnd->nwnd) { 132892f017c4SKenneth Lee new_free = kmalloc_array(new_wnd, sizeof(u16), GFP_NOFS); 13293f3b442bSKonstantin Komarov if (!new_free) 13303f3b442bSKonstantin Komarov return -ENOMEM; 13313f3b442bSKonstantin Komarov 1332548744f8SChristophe JAILLET memcpy(new_free, wnd->free_bits, wnd->nwnd * sizeof(short)); 13333f3b442bSKonstantin Komarov memset(new_free + wnd->nwnd, 0, 13343f3b442bSKonstantin Komarov (new_wnd - wnd->nwnd) * sizeof(short)); 1335ddb17dc8SKonstantin Komarov kvfree(wnd->free_bits); 13363f3b442bSKonstantin Komarov wnd->free_bits = new_free; 13373f3b442bSKonstantin Komarov } 13383f3b442bSKonstantin Komarov 1339e8b8e97fSKari Argillander /* Zero bits [old_bits,new_bits). */ 13403f3b442bSKonstantin Komarov bits = new_bits - old_bits; 13413f3b442bSKonstantin Komarov b0 = old_bits & (wbits - 1); 13423f3b442bSKonstantin Komarov 13433f3b442bSKonstantin Komarov for (iw = old_bits >> (sb->s_blocksize_bits + 3); bits; iw += 1) { 13443f3b442bSKonstantin Komarov u32 op; 13453f3b442bSKonstantin Komarov size_t frb; 13463f3b442bSKonstantin Komarov u64 vbo, lbo, bytes; 13473f3b442bSKonstantin Komarov struct buffer_head *bh; 13483f3b442bSKonstantin Komarov 13493f3b442bSKonstantin Komarov if (iw + 1 == new_wnd) 13503f3b442bSKonstantin Komarov wbits = new_last; 13513f3b442bSKonstantin Komarov 13523f3b442bSKonstantin Komarov op = b0 + bits > wbits ? wbits - b0 : bits; 13533f3b442bSKonstantin Komarov vbo = (u64)iw * blocksize; 13543f3b442bSKonstantin Komarov 13553f3b442bSKonstantin Komarov err = ntfs_vbo_to_lbo(sbi, &wnd->run, vbo, &lbo, &bytes); 13563f3b442bSKonstantin Komarov if (err) 13572cbbd968SKonstantin Komarov return err; 13583f3b442bSKonstantin Komarov 13593f3b442bSKonstantin Komarov bh = ntfs_bread(sb, lbo >> sb->s_blocksize_bits); 13603f3b442bSKonstantin Komarov if (!bh) 13613f3b442bSKonstantin Komarov return -EIO; 13623f3b442bSKonstantin Komarov 13633f3b442bSKonstantin Komarov lock_buffer(bh); 13643f3b442bSKonstantin Komarov 136508811ba5SKonstantin Komarov ntfs_bitmap_clear_le(bh->b_data, b0, blocksize * 8 - b0); 136608811ba5SKonstantin Komarov frb = wbits - ntfs_bitmap_weight_le(bh->b_data, wbits); 13673f3b442bSKonstantin Komarov wnd->total_zeroes += frb - wnd->free_bits[iw]; 13683f3b442bSKonstantin Komarov wnd->free_bits[iw] = frb; 13693f3b442bSKonstantin Komarov 13703f3b442bSKonstantin Komarov set_buffer_uptodate(bh); 13713f3b442bSKonstantin Komarov mark_buffer_dirty(bh); 13723f3b442bSKonstantin Komarov unlock_buffer(bh); 13733f3b442bSKonstantin Komarov /* err = sync_dirty_buffer(bh); */ 13743f3b442bSKonstantin Komarov 13753f3b442bSKonstantin Komarov b0 = 0; 13763f3b442bSKonstantin Komarov bits -= op; 13773f3b442bSKonstantin Komarov } 13783f3b442bSKonstantin Komarov 13793f3b442bSKonstantin Komarov wnd->nbits = new_bits; 13803f3b442bSKonstantin Komarov wnd->nwnd = new_wnd; 13813f3b442bSKonstantin Komarov wnd->bits_last = new_last; 13823f3b442bSKonstantin Komarov 13833f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, old_bits, new_bits - old_bits, false); 13843f3b442bSKonstantin Komarov 13853f3b442bSKonstantin Komarov return 0; 13863f3b442bSKonstantin Komarov } 13873f3b442bSKonstantin Komarov 13883f3b442bSKonstantin Komarov void wnd_zone_set(struct wnd_bitmap *wnd, size_t lcn, size_t len) 13893f3b442bSKonstantin Komarov { 139054033c13SKonstantin Komarov size_t zlen = wnd->zone_end - wnd->zone_bit; 13913f3b442bSKonstantin Komarov 13923f3b442bSKonstantin Komarov if (zlen) 13933f3b442bSKonstantin Komarov wnd_add_free_ext(wnd, wnd->zone_bit, zlen, false); 13943f3b442bSKonstantin Komarov 13953f3b442bSKonstantin Komarov if (!RB_EMPTY_ROOT(&wnd->start_tree) && len) 13963f3b442bSKonstantin Komarov wnd_remove_free_ext(wnd, lcn, len); 13973f3b442bSKonstantin Komarov 13983f3b442bSKonstantin Komarov wnd->zone_bit = lcn; 13993f3b442bSKonstantin Komarov wnd->zone_end = lcn + len; 14003f3b442bSKonstantin Komarov } 14013f3b442bSKonstantin Komarov 14023f3b442bSKonstantin Komarov int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range) 14033f3b442bSKonstantin Komarov { 14043f3b442bSKonstantin Komarov int err = 0; 14053f3b442bSKonstantin Komarov struct super_block *sb = sbi->sb; 14063f3b442bSKonstantin Komarov struct wnd_bitmap *wnd = &sbi->used.bitmap; 14073f3b442bSKonstantin Komarov u32 wbits = 8 * sb->s_blocksize; 14083f3b442bSKonstantin Komarov CLST len = 0, lcn = 0, done = 0; 14093f3b442bSKonstantin Komarov CLST minlen = bytes_to_cluster(sbi, range->minlen); 14103f3b442bSKonstantin Komarov CLST lcn_from = bytes_to_cluster(sbi, range->start); 14113f3b442bSKonstantin Komarov size_t iw = lcn_from >> (sb->s_blocksize_bits + 3); 14123f3b442bSKonstantin Komarov u32 wbit = lcn_from & (wbits - 1); 14133f3b442bSKonstantin Komarov CLST lcn_to; 14143f3b442bSKonstantin Komarov 14153f3b442bSKonstantin Komarov if (!minlen) 14163f3b442bSKonstantin Komarov minlen = 1; 14173f3b442bSKonstantin Komarov 14183f3b442bSKonstantin Komarov if (range->len == (u64)-1) 14193f3b442bSKonstantin Komarov lcn_to = wnd->nbits; 14203f3b442bSKonstantin Komarov else 14213f3b442bSKonstantin Komarov lcn_to = bytes_to_cluster(sbi, range->start + range->len); 14223f3b442bSKonstantin Komarov 14233f3b442bSKonstantin Komarov down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS); 14243f3b442bSKonstantin Komarov 1425557d1967SAbdun Nihaal for (; iw < wnd->nwnd; iw++, wbit = 0) { 14263f3b442bSKonstantin Komarov CLST lcn_wnd = iw * wbits; 14273f3b442bSKonstantin Komarov struct buffer_head *bh; 14283f3b442bSKonstantin Komarov 14293f3b442bSKonstantin Komarov if (lcn_wnd > lcn_to) 14303f3b442bSKonstantin Komarov break; 14313f3b442bSKonstantin Komarov 14323f3b442bSKonstantin Komarov if (!wnd->free_bits[iw]) 14333f3b442bSKonstantin Komarov continue; 14343f3b442bSKonstantin Komarov 14353f3b442bSKonstantin Komarov if (iw + 1 == wnd->nwnd) 14363f3b442bSKonstantin Komarov wbits = wnd->bits_last; 14373f3b442bSKonstantin Komarov 14383f3b442bSKonstantin Komarov if (lcn_wnd + wbits > lcn_to) 14393f3b442bSKonstantin Komarov wbits = lcn_to - lcn_wnd; 14403f3b442bSKonstantin Komarov 14413f3b442bSKonstantin Komarov bh = wnd_map(wnd, iw); 14423f3b442bSKonstantin Komarov if (IS_ERR(bh)) { 14433f3b442bSKonstantin Komarov err = PTR_ERR(bh); 14443f3b442bSKonstantin Komarov break; 14453f3b442bSKonstantin Komarov } 14463f3b442bSKonstantin Komarov 14473f3b442bSKonstantin Komarov for (; wbit < wbits; wbit++) { 144808811ba5SKonstantin Komarov if (!test_bit_le(wbit, bh->b_data)) { 14493f3b442bSKonstantin Komarov if (!len) 14503f3b442bSKonstantin Komarov lcn = lcn_wnd + wbit; 14513f3b442bSKonstantin Komarov len += 1; 14523f3b442bSKonstantin Komarov continue; 14533f3b442bSKonstantin Komarov } 14543f3b442bSKonstantin Komarov if (len >= minlen) { 14553f3b442bSKonstantin Komarov err = ntfs_discard(sbi, lcn, len); 14563f3b442bSKonstantin Komarov if (err) 14573f3b442bSKonstantin Komarov goto out; 14583f3b442bSKonstantin Komarov done += len; 14593f3b442bSKonstantin Komarov } 14603f3b442bSKonstantin Komarov len = 0; 14613f3b442bSKonstantin Komarov } 14623f3b442bSKonstantin Komarov put_bh(bh); 14633f3b442bSKonstantin Komarov } 14643f3b442bSKonstantin Komarov 1465e8b8e97fSKari Argillander /* Process the last fragment. */ 14663f3b442bSKonstantin Komarov if (len >= minlen) { 14673f3b442bSKonstantin Komarov err = ntfs_discard(sbi, lcn, len); 14683f3b442bSKonstantin Komarov if (err) 14693f3b442bSKonstantin Komarov goto out; 14703f3b442bSKonstantin Komarov done += len; 14713f3b442bSKonstantin Komarov } 14723f3b442bSKonstantin Komarov 14733f3b442bSKonstantin Komarov out: 14743f3b442bSKonstantin Komarov range->len = (u64)done << sbi->cluster_bits; 14753f3b442bSKonstantin Komarov 14763f3b442bSKonstantin Komarov up_read(&wnd->rw_lock); 14773f3b442bSKonstantin Komarov 14783f3b442bSKonstantin Komarov return err; 14793f3b442bSKonstantin Komarov } 148088a8d0d2SThomas Kühnel 148108811ba5SKonstantin Komarov #if BITS_PER_LONG == 64 148208811ba5SKonstantin Komarov typedef __le64 bitmap_ulong; 148308811ba5SKonstantin Komarov #define cpu_to_ul(x) cpu_to_le64(x) 148408811ba5SKonstantin Komarov #define ul_to_cpu(x) le64_to_cpu(x) 148508811ba5SKonstantin Komarov #else 148608811ba5SKonstantin Komarov typedef __le32 bitmap_ulong; 148708811ba5SKonstantin Komarov #define cpu_to_ul(x) cpu_to_le32(x) 148808811ba5SKonstantin Komarov #define ul_to_cpu(x) le32_to_cpu(x) 148908811ba5SKonstantin Komarov #endif 149008811ba5SKonstantin Komarov 149108811ba5SKonstantin Komarov void ntfs_bitmap_set_le(void *map, unsigned int start, int len) 149288a8d0d2SThomas Kühnel { 149308811ba5SKonstantin Komarov bitmap_ulong *p = (bitmap_ulong *)map + BIT_WORD(start); 149488a8d0d2SThomas Kühnel const unsigned int size = start + len; 149588a8d0d2SThomas Kühnel int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); 149608811ba5SKonstantin Komarov bitmap_ulong mask_to_set = cpu_to_ul(BITMAP_FIRST_WORD_MASK(start)); 149788a8d0d2SThomas Kühnel 149888a8d0d2SThomas Kühnel while (len - bits_to_set >= 0) { 149988a8d0d2SThomas Kühnel *p |= mask_to_set; 150088a8d0d2SThomas Kühnel len -= bits_to_set; 150188a8d0d2SThomas Kühnel bits_to_set = BITS_PER_LONG; 150208811ba5SKonstantin Komarov mask_to_set = cpu_to_ul(~0UL); 150388a8d0d2SThomas Kühnel p++; 150488a8d0d2SThomas Kühnel } 150588a8d0d2SThomas Kühnel if (len) { 150608811ba5SKonstantin Komarov mask_to_set &= cpu_to_ul(BITMAP_LAST_WORD_MASK(size)); 150788a8d0d2SThomas Kühnel *p |= mask_to_set; 150888a8d0d2SThomas Kühnel } 150988a8d0d2SThomas Kühnel } 151088a8d0d2SThomas Kühnel 151108811ba5SKonstantin Komarov void ntfs_bitmap_clear_le(void *map, unsigned int start, int len) 151288a8d0d2SThomas Kühnel { 151308811ba5SKonstantin Komarov bitmap_ulong *p = (bitmap_ulong *)map + BIT_WORD(start); 151488a8d0d2SThomas Kühnel const unsigned int size = start + len; 151588a8d0d2SThomas Kühnel int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); 151608811ba5SKonstantin Komarov bitmap_ulong mask_to_clear = cpu_to_ul(BITMAP_FIRST_WORD_MASK(start)); 151788a8d0d2SThomas Kühnel 151888a8d0d2SThomas Kühnel while (len - bits_to_clear >= 0) { 151988a8d0d2SThomas Kühnel *p &= ~mask_to_clear; 152088a8d0d2SThomas Kühnel len -= bits_to_clear; 152188a8d0d2SThomas Kühnel bits_to_clear = BITS_PER_LONG; 152208811ba5SKonstantin Komarov mask_to_clear = cpu_to_ul(~0UL); 152388a8d0d2SThomas Kühnel p++; 152488a8d0d2SThomas Kühnel } 152588a8d0d2SThomas Kühnel if (len) { 152608811ba5SKonstantin Komarov mask_to_clear &= cpu_to_ul(BITMAP_LAST_WORD_MASK(size)); 152788a8d0d2SThomas Kühnel *p &= ~mask_to_clear; 152888a8d0d2SThomas Kühnel } 152988a8d0d2SThomas Kühnel } 153008811ba5SKonstantin Komarov 153108811ba5SKonstantin Komarov unsigned int ntfs_bitmap_weight_le(const void *bitmap, int bits) 153208811ba5SKonstantin Komarov { 153308811ba5SKonstantin Komarov const ulong *bmp = bitmap; 153408811ba5SKonstantin Komarov unsigned int k, lim = bits / BITS_PER_LONG; 153508811ba5SKonstantin Komarov unsigned int w = 0; 153608811ba5SKonstantin Komarov 153708811ba5SKonstantin Komarov for (k = 0; k < lim; k++) 153808811ba5SKonstantin Komarov w += hweight_long(bmp[k]); 153908811ba5SKonstantin Komarov 154008811ba5SKonstantin Komarov if (bits % BITS_PER_LONG) { 154108811ba5SKonstantin Komarov w += hweight_long(ul_to_cpu(((bitmap_ulong *)bitmap)[k]) & 154208811ba5SKonstantin Komarov BITMAP_LAST_WORD_MASK(bits)); 154308811ba5SKonstantin Komarov } 154408811ba5SKonstantin Komarov 154508811ba5SKonstantin Komarov return w; 154608811ba5SKonstantin Komarov } 1547