1
2
3
4
5
6
7
8#ifdef NTFS_RW
9
10#include <linux/pagemap.h>
11
12#include "bitmap.h"
13#include "debug.h"
14#include "aops.h"
15#include "ntfs.h"
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
34 const s64 count, const u8 value, const bool is_rollback)
35{
36 s64 cnt = count;
37 pgoff_t index, end_index;
38 struct address_space *mapping;
39 struct page *page;
40 u8 *kaddr;
41 int pos, len;
42 u8 bit;
43
44 BUG_ON(!vi);
45 ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
46 "value %u.%s", vi->i_ino, (unsigned long long)start_bit,
47 (unsigned long long)cnt, (unsigned int)value,
48 is_rollback ? " (rollback)" : "");
49 BUG_ON(start_bit < 0);
50 BUG_ON(cnt < 0);
51 BUG_ON(value > 1);
52
53
54
55
56 index = start_bit >> (3 + PAGE_SHIFT);
57 end_index = (start_bit + cnt - 1) >> (3 + PAGE_SHIFT);
58
59
60 mapping = vi->i_mapping;
61 page = ntfs_map_page(mapping, index);
62 if (IS_ERR(page)) {
63 if (!is_rollback)
64 ntfs_error(vi->i_sb, "Failed to map first page (error "
65 "%li), aborting.", PTR_ERR(page));
66 return PTR_ERR(page);
67 }
68 kaddr = page_address(page);
69
70
71 pos = (start_bit >> 3) & ~PAGE_MASK;
72
73
74 bit = start_bit & 7;
75
76
77 if (bit) {
78 u8 *byte = kaddr + pos;
79 while ((bit & 7) && cnt) {
80 cnt--;
81 if (value)
82 *byte |= 1 << bit++;
83 else
84 *byte &= ~(1 << bit++);
85 }
86
87 if (!cnt)
88 goto done;
89
90
91 pos++;
92 }
93
94
95
96
97 len = min_t(s64, cnt >> 3, PAGE_SIZE - pos);
98 memset(kaddr + pos, value ? 0xff : 0, len);
99 cnt -= len << 3;
100
101
102 if (cnt < 8)
103 len += pos;
104
105
106 while (index < end_index) {
107 BUG_ON(cnt <= 0);
108
109
110 flush_dcache_page(page);
111 set_page_dirty(page);
112 ntfs_unmap_page(page);
113 page = ntfs_map_page(mapping, ++index);
114 if (IS_ERR(page))
115 goto rollback;
116 kaddr = page_address(page);
117
118
119
120
121 len = min_t(s64, cnt >> 3, PAGE_SIZE);
122 memset(kaddr, value ? 0xff : 0, len);
123 cnt -= len << 3;
124 }
125
126
127
128
129
130 if (cnt) {
131 u8 *byte;
132
133 BUG_ON(cnt > 7);
134
135 bit = cnt;
136 byte = kaddr + len;
137 while (bit--) {
138 if (value)
139 *byte |= 1 << bit;
140 else
141 *byte &= ~(1 << bit);
142 }
143 }
144done:
145
146 flush_dcache_page(page);
147 set_page_dirty(page);
148 ntfs_unmap_page(page);
149 ntfs_debug("Done.");
150 return 0;
151rollback:
152
153
154
155
156
157 if (is_rollback)
158 return PTR_ERR(page);
159 if (count != cnt)
160 pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
161 value ? 0 : 1, true);
162 else
163 pos = 0;
164 if (!pos) {
165
166 ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
167 "%li), aborting.", PTR_ERR(page));
168 } else {
169
170 ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
171 "%li) and rollback failed (error %i). "
172 "Aborting and leaving inconsistent metadata. "
173 "Unmount and run chkdsk.", PTR_ERR(page), pos);
174 NVolSetErrors(NTFS_SB(vi->i_sb));
175 }
176 return PTR_ERR(page);
177}
178
179#endif
180