0001
0002
0003
0004
0005
0006
0007
0008 #ifdef NTFS_RW
0009
0010 #include <linux/pagemap.h>
0011
0012 #include "bitmap.h"
0013 #include "debug.h"
0014 #include "aops.h"
0015 #include "ntfs.h"
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
0034 const s64 count, const u8 value, const bool is_rollback)
0035 {
0036 s64 cnt = count;
0037 pgoff_t index, end_index;
0038 struct address_space *mapping;
0039 struct page *page;
0040 u8 *kaddr;
0041 int pos, len;
0042 u8 bit;
0043
0044 BUG_ON(!vi);
0045 ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
0046 "value %u.%s", vi->i_ino, (unsigned long long)start_bit,
0047 (unsigned long long)cnt, (unsigned int)value,
0048 is_rollback ? " (rollback)" : "");
0049 BUG_ON(start_bit < 0);
0050 BUG_ON(cnt < 0);
0051 BUG_ON(value > 1);
0052
0053
0054
0055
0056 index = start_bit >> (3 + PAGE_SHIFT);
0057 end_index = (start_bit + cnt - 1) >> (3 + PAGE_SHIFT);
0058
0059
0060 mapping = vi->i_mapping;
0061 page = ntfs_map_page(mapping, index);
0062 if (IS_ERR(page)) {
0063 if (!is_rollback)
0064 ntfs_error(vi->i_sb, "Failed to map first page (error "
0065 "%li), aborting.", PTR_ERR(page));
0066 return PTR_ERR(page);
0067 }
0068 kaddr = page_address(page);
0069
0070
0071 pos = (start_bit >> 3) & ~PAGE_MASK;
0072
0073
0074 bit = start_bit & 7;
0075
0076
0077 if (bit) {
0078 u8 *byte = kaddr + pos;
0079 while ((bit & 7) && cnt) {
0080 cnt--;
0081 if (value)
0082 *byte |= 1 << bit++;
0083 else
0084 *byte &= ~(1 << bit++);
0085 }
0086
0087 if (!cnt)
0088 goto done;
0089
0090
0091 pos++;
0092 }
0093
0094
0095
0096
0097 len = min_t(s64, cnt >> 3, PAGE_SIZE - pos);
0098 memset(kaddr + pos, value ? 0xff : 0, len);
0099 cnt -= len << 3;
0100
0101
0102 if (cnt < 8)
0103 len += pos;
0104
0105
0106 while (index < end_index) {
0107 BUG_ON(cnt <= 0);
0108
0109
0110 flush_dcache_page(page);
0111 set_page_dirty(page);
0112 ntfs_unmap_page(page);
0113 page = ntfs_map_page(mapping, ++index);
0114 if (IS_ERR(page))
0115 goto rollback;
0116 kaddr = page_address(page);
0117
0118
0119
0120
0121 len = min_t(s64, cnt >> 3, PAGE_SIZE);
0122 memset(kaddr, value ? 0xff : 0, len);
0123 cnt -= len << 3;
0124 }
0125
0126
0127
0128
0129
0130 if (cnt) {
0131 u8 *byte;
0132
0133 BUG_ON(cnt > 7);
0134
0135 bit = cnt;
0136 byte = kaddr + len;
0137 while (bit--) {
0138 if (value)
0139 *byte |= 1 << bit;
0140 else
0141 *byte &= ~(1 << bit);
0142 }
0143 }
0144 done:
0145
0146 flush_dcache_page(page);
0147 set_page_dirty(page);
0148 ntfs_unmap_page(page);
0149 ntfs_debug("Done.");
0150 return 0;
0151 rollback:
0152
0153
0154
0155
0156
0157 if (is_rollback)
0158 return PTR_ERR(page);
0159 if (count != cnt)
0160 pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
0161 value ? 0 : 1, true);
0162 else
0163 pos = 0;
0164 if (!pos) {
0165
0166 ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
0167 "%li), aborting.", PTR_ERR(page));
0168 } else {
0169
0170 ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
0171 "%li) and rollback failed (error %i). "
0172 "Aborting and leaving inconsistent metadata. "
0173 "Unmount and run chkdsk.", PTR_ERR(page), pos);
0174 NVolSetErrors(NTFS_SB(vi->i_sb));
0175 }
0176 return PTR_ERR(page);
0177 }
0178
0179 #endif