diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 14:55:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 14:55:55 -0400 |
commit | 824b005c86f91fe02eb2743a4526361f11786f70 (patch) | |
tree | 5e1834ed89f115f0e9ae4bfa1ebd8469140159b8 | |
parent | dd5cdb48edfd34401799056a9acf61078d773f90 (diff) | |
parent | f49a26e7718dd30b49e3541e3e25aecf5e7294e2 (diff) |
Merge branch 'hpfs' (patches from Mikulas)
Merge hpfs upddate from Mikulas Patocka.
* emailed patches from Mikulas Patocka <mikulas@twibright.com>:
hpfs: update ctime and mtime on directory modification
hpfs: support hotfixes
-rw-r--r-- | fs/hpfs/buffer.c | 39 | ||||
-rw-r--r-- | fs/hpfs/file.c | 9 | ||||
-rw-r--r-- | fs/hpfs/hpfs_fn.h | 7 | ||||
-rw-r--r-- | fs/hpfs/map.c | 26 | ||||
-rw-r--r-- | fs/hpfs/namei.c | 25 | ||||
-rw-r--r-- | fs/hpfs/super.c | 15 |
6 files changed, 100 insertions, 21 deletions
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 8057fe4e6574..f626114449e4 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c | |||
@@ -10,6 +10,30 @@ | |||
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include "hpfs_fn.h" | 11 | #include "hpfs_fn.h" |
12 | 12 | ||
13 | secno hpfs_search_hotfix_map(struct super_block *s, secno sec) | ||
14 | { | ||
15 | unsigned i; | ||
16 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
17 | for (i = 0; unlikely(i < sbi->n_hotfixes); i++) { | ||
18 | if (sbi->hotfix_from[i] == sec) { | ||
19 | return sbi->hotfix_to[i]; | ||
20 | } | ||
21 | } | ||
22 | return sec; | ||
23 | } | ||
24 | |||
25 | unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n) | ||
26 | { | ||
27 | unsigned i; | ||
28 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
29 | for (i = 0; unlikely(i < sbi->n_hotfixes); i++) { | ||
30 | if (sbi->hotfix_from[i] >= sec && sbi->hotfix_from[i] < sec + n) { | ||
31 | n = sbi->hotfix_from[i] - sec; | ||
32 | } | ||
33 | } | ||
34 | return n; | ||
35 | } | ||
36 | |||
13 | void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n) | 37 | void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n) |
14 | { | 38 | { |
15 | struct buffer_head *bh; | 39 | struct buffer_head *bh; |
@@ -18,6 +42,9 @@ void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n) | |||
18 | if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size)) | 42 | if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size)) |
19 | return; | 43 | return; |
20 | 44 | ||
45 | if (unlikely(hpfs_search_hotfix_map_for_range(s, secno, n) != n)) | ||
46 | return; | ||
47 | |||
21 | bh = sb_find_get_block(s, secno); | 48 | bh = sb_find_get_block(s, secno); |
22 | if (bh) { | 49 | if (bh) { |
23 | if (buffer_uptodate(bh)) { | 50 | if (buffer_uptodate(bh)) { |
@@ -51,7 +78,7 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
51 | 78 | ||
52 | cond_resched(); | 79 | cond_resched(); |
53 | 80 | ||
54 | *bhp = bh = sb_bread(s, secno); | 81 | *bhp = bh = sb_bread(s, hpfs_search_hotfix_map(s, secno)); |
55 | if (bh != NULL) | 82 | if (bh != NULL) |
56 | return bh->b_data; | 83 | return bh->b_data; |
57 | else { | 84 | else { |
@@ -71,7 +98,7 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
71 | 98 | ||
72 | cond_resched(); | 99 | cond_resched(); |
73 | 100 | ||
74 | if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { | 101 | if ((*bhp = bh = sb_getblk(s, hpfs_search_hotfix_map(s, secno))) != NULL) { |
75 | if (!buffer_uptodate(bh)) wait_on_buffer(bh); | 102 | if (!buffer_uptodate(bh)) wait_on_buffer(bh); |
76 | set_buffer_uptodate(bh); | 103 | set_buffer_uptodate(bh); |
77 | return bh->b_data; | 104 | return bh->b_data; |
@@ -99,10 +126,10 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe | |||
99 | 126 | ||
100 | hpfs_prefetch_sectors(s, secno, 4 + ahead); | 127 | hpfs_prefetch_sectors(s, secno, 4 + ahead); |
101 | 128 | ||
102 | if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0; | 129 | if (!hpfs_map_sector(s, secno + 0, &qbh->bh[0], 0)) goto bail0; |
103 | if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1; | 130 | if (!hpfs_map_sector(s, secno + 1, &qbh->bh[1], 0)) goto bail1; |
104 | if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2; | 131 | if (!hpfs_map_sector(s, secno + 2, &qbh->bh[2], 0)) goto bail2; |
105 | if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3; | 132 | if (!hpfs_map_sector(s, secno + 3, &qbh->bh[3], 0)) goto bail3; |
106 | 133 | ||
107 | if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && | 134 | if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && |
108 | likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && | 135 | likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 7ca28d604bf7..d3bcdd975700 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -83,6 +83,11 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he | |||
83 | if (s) { | 83 | if (s) { |
84 | if (bh_result->b_size >> 9 < n_secs) | 84 | if (bh_result->b_size >> 9 < n_secs) |
85 | n_secs = bh_result->b_size >> 9; | 85 | n_secs = bh_result->b_size >> 9; |
86 | n_secs = hpfs_search_hotfix_map_for_range(inode->i_sb, s, n_secs); | ||
87 | if (unlikely(!n_secs)) { | ||
88 | s = hpfs_search_hotfix_map(inode->i_sb, s); | ||
89 | n_secs = 1; | ||
90 | } | ||
86 | map_bh(bh_result, inode->i_sb, s); | 91 | map_bh(bh_result, inode->i_sb, s); |
87 | bh_result->b_size = n_secs << 9; | 92 | bh_result->b_size = n_secs << 9; |
88 | goto ret_0; | 93 | goto ret_0; |
@@ -101,7 +106,7 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he | |||
101 | inode->i_blocks++; | 106 | inode->i_blocks++; |
102 | hpfs_i(inode)->mmu_private += 512; | 107 | hpfs_i(inode)->mmu_private += 512; |
103 | set_buffer_new(bh_result); | 108 | set_buffer_new(bh_result); |
104 | map_bh(bh_result, inode->i_sb, s); | 109 | map_bh(bh_result, inode->i_sb, hpfs_search_hotfix_map(inode->i_sb, s)); |
105 | ret_0: | 110 | ret_0: |
106 | r = 0; | 111 | r = 0; |
107 | ret_r: | 112 | ret_r: |
@@ -181,7 +186,7 @@ static int hpfs_write_end(struct file *file, struct address_space *mapping, | |||
181 | 186 | ||
182 | static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) | 187 | static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) |
183 | { | 188 | { |
184 | return generic_block_bmap(mapping,block,hpfs_get_block); | 189 | return generic_block_bmap(mapping, block, hpfs_get_block); |
185 | } | 190 | } |
186 | 191 | ||
187 | const struct address_space_operations hpfs_aops = { | 192 | const struct address_space_operations hpfs_aops = { |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index c4867b5116dd..975654a63c13 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -88,6 +88,10 @@ struct hpfs_sb_info { | |||
88 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ | 88 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ |
89 | int sb_timeshift; | 89 | int sb_timeshift; |
90 | struct rcu_head rcu; | 90 | struct rcu_head rcu; |
91 | |||
92 | unsigned n_hotfixes; | ||
93 | secno hotfix_from[256]; | ||
94 | secno hotfix_to[256]; | ||
91 | }; | 95 | }; |
92 | 96 | ||
93 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ | 97 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ |
@@ -217,6 +221,8 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno); | |||
217 | 221 | ||
218 | /* buffer.c */ | 222 | /* buffer.c */ |
219 | 223 | ||
224 | secno hpfs_search_hotfix_map(struct super_block *s, secno sec); | ||
225 | unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n); | ||
220 | void hpfs_prefetch_sectors(struct super_block *, unsigned, int); | 226 | void hpfs_prefetch_sectors(struct super_block *, unsigned, int); |
221 | void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); | 227 | void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); |
222 | void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); | 228 | void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); |
@@ -285,6 +291,7 @@ __le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head | |||
285 | void hpfs_prefetch_bitmap(struct super_block *, unsigned); | 291 | void hpfs_prefetch_bitmap(struct super_block *, unsigned); |
286 | unsigned char *hpfs_load_code_page(struct super_block *, secno); | 292 | unsigned char *hpfs_load_code_page(struct super_block *, secno); |
287 | __le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp); | 293 | __le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp); |
294 | void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock); | ||
288 | struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); | 295 | struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); |
289 | struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **); | 296 | struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **); |
290 | struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); | 297 | struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); |
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index 442770edcdc7..a69bbc1e87f8 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c | |||
@@ -130,6 +130,32 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) | |||
130 | return b; | 130 | return b; |
131 | } | 131 | } |
132 | 132 | ||
133 | void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock) | ||
134 | { | ||
135 | struct quad_buffer_head qbh; | ||
136 | u32 *directory; | ||
137 | u32 n_hotfixes, n_used_hotfixes; | ||
138 | unsigned i; | ||
139 | |||
140 | n_hotfixes = le32_to_cpu(spareblock->n_spares); | ||
141 | n_used_hotfixes = le32_to_cpu(spareblock->n_spares_used); | ||
142 | |||
143 | if (n_hotfixes > 256 || n_used_hotfixes > n_hotfixes) { | ||
144 | hpfs_error(s, "invalid number of hotfixes: %u, used: %u", n_hotfixes, n_used_hotfixes); | ||
145 | return; | ||
146 | } | ||
147 | if (!(directory = hpfs_map_4sectors(s, le32_to_cpu(spareblock->hotfix_map), &qbh, 0))) { | ||
148 | hpfs_error(s, "can't load hotfix map"); | ||
149 | return; | ||
150 | } | ||
151 | for (i = 0; i < n_used_hotfixes; i++) { | ||
152 | hpfs_sb(s)->hotfix_from[i] = le32_to_cpu(directory[i]); | ||
153 | hpfs_sb(s)->hotfix_to[i] = le32_to_cpu(directory[n_hotfixes + i]); | ||
154 | } | ||
155 | hpfs_sb(s)->n_hotfixes = n_used_hotfixes; | ||
156 | hpfs_brelse4(&qbh); | ||
157 | } | ||
158 | |||
133 | /* | 159 | /* |
134 | * Load fnode to memory | 160 | * Load fnode to memory |
135 | */ | 161 | */ |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index a0872f239f04..9e92c9c2d319 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
@@ -8,6 +8,17 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include "hpfs_fn.h" | 9 | #include "hpfs_fn.h" |
10 | 10 | ||
11 | static void hpfs_update_directory_times(struct inode *dir) | ||
12 | { | ||
13 | time_t t = get_seconds(); | ||
14 | if (t == dir->i_mtime.tv_sec && | ||
15 | t == dir->i_ctime.tv_sec) | ||
16 | return; | ||
17 | dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t; | ||
18 | dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0; | ||
19 | hpfs_write_inode_nolock(dir); | ||
20 | } | ||
21 | |||
11 | static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 22 | static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
12 | { | 23 | { |
13 | const unsigned char *name = dentry->d_name.name; | 24 | const unsigned char *name = dentry->d_name.name; |
@@ -99,6 +110,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
99 | result->i_mode = mode | S_IFDIR; | 110 | result->i_mode = mode | S_IFDIR; |
100 | hpfs_write_inode_nolock(result); | 111 | hpfs_write_inode_nolock(result); |
101 | } | 112 | } |
113 | hpfs_update_directory_times(dir); | ||
102 | d_instantiate(dentry, result); | 114 | d_instantiate(dentry, result); |
103 | hpfs_unlock(dir->i_sb); | 115 | hpfs_unlock(dir->i_sb); |
104 | return 0; | 116 | return 0; |
@@ -187,6 +199,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, b | |||
187 | result->i_mode = mode | S_IFREG; | 199 | result->i_mode = mode | S_IFREG; |
188 | hpfs_write_inode_nolock(result); | 200 | hpfs_write_inode_nolock(result); |
189 | } | 201 | } |
202 | hpfs_update_directory_times(dir); | ||
190 | d_instantiate(dentry, result); | 203 | d_instantiate(dentry, result); |
191 | hpfs_unlock(dir->i_sb); | 204 | hpfs_unlock(dir->i_sb); |
192 | return 0; | 205 | return 0; |
@@ -262,6 +275,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, de | |||
262 | insert_inode_hash(result); | 275 | insert_inode_hash(result); |
263 | 276 | ||
264 | hpfs_write_inode_nolock(result); | 277 | hpfs_write_inode_nolock(result); |
278 | hpfs_update_directory_times(dir); | ||
265 | d_instantiate(dentry, result); | 279 | d_instantiate(dentry, result); |
266 | brelse(bh); | 280 | brelse(bh); |
267 | hpfs_unlock(dir->i_sb); | 281 | hpfs_unlock(dir->i_sb); |
@@ -340,6 +354,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
340 | insert_inode_hash(result); | 354 | insert_inode_hash(result); |
341 | 355 | ||
342 | hpfs_write_inode_nolock(result); | 356 | hpfs_write_inode_nolock(result); |
357 | hpfs_update_directory_times(dir); | ||
343 | d_instantiate(dentry, result); | 358 | d_instantiate(dentry, result); |
344 | hpfs_unlock(dir->i_sb); | 359 | hpfs_unlock(dir->i_sb); |
345 | return 0; | 360 | return 0; |
@@ -423,6 +438,8 @@ again: | |||
423 | out1: | 438 | out1: |
424 | hpfs_brelse4(&qbh); | 439 | hpfs_brelse4(&qbh); |
425 | out: | 440 | out: |
441 | if (!err) | ||
442 | hpfs_update_directory_times(dir); | ||
426 | hpfs_unlock(dir->i_sb); | 443 | hpfs_unlock(dir->i_sb); |
427 | return err; | 444 | return err; |
428 | } | 445 | } |
@@ -477,6 +494,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
477 | out1: | 494 | out1: |
478 | hpfs_brelse4(&qbh); | 495 | hpfs_brelse4(&qbh); |
479 | out: | 496 | out: |
497 | if (!err) | ||
498 | hpfs_update_directory_times(dir); | ||
480 | hpfs_unlock(dir->i_sb); | 499 | hpfs_unlock(dir->i_sb); |
481 | return err; | 500 | return err; |
482 | } | 501 | } |
@@ -595,7 +614,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
595 | goto end1; | 614 | goto end1; |
596 | } | 615 | } |
597 | 616 | ||
598 | end: | 617 | end: |
599 | hpfs_i(i)->i_parent_dir = new_dir->i_ino; | 618 | hpfs_i(i)->i_parent_dir = new_dir->i_ino; |
600 | if (S_ISDIR(i->i_mode)) { | 619 | if (S_ISDIR(i->i_mode)) { |
601 | inc_nlink(new_dir); | 620 | inc_nlink(new_dir); |
@@ -610,6 +629,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
610 | brelse(bh); | 629 | brelse(bh); |
611 | } | 630 | } |
612 | end1: | 631 | end1: |
632 | if (!err) { | ||
633 | hpfs_update_directory_times(old_dir); | ||
634 | hpfs_update_directory_times(new_dir); | ||
635 | } | ||
613 | hpfs_unlock(i->i_sb); | 636 | hpfs_unlock(i->i_sb); |
614 | return err; | 637 | return err; |
615 | } | 638 | } |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 68a9bed05628..a561591896bd 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -628,6 +628,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
628 | goto bail4; | 628 | goto bail4; |
629 | } | 629 | } |
630 | 630 | ||
631 | if (spareblock->n_spares_used) | ||
632 | hpfs_load_hotfix_map(s, spareblock); | ||
633 | |||
631 | /* Load bitmap directory */ | 634 | /* Load bitmap directory */ |
632 | if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) | 635 | if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) |
633 | goto bail4; | 636 | goto bail4; |
@@ -647,18 +650,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
647 | mark_buffer_dirty(bh2); | 650 | mark_buffer_dirty(bh2); |
648 | } | 651 | } |
649 | 652 | ||
650 | if (spareblock->hotfixes_used || spareblock->n_spares_used) { | ||
651 | if (errs >= 2) { | ||
652 | pr_err("Hotfixes not supported here, try chkdsk\n"); | ||
653 | mark_dirty(s, 0); | ||
654 | goto bail4; | ||
655 | } | ||
656 | hpfs_error(s, "hotfixes not supported here, try chkdsk"); | ||
657 | if (errs == 0) | ||
658 | pr_err("Proceeding, but your filesystem will be probably corrupted by this driver...\n"); | ||
659 | else | ||
660 | pr_err("This driver may read bad files or crash when operating on disk with hotfixes.\n"); | ||
661 | } | ||
662 | if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) { | 653 | if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) { |
663 | if (errs >= 2) { | 654 | if (errs >= 2) { |
664 | pr_err("Spare dnodes used, try chkdsk\n"); | 655 | pr_err("Spare dnodes used, try chkdsk\n"); |