diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 09:04:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 09:04:38 -0400 |
commit | 54e514b91b95d6441c12a7955addfb9f9d2afc65 (patch) | |
tree | 8b73d901bd2a6ec5a31f34a8954e5ea92216dd6c /fs/nilfs2 | |
parent | 4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (diff) | |
parent | 6c8c90319c0bb1c9e0b68e721359b89ae4f28465 (diff) |
Merge branch 'akpm' (patches from Andrew)
Merge third patchbomb from Andrew Morton:
- various misc things
- a couple of lib/ optimisations
- provide DIV_ROUND_CLOSEST_ULL()
- checkpatch updates
- rtc tree
- befs, nilfs2, hfs, hfsplus, fatfs, adfs, affs, bfs
- ptrace fixes
- fork() fixes
- seccomp cleanups
- more mmap_sem hold time reductions from Davidlohr
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (138 commits)
proc: show locks in /proc/pid/fdinfo/X
docs: add missing and new /proc/PID/status file entries, fix typos
drivers/rtc/rtc-at91rm9200.c: make IO endian agnostic
Documentation/spi/spidev_test.c: fix warning
drivers/rtc/rtc-s5m.c: allow usage on device type different than main MFD type
.gitignore: ignore *.tar
MAINTAINERS: add Mediatek SoC mailing list
tomoyo: reduce mmap_sem hold for mm->exe_file
powerpc/oprofile: reduce mmap_sem hold for exe_file
oprofile: reduce mmap_sem hold for mm->exe_file
mips: ip32: add platform data hooks to use DS1685 driver
lib/Kconfig: fix up HAVE_ARCH_BITREVERSE help text
x86: switch to using asm-generic for seccomp.h
sparc: switch to using asm-generic for seccomp.h
powerpc: switch to using asm-generic for seccomp.h
parisc: switch to using asm-generic for seccomp.h
mips: switch to using asm-generic for seccomp.h
microblaze: use asm-generic for seccomp.h
arm: use asm-generic for seccomp.h
seccomp: allow COMPAT sigreturn overrides
...
Diffstat (limited to 'fs/nilfs2')
-rw-r--r-- | fs/nilfs2/alloc.c | 5 | ||||
-rw-r--r-- | fs/nilfs2/bmap.c | 48 | ||||
-rw-r--r-- | fs/nilfs2/bmap.h | 13 | ||||
-rw-r--r-- | fs/nilfs2/btree.c | 63 | ||||
-rw-r--r-- | fs/nilfs2/cpfile.c | 58 | ||||
-rw-r--r-- | fs/nilfs2/direct.c | 17 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 25 | ||||
-rw-r--r-- | fs/nilfs2/mdt.c | 54 | ||||
-rw-r--r-- | fs/nilfs2/mdt.h | 10 | ||||
-rw-r--r-- | fs/nilfs2/page.c | 24 | ||||
-rw-r--r-- | fs/nilfs2/segment.c | 17 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 2 |
12 files changed, 274 insertions, 62 deletions
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index 741fd02e0444..8df0f3b7839b 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c | |||
@@ -405,13 +405,14 @@ nilfs_palloc_rest_groups_in_desc_block(const struct inode *inode, | |||
405 | static int nilfs_palloc_count_desc_blocks(struct inode *inode, | 405 | static int nilfs_palloc_count_desc_blocks(struct inode *inode, |
406 | unsigned long *desc_blocks) | 406 | unsigned long *desc_blocks) |
407 | { | 407 | { |
408 | unsigned long blknum; | 408 | __u64 blknum; |
409 | int ret; | 409 | int ret; |
410 | 410 | ||
411 | ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum); | 411 | ret = nilfs_bmap_last_key(NILFS_I(inode)->i_bmap, &blknum); |
412 | if (likely(!ret)) | 412 | if (likely(!ret)) |
413 | *desc_blocks = DIV_ROUND_UP( | 413 | *desc_blocks = DIV_ROUND_UP( |
414 | blknum, NILFS_MDT(inode)->mi_blocks_per_desc_block); | 414 | (unsigned long)blknum, |
415 | NILFS_MDT(inode)->mi_blocks_per_desc_block); | ||
415 | return ret; | 416 | return ret; |
416 | } | 417 | } |
417 | 418 | ||
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index aadbd0b5e3e8..27f75bcbeb30 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -152,9 +152,7 @@ static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
152 | * | 152 | * |
153 | * %-EEXIST - A record associated with @key already exist. | 153 | * %-EEXIST - A record associated with @key already exist. |
154 | */ | 154 | */ |
155 | int nilfs_bmap_insert(struct nilfs_bmap *bmap, | 155 | int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec) |
156 | unsigned long key, | ||
157 | unsigned long rec) | ||
158 | { | 156 | { |
159 | int ret; | 157 | int ret; |
160 | 158 | ||
@@ -191,19 +189,47 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) | |||
191 | return bmap->b_ops->bop_delete(bmap, key); | 189 | return bmap->b_ops->bop_delete(bmap, key); |
192 | } | 190 | } |
193 | 191 | ||
194 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key) | 192 | /** |
193 | * nilfs_bmap_seek_key - seek a valid entry and return its key | ||
194 | * @bmap: bmap struct | ||
195 | * @start: start key number | ||
196 | * @keyp: place to store valid key | ||
197 | * | ||
198 | * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap | ||
199 | * starting from @start, and stores it to @keyp if found. | ||
200 | * | ||
201 | * Return Value: On success, 0 is returned. On error, one of the following | ||
202 | * negative error codes is returned. | ||
203 | * | ||
204 | * %-EIO - I/O error. | ||
205 | * | ||
206 | * %-ENOMEM - Insufficient amount of memory available. | ||
207 | * | ||
208 | * %-ENOENT - No valid entry was found | ||
209 | */ | ||
210 | int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp) | ||
195 | { | 211 | { |
196 | __u64 lastkey; | ||
197 | int ret; | 212 | int ret; |
198 | 213 | ||
199 | down_read(&bmap->b_sem); | 214 | down_read(&bmap->b_sem); |
200 | ret = bmap->b_ops->bop_last_key(bmap, &lastkey); | 215 | ret = bmap->b_ops->bop_seek_key(bmap, start, keyp); |
216 | up_read(&bmap->b_sem); | ||
217 | |||
218 | if (ret < 0) | ||
219 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | down_read(&bmap->b_sem); | ||
228 | ret = bmap->b_ops->bop_last_key(bmap, keyp); | ||
201 | up_read(&bmap->b_sem); | 229 | up_read(&bmap->b_sem); |
202 | 230 | ||
203 | if (ret < 0) | 231 | if (ret < 0) |
204 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); | 232 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); |
205 | else | ||
206 | *key = lastkey; | ||
207 | return ret; | 233 | return ret; |
208 | } | 234 | } |
209 | 235 | ||
@@ -224,7 +250,7 @@ int nilfs_bmap_last_key(struct nilfs_bmap *bmap, unsigned long *key) | |||
224 | * | 250 | * |
225 | * %-ENOENT - A record associated with @key does not exist. | 251 | * %-ENOENT - A record associated with @key does not exist. |
226 | */ | 252 | */ |
227 | int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key) | 253 | int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key) |
228 | { | 254 | { |
229 | int ret; | 255 | int ret; |
230 | 256 | ||
@@ -235,7 +261,7 @@ int nilfs_bmap_delete(struct nilfs_bmap *bmap, unsigned long key) | |||
235 | return nilfs_bmap_convert_error(bmap, __func__, ret); | 261 | return nilfs_bmap_convert_error(bmap, __func__, ret); |
236 | } | 262 | } |
237 | 263 | ||
238 | static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) | 264 | static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key) |
239 | { | 265 | { |
240 | __u64 lastkey; | 266 | __u64 lastkey; |
241 | int ret; | 267 | int ret; |
@@ -276,7 +302,7 @@ static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, unsigned long key) | |||
276 | * | 302 | * |
277 | * %-ENOMEM - Insufficient amount of memory available. | 303 | * %-ENOMEM - Insufficient amount of memory available. |
278 | */ | 304 | */ |
279 | int nilfs_bmap_truncate(struct nilfs_bmap *bmap, unsigned long key) | 305 | int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key) |
280 | { | 306 | { |
281 | int ret; | 307 | int ret; |
282 | 308 | ||
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index b89e68076adc..bfa817ce40b3 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
@@ -76,8 +76,10 @@ struct nilfs_bmap_operations { | |||
76 | union nilfs_binfo *); | 76 | union nilfs_binfo *); |
77 | int (*bop_mark)(struct nilfs_bmap *, __u64, int); | 77 | int (*bop_mark)(struct nilfs_bmap *, __u64, int); |
78 | 78 | ||
79 | /* The following functions are internal use only. */ | 79 | int (*bop_seek_key)(const struct nilfs_bmap *, __u64, __u64 *); |
80 | int (*bop_last_key)(const struct nilfs_bmap *, __u64 *); | 80 | int (*bop_last_key)(const struct nilfs_bmap *, __u64 *); |
81 | |||
82 | /* The following functions are internal use only. */ | ||
81 | int (*bop_check_insert)(const struct nilfs_bmap *, __u64); | 83 | int (*bop_check_insert)(const struct nilfs_bmap *, __u64); |
82 | int (*bop_check_delete)(struct nilfs_bmap *, __u64); | 84 | int (*bop_check_delete)(struct nilfs_bmap *, __u64); |
83 | int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int); | 85 | int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int); |
@@ -153,10 +155,11 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); | |||
153 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); | 155 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); |
154 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); | 156 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); |
155 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); | 157 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); |
156 | int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); | 158 | int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); |
157 | int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); | 159 | int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); |
158 | int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *); | 160 | int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp); |
159 | int nilfs_bmap_truncate(struct nilfs_bmap *, unsigned long); | 161 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); |
162 | int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); | ||
160 | void nilfs_bmap_clear(struct nilfs_bmap *); | 163 | void nilfs_bmap_clear(struct nilfs_bmap *); |
161 | int nilfs_bmap_propagate(struct nilfs_bmap *, struct buffer_head *); | 164 | int nilfs_bmap_propagate(struct nilfs_bmap *, struct buffer_head *); |
162 | void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *, struct list_head *); | 165 | void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *, struct list_head *); |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index ecdbae19a766..059f37137f9a 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -633,6 +633,44 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree, | |||
633 | return 0; | 633 | return 0; |
634 | } | 634 | } |
635 | 635 | ||
636 | /** | ||
637 | * nilfs_btree_get_next_key - get next valid key from btree path array | ||
638 | * @btree: bmap struct of btree | ||
639 | * @path: array of nilfs_btree_path struct | ||
640 | * @minlevel: start level | ||
641 | * @nextkey: place to store the next valid key | ||
642 | * | ||
643 | * Return Value: If a next key was found, 0 is returned. Otherwise, | ||
644 | * -ENOENT is returned. | ||
645 | */ | ||
646 | static int nilfs_btree_get_next_key(const struct nilfs_bmap *btree, | ||
647 | const struct nilfs_btree_path *path, | ||
648 | int minlevel, __u64 *nextkey) | ||
649 | { | ||
650 | struct nilfs_btree_node *node; | ||
651 | int maxlevel = nilfs_btree_height(btree) - 1; | ||
652 | int index, next_adj, level; | ||
653 | |||
654 | /* Next index is already set to bp_index for leaf nodes. */ | ||
655 | next_adj = 0; | ||
656 | for (level = minlevel; level <= maxlevel; level++) { | ||
657 | if (level == maxlevel) | ||
658 | node = nilfs_btree_get_root(btree); | ||
659 | else | ||
660 | node = nilfs_btree_get_nonroot_node(path, level); | ||
661 | |||
662 | index = path[level].bp_index + next_adj; | ||
663 | if (index < nilfs_btree_node_get_nchildren(node)) { | ||
664 | /* Next key is in this node */ | ||
665 | *nextkey = nilfs_btree_node_get_key(node, index); | ||
666 | return 0; | ||
667 | } | ||
668 | /* For non-leaf nodes, next index is stored at bp_index + 1. */ | ||
669 | next_adj = 1; | ||
670 | } | ||
671 | return -ENOENT; | ||
672 | } | ||
673 | |||
636 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, | 674 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, |
637 | __u64 key, int level, __u64 *ptrp) | 675 | __u64 key, int level, __u64 *ptrp) |
638 | { | 676 | { |
@@ -1563,6 +1601,27 @@ out: | |||
1563 | return ret; | 1601 | return ret; |
1564 | } | 1602 | } |
1565 | 1603 | ||
1604 | static int nilfs_btree_seek_key(const struct nilfs_bmap *btree, __u64 start, | ||
1605 | __u64 *keyp) | ||
1606 | { | ||
1607 | struct nilfs_btree_path *path; | ||
1608 | const int minlevel = NILFS_BTREE_LEVEL_NODE_MIN; | ||
1609 | int ret; | ||
1610 | |||
1611 | path = nilfs_btree_alloc_path(); | ||
1612 | if (!path) | ||
1613 | return -ENOMEM; | ||
1614 | |||
1615 | ret = nilfs_btree_do_lookup(btree, path, start, NULL, minlevel, 0); | ||
1616 | if (!ret) | ||
1617 | *keyp = start; | ||
1618 | else if (ret == -ENOENT) | ||
1619 | ret = nilfs_btree_get_next_key(btree, path, minlevel, keyp); | ||
1620 | |||
1621 | nilfs_btree_free_path(path); | ||
1622 | return ret; | ||
1623 | } | ||
1624 | |||
1566 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) | 1625 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) |
1567 | { | 1626 | { |
1568 | struct nilfs_btree_path *path; | 1627 | struct nilfs_btree_path *path; |
@@ -2298,7 +2357,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = { | |||
2298 | .bop_assign = nilfs_btree_assign, | 2357 | .bop_assign = nilfs_btree_assign, |
2299 | .bop_mark = nilfs_btree_mark, | 2358 | .bop_mark = nilfs_btree_mark, |
2300 | 2359 | ||
2360 | .bop_seek_key = nilfs_btree_seek_key, | ||
2301 | .bop_last_key = nilfs_btree_last_key, | 2361 | .bop_last_key = nilfs_btree_last_key, |
2362 | |||
2302 | .bop_check_insert = NULL, | 2363 | .bop_check_insert = NULL, |
2303 | .bop_check_delete = nilfs_btree_check_delete, | 2364 | .bop_check_delete = nilfs_btree_check_delete, |
2304 | .bop_gather_data = nilfs_btree_gather_data, | 2365 | .bop_gather_data = nilfs_btree_gather_data, |
@@ -2318,7 +2379,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
2318 | .bop_assign = nilfs_btree_assign_gc, | 2379 | .bop_assign = nilfs_btree_assign_gc, |
2319 | .bop_mark = NULL, | 2380 | .bop_mark = NULL, |
2320 | 2381 | ||
2382 | .bop_seek_key = NULL, | ||
2321 | .bop_last_key = NULL, | 2383 | .bop_last_key = NULL, |
2384 | |||
2322 | .bop_check_insert = NULL, | 2385 | .bop_check_insert = NULL, |
2323 | .bop_check_delete = NULL, | 2386 | .bop_check_delete = NULL, |
2324 | .bop_gather_data = NULL, | 2387 | .bop_gather_data = NULL, |
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 0d58075f34e2..b6596cab9e99 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
@@ -53,6 +53,13 @@ nilfs_cpfile_get_offset(const struct inode *cpfile, __u64 cno) | |||
53 | return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile)); | 53 | return do_div(tcno, nilfs_cpfile_checkpoints_per_block(cpfile)); |
54 | } | 54 | } |
55 | 55 | ||
56 | static __u64 nilfs_cpfile_first_checkpoint_in_block(const struct inode *cpfile, | ||
57 | unsigned long blkoff) | ||
58 | { | ||
59 | return (__u64)nilfs_cpfile_checkpoints_per_block(cpfile) * blkoff | ||
60 | + 1 - NILFS_MDT(cpfile)->mi_first_entry_offset; | ||
61 | } | ||
62 | |||
56 | static unsigned long | 63 | static unsigned long |
57 | nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile, | 64 | nilfs_cpfile_checkpoints_in_block(const struct inode *cpfile, |
58 | __u64 curr, | 65 | __u64 curr, |
@@ -146,6 +153,44 @@ static inline int nilfs_cpfile_get_checkpoint_block(struct inode *cpfile, | |||
146 | create, nilfs_cpfile_block_init, bhp); | 153 | create, nilfs_cpfile_block_init, bhp); |
147 | } | 154 | } |
148 | 155 | ||
156 | /** | ||
157 | * nilfs_cpfile_find_checkpoint_block - find and get a buffer on cpfile | ||
158 | * @cpfile: inode of cpfile | ||
159 | * @start_cno: start checkpoint number (inclusive) | ||
160 | * @end_cno: end checkpoint number (inclusive) | ||
161 | * @cnop: place to store the next checkpoint number | ||
162 | * @bhp: place to store a pointer to buffer_head struct | ||
163 | * | ||
164 | * Return Value: On success, it returns 0. On error, the following negative | ||
165 | * error code is returned. | ||
166 | * | ||
167 | * %-ENOMEM - Insufficient memory available. | ||
168 | * | ||
169 | * %-EIO - I/O error | ||
170 | * | ||
171 | * %-ENOENT - no block exists in the range. | ||
172 | */ | ||
173 | static int nilfs_cpfile_find_checkpoint_block(struct inode *cpfile, | ||
174 | __u64 start_cno, __u64 end_cno, | ||
175 | __u64 *cnop, | ||
176 | struct buffer_head **bhp) | ||
177 | { | ||
178 | unsigned long start, end, blkoff; | ||
179 | int ret; | ||
180 | |||
181 | if (unlikely(start_cno > end_cno)) | ||
182 | return -ENOENT; | ||
183 | |||
184 | start = nilfs_cpfile_get_blkoff(cpfile, start_cno); | ||
185 | end = nilfs_cpfile_get_blkoff(cpfile, end_cno); | ||
186 | |||
187 | ret = nilfs_mdt_find_block(cpfile, start, end, &blkoff, bhp); | ||
188 | if (!ret) | ||
189 | *cnop = (blkoff == start) ? start_cno : | ||
190 | nilfs_cpfile_first_checkpoint_in_block(cpfile, blkoff); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
149 | static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile, | 194 | static inline int nilfs_cpfile_delete_checkpoint_block(struct inode *cpfile, |
150 | __u64 cno) | 195 | __u64 cno) |
151 | { | 196 | { |
@@ -403,14 +448,15 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, | |||
403 | return -ENOENT; /* checkpoint number 0 is invalid */ | 448 | return -ENOENT; /* checkpoint number 0 is invalid */ |
404 | down_read(&NILFS_MDT(cpfile)->mi_sem); | 449 | down_read(&NILFS_MDT(cpfile)->mi_sem); |
405 | 450 | ||
406 | for (n = 0; cno < cur_cno && n < nci; cno += ncps) { | 451 | for (n = 0; n < nci; cno += ncps) { |
407 | ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); | 452 | ret = nilfs_cpfile_find_checkpoint_block( |
408 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh); | 453 | cpfile, cno, cur_cno - 1, &cno, &bh); |
409 | if (ret < 0) { | 454 | if (ret < 0) { |
410 | if (ret != -ENOENT) | 455 | if (likely(ret == -ENOENT)) |
411 | goto out; | 456 | break; |
412 | continue; /* skip hole */ | 457 | goto out; |
413 | } | 458 | } |
459 | ncps = nilfs_cpfile_checkpoints_in_block(cpfile, cno, cur_cno); | ||
414 | 460 | ||
415 | kaddr = kmap_atomic(bh->b_page); | 461 | kaddr = kmap_atomic(bh->b_page); |
416 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); | 462 | cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 82f4865e86dd..ebf89fd8ac1a 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
@@ -173,6 +173,21 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) | |||
173 | return ret; | 173 | return ret; |
174 | } | 174 | } |
175 | 175 | ||
176 | static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start, | ||
177 | __u64 *keyp) | ||
178 | { | ||
179 | __u64 key; | ||
180 | |||
181 | for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) { | ||
182 | if (nilfs_direct_get_ptr(direct, key) != | ||
183 | NILFS_BMAP_INVALID_PTR) { | ||
184 | *keyp = key; | ||
185 | return 0; | ||
186 | } | ||
187 | } | ||
188 | return -ENOENT; | ||
189 | } | ||
190 | |||
176 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) | 191 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) |
177 | { | 192 | { |
178 | __u64 key, lastkey; | 193 | __u64 key, lastkey; |
@@ -355,7 +370,9 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = { | |||
355 | .bop_assign = nilfs_direct_assign, | 370 | .bop_assign = nilfs_direct_assign, |
356 | .bop_mark = NULL, | 371 | .bop_mark = NULL, |
357 | 372 | ||
373 | .bop_seek_key = nilfs_direct_seek_key, | ||
358 | .bop_last_key = nilfs_direct_last_key, | 374 | .bop_last_key = nilfs_direct_last_key, |
375 | |||
359 | .bop_check_insert = nilfs_direct_check_insert, | 376 | .bop_check_insert = nilfs_direct_check_insert, |
360 | .bop_check_delete = NULL, | 377 | .bop_check_delete = NULL, |
361 | .bop_gather_data = nilfs_direct_gather_data, | 378 | .bop_gather_data = nilfs_direct_gather_data, |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 36f057fa8aa3..be936df4ba73 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -106,7 +106,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, | |||
106 | err = nilfs_transaction_begin(inode->i_sb, &ti, 1); | 106 | err = nilfs_transaction_begin(inode->i_sb, &ti, 1); |
107 | if (unlikely(err)) | 107 | if (unlikely(err)) |
108 | goto out; | 108 | goto out; |
109 | err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff, | 109 | err = nilfs_bmap_insert(ii->i_bmap, blkoff, |
110 | (unsigned long)bh_result); | 110 | (unsigned long)bh_result); |
111 | if (unlikely(err != 0)) { | 111 | if (unlikely(err != 0)) { |
112 | if (err == -EEXIST) { | 112 | if (err == -EEXIST) { |
@@ -441,21 +441,20 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) | |||
441 | void nilfs_set_inode_flags(struct inode *inode) | 441 | void nilfs_set_inode_flags(struct inode *inode) |
442 | { | 442 | { |
443 | unsigned int flags = NILFS_I(inode)->i_flags; | 443 | unsigned int flags = NILFS_I(inode)->i_flags; |
444 | unsigned int new_fl = 0; | ||
444 | 445 | ||
445 | inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | | ||
446 | S_DIRSYNC); | ||
447 | if (flags & FS_SYNC_FL) | 446 | if (flags & FS_SYNC_FL) |
448 | inode->i_flags |= S_SYNC; | 447 | new_fl |= S_SYNC; |
449 | if (flags & FS_APPEND_FL) | 448 | if (flags & FS_APPEND_FL) |
450 | inode->i_flags |= S_APPEND; | 449 | new_fl |= S_APPEND; |
451 | if (flags & FS_IMMUTABLE_FL) | 450 | if (flags & FS_IMMUTABLE_FL) |
452 | inode->i_flags |= S_IMMUTABLE; | 451 | new_fl |= S_IMMUTABLE; |
453 | if (flags & FS_NOATIME_FL) | 452 | if (flags & FS_NOATIME_FL) |
454 | inode->i_flags |= S_NOATIME; | 453 | new_fl |= S_NOATIME; |
455 | if (flags & FS_DIRSYNC_FL) | 454 | if (flags & FS_DIRSYNC_FL) |
456 | inode->i_flags |= S_DIRSYNC; | 455 | new_fl |= S_DIRSYNC; |
457 | mapping_set_gfp_mask(inode->i_mapping, | 456 | inode_set_flags(inode, new_fl, S_SYNC | S_APPEND | S_IMMUTABLE | |
458 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | 457 | S_NOATIME | S_DIRSYNC); |
459 | } | 458 | } |
460 | 459 | ||
461 | int nilfs_read_inode_common(struct inode *inode, | 460 | int nilfs_read_inode_common(struct inode *inode, |
@@ -540,6 +539,8 @@ static int __nilfs_read_inode(struct super_block *sb, | |||
540 | brelse(bh); | 539 | brelse(bh); |
541 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); | 540 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
542 | nilfs_set_inode_flags(inode); | 541 | nilfs_set_inode_flags(inode); |
542 | mapping_set_gfp_mask(inode->i_mapping, | ||
543 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | ||
543 | return 0; | 544 | return 0; |
544 | 545 | ||
545 | failed_unmap: | 546 | failed_unmap: |
@@ -712,7 +713,7 @@ void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags) | |||
712 | static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, | 713 | static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, |
713 | unsigned long from) | 714 | unsigned long from) |
714 | { | 715 | { |
715 | unsigned long b; | 716 | __u64 b; |
716 | int ret; | 717 | int ret; |
717 | 718 | ||
718 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) | 719 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) |
@@ -727,7 +728,7 @@ repeat: | |||
727 | if (b < from) | 728 | if (b < from) |
728 | return; | 729 | return; |
729 | 730 | ||
730 | b -= min_t(unsigned long, NILFS_MAX_TRUNCATE_BLOCKS, b - from); | 731 | b -= min_t(__u64, NILFS_MAX_TRUNCATE_BLOCKS, b - from); |
731 | ret = nilfs_bmap_truncate(ii->i_bmap, b); | 732 | ret = nilfs_bmap_truncate(ii->i_bmap, b); |
732 | nilfs_relax_pressure_in_lock(ii->vfs_inode.i_sb); | 733 | nilfs_relax_pressure_in_lock(ii->vfs_inode.i_sb); |
733 | if (!ret || (ret == -ENOMEM && | 734 | if (!ret || (ret == -ENOMEM && |
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 892cf5ffdb8e..dee34d990281 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
@@ -261,6 +261,60 @@ int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create, | |||
261 | } | 261 | } |
262 | 262 | ||
263 | /** | 263 | /** |
264 | * nilfs_mdt_find_block - find and get a buffer on meta data file. | ||
265 | * @inode: inode of the meta data file | ||
266 | * @start: start block offset (inclusive) | ||
267 | * @end: end block offset (inclusive) | ||
268 | * @blkoff: block offset | ||
269 | * @out_bh: place to store a pointer to buffer_head struct | ||
270 | * | ||
271 | * nilfs_mdt_find_block() looks up an existing block in range of | ||
272 | * [@start, @end] and stores pointer to a buffer head of the block to | ||
273 | * @out_bh, and block offset to @blkoff, respectively. @out_bh and | ||
274 | * @blkoff are substituted only when zero is returned. | ||
275 | * | ||
276 | * Return Value: On success, it returns 0. On error, the following negative | ||
277 | * error code is returned. | ||
278 | * | ||
279 | * %-ENOMEM - Insufficient memory available. | ||
280 | * | ||
281 | * %-EIO - I/O error | ||
282 | * | ||
283 | * %-ENOENT - no block was found in the range | ||
284 | */ | ||
285 | int nilfs_mdt_find_block(struct inode *inode, unsigned long start, | ||
286 | unsigned long end, unsigned long *blkoff, | ||
287 | struct buffer_head **out_bh) | ||
288 | { | ||
289 | __u64 next; | ||
290 | int ret; | ||
291 | |||
292 | if (unlikely(start > end)) | ||
293 | return -ENOENT; | ||
294 | |||
295 | ret = nilfs_mdt_read_block(inode, start, true, out_bh); | ||
296 | if (!ret) { | ||
297 | *blkoff = start; | ||
298 | goto out; | ||
299 | } | ||
300 | if (unlikely(ret != -ENOENT || start == ULONG_MAX)) | ||
301 | goto out; | ||
302 | |||
303 | ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next); | ||
304 | if (!ret) { | ||
305 | if (next <= end) { | ||
306 | ret = nilfs_mdt_read_block(inode, next, true, out_bh); | ||
307 | if (!ret) | ||
308 | *blkoff = next; | ||
309 | } else { | ||
310 | ret = -ENOENT; | ||
311 | } | ||
312 | } | ||
313 | out: | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | /** | ||
264 | * nilfs_mdt_delete_block - make a hole on the meta data file. | 318 | * nilfs_mdt_delete_block - make a hole on the meta data file. |
265 | * @inode: inode of the meta data file | 319 | * @inode: inode of the meta data file |
266 | * @block: block offset | 320 | * @block: block offset |
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index ab172e8549c5..fe529a87a208 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h | |||
@@ -78,6 +78,9 @@ int nilfs_mdt_get_block(struct inode *, unsigned long, int, | |||
78 | void (*init_block)(struct inode *, | 78 | void (*init_block)(struct inode *, |
79 | struct buffer_head *, void *), | 79 | struct buffer_head *, void *), |
80 | struct buffer_head **); | 80 | struct buffer_head **); |
81 | int nilfs_mdt_find_block(struct inode *inode, unsigned long start, | ||
82 | unsigned long end, unsigned long *blkoff, | ||
83 | struct buffer_head **out_bh); | ||
81 | int nilfs_mdt_delete_block(struct inode *, unsigned long); | 84 | int nilfs_mdt_delete_block(struct inode *, unsigned long); |
82 | int nilfs_mdt_forget_block(struct inode *, unsigned long); | 85 | int nilfs_mdt_forget_block(struct inode *, unsigned long); |
83 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); | 86 | int nilfs_mdt_mark_block_dirty(struct inode *, unsigned long); |
@@ -111,7 +114,10 @@ static inline __u64 nilfs_mdt_cno(struct inode *inode) | |||
111 | return ((struct the_nilfs *)inode->i_sb->s_fs_info)->ns_cno; | 114 | return ((struct the_nilfs *)inode->i_sb->s_fs_info)->ns_cno; |
112 | } | 115 | } |
113 | 116 | ||
114 | #define nilfs_mdt_bgl_lock(inode, bg) \ | 117 | static inline spinlock_t * |
115 | (&NILFS_MDT(inode)->mi_bgl->locks[(bg) & (NR_BG_LOCKS-1)].lock) | 118 | nilfs_mdt_bgl_lock(struct inode *inode, unsigned int block_group) |
119 | { | ||
120 | return bgl_lock_ptr(NILFS_MDT(inode)->mi_bgl, block_group); | ||
121 | } | ||
116 | 122 | ||
117 | #endif /* _NILFS_MDT_H */ | 123 | #endif /* _NILFS_MDT_H */ |
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 700ecbcca55d..45d650addd56 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
@@ -89,18 +89,16 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode, | |||
89 | void nilfs_forget_buffer(struct buffer_head *bh) | 89 | void nilfs_forget_buffer(struct buffer_head *bh) |
90 | { | 90 | { |
91 | struct page *page = bh->b_page; | 91 | struct page *page = bh->b_page; |
92 | const unsigned long clear_bits = | ||
93 | (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped | | ||
94 | 1 << BH_Async_Write | 1 << BH_NILFS_Volatile | | ||
95 | 1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected); | ||
92 | 96 | ||
93 | lock_buffer(bh); | 97 | lock_buffer(bh); |
94 | clear_buffer_nilfs_volatile(bh); | 98 | set_mask_bits(&bh->b_state, clear_bits, 0); |
95 | clear_buffer_nilfs_checked(bh); | ||
96 | clear_buffer_nilfs_redirected(bh); | ||
97 | clear_buffer_async_write(bh); | ||
98 | clear_buffer_dirty(bh); | ||
99 | if (nilfs_page_buffers_clean(page)) | 99 | if (nilfs_page_buffers_clean(page)) |
100 | __nilfs_clear_page_dirty(page); | 100 | __nilfs_clear_page_dirty(page); |
101 | 101 | ||
102 | clear_buffer_uptodate(bh); | ||
103 | clear_buffer_mapped(bh); | ||
104 | bh->b_blocknr = -1; | 102 | bh->b_blocknr = -1; |
105 | ClearPageUptodate(page); | 103 | ClearPageUptodate(page); |
106 | ClearPageMappedToDisk(page); | 104 | ClearPageMappedToDisk(page); |
@@ -421,6 +419,10 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) | |||
421 | 419 | ||
422 | if (page_has_buffers(page)) { | 420 | if (page_has_buffers(page)) { |
423 | struct buffer_head *bh, *head; | 421 | struct buffer_head *bh, *head; |
422 | const unsigned long clear_bits = | ||
423 | (1 << BH_Uptodate | 1 << BH_Dirty | 1 << BH_Mapped | | ||
424 | 1 << BH_Async_Write | 1 << BH_NILFS_Volatile | | ||
425 | 1 << BH_NILFS_Checked | 1 << BH_NILFS_Redirected); | ||
424 | 426 | ||
425 | bh = head = page_buffers(page); | 427 | bh = head = page_buffers(page); |
426 | do { | 428 | do { |
@@ -430,13 +432,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) | |||
430 | "discard block %llu, size %zu", | 432 | "discard block %llu, size %zu", |
431 | (u64)bh->b_blocknr, bh->b_size); | 433 | (u64)bh->b_blocknr, bh->b_size); |
432 | } | 434 | } |
433 | clear_buffer_async_write(bh); | 435 | set_mask_bits(&bh->b_state, clear_bits, 0); |
434 | clear_buffer_dirty(bh); | ||
435 | clear_buffer_nilfs_volatile(bh); | ||
436 | clear_buffer_nilfs_checked(bh); | ||
437 | clear_buffer_nilfs_redirected(bh); | ||
438 | clear_buffer_uptodate(bh); | ||
439 | clear_buffer_mapped(bh); | ||
440 | unlock_buffer(bh); | 436 | unlock_buffer(bh); |
441 | } while (bh = bh->b_this_page, bh != head); | 437 | } while (bh = bh->b_this_page, bh != head); |
442 | } | 438 | } |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 0c3f303baf32..c6abbad9b8e3 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/pagemap.h> | 24 | #include <linux/pagemap.h> |
25 | #include <linux/buffer_head.h> | 25 | #include <linux/buffer_head.h> |
26 | #include <linux/writeback.h> | 26 | #include <linux/writeback.h> |
27 | #include <linux/bitops.h> | ||
27 | #include <linux/bio.h> | 28 | #include <linux/bio.h> |
28 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
29 | #include <linux/blkdev.h> | 30 | #include <linux/blkdev.h> |
@@ -1588,7 +1589,6 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci) | |||
1588 | 1589 | ||
1589 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1590 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
1590 | b_assoc_buffers) { | 1591 | b_assoc_buffers) { |
1591 | set_buffer_async_write(bh); | ||
1592 | if (bh->b_page != bd_page) { | 1592 | if (bh->b_page != bd_page) { |
1593 | if (bd_page) { | 1593 | if (bd_page) { |
1594 | lock_page(bd_page); | 1594 | lock_page(bd_page); |
@@ -1688,7 +1688,6 @@ static void nilfs_abort_logs(struct list_head *logs, int err) | |||
1688 | list_for_each_entry(segbuf, logs, sb_list) { | 1688 | list_for_each_entry(segbuf, logs, sb_list) { |
1689 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1689 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
1690 | b_assoc_buffers) { | 1690 | b_assoc_buffers) { |
1691 | clear_buffer_async_write(bh); | ||
1692 | if (bh->b_page != bd_page) { | 1691 | if (bh->b_page != bd_page) { |
1693 | if (bd_page) | 1692 | if (bd_page) |
1694 | end_page_writeback(bd_page); | 1693 | end_page_writeback(bd_page); |
@@ -1768,7 +1767,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1768 | b_assoc_buffers) { | 1767 | b_assoc_buffers) { |
1769 | set_buffer_uptodate(bh); | 1768 | set_buffer_uptodate(bh); |
1770 | clear_buffer_dirty(bh); | 1769 | clear_buffer_dirty(bh); |
1771 | clear_buffer_async_write(bh); | ||
1772 | if (bh->b_page != bd_page) { | 1770 | if (bh->b_page != bd_page) { |
1773 | if (bd_page) | 1771 | if (bd_page) |
1774 | end_page_writeback(bd_page); | 1772 | end_page_writeback(bd_page); |
@@ -1788,12 +1786,13 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1788 | */ | 1786 | */ |
1789 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1787 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
1790 | b_assoc_buffers) { | 1788 | b_assoc_buffers) { |
1791 | set_buffer_uptodate(bh); | 1789 | const unsigned long set_bits = (1 << BH_Uptodate); |
1792 | clear_buffer_dirty(bh); | 1790 | const unsigned long clear_bits = |
1793 | clear_buffer_async_write(bh); | 1791 | (1 << BH_Dirty | 1 << BH_Async_Write | |
1794 | clear_buffer_delay(bh); | 1792 | 1 << BH_Delay | 1 << BH_NILFS_Volatile | |
1795 | clear_buffer_nilfs_volatile(bh); | 1793 | 1 << BH_NILFS_Redirected); |
1796 | clear_buffer_nilfs_redirected(bh); | 1794 | |
1795 | set_mask_bits(&bh->b_state, clear_bits, set_bits); | ||
1797 | if (bh == segbuf->sb_super_root) { | 1796 | if (bh == segbuf->sb_super_root) { |
1798 | if (bh->b_page != bd_page) { | 1797 | if (bh->b_page != bd_page) { |
1799 | end_page_writeback(bd_page); | 1798 | end_page_writeback(bd_page); |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 5bc2a1cf73c3..c1725f20a9d1 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -1020,7 +1020,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) | |||
1020 | struct dentry *dentry; | 1020 | struct dentry *dentry; |
1021 | int ret; | 1021 | int ret; |
1022 | 1022 | ||
1023 | if (cno < 0 || cno > nilfs->ns_cno) | 1023 | if (cno > nilfs->ns_cno) |
1024 | return false; | 1024 | return false; |
1025 | 1025 | ||
1026 | if (cno >= nilfs_last_cno(nilfs)) | 1026 | if (cno >= nilfs_last_cno(nilfs)) |