diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-08-24 06:25:44 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-08-24 06:25:54 -0400 |
| commit | 5f9ece02401116b29eb04396b99ea092acb75dd8 (patch) | |
| tree | e10386e2dc63c275646b4eb0bed857da7bf86c6a /fs | |
| parent | 9f51e24ee8b5a1595b6a5ac0c2be278a16488e75 (diff) | |
| parent | 422bef879e84104fee6dc68ded0e371dbeb5f88e (diff) | |
Merge commit 'v2.6.31-rc7' into x86/cleanups
Merge reason: we were on -rc1 before - go up to -rc7
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs')
206 files changed, 3821 insertions, 2631 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 6fcb1e7095cf..92828281a30b 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c | |||
| @@ -57,7 +57,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page) | |||
| 57 | buffer = kmap(page); | 57 | buffer = kmap(page); |
| 58 | offset = page_offset(page); | 58 | offset = page_offset(page); |
| 59 | 59 | ||
| 60 | retval = v9fs_file_readn(filp, buffer, NULL, offset, PAGE_CACHE_SIZE); | 60 | retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset); |
| 61 | if (retval < 0) | 61 | if (retval < 0) |
| 62 | goto done; | 62 | goto done; |
| 63 | 63 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index a97263be6a91..0e7da7bb5d93 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -186,32 +186,7 @@ source "fs/romfs/Kconfig" | |||
| 186 | source "fs/sysv/Kconfig" | 186 | source "fs/sysv/Kconfig" |
| 187 | source "fs/ufs/Kconfig" | 187 | source "fs/ufs/Kconfig" |
| 188 | source "fs/exofs/Kconfig" | 188 | source "fs/exofs/Kconfig" |
| 189 | 189 | source "fs/nilfs2/Kconfig" | |
| 190 | config NILFS2_FS | ||
| 191 | tristate "NILFS2 file system support (EXPERIMENTAL)" | ||
| 192 | depends on BLOCK && EXPERIMENTAL | ||
| 193 | select CRC32 | ||
| 194 | help | ||
| 195 | NILFS2 is a log-structured file system (LFS) supporting continuous | ||
| 196 | snapshotting. In addition to versioning capability of the entire | ||
| 197 | file system, users can even restore files mistakenly overwritten or | ||
| 198 | destroyed just a few seconds ago. Since this file system can keep | ||
| 199 | consistency like conventional LFS, it achieves quick recovery after | ||
| 200 | system crashes. | ||
| 201 | |||
| 202 | NILFS2 creates a number of checkpoints every few seconds or per | ||
| 203 | synchronous write basis (unless there is no change). Users can | ||
| 204 | select significant versions among continuously created checkpoints, | ||
| 205 | and can change them into snapshots which will be preserved for long | ||
| 206 | periods until they are changed back to checkpoints. Each | ||
| 207 | snapshot is mountable as a read-only file system concurrently with | ||
| 208 | its writable mount, and this feature is convenient for online backup. | ||
| 209 | |||
| 210 | Some features including atime, extended attributes, and POSIX ACLs, | ||
| 211 | are not supported yet. | ||
| 212 | |||
| 213 | To compile this file system support as a module, choose M here: the | ||
| 214 | module will be called nilfs2. If unsure, say N. | ||
| 215 | 190 | ||
| 216 | endif # MISC_FILESYSTEMS | 191 | endif # MISC_FILESYSTEMS |
| 217 | 192 | ||
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index aad92f0a1048..6910a98bd73c 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/parser.h> | 13 | #include <linux/parser.h> |
| 14 | #include <linux/mount.h> | 14 | #include <linux/mount.h> |
| 15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 16 | #include <linux/statfs.h> | 17 | #include <linux/statfs.h> |
| 17 | #include "adfs.h" | 18 | #include "adfs.h" |
| 18 | #include "dir_f.h" | 19 | #include "dir_f.h" |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 9bd757774c9e..88067f36e5e7 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -564,7 +564,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 564 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 564 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 565 | { | 565 | { |
| 566 | struct afs_vnode *vnode, *dir; | 566 | struct afs_vnode *vnode, *dir; |
| 567 | struct afs_fid fid; | 567 | struct afs_fid uninitialized_var(fid); |
| 568 | struct dentry *parent; | 568 | struct dentry *parent; |
| 569 | struct key *key; | 569 | struct key *key; |
| 570 | void *dir_version; | 570 | void *dir_version; |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index c52be53f6946..5ffb570cd3a8 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
| 18 | #include <linux/mount.h> | 18 | #include <linux/mount.h> |
| 19 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
| 20 | #include <linux/mnt_namespace.h> | ||
| 21 | #include "internal.h" | 20 | #include "internal.h" |
| 22 | 21 | ||
| 23 | 22 | ||
diff --git a/fs/afs/super.c b/fs/afs/super.c index ad0514d0115f..e1ea1c240b6a 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/smp_lock.h> | ||
| 21 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 22 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
| 23 | #include <linux/parser.h> | 24 | #include <linux/parser.h> |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index f3da2eb51f56..00bf8fcb245f 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 20 | #include <linux/compat.h> | 20 | #include <linux/compat.h> |
| 21 | #include <linux/syscalls.h> | 21 | #include <linux/syscalls.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 23 | #include <linux/magic.h> | 22 | #include <linux/magic.h> |
| 24 | #include <linux/dcache.h> | 23 | #include <linux/dcache.h> |
| 25 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 54bd07d44e68..1e41aadb1068 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <linux/time.h> | 8 | #include <linux/time.h> |
| 9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
| 10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
| 11 | #include <linux/smp_lock.h> | ||
| 12 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
| 13 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
| 14 | #include "bfs.h" | 13 | #include "bfs.h" |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 6a021265f018..88b9a3ff44e4 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
| 13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
| 14 | #include <linux/smp_lock.h> | ||
| 15 | #include "bfs.h" | 14 | #include "bfs.h" |
| 16 | 15 | ||
| 17 | #undef DEBUG | 16 | #undef DEBUG |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 697f6b5f1313..e92f229e3c6e 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
| @@ -828,15 +828,22 @@ static int load_flat_shared_library(int id, struct lib_info *libs) | |||
| 828 | if (IS_ERR(bprm.file)) | 828 | if (IS_ERR(bprm.file)) |
| 829 | return res; | 829 | return res; |
| 830 | 830 | ||
| 831 | bprm.cred = prepare_exec_creds(); | ||
| 832 | res = -ENOMEM; | ||
| 833 | if (!bprm.cred) | ||
| 834 | goto out; | ||
| 835 | |||
| 831 | res = prepare_binprm(&bprm); | 836 | res = prepare_binprm(&bprm); |
| 832 | 837 | ||
| 833 | if (res <= (unsigned long)-4096) | 838 | if (res <= (unsigned long)-4096) |
| 834 | res = load_flat_file(&bprm, libs, id, NULL); | 839 | res = load_flat_file(&bprm, libs, id, NULL); |
| 835 | if (bprm.file) { | 840 | |
| 836 | allow_write_access(bprm.file); | 841 | abort_creds(bprm.cred); |
| 837 | fput(bprm.file); | 842 | |
| 838 | bprm.file = NULL; | 843 | out: |
| 839 | } | 844 | allow_write_access(bprm.file); |
| 845 | fput(bprm.file); | ||
| 846 | |||
| 840 | return(res); | 847 | return(res); |
| 841 | } | 848 | } |
| 842 | 849 | ||
| @@ -705,14 +705,13 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, | |||
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, | 707 | static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, |
| 708 | struct sg_iovec *iov, int iov_count, int uncopy, | 708 | struct sg_iovec *iov, int iov_count, |
| 709 | int do_free_page) | 709 | int to_user, int from_user, int do_free_page) |
| 710 | { | 710 | { |
| 711 | int ret = 0, i; | 711 | int ret = 0, i; |
| 712 | struct bio_vec *bvec; | 712 | struct bio_vec *bvec; |
| 713 | int iov_idx = 0; | 713 | int iov_idx = 0; |
| 714 | unsigned int iov_off = 0; | 714 | unsigned int iov_off = 0; |
| 715 | int read = bio_data_dir(bio) == READ; | ||
| 716 | 715 | ||
| 717 | __bio_for_each_segment(bvec, bio, i, 0) { | 716 | __bio_for_each_segment(bvec, bio, i, 0) { |
| 718 | char *bv_addr = page_address(bvec->bv_page); | 717 | char *bv_addr = page_address(bvec->bv_page); |
| @@ -727,13 +726,14 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, | |||
| 727 | iov_addr = iov[iov_idx].iov_base + iov_off; | 726 | iov_addr = iov[iov_idx].iov_base + iov_off; |
| 728 | 727 | ||
| 729 | if (!ret) { | 728 | if (!ret) { |
| 730 | if (!read && !uncopy) | 729 | if (to_user) |
| 731 | ret = copy_from_user(bv_addr, iov_addr, | ||
| 732 | bytes); | ||
| 733 | if (read && uncopy) | ||
| 734 | ret = copy_to_user(iov_addr, bv_addr, | 730 | ret = copy_to_user(iov_addr, bv_addr, |
| 735 | bytes); | 731 | bytes); |
| 736 | 732 | ||
| 733 | if (from_user) | ||
| 734 | ret = copy_from_user(bv_addr, iov_addr, | ||
| 735 | bytes); | ||
| 736 | |||
| 737 | if (ret) | 737 | if (ret) |
| 738 | ret = -EFAULT; | 738 | ret = -EFAULT; |
| 739 | } | 739 | } |
| @@ -770,7 +770,8 @@ int bio_uncopy_user(struct bio *bio) | |||
| 770 | 770 | ||
| 771 | if (!bio_flagged(bio, BIO_NULL_MAPPED)) | 771 | if (!bio_flagged(bio, BIO_NULL_MAPPED)) |
| 772 | ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, | 772 | ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, |
| 773 | bmd->nr_sgvecs, 1, bmd->is_our_pages); | 773 | bmd->nr_sgvecs, bio_data_dir(bio) == READ, |
| 774 | 0, bmd->is_our_pages); | ||
| 774 | bio_free_map_data(bmd); | 775 | bio_free_map_data(bmd); |
| 775 | bio_put(bio); | 776 | bio_put(bio); |
| 776 | return ret; | 777 | return ret; |
| @@ -875,8 +876,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
| 875 | /* | 876 | /* |
| 876 | * success | 877 | * success |
| 877 | */ | 878 | */ |
| 878 | if (!write_to_vm && (!map_data || !map_data->null_mapped)) { | 879 | if ((!write_to_vm && (!map_data || !map_data->null_mapped)) || |
| 879 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); | 880 | (map_data && map_data->from_user)) { |
| 881 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0); | ||
| 880 | if (ret) | 882 | if (ret) |
| 881 | goto cleanup; | 883 | goto cleanup; |
| 882 | } | 884 | } |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 3a6d4fb2a329..94dfda24c06e 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev) | |||
| 564 | 564 | ||
| 565 | EXPORT_SYMBOL(bdget); | 565 | EXPORT_SYMBOL(bdget); |
| 566 | 566 | ||
| 567 | /** | ||
| 568 | * bdgrab -- Grab a reference to an already referenced block device | ||
| 569 | * @bdev: Block device to grab a reference to. | ||
| 570 | */ | ||
| 571 | struct block_device *bdgrab(struct block_device *bdev) | ||
| 572 | { | ||
| 573 | atomic_inc(&bdev->bd_inode->i_count); | ||
| 574 | return bdev; | ||
| 575 | } | ||
| 576 | |||
| 567 | long nr_blockdev_pages(void) | 577 | long nr_blockdev_pages(void) |
| 568 | { | 578 | { |
| 569 | struct block_device *bdev; | 579 | struct block_device *bdev; |
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 6e4f6c50a120..019e8af449ab 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
| @@ -424,11 +424,11 @@ int btrfs_requeue_work(struct btrfs_work *work) | |||
| 424 | * list | 424 | * list |
| 425 | */ | 425 | */ |
| 426 | if (worker->idle) { | 426 | if (worker->idle) { |
| 427 | spin_lock_irqsave(&worker->workers->lock, flags); | 427 | spin_lock(&worker->workers->lock); |
| 428 | worker->idle = 0; | 428 | worker->idle = 0; |
| 429 | list_move_tail(&worker->worker_list, | 429 | list_move_tail(&worker->worker_list, |
| 430 | &worker->workers->worker_list); | 430 | &worker->workers->worker_list); |
| 431 | spin_unlock_irqrestore(&worker->workers->lock, flags); | 431 | spin_unlock(&worker->workers->lock); |
| 432 | } | 432 | } |
| 433 | if (!worker->working) { | 433 | if (!worker->working) { |
| 434 | wake = 1; | 434 | wake = 1; |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index de1e2fd32080..9d8ba4d54a37 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | #include <linux/backing-dev.h> | 29 | #include <linux/backing-dev.h> |
| 31 | #include <linux/mpage.h> | 30 | #include <linux/mpage.h> |
| 32 | #include <linux/swap.h> | 31 | #include <linux/swap.h> |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 60a45f3a4e91..3fdcc0512d3a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -557,19 +557,7 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | |||
| 557 | 557 | ||
| 558 | btrfs_disk_key_to_cpu(&k1, disk); | 558 | btrfs_disk_key_to_cpu(&k1, disk); |
| 559 | 559 | ||
| 560 | if (k1.objectid > k2->objectid) | 560 | return btrfs_comp_cpu_keys(&k1, k2); |
| 561 | return 1; | ||
| 562 | if (k1.objectid < k2->objectid) | ||
| 563 | return -1; | ||
| 564 | if (k1.type > k2->type) | ||
| 565 | return 1; | ||
| 566 | if (k1.type < k2->type) | ||
| 567 | return -1; | ||
| 568 | if (k1.offset > k2->offset) | ||
| 569 | return 1; | ||
| 570 | if (k1.offset < k2->offset) | ||
| 571 | return -1; | ||
| 572 | return 0; | ||
| 573 | } | 561 | } |
| 574 | 562 | ||
| 575 | /* | 563 | /* |
| @@ -1052,9 +1040,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1052 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 1040 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
| 1053 | return 0; | 1041 | return 0; |
| 1054 | 1042 | ||
| 1055 | if (btrfs_header_nritems(mid) > 2) | ||
| 1056 | return 0; | ||
| 1057 | |||
| 1058 | if (btrfs_header_nritems(mid) < 2) | 1043 | if (btrfs_header_nritems(mid) < 2) |
| 1059 | err_on_enospc = 1; | 1044 | err_on_enospc = 1; |
| 1060 | 1045 | ||
| @@ -1701,6 +1686,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1701 | struct extent_buffer *b; | 1686 | struct extent_buffer *b; |
| 1702 | int slot; | 1687 | int slot; |
| 1703 | int ret; | 1688 | int ret; |
| 1689 | int err; | ||
| 1704 | int level; | 1690 | int level; |
| 1705 | int lowest_unlock = 1; | 1691 | int lowest_unlock = 1; |
| 1706 | u8 lowest_level = 0; | 1692 | u8 lowest_level = 0; |
| @@ -1737,8 +1723,6 @@ again: | |||
| 1737 | p->locks[level] = 1; | 1723 | p->locks[level] = 1; |
| 1738 | 1724 | ||
| 1739 | if (cow) { | 1725 | if (cow) { |
| 1740 | int wret; | ||
| 1741 | |||
| 1742 | /* | 1726 | /* |
| 1743 | * if we don't really need to cow this block | 1727 | * if we don't really need to cow this block |
| 1744 | * then we don't want to set the path blocking, | 1728 | * then we don't want to set the path blocking, |
| @@ -1749,12 +1733,12 @@ again: | |||
| 1749 | 1733 | ||
| 1750 | btrfs_set_path_blocking(p); | 1734 | btrfs_set_path_blocking(p); |
| 1751 | 1735 | ||
| 1752 | wret = btrfs_cow_block(trans, root, b, | 1736 | err = btrfs_cow_block(trans, root, b, |
| 1753 | p->nodes[level + 1], | 1737 | p->nodes[level + 1], |
| 1754 | p->slots[level + 1], &b); | 1738 | p->slots[level + 1], &b); |
| 1755 | if (wret) { | 1739 | if (err) { |
| 1756 | free_extent_buffer(b); | 1740 | free_extent_buffer(b); |
| 1757 | ret = wret; | 1741 | ret = err; |
| 1758 | goto done; | 1742 | goto done; |
| 1759 | } | 1743 | } |
| 1760 | } | 1744 | } |
| @@ -1793,41 +1777,45 @@ cow_done: | |||
| 1793 | ret = bin_search(b, key, level, &slot); | 1777 | ret = bin_search(b, key, level, &slot); |
| 1794 | 1778 | ||
| 1795 | if (level != 0) { | 1779 | if (level != 0) { |
| 1796 | if (ret && slot > 0) | 1780 | int dec = 0; |
| 1781 | if (ret && slot > 0) { | ||
| 1782 | dec = 1; | ||
| 1797 | slot -= 1; | 1783 | slot -= 1; |
| 1784 | } | ||
| 1798 | p->slots[level] = slot; | 1785 | p->slots[level] = slot; |
| 1799 | ret = setup_nodes_for_search(trans, root, p, b, level, | 1786 | err = setup_nodes_for_search(trans, root, p, b, level, |
| 1800 | ins_len); | 1787 | ins_len); |
| 1801 | if (ret == -EAGAIN) | 1788 | if (err == -EAGAIN) |
| 1802 | goto again; | 1789 | goto again; |
| 1803 | else if (ret) | 1790 | if (err) { |
| 1791 | ret = err; | ||
| 1804 | goto done; | 1792 | goto done; |
| 1793 | } | ||
| 1805 | b = p->nodes[level]; | 1794 | b = p->nodes[level]; |
| 1806 | slot = p->slots[level]; | 1795 | slot = p->slots[level]; |
| 1807 | 1796 | ||
| 1808 | unlock_up(p, level, lowest_unlock); | 1797 | unlock_up(p, level, lowest_unlock); |
| 1809 | 1798 | ||
| 1810 | /* this is only true while dropping a snapshot */ | ||
| 1811 | if (level == lowest_level) { | 1799 | if (level == lowest_level) { |
| 1812 | ret = 0; | 1800 | if (dec) |
| 1801 | p->slots[level]++; | ||
| 1813 | goto done; | 1802 | goto done; |
| 1814 | } | 1803 | } |
| 1815 | 1804 | ||
| 1816 | ret = read_block_for_search(trans, root, p, | 1805 | err = read_block_for_search(trans, root, p, |
| 1817 | &b, level, slot, key); | 1806 | &b, level, slot, key); |
| 1818 | if (ret == -EAGAIN) | 1807 | if (err == -EAGAIN) |
| 1819 | goto again; | 1808 | goto again; |
| 1820 | 1809 | if (err) { | |
| 1821 | if (ret == -EIO) | 1810 | ret = err; |
| 1822 | goto done; | 1811 | goto done; |
| 1812 | } | ||
| 1823 | 1813 | ||
| 1824 | if (!p->skip_locking) { | 1814 | if (!p->skip_locking) { |
| 1825 | int lret; | ||
| 1826 | |||
| 1827 | btrfs_clear_path_blocking(p, NULL); | 1815 | btrfs_clear_path_blocking(p, NULL); |
| 1828 | lret = btrfs_try_spin_lock(b); | 1816 | err = btrfs_try_spin_lock(b); |
| 1829 | 1817 | ||
| 1830 | if (!lret) { | 1818 | if (!err) { |
| 1831 | btrfs_set_path_blocking(p); | 1819 | btrfs_set_path_blocking(p); |
| 1832 | btrfs_tree_lock(b); | 1820 | btrfs_tree_lock(b); |
| 1833 | btrfs_clear_path_blocking(p, b); | 1821 | btrfs_clear_path_blocking(p, b); |
| @@ -1837,16 +1825,14 @@ cow_done: | |||
| 1837 | p->slots[level] = slot; | 1825 | p->slots[level] = slot; |
| 1838 | if (ins_len > 0 && | 1826 | if (ins_len > 0 && |
| 1839 | btrfs_leaf_free_space(root, b) < ins_len) { | 1827 | btrfs_leaf_free_space(root, b) < ins_len) { |
| 1840 | int sret; | ||
| 1841 | |||
| 1842 | btrfs_set_path_blocking(p); | 1828 | btrfs_set_path_blocking(p); |
| 1843 | sret = split_leaf(trans, root, key, | 1829 | err = split_leaf(trans, root, key, |
| 1844 | p, ins_len, ret == 0); | 1830 | p, ins_len, ret == 0); |
| 1845 | btrfs_clear_path_blocking(p, NULL); | 1831 | btrfs_clear_path_blocking(p, NULL); |
| 1846 | 1832 | ||
| 1847 | BUG_ON(sret > 0); | 1833 | BUG_ON(err > 0); |
| 1848 | if (sret) { | 1834 | if (err) { |
| 1849 | ret = sret; | 1835 | ret = err; |
| 1850 | goto done; | 1836 | goto done; |
| 1851 | } | 1837 | } |
| 1852 | } | 1838 | } |
| @@ -3807,7 +3793,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 3807 | } | 3793 | } |
| 3808 | 3794 | ||
| 3809 | /* delete the leaf if it is mostly empty */ | 3795 | /* delete the leaf if it is mostly empty */ |
| 3810 | if (used < BTRFS_LEAF_DATA_SIZE(root) / 2) { | 3796 | if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { |
| 3811 | /* push_leaf_left fixes the path. | 3797 | /* push_leaf_left fixes the path. |
| 3812 | * make sure the path still points to our leaf | 3798 | * make sure the path still points to our leaf |
| 3813 | * for possible call to del_ptr below | 3799 | * for possible call to del_ptr below |
| @@ -4042,10 +4028,9 @@ out: | |||
| 4042 | * calling this function. | 4028 | * calling this function. |
| 4043 | */ | 4029 | */ |
| 4044 | int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, | 4030 | int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, |
| 4045 | struct btrfs_key *key, int lowest_level, | 4031 | struct btrfs_key *key, int level, |
| 4046 | int cache_only, u64 min_trans) | 4032 | int cache_only, u64 min_trans) |
| 4047 | { | 4033 | { |
| 4048 | int level = lowest_level; | ||
| 4049 | int slot; | 4034 | int slot; |
| 4050 | struct extent_buffer *c; | 4035 | struct extent_buffer *c; |
| 4051 | 4036 | ||
| @@ -4058,11 +4043,40 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, | |||
| 4058 | c = path->nodes[level]; | 4043 | c = path->nodes[level]; |
| 4059 | next: | 4044 | next: |
| 4060 | if (slot >= btrfs_header_nritems(c)) { | 4045 | if (slot >= btrfs_header_nritems(c)) { |
| 4061 | level++; | 4046 | int ret; |
| 4062 | if (level == BTRFS_MAX_LEVEL) | 4047 | int orig_lowest; |
| 4048 | struct btrfs_key cur_key; | ||
| 4049 | if (level + 1 >= BTRFS_MAX_LEVEL || | ||
| 4050 | !path->nodes[level + 1]) | ||
| 4063 | return 1; | 4051 | return 1; |
| 4064 | continue; | 4052 | |
| 4053 | if (path->locks[level + 1]) { | ||
| 4054 | level++; | ||
| 4055 | continue; | ||
| 4056 | } | ||
| 4057 | |||
| 4058 | slot = btrfs_header_nritems(c) - 1; | ||
| 4059 | if (level == 0) | ||
| 4060 | btrfs_item_key_to_cpu(c, &cur_key, slot); | ||
| 4061 | else | ||
| 4062 | btrfs_node_key_to_cpu(c, &cur_key, slot); | ||
| 4063 | |||
| 4064 | orig_lowest = path->lowest_level; | ||
| 4065 | btrfs_release_path(root, path); | ||
| 4066 | path->lowest_level = level; | ||
| 4067 | ret = btrfs_search_slot(NULL, root, &cur_key, path, | ||
| 4068 | 0, 0); | ||
| 4069 | path->lowest_level = orig_lowest; | ||
| 4070 | if (ret < 0) | ||
| 4071 | return ret; | ||
| 4072 | |||
| 4073 | c = path->nodes[level]; | ||
| 4074 | slot = path->slots[level]; | ||
| 4075 | if (ret == 0) | ||
| 4076 | slot++; | ||
| 4077 | goto next; | ||
| 4065 | } | 4078 | } |
| 4079 | |||
| 4066 | if (level == 0) | 4080 | if (level == 0) |
| 4067 | btrfs_item_key_to_cpu(c, key, slot); | 4081 | btrfs_item_key_to_cpu(c, key, slot); |
| 4068 | else { | 4082 | else { |
| @@ -4146,7 +4160,8 @@ again: | |||
| 4146 | * advance the path if there are now more items available. | 4160 | * advance the path if there are now more items available. |
| 4147 | */ | 4161 | */ |
| 4148 | if (nritems > 0 && path->slots[0] < nritems - 1) { | 4162 | if (nritems > 0 && path->slots[0] < nritems - 1) { |
| 4149 | path->slots[0]++; | 4163 | if (ret == 0) |
| 4164 | path->slots[0]++; | ||
| 4150 | ret = 0; | 4165 | ret = 0; |
| 4151 | goto done; | 4166 | goto done; |
| 4152 | } | 4167 | } |
| @@ -4278,10 +4293,10 @@ int btrfs_previous_item(struct btrfs_root *root, | |||
| 4278 | path->slots[0]--; | 4293 | path->slots[0]--; |
| 4279 | 4294 | ||
| 4280 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 4295 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 4281 | if (found_key.type == type) | ||
| 4282 | return 0; | ||
| 4283 | if (found_key.objectid < min_objectid) | 4296 | if (found_key.objectid < min_objectid) |
| 4284 | break; | 4297 | break; |
| 4298 | if (found_key.type == type) | ||
| 4299 | return 0; | ||
| 4285 | if (found_key.objectid == min_objectid && | 4300 | if (found_key.objectid == min_objectid && |
| 4286 | found_key.type < type) | 4301 | found_key.type < type) |
| 4287 | break; | 4302 | break; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 98a873838717..837435ce84ca 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -481,7 +481,7 @@ struct btrfs_shared_data_ref { | |||
| 481 | 481 | ||
| 482 | struct btrfs_extent_inline_ref { | 482 | struct btrfs_extent_inline_ref { |
| 483 | u8 type; | 483 | u8 type; |
| 484 | u64 offset; | 484 | __le64 offset; |
| 485 | } __attribute__ ((__packed__)); | 485 | } __attribute__ ((__packed__)); |
| 486 | 486 | ||
| 487 | /* old style backrefs item */ | 487 | /* old style backrefs item */ |
| @@ -689,6 +689,7 @@ struct btrfs_space_info { | |||
| 689 | struct list_head block_groups; | 689 | struct list_head block_groups; |
| 690 | spinlock_t lock; | 690 | spinlock_t lock; |
| 691 | struct rw_semaphore groups_sem; | 691 | struct rw_semaphore groups_sem; |
| 692 | atomic_t caching_threads; | ||
| 692 | }; | 693 | }; |
| 693 | 694 | ||
| 694 | /* | 695 | /* |
| @@ -707,6 +708,9 @@ struct btrfs_free_cluster { | |||
| 707 | /* first extent starting offset */ | 708 | /* first extent starting offset */ |
| 708 | u64 window_start; | 709 | u64 window_start; |
| 709 | 710 | ||
| 711 | /* if this cluster simply points at a bitmap in the block group */ | ||
| 712 | bool points_to_bitmap; | ||
| 713 | |||
| 710 | struct btrfs_block_group_cache *block_group; | 714 | struct btrfs_block_group_cache *block_group; |
| 711 | /* | 715 | /* |
| 712 | * when a cluster is allocated from a block group, we put the | 716 | * when a cluster is allocated from a block group, we put the |
| @@ -716,24 +720,37 @@ struct btrfs_free_cluster { | |||
| 716 | struct list_head block_group_list; | 720 | struct list_head block_group_list; |
| 717 | }; | 721 | }; |
| 718 | 722 | ||
| 723 | enum btrfs_caching_type { | ||
| 724 | BTRFS_CACHE_NO = 0, | ||
| 725 | BTRFS_CACHE_STARTED = 1, | ||
| 726 | BTRFS_CACHE_FINISHED = 2, | ||
| 727 | }; | ||
| 728 | |||
| 719 | struct btrfs_block_group_cache { | 729 | struct btrfs_block_group_cache { |
| 720 | struct btrfs_key key; | 730 | struct btrfs_key key; |
| 721 | struct btrfs_block_group_item item; | 731 | struct btrfs_block_group_item item; |
| 732 | struct btrfs_fs_info *fs_info; | ||
| 722 | spinlock_t lock; | 733 | spinlock_t lock; |
| 723 | struct mutex cache_mutex; | ||
| 724 | u64 pinned; | 734 | u64 pinned; |
| 725 | u64 reserved; | 735 | u64 reserved; |
| 726 | u64 flags; | 736 | u64 flags; |
| 727 | int cached; | 737 | u64 sectorsize; |
| 738 | int extents_thresh; | ||
| 739 | int free_extents; | ||
| 740 | int total_bitmaps; | ||
| 728 | int ro; | 741 | int ro; |
| 729 | int dirty; | 742 | int dirty; |
| 730 | 743 | ||
| 744 | /* cache tracking stuff */ | ||
| 745 | wait_queue_head_t caching_q; | ||
| 746 | int cached; | ||
| 747 | |||
| 731 | struct btrfs_space_info *space_info; | 748 | struct btrfs_space_info *space_info; |
| 732 | 749 | ||
| 733 | /* free space cache stuff */ | 750 | /* free space cache stuff */ |
| 734 | spinlock_t tree_lock; | 751 | spinlock_t tree_lock; |
| 735 | struct rb_root free_space_bytes; | ||
| 736 | struct rb_root free_space_offset; | 752 | struct rb_root free_space_offset; |
| 753 | u64 free_space; | ||
| 737 | 754 | ||
| 738 | /* block group cache stuff */ | 755 | /* block group cache stuff */ |
| 739 | struct rb_node cache_node; | 756 | struct rb_node cache_node; |
| @@ -808,6 +825,7 @@ struct btrfs_fs_info { | |||
| 808 | struct mutex drop_mutex; | 825 | struct mutex drop_mutex; |
| 809 | struct mutex volume_mutex; | 826 | struct mutex volume_mutex; |
| 810 | struct mutex tree_reloc_mutex; | 827 | struct mutex tree_reloc_mutex; |
| 828 | struct rw_semaphore extent_commit_sem; | ||
| 811 | 829 | ||
| 812 | /* | 830 | /* |
| 813 | * this protects the ordered operations list only while we are | 831 | * this protects the ordered operations list only while we are |
| @@ -1988,6 +2006,7 @@ void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode, | |||
| 1988 | u64 bytes); | 2006 | u64 bytes); |
| 1989 | void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, | 2007 | void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, |
| 1990 | u64 bytes); | 2008 | u64 bytes); |
| 2009 | void btrfs_free_pinned_extents(struct btrfs_fs_info *info); | ||
| 1991 | /* ctree.c */ | 2010 | /* ctree.c */ |
| 1992 | int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, | 2011 | int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, |
| 1993 | int level, int *slot); | 2012 | int level, int *slot); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d28d29c95f7c..e83be2e4602c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1639,6 +1639,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1639 | mutex_init(&fs_info->cleaner_mutex); | 1639 | mutex_init(&fs_info->cleaner_mutex); |
| 1640 | mutex_init(&fs_info->volume_mutex); | 1640 | mutex_init(&fs_info->volume_mutex); |
| 1641 | mutex_init(&fs_info->tree_reloc_mutex); | 1641 | mutex_init(&fs_info->tree_reloc_mutex); |
| 1642 | init_rwsem(&fs_info->extent_commit_sem); | ||
| 1642 | 1643 | ||
| 1643 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); | 1644 | btrfs_init_free_cluster(&fs_info->meta_alloc_cluster); |
| 1644 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); | 1645 | btrfs_init_free_cluster(&fs_info->data_alloc_cluster); |
| @@ -1799,6 +1800,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1799 | btrfs_super_chunk_root(disk_super), | 1800 | btrfs_super_chunk_root(disk_super), |
| 1800 | blocksize, generation); | 1801 | blocksize, generation); |
| 1801 | BUG_ON(!chunk_root->node); | 1802 | BUG_ON(!chunk_root->node); |
| 1803 | if (!test_bit(EXTENT_BUFFER_UPTODATE, &chunk_root->node->bflags)) { | ||
| 1804 | printk(KERN_WARNING "btrfs: failed to read chunk root on %s\n", | ||
| 1805 | sb->s_id); | ||
| 1806 | goto fail_chunk_root; | ||
| 1807 | } | ||
| 1802 | btrfs_set_root_node(&chunk_root->root_item, chunk_root->node); | 1808 | btrfs_set_root_node(&chunk_root->root_item, chunk_root->node); |
| 1803 | chunk_root->commit_root = btrfs_root_node(chunk_root); | 1809 | chunk_root->commit_root = btrfs_root_node(chunk_root); |
| 1804 | 1810 | ||
| @@ -1826,6 +1832,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1826 | blocksize, generation); | 1832 | blocksize, generation); |
| 1827 | if (!tree_root->node) | 1833 | if (!tree_root->node) |
| 1828 | goto fail_chunk_root; | 1834 | goto fail_chunk_root; |
| 1835 | if (!test_bit(EXTENT_BUFFER_UPTODATE, &tree_root->node->bflags)) { | ||
| 1836 | printk(KERN_WARNING "btrfs: failed to read tree root on %s\n", | ||
| 1837 | sb->s_id); | ||
| 1838 | goto fail_tree_root; | ||
| 1839 | } | ||
| 1829 | btrfs_set_root_node(&tree_root->root_item, tree_root->node); | 1840 | btrfs_set_root_node(&tree_root->root_item, tree_root->node); |
| 1830 | tree_root->commit_root = btrfs_root_node(tree_root); | 1841 | tree_root->commit_root = btrfs_root_node(tree_root); |
| 1831 | 1842 | ||
| @@ -2322,6 +2333,9 @@ int close_ctree(struct btrfs_root *root) | |||
| 2322 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); | 2333 | printk(KERN_ERR "btrfs: commit super ret %d\n", ret); |
| 2323 | } | 2334 | } |
| 2324 | 2335 | ||
| 2336 | fs_info->closing = 2; | ||
| 2337 | smp_mb(); | ||
| 2338 | |||
| 2325 | if (fs_info->delalloc_bytes) { | 2339 | if (fs_info->delalloc_bytes) { |
| 2326 | printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n", | 2340 | printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n", |
| 2327 | (unsigned long long)fs_info->delalloc_bytes); | 2341 | (unsigned long long)fs_info->delalloc_bytes); |
| @@ -2343,6 +2357,7 @@ int close_ctree(struct btrfs_root *root) | |||
| 2343 | free_extent_buffer(root->fs_info->csum_root->commit_root); | 2357 | free_extent_buffer(root->fs_info->csum_root->commit_root); |
| 2344 | 2358 | ||
| 2345 | btrfs_free_block_groups(root->fs_info); | 2359 | btrfs_free_block_groups(root->fs_info); |
| 2360 | btrfs_free_pinned_extents(root->fs_info); | ||
| 2346 | 2361 | ||
| 2347 | del_fs_roots(fs_info); | 2362 | del_fs_roots(fs_info); |
| 2348 | 2363 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a5aca3997d42..72a2b9c28e9f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
| 22 | #include <linux/sort.h> | 22 | #include <linux/sort.h> |
| 23 | #include <linux/rcupdate.h> | 23 | #include <linux/rcupdate.h> |
| 24 | #include <linux/kthread.h> | ||
| 24 | #include "compat.h" | 25 | #include "compat.h" |
| 25 | #include "hash.h" | 26 | #include "hash.h" |
| 26 | #include "ctree.h" | 27 | #include "ctree.h" |
| @@ -61,6 +62,13 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
| 61 | struct btrfs_root *extent_root, u64 alloc_bytes, | 62 | struct btrfs_root *extent_root, u64 alloc_bytes, |
| 62 | u64 flags, int force); | 63 | u64 flags, int force); |
| 63 | 64 | ||
| 65 | static noinline int | ||
| 66 | block_group_cache_done(struct btrfs_block_group_cache *cache) | ||
| 67 | { | ||
| 68 | smp_mb(); | ||
| 69 | return cache->cached == BTRFS_CACHE_FINISHED; | ||
| 70 | } | ||
| 71 | |||
| 64 | static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) | 72 | static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) |
| 65 | { | 73 | { |
| 66 | return (cache->flags & bits) == bits; | 74 | return (cache->flags & bits) == bits; |
| @@ -146,20 +154,70 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr, | |||
| 146 | } | 154 | } |
| 147 | 155 | ||
| 148 | /* | 156 | /* |
| 157 | * We always set EXTENT_LOCKED for the super mirror extents so we don't | ||
| 158 | * overwrite them, so those bits need to be unset. Also, if we are unmounting | ||
| 159 | * with pinned extents still sitting there because we had a block group caching, | ||
| 160 | * we need to clear those now, since we are done. | ||
| 161 | */ | ||
| 162 | void btrfs_free_pinned_extents(struct btrfs_fs_info *info) | ||
| 163 | { | ||
| 164 | u64 start, end, last = 0; | ||
| 165 | int ret; | ||
| 166 | |||
| 167 | while (1) { | ||
| 168 | ret = find_first_extent_bit(&info->pinned_extents, last, | ||
| 169 | &start, &end, | ||
| 170 | EXTENT_LOCKED|EXTENT_DIRTY); | ||
| 171 | if (ret) | ||
| 172 | break; | ||
| 173 | |||
| 174 | clear_extent_bits(&info->pinned_extents, start, end, | ||
| 175 | EXTENT_LOCKED|EXTENT_DIRTY, GFP_NOFS); | ||
| 176 | last = end+1; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | static int remove_sb_from_cache(struct btrfs_root *root, | ||
| 181 | struct btrfs_block_group_cache *cache) | ||
| 182 | { | ||
| 183 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
| 184 | u64 bytenr; | ||
| 185 | u64 *logical; | ||
| 186 | int stripe_len; | ||
| 187 | int i, nr, ret; | ||
| 188 | |||
| 189 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { | ||
| 190 | bytenr = btrfs_sb_offset(i); | ||
| 191 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, | ||
| 192 | cache->key.objectid, bytenr, | ||
| 193 | 0, &logical, &nr, &stripe_len); | ||
| 194 | BUG_ON(ret); | ||
| 195 | while (nr--) { | ||
| 196 | try_lock_extent(&fs_info->pinned_extents, | ||
| 197 | logical[nr], | ||
| 198 | logical[nr] + stripe_len - 1, GFP_NOFS); | ||
| 199 | } | ||
| 200 | kfree(logical); | ||
| 201 | } | ||
| 202 | |||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* | ||
| 149 | * this is only called by cache_block_group, since we could have freed extents | 207 | * this is only called by cache_block_group, since we could have freed extents |
| 150 | * we need to check the pinned_extents for any extents that can't be used yet | 208 | * we need to check the pinned_extents for any extents that can't be used yet |
| 151 | * since their free space will be released as soon as the transaction commits. | 209 | * since their free space will be released as soon as the transaction commits. |
| 152 | */ | 210 | */ |
| 153 | static int add_new_free_space(struct btrfs_block_group_cache *block_group, | 211 | static u64 add_new_free_space(struct btrfs_block_group_cache *block_group, |
| 154 | struct btrfs_fs_info *info, u64 start, u64 end) | 212 | struct btrfs_fs_info *info, u64 start, u64 end) |
| 155 | { | 213 | { |
| 156 | u64 extent_start, extent_end, size; | 214 | u64 extent_start, extent_end, size, total_added = 0; |
| 157 | int ret; | 215 | int ret; |
| 158 | 216 | ||
| 159 | while (start < end) { | 217 | while (start < end) { |
| 160 | ret = find_first_extent_bit(&info->pinned_extents, start, | 218 | ret = find_first_extent_bit(&info->pinned_extents, start, |
| 161 | &extent_start, &extent_end, | 219 | &extent_start, &extent_end, |
| 162 | EXTENT_DIRTY); | 220 | EXTENT_DIRTY|EXTENT_LOCKED); |
| 163 | if (ret) | 221 | if (ret) |
| 164 | break; | 222 | break; |
| 165 | 223 | ||
| @@ -167,6 +225,7 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group, | |||
| 167 | start = extent_end + 1; | 225 | start = extent_end + 1; |
| 168 | } else if (extent_start > start && extent_start < end) { | 226 | } else if (extent_start > start && extent_start < end) { |
| 169 | size = extent_start - start; | 227 | size = extent_start - start; |
| 228 | total_added += size; | ||
| 170 | ret = btrfs_add_free_space(block_group, start, | 229 | ret = btrfs_add_free_space(block_group, start, |
| 171 | size); | 230 | size); |
| 172 | BUG_ON(ret); | 231 | BUG_ON(ret); |
| @@ -178,84 +237,93 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group, | |||
| 178 | 237 | ||
| 179 | if (start < end) { | 238 | if (start < end) { |
| 180 | size = end - start; | 239 | size = end - start; |
| 240 | total_added += size; | ||
| 181 | ret = btrfs_add_free_space(block_group, start, size); | 241 | ret = btrfs_add_free_space(block_group, start, size); |
| 182 | BUG_ON(ret); | 242 | BUG_ON(ret); |
| 183 | } | 243 | } |
| 184 | 244 | ||
| 185 | return 0; | 245 | return total_added; |
| 186 | } | ||
| 187 | |||
| 188 | static int remove_sb_from_cache(struct btrfs_root *root, | ||
| 189 | struct btrfs_block_group_cache *cache) | ||
| 190 | { | ||
| 191 | u64 bytenr; | ||
| 192 | u64 *logical; | ||
| 193 | int stripe_len; | ||
| 194 | int i, nr, ret; | ||
| 195 | |||
| 196 | for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { | ||
| 197 | bytenr = btrfs_sb_offset(i); | ||
| 198 | ret = btrfs_rmap_block(&root->fs_info->mapping_tree, | ||
| 199 | cache->key.objectid, bytenr, 0, | ||
| 200 | &logical, &nr, &stripe_len); | ||
| 201 | BUG_ON(ret); | ||
| 202 | while (nr--) { | ||
| 203 | btrfs_remove_free_space(cache, logical[nr], | ||
| 204 | stripe_len); | ||
| 205 | } | ||
| 206 | kfree(logical); | ||
| 207 | } | ||
| 208 | return 0; | ||
| 209 | } | 246 | } |
| 210 | 247 | ||
| 211 | static int cache_block_group(struct btrfs_root *root, | 248 | static int caching_kthread(void *data) |
| 212 | struct btrfs_block_group_cache *block_group) | ||
| 213 | { | 249 | { |
| 250 | struct btrfs_block_group_cache *block_group = data; | ||
| 251 | struct btrfs_fs_info *fs_info = block_group->fs_info; | ||
| 252 | u64 last = 0; | ||
| 214 | struct btrfs_path *path; | 253 | struct btrfs_path *path; |
| 215 | int ret = 0; | 254 | int ret = 0; |
| 216 | struct btrfs_key key; | 255 | struct btrfs_key key; |
| 217 | struct extent_buffer *leaf; | 256 | struct extent_buffer *leaf; |
| 218 | int slot; | 257 | int slot; |
| 219 | u64 last; | 258 | u64 total_found = 0; |
| 220 | |||
| 221 | if (!block_group) | ||
| 222 | return 0; | ||
| 223 | |||
| 224 | root = root->fs_info->extent_root; | ||
| 225 | 259 | ||
| 226 | if (block_group->cached) | 260 | BUG_ON(!fs_info); |
| 227 | return 0; | ||
| 228 | 261 | ||
| 229 | path = btrfs_alloc_path(); | 262 | path = btrfs_alloc_path(); |
| 230 | if (!path) | 263 | if (!path) |
| 231 | return -ENOMEM; | 264 | return -ENOMEM; |
| 232 | 265 | ||
| 233 | path->reada = 2; | 266 | atomic_inc(&block_group->space_info->caching_threads); |
| 267 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); | ||
| 234 | /* | 268 | /* |
| 235 | * we get into deadlocks with paths held by callers of this function. | 269 | * We don't want to deadlock with somebody trying to allocate a new |
| 236 | * since the alloc_mutex is protecting things right now, just | 270 | * extent for the extent root while also trying to search the extent |
| 237 | * skip the locking here | 271 | * root to add free space. So we skip locking and search the commit |
| 272 | * root, since its read-only | ||
| 238 | */ | 273 | */ |
| 239 | path->skip_locking = 1; | 274 | path->skip_locking = 1; |
| 240 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); | 275 | path->search_commit_root = 1; |
| 276 | path->reada = 2; | ||
| 277 | |||
| 241 | key.objectid = last; | 278 | key.objectid = last; |
| 242 | key.offset = 0; | 279 | key.offset = 0; |
| 243 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 280 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
| 244 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 281 | again: |
| 282 | /* need to make sure the commit_root doesn't disappear */ | ||
| 283 | down_read(&fs_info->extent_commit_sem); | ||
| 284 | |||
| 285 | ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); | ||
| 245 | if (ret < 0) | 286 | if (ret < 0) |
| 246 | goto err; | 287 | goto err; |
| 247 | 288 | ||
| 248 | while (1) { | 289 | while (1) { |
| 290 | smp_mb(); | ||
| 291 | if (block_group->fs_info->closing > 1) { | ||
| 292 | last = (u64)-1; | ||
| 293 | break; | ||
| 294 | } | ||
| 295 | |||
| 249 | leaf = path->nodes[0]; | 296 | leaf = path->nodes[0]; |
| 250 | slot = path->slots[0]; | 297 | slot = path->slots[0]; |
| 251 | if (slot >= btrfs_header_nritems(leaf)) { | 298 | if (slot >= btrfs_header_nritems(leaf)) { |
| 252 | ret = btrfs_next_leaf(root, path); | 299 | ret = btrfs_next_leaf(fs_info->extent_root, path); |
| 253 | if (ret < 0) | 300 | if (ret < 0) |
| 254 | goto err; | 301 | goto err; |
| 255 | if (ret == 0) | 302 | else if (ret) |
| 256 | continue; | ||
| 257 | else | ||
| 258 | break; | 303 | break; |
| 304 | |||
| 305 | if (need_resched() || | ||
| 306 | btrfs_transaction_in_commit(fs_info)) { | ||
| 307 | leaf = path->nodes[0]; | ||
| 308 | |||
| 309 | /* this shouldn't happen, but if the | ||
| 310 | * leaf is empty just move on. | ||
| 311 | */ | ||
| 312 | if (btrfs_header_nritems(leaf) == 0) | ||
| 313 | break; | ||
| 314 | /* | ||
| 315 | * we need to copy the key out so that | ||
| 316 | * we are sure the next search advances | ||
| 317 | * us forward in the btree. | ||
| 318 | */ | ||
| 319 | btrfs_item_key_to_cpu(leaf, &key, 0); | ||
| 320 | btrfs_release_path(fs_info->extent_root, path); | ||
| 321 | up_read(&fs_info->extent_commit_sem); | ||
| 322 | schedule_timeout(1); | ||
| 323 | goto again; | ||
| 324 | } | ||
| 325 | |||
| 326 | continue; | ||
| 259 | } | 327 | } |
| 260 | btrfs_item_key_to_cpu(leaf, &key, slot); | 328 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 261 | if (key.objectid < block_group->key.objectid) | 329 | if (key.objectid < block_group->key.objectid) |
| @@ -266,24 +334,59 @@ static int cache_block_group(struct btrfs_root *root, | |||
| 266 | break; | 334 | break; |
| 267 | 335 | ||
| 268 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { | 336 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { |
| 269 | add_new_free_space(block_group, root->fs_info, last, | 337 | total_found += add_new_free_space(block_group, |
| 270 | key.objectid); | 338 | fs_info, last, |
| 271 | 339 | key.objectid); | |
| 272 | last = key.objectid + key.offset; | 340 | last = key.objectid + key.offset; |
| 273 | } | 341 | } |
| 342 | |||
| 343 | if (total_found > (1024 * 1024 * 2)) { | ||
| 344 | total_found = 0; | ||
| 345 | wake_up(&block_group->caching_q); | ||
| 346 | } | ||
| 274 | next: | 347 | next: |
| 275 | path->slots[0]++; | 348 | path->slots[0]++; |
| 276 | } | 349 | } |
| 350 | ret = 0; | ||
| 277 | 351 | ||
| 278 | add_new_free_space(block_group, root->fs_info, last, | 352 | total_found += add_new_free_space(block_group, fs_info, last, |
| 279 | block_group->key.objectid + | 353 | block_group->key.objectid + |
| 280 | block_group->key.offset); | 354 | block_group->key.offset); |
| 355 | |||
| 356 | spin_lock(&block_group->lock); | ||
| 357 | block_group->cached = BTRFS_CACHE_FINISHED; | ||
| 358 | spin_unlock(&block_group->lock); | ||
| 281 | 359 | ||
| 282 | block_group->cached = 1; | ||
| 283 | remove_sb_from_cache(root, block_group); | ||
| 284 | ret = 0; | ||
| 285 | err: | 360 | err: |
| 286 | btrfs_free_path(path); | 361 | btrfs_free_path(path); |
| 362 | up_read(&fs_info->extent_commit_sem); | ||
| 363 | atomic_dec(&block_group->space_info->caching_threads); | ||
| 364 | wake_up(&block_group->caching_q); | ||
| 365 | |||
| 366 | return 0; | ||
| 367 | } | ||
| 368 | |||
| 369 | static int cache_block_group(struct btrfs_block_group_cache *cache) | ||
| 370 | { | ||
| 371 | struct task_struct *tsk; | ||
| 372 | int ret = 0; | ||
| 373 | |||
| 374 | spin_lock(&cache->lock); | ||
| 375 | if (cache->cached != BTRFS_CACHE_NO) { | ||
| 376 | spin_unlock(&cache->lock); | ||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | cache->cached = BTRFS_CACHE_STARTED; | ||
| 380 | spin_unlock(&cache->lock); | ||
| 381 | |||
| 382 | tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n", | ||
| 383 | cache->key.objectid); | ||
| 384 | if (IS_ERR(tsk)) { | ||
| 385 | ret = PTR_ERR(tsk); | ||
| 386 | printk(KERN_ERR "error running thread %d\n", ret); | ||
| 387 | BUG(); | ||
| 388 | } | ||
| 389 | |||
| 287 | return ret; | 390 | return ret; |
| 288 | } | 391 | } |
| 289 | 392 | ||
| @@ -2387,13 +2490,29 @@ fail: | |||
| 2387 | 2490 | ||
| 2388 | } | 2491 | } |
| 2389 | 2492 | ||
| 2493 | static struct btrfs_block_group_cache * | ||
| 2494 | next_block_group(struct btrfs_root *root, | ||
| 2495 | struct btrfs_block_group_cache *cache) | ||
| 2496 | { | ||
| 2497 | struct rb_node *node; | ||
| 2498 | spin_lock(&root->fs_info->block_group_cache_lock); | ||
| 2499 | node = rb_next(&cache->cache_node); | ||
| 2500 | btrfs_put_block_group(cache); | ||
| 2501 | if (node) { | ||
| 2502 | cache = rb_entry(node, struct btrfs_block_group_cache, | ||
| 2503 | cache_node); | ||
| 2504 | atomic_inc(&cache->count); | ||
| 2505 | } else | ||
| 2506 | cache = NULL; | ||
| 2507 | spin_unlock(&root->fs_info->block_group_cache_lock); | ||
| 2508 | return cache; | ||
| 2509 | } | ||
| 2510 | |||
| 2390 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | 2511 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, |
| 2391 | struct btrfs_root *root) | 2512 | struct btrfs_root *root) |
| 2392 | { | 2513 | { |
| 2393 | struct btrfs_block_group_cache *cache, *entry; | 2514 | struct btrfs_block_group_cache *cache; |
| 2394 | struct rb_node *n; | ||
| 2395 | int err = 0; | 2515 | int err = 0; |
| 2396 | int werr = 0; | ||
| 2397 | struct btrfs_path *path; | 2516 | struct btrfs_path *path; |
| 2398 | u64 last = 0; | 2517 | u64 last = 0; |
| 2399 | 2518 | ||
| @@ -2402,39 +2521,35 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
| 2402 | return -ENOMEM; | 2521 | return -ENOMEM; |
| 2403 | 2522 | ||
| 2404 | while (1) { | 2523 | while (1) { |
| 2405 | cache = NULL; | 2524 | if (last == 0) { |
| 2406 | spin_lock(&root->fs_info->block_group_cache_lock); | 2525 | err = btrfs_run_delayed_refs(trans, root, |
| 2407 | for (n = rb_first(&root->fs_info->block_group_cache_tree); | 2526 | (unsigned long)-1); |
| 2408 | n; n = rb_next(n)) { | 2527 | BUG_ON(err); |
| 2409 | entry = rb_entry(n, struct btrfs_block_group_cache, | ||
| 2410 | cache_node); | ||
| 2411 | if (entry->dirty) { | ||
| 2412 | cache = entry; | ||
| 2413 | break; | ||
| 2414 | } | ||
| 2415 | } | 2528 | } |
| 2416 | spin_unlock(&root->fs_info->block_group_cache_lock); | ||
| 2417 | 2529 | ||
| 2418 | if (!cache) | 2530 | cache = btrfs_lookup_first_block_group(root->fs_info, last); |
| 2419 | break; | 2531 | while (cache) { |
| 2532 | if (cache->dirty) | ||
| 2533 | break; | ||
| 2534 | cache = next_block_group(root, cache); | ||
| 2535 | } | ||
| 2536 | if (!cache) { | ||
| 2537 | if (last == 0) | ||
| 2538 | break; | ||
| 2539 | last = 0; | ||
| 2540 | continue; | ||
| 2541 | } | ||
| 2420 | 2542 | ||
| 2421 | cache->dirty = 0; | 2543 | cache->dirty = 0; |
| 2422 | last += cache->key.offset; | 2544 | last = cache->key.objectid + cache->key.offset; |
| 2423 | 2545 | ||
| 2424 | err = write_one_cache_group(trans, root, | 2546 | err = write_one_cache_group(trans, root, path, cache); |
| 2425 | path, cache); | 2547 | BUG_ON(err); |
| 2426 | /* | 2548 | btrfs_put_block_group(cache); |
| 2427 | * if we fail to write the cache group, we want | ||
| 2428 | * to keep it marked dirty in hopes that a later | ||
| 2429 | * write will work | ||
| 2430 | */ | ||
| 2431 | if (err) { | ||
| 2432 | werr = err; | ||
| 2433 | continue; | ||
| 2434 | } | ||
| 2435 | } | 2549 | } |
| 2550 | |||
| 2436 | btrfs_free_path(path); | 2551 | btrfs_free_path(path); |
| 2437 | return werr; | 2552 | return 0; |
| 2438 | } | 2553 | } |
| 2439 | 2554 | ||
| 2440 | int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) | 2555 | int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr) |
| @@ -2484,6 +2599,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
| 2484 | found->force_alloc = 0; | 2599 | found->force_alloc = 0; |
| 2485 | *space_info = found; | 2600 | *space_info = found; |
| 2486 | list_add_rcu(&found->list, &info->space_info); | 2601 | list_add_rcu(&found->list, &info->space_info); |
| 2602 | atomic_set(&found->caching_threads, 0); | ||
| 2487 | return 0; | 2603 | return 0; |
| 2488 | } | 2604 | } |
| 2489 | 2605 | ||
| @@ -2947,13 +3063,9 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
| 2947 | struct btrfs_block_group_cache *cache; | 3063 | struct btrfs_block_group_cache *cache; |
| 2948 | struct btrfs_fs_info *fs_info = root->fs_info; | 3064 | struct btrfs_fs_info *fs_info = root->fs_info; |
| 2949 | 3065 | ||
| 2950 | if (pin) { | 3066 | if (pin) |
| 2951 | set_extent_dirty(&fs_info->pinned_extents, | 3067 | set_extent_dirty(&fs_info->pinned_extents, |
| 2952 | bytenr, bytenr + num - 1, GFP_NOFS); | 3068 | bytenr, bytenr + num - 1, GFP_NOFS); |
| 2953 | } else { | ||
| 2954 | clear_extent_dirty(&fs_info->pinned_extents, | ||
| 2955 | bytenr, bytenr + num - 1, GFP_NOFS); | ||
| 2956 | } | ||
| 2957 | 3069 | ||
| 2958 | while (num > 0) { | 3070 | while (num > 0) { |
| 2959 | cache = btrfs_lookup_block_group(fs_info, bytenr); | 3071 | cache = btrfs_lookup_block_group(fs_info, bytenr); |
| @@ -2969,14 +3081,34 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
| 2969 | spin_unlock(&cache->space_info->lock); | 3081 | spin_unlock(&cache->space_info->lock); |
| 2970 | fs_info->total_pinned += len; | 3082 | fs_info->total_pinned += len; |
| 2971 | } else { | 3083 | } else { |
| 3084 | int unpin = 0; | ||
| 3085 | |||
| 3086 | /* | ||
| 3087 | * in order to not race with the block group caching, we | ||
| 3088 | * only want to unpin the extent if we are cached. If | ||
| 3089 | * we aren't cached, we want to start async caching this | ||
| 3090 | * block group so we can free the extent the next time | ||
| 3091 | * around. | ||
| 3092 | */ | ||
| 2972 | spin_lock(&cache->space_info->lock); | 3093 | spin_lock(&cache->space_info->lock); |
| 2973 | spin_lock(&cache->lock); | 3094 | spin_lock(&cache->lock); |
| 2974 | cache->pinned -= len; | 3095 | unpin = (cache->cached == BTRFS_CACHE_FINISHED); |
| 2975 | cache->space_info->bytes_pinned -= len; | 3096 | if (likely(unpin)) { |
| 3097 | cache->pinned -= len; | ||
| 3098 | cache->space_info->bytes_pinned -= len; | ||
| 3099 | fs_info->total_pinned -= len; | ||
| 3100 | } | ||
| 2976 | spin_unlock(&cache->lock); | 3101 | spin_unlock(&cache->lock); |
| 2977 | spin_unlock(&cache->space_info->lock); | 3102 | spin_unlock(&cache->space_info->lock); |
| 2978 | fs_info->total_pinned -= len; | 3103 | |
| 2979 | if (cache->cached) | 3104 | if (likely(unpin)) |
| 3105 | clear_extent_dirty(&fs_info->pinned_extents, | ||
| 3106 | bytenr, bytenr + len -1, | ||
| 3107 | GFP_NOFS); | ||
| 3108 | else | ||
| 3109 | cache_block_group(cache); | ||
| 3110 | |||
| 3111 | if (unpin) | ||
| 2980 | btrfs_add_free_space(cache, bytenr, len); | 3112 | btrfs_add_free_space(cache, bytenr, len); |
| 2981 | } | 3113 | } |
| 2982 | btrfs_put_block_group(cache); | 3114 | btrfs_put_block_group(cache); |
| @@ -3030,6 +3162,7 @@ int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy) | |||
| 3030 | &start, &end, EXTENT_DIRTY); | 3162 | &start, &end, EXTENT_DIRTY); |
| 3031 | if (ret) | 3163 | if (ret) |
| 3032 | break; | 3164 | break; |
| 3165 | |||
| 3033 | set_extent_dirty(copy, start, end, GFP_NOFS); | 3166 | set_extent_dirty(copy, start, end, GFP_NOFS); |
| 3034 | last = end + 1; | 3167 | last = end + 1; |
| 3035 | } | 3168 | } |
| @@ -3058,6 +3191,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
| 3058 | 3191 | ||
| 3059 | cond_resched(); | 3192 | cond_resched(); |
| 3060 | } | 3193 | } |
| 3194 | |||
| 3061 | return ret; | 3195 | return ret; |
| 3062 | } | 3196 | } |
| 3063 | 3197 | ||
| @@ -3436,6 +3570,45 @@ static u64 stripe_align(struct btrfs_root *root, u64 val) | |||
| 3436 | } | 3570 | } |
| 3437 | 3571 | ||
| 3438 | /* | 3572 | /* |
| 3573 | * when we wait for progress in the block group caching, its because | ||
| 3574 | * our allocation attempt failed at least once. So, we must sleep | ||
| 3575 | * and let some progress happen before we try again. | ||
| 3576 | * | ||
| 3577 | * This function will sleep at least once waiting for new free space to | ||
| 3578 | * show up, and then it will check the block group free space numbers | ||
| 3579 | * for our min num_bytes. Another option is to have it go ahead | ||
| 3580 | * and look in the rbtree for a free extent of a given size, but this | ||
| 3581 | * is a good start. | ||
| 3582 | */ | ||
| 3583 | static noinline int | ||
| 3584 | wait_block_group_cache_progress(struct btrfs_block_group_cache *cache, | ||
| 3585 | u64 num_bytes) | ||
| 3586 | { | ||
| 3587 | DEFINE_WAIT(wait); | ||
| 3588 | |||
| 3589 | prepare_to_wait(&cache->caching_q, &wait, TASK_UNINTERRUPTIBLE); | ||
| 3590 | |||
| 3591 | if (block_group_cache_done(cache)) { | ||
| 3592 | finish_wait(&cache->caching_q, &wait); | ||
| 3593 | return 0; | ||
| 3594 | } | ||
| 3595 | schedule(); | ||
| 3596 | finish_wait(&cache->caching_q, &wait); | ||
| 3597 | |||
| 3598 | wait_event(cache->caching_q, block_group_cache_done(cache) || | ||
| 3599 | (cache->free_space >= num_bytes)); | ||
| 3600 | return 0; | ||
| 3601 | } | ||
| 3602 | |||
| 3603 | enum btrfs_loop_type { | ||
| 3604 | LOOP_CACHED_ONLY = 0, | ||
| 3605 | LOOP_CACHING_NOWAIT = 1, | ||
| 3606 | LOOP_CACHING_WAIT = 2, | ||
| 3607 | LOOP_ALLOC_CHUNK = 3, | ||
| 3608 | LOOP_NO_EMPTY_SIZE = 4, | ||
| 3609 | }; | ||
| 3610 | |||
| 3611 | /* | ||
| 3439 | * walks the btree of allocated extents and find a hole of a given size. | 3612 | * walks the btree of allocated extents and find a hole of a given size. |
| 3440 | * The key ins is changed to record the hole: | 3613 | * The key ins is changed to record the hole: |
| 3441 | * ins->objectid == block start | 3614 | * ins->objectid == block start |
| @@ -3460,6 +3633,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 3460 | struct btrfs_space_info *space_info; | 3633 | struct btrfs_space_info *space_info; |
| 3461 | int last_ptr_loop = 0; | 3634 | int last_ptr_loop = 0; |
| 3462 | int loop = 0; | 3635 | int loop = 0; |
| 3636 | bool found_uncached_bg = false; | ||
| 3463 | 3637 | ||
| 3464 | WARN_ON(num_bytes < root->sectorsize); | 3638 | WARN_ON(num_bytes < root->sectorsize); |
| 3465 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 3639 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
| @@ -3491,15 +3665,18 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 3491 | search_start = max(search_start, first_logical_byte(root, 0)); | 3665 | search_start = max(search_start, first_logical_byte(root, 0)); |
| 3492 | search_start = max(search_start, hint_byte); | 3666 | search_start = max(search_start, hint_byte); |
| 3493 | 3667 | ||
| 3494 | if (!last_ptr) { | 3668 | if (!last_ptr) |
| 3495 | empty_cluster = 0; | 3669 | empty_cluster = 0; |
| 3496 | loop = 1; | ||
| 3497 | } | ||
| 3498 | 3670 | ||
| 3499 | if (search_start == hint_byte) { | 3671 | if (search_start == hint_byte) { |
| 3500 | block_group = btrfs_lookup_block_group(root->fs_info, | 3672 | block_group = btrfs_lookup_block_group(root->fs_info, |
| 3501 | search_start); | 3673 | search_start); |
| 3502 | if (block_group && block_group_bits(block_group, data)) { | 3674 | /* |
| 3675 | * we don't want to use the block group if it doesn't match our | ||
| 3676 | * allocation bits, or if its not cached. | ||
| 3677 | */ | ||
| 3678 | if (block_group && block_group_bits(block_group, data) && | ||
| 3679 | block_group_cache_done(block_group)) { | ||
| 3503 | down_read(&space_info->groups_sem); | 3680 | down_read(&space_info->groups_sem); |
| 3504 | if (list_empty(&block_group->list) || | 3681 | if (list_empty(&block_group->list) || |
| 3505 | block_group->ro) { | 3682 | block_group->ro) { |
| @@ -3522,21 +3699,35 @@ search: | |||
| 3522 | down_read(&space_info->groups_sem); | 3699 | down_read(&space_info->groups_sem); |
| 3523 | list_for_each_entry(block_group, &space_info->block_groups, list) { | 3700 | list_for_each_entry(block_group, &space_info->block_groups, list) { |
| 3524 | u64 offset; | 3701 | u64 offset; |
| 3702 | int cached; | ||
| 3525 | 3703 | ||
| 3526 | atomic_inc(&block_group->count); | 3704 | atomic_inc(&block_group->count); |
| 3527 | search_start = block_group->key.objectid; | 3705 | search_start = block_group->key.objectid; |
| 3528 | 3706 | ||
| 3529 | have_block_group: | 3707 | have_block_group: |
| 3530 | if (unlikely(!block_group->cached)) { | 3708 | if (unlikely(block_group->cached == BTRFS_CACHE_NO)) { |
| 3531 | mutex_lock(&block_group->cache_mutex); | 3709 | /* |
| 3532 | ret = cache_block_group(root, block_group); | 3710 | * we want to start caching kthreads, but not too many |
| 3533 | mutex_unlock(&block_group->cache_mutex); | 3711 | * right off the bat so we don't overwhelm the system, |
| 3534 | if (ret) { | 3712 | * so only start them if there are less than 2 and we're |
| 3535 | btrfs_put_block_group(block_group); | 3713 | * in the initial allocation phase. |
| 3536 | break; | 3714 | */ |
| 3715 | if (loop > LOOP_CACHING_NOWAIT || | ||
| 3716 | atomic_read(&space_info->caching_threads) < 2) { | ||
| 3717 | ret = cache_block_group(block_group); | ||
| 3718 | BUG_ON(ret); | ||
| 3537 | } | 3719 | } |
| 3538 | } | 3720 | } |
| 3539 | 3721 | ||
| 3722 | cached = block_group_cache_done(block_group); | ||
| 3723 | if (unlikely(!cached)) { | ||
| 3724 | found_uncached_bg = true; | ||
| 3725 | |||
| 3726 | /* if we only want cached bgs, loop */ | ||
| 3727 | if (loop == LOOP_CACHED_ONLY) | ||
| 3728 | goto loop; | ||
| 3729 | } | ||
| 3730 | |||
| 3540 | if (unlikely(block_group->ro)) | 3731 | if (unlikely(block_group->ro)) |
| 3541 | goto loop; | 3732 | goto loop; |
| 3542 | 3733 | ||
| @@ -3615,14 +3806,21 @@ refill_cluster: | |||
| 3615 | spin_unlock(&last_ptr->refill_lock); | 3806 | spin_unlock(&last_ptr->refill_lock); |
| 3616 | goto checks; | 3807 | goto checks; |
| 3617 | } | 3808 | } |
| 3809 | } else if (!cached && loop > LOOP_CACHING_NOWAIT) { | ||
| 3810 | spin_unlock(&last_ptr->refill_lock); | ||
| 3811 | |||
| 3812 | wait_block_group_cache_progress(block_group, | ||
| 3813 | num_bytes + empty_cluster + empty_size); | ||
| 3814 | goto have_block_group; | ||
| 3618 | } | 3815 | } |
| 3816 | |||
| 3619 | /* | 3817 | /* |
| 3620 | * at this point we either didn't find a cluster | 3818 | * at this point we either didn't find a cluster |
| 3621 | * or we weren't able to allocate a block from our | 3819 | * or we weren't able to allocate a block from our |
| 3622 | * cluster. Free the cluster we've been trying | 3820 | * cluster. Free the cluster we've been trying |
| 3623 | * to use, and go to the next block group | 3821 | * to use, and go to the next block group |
| 3624 | */ | 3822 | */ |
| 3625 | if (loop < 2) { | 3823 | if (loop < LOOP_NO_EMPTY_SIZE) { |
| 3626 | btrfs_return_cluster_to_free_space(NULL, | 3824 | btrfs_return_cluster_to_free_space(NULL, |
| 3627 | last_ptr); | 3825 | last_ptr); |
| 3628 | spin_unlock(&last_ptr->refill_lock); | 3826 | spin_unlock(&last_ptr->refill_lock); |
| @@ -3633,11 +3831,17 @@ refill_cluster: | |||
| 3633 | 3831 | ||
| 3634 | offset = btrfs_find_space_for_alloc(block_group, search_start, | 3832 | offset = btrfs_find_space_for_alloc(block_group, search_start, |
| 3635 | num_bytes, empty_size); | 3833 | num_bytes, empty_size); |
| 3636 | if (!offset) | 3834 | if (!offset && (cached || (!cached && |
| 3835 | loop == LOOP_CACHING_NOWAIT))) { | ||
| 3637 | goto loop; | 3836 | goto loop; |
| 3837 | } else if (!offset && (!cached && | ||
| 3838 | loop > LOOP_CACHING_NOWAIT)) { | ||
| 3839 | wait_block_group_cache_progress(block_group, | ||
| 3840 | num_bytes + empty_size); | ||
| 3841 | goto have_block_group; | ||
| 3842 | } | ||
| 3638 | checks: | 3843 | checks: |
| 3639 | search_start = stripe_align(root, offset); | 3844 | search_start = stripe_align(root, offset); |
| 3640 | |||
| 3641 | /* move on to the next group */ | 3845 | /* move on to the next group */ |
| 3642 | if (search_start + num_bytes >= search_end) { | 3846 | if (search_start + num_bytes >= search_end) { |
| 3643 | btrfs_add_free_space(block_group, offset, num_bytes); | 3847 | btrfs_add_free_space(block_group, offset, num_bytes); |
| @@ -3683,13 +3887,26 @@ loop: | |||
| 3683 | } | 3887 | } |
| 3684 | up_read(&space_info->groups_sem); | 3888 | up_read(&space_info->groups_sem); |
| 3685 | 3889 | ||
| 3686 | /* loop == 0, try to find a clustered alloc in every block group | 3890 | /* LOOP_CACHED_ONLY, only search fully cached block groups |
| 3687 | * loop == 1, try again after forcing a chunk allocation | 3891 | * LOOP_CACHING_NOWAIT, search partially cached block groups, but |
| 3688 | * loop == 2, set empty_size and empty_cluster to 0 and try again | 3892 | * dont wait foR them to finish caching |
| 3893 | * LOOP_CACHING_WAIT, search everything, and wait if our bg is caching | ||
| 3894 | * LOOP_ALLOC_CHUNK, force a chunk allocation and try again | ||
| 3895 | * LOOP_NO_EMPTY_SIZE, set empty_size and empty_cluster to 0 and try | ||
| 3896 | * again | ||
| 3689 | */ | 3897 | */ |
| 3690 | if (!ins->objectid && loop < 3 && | 3898 | if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE && |
| 3691 | (empty_size || empty_cluster || allowed_chunk_alloc)) { | 3899 | (found_uncached_bg || empty_size || empty_cluster || |
| 3692 | if (loop >= 2) { | 3900 | allowed_chunk_alloc)) { |
| 3901 | if (found_uncached_bg) { | ||
| 3902 | found_uncached_bg = false; | ||
| 3903 | if (loop < LOOP_CACHING_WAIT) { | ||
| 3904 | loop++; | ||
| 3905 | goto search; | ||
| 3906 | } | ||
| 3907 | } | ||
| 3908 | |||
| 3909 | if (loop == LOOP_ALLOC_CHUNK) { | ||
| 3693 | empty_size = 0; | 3910 | empty_size = 0; |
| 3694 | empty_cluster = 0; | 3911 | empty_cluster = 0; |
| 3695 | } | 3912 | } |
| @@ -3702,7 +3919,7 @@ loop: | |||
| 3702 | space_info->force_alloc = 1; | 3919 | space_info->force_alloc = 1; |
| 3703 | } | 3920 | } |
| 3704 | 3921 | ||
| 3705 | if (loop < 3) { | 3922 | if (loop < LOOP_NO_EMPTY_SIZE) { |
| 3706 | loop++; | 3923 | loop++; |
| 3707 | goto search; | 3924 | goto search; |
| 3708 | } | 3925 | } |
| @@ -3798,7 +4015,7 @@ again: | |||
| 3798 | num_bytes, data, 1); | 4015 | num_bytes, data, 1); |
| 3799 | goto again; | 4016 | goto again; |
| 3800 | } | 4017 | } |
| 3801 | if (ret) { | 4018 | if (ret == -ENOSPC) { |
| 3802 | struct btrfs_space_info *sinfo; | 4019 | struct btrfs_space_info *sinfo; |
| 3803 | 4020 | ||
| 3804 | sinfo = __find_space_info(root->fs_info, data); | 4021 | sinfo = __find_space_info(root->fs_info, data); |
| @@ -3806,7 +4023,6 @@ again: | |||
| 3806 | "wanted %llu\n", (unsigned long long)data, | 4023 | "wanted %llu\n", (unsigned long long)data, |
| 3807 | (unsigned long long)num_bytes); | 4024 | (unsigned long long)num_bytes); |
| 3808 | dump_space_info(sinfo, num_bytes); | 4025 | dump_space_info(sinfo, num_bytes); |
| 3809 | BUG(); | ||
| 3810 | } | 4026 | } |
| 3811 | 4027 | ||
| 3812 | return ret; | 4028 | return ret; |
| @@ -3844,7 +4060,9 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | |||
| 3844 | ret = __btrfs_reserve_extent(trans, root, num_bytes, min_alloc_size, | 4060 | ret = __btrfs_reserve_extent(trans, root, num_bytes, min_alloc_size, |
| 3845 | empty_size, hint_byte, search_end, ins, | 4061 | empty_size, hint_byte, search_end, ins, |
| 3846 | data); | 4062 | data); |
| 3847 | update_reserved_extents(root, ins->objectid, ins->offset, 1); | 4063 | if (!ret) |
| 4064 | update_reserved_extents(root, ins->objectid, ins->offset, 1); | ||
| 4065 | |||
| 3848 | return ret; | 4066 | return ret; |
| 3849 | } | 4067 | } |
| 3850 | 4068 | ||
| @@ -4006,9 +4224,9 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, | |||
| 4006 | struct btrfs_block_group_cache *block_group; | 4224 | struct btrfs_block_group_cache *block_group; |
| 4007 | 4225 | ||
| 4008 | block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); | 4226 | block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid); |
| 4009 | mutex_lock(&block_group->cache_mutex); | 4227 | cache_block_group(block_group); |
| 4010 | cache_block_group(root, block_group); | 4228 | wait_event(block_group->caching_q, |
| 4011 | mutex_unlock(&block_group->cache_mutex); | 4229 | block_group_cache_done(block_group)); |
| 4012 | 4230 | ||
| 4013 | ret = btrfs_remove_free_space(block_group, ins->objectid, | 4231 | ret = btrfs_remove_free_space(block_group, ins->objectid, |
| 4014 | ins->offset); | 4232 | ins->offset); |
| @@ -4039,7 +4257,8 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans, | |||
| 4039 | ret = __btrfs_reserve_extent(trans, root, num_bytes, num_bytes, | 4257 | ret = __btrfs_reserve_extent(trans, root, num_bytes, num_bytes, |
| 4040 | empty_size, hint_byte, search_end, | 4258 | empty_size, hint_byte, search_end, |
| 4041 | ins, 0); | 4259 | ins, 0); |
| 4042 | BUG_ON(ret); | 4260 | if (ret) |
| 4261 | return ret; | ||
| 4043 | 4262 | ||
| 4044 | if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { | 4263 | if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { |
| 4045 | if (parent == 0) | 4264 | if (parent == 0) |
| @@ -6955,11 +7174,16 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
| 6955 | &info->block_group_cache_tree); | 7174 | &info->block_group_cache_tree); |
| 6956 | spin_unlock(&info->block_group_cache_lock); | 7175 | spin_unlock(&info->block_group_cache_lock); |
| 6957 | 7176 | ||
| 6958 | btrfs_remove_free_space_cache(block_group); | ||
| 6959 | down_write(&block_group->space_info->groups_sem); | 7177 | down_write(&block_group->space_info->groups_sem); |
| 6960 | list_del(&block_group->list); | 7178 | list_del(&block_group->list); |
| 6961 | up_write(&block_group->space_info->groups_sem); | 7179 | up_write(&block_group->space_info->groups_sem); |
| 6962 | 7180 | ||
| 7181 | if (block_group->cached == BTRFS_CACHE_STARTED) | ||
| 7182 | wait_event(block_group->caching_q, | ||
| 7183 | block_group_cache_done(block_group)); | ||
| 7184 | |||
| 7185 | btrfs_remove_free_space_cache(block_group); | ||
| 7186 | |||
| 6963 | WARN_ON(atomic_read(&block_group->count) != 1); | 7187 | WARN_ON(atomic_read(&block_group->count) != 1); |
| 6964 | kfree(block_group); | 7188 | kfree(block_group); |
| 6965 | 7189 | ||
| @@ -7025,9 +7249,19 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 7025 | atomic_set(&cache->count, 1); | 7249 | atomic_set(&cache->count, 1); |
| 7026 | spin_lock_init(&cache->lock); | 7250 | spin_lock_init(&cache->lock); |
| 7027 | spin_lock_init(&cache->tree_lock); | 7251 | spin_lock_init(&cache->tree_lock); |
| 7028 | mutex_init(&cache->cache_mutex); | 7252 | cache->fs_info = info; |
| 7253 | init_waitqueue_head(&cache->caching_q); | ||
| 7029 | INIT_LIST_HEAD(&cache->list); | 7254 | INIT_LIST_HEAD(&cache->list); |
| 7030 | INIT_LIST_HEAD(&cache->cluster_list); | 7255 | INIT_LIST_HEAD(&cache->cluster_list); |
| 7256 | |||
| 7257 | /* | ||
| 7258 | * we only want to have 32k of ram per block group for keeping | ||
| 7259 | * track of free space, and if we pass 1/2 of that we want to | ||
| 7260 | * start converting things over to using bitmaps | ||
| 7261 | */ | ||
| 7262 | cache->extents_thresh = ((1024 * 32) / 2) / | ||
| 7263 | sizeof(struct btrfs_free_space); | ||
| 7264 | |||
| 7031 | read_extent_buffer(leaf, &cache->item, | 7265 | read_extent_buffer(leaf, &cache->item, |
| 7032 | btrfs_item_ptr_offset(leaf, path->slots[0]), | 7266 | btrfs_item_ptr_offset(leaf, path->slots[0]), |
| 7033 | sizeof(cache->item)); | 7267 | sizeof(cache->item)); |
| @@ -7036,6 +7270,26 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
| 7036 | key.objectid = found_key.objectid + found_key.offset; | 7270 | key.objectid = found_key.objectid + found_key.offset; |
| 7037 | btrfs_release_path(root, path); | 7271 | btrfs_release_path(root, path); |
| 7038 | cache->flags = btrfs_block_group_flags(&cache->item); | 7272 | cache->flags = btrfs_block_group_flags(&cache->item); |
| 7273 | cache->sectorsize = root->sectorsize; | ||
| 7274 | |||
| 7275 | remove_sb_from_cache(root, cache); | ||
| 7276 | |||
| 7277 | /* | ||
| 7278 | * check for two cases, either we are full, and therefore | ||
| 7279 | * don't need to bother with the caching work since we won't | ||
| 7280 | * find any space, or we are empty, and we can just add all | ||
| 7281 | * the space in and be done with it. This saves us _alot_ of | ||
| 7282 | * time, particularly in the full case. | ||
| 7283 | */ | ||
| 7284 | if (found_key.offset == btrfs_block_group_used(&cache->item)) { | ||
| 7285 | cache->cached = BTRFS_CACHE_FINISHED; | ||
| 7286 | } else if (btrfs_block_group_used(&cache->item) == 0) { | ||
| 7287 | cache->cached = BTRFS_CACHE_FINISHED; | ||
| 7288 | add_new_free_space(cache, root->fs_info, | ||
| 7289 | found_key.objectid, | ||
| 7290 | found_key.objectid + | ||
| 7291 | found_key.offset); | ||
| 7292 | } | ||
| 7039 | 7293 | ||
| 7040 | ret = update_space_info(info, cache->flags, found_key.offset, | 7294 | ret = update_space_info(info, cache->flags, found_key.offset, |
| 7041 | btrfs_block_group_used(&cache->item), | 7295 | btrfs_block_group_used(&cache->item), |
| @@ -7079,10 +7333,19 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
| 7079 | cache->key.objectid = chunk_offset; | 7333 | cache->key.objectid = chunk_offset; |
| 7080 | cache->key.offset = size; | 7334 | cache->key.offset = size; |
| 7081 | cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; | 7335 | cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; |
| 7336 | cache->sectorsize = root->sectorsize; | ||
| 7337 | |||
| 7338 | /* | ||
| 7339 | * we only want to have 32k of ram per block group for keeping track | ||
| 7340 | * of free space, and if we pass 1/2 of that we want to start | ||
| 7341 | * converting things over to using bitmaps | ||
| 7342 | */ | ||
| 7343 | cache->extents_thresh = ((1024 * 32) / 2) / | ||
| 7344 | sizeof(struct btrfs_free_space); | ||
| 7082 | atomic_set(&cache->count, 1); | 7345 | atomic_set(&cache->count, 1); |
| 7083 | spin_lock_init(&cache->lock); | 7346 | spin_lock_init(&cache->lock); |
| 7084 | spin_lock_init(&cache->tree_lock); | 7347 | spin_lock_init(&cache->tree_lock); |
| 7085 | mutex_init(&cache->cache_mutex); | 7348 | init_waitqueue_head(&cache->caching_q); |
| 7086 | INIT_LIST_HEAD(&cache->list); | 7349 | INIT_LIST_HEAD(&cache->list); |
| 7087 | INIT_LIST_HEAD(&cache->cluster_list); | 7350 | INIT_LIST_HEAD(&cache->cluster_list); |
| 7088 | 7351 | ||
| @@ -7091,6 +7354,12 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, | |||
| 7091 | cache->flags = type; | 7354 | cache->flags = type; |
| 7092 | btrfs_set_block_group_flags(&cache->item, type); | 7355 | btrfs_set_block_group_flags(&cache->item, type); |
| 7093 | 7356 | ||
| 7357 | cache->cached = BTRFS_CACHE_FINISHED; | ||
| 7358 | remove_sb_from_cache(root, cache); | ||
| 7359 | |||
| 7360 | add_new_free_space(cache, root->fs_info, chunk_offset, | ||
| 7361 | chunk_offset + size); | ||
| 7362 | |||
| 7094 | ret = update_space_info(root->fs_info, cache->flags, size, bytes_used, | 7363 | ret = update_space_info(root->fs_info, cache->flags, size, bytes_used, |
| 7095 | &cache->space_info); | 7364 | &cache->space_info); |
| 7096 | BUG_ON(ret); | 7365 | BUG_ON(ret); |
| @@ -7149,7 +7418,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
| 7149 | rb_erase(&block_group->cache_node, | 7418 | rb_erase(&block_group->cache_node, |
| 7150 | &root->fs_info->block_group_cache_tree); | 7419 | &root->fs_info->block_group_cache_tree); |
| 7151 | spin_unlock(&root->fs_info->block_group_cache_lock); | 7420 | spin_unlock(&root->fs_info->block_group_cache_lock); |
| 7152 | btrfs_remove_free_space_cache(block_group); | 7421 | |
| 7153 | down_write(&block_group->space_info->groups_sem); | 7422 | down_write(&block_group->space_info->groups_sem); |
| 7154 | /* | 7423 | /* |
| 7155 | * we must use list_del_init so people can check to see if they | 7424 | * we must use list_del_init so people can check to see if they |
| @@ -7158,11 +7427,18 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
| 7158 | list_del_init(&block_group->list); | 7427 | list_del_init(&block_group->list); |
| 7159 | up_write(&block_group->space_info->groups_sem); | 7428 | up_write(&block_group->space_info->groups_sem); |
| 7160 | 7429 | ||
| 7430 | if (block_group->cached == BTRFS_CACHE_STARTED) | ||
| 7431 | wait_event(block_group->caching_q, | ||
| 7432 | block_group_cache_done(block_group)); | ||
| 7433 | |||
| 7434 | btrfs_remove_free_space_cache(block_group); | ||
| 7435 | |||
| 7161 | spin_lock(&block_group->space_info->lock); | 7436 | spin_lock(&block_group->space_info->lock); |
| 7162 | block_group->space_info->total_bytes -= block_group->key.offset; | 7437 | block_group->space_info->total_bytes -= block_group->key.offset; |
| 7163 | block_group->space_info->bytes_readonly -= block_group->key.offset; | 7438 | block_group->space_info->bytes_readonly -= block_group->key.offset; |
| 7164 | spin_unlock(&block_group->space_info->lock); | 7439 | spin_unlock(&block_group->space_info->lock); |
| 7165 | block_group->space_info->full = 0; | 7440 | |
| 7441 | btrfs_clear_space_info_full(root->fs_info); | ||
| 7166 | 7442 | ||
| 7167 | btrfs_put_block_group(block_group); | 7443 | btrfs_put_block_group(block_group); |
| 7168 | btrfs_put_block_group(block_group); | 7444 | btrfs_put_block_group(block_group); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7c3cd248d8d6..4b833972273a 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
| 25 | #include <linux/smp_lock.h> | ||
| 26 | #include <linux/backing-dev.h> | 25 | #include <linux/backing-dev.h> |
| 27 | #include <linux/mpage.h> | 26 | #include <linux/mpage.h> |
| 28 | #include <linux/swap.h> | 27 | #include <linux/swap.h> |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 4538e48581a5..5edcee3a617f 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -16,45 +16,46 @@ | |||
| 16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/pagemap.h> | ||
| 19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/math64.h> | ||
| 20 | #include "ctree.h" | 22 | #include "ctree.h" |
| 21 | #include "free-space-cache.h" | 23 | #include "free-space-cache.h" |
| 22 | #include "transaction.h" | 24 | #include "transaction.h" |
| 23 | 25 | ||
| 24 | struct btrfs_free_space { | 26 | #define BITS_PER_BITMAP (PAGE_CACHE_SIZE * 8) |
| 25 | struct rb_node bytes_index; | 27 | #define MAX_CACHE_BYTES_PER_GIG (32 * 1024) |
| 26 | struct rb_node offset_index; | ||
| 27 | u64 offset; | ||
| 28 | u64 bytes; | ||
| 29 | }; | ||
| 30 | 28 | ||
| 31 | static int tree_insert_offset(struct rb_root *root, u64 offset, | 29 | static inline unsigned long offset_to_bit(u64 bitmap_start, u64 sectorsize, |
| 32 | struct rb_node *node) | 30 | u64 offset) |
| 33 | { | 31 | { |
| 34 | struct rb_node **p = &root->rb_node; | 32 | BUG_ON(offset < bitmap_start); |
| 35 | struct rb_node *parent = NULL; | 33 | offset -= bitmap_start; |
| 36 | struct btrfs_free_space *info; | 34 | return (unsigned long)(div64_u64(offset, sectorsize)); |
| 35 | } | ||
| 37 | 36 | ||
| 38 | while (*p) { | 37 | static inline unsigned long bytes_to_bits(u64 bytes, u64 sectorsize) |
| 39 | parent = *p; | 38 | { |
| 40 | info = rb_entry(parent, struct btrfs_free_space, offset_index); | 39 | return (unsigned long)(div64_u64(bytes, sectorsize)); |
| 40 | } | ||
| 41 | 41 | ||
| 42 | if (offset < info->offset) | 42 | static inline u64 offset_to_bitmap(struct btrfs_block_group_cache *block_group, |
| 43 | p = &(*p)->rb_left; | 43 | u64 offset) |
| 44 | else if (offset > info->offset) | 44 | { |
| 45 | p = &(*p)->rb_right; | 45 | u64 bitmap_start; |
| 46 | else | 46 | u64 bytes_per_bitmap; |
| 47 | return -EEXIST; | ||
| 48 | } | ||
| 49 | 47 | ||
| 50 | rb_link_node(node, parent, p); | 48 | bytes_per_bitmap = BITS_PER_BITMAP * block_group->sectorsize; |
| 51 | rb_insert_color(node, root); | 49 | bitmap_start = offset - block_group->key.objectid; |
| 50 | bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap); | ||
| 51 | bitmap_start *= bytes_per_bitmap; | ||
| 52 | bitmap_start += block_group->key.objectid; | ||
| 52 | 53 | ||
| 53 | return 0; | 54 | return bitmap_start; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | static int tree_insert_bytes(struct rb_root *root, u64 bytes, | 57 | static int tree_insert_offset(struct rb_root *root, u64 offset, |
| 57 | struct rb_node *node) | 58 | struct rb_node *node, int bitmap) |
| 58 | { | 59 | { |
| 59 | struct rb_node **p = &root->rb_node; | 60 | struct rb_node **p = &root->rb_node; |
| 60 | struct rb_node *parent = NULL; | 61 | struct rb_node *parent = NULL; |
| @@ -62,12 +63,34 @@ static int tree_insert_bytes(struct rb_root *root, u64 bytes, | |||
| 62 | 63 | ||
| 63 | while (*p) { | 64 | while (*p) { |
| 64 | parent = *p; | 65 | parent = *p; |
| 65 | info = rb_entry(parent, struct btrfs_free_space, bytes_index); | 66 | info = rb_entry(parent, struct btrfs_free_space, offset_index); |
| 66 | 67 | ||
| 67 | if (bytes < info->bytes) | 68 | if (offset < info->offset) { |
| 68 | p = &(*p)->rb_left; | 69 | p = &(*p)->rb_left; |
| 69 | else | 70 | } else if (offset > info->offset) { |
| 70 | p = &(*p)->rb_right; | 71 | p = &(*p)->rb_right; |
| 72 | } else { | ||
| 73 | /* | ||
| 74 | * we could have a bitmap entry and an extent entry | ||
| 75 | * share the same offset. If this is the case, we want | ||
| 76 | * the extent entry to always be found first if we do a | ||
| 77 | * linear search through the tree, since we want to have | ||
| 78 | * the quickest allocation time, and allocating from an | ||
| 79 | * extent is faster than allocating from a bitmap. So | ||
| 80 | * if we're inserting a bitmap and we find an entry at | ||
| 81 | * this offset, we want to go right, or after this entry | ||
| 82 | * logically. If we are inserting an extent and we've | ||
| 83 | * found a bitmap, we want to go left, or before | ||
| 84 | * logically. | ||
| 85 | */ | ||
| 86 | if (bitmap) { | ||
| 87 | WARN_ON(info->bitmap); | ||
| 88 | p = &(*p)->rb_right; | ||
| 89 | } else { | ||
| 90 | WARN_ON(!info->bitmap); | ||
| 91 | p = &(*p)->rb_left; | ||
| 92 | } | ||
| 93 | } | ||
| 71 | } | 94 | } |
| 72 | 95 | ||
| 73 | rb_link_node(node, parent, p); | 96 | rb_link_node(node, parent, p); |
| @@ -79,110 +102,143 @@ static int tree_insert_bytes(struct rb_root *root, u64 bytes, | |||
| 79 | /* | 102 | /* |
| 80 | * searches the tree for the given offset. | 103 | * searches the tree for the given offset. |
| 81 | * | 104 | * |
| 82 | * fuzzy == 1: this is used for allocations where we are given a hint of where | 105 | * fuzzy - If this is set, then we are trying to make an allocation, and we just |
| 83 | * to look for free space. Because the hint may not be completely on an offset | 106 | * want a section that has at least bytes size and comes at or after the given |
| 84 | * mark, or the hint may no longer point to free space we need to fudge our | 107 | * offset. |
| 85 | * results a bit. So we look for free space starting at or after offset with at | ||
| 86 | * least bytes size. We prefer to find as close to the given offset as we can. | ||
| 87 | * Also if the offset is within a free space range, then we will return the free | ||
| 88 | * space that contains the given offset, which means we can return a free space | ||
| 89 | * chunk with an offset before the provided offset. | ||
| 90 | * | ||
| 91 | * fuzzy == 0: this is just a normal tree search. Give us the free space that | ||
| 92 | * starts at the given offset which is at least bytes size, and if its not there | ||
| 93 | * return NULL. | ||
| 94 | */ | 108 | */ |
| 95 | static struct btrfs_free_space *tree_search_offset(struct rb_root *root, | 109 | static struct btrfs_free_space * |
| 96 | u64 offset, u64 bytes, | 110 | tree_search_offset(struct btrfs_block_group_cache *block_group, |
| 97 | int fuzzy) | 111 | u64 offset, int bitmap_only, int fuzzy) |
| 98 | { | 112 | { |
| 99 | struct rb_node *n = root->rb_node; | 113 | struct rb_node *n = block_group->free_space_offset.rb_node; |
| 100 | struct btrfs_free_space *entry, *ret = NULL; | 114 | struct btrfs_free_space *entry, *prev = NULL; |
| 115 | |||
| 116 | /* find entry that is closest to the 'offset' */ | ||
| 117 | while (1) { | ||
| 118 | if (!n) { | ||
| 119 | entry = NULL; | ||
| 120 | break; | ||
| 121 | } | ||
| 101 | 122 | ||
| 102 | while (n) { | ||
| 103 | entry = rb_entry(n, struct btrfs_free_space, offset_index); | 123 | entry = rb_entry(n, struct btrfs_free_space, offset_index); |
| 124 | prev = entry; | ||
| 104 | 125 | ||
| 105 | if (offset < entry->offset) { | 126 | if (offset < entry->offset) |
| 106 | if (fuzzy && | ||
| 107 | (!ret || entry->offset < ret->offset) && | ||
| 108 | (bytes <= entry->bytes)) | ||
| 109 | ret = entry; | ||
| 110 | n = n->rb_left; | 127 | n = n->rb_left; |
| 111 | } else if (offset > entry->offset) { | 128 | else if (offset > entry->offset) |
| 112 | if (fuzzy && | ||
| 113 | (entry->offset + entry->bytes - 1) >= offset && | ||
| 114 | bytes <= entry->bytes) { | ||
| 115 | ret = entry; | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | n = n->rb_right; | 129 | n = n->rb_right; |
| 119 | } else { | 130 | else |
| 120 | if (bytes > entry->bytes) { | ||
| 121 | n = n->rb_right; | ||
| 122 | continue; | ||
| 123 | } | ||
| 124 | ret = entry; | ||
| 125 | break; | 131 | break; |
| 126 | } | ||
| 127 | } | 132 | } |
| 128 | 133 | ||
| 129 | return ret; | 134 | if (bitmap_only) { |
| 130 | } | 135 | if (!entry) |
| 136 | return NULL; | ||
| 137 | if (entry->bitmap) | ||
| 138 | return entry; | ||
| 131 | 139 | ||
| 132 | /* | 140 | /* |
| 133 | * return a chunk at least bytes size, as close to offset that we can get. | 141 | * bitmap entry and extent entry may share same offset, |
| 134 | */ | 142 | * in that case, bitmap entry comes after extent entry. |
| 135 | static struct btrfs_free_space *tree_search_bytes(struct rb_root *root, | 143 | */ |
| 136 | u64 offset, u64 bytes) | 144 | n = rb_next(n); |
| 137 | { | 145 | if (!n) |
| 138 | struct rb_node *n = root->rb_node; | 146 | return NULL; |
| 139 | struct btrfs_free_space *entry, *ret = NULL; | 147 | entry = rb_entry(n, struct btrfs_free_space, offset_index); |
| 140 | 148 | if (entry->offset != offset) | |
| 141 | while (n) { | 149 | return NULL; |
| 142 | entry = rb_entry(n, struct btrfs_free_space, bytes_index); | ||
| 143 | 150 | ||
| 144 | if (bytes < entry->bytes) { | 151 | WARN_ON(!entry->bitmap); |
| 152 | return entry; | ||
| 153 | } else if (entry) { | ||
| 154 | if (entry->bitmap) { | ||
| 145 | /* | 155 | /* |
| 146 | * We prefer to get a hole size as close to the size we | 156 | * if previous extent entry covers the offset, |
| 147 | * are asking for so we don't take small slivers out of | 157 | * we should return it instead of the bitmap entry |
| 148 | * huge holes, but we also want to get as close to the | ||
| 149 | * offset as possible so we don't have a whole lot of | ||
| 150 | * fragmentation. | ||
| 151 | */ | 158 | */ |
| 152 | if (offset <= entry->offset) { | 159 | n = &entry->offset_index; |
| 153 | if (!ret) | 160 | while (1) { |
| 154 | ret = entry; | 161 | n = rb_prev(n); |
| 155 | else if (entry->bytes < ret->bytes) | 162 | if (!n) |
| 156 | ret = entry; | 163 | break; |
| 157 | else if (entry->offset < ret->offset) | 164 | prev = rb_entry(n, struct btrfs_free_space, |
| 158 | ret = entry; | 165 | offset_index); |
| 166 | if (!prev->bitmap) { | ||
| 167 | if (prev->offset + prev->bytes > offset) | ||
| 168 | entry = prev; | ||
| 169 | break; | ||
| 170 | } | ||
| 159 | } | 171 | } |
| 160 | n = n->rb_left; | 172 | } |
| 161 | } else if (bytes > entry->bytes) { | 173 | return entry; |
| 162 | n = n->rb_right; | 174 | } |
| 175 | |||
| 176 | if (!prev) | ||
| 177 | return NULL; | ||
| 178 | |||
| 179 | /* find last entry before the 'offset' */ | ||
| 180 | entry = prev; | ||
| 181 | if (entry->offset > offset) { | ||
| 182 | n = rb_prev(&entry->offset_index); | ||
| 183 | if (n) { | ||
| 184 | entry = rb_entry(n, struct btrfs_free_space, | ||
| 185 | offset_index); | ||
| 186 | BUG_ON(entry->offset > offset); | ||
| 163 | } else { | 187 | } else { |
| 164 | /* | 188 | if (fuzzy) |
| 165 | * Ok we may have multiple chunks of the wanted size, | 189 | return entry; |
| 166 | * so we don't want to take the first one we find, we | 190 | else |
| 167 | * want to take the one closest to our given offset, so | 191 | return NULL; |
| 168 | * keep searching just in case theres a better match. | ||
| 169 | */ | ||
| 170 | n = n->rb_right; | ||
| 171 | if (offset > entry->offset) | ||
| 172 | continue; | ||
| 173 | else if (!ret || entry->offset < ret->offset) | ||
| 174 | ret = entry; | ||
| 175 | } | 192 | } |
| 176 | } | 193 | } |
| 177 | 194 | ||
| 178 | return ret; | 195 | if (entry->bitmap) { |
| 196 | n = &entry->offset_index; | ||
| 197 | while (1) { | ||
| 198 | n = rb_prev(n); | ||
| 199 | if (!n) | ||
| 200 | break; | ||
| 201 | prev = rb_entry(n, struct btrfs_free_space, | ||
| 202 | offset_index); | ||
| 203 | if (!prev->bitmap) { | ||
| 204 | if (prev->offset + prev->bytes > offset) | ||
| 205 | return prev; | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | if (entry->offset + BITS_PER_BITMAP * | ||
| 210 | block_group->sectorsize > offset) | ||
| 211 | return entry; | ||
| 212 | } else if (entry->offset + entry->bytes > offset) | ||
| 213 | return entry; | ||
| 214 | |||
| 215 | if (!fuzzy) | ||
| 216 | return NULL; | ||
| 217 | |||
| 218 | while (1) { | ||
| 219 | if (entry->bitmap) { | ||
| 220 | if (entry->offset + BITS_PER_BITMAP * | ||
| 221 | block_group->sectorsize > offset) | ||
| 222 | break; | ||
| 223 | } else { | ||
| 224 | if (entry->offset + entry->bytes > offset) | ||
| 225 | break; | ||
| 226 | } | ||
| 227 | |||
| 228 | n = rb_next(&entry->offset_index); | ||
| 229 | if (!n) | ||
| 230 | return NULL; | ||
| 231 | entry = rb_entry(n, struct btrfs_free_space, offset_index); | ||
| 232 | } | ||
| 233 | return entry; | ||
| 179 | } | 234 | } |
| 180 | 235 | ||
| 181 | static void unlink_free_space(struct btrfs_block_group_cache *block_group, | 236 | static void unlink_free_space(struct btrfs_block_group_cache *block_group, |
| 182 | struct btrfs_free_space *info) | 237 | struct btrfs_free_space *info) |
| 183 | { | 238 | { |
| 184 | rb_erase(&info->offset_index, &block_group->free_space_offset); | 239 | rb_erase(&info->offset_index, &block_group->free_space_offset); |
| 185 | rb_erase(&info->bytes_index, &block_group->free_space_bytes); | 240 | block_group->free_extents--; |
| 241 | block_group->free_space -= info->bytes; | ||
| 186 | } | 242 | } |
| 187 | 243 | ||
| 188 | static int link_free_space(struct btrfs_block_group_cache *block_group, | 244 | static int link_free_space(struct btrfs_block_group_cache *block_group, |
| @@ -190,17 +246,353 @@ static int link_free_space(struct btrfs_block_group_cache *block_group, | |||
| 190 | { | 246 | { |
| 191 | int ret = 0; | 247 | int ret = 0; |
| 192 | 248 | ||
| 193 | 249 | BUG_ON(!info->bitmap && !info->bytes); | |
| 194 | BUG_ON(!info->bytes); | ||
| 195 | ret = tree_insert_offset(&block_group->free_space_offset, info->offset, | 250 | ret = tree_insert_offset(&block_group->free_space_offset, info->offset, |
| 196 | &info->offset_index); | 251 | &info->offset_index, (info->bitmap != NULL)); |
| 197 | if (ret) | 252 | if (ret) |
| 198 | return ret; | 253 | return ret; |
| 199 | 254 | ||
| 200 | ret = tree_insert_bytes(&block_group->free_space_bytes, info->bytes, | 255 | block_group->free_space += info->bytes; |
| 201 | &info->bytes_index); | 256 | block_group->free_extents++; |
| 202 | if (ret) | 257 | return ret; |
| 203 | return ret; | 258 | } |
| 259 | |||
| 260 | static void recalculate_thresholds(struct btrfs_block_group_cache *block_group) | ||
| 261 | { | ||
| 262 | u64 max_bytes, possible_bytes; | ||
| 263 | |||
| 264 | /* | ||
| 265 | * The goal is to keep the total amount of memory used per 1gb of space | ||
| 266 | * at or below 32k, so we need to adjust how much memory we allow to be | ||
| 267 | * used by extent based free space tracking | ||
| 268 | */ | ||
| 269 | max_bytes = MAX_CACHE_BYTES_PER_GIG * | ||
| 270 | (div64_u64(block_group->key.offset, 1024 * 1024 * 1024)); | ||
| 271 | |||
| 272 | possible_bytes = (block_group->total_bitmaps * PAGE_CACHE_SIZE) + | ||
| 273 | (sizeof(struct btrfs_free_space) * | ||
| 274 | block_group->extents_thresh); | ||
| 275 | |||
| 276 | if (possible_bytes > max_bytes) { | ||
| 277 | int extent_bytes = max_bytes - | ||
| 278 | (block_group->total_bitmaps * PAGE_CACHE_SIZE); | ||
| 279 | |||
| 280 | if (extent_bytes <= 0) { | ||
| 281 | block_group->extents_thresh = 0; | ||
| 282 | return; | ||
| 283 | } | ||
| 284 | |||
| 285 | block_group->extents_thresh = extent_bytes / | ||
| 286 | (sizeof(struct btrfs_free_space)); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | static void bitmap_clear_bits(struct btrfs_block_group_cache *block_group, | ||
| 291 | struct btrfs_free_space *info, u64 offset, | ||
| 292 | u64 bytes) | ||
| 293 | { | ||
| 294 | unsigned long start, end; | ||
| 295 | unsigned long i; | ||
| 296 | |||
| 297 | start = offset_to_bit(info->offset, block_group->sectorsize, offset); | ||
| 298 | end = start + bytes_to_bits(bytes, block_group->sectorsize); | ||
| 299 | BUG_ON(end > BITS_PER_BITMAP); | ||
| 300 | |||
| 301 | for (i = start; i < end; i++) | ||
| 302 | clear_bit(i, info->bitmap); | ||
| 303 | |||
| 304 | info->bytes -= bytes; | ||
| 305 | block_group->free_space -= bytes; | ||
| 306 | } | ||
| 307 | |||
| 308 | static void bitmap_set_bits(struct btrfs_block_group_cache *block_group, | ||
| 309 | struct btrfs_free_space *info, u64 offset, | ||
| 310 | u64 bytes) | ||
| 311 | { | ||
| 312 | unsigned long start, end; | ||
| 313 | unsigned long i; | ||
| 314 | |||
| 315 | start = offset_to_bit(info->offset, block_group->sectorsize, offset); | ||
| 316 | end = start + bytes_to_bits(bytes, block_group->sectorsize); | ||
| 317 | BUG_ON(end > BITS_PER_BITMAP); | ||
| 318 | |||
| 319 | for (i = start; i < end; i++) | ||
| 320 | set_bit(i, info->bitmap); | ||
| 321 | |||
| 322 | info->bytes += bytes; | ||
| 323 | block_group->free_space += bytes; | ||
| 324 | } | ||
| 325 | |||
| 326 | static int search_bitmap(struct btrfs_block_group_cache *block_group, | ||
| 327 | struct btrfs_free_space *bitmap_info, u64 *offset, | ||
| 328 | u64 *bytes) | ||
| 329 | { | ||
| 330 | unsigned long found_bits = 0; | ||
| 331 | unsigned long bits, i; | ||
| 332 | unsigned long next_zero; | ||
| 333 | |||
| 334 | i = offset_to_bit(bitmap_info->offset, block_group->sectorsize, | ||
| 335 | max_t(u64, *offset, bitmap_info->offset)); | ||
| 336 | bits = bytes_to_bits(*bytes, block_group->sectorsize); | ||
| 337 | |||
| 338 | for (i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i); | ||
| 339 | i < BITS_PER_BITMAP; | ||
| 340 | i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i + 1)) { | ||
| 341 | next_zero = find_next_zero_bit(bitmap_info->bitmap, | ||
| 342 | BITS_PER_BITMAP, i); | ||
| 343 | if ((next_zero - i) >= bits) { | ||
| 344 | found_bits = next_zero - i; | ||
| 345 | break; | ||
| 346 | } | ||
| 347 | i = next_zero; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (found_bits) { | ||
| 351 | *offset = (u64)(i * block_group->sectorsize) + | ||
| 352 | bitmap_info->offset; | ||
| 353 | *bytes = (u64)(found_bits) * block_group->sectorsize; | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | return -1; | ||
| 358 | } | ||
| 359 | |||
| 360 | static struct btrfs_free_space *find_free_space(struct btrfs_block_group_cache | ||
| 361 | *block_group, u64 *offset, | ||
| 362 | u64 *bytes, int debug) | ||
| 363 | { | ||
| 364 | struct btrfs_free_space *entry; | ||
| 365 | struct rb_node *node; | ||
| 366 | int ret; | ||
| 367 | |||
| 368 | if (!block_group->free_space_offset.rb_node) | ||
| 369 | return NULL; | ||
| 370 | |||
| 371 | entry = tree_search_offset(block_group, | ||
| 372 | offset_to_bitmap(block_group, *offset), | ||
| 373 | 0, 1); | ||
| 374 | if (!entry) | ||
| 375 | return NULL; | ||
| 376 | |||
| 377 | for (node = &entry->offset_index; node; node = rb_next(node)) { | ||
| 378 | entry = rb_entry(node, struct btrfs_free_space, offset_index); | ||
| 379 | if (entry->bytes < *bytes) | ||
| 380 | continue; | ||
| 381 | |||
| 382 | if (entry->bitmap) { | ||
| 383 | ret = search_bitmap(block_group, entry, offset, bytes); | ||
| 384 | if (!ret) | ||
| 385 | return entry; | ||
| 386 | continue; | ||
| 387 | } | ||
| 388 | |||
| 389 | *offset = entry->offset; | ||
| 390 | *bytes = entry->bytes; | ||
| 391 | return entry; | ||
| 392 | } | ||
| 393 | |||
| 394 | return NULL; | ||
| 395 | } | ||
| 396 | |||
| 397 | static void add_new_bitmap(struct btrfs_block_group_cache *block_group, | ||
| 398 | struct btrfs_free_space *info, u64 offset) | ||
| 399 | { | ||
| 400 | u64 bytes_per_bg = BITS_PER_BITMAP * block_group->sectorsize; | ||
| 401 | int max_bitmaps = (int)div64_u64(block_group->key.offset + | ||
| 402 | bytes_per_bg - 1, bytes_per_bg); | ||
| 403 | BUG_ON(block_group->total_bitmaps >= max_bitmaps); | ||
| 404 | |||
| 405 | info->offset = offset_to_bitmap(block_group, offset); | ||
| 406 | link_free_space(block_group, info); | ||
| 407 | block_group->total_bitmaps++; | ||
| 408 | |||
| 409 | recalculate_thresholds(block_group); | ||
| 410 | } | ||
| 411 | |||
| 412 | static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_group, | ||
| 413 | struct btrfs_free_space *bitmap_info, | ||
| 414 | u64 *offset, u64 *bytes) | ||
| 415 | { | ||
| 416 | u64 end; | ||
| 417 | u64 search_start, search_bytes; | ||
| 418 | int ret; | ||
| 419 | |||
| 420 | again: | ||
| 421 | end = bitmap_info->offset + | ||
| 422 | (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1; | ||
| 423 | |||
| 424 | /* | ||
| 425 | * XXX - this can go away after a few releases. | ||
| 426 | * | ||
| 427 | * since the only user of btrfs_remove_free_space is the tree logging | ||
| 428 | * stuff, and the only way to test that is under crash conditions, we | ||
| 429 | * want to have this debug stuff here just in case somethings not | ||
| 430 | * working. Search the bitmap for the space we are trying to use to | ||
| 431 | * make sure its actually there. If its not there then we need to stop | ||
| 432 | * because something has gone wrong. | ||
| 433 | */ | ||
| 434 | search_start = *offset; | ||
| 435 | search_bytes = *bytes; | ||
| 436 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 437 | &search_bytes); | ||
| 438 | BUG_ON(ret < 0 || search_start != *offset); | ||
| 439 | |||
| 440 | if (*offset > bitmap_info->offset && *offset + *bytes > end) { | ||
| 441 | bitmap_clear_bits(block_group, bitmap_info, *offset, | ||
| 442 | end - *offset + 1); | ||
| 443 | *bytes -= end - *offset + 1; | ||
| 444 | *offset = end + 1; | ||
| 445 | } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) { | ||
| 446 | bitmap_clear_bits(block_group, bitmap_info, *offset, *bytes); | ||
| 447 | *bytes = 0; | ||
| 448 | } | ||
| 449 | |||
| 450 | if (*bytes) { | ||
| 451 | struct rb_node *next = rb_next(&bitmap_info->offset_index); | ||
| 452 | if (!bitmap_info->bytes) { | ||
| 453 | unlink_free_space(block_group, bitmap_info); | ||
| 454 | kfree(bitmap_info->bitmap); | ||
| 455 | kfree(bitmap_info); | ||
| 456 | block_group->total_bitmaps--; | ||
| 457 | recalculate_thresholds(block_group); | ||
| 458 | } | ||
| 459 | |||
| 460 | /* | ||
| 461 | * no entry after this bitmap, but we still have bytes to | ||
| 462 | * remove, so something has gone wrong. | ||
| 463 | */ | ||
| 464 | if (!next) | ||
| 465 | return -EINVAL; | ||
| 466 | |||
| 467 | bitmap_info = rb_entry(next, struct btrfs_free_space, | ||
| 468 | offset_index); | ||
| 469 | |||
| 470 | /* | ||
| 471 | * if the next entry isn't a bitmap we need to return to let the | ||
| 472 | * extent stuff do its work. | ||
| 473 | */ | ||
| 474 | if (!bitmap_info->bitmap) | ||
| 475 | return -EAGAIN; | ||
| 476 | |||
| 477 | /* | ||
| 478 | * Ok the next item is a bitmap, but it may not actually hold | ||
| 479 | * the information for the rest of this free space stuff, so | ||
| 480 | * look for it, and if we don't find it return so we can try | ||
| 481 | * everything over again. | ||
| 482 | */ | ||
| 483 | search_start = *offset; | ||
| 484 | search_bytes = *bytes; | ||
| 485 | ret = search_bitmap(block_group, bitmap_info, &search_start, | ||
| 486 | &search_bytes); | ||
| 487 | if (ret < 0 || search_start != *offset) | ||
| 488 | return -EAGAIN; | ||
| 489 | |||
| 490 | goto again; | ||
| 491 | } else if (!bitmap_info->bytes) { | ||
| 492 | unlink_free_space(block_group, bitmap_info); | ||
| 493 | kfree(bitmap_info->bitmap); | ||
| 494 | kfree(bitmap_info); | ||
| 495 | block_group->total_bitmaps--; | ||
| 496 | recalculate_thresholds(block_group); | ||
| 497 | } | ||
| 498 | |||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | static int insert_into_bitmap(struct btrfs_block_group_cache *block_group, | ||
| 503 | struct btrfs_free_space *info) | ||
| 504 | { | ||
| 505 | struct btrfs_free_space *bitmap_info; | ||
| 506 | int added = 0; | ||
| 507 | u64 bytes, offset, end; | ||
| 508 | int ret; | ||
| 509 | |||
| 510 | /* | ||
| 511 | * If we are below the extents threshold then we can add this as an | ||
| 512 | * extent, and don't have to deal with the bitmap | ||
| 513 | */ | ||
| 514 | if (block_group->free_extents < block_group->extents_thresh && | ||
| 515 | info->bytes > block_group->sectorsize * 4) | ||
| 516 | return 0; | ||
| 517 | |||
| 518 | /* | ||
| 519 | * some block groups are so tiny they can't be enveloped by a bitmap, so | ||
| 520 | * don't even bother to create a bitmap for this | ||
| 521 | */ | ||
| 522 | if (BITS_PER_BITMAP * block_group->sectorsize > | ||
| 523 | block_group->key.offset) | ||
| 524 | return 0; | ||
| 525 | |||
| 526 | bytes = info->bytes; | ||
| 527 | offset = info->offset; | ||
| 528 | |||
| 529 | again: | ||
| 530 | bitmap_info = tree_search_offset(block_group, | ||
| 531 | offset_to_bitmap(block_group, offset), | ||
| 532 | 1, 0); | ||
| 533 | if (!bitmap_info) { | ||
| 534 | BUG_ON(added); | ||
| 535 | goto new_bitmap; | ||
| 536 | } | ||
| 537 | |||
| 538 | end = bitmap_info->offset + | ||
| 539 | (u64)(BITS_PER_BITMAP * block_group->sectorsize); | ||
| 540 | |||
| 541 | if (offset >= bitmap_info->offset && offset + bytes > end) { | ||
| 542 | bitmap_set_bits(block_group, bitmap_info, offset, | ||
| 543 | end - offset); | ||
| 544 | bytes -= end - offset; | ||
| 545 | offset = end; | ||
| 546 | added = 0; | ||
| 547 | } else if (offset >= bitmap_info->offset && offset + bytes <= end) { | ||
| 548 | bitmap_set_bits(block_group, bitmap_info, offset, bytes); | ||
| 549 | bytes = 0; | ||
| 550 | } else { | ||
| 551 | BUG(); | ||
| 552 | } | ||
| 553 | |||
| 554 | if (!bytes) { | ||
| 555 | ret = 1; | ||
| 556 | goto out; | ||
| 557 | } else | ||
| 558 | goto again; | ||
| 559 | |||
| 560 | new_bitmap: | ||
| 561 | if (info && info->bitmap) { | ||
| 562 | add_new_bitmap(block_group, info, offset); | ||
| 563 | added = 1; | ||
| 564 | info = NULL; | ||
| 565 | goto again; | ||
| 566 | } else { | ||
| 567 | spin_unlock(&block_group->tree_lock); | ||
| 568 | |||
| 569 | /* no pre-allocated info, allocate a new one */ | ||
| 570 | if (!info) { | ||
| 571 | info = kzalloc(sizeof(struct btrfs_free_space), | ||
| 572 | GFP_NOFS); | ||
| 573 | if (!info) { | ||
| 574 | spin_lock(&block_group->tree_lock); | ||
| 575 | ret = -ENOMEM; | ||
| 576 | goto out; | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 580 | /* allocate the bitmap */ | ||
| 581 | info->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS); | ||
| 582 | spin_lock(&block_group->tree_lock); | ||
| 583 | if (!info->bitmap) { | ||
| 584 | ret = -ENOMEM; | ||
| 585 | goto out; | ||
| 586 | } | ||
| 587 | goto again; | ||
| 588 | } | ||
| 589 | |||
| 590 | out: | ||
| 591 | if (info) { | ||
| 592 | if (info->bitmap) | ||
| 593 | kfree(info->bitmap); | ||
| 594 | kfree(info); | ||
| 595 | } | ||
| 204 | 596 | ||
| 205 | return ret; | 597 | return ret; |
| 206 | } | 598 | } |
| @@ -208,8 +600,8 @@ static int link_free_space(struct btrfs_block_group_cache *block_group, | |||
| 208 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | 600 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, |
| 209 | u64 offset, u64 bytes) | 601 | u64 offset, u64 bytes) |
| 210 | { | 602 | { |
| 211 | struct btrfs_free_space *right_info; | 603 | struct btrfs_free_space *right_info = NULL; |
| 212 | struct btrfs_free_space *left_info; | 604 | struct btrfs_free_space *left_info = NULL; |
| 213 | struct btrfs_free_space *info = NULL; | 605 | struct btrfs_free_space *info = NULL; |
| 214 | int ret = 0; | 606 | int ret = 0; |
| 215 | 607 | ||
| @@ -227,18 +619,38 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | |||
| 227 | * are adding, if there is remove that struct and add a new one to | 619 | * are adding, if there is remove that struct and add a new one to |
| 228 | * cover the entire range | 620 | * cover the entire range |
| 229 | */ | 621 | */ |
| 230 | right_info = tree_search_offset(&block_group->free_space_offset, | 622 | right_info = tree_search_offset(block_group, offset + bytes, 0, 0); |
| 231 | offset+bytes, 0, 0); | 623 | if (right_info && rb_prev(&right_info->offset_index)) |
| 232 | left_info = tree_search_offset(&block_group->free_space_offset, | 624 | left_info = rb_entry(rb_prev(&right_info->offset_index), |
| 233 | offset-1, 0, 1); | 625 | struct btrfs_free_space, offset_index); |
| 626 | else | ||
| 627 | left_info = tree_search_offset(block_group, offset - 1, 0, 0); | ||
| 628 | |||
| 629 | /* | ||
| 630 | * If there was no extent directly to the left or right of this new | ||
| 631 | * extent then we know we're going to have to allocate a new extent, so | ||
| 632 | * before we do that see if we need to drop this into a bitmap | ||
| 633 | */ | ||
| 634 | if ((!left_info || left_info->bitmap) && | ||
| 635 | (!right_info || right_info->bitmap)) { | ||
| 636 | ret = insert_into_bitmap(block_group, info); | ||
| 637 | |||
| 638 | if (ret < 0) { | ||
| 639 | goto out; | ||
| 640 | } else if (ret) { | ||
| 641 | ret = 0; | ||
| 642 | goto out; | ||
| 643 | } | ||
| 644 | } | ||
| 234 | 645 | ||
| 235 | if (right_info) { | 646 | if (right_info && !right_info->bitmap) { |
| 236 | unlink_free_space(block_group, right_info); | 647 | unlink_free_space(block_group, right_info); |
| 237 | info->bytes += right_info->bytes; | 648 | info->bytes += right_info->bytes; |
| 238 | kfree(right_info); | 649 | kfree(right_info); |
| 239 | } | 650 | } |
| 240 | 651 | ||
| 241 | if (left_info && left_info->offset + left_info->bytes == offset) { | 652 | if (left_info && !left_info->bitmap && |
| 653 | left_info->offset + left_info->bytes == offset) { | ||
| 242 | unlink_free_space(block_group, left_info); | 654 | unlink_free_space(block_group, left_info); |
| 243 | info->offset = left_info->offset; | 655 | info->offset = left_info->offset; |
| 244 | info->bytes += left_info->bytes; | 656 | info->bytes += left_info->bytes; |
| @@ -248,11 +660,11 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | |||
| 248 | ret = link_free_space(block_group, info); | 660 | ret = link_free_space(block_group, info); |
| 249 | if (ret) | 661 | if (ret) |
| 250 | kfree(info); | 662 | kfree(info); |
| 251 | 663 | out: | |
| 252 | spin_unlock(&block_group->tree_lock); | 664 | spin_unlock(&block_group->tree_lock); |
| 253 | 665 | ||
| 254 | if (ret) { | 666 | if (ret) { |
| 255 | printk(KERN_ERR "btrfs: unable to add free space :%d\n", ret); | 667 | printk(KERN_CRIT "btrfs: unable to add free space :%d\n", ret); |
| 256 | BUG_ON(ret == -EEXIST); | 668 | BUG_ON(ret == -EEXIST); |
| 257 | } | 669 | } |
| 258 | 670 | ||
| @@ -263,40 +675,74 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
| 263 | u64 offset, u64 bytes) | 675 | u64 offset, u64 bytes) |
| 264 | { | 676 | { |
| 265 | struct btrfs_free_space *info; | 677 | struct btrfs_free_space *info; |
| 678 | struct btrfs_free_space *next_info = NULL; | ||
| 266 | int ret = 0; | 679 | int ret = 0; |
| 267 | 680 | ||
| 268 | spin_lock(&block_group->tree_lock); | 681 | spin_lock(&block_group->tree_lock); |
| 269 | 682 | ||
| 270 | info = tree_search_offset(&block_group->free_space_offset, offset, 0, | 683 | again: |
| 271 | 1); | 684 | info = tree_search_offset(block_group, offset, 0, 0); |
| 272 | if (info && info->offset == offset) { | 685 | if (!info) { |
| 273 | if (info->bytes < bytes) { | 686 | /* |
| 274 | printk(KERN_ERR "Found free space at %llu, size %llu," | 687 | * oops didn't find an extent that matched the space we wanted |
| 275 | "trying to use %llu\n", | 688 | * to remove, look for a bitmap instead |
| 276 | (unsigned long long)info->offset, | 689 | */ |
| 277 | (unsigned long long)info->bytes, | 690 | info = tree_search_offset(block_group, |
| 278 | (unsigned long long)bytes); | 691 | offset_to_bitmap(block_group, offset), |
| 692 | 1, 0); | ||
| 693 | if (!info) { | ||
| 694 | WARN_ON(1); | ||
| 695 | goto out_lock; | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 699 | if (info->bytes < bytes && rb_next(&info->offset_index)) { | ||
| 700 | u64 end; | ||
| 701 | next_info = rb_entry(rb_next(&info->offset_index), | ||
| 702 | struct btrfs_free_space, | ||
| 703 | offset_index); | ||
| 704 | |||
| 705 | if (next_info->bitmap) | ||
| 706 | end = next_info->offset + BITS_PER_BITMAP * | ||
| 707 | block_group->sectorsize - 1; | ||
| 708 | else | ||
| 709 | end = next_info->offset + next_info->bytes; | ||
| 710 | |||
| 711 | if (next_info->bytes < bytes || | ||
| 712 | next_info->offset > offset || offset > end) { | ||
| 713 | printk(KERN_CRIT "Found free space at %llu, size %llu," | ||
| 714 | " trying to use %llu\n", | ||
| 715 | (unsigned long long)info->offset, | ||
| 716 | (unsigned long long)info->bytes, | ||
| 717 | (unsigned long long)bytes); | ||
| 279 | WARN_ON(1); | 718 | WARN_ON(1); |
| 280 | ret = -EINVAL; | 719 | ret = -EINVAL; |
| 281 | spin_unlock(&block_group->tree_lock); | 720 | goto out_lock; |
| 282 | goto out; | ||
| 283 | } | 721 | } |
| 284 | unlink_free_space(block_group, info); | ||
| 285 | 722 | ||
| 286 | if (info->bytes == bytes) { | 723 | info = next_info; |
| 287 | kfree(info); | 724 | } |
| 288 | spin_unlock(&block_group->tree_lock); | 725 | |
| 289 | goto out; | 726 | if (info->bytes == bytes) { |
| 727 | unlink_free_space(block_group, info); | ||
| 728 | if (info->bitmap) { | ||
| 729 | kfree(info->bitmap); | ||
| 730 | block_group->total_bitmaps--; | ||
| 290 | } | 731 | } |
| 732 | kfree(info); | ||
| 733 | goto out_lock; | ||
| 734 | } | ||
| 291 | 735 | ||
| 736 | if (!info->bitmap && info->offset == offset) { | ||
| 737 | unlink_free_space(block_group, info); | ||
| 292 | info->offset += bytes; | 738 | info->offset += bytes; |
| 293 | info->bytes -= bytes; | 739 | info->bytes -= bytes; |
| 740 | link_free_space(block_group, info); | ||
| 741 | goto out_lock; | ||
| 742 | } | ||
| 294 | 743 | ||
| 295 | ret = link_free_space(block_group, info); | 744 | if (!info->bitmap && info->offset <= offset && |
| 296 | spin_unlock(&block_group->tree_lock); | 745 | info->offset + info->bytes >= offset + bytes) { |
| 297 | BUG_ON(ret); | ||
| 298 | } else if (info && info->offset < offset && | ||
| 299 | info->offset + info->bytes >= offset + bytes) { | ||
| 300 | u64 old_start = info->offset; | 746 | u64 old_start = info->offset; |
| 301 | /* | 747 | /* |
| 302 | * we're freeing space in the middle of the info, | 748 | * we're freeing space in the middle of the info, |
| @@ -312,7 +758,9 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
| 312 | info->offset = offset + bytes; | 758 | info->offset = offset + bytes; |
| 313 | info->bytes = old_end - info->offset; | 759 | info->bytes = old_end - info->offset; |
| 314 | ret = link_free_space(block_group, info); | 760 | ret = link_free_space(block_group, info); |
| 315 | BUG_ON(ret); | 761 | WARN_ON(ret); |
| 762 | if (ret) | ||
| 763 | goto out_lock; | ||
| 316 | } else { | 764 | } else { |
| 317 | /* the hole we're creating ends at the end | 765 | /* the hole we're creating ends at the end |
| 318 | * of the info struct, just free the info | 766 | * of the info struct, just free the info |
| @@ -320,32 +768,22 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
| 320 | kfree(info); | 768 | kfree(info); |
| 321 | } | 769 | } |
| 322 | spin_unlock(&block_group->tree_lock); | 770 | spin_unlock(&block_group->tree_lock); |
| 323 | /* step two, insert a new info struct to cover anything | 771 | |
| 324 | * before the hole | 772 | /* step two, insert a new info struct to cover |
| 773 | * anything before the hole | ||
| 325 | */ | 774 | */ |
| 326 | ret = btrfs_add_free_space(block_group, old_start, | 775 | ret = btrfs_add_free_space(block_group, old_start, |
| 327 | offset - old_start); | 776 | offset - old_start); |
| 328 | BUG_ON(ret); | 777 | WARN_ON(ret); |
| 329 | } else { | 778 | goto out; |
| 330 | spin_unlock(&block_group->tree_lock); | ||
| 331 | if (!info) { | ||
| 332 | printk(KERN_ERR "couldn't find space %llu to free\n", | ||
| 333 | (unsigned long long)offset); | ||
| 334 | printk(KERN_ERR "cached is %d, offset %llu bytes %llu\n", | ||
| 335 | block_group->cached, | ||
| 336 | (unsigned long long)block_group->key.objectid, | ||
| 337 | (unsigned long long)block_group->key.offset); | ||
| 338 | btrfs_dump_free_space(block_group, bytes); | ||
| 339 | } else if (info) { | ||
| 340 | printk(KERN_ERR "hmm, found offset=%llu bytes=%llu, " | ||
| 341 | "but wanted offset=%llu bytes=%llu\n", | ||
| 342 | (unsigned long long)info->offset, | ||
| 343 | (unsigned long long)info->bytes, | ||
| 344 | (unsigned long long)offset, | ||
| 345 | (unsigned long long)bytes); | ||
| 346 | } | ||
| 347 | WARN_ON(1); | ||
| 348 | } | 779 | } |
| 780 | |||
| 781 | ret = remove_from_bitmap(block_group, info, &offset, &bytes); | ||
| 782 | if (ret == -EAGAIN) | ||
| 783 | goto again; | ||
| 784 | BUG_ON(ret); | ||
| 785 | out_lock: | ||
| 786 | spin_unlock(&block_group->tree_lock); | ||
| 349 | out: | 787 | out: |
| 350 | return ret; | 788 | return ret; |
| 351 | } | 789 | } |
| @@ -361,10 +799,13 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, | |||
| 361 | info = rb_entry(n, struct btrfs_free_space, offset_index); | 799 | info = rb_entry(n, struct btrfs_free_space, offset_index); |
| 362 | if (info->bytes >= bytes) | 800 | if (info->bytes >= bytes) |
| 363 | count++; | 801 | count++; |
| 364 | printk(KERN_ERR "entry offset %llu, bytes %llu\n", | 802 | printk(KERN_CRIT "entry offset %llu, bytes %llu, bitmap %s\n", |
| 365 | (unsigned long long)info->offset, | 803 | (unsigned long long)info->offset, |
| 366 | (unsigned long long)info->bytes); | 804 | (unsigned long long)info->bytes, |
| 805 | (info->bitmap) ? "yes" : "no"); | ||
| 367 | } | 806 | } |
| 807 | printk(KERN_INFO "block group has cluster?: %s\n", | ||
| 808 | list_empty(&block_group->cluster_list) ? "no" : "yes"); | ||
| 368 | printk(KERN_INFO "%d blocks of free space at or bigger than bytes is" | 809 | printk(KERN_INFO "%d blocks of free space at or bigger than bytes is" |
| 369 | "\n", count); | 810 | "\n", count); |
| 370 | } | 811 | } |
| @@ -397,26 +838,35 @@ __btrfs_return_cluster_to_free_space( | |||
| 397 | { | 838 | { |
| 398 | struct btrfs_free_space *entry; | 839 | struct btrfs_free_space *entry; |
| 399 | struct rb_node *node; | 840 | struct rb_node *node; |
| 841 | bool bitmap; | ||
| 400 | 842 | ||
| 401 | spin_lock(&cluster->lock); | 843 | spin_lock(&cluster->lock); |
| 402 | if (cluster->block_group != block_group) | 844 | if (cluster->block_group != block_group) |
| 403 | goto out; | 845 | goto out; |
| 404 | 846 | ||
| 847 | bitmap = cluster->points_to_bitmap; | ||
| 848 | cluster->block_group = NULL; | ||
| 405 | cluster->window_start = 0; | 849 | cluster->window_start = 0; |
| 850 | list_del_init(&cluster->block_group_list); | ||
| 851 | cluster->points_to_bitmap = false; | ||
| 852 | |||
| 853 | if (bitmap) | ||
| 854 | goto out; | ||
| 855 | |||
| 406 | node = rb_first(&cluster->root); | 856 | node = rb_first(&cluster->root); |
| 407 | while(node) { | 857 | while (node) { |
| 408 | entry = rb_entry(node, struct btrfs_free_space, offset_index); | 858 | entry = rb_entry(node, struct btrfs_free_space, offset_index); |
| 409 | node = rb_next(&entry->offset_index); | 859 | node = rb_next(&entry->offset_index); |
| 410 | rb_erase(&entry->offset_index, &cluster->root); | 860 | rb_erase(&entry->offset_index, &cluster->root); |
| 411 | link_free_space(block_group, entry); | 861 | BUG_ON(entry->bitmap); |
| 862 | tree_insert_offset(&block_group->free_space_offset, | ||
| 863 | entry->offset, &entry->offset_index, 0); | ||
| 412 | } | 864 | } |
| 413 | list_del_init(&cluster->block_group_list); | ||
| 414 | |||
| 415 | btrfs_put_block_group(cluster->block_group); | ||
| 416 | cluster->block_group = NULL; | ||
| 417 | cluster->root.rb_node = NULL; | 865 | cluster->root.rb_node = NULL; |
| 866 | |||
| 418 | out: | 867 | out: |
| 419 | spin_unlock(&cluster->lock); | 868 | spin_unlock(&cluster->lock); |
| 869 | btrfs_put_block_group(block_group); | ||
| 420 | return 0; | 870 | return 0; |
| 421 | } | 871 | } |
| 422 | 872 | ||
| @@ -425,20 +875,28 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) | |||
| 425 | struct btrfs_free_space *info; | 875 | struct btrfs_free_space *info; |
| 426 | struct rb_node *node; | 876 | struct rb_node *node; |
| 427 | struct btrfs_free_cluster *cluster; | 877 | struct btrfs_free_cluster *cluster; |
| 428 | struct btrfs_free_cluster *safe; | 878 | struct list_head *head; |
| 429 | 879 | ||
| 430 | spin_lock(&block_group->tree_lock); | 880 | spin_lock(&block_group->tree_lock); |
| 431 | 881 | while ((head = block_group->cluster_list.next) != | |
| 432 | list_for_each_entry_safe(cluster, safe, &block_group->cluster_list, | 882 | &block_group->cluster_list) { |
| 433 | block_group_list) { | 883 | cluster = list_entry(head, struct btrfs_free_cluster, |
| 884 | block_group_list); | ||
| 434 | 885 | ||
| 435 | WARN_ON(cluster->block_group != block_group); | 886 | WARN_ON(cluster->block_group != block_group); |
| 436 | __btrfs_return_cluster_to_free_space(block_group, cluster); | 887 | __btrfs_return_cluster_to_free_space(block_group, cluster); |
| 888 | if (need_resched()) { | ||
| 889 | spin_unlock(&block_group->tree_lock); | ||
| 890 | cond_resched(); | ||
| 891 | spin_lock(&block_group->tree_lock); | ||
| 892 | } | ||
| 437 | } | 893 | } |
| 438 | 894 | ||
| 439 | while ((node = rb_last(&block_group->free_space_bytes)) != NULL) { | 895 | while ((node = rb_last(&block_group->free_space_offset)) != NULL) { |
| 440 | info = rb_entry(node, struct btrfs_free_space, bytes_index); | 896 | info = rb_entry(node, struct btrfs_free_space, offset_index); |
| 441 | unlink_free_space(block_group, info); | 897 | unlink_free_space(block_group, info); |
| 898 | if (info->bitmap) | ||
| 899 | kfree(info->bitmap); | ||
| 442 | kfree(info); | 900 | kfree(info); |
| 443 | if (need_resched()) { | 901 | if (need_resched()) { |
| 444 | spin_unlock(&block_group->tree_lock); | 902 | spin_unlock(&block_group->tree_lock); |
| @@ -446,6 +904,7 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) | |||
| 446 | spin_lock(&block_group->tree_lock); | 904 | spin_lock(&block_group->tree_lock); |
| 447 | } | 905 | } |
| 448 | } | 906 | } |
| 907 | |||
| 449 | spin_unlock(&block_group->tree_lock); | 908 | spin_unlock(&block_group->tree_lock); |
| 450 | } | 909 | } |
| 451 | 910 | ||
| @@ -453,25 +912,35 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, | |||
| 453 | u64 offset, u64 bytes, u64 empty_size) | 912 | u64 offset, u64 bytes, u64 empty_size) |
| 454 | { | 913 | { |
| 455 | struct btrfs_free_space *entry = NULL; | 914 | struct btrfs_free_space *entry = NULL; |
| 915 | u64 bytes_search = bytes + empty_size; | ||
| 456 | u64 ret = 0; | 916 | u64 ret = 0; |
| 457 | 917 | ||
| 458 | spin_lock(&block_group->tree_lock); | 918 | spin_lock(&block_group->tree_lock); |
| 459 | entry = tree_search_offset(&block_group->free_space_offset, offset, | 919 | entry = find_free_space(block_group, &offset, &bytes_search, 0); |
| 460 | bytes + empty_size, 1); | ||
| 461 | if (!entry) | 920 | if (!entry) |
| 462 | entry = tree_search_bytes(&block_group->free_space_bytes, | 921 | goto out; |
| 463 | offset, bytes + empty_size); | 922 | |
| 464 | if (entry) { | 923 | ret = offset; |
| 924 | if (entry->bitmap) { | ||
| 925 | bitmap_clear_bits(block_group, entry, offset, bytes); | ||
| 926 | if (!entry->bytes) { | ||
| 927 | unlink_free_space(block_group, entry); | ||
| 928 | kfree(entry->bitmap); | ||
| 929 | kfree(entry); | ||
| 930 | block_group->total_bitmaps--; | ||
| 931 | recalculate_thresholds(block_group); | ||
| 932 | } | ||
| 933 | } else { | ||
| 465 | unlink_free_space(block_group, entry); | 934 | unlink_free_space(block_group, entry); |
| 466 | ret = entry->offset; | ||
| 467 | entry->offset += bytes; | 935 | entry->offset += bytes; |
| 468 | entry->bytes -= bytes; | 936 | entry->bytes -= bytes; |
| 469 | |||
| 470 | if (!entry->bytes) | 937 | if (!entry->bytes) |
| 471 | kfree(entry); | 938 | kfree(entry); |
| 472 | else | 939 | else |
| 473 | link_free_space(block_group, entry); | 940 | link_free_space(block_group, entry); |
| 474 | } | 941 | } |
| 942 | |||
| 943 | out: | ||
| 475 | spin_unlock(&block_group->tree_lock); | 944 | spin_unlock(&block_group->tree_lock); |
| 476 | 945 | ||
| 477 | return ret; | 946 | return ret; |
| @@ -517,6 +986,54 @@ int btrfs_return_cluster_to_free_space( | |||
| 517 | return ret; | 986 | return ret; |
| 518 | } | 987 | } |
| 519 | 988 | ||
| 989 | static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, | ||
| 990 | struct btrfs_free_cluster *cluster, | ||
| 991 | u64 bytes, u64 min_start) | ||
| 992 | { | ||
| 993 | struct btrfs_free_space *entry; | ||
| 994 | int err; | ||
| 995 | u64 search_start = cluster->window_start; | ||
| 996 | u64 search_bytes = bytes; | ||
| 997 | u64 ret = 0; | ||
| 998 | |||
| 999 | spin_lock(&block_group->tree_lock); | ||
| 1000 | spin_lock(&cluster->lock); | ||
| 1001 | |||
| 1002 | if (!cluster->points_to_bitmap) | ||
| 1003 | goto out; | ||
| 1004 | |||
| 1005 | if (cluster->block_group != block_group) | ||
| 1006 | goto out; | ||
| 1007 | |||
| 1008 | /* | ||
| 1009 | * search_start is the beginning of the bitmap, but at some point it may | ||
| 1010 | * be a good idea to point to the actual start of the free area in the | ||
| 1011 | * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only | ||
| 1012 | * to 1 to make sure we get the bitmap entry | ||
| 1013 | */ | ||
| 1014 | entry = tree_search_offset(block_group, | ||
| 1015 | offset_to_bitmap(block_group, search_start), | ||
| 1016 | 1, 0); | ||
| 1017 | if (!entry || !entry->bitmap) | ||
| 1018 | goto out; | ||
| 1019 | |||
| 1020 | search_start = min_start; | ||
| 1021 | search_bytes = bytes; | ||
| 1022 | |||
| 1023 | err = search_bitmap(block_group, entry, &search_start, | ||
| 1024 | &search_bytes); | ||
| 1025 | if (err) | ||
| 1026 | goto out; | ||
| 1027 | |||
| 1028 | ret = search_start; | ||
| 1029 | bitmap_clear_bits(block_group, entry, ret, bytes); | ||
| 1030 | out: | ||
| 1031 | spin_unlock(&cluster->lock); | ||
| 1032 | spin_unlock(&block_group->tree_lock); | ||
| 1033 | |||
| 1034 | return ret; | ||
| 1035 | } | ||
| 1036 | |||
| 520 | /* | 1037 | /* |
| 521 | * given a cluster, try to allocate 'bytes' from it, returns 0 | 1038 | * given a cluster, try to allocate 'bytes' from it, returns 0 |
| 522 | * if it couldn't find anything suitably large, or a logical disk offset | 1039 | * if it couldn't find anything suitably large, or a logical disk offset |
| @@ -530,6 +1047,10 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, | |||
| 530 | struct rb_node *node; | 1047 | struct rb_node *node; |
| 531 | u64 ret = 0; | 1048 | u64 ret = 0; |
| 532 | 1049 | ||
| 1050 | if (cluster->points_to_bitmap) | ||
| 1051 | return btrfs_alloc_from_bitmap(block_group, cluster, bytes, | ||
| 1052 | min_start); | ||
| 1053 | |||
| 533 | spin_lock(&cluster->lock); | 1054 | spin_lock(&cluster->lock); |
| 534 | if (bytes > cluster->max_size) | 1055 | if (bytes > cluster->max_size) |
| 535 | goto out; | 1056 | goto out; |
| @@ -567,9 +1088,73 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, | |||
| 567 | } | 1088 | } |
| 568 | out: | 1089 | out: |
| 569 | spin_unlock(&cluster->lock); | 1090 | spin_unlock(&cluster->lock); |
| 1091 | |||
| 570 | return ret; | 1092 | return ret; |
| 571 | } | 1093 | } |
| 572 | 1094 | ||
| 1095 | static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, | ||
| 1096 | struct btrfs_free_space *entry, | ||
| 1097 | struct btrfs_free_cluster *cluster, | ||
| 1098 | u64 offset, u64 bytes, u64 min_bytes) | ||
| 1099 | { | ||
| 1100 | unsigned long next_zero; | ||
| 1101 | unsigned long i; | ||
| 1102 | unsigned long search_bits; | ||
| 1103 | unsigned long total_bits; | ||
| 1104 | unsigned long found_bits; | ||
| 1105 | unsigned long start = 0; | ||
| 1106 | unsigned long total_found = 0; | ||
| 1107 | bool found = false; | ||
| 1108 | |||
| 1109 | i = offset_to_bit(entry->offset, block_group->sectorsize, | ||
| 1110 | max_t(u64, offset, entry->offset)); | ||
| 1111 | search_bits = bytes_to_bits(min_bytes, block_group->sectorsize); | ||
| 1112 | total_bits = bytes_to_bits(bytes, block_group->sectorsize); | ||
| 1113 | |||
| 1114 | again: | ||
| 1115 | found_bits = 0; | ||
| 1116 | for (i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i); | ||
| 1117 | i < BITS_PER_BITMAP; | ||
| 1118 | i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i + 1)) { | ||
| 1119 | next_zero = find_next_zero_bit(entry->bitmap, | ||
| 1120 | BITS_PER_BITMAP, i); | ||
| 1121 | if (next_zero - i >= search_bits) { | ||
| 1122 | found_bits = next_zero - i; | ||
| 1123 | break; | ||
| 1124 | } | ||
| 1125 | i = next_zero; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | if (!found_bits) | ||
| 1129 | return -1; | ||
| 1130 | |||
| 1131 | if (!found) { | ||
| 1132 | start = i; | ||
| 1133 | found = true; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | total_found += found_bits; | ||
| 1137 | |||
| 1138 | if (cluster->max_size < found_bits * block_group->sectorsize) | ||
| 1139 | cluster->max_size = found_bits * block_group->sectorsize; | ||
| 1140 | |||
| 1141 | if (total_found < total_bits) { | ||
| 1142 | i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, next_zero); | ||
| 1143 | if (i - start > total_bits * 2) { | ||
| 1144 | total_found = 0; | ||
| 1145 | cluster->max_size = 0; | ||
| 1146 | found = false; | ||
| 1147 | } | ||
| 1148 | goto again; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | cluster->window_start = start * block_group->sectorsize + | ||
| 1152 | entry->offset; | ||
| 1153 | cluster->points_to_bitmap = true; | ||
| 1154 | |||
| 1155 | return 0; | ||
| 1156 | } | ||
| 1157 | |||
| 573 | /* | 1158 | /* |
| 574 | * here we try to find a cluster of blocks in a block group. The goal | 1159 | * here we try to find a cluster of blocks in a block group. The goal |
| 575 | * is to find at least bytes free and up to empty_size + bytes free. | 1160 | * is to find at least bytes free and up to empty_size + bytes free. |
| @@ -587,12 +1172,12 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, | |||
| 587 | struct btrfs_free_space *entry = NULL; | 1172 | struct btrfs_free_space *entry = NULL; |
| 588 | struct rb_node *node; | 1173 | struct rb_node *node; |
| 589 | struct btrfs_free_space *next; | 1174 | struct btrfs_free_space *next; |
| 590 | struct btrfs_free_space *last; | 1175 | struct btrfs_free_space *last = NULL; |
| 591 | u64 min_bytes; | 1176 | u64 min_bytes; |
| 592 | u64 window_start; | 1177 | u64 window_start; |
| 593 | u64 window_free; | 1178 | u64 window_free; |
| 594 | u64 max_extent = 0; | 1179 | u64 max_extent = 0; |
| 595 | int total_retries = 0; | 1180 | bool found_bitmap = false; |
| 596 | int ret; | 1181 | int ret; |
| 597 | 1182 | ||
| 598 | /* for metadata, allow allocates with more holes */ | 1183 | /* for metadata, allow allocates with more holes */ |
| @@ -620,31 +1205,80 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, | |||
| 620 | goto out; | 1205 | goto out; |
| 621 | } | 1206 | } |
| 622 | again: | 1207 | again: |
| 623 | min_bytes = min(min_bytes, bytes + empty_size); | 1208 | entry = tree_search_offset(block_group, offset, found_bitmap, 1); |
| 624 | entry = tree_search_bytes(&block_group->free_space_bytes, | ||
| 625 | offset, min_bytes); | ||
| 626 | if (!entry) { | 1209 | if (!entry) { |
| 627 | ret = -ENOSPC; | 1210 | ret = -ENOSPC; |
| 628 | goto out; | 1211 | goto out; |
| 629 | } | 1212 | } |
| 1213 | |||
| 1214 | /* | ||
| 1215 | * If found_bitmap is true, we exhausted our search for extent entries, | ||
| 1216 | * and we just want to search all of the bitmaps that we can find, and | ||
| 1217 | * ignore any extent entries we find. | ||
| 1218 | */ | ||
| 1219 | while (entry->bitmap || found_bitmap || | ||
| 1220 | (!entry->bitmap && entry->bytes < min_bytes)) { | ||
| 1221 | struct rb_node *node = rb_next(&entry->offset_index); | ||
| 1222 | |||
| 1223 | if (entry->bitmap && entry->bytes > bytes + empty_size) { | ||
| 1224 | ret = btrfs_bitmap_cluster(block_group, entry, cluster, | ||
| 1225 | offset, bytes + empty_size, | ||
| 1226 | min_bytes); | ||
| 1227 | if (!ret) | ||
| 1228 | goto got_it; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | if (!node) { | ||
| 1232 | ret = -ENOSPC; | ||
| 1233 | goto out; | ||
| 1234 | } | ||
| 1235 | entry = rb_entry(node, struct btrfs_free_space, offset_index); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | /* | ||
| 1239 | * We already searched all the extent entries from the passed in offset | ||
| 1240 | * to the end and didn't find enough space for the cluster, and we also | ||
| 1241 | * didn't find any bitmaps that met our criteria, just go ahead and exit | ||
| 1242 | */ | ||
| 1243 | if (found_bitmap) { | ||
| 1244 | ret = -ENOSPC; | ||
| 1245 | goto out; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | cluster->points_to_bitmap = false; | ||
| 630 | window_start = entry->offset; | 1249 | window_start = entry->offset; |
| 631 | window_free = entry->bytes; | 1250 | window_free = entry->bytes; |
| 632 | last = entry; | 1251 | last = entry; |
| 633 | max_extent = entry->bytes; | 1252 | max_extent = entry->bytes; |
| 634 | 1253 | ||
| 635 | while(1) { | 1254 | while (1) { |
| 636 | /* out window is just right, lets fill it */ | 1255 | /* out window is just right, lets fill it */ |
| 637 | if (window_free >= bytes + empty_size) | 1256 | if (window_free >= bytes + empty_size) |
| 638 | break; | 1257 | break; |
| 639 | 1258 | ||
| 640 | node = rb_next(&last->offset_index); | 1259 | node = rb_next(&last->offset_index); |
| 641 | if (!node) { | 1260 | if (!node) { |
| 1261 | if (found_bitmap) | ||
| 1262 | goto again; | ||
| 642 | ret = -ENOSPC; | 1263 | ret = -ENOSPC; |
| 643 | goto out; | 1264 | goto out; |
| 644 | } | 1265 | } |
| 645 | next = rb_entry(node, struct btrfs_free_space, offset_index); | 1266 | next = rb_entry(node, struct btrfs_free_space, offset_index); |
| 646 | 1267 | ||
| 647 | /* | 1268 | /* |
| 1269 | * we found a bitmap, so if this search doesn't result in a | ||
| 1270 | * cluster, we know to go and search again for the bitmaps and | ||
| 1271 | * start looking for space there | ||
| 1272 | */ | ||
| 1273 | if (next->bitmap) { | ||
| 1274 | if (!found_bitmap) | ||
| 1275 | offset = next->offset; | ||
| 1276 | found_bitmap = true; | ||
| 1277 | last = next; | ||
| 1278 | continue; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | /* | ||
| 648 | * we haven't filled the empty size and the window is | 1282 | * we haven't filled the empty size and the window is |
| 649 | * very large. reset and try again | 1283 | * very large. reset and try again |
| 650 | */ | 1284 | */ |
| @@ -655,19 +1289,6 @@ again: | |||
| 655 | window_free = entry->bytes; | 1289 | window_free = entry->bytes; |
| 656 | last = entry; | 1290 | last = entry; |
| 657 | max_extent = 0; | 1291 | max_extent = 0; |
| 658 | total_retries++; | ||
| 659 | if (total_retries % 64 == 0) { | ||
| 660 | if (min_bytes >= (bytes + empty_size)) { | ||
| 661 | ret = -ENOSPC; | ||
| 662 | goto out; | ||
| 663 | } | ||
| 664 | /* | ||
| 665 | * grow our allocation a bit, we're not having | ||
| 666 | * much luck | ||
| 667 | */ | ||
| 668 | min_bytes *= 2; | ||
| 669 | goto again; | ||
| 670 | } | ||
| 671 | } else { | 1292 | } else { |
| 672 | last = next; | 1293 | last = next; |
| 673 | window_free += next->bytes; | 1294 | window_free += next->bytes; |
| @@ -685,11 +1306,19 @@ again: | |||
| 685 | * The cluster includes an rbtree, but only uses the offset index | 1306 | * The cluster includes an rbtree, but only uses the offset index |
| 686 | * of each free space cache entry. | 1307 | * of each free space cache entry. |
| 687 | */ | 1308 | */ |
| 688 | while(1) { | 1309 | while (1) { |
| 689 | node = rb_next(&entry->offset_index); | 1310 | node = rb_next(&entry->offset_index); |
| 690 | unlink_free_space(block_group, entry); | 1311 | if (entry->bitmap && node) { |
| 1312 | entry = rb_entry(node, struct btrfs_free_space, | ||
| 1313 | offset_index); | ||
| 1314 | continue; | ||
| 1315 | } else if (entry->bitmap && !node) { | ||
| 1316 | break; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | rb_erase(&entry->offset_index, &block_group->free_space_offset); | ||
| 691 | ret = tree_insert_offset(&cluster->root, entry->offset, | 1320 | ret = tree_insert_offset(&cluster->root, entry->offset, |
| 692 | &entry->offset_index); | 1321 | &entry->offset_index, 0); |
| 693 | BUG_ON(ret); | 1322 | BUG_ON(ret); |
| 694 | 1323 | ||
| 695 | if (!node || entry == last) | 1324 | if (!node || entry == last) |
| @@ -697,8 +1326,10 @@ again: | |||
| 697 | 1326 | ||
| 698 | entry = rb_entry(node, struct btrfs_free_space, offset_index); | 1327 | entry = rb_entry(node, struct btrfs_free_space, offset_index); |
| 699 | } | 1328 | } |
| 700 | ret = 0; | 1329 | |
| 701 | cluster->max_size = max_extent; | 1330 | cluster->max_size = max_extent; |
| 1331 | got_it: | ||
| 1332 | ret = 0; | ||
| 702 | atomic_inc(&block_group->count); | 1333 | atomic_inc(&block_group->count); |
| 703 | list_add_tail(&cluster->block_group_list, &block_group->cluster_list); | 1334 | list_add_tail(&cluster->block_group_list, &block_group->cluster_list); |
| 704 | cluster->block_group = block_group; | 1335 | cluster->block_group = block_group; |
| @@ -718,6 +1349,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) | |||
| 718 | spin_lock_init(&cluster->refill_lock); | 1349 | spin_lock_init(&cluster->refill_lock); |
| 719 | cluster->root.rb_node = NULL; | 1350 | cluster->root.rb_node = NULL; |
| 720 | cluster->max_size = 0; | 1351 | cluster->max_size = 0; |
| 1352 | cluster->points_to_bitmap = false; | ||
| 721 | INIT_LIST_HEAD(&cluster->block_group_list); | 1353 | INIT_LIST_HEAD(&cluster->block_group_list); |
| 722 | cluster->block_group = NULL; | 1354 | cluster->block_group = NULL; |
| 723 | } | 1355 | } |
diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h index 266fb8764054..890a8e79011b 100644 --- a/fs/btrfs/free-space-cache.h +++ b/fs/btrfs/free-space-cache.h | |||
| @@ -19,6 +19,14 @@ | |||
| 19 | #ifndef __BTRFS_FREE_SPACE_CACHE | 19 | #ifndef __BTRFS_FREE_SPACE_CACHE |
| 20 | #define __BTRFS_FREE_SPACE_CACHE | 20 | #define __BTRFS_FREE_SPACE_CACHE |
| 21 | 21 | ||
| 22 | struct btrfs_free_space { | ||
| 23 | struct rb_node offset_index; | ||
| 24 | u64 offset; | ||
| 25 | u64 bytes; | ||
| 26 | unsigned long *bitmap; | ||
| 27 | struct list_head list; | ||
| 28 | }; | ||
| 29 | |||
| 22 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | 30 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, |
| 23 | u64 bytenr, u64 size); | 31 | u64 bytenr, u64 size); |
| 24 | int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | 32 | int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7ffa3d34ea19..59cba180fe83 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
| 27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | #include <linux/backing-dev.h> | 29 | #include <linux/backing-dev.h> |
| 31 | #include <linux/mpage.h> | 30 | #include <linux/mpage.h> |
| 32 | #include <linux/swap.h> | 31 | #include <linux/swap.h> |
| @@ -2604,8 +2603,8 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
| 2604 | if (root->ref_cows) | 2603 | if (root->ref_cows) |
| 2605 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); | 2604 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); |
| 2606 | path = btrfs_alloc_path(); | 2605 | path = btrfs_alloc_path(); |
| 2607 | path->reada = -1; | ||
| 2608 | BUG_ON(!path); | 2606 | BUG_ON(!path); |
| 2607 | path->reada = -1; | ||
| 2609 | 2608 | ||
| 2610 | /* FIXME, add redo link to tree so we don't leak on crash */ | 2609 | /* FIXME, add redo link to tree so we don't leak on crash */ |
| 2611 | key.objectid = inode->i_ino; | 2610 | key.objectid = inode->i_ino; |
| @@ -3100,8 +3099,12 @@ static void inode_tree_add(struct inode *inode) | |||
| 3100 | { | 3099 | { |
| 3101 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3100 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3102 | struct btrfs_inode *entry; | 3101 | struct btrfs_inode *entry; |
| 3103 | struct rb_node **p = &root->inode_tree.rb_node; | 3102 | struct rb_node **p; |
| 3104 | struct rb_node *parent = NULL; | 3103 | struct rb_node *parent; |
| 3104 | |||
| 3105 | again: | ||
| 3106 | p = &root->inode_tree.rb_node; | ||
| 3107 | parent = NULL; | ||
| 3105 | 3108 | ||
| 3106 | spin_lock(&root->inode_lock); | 3109 | spin_lock(&root->inode_lock); |
| 3107 | while (*p) { | 3110 | while (*p) { |
| @@ -3109,13 +3112,16 @@ static void inode_tree_add(struct inode *inode) | |||
| 3109 | entry = rb_entry(parent, struct btrfs_inode, rb_node); | 3112 | entry = rb_entry(parent, struct btrfs_inode, rb_node); |
| 3110 | 3113 | ||
| 3111 | if (inode->i_ino < entry->vfs_inode.i_ino) | 3114 | if (inode->i_ino < entry->vfs_inode.i_ino) |
| 3112 | p = &(*p)->rb_left; | 3115 | p = &parent->rb_left; |
| 3113 | else if (inode->i_ino > entry->vfs_inode.i_ino) | 3116 | else if (inode->i_ino > entry->vfs_inode.i_ino) |
| 3114 | p = &(*p)->rb_right; | 3117 | p = &parent->rb_right; |
| 3115 | else { | 3118 | else { |
| 3116 | WARN_ON(!(entry->vfs_inode.i_state & | 3119 | WARN_ON(!(entry->vfs_inode.i_state & |
| 3117 | (I_WILL_FREE | I_FREEING | I_CLEAR))); | 3120 | (I_WILL_FREE | I_FREEING | I_CLEAR))); |
| 3118 | break; | 3121 | rb_erase(parent, &root->inode_tree); |
| 3122 | RB_CLEAR_NODE(parent); | ||
| 3123 | spin_unlock(&root->inode_lock); | ||
| 3124 | goto again; | ||
| 3119 | } | 3125 | } |
| 3120 | } | 3126 | } |
| 3121 | rb_link_node(&BTRFS_I(inode)->rb_node, parent, p); | 3127 | rb_link_node(&BTRFS_I(inode)->rb_node, parent, p); |
| @@ -3127,12 +3133,12 @@ static void inode_tree_del(struct inode *inode) | |||
| 3127 | { | 3133 | { |
| 3128 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3134 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3129 | 3135 | ||
| 3136 | spin_lock(&root->inode_lock); | ||
| 3130 | if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) { | 3137 | if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) { |
| 3131 | spin_lock(&root->inode_lock); | ||
| 3132 | rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree); | 3138 | rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree); |
| 3133 | spin_unlock(&root->inode_lock); | ||
| 3134 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); | 3139 | RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node); |
| 3135 | } | 3140 | } |
| 3141 | spin_unlock(&root->inode_lock); | ||
| 3136 | } | 3142 | } |
| 3137 | 3143 | ||
| 3138 | static noinline void init_btrfs_i(struct inode *inode) | 3144 | static noinline void init_btrfs_i(struct inode *inode) |
| @@ -4786,8 +4792,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 4786 | * and the replacement file is large. Start IO on it now so | 4792 | * and the replacement file is large. Start IO on it now so |
| 4787 | * we don't add too much work to the end of the transaction | 4793 | * we don't add too much work to the end of the transaction |
| 4788 | */ | 4794 | */ |
| 4789 | if (new_inode && old_inode && S_ISREG(old_inode->i_mode) && | 4795 | if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size && |
| 4790 | new_inode->i_size && | ||
| 4791 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 4796 | old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
| 4792 | filemap_flush(old_inode->i_mapping); | 4797 | filemap_flush(old_inode->i_mapping); |
| 4793 | 4798 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9f4db848db10..bd88f25889f7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
| 28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
| 30 | #include <linux/smp_lock.h> | ||
| 31 | #include <linux/backing-dev.h> | 30 | #include <linux/backing-dev.h> |
| 32 | #include <linux/mount.h> | 31 | #include <linux/mount.h> |
| 33 | #include <linux/mpage.h> | 32 | #include <linux/mpage.h> |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 6d6523da0a30..0d126be22b63 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
| @@ -309,7 +309,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c) | |||
| 309 | } | 309 | } |
| 310 | printk(KERN_INFO "node %llu level %d total ptrs %d free spc %u\n", | 310 | printk(KERN_INFO "node %llu level %d total ptrs %d free spc %u\n", |
| 311 | (unsigned long long)btrfs_header_bytenr(c), | 311 | (unsigned long long)btrfs_header_bytenr(c), |
| 312 | btrfs_header_level(c), nr, | 312 | level, nr, |
| 313 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); | 313 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); |
| 314 | for (i = 0; i < nr; i++) { | 314 | for (i = 0; i < nr; i++) { |
| 315 | btrfs_node_key_to_cpu(c, &key, i); | 315 | btrfs_node_key_to_cpu(c, &key, i); |
| @@ -326,10 +326,10 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c) | |||
| 326 | btrfs_level_size(root, level - 1), | 326 | btrfs_level_size(root, level - 1), |
| 327 | btrfs_node_ptr_generation(c, i)); | 327 | btrfs_node_ptr_generation(c, i)); |
| 328 | if (btrfs_is_leaf(next) && | 328 | if (btrfs_is_leaf(next) && |
| 329 | btrfs_header_level(c) != 1) | 329 | level != 1) |
| 330 | BUG(); | 330 | BUG(); |
| 331 | if (btrfs_header_level(next) != | 331 | if (btrfs_header_level(next) != |
| 332 | btrfs_header_level(c) - 1) | 332 | level - 1) |
| 333 | BUG(); | 333 | BUG(); |
| 334 | btrfs_print_tree(root, next); | 334 | btrfs_print_tree(root, next); |
| 335 | free_extent_buffer(next); | 335 | free_extent_buffer(next); |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 008397934778..c04f7f212602 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -670,6 +670,8 @@ again: | |||
| 670 | err = ret; | 670 | err = ret; |
| 671 | goto out; | 671 | goto out; |
| 672 | } | 672 | } |
| 673 | if (ret > 0 && path2->slots[level] > 0) | ||
| 674 | path2->slots[level]--; | ||
| 673 | 675 | ||
| 674 | eb = path2->nodes[level]; | 676 | eb = path2->nodes[level]; |
| 675 | WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) != | 677 | WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) != |
| @@ -1609,6 +1611,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
| 1609 | BUG_ON(level == 0); | 1611 | BUG_ON(level == 0); |
| 1610 | path->lowest_level = level; | 1612 | path->lowest_level = level; |
| 1611 | ret = btrfs_search_slot(NULL, reloc_root, &key, path, 0, 0); | 1613 | ret = btrfs_search_slot(NULL, reloc_root, &key, path, 0, 0); |
| 1614 | path->lowest_level = 0; | ||
| 1612 | if (ret < 0) { | 1615 | if (ret < 0) { |
| 1613 | btrfs_free_path(path); | 1616 | btrfs_free_path(path); |
| 1614 | return ret; | 1617 | return ret; |
| @@ -2550,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len) | |||
| 2550 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; | 2553 | last_index = (start + len - 1) >> PAGE_CACHE_SHIFT; |
| 2551 | 2554 | ||
| 2552 | /* make sure the dirty trick played by the caller work */ | 2555 | /* make sure the dirty trick played by the caller work */ |
| 2553 | ret = invalidate_inode_pages2_range(inode->i_mapping, | 2556 | while (1) { |
| 2554 | first_index, last_index); | 2557 | ret = invalidate_inode_pages2_range(inode->i_mapping, |
| 2558 | first_index, last_index); | ||
| 2559 | if (ret != -EBUSY) | ||
| 2560 | break; | ||
| 2561 | schedule_timeout(HZ/10); | ||
| 2562 | } | ||
| 2555 | if (ret) | 2563 | if (ret) |
| 2556 | goto out_unlock; | 2564 | goto out_unlock; |
| 2557 | 2565 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9f179d4832d5..6d6d06cb6dfc 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
| 27 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | #include <linux/backing-dev.h> | 29 | #include <linux/backing-dev.h> |
| 31 | #include <linux/mount.h> | 30 | #include <linux/mount.h> |
| 32 | #include <linux/mpage.h> | 31 | #include <linux/mpage.h> |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2dbf1c1f56ee..cdbb5022da52 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -40,6 +40,12 @@ static noinline void put_transaction(struct btrfs_transaction *transaction) | |||
| 40 | } | 40 | } |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static noinline void switch_commit_root(struct btrfs_root *root) | ||
| 44 | { | ||
| 45 | free_extent_buffer(root->commit_root); | ||
| 46 | root->commit_root = btrfs_root_node(root); | ||
| 47 | } | ||
| 48 | |||
| 43 | /* | 49 | /* |
| 44 | * either allocate a new transaction or hop into the existing one | 50 | * either allocate a new transaction or hop into the existing one |
| 45 | */ | 51 | */ |
| @@ -444,9 +450,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 444 | 450 | ||
| 445 | btrfs_write_dirty_block_groups(trans, root); | 451 | btrfs_write_dirty_block_groups(trans, root); |
| 446 | 452 | ||
| 447 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
| 448 | BUG_ON(ret); | ||
| 449 | |||
| 450 | while (1) { | 453 | while (1) { |
| 451 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); | 454 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); |
| 452 | if (old_root_bytenr == root->node->start) | 455 | if (old_root_bytenr == root->node->start) |
| @@ -457,13 +460,14 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
| 457 | &root->root_key, | 460 | &root->root_key, |
| 458 | &root->root_item); | 461 | &root->root_item); |
| 459 | BUG_ON(ret); | 462 | BUG_ON(ret); |
| 460 | btrfs_write_dirty_block_groups(trans, root); | ||
| 461 | 463 | ||
| 462 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 464 | ret = btrfs_write_dirty_block_groups(trans, root); |
| 463 | BUG_ON(ret); | 465 | BUG_ON(ret); |
| 464 | } | 466 | } |
| 465 | free_extent_buffer(root->commit_root); | 467 | |
| 466 | root->commit_root = btrfs_root_node(root); | 468 | if (root != root->fs_info->extent_root) |
| 469 | switch_commit_root(root); | ||
| 470 | |||
| 467 | return 0; | 471 | return 0; |
| 468 | } | 472 | } |
| 469 | 473 | ||
| @@ -495,10 +499,12 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
| 495 | root = list_entry(next, struct btrfs_root, dirty_list); | 499 | root = list_entry(next, struct btrfs_root, dirty_list); |
| 496 | 500 | ||
| 497 | update_cowonly_root(trans, root); | 501 | update_cowonly_root(trans, root); |
| 498 | |||
| 499 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | ||
| 500 | BUG_ON(ret); | ||
| 501 | } | 502 | } |
| 503 | |||
| 504 | down_write(&fs_info->extent_commit_sem); | ||
| 505 | switch_commit_root(fs_info->extent_root); | ||
| 506 | up_write(&fs_info->extent_commit_sem); | ||
| 507 | |||
| 502 | return 0; | 508 | return 0; |
| 503 | } | 509 | } |
| 504 | 510 | ||
| @@ -544,8 +550,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 544 | btrfs_update_reloc_root(trans, root); | 550 | btrfs_update_reloc_root(trans, root); |
| 545 | 551 | ||
| 546 | if (root->commit_root != root->node) { | 552 | if (root->commit_root != root->node) { |
| 547 | free_extent_buffer(root->commit_root); | 553 | switch_commit_root(root); |
| 548 | root->commit_root = btrfs_root_node(root); | ||
| 549 | btrfs_set_root_node(&root->root_item, | 554 | btrfs_set_root_node(&root->root_item, |
| 550 | root->node); | 555 | root->node); |
| 551 | } | 556 | } |
| @@ -852,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root) | |||
| 852 | super->root_level = root_item->level; | 857 | super->root_level = root_item->level; |
| 853 | } | 858 | } |
| 854 | 859 | ||
| 860 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | ||
| 861 | { | ||
| 862 | int ret = 0; | ||
| 863 | spin_lock(&info->new_trans_lock); | ||
| 864 | if (info->running_transaction) | ||
| 865 | ret = info->running_transaction->in_commit; | ||
| 866 | spin_unlock(&info->new_trans_lock); | ||
| 867 | return ret; | ||
| 868 | } | ||
| 869 | |||
| 855 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 870 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
| 856 | struct btrfs_root *root) | 871 | struct btrfs_root *root) |
| 857 | { | 872 | { |
| @@ -943,9 +958,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 943 | 958 | ||
| 944 | mutex_unlock(&root->fs_info->trans_mutex); | 959 | mutex_unlock(&root->fs_info->trans_mutex); |
| 945 | 960 | ||
| 946 | if (flush_on_commit || snap_pending) { | 961 | if (flush_on_commit) { |
| 947 | if (flush_on_commit) | 962 | btrfs_start_delalloc_inodes(root); |
| 948 | btrfs_start_delalloc_inodes(root); | 963 | ret = btrfs_wait_ordered_extents(root, 0); |
| 964 | BUG_ON(ret); | ||
| 965 | } else if (snap_pending) { | ||
| 949 | ret = btrfs_wait_ordered_extents(root, 1); | 966 | ret = btrfs_wait_ordered_extents(root, 1); |
| 950 | BUG_ON(ret); | 967 | BUG_ON(ret); |
| 951 | } | 968 | } |
| @@ -1009,15 +1026,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1009 | 1026 | ||
| 1010 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, | 1027 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, |
| 1011 | root->fs_info->tree_root->node); | 1028 | root->fs_info->tree_root->node); |
| 1012 | free_extent_buffer(root->fs_info->tree_root->commit_root); | 1029 | switch_commit_root(root->fs_info->tree_root); |
| 1013 | root->fs_info->tree_root->commit_root = | ||
| 1014 | btrfs_root_node(root->fs_info->tree_root); | ||
| 1015 | 1030 | ||
| 1016 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, | 1031 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, |
| 1017 | root->fs_info->chunk_root->node); | 1032 | root->fs_info->chunk_root->node); |
| 1018 | free_extent_buffer(root->fs_info->chunk_root->commit_root); | 1033 | switch_commit_root(root->fs_info->chunk_root); |
| 1019 | root->fs_info->chunk_root->commit_root = | ||
| 1020 | btrfs_root_node(root->fs_info->chunk_root); | ||
| 1021 | 1034 | ||
| 1022 | update_super_roots(root); | 1035 | update_super_roots(root); |
| 1023 | 1036 | ||
| @@ -1057,6 +1070,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1057 | cur_trans->commit_done = 1; | 1070 | cur_trans->commit_done = 1; |
| 1058 | 1071 | ||
| 1059 | root->fs_info->last_trans_committed = cur_trans->transid; | 1072 | root->fs_info->last_trans_committed = cur_trans->transid; |
| 1073 | |||
| 1060 | wake_up(&cur_trans->commit_wait); | 1074 | wake_up(&cur_trans->commit_wait); |
| 1061 | 1075 | ||
| 1062 | put_transaction(cur_trans); | 1076 | put_transaction(cur_trans); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 961c3ee5a2e1..663c67404918 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -107,4 +107,5 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | |||
| 107 | struct btrfs_root *root); | 107 | struct btrfs_root *root); |
| 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, | 108 | int btrfs_write_and_wait_marked_extents(struct btrfs_root *root, |
| 109 | struct extent_io_tree *dirty_pages); | 109 | struct extent_io_tree *dirty_pages); |
| 110 | int btrfs_transaction_in_commit(struct btrfs_fs_info *info); | ||
| 110 | #endif | 111 | #endif |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c13922206d1b..d91b0de7c502 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -797,7 +797,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, | |||
| 797 | return -ENOENT; | 797 | return -ENOENT; |
| 798 | 798 | ||
| 799 | inode = read_one_inode(root, key->objectid); | 799 | inode = read_one_inode(root, key->objectid); |
| 800 | BUG_ON(!dir); | 800 | BUG_ON(!inode); |
| 801 | 801 | ||
| 802 | ref_ptr = btrfs_item_ptr_offset(eb, slot); | 802 | ref_ptr = btrfs_item_ptr_offset(eb, slot); |
| 803 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); | 803 | ref_end = ref_ptr + btrfs_item_size_nr(eb, slot); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3ab80e9cd767..5dbefd11b4af 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -721,7 +721,8 @@ error: | |||
| 721 | */ | 721 | */ |
| 722 | static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans, | 722 | static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans, |
| 723 | struct btrfs_device *device, | 723 | struct btrfs_device *device, |
| 724 | u64 num_bytes, u64 *start) | 724 | u64 num_bytes, u64 *start, |
| 725 | u64 *max_avail) | ||
| 725 | { | 726 | { |
| 726 | struct btrfs_key key; | 727 | struct btrfs_key key; |
| 727 | struct btrfs_root *root = device->dev_root; | 728 | struct btrfs_root *root = device->dev_root; |
| @@ -758,9 +759,13 @@ static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans, | |||
| 758 | ret = btrfs_search_slot(trans, root, &key, path, 0, 0); | 759 | ret = btrfs_search_slot(trans, root, &key, path, 0, 0); |
| 759 | if (ret < 0) | 760 | if (ret < 0) |
| 760 | goto error; | 761 | goto error; |
| 761 | ret = btrfs_previous_item(root, path, 0, key.type); | 762 | if (ret > 0) { |
| 762 | if (ret < 0) | 763 | ret = btrfs_previous_item(root, path, key.objectid, key.type); |
| 763 | goto error; | 764 | if (ret < 0) |
| 765 | goto error; | ||
| 766 | if (ret > 0) | ||
| 767 | start_found = 1; | ||
| 768 | } | ||
| 764 | l = path->nodes[0]; | 769 | l = path->nodes[0]; |
| 765 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 770 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
| 766 | while (1) { | 771 | while (1) { |
| @@ -803,6 +808,10 @@ no_more_items: | |||
| 803 | if (last_byte < search_start) | 808 | if (last_byte < search_start) |
| 804 | last_byte = search_start; | 809 | last_byte = search_start; |
| 805 | hole_size = key.offset - last_byte; | 810 | hole_size = key.offset - last_byte; |
| 811 | |||
| 812 | if (hole_size > *max_avail) | ||
| 813 | *max_avail = hole_size; | ||
| 814 | |||
| 806 | if (key.offset > last_byte && | 815 | if (key.offset > last_byte && |
| 807 | hole_size >= num_bytes) { | 816 | hole_size >= num_bytes) { |
| 808 | *start = last_byte; | 817 | *start = last_byte; |
| @@ -1621,6 +1630,7 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans, | |||
| 1621 | device->fs_devices->total_rw_bytes += diff; | 1630 | device->fs_devices->total_rw_bytes += diff; |
| 1622 | 1631 | ||
| 1623 | device->total_bytes = new_size; | 1632 | device->total_bytes = new_size; |
| 1633 | device->disk_total_bytes = new_size; | ||
| 1624 | btrfs_clear_space_info_full(device->dev_root->fs_info); | 1634 | btrfs_clear_space_info_full(device->dev_root->fs_info); |
| 1625 | 1635 | ||
| 1626 | return btrfs_update_device(trans, device); | 1636 | return btrfs_update_device(trans, device); |
| @@ -2007,7 +2017,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
| 2007 | goto done; | 2017 | goto done; |
| 2008 | if (ret) { | 2018 | if (ret) { |
| 2009 | ret = 0; | 2019 | ret = 0; |
| 2010 | goto done; | 2020 | break; |
| 2011 | } | 2021 | } |
| 2012 | 2022 | ||
| 2013 | l = path->nodes[0]; | 2023 | l = path->nodes[0]; |
| @@ -2015,7 +2025,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size) | |||
| 2015 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 2025 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
| 2016 | 2026 | ||
| 2017 | if (key.objectid != device->devid) | 2027 | if (key.objectid != device->devid) |
| 2018 | goto done; | 2028 | break; |
| 2019 | 2029 | ||
| 2020 | dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent); | 2030 | dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent); |
| 2021 | length = btrfs_dev_extent_length(l, dev_extent); | 2031 | length = btrfs_dev_extent_length(l, dev_extent); |
| @@ -2171,6 +2181,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 2171 | max_chunk_size); | 2181 | max_chunk_size); |
| 2172 | 2182 | ||
| 2173 | again: | 2183 | again: |
| 2184 | max_avail = 0; | ||
| 2174 | if (!map || map->num_stripes != num_stripes) { | 2185 | if (!map || map->num_stripes != num_stripes) { |
| 2175 | kfree(map); | 2186 | kfree(map); |
| 2176 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); | 2187 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); |
| @@ -2219,7 +2230,8 @@ again: | |||
| 2219 | 2230 | ||
| 2220 | if (device->in_fs_metadata && avail >= min_free) { | 2231 | if (device->in_fs_metadata && avail >= min_free) { |
| 2221 | ret = find_free_dev_extent(trans, device, | 2232 | ret = find_free_dev_extent(trans, device, |
| 2222 | min_free, &dev_offset); | 2233 | min_free, &dev_offset, |
| 2234 | &max_avail); | ||
| 2223 | if (ret == 0) { | 2235 | if (ret == 0) { |
| 2224 | list_move_tail(&device->dev_alloc_list, | 2236 | list_move_tail(&device->dev_alloc_list, |
| 2225 | &private_devs); | 2237 | &private_devs); |
| @@ -2795,26 +2807,6 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
| 2795 | } | 2807 | } |
| 2796 | } | 2808 | } |
| 2797 | 2809 | ||
| 2798 | for (i = 0; i > nr; i++) { | ||
| 2799 | struct btrfs_multi_bio *multi; | ||
| 2800 | struct btrfs_bio_stripe *stripe; | ||
| 2801 | int ret; | ||
| 2802 | |||
| 2803 | length = 1; | ||
| 2804 | ret = btrfs_map_block(map_tree, WRITE, buf[i], | ||
| 2805 | &length, &multi, 0); | ||
| 2806 | BUG_ON(ret); | ||
| 2807 | |||
| 2808 | stripe = multi->stripes; | ||
| 2809 | for (j = 0; j < multi->num_stripes; j++) { | ||
| 2810 | if (stripe->physical >= physical && | ||
| 2811 | physical < stripe->physical + length) | ||
| 2812 | break; | ||
| 2813 | } | ||
| 2814 | BUG_ON(j >= multi->num_stripes); | ||
| 2815 | kfree(multi); | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | *logical = buf; | 2810 | *logical = buf; |
| 2819 | *naddrs = nr; | 2811 | *naddrs = nr; |
| 2820 | *stripe_len = map->stripe_len; | 2812 | *stripe_len = map->stripe_len; |
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index ecfbce836d32..3e2b90eaa239 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c | |||
| @@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping, | |||
| 208 | *total_in = 0; | 208 | *total_in = 0; |
| 209 | 209 | ||
| 210 | workspace = find_zlib_workspace(); | 210 | workspace = find_zlib_workspace(); |
| 211 | if (!workspace) | 211 | if (IS_ERR(workspace)) |
| 212 | return -1; | 212 | return -1; |
| 213 | 213 | ||
| 214 | if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { | 214 | if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) { |
| @@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in, | |||
| 366 | char *kaddr; | 366 | char *kaddr; |
| 367 | 367 | ||
| 368 | workspace = find_zlib_workspace(); | 368 | workspace = find_zlib_workspace(); |
| 369 | if (!workspace) | 369 | if (IS_ERR(workspace)) |
| 370 | return -ENOMEM; | 370 | return -ENOMEM; |
| 371 | 371 | ||
| 372 | data_in = kmap(pages_in[page_in_index]); | 372 | data_in = kmap(pages_in[page_in_index]); |
| @@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in, | |||
| 547 | return -ENOMEM; | 547 | return -ENOMEM; |
| 548 | 548 | ||
| 549 | workspace = find_zlib_workspace(); | 549 | workspace = find_zlib_workspace(); |
| 550 | if (!workspace) | 550 | if (IS_ERR(workspace)) |
| 551 | return -ENOMEM; | 551 | return -ENOMEM; |
| 552 | 552 | ||
| 553 | workspace->inf_strm.next_in = data_in; | 553 | workspace->inf_strm.next_in = data_in; |
diff --git a/fs/buffer.c b/fs/buffer.c index a3ef091a45bd..28f320fac4d4 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -1165,8 +1165,11 @@ void mark_buffer_dirty(struct buffer_head *bh) | |||
| 1165 | 1165 | ||
| 1166 | if (!test_set_buffer_dirty(bh)) { | 1166 | if (!test_set_buffer_dirty(bh)) { |
| 1167 | struct page *page = bh->b_page; | 1167 | struct page *page = bh->b_page; |
| 1168 | if (!TestSetPageDirty(page)) | 1168 | if (!TestSetPageDirty(page)) { |
| 1169 | __set_page_dirty(page, page_mapping(page), 0); | 1169 | struct address_space *mapping = page_mapping(page); |
| 1170 | if (mapping) | ||
| 1171 | __set_page_dirty(page, mapping, 0); | ||
| 1172 | } | ||
| 1170 | } | 1173 | } |
| 1171 | } | 1174 | } |
| 1172 | 1175 | ||
diff --git a/fs/char_dev.c b/fs/char_dev.c index b7c9d5187a75..a173551e19d7 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/major.h> | 13 | #include <linux/major.h> |
| 14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 17 | #include <linux/seq_file.h> | 16 | #include <linux/seq_file.h> |
| 18 | 17 | ||
| 19 | #include <linux/kobject.h> | 18 | #include <linux/kobject.h> |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3a9b7a58a51d..e85b1e4389e0 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | Version 1.60 | ||
| 2 | ------------- | ||
| 3 | Fix memory leak in reconnect. Fix oops in DFS mount error path. | ||
| 4 | Set s_maxbytes to smaller (the max that vfs can handle) so that | ||
| 5 | sendfile will now work over cifs mounts again. Add noforcegid | ||
| 6 | and noforceuid mount parameters. | ||
| 7 | |||
| 1 | Version 1.59 | 8 | Version 1.59 |
| 2 | ------------ | 9 | ------------ |
| 3 | Client uses server inode numbers (which are persistent) rather than | 10 | Client uses server inode numbers (which are persistent) rather than |
| @@ -5,7 +12,11 @@ client generated ones by default (mount option "serverino" turned | |||
| 5 | on by default if server supports it). Add forceuid and forcegid | 12 | on by default if server supports it). Add forceuid and forcegid |
| 6 | mount options (so that when negotiating unix extensions specifying | 13 | mount options (so that when negotiating unix extensions specifying |
| 7 | which uid mounted does not immediately force the server's reported | 14 | which uid mounted does not immediately force the server's reported |
| 8 | uids to be overridden). Add support for scope moutn parm. | 15 | uids to be overridden). Add support for scope mount parm. Improve |
| 16 | hard link detection to use same inode for both. Do not set | ||
| 17 | read-only dos attribute on directories (for chmod) since Windows | ||
| 18 | explorer special cases this attribute bit for directories for | ||
| 19 | a different purpose. | ||
| 9 | 20 | ||
| 10 | Version 1.58 | 21 | Version 1.58 |
| 11 | ------------ | 22 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index ad92921dbde4..79c1a93400be 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
| @@ -262,11 +262,11 @@ A partial list of the supported mount options follows: | |||
| 262 | mount. | 262 | mount. |
| 263 | domain Set the SMB/CIFS workgroup name prepended to the | 263 | domain Set the SMB/CIFS workgroup name prepended to the |
| 264 | username during CIFS session establishment | 264 | username during CIFS session establishment |
| 265 | forceuid Set the default uid for inodes based on the uid | 265 | forceuid Set the default uid for inodes to the uid |
| 266 | passed in. For mounts to servers | 266 | passed in on mount. For mounts to servers |
| 267 | which do support the CIFS Unix extensions, such as a | 267 | which do support the CIFS Unix extensions, such as a |
| 268 | properly configured Samba server, the server provides | 268 | properly configured Samba server, the server provides |
| 269 | the uid, gid and mode so this parameter should not be | 269 | the uid, gid and mode so this parameter should not be |
| 270 | specified unless the server and clients uid and gid | 270 | specified unless the server and clients uid and gid |
| 271 | numbering differ. If the server and client are in the | 271 | numbering differ. If the server and client are in the |
| 272 | same domain (e.g. running winbind or nss_ldap) and | 272 | same domain (e.g. running winbind or nss_ldap) and |
| @@ -278,11 +278,7 @@ A partial list of the supported mount options follows: | |||
| 278 | of existing files will be the uid (gid) of the person | 278 | of existing files will be the uid (gid) of the person |
| 279 | who executed the mount (root, except when mount.cifs | 279 | who executed the mount (root, except when mount.cifs |
| 280 | is configured setuid for user mounts) unless the "uid=" | 280 | is configured setuid for user mounts) unless the "uid=" |
| 281 | (gid) mount option is specified. For the uid (gid) of newly | 281 | (gid) mount option is specified. Also note that permission |
| 282 | created files and directories, ie files created since | ||
| 283 | the last mount of the server share, the expected uid | ||
| 284 | (gid) is cached as long as the inode remains in | ||
| 285 | memory on the client. Also note that permission | ||
| 286 | checks (authorization checks) on accesses to a file occur | 282 | checks (authorization checks) on accesses to a file occur |
| 287 | at the server, but there are cases in which an administrator | 283 | at the server, but there are cases in which an administrator |
| 288 | may want to restrict at the client as well. For those | 284 | may want to restrict at the client as well. For those |
| @@ -290,12 +286,15 @@ A partial list of the supported mount options follows: | |||
| 290 | (such as Windows), permissions can also be checked at the | 286 | (such as Windows), permissions can also be checked at the |
| 291 | client, and a crude form of client side permission checking | 287 | client, and a crude form of client side permission checking |
| 292 | can be enabled by specifying file_mode and dir_mode on | 288 | can be enabled by specifying file_mode and dir_mode on |
| 293 | the client. Note that the mount.cifs helper must be | 289 | the client. (default) |
| 294 | at version 1.10 or higher to support specifying the uid | 290 | forcegid (similar to above but for the groupid instead of uid) (default) |
| 295 | (or gid) in non-numeric form. | 291 | noforceuid Fill in file owner information (uid) by requesting it from |
| 296 | forcegid (similar to above but for the groupid instead of uid) | 292 | the server if possible. With this option, the value given in |
| 293 | the uid= option (on mount) will only be used if the server | ||
| 294 | can not support returning uids on inodes. | ||
| 295 | noforcegid (similar to above but for the group owner, gid, instead of uid) | ||
| 297 | uid Set the default uid for inodes, and indicate to the | 296 | uid Set the default uid for inodes, and indicate to the |
| 298 | cifs kernel driver which local user mounted . If the server | 297 | cifs kernel driver which local user mounted. If the server |
| 299 | supports the unix extensions the default uid is | 298 | supports the unix extensions the default uid is |
| 300 | not used to fill in the owner fields of inodes (files) | 299 | not used to fill in the owner fields of inodes (files) |
| 301 | unless the "forceuid" parameter is specified. | 300 | unless the "forceuid" parameter is specified. |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 7f19fefd3d45..42cec2a7c0cf 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -261,6 +261,8 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
| 261 | atomic_set(&tcon->num_reads, 0); | 261 | atomic_set(&tcon->num_reads, 0); |
| 262 | atomic_set(&tcon->num_oplock_brks, 0); | 262 | atomic_set(&tcon->num_oplock_brks, 0); |
| 263 | atomic_set(&tcon->num_opens, 0); | 263 | atomic_set(&tcon->num_opens, 0); |
| 264 | atomic_set(&tcon->num_posixopens, 0); | ||
| 265 | atomic_set(&tcon->num_posixmkdirs, 0); | ||
| 264 | atomic_set(&tcon->num_closes, 0); | 266 | atomic_set(&tcon->num_closes, 0); |
| 265 | atomic_set(&tcon->num_deletes, 0); | 267 | atomic_set(&tcon->num_deletes, 0); |
| 266 | atomic_set(&tcon->num_mkdirs, 0); | 268 | atomic_set(&tcon->num_mkdirs, 0); |
| @@ -347,11 +349,15 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
| 347 | atomic_read(&tcon->num_locks), | 349 | atomic_read(&tcon->num_locks), |
| 348 | atomic_read(&tcon->num_hardlinks), | 350 | atomic_read(&tcon->num_hardlinks), |
| 349 | atomic_read(&tcon->num_symlinks)); | 351 | atomic_read(&tcon->num_symlinks)); |
| 350 | seq_printf(m, "\nOpens: %d Closes: %d" | 352 | seq_printf(m, "\nOpens: %d Closes: %d " |
| 351 | "Deletes: %d", | 353 | "Deletes: %d", |
| 352 | atomic_read(&tcon->num_opens), | 354 | atomic_read(&tcon->num_opens), |
| 353 | atomic_read(&tcon->num_closes), | 355 | atomic_read(&tcon->num_closes), |
| 354 | atomic_read(&tcon->num_deletes)); | 356 | atomic_read(&tcon->num_deletes)); |
| 357 | seq_printf(m, "\nPosix Opens: %d " | ||
| 358 | "Posix Mkdirs: %d", | ||
| 359 | atomic_read(&tcon->num_posixopens), | ||
| 360 | atomic_read(&tcon->num_posixmkdirs)); | ||
| 355 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", | 361 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", |
| 356 | atomic_read(&tcon->num_mkdirs), | 362 | atomic_read(&tcon->num_mkdirs), |
| 357 | atomic_read(&tcon->num_rmdirs)); | 363 | atomic_read(&tcon->num_rmdirs)); |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 3bb11be8b6a8..606912d8f2a8 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
| @@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void) | |||
| 55 | * i.e. strips from UNC trailing path that is not part of share | 55 | * i.e. strips from UNC trailing path that is not part of share |
| 56 | * name and fixup missing '\' in the begining of DFS node refferal | 56 | * name and fixup missing '\' in the begining of DFS node refferal |
| 57 | * if neccessary. | 57 | * if neccessary. |
| 58 | * Returns pointer to share name on success or NULL on error. | 58 | * Returns pointer to share name on success or ERR_PTR on error. |
| 59 | * Caller is responsible for freeing returned string. | 59 | * Caller is responsible for freeing returned string. |
| 60 | */ | 60 | */ |
| 61 | static char *cifs_get_share_name(const char *node_name) | 61 | static char *cifs_get_share_name(const char *node_name) |
| @@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 68 | UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, | 68 | UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, |
| 69 | GFP_KERNEL); | 69 | GFP_KERNEL); |
| 70 | if (!UNC) | 70 | if (!UNC) |
| 71 | return NULL; | 71 | return ERR_PTR(-ENOMEM); |
| 72 | 72 | ||
| 73 | /* get share name and server name */ | 73 | /* get share name and server name */ |
| 74 | if (node_name[1] != '\\') { | 74 | if (node_name[1] != '\\') { |
| @@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 87 | cERROR(1, ("%s: no server name end in node name: %s", | 87 | cERROR(1, ("%s: no server name end in node name: %s", |
| 88 | __func__, node_name)); | 88 | __func__, node_name)); |
| 89 | kfree(UNC); | 89 | kfree(UNC); |
| 90 | return NULL; | 90 | return ERR_PTR(-EINVAL); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /* find sharename end */ | 93 | /* find sharename end */ |
| @@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata, | |||
| 133 | return ERR_PTR(-EINVAL); | 133 | return ERR_PTR(-EINVAL); |
| 134 | 134 | ||
| 135 | *devname = cifs_get_share_name(ref->node_name); | 135 | *devname = cifs_get_share_name(ref->node_name); |
| 136 | if (IS_ERR(*devname)) { | ||
| 137 | rc = PTR_ERR(*devname); | ||
| 138 | *devname = NULL; | ||
| 139 | goto compose_mount_options_err; | ||
| 140 | } | ||
| 141 | |||
| 136 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 142 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
| 137 | if (rc != 0) { | 143 | if (rc != 0) { |
| 138 | cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", | 144 | cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 4a4581cb2b5e..051caecf7d67 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
| @@ -86,6 +86,9 @@ struct key_type cifs_spnego_key_type = { | |||
| 86 | /* strlen of ";user=" */ | 86 | /* strlen of ";user=" */ |
| 87 | #define USER_KEY_LEN 6 | 87 | #define USER_KEY_LEN 6 |
| 88 | 88 | ||
| 89 | /* strlen of ";pid=0x" */ | ||
| 90 | #define PID_KEY_LEN 7 | ||
| 91 | |||
| 89 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ | 92 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ |
| 90 | struct key * | 93 | struct key * |
| 91 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | 94 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) |
| @@ -103,7 +106,8 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
| 103 | IP_KEY_LEN + INET6_ADDRSTRLEN + | 106 | IP_KEY_LEN + INET6_ADDRSTRLEN + |
| 104 | MAX_MECH_STR_LEN + | 107 | MAX_MECH_STR_LEN + |
| 105 | UID_KEY_LEN + (sizeof(uid_t) * 2) + | 108 | UID_KEY_LEN + (sizeof(uid_t) * 2) + |
| 106 | USER_KEY_LEN + strlen(sesInfo->userName) + 1; | 109 | USER_KEY_LEN + strlen(sesInfo->userName) + |
| 110 | PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; | ||
| 107 | 111 | ||
| 108 | spnego_key = ERR_PTR(-ENOMEM); | 112 | spnego_key = ERR_PTR(-ENOMEM); |
| 109 | description = kzalloc(desc_len, GFP_KERNEL); | 113 | description = kzalloc(desc_len, GFP_KERNEL); |
| @@ -141,6 +145,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
| 141 | dp = description + strlen(description); | 145 | dp = description + strlen(description); |
| 142 | sprintf(dp, ";user=%s", sesInfo->userName); | 146 | sprintf(dp, ";user=%s", sesInfo->userName); |
| 143 | 147 | ||
| 148 | dp = description + strlen(description); | ||
| 149 | sprintf(dp, ";pid=0x%x", current->pid); | ||
| 150 | |||
| 144 | cFYI(1, ("key description = %s", description)); | 151 | cFYI(1, ("key description = %s", description)); |
| 145 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); | 152 | spnego_key = request_key(&cifs_spnego_key_type, description, ""); |
| 146 | 153 | ||
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 60e3c4253de0..714a542cbafc 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
| @@ -44,7 +44,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 44 | int maxwords = maxbytes / 2; | 44 | int maxwords = maxbytes / 2; |
| 45 | char tmp[NLS_MAX_CHARSET_SIZE]; | 45 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 46 | 46 | ||
| 47 | for (i = 0; from[i] && i < maxwords; i++) { | 47 | for (i = 0; i < maxwords && from[i]; i++) { |
| 48 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, | 48 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, |
| 49 | NLS_MAX_CHARSET_SIZE); | 49 | NLS_MAX_CHARSET_SIZE); |
| 50 | if (charlen > 0) | 50 | if (charlen > 0) |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 1403b5d86a73..6941c22398a6 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) | |||
| 327 | 327 | ||
| 328 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | 328 | static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, |
| 329 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, | 329 | struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, |
| 330 | struct inode *inode) | 330 | struct cifs_fattr *fattr) |
| 331 | { | 331 | { |
| 332 | int i; | 332 | int i; |
| 333 | int num_aces = 0; | 333 | int num_aces = 0; |
| @@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
| 340 | if (!pdacl) { | 340 | if (!pdacl) { |
| 341 | /* no DACL in the security descriptor, set | 341 | /* no DACL in the security descriptor, set |
| 342 | all the permissions for user/group/other */ | 342 | all the permissions for user/group/other */ |
| 343 | inode->i_mode |= S_IRWXUGO; | 343 | fattr->cf_mode |= S_IRWXUGO; |
| 344 | return; | 344 | return; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| @@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
| 357 | /* reset rwx permissions for user/group/other. | 357 | /* reset rwx permissions for user/group/other. |
| 358 | Also, if num_aces is 0 i.e. DACL has no ACEs, | 358 | Also, if num_aces is 0 i.e. DACL has no ACEs, |
| 359 | user/group/other have no permissions */ | 359 | user/group/other have no permissions */ |
| 360 | inode->i_mode &= ~(S_IRWXUGO); | 360 | fattr->cf_mode &= ~(S_IRWXUGO); |
| 361 | 361 | ||
| 362 | acl_base = (char *)pdacl; | 362 | acl_base = (char *)pdacl; |
| 363 | acl_size = sizeof(struct cifs_acl); | 363 | acl_size = sizeof(struct cifs_acl); |
| @@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
| 379 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 379 | if (compare_sids(&(ppace[i]->sid), pownersid)) |
| 380 | access_flags_to_mode(ppace[i]->access_req, | 380 | access_flags_to_mode(ppace[i]->access_req, |
| 381 | ppace[i]->type, | 381 | ppace[i]->type, |
| 382 | &(inode->i_mode), | 382 | &fattr->cf_mode, |
| 383 | &user_mask); | 383 | &user_mask); |
| 384 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 384 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) |
| 385 | access_flags_to_mode(ppace[i]->access_req, | 385 | access_flags_to_mode(ppace[i]->access_req, |
| 386 | ppace[i]->type, | 386 | ppace[i]->type, |
| 387 | &(inode->i_mode), | 387 | &fattr->cf_mode, |
| 388 | &group_mask); | 388 | &group_mask); |
| 389 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 389 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) |
| 390 | access_flags_to_mode(ppace[i]->access_req, | 390 | access_flags_to_mode(ppace[i]->access_req, |
| 391 | ppace[i]->type, | 391 | ppace[i]->type, |
| 392 | &(inode->i_mode), | 392 | &fattr->cf_mode, |
| 393 | &other_mask); | 393 | &other_mask); |
| 394 | 394 | ||
| 395 | /* memcpy((void *)(&(cifscred->aces[i])), | 395 | /* memcpy((void *)(&(cifscred->aces[i])), |
| @@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
| 464 | 464 | ||
| 465 | /* Convert CIFS ACL to POSIX form */ | 465 | /* Convert CIFS ACL to POSIX form */ |
| 466 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | 466 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, |
| 467 | struct inode *inode) | 467 | struct cifs_fattr *fattr) |
| 468 | { | 468 | { |
| 469 | int rc; | 469 | int rc; |
| 470 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 470 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
| @@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
| 472 | char *end_of_acl = ((char *)pntsd) + acl_len; | 472 | char *end_of_acl = ((char *)pntsd) + acl_len; |
| 473 | __u32 dacloffset; | 473 | __u32 dacloffset; |
| 474 | 474 | ||
| 475 | if ((inode == NULL) || (pntsd == NULL)) | 475 | if (pntsd == NULL) |
| 476 | return -EIO; | 476 | return -EIO; |
| 477 | 477 | ||
| 478 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | 478 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
| @@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
| 497 | 497 | ||
| 498 | if (dacloffset) | 498 | if (dacloffset) |
| 499 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 499 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
| 500 | group_sid_ptr, inode); | 500 | group_sid_ptr, fattr); |
| 501 | else | 501 | else |
| 502 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ | 502 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ |
| 503 | 503 | ||
| @@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
| 508 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 508 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
| 509 | sizeof(struct cifs_sid)); */ | 509 | sizeof(struct cifs_sid)); */ |
| 510 | 510 | ||
| 511 | |||
| 512 | return 0; | 511 | return 0; |
| 513 | } | 512 | } |
| 514 | 513 | ||
| @@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 671 | } | 670 | } |
| 672 | 671 | ||
| 673 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 672 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
| 674 | void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | 673 | void |
| 675 | const char *path, const __u16 *pfid) | 674 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 675 | struct inode *inode, const char *path, const __u16 *pfid) | ||
| 676 | { | 676 | { |
| 677 | struct cifs_ntsd *pntsd = NULL; | 677 | struct cifs_ntsd *pntsd = NULL; |
| 678 | u32 acllen = 0; | 678 | u32 acllen = 0; |
| @@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | |||
| 687 | 687 | ||
| 688 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 688 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
| 689 | if (pntsd) | 689 | if (pntsd) |
| 690 | rc = parse_sec_desc(pntsd, acllen, inode); | 690 | rc = parse_sec_desc(pntsd, acllen, fattr); |
| 691 | if (rc) | 691 | if (rc) |
| 692 | cFYI(1, ("parse sec desc failed rc = %d", rc)); | 692 | cFYI(1, ("parse sec desc failed rc = %d", rc)); |
| 693 | 693 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9f669f982c4d..84b75253b05a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -308,7 +308,6 @@ cifs_alloc_inode(struct super_block *sb) | |||
| 308 | if (!cifs_inode) | 308 | if (!cifs_inode) |
| 309 | return NULL; | 309 | return NULL; |
| 310 | cifs_inode->cifsAttrs = 0x20; /* default */ | 310 | cifs_inode->cifsAttrs = 0x20; /* default */ |
| 311 | atomic_set(&cifs_inode->inUse, 0); | ||
| 312 | cifs_inode->time = 0; | 311 | cifs_inode->time = 0; |
| 313 | cifs_inode->write_behind_rc = 0; | 312 | cifs_inode->write_behind_rc = 0; |
| 314 | /* Until the file is open and we have gotten oplock | 313 | /* Until the file is open and we have gotten oplock |
| @@ -377,10 +376,14 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 377 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | 376 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); |
| 378 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 377 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 379 | seq_printf(s, ",forceuid"); | 378 | seq_printf(s, ",forceuid"); |
| 379 | else | ||
| 380 | seq_printf(s, ",noforceuid"); | ||
| 380 | 381 | ||
| 381 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | 382 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); |
| 382 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | 383 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 383 | seq_printf(s, ",forcegid"); | 384 | seq_printf(s, ",forcegid"); |
| 385 | else | ||
| 386 | seq_printf(s, ",noforcegid"); | ||
| 384 | 387 | ||
| 385 | cifs_show_address(s, tcon->ses->server); | 388 | cifs_show_address(s, tcon->ses->server); |
| 386 | 389 | ||
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 9570a0e8023f..6c170948300d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -24,6 +24,19 @@ | |||
| 24 | 24 | ||
| 25 | #define ROOT_I 2 | 25 | #define ROOT_I 2 |
| 26 | 26 | ||
| 27 | /* | ||
| 28 | * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down | ||
| 29 | * so that it will fit. | ||
| 30 | */ | ||
| 31 | static inline ino_t | ||
| 32 | cifs_uniqueid_to_ino_t(u64 fileid) | ||
| 33 | { | ||
| 34 | ino_t ino = (ino_t) fileid; | ||
| 35 | if (sizeof(ino_t) < sizeof(u64)) | ||
| 36 | ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8; | ||
| 37 | return ino; | ||
| 38 | } | ||
| 39 | |||
| 27 | extern struct file_system_type cifs_fs_type; | 40 | extern struct file_system_type cifs_fs_type; |
| 28 | extern const struct address_space_operations cifs_addr_ops; | 41 | extern const struct address_space_operations cifs_addr_ops; |
| 29 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
| @@ -100,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 100 | extern const struct export_operations cifs_export_ops; | 113 | extern const struct export_operations cifs_export_ops; |
| 101 | #endif /* EXPERIMENTAL */ | 114 | #endif /* EXPERIMENTAL */ |
| 102 | 115 | ||
| 103 | #define CIFS_VERSION "1.59" | 116 | #define CIFS_VERSION "1.60" |
| 104 | #endif /* _CIFSFS_H */ | 117 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e1225e6ded2f..6084d6379c03 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -260,6 +260,8 @@ struct cifsTconInfo { | |||
| 260 | atomic_t num_closes; | 260 | atomic_t num_closes; |
| 261 | atomic_t num_deletes; | 261 | atomic_t num_deletes; |
| 262 | atomic_t num_mkdirs; | 262 | atomic_t num_mkdirs; |
| 263 | atomic_t num_posixopens; | ||
| 264 | atomic_t num_posixmkdirs; | ||
| 263 | atomic_t num_rmdirs; | 265 | atomic_t num_rmdirs; |
| 264 | atomic_t num_renames; | 266 | atomic_t num_renames; |
| 265 | atomic_t num_t2renames; | 267 | atomic_t num_t2renames; |
| @@ -364,13 +366,13 @@ struct cifsInodeInfo { | |||
| 364 | struct list_head openFileList; | 366 | struct list_head openFileList; |
| 365 | int write_behind_rc; | 367 | int write_behind_rc; |
| 366 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 368 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
| 367 | atomic_t inUse; /* num concurrent users (local openers cifs) of file*/ | ||
| 368 | unsigned long time; /* jiffies of last update/check of inode */ | 369 | unsigned long time; /* jiffies of last update/check of inode */ |
| 369 | bool clientCanCacheRead:1; /* read oplock */ | 370 | bool clientCanCacheRead:1; /* read oplock */ |
| 370 | bool clientCanCacheAll:1; /* read and writebehind oplock */ | 371 | bool clientCanCacheAll:1; /* read and writebehind oplock */ |
| 371 | bool oplockPending:1; | 372 | bool oplockPending:1; |
| 372 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 373 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ |
| 373 | u64 server_eof; /* current file size on server */ | 374 | u64 server_eof; /* current file size on server */ |
| 375 | u64 uniqueid; /* server inode number */ | ||
| 374 | struct inode vfs_inode; | 376 | struct inode vfs_inode; |
| 375 | }; | 377 | }; |
| 376 | 378 | ||
| @@ -472,6 +474,32 @@ struct dfs_info3_param { | |||
| 472 | char *node_name; | 474 | char *node_name; |
| 473 | }; | 475 | }; |
| 474 | 476 | ||
| 477 | /* | ||
| 478 | * common struct for holding inode info when searching for or updating an | ||
| 479 | * inode with new info | ||
| 480 | */ | ||
| 481 | |||
| 482 | #define CIFS_FATTR_DFS_REFERRAL 0x1 | ||
| 483 | #define CIFS_FATTR_DELETE_PENDING 0x2 | ||
| 484 | #define CIFS_FATTR_NEED_REVAL 0x4 | ||
| 485 | |||
| 486 | struct cifs_fattr { | ||
| 487 | u32 cf_flags; | ||
| 488 | u32 cf_cifsattrs; | ||
| 489 | u64 cf_uniqueid; | ||
| 490 | u64 cf_eof; | ||
| 491 | u64 cf_bytes; | ||
| 492 | uid_t cf_uid; | ||
| 493 | gid_t cf_gid; | ||
| 494 | umode_t cf_mode; | ||
| 495 | dev_t cf_rdev; | ||
| 496 | unsigned int cf_nlink; | ||
| 497 | unsigned int cf_dtype; | ||
| 498 | struct timespec cf_atime; | ||
| 499 | struct timespec cf_mtime; | ||
| 500 | struct timespec cf_ctime; | ||
| 501 | }; | ||
| 502 | |||
| 475 | static inline void free_dfs_info_param(struct dfs_info3_param *param) | 503 | static inline void free_dfs_info_param(struct dfs_info3_param *param) |
| 476 | { | 504 | { |
| 477 | if (param) { | 505 | if (param) { |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index a785f69dbc9f..2d07f890a842 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -2328,19 +2328,7 @@ struct file_attrib_tag { | |||
| 2328 | typedef struct { | 2328 | typedef struct { |
| 2329 | __le32 NextEntryOffset; | 2329 | __le32 NextEntryOffset; |
| 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ | 2330 | __u32 ResumeKey; /* as with FileIndex - no need to convert */ |
| 2331 | __le64 EndOfFile; | 2331 | FILE_UNIX_BASIC_INFO basic; |
| 2332 | __le64 NumOfBytes; | ||
| 2333 | __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */ | ||
| 2334 | __le64 LastAccessTime; | ||
| 2335 | __le64 LastModificationTime; | ||
| 2336 | __le64 Uid; | ||
| 2337 | __le64 Gid; | ||
| 2338 | __le32 Type; | ||
| 2339 | __le64 DevMajor; | ||
| 2340 | __le64 DevMinor; | ||
| 2341 | __le64 UniqueId; | ||
| 2342 | __le64 Permissions; | ||
| 2343 | __le64 Nlinks; | ||
| 2344 | char FileName[1]; | 2332 | char FileName[1]; |
| 2345 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ | 2333 | } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */ |
| 2346 | 2334 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c419416a42ee..da8fbf565991 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -98,9 +98,13 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | |||
| 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, | 98 | extern int cifs_posix_open(char *full_path, struct inode **pinode, |
| 99 | struct super_block *sb, int mode, int oflags, | 99 | struct super_block *sb, int mode, int oflags, |
| 100 | int *poplock, __u16 *pnetfid, int xid); | 100 | int *poplock, __u16 *pnetfid, int xid); |
| 101 | extern void posix_fill_in_inode(struct inode *tmp_inode, | 101 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
| 102 | FILE_UNIX_BASIC_INFO *pData, int isNewInode); | 102 | FILE_UNIX_BASIC_INFO *info, |
| 103 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); | 103 | struct cifs_sb_info *cifs_sb); |
| 104 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | ||
| 105 | extern struct inode *cifs_iget(struct super_block *sb, | ||
| 106 | struct cifs_fattr *fattr); | ||
| 107 | |||
| 104 | extern int cifs_get_inode_info(struct inode **pinode, | 108 | extern int cifs_get_inode_info(struct inode **pinode, |
| 105 | const unsigned char *search_path, | 109 | const unsigned char *search_path, |
| 106 | FILE_ALL_INFO *pfile_info, | 110 | FILE_ALL_INFO *pfile_info, |
| @@ -108,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode, | |||
| 108 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 112 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
| 109 | const unsigned char *search_path, | 113 | const unsigned char *search_path, |
| 110 | struct super_block *sb, int xid); | 114 | struct super_block *sb, int xid); |
| 111 | extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, | 115 | extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
| 112 | const char *path, const __u16 *pfid); | 116 | struct cifs_fattr *fattr, struct inode *inode, |
| 117 | const char *path, const __u16 *pfid); | ||
| 113 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 118 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); |
| 114 | 119 | ||
| 115 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 120 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
| @@ -215,7 +220,11 @@ struct cifs_unix_set_info_args { | |||
| 215 | dev_t device; | 220 | dev_t device; |
| 216 | }; | 221 | }; |
| 217 | 222 | ||
| 218 | extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon, | 223 | extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
| 224 | const struct cifs_unix_set_info_args *args, | ||
| 225 | u16 fid, u32 pid_of_opener); | ||
| 226 | |||
| 227 | extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, | ||
| 219 | char *fileName, | 228 | char *fileName, |
| 220 | const struct cifs_unix_set_info_args *args, | 229 | const struct cifs_unix_set_info_args *args, |
| 221 | const struct nls_table *nls_codepage, | 230 | const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61007c627497..1866bc2927d4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1113,7 +1113,10 @@ PsxCreat: | |||
| 1113 | psx_create_err: | 1113 | psx_create_err: |
| 1114 | cifs_buf_release(pSMB); | 1114 | cifs_buf_release(pSMB); |
| 1115 | 1115 | ||
| 1116 | cifs_stats_inc(&tcon->num_mkdirs); | 1116 | if (posix_flags & SMB_O_DIRECTORY) |
| 1117 | cifs_stats_inc(&tcon->num_posixmkdirs); | ||
| 1118 | else | ||
| 1119 | cifs_stats_inc(&tcon->num_posixopens); | ||
| 1117 | 1120 | ||
| 1118 | if (rc == -EAGAIN) | 1121 | if (rc == -EAGAIN) |
| 1119 | goto PsxCreat; | 1122 | goto PsxCreat; |
| @@ -5074,10 +5077,114 @@ SetAttrLgcyRetry: | |||
| 5074 | } | 5077 | } |
| 5075 | #endif /* temporarily unneeded SetAttr legacy function */ | 5078 | #endif /* temporarily unneeded SetAttr legacy function */ |
| 5076 | 5079 | ||
| 5080 | static void | ||
| 5081 | cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | ||
| 5082 | const struct cifs_unix_set_info_args *args) | ||
| 5083 | { | ||
| 5084 | u64 mode = args->mode; | ||
| 5085 | |||
| 5086 | /* | ||
| 5087 | * Samba server ignores set of file size to zero due to bugs in some | ||
| 5088 | * older clients, but we should be precise - we use SetFileSize to | ||
| 5089 | * set file size and do not want to truncate file size to zero | ||
| 5090 | * accidently as happened on one Samba server beta by putting | ||
| 5091 | * zero instead of -1 here | ||
| 5092 | */ | ||
| 5093 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
| 5094 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
| 5095 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
| 5096 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
| 5097 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
| 5098 | data_offset->Uid = cpu_to_le64(args->uid); | ||
| 5099 | data_offset->Gid = cpu_to_le64(args->gid); | ||
| 5100 | /* better to leave device as zero when it is */ | ||
| 5101 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
| 5102 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
| 5103 | data_offset->Permissions = cpu_to_le64(mode); | ||
| 5104 | |||
| 5105 | if (S_ISREG(mode)) | ||
| 5106 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
| 5107 | else if (S_ISDIR(mode)) | ||
| 5108 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
| 5109 | else if (S_ISLNK(mode)) | ||
| 5110 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
| 5111 | else if (S_ISCHR(mode)) | ||
| 5112 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
| 5113 | else if (S_ISBLK(mode)) | ||
| 5114 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
| 5115 | else if (S_ISFIFO(mode)) | ||
| 5116 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
| 5117 | else if (S_ISSOCK(mode)) | ||
| 5118 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
| 5119 | } | ||
| 5120 | |||
| 5077 | int | 5121 | int |
| 5078 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5122 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
| 5079 | const struct cifs_unix_set_info_args *args, | 5123 | const struct cifs_unix_set_info_args *args, |
| 5080 | const struct nls_table *nls_codepage, int remap) | 5124 | u16 fid, u32 pid_of_opener) |
| 5125 | { | ||
| 5126 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | ||
| 5127 | FILE_UNIX_BASIC_INFO *data_offset; | ||
| 5128 | int rc = 0; | ||
| 5129 | u16 params, param_offset, offset, byte_count, count; | ||
| 5130 | |||
| 5131 | cFYI(1, ("Set Unix Info (via SetFileInfo)")); | ||
| 5132 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | ||
| 5133 | |||
| 5134 | if (rc) | ||
| 5135 | return rc; | ||
| 5136 | |||
| 5137 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | ||
| 5138 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | ||
| 5139 | |||
| 5140 | params = 6; | ||
| 5141 | pSMB->MaxSetupCount = 0; | ||
| 5142 | pSMB->Reserved = 0; | ||
| 5143 | pSMB->Flags = 0; | ||
| 5144 | pSMB->Timeout = 0; | ||
| 5145 | pSMB->Reserved2 = 0; | ||
| 5146 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | ||
| 5147 | offset = param_offset + params; | ||
| 5148 | |||
| 5149 | data_offset = (FILE_UNIX_BASIC_INFO *) | ||
| 5150 | ((char *)(&pSMB->hdr.Protocol) + offset); | ||
| 5151 | count = sizeof(FILE_UNIX_BASIC_INFO); | ||
| 5152 | |||
| 5153 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
| 5154 | /* BB find max SMB PDU from sess */ | ||
| 5155 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
| 5156 | pSMB->SetupCount = 1; | ||
| 5157 | pSMB->Reserved3 = 0; | ||
| 5158 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | ||
| 5159 | byte_count = 3 /* pad */ + params + count; | ||
| 5160 | pSMB->DataCount = cpu_to_le16(count); | ||
| 5161 | pSMB->ParameterCount = cpu_to_le16(params); | ||
| 5162 | pSMB->TotalDataCount = pSMB->DataCount; | ||
| 5163 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
| 5164 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
| 5165 | pSMB->DataOffset = cpu_to_le16(offset); | ||
| 5166 | pSMB->Fid = fid; | ||
| 5167 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | ||
| 5168 | pSMB->Reserved4 = 0; | ||
| 5169 | pSMB->hdr.smb_buf_length += byte_count; | ||
| 5170 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
| 5171 | |||
| 5172 | cifs_fill_unix_set_info(data_offset, args); | ||
| 5173 | |||
| 5174 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | ||
| 5175 | if (rc) | ||
| 5176 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | ||
| 5177 | |||
| 5178 | /* Note: On -EAGAIN error only caller can retry on handle based calls | ||
| 5179 | since file handle passed in no longer valid */ | ||
| 5180 | |||
| 5181 | return rc; | ||
| 5182 | } | ||
| 5183 | |||
| 5184 | int | ||
| 5185 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | ||
| 5186 | const struct cifs_unix_set_info_args *args, | ||
| 5187 | const struct nls_table *nls_codepage, int remap) | ||
| 5081 | { | 5188 | { |
| 5082 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 5189 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
| 5083 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 5190 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
| @@ -5086,7 +5193,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | |||
| 5086 | int bytes_returned = 0; | 5193 | int bytes_returned = 0; |
| 5087 | FILE_UNIX_BASIC_INFO *data_offset; | 5194 | FILE_UNIX_BASIC_INFO *data_offset; |
| 5088 | __u16 params, param_offset, offset, count, byte_count; | 5195 | __u16 params, param_offset, offset, count, byte_count; |
| 5089 | __u64 mode = args->mode; | ||
| 5090 | 5196 | ||
| 5091 | cFYI(1, ("In SetUID/GID/Mode")); | 5197 | cFYI(1, ("In SetUID/GID/Mode")); |
| 5092 | setPermsRetry: | 5198 | setPermsRetry: |
| @@ -5137,38 +5243,8 @@ setPermsRetry: | |||
| 5137 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5243 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
| 5138 | pSMB->Reserved4 = 0; | 5244 | pSMB->Reserved4 = 0; |
| 5139 | pSMB->hdr.smb_buf_length += byte_count; | 5245 | pSMB->hdr.smb_buf_length += byte_count; |
| 5140 | /* Samba server ignores set of file size to zero due to bugs in some | ||
| 5141 | older clients, but we should be precise - we use SetFileSize to | ||
| 5142 | set file size and do not want to truncate file size to zero | ||
| 5143 | accidently as happened on one Samba server beta by putting | ||
| 5144 | zero instead of -1 here */ | ||
| 5145 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
| 5146 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
| 5147 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
| 5148 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
| 5149 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
| 5150 | data_offset->Uid = cpu_to_le64(args->uid); | ||
| 5151 | data_offset->Gid = cpu_to_le64(args->gid); | ||
| 5152 | /* better to leave device as zero when it is */ | ||
| 5153 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
| 5154 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
| 5155 | data_offset->Permissions = cpu_to_le64(mode); | ||
| 5156 | |||
| 5157 | if (S_ISREG(mode)) | ||
| 5158 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
| 5159 | else if (S_ISDIR(mode)) | ||
| 5160 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
| 5161 | else if (S_ISLNK(mode)) | ||
| 5162 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
| 5163 | else if (S_ISCHR(mode)) | ||
| 5164 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
| 5165 | else if (S_ISBLK(mode)) | ||
| 5166 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
| 5167 | else if (S_ISFIFO(mode)) | ||
| 5168 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
| 5169 | else if (S_ISSOCK(mode)) | ||
| 5170 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
| 5171 | 5246 | ||
| 5247 | cifs_fill_unix_set_info(data_offset, args); | ||
| 5172 | 5248 | ||
| 5173 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5249 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5174 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5250 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e16d7592116a..1f3345d7fa79 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -803,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 803 | char *data; | 803 | char *data; |
| 804 | unsigned int temp_len, i, j; | 804 | unsigned int temp_len, i, j; |
| 805 | char separator[2]; | 805 | char separator[2]; |
| 806 | short int override_uid = -1; | ||
| 807 | short int override_gid = -1; | ||
| 808 | bool uid_specified = false; | ||
| 809 | bool gid_specified = false; | ||
| 806 | 810 | ||
| 807 | separator[0] = ','; | 811 | separator[0] = ','; |
| 808 | separator[1] = 0; | 812 | separator[1] = 0; |
| @@ -1093,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1093 | "too long.\n"); | 1097 | "too long.\n"); |
| 1094 | return 1; | 1098 | return 1; |
| 1095 | } | 1099 | } |
| 1096 | } else if (strnicmp(data, "uid", 3) == 0) { | 1100 | } else if (!strnicmp(data, "uid", 3) && value && *value) { |
| 1097 | if (value && *value) | 1101 | vol->linux_uid = simple_strtoul(value, &value, 0); |
| 1098 | vol->linux_uid = | 1102 | uid_specified = true; |
| 1099 | simple_strtoul(value, &value, 0); | 1103 | } else if (!strnicmp(data, "forceuid", 8)) { |
| 1100 | } else if (strnicmp(data, "forceuid", 8) == 0) { | 1104 | override_uid = 1; |
| 1101 | vol->override_uid = 1; | 1105 | } else if (!strnicmp(data, "noforceuid", 10)) { |
| 1102 | } else if (strnicmp(data, "gid", 3) == 0) { | 1106 | override_uid = 0; |
| 1103 | if (value && *value) | 1107 | } else if (!strnicmp(data, "gid", 3) && value && *value) { |
| 1104 | vol->linux_gid = | 1108 | vol->linux_gid = simple_strtoul(value, &value, 0); |
| 1105 | simple_strtoul(value, &value, 0); | 1109 | gid_specified = true; |
| 1106 | } else if (strnicmp(data, "forcegid", 8) == 0) { | 1110 | } else if (!strnicmp(data, "forcegid", 8)) { |
| 1107 | vol->override_gid = 1; | 1111 | override_gid = 1; |
| 1112 | } else if (!strnicmp(data, "noforcegid", 10)) { | ||
| 1113 | override_gid = 0; | ||
| 1108 | } else if (strnicmp(data, "file_mode", 4) == 0) { | 1114 | } else if (strnicmp(data, "file_mode", 4) == 0) { |
| 1109 | if (value && *value) { | 1115 | if (value && *value) { |
| 1110 | vol->file_mode = | 1116 | vol->file_mode = |
| @@ -1355,6 +1361,18 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1355 | if (vol->UNCip == NULL) | 1361 | if (vol->UNCip == NULL) |
| 1356 | vol->UNCip = &vol->UNC[2]; | 1362 | vol->UNCip = &vol->UNC[2]; |
| 1357 | 1363 | ||
| 1364 | if (uid_specified) | ||
| 1365 | vol->override_uid = override_uid; | ||
| 1366 | else if (override_uid == 1) | ||
| 1367 | printk(KERN_NOTICE "CIFS: ignoring forceuid mount option " | ||
| 1368 | "specified with no uid= option.\n"); | ||
| 1369 | |||
| 1370 | if (gid_specified) | ||
| 1371 | vol->override_gid = override_gid; | ||
| 1372 | else if (override_gid == 1) | ||
| 1373 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " | ||
| 1374 | "specified with no gid= option.\n"); | ||
| 1375 | |||
| 1358 | return 0; | 1376 | return 0; |
| 1359 | } | 1377 | } |
| 1360 | 1378 | ||
| @@ -2452,10 +2470,10 @@ try_mount_again: | |||
| 2452 | tcon->local_lease = volume_info->local_lease; | 2470 | tcon->local_lease = volume_info->local_lease; |
| 2453 | } | 2471 | } |
| 2454 | if (pSesInfo) { | 2472 | if (pSesInfo) { |
| 2455 | if (pSesInfo->capabilities & CAP_LARGE_FILES) { | 2473 | if (pSesInfo->capabilities & CAP_LARGE_FILES) |
| 2456 | sb->s_maxbytes = (u64) 1 << 63; | 2474 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 2457 | } else | 2475 | else |
| 2458 | sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ | 2476 | sb->s_maxbytes = MAX_NON_LFS; |
| 2459 | } | 2477 | } |
| 2460 | 2478 | ||
| 2461 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | 2479 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
| @@ -2544,11 +2562,20 @@ remote_path_check: | |||
| 2544 | 2562 | ||
| 2545 | if (mount_data != mount_data_global) | 2563 | if (mount_data != mount_data_global) |
| 2546 | kfree(mount_data); | 2564 | kfree(mount_data); |
| 2565 | |||
| 2547 | mount_data = cifs_compose_mount_options( | 2566 | mount_data = cifs_compose_mount_options( |
| 2548 | cifs_sb->mountdata, full_path + 1, | 2567 | cifs_sb->mountdata, full_path + 1, |
| 2549 | referrals, &fake_devname); | 2568 | referrals, &fake_devname); |
| 2550 | kfree(fake_devname); | 2569 | |
| 2551 | free_dfs_info_array(referrals, num_referrals); | 2570 | free_dfs_info_array(referrals, num_referrals); |
| 2571 | kfree(fake_devname); | ||
| 2572 | kfree(full_path); | ||
| 2573 | |||
| 2574 | if (IS_ERR(mount_data)) { | ||
| 2575 | rc = PTR_ERR(mount_data); | ||
| 2576 | mount_data = NULL; | ||
| 2577 | goto mount_fail_check; | ||
| 2578 | } | ||
| 2552 | 2579 | ||
| 2553 | if (tcon) | 2580 | if (tcon) |
| 2554 | cifs_put_tcon(tcon); | 2581 | cifs_put_tcon(tcon); |
| @@ -2556,8 +2583,6 @@ remote_path_check: | |||
| 2556 | cifs_put_smb_ses(pSesInfo); | 2583 | cifs_put_smb_ses(pSesInfo); |
| 2557 | 2584 | ||
| 2558 | cleanup_volume_info(&volume_info); | 2585 | cleanup_volume_info(&volume_info); |
| 2559 | FreeXid(xid); | ||
| 2560 | kfree(full_path); | ||
| 2561 | referral_walks_count++; | 2586 | referral_walks_count++; |
| 2562 | goto try_mount_again; | 2587 | goto try_mount_again; |
| 2563 | } | 2588 | } |
| @@ -2726,6 +2751,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
| 2726 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 2751 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); |
| 2727 | 2752 | ||
| 2728 | /* mostly informational -- no need to fail on error here */ | 2753 | /* mostly informational -- no need to fail on error here */ |
| 2754 | kfree(tcon->nativeFileSystem); | ||
| 2729 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, | 2755 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, |
| 2730 | bytes_left, is_unicode, | 2756 | bytes_left, is_unicode, |
| 2731 | nls_codepage); | 2757 | nls_codepage); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9def..4326ffd90fa9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
| 188 | FILE_UNIX_BASIC_INFO *presp_data; | 188 | FILE_UNIX_BASIC_INFO *presp_data; |
| 189 | __u32 posix_flags = 0; | 189 | __u32 posix_flags = 0; |
| 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 191 | struct cifs_fattr fattr; | ||
| 191 | 192 | ||
| 192 | cFYI(1, ("posix open %s", full_path)); | 193 | cFYI(1, ("posix open %s", full_path)); |
| 193 | 194 | ||
| @@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
| 236 | if (presp_data->Type == cpu_to_le32(-1)) | 237 | if (presp_data->Type == cpu_to_le32(-1)) |
| 237 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | 238 | goto posix_open_ret; /* open ok, caller does qpathinfo */ |
| 238 | 239 | ||
| 239 | /* get new inode and set it up */ | ||
| 240 | if (!pinode) | 240 | if (!pinode) |
| 241 | goto posix_open_ret; /* caller does not need info */ | 241 | goto posix_open_ret; /* caller does not need info */ |
| 242 | 242 | ||
| 243 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
| 244 | |||
| 245 | /* get new inode and set it up */ | ||
| 243 | if (*pinode == NULL) { | 246 | if (*pinode == NULL) { |
| 244 | __u64 unique_id = le64_to_cpu(presp_data->UniqueId); | 247 | *pinode = cifs_iget(sb, &fattr); |
| 245 | *pinode = cifs_new_inode(sb, &unique_id); | 248 | if (!*pinode) { |
| 249 | rc = -ENOMEM; | ||
| 250 | goto posix_open_ret; | ||
| 251 | } | ||
| 252 | } else { | ||
| 253 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 246 | } | 254 | } |
| 247 | /* else an inode was passed in. Update its info, don't create one */ | ||
| 248 | |||
| 249 | /* We do not need to close the file if new_inode fails since | ||
| 250 | the caller will retry qpathinfo as long as inode is null */ | ||
| 251 | if (*pinode == NULL) | ||
| 252 | goto posix_open_ret; | ||
| 253 | |||
| 254 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
| 255 | 255 | ||
| 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); |
| 257 | 257 | ||
| @@ -425,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 425 | args.uid = NO_CHANGE_64; | 425 | args.uid = NO_CHANGE_64; |
| 426 | args.gid = NO_CHANGE_64; | 426 | args.gid = NO_CHANGE_64; |
| 427 | } | 427 | } |
| 428 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | 428 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
| 429 | cifs_sb->local_nls, | 429 | cifs_sb->local_nls, |
| 430 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 430 | cifs_sb->mnt_cifs_flags & |
| 431 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 431 | } else { | 432 | } else { |
| 432 | /* BB implement mode setting via Windows security | 433 | /* BB implement mode setting via Windows security |
| 433 | descriptors e.g. */ | 434 | descriptors e.g. */ |
| @@ -515,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 515 | args.uid = NO_CHANGE_64; | 516 | args.uid = NO_CHANGE_64; |
| 516 | args.gid = NO_CHANGE_64; | 517 | args.gid = NO_CHANGE_64; |
| 517 | } | 518 | } |
| 518 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, | 519 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
| 519 | &args, cifs_sb->local_nls, | 520 | cifs_sb->local_nls, |
| 520 | cifs_sb->mnt_cifs_flags & | 521 | cifs_sb->mnt_cifs_flags & |
| 521 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 522 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 522 | 523 | ||
| 523 | if (!rc) { | 524 | if (!rc) { |
| 524 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 525 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
| @@ -643,6 +644,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
| 643 | } | 644 | } |
| 644 | } | 645 | } |
| 645 | 646 | ||
| 647 | /* | ||
| 648 | * O_EXCL: optimize away the lookup, but don't hash the dentry. Let | ||
| 649 | * the VFS handle the create. | ||
| 650 | */ | ||
| 651 | if (nd->flags & LOOKUP_EXCL) { | ||
| 652 | d_instantiate(direntry, NULL); | ||
| 653 | return 0; | ||
| 654 | } | ||
| 655 | |||
| 646 | /* can not grab the rename sem here since it would | 656 | /* can not grab the rename sem here since it would |
| 647 | deadlock in the cases (beginning of sys_rename itself) | 657 | deadlock in the cases (beginning of sys_rename itself) |
| 648 | in which we already have the sb rename sem */ | 658 | in which we already have the sb rename sem */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 97ce4bf89d15..c34b7f8a217b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -448,9 +448,9 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 448 | .mtime = NO_CHANGE_64, | 448 | .mtime = NO_CHANGE_64, |
| 449 | .device = 0, | 449 | .device = 0, |
| 450 | }; | 450 | }; |
| 451 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | 451 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
| 452 | cifs_sb->local_nls, | 452 | cifs_sb->local_nls, |
| 453 | cifs_sb->mnt_cifs_flags & | 453 | cifs_sb->mnt_cifs_flags & |
| 454 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 454 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 455 | } | 455 | } |
| 456 | } | 456 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 155c9e785d0c..82d83839655e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -77,239 +77,202 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
| 77 | } | 77 | } |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static void cifs_unix_info_to_inode(struct inode *inode, | 80 | /* populate an inode with info from a cifs_fattr struct */ |
| 81 | FILE_UNIX_BASIC_INFO *info, int force_uid_gid) | 81 | void |
| 82 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | ||
| 82 | { | 83 | { |
| 84 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||
| 83 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 85 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 84 | struct cifsInodeInfo *cifsInfo = CIFS_I(inode); | 86 | unsigned long oldtime = cifs_i->time; |
| 85 | __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes); | 87 | |
| 86 | __u64 end_of_file = le64_to_cpu(info->EndOfFile); | 88 | inode->i_atime = fattr->cf_atime; |
| 89 | inode->i_mtime = fattr->cf_mtime; | ||
| 90 | inode->i_ctime = fattr->cf_ctime; | ||
| 91 | inode->i_rdev = fattr->cf_rdev; | ||
| 92 | inode->i_nlink = fattr->cf_nlink; | ||
| 93 | inode->i_uid = fattr->cf_uid; | ||
| 94 | inode->i_gid = fattr->cf_gid; | ||
| 95 | |||
| 96 | /* if dynperm is set, don't clobber existing mode */ | ||
| 97 | if (inode->i_state & I_NEW || | ||
| 98 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) | ||
| 99 | inode->i_mode = fattr->cf_mode; | ||
| 100 | |||
| 101 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | ||
| 102 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
| 103 | |||
| 104 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | ||
| 105 | cifs_i->time = 0; | ||
| 106 | else | ||
| 107 | cifs_i->time = jiffies; | ||
| 108 | |||
| 109 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | ||
| 110 | oldtime, cifs_i->time)); | ||
| 87 | 111 | ||
| 88 | inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
| 89 | inode->i_mtime = | 113 | |
| 90 | cifs_NTtimeToUnix(info->LastModificationTime); | 114 | /* |
| 91 | inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | 115 | * Can't safely change the file size here if the client is writing to |
| 92 | inode->i_mode = le64_to_cpu(info->Permissions); | 116 | * it due to potential races. |
| 117 | */ | ||
| 118 | spin_lock(&inode->i_lock); | ||
| 119 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) { | ||
| 120 | i_size_write(inode, fattr->cf_eof); | ||
| 121 | |||
| 122 | /* | ||
| 123 | * i_blocks is not related to (i_size / i_blksize), | ||
| 124 | * but instead 512 byte (2**9) size is required for | ||
| 125 | * calculating num blocks. | ||
| 126 | */ | ||
| 127 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
| 128 | } | ||
| 129 | spin_unlock(&inode->i_lock); | ||
| 130 | |||
| 131 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | ||
| 135 | void | ||
| 136 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | ||
| 137 | struct cifs_sb_info *cifs_sb) | ||
| 138 | { | ||
| 139 | memset(fattr, 0, sizeof(*fattr)); | ||
| 140 | fattr->cf_uniqueid = le64_to_cpu(info->UniqueId); | ||
| 141 | fattr->cf_bytes = le64_to_cpu(info->NumOfBytes); | ||
| 142 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | ||
| 143 | |||
| 144 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); | ||
| 145 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); | ||
| 146 | fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); | ||
| 147 | fattr->cf_mode = le64_to_cpu(info->Permissions); | ||
| 93 | 148 | ||
| 94 | /* | 149 | /* |
| 95 | * Since we set the inode type below we need to mask off | 150 | * Since we set the inode type below we need to mask off |
| 96 | * to avoid strange results if bits set above. | 151 | * to avoid strange results if bits set above. |
| 97 | */ | 152 | */ |
| 98 | inode->i_mode &= ~S_IFMT; | 153 | fattr->cf_mode &= ~S_IFMT; |
| 99 | switch (le32_to_cpu(info->Type)) { | 154 | switch (le32_to_cpu(info->Type)) { |
| 100 | case UNIX_FILE: | 155 | case UNIX_FILE: |
| 101 | inode->i_mode |= S_IFREG; | 156 | fattr->cf_mode |= S_IFREG; |
| 157 | fattr->cf_dtype = DT_REG; | ||
| 102 | break; | 158 | break; |
| 103 | case UNIX_SYMLINK: | 159 | case UNIX_SYMLINK: |
| 104 | inode->i_mode |= S_IFLNK; | 160 | fattr->cf_mode |= S_IFLNK; |
| 161 | fattr->cf_dtype = DT_LNK; | ||
| 105 | break; | 162 | break; |
| 106 | case UNIX_DIR: | 163 | case UNIX_DIR: |
| 107 | inode->i_mode |= S_IFDIR; | 164 | fattr->cf_mode |= S_IFDIR; |
| 165 | fattr->cf_dtype = DT_DIR; | ||
| 108 | break; | 166 | break; |
| 109 | case UNIX_CHARDEV: | 167 | case UNIX_CHARDEV: |
| 110 | inode->i_mode |= S_IFCHR; | 168 | fattr->cf_mode |= S_IFCHR; |
| 111 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 169 | fattr->cf_dtype = DT_CHR; |
| 112 | le64_to_cpu(info->DevMinor) & MINORMASK); | 170 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
| 171 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
| 113 | break; | 172 | break; |
| 114 | case UNIX_BLOCKDEV: | 173 | case UNIX_BLOCKDEV: |
| 115 | inode->i_mode |= S_IFBLK; | 174 | fattr->cf_mode |= S_IFBLK; |
| 116 | inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor), | 175 | fattr->cf_dtype = DT_BLK; |
| 117 | le64_to_cpu(info->DevMinor) & MINORMASK); | 176 | fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor), |
| 177 | le64_to_cpu(info->DevMinor) & MINORMASK); | ||
| 118 | break; | 178 | break; |
| 119 | case UNIX_FIFO: | 179 | case UNIX_FIFO: |
| 120 | inode->i_mode |= S_IFIFO; | 180 | fattr->cf_mode |= S_IFIFO; |
| 181 | fattr->cf_dtype = DT_FIFO; | ||
| 121 | break; | 182 | break; |
| 122 | case UNIX_SOCKET: | 183 | case UNIX_SOCKET: |
| 123 | inode->i_mode |= S_IFSOCK; | 184 | fattr->cf_mode |= S_IFSOCK; |
| 185 | fattr->cf_dtype = DT_SOCK; | ||
| 124 | break; | 186 | break; |
| 125 | default: | 187 | default: |
| 126 | /* safest to call it a file if we do not know */ | 188 | /* safest to call it a file if we do not know */ |
| 127 | inode->i_mode |= S_IFREG; | 189 | fattr->cf_mode |= S_IFREG; |
| 190 | fattr->cf_dtype = DT_REG; | ||
| 128 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 191 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); |
| 129 | break; | 192 | break; |
| 130 | } | 193 | } |
| 131 | 194 | ||
| 132 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) && | 195 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 133 | !force_uid_gid) | 196 | fattr->cf_uid = cifs_sb->mnt_uid; |
| 134 | inode->i_uid = cifs_sb->mnt_uid; | ||
| 135 | else | 197 | else |
| 136 | inode->i_uid = le64_to_cpu(info->Uid); | 198 | fattr->cf_uid = le64_to_cpu(info->Uid); |
| 137 | 199 | ||
| 138 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) && | 200 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 139 | !force_uid_gid) | 201 | fattr->cf_gid = cifs_sb->mnt_gid; |
| 140 | inode->i_gid = cifs_sb->mnt_gid; | ||
| 141 | else | 202 | else |
| 142 | inode->i_gid = le64_to_cpu(info->Gid); | 203 | fattr->cf_gid = le64_to_cpu(info->Gid); |
| 143 | 204 | ||
| 144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | 205 | fattr->cf_nlink = le64_to_cpu(info->Nlinks); |
| 145 | |||
| 146 | cifsInfo->server_eof = end_of_file; | ||
| 147 | spin_lock(&inode->i_lock); | ||
| 148 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
| 149 | /* | ||
| 150 | * We can not safely change the file size here if the client | ||
| 151 | * is writing to it due to potential races. | ||
| 152 | */ | ||
| 153 | i_size_write(inode, end_of_file); | ||
| 154 | |||
| 155 | /* | ||
| 156 | * i_blocks is not related to (i_size / i_blksize), | ||
| 157 | * but instead 512 byte (2**9) size is required for | ||
| 158 | * calculating num blocks. | ||
| 159 | */ | ||
| 160 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
| 161 | } | ||
| 162 | spin_unlock(&inode->i_lock); | ||
| 163 | } | 206 | } |
| 164 | 207 | ||
| 165 | |||
| 166 | /* | 208 | /* |
| 167 | * Needed to setup inode data for the directory which is the | 209 | * Fill a cifs_fattr struct with fake inode info. |
| 168 | * junction to the new submount (ie to setup the fake directory | ||
| 169 | * which represents a DFS referral) | ||
| 170 | */ | ||
| 171 | static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | ||
| 172 | struct super_block *sb) | ||
| 173 | { | ||
| 174 | struct inode *pinode = NULL; | ||
| 175 | |||
| 176 | memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); | ||
| 177 | |||
| 178 | /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | ||
| 179 | __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); | ||
| 180 | __u64 UniqueId = 0; */ | ||
| 181 | pfnd_dat->LastStatusChange = | ||
| 182 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 183 | pfnd_dat->LastAccessTime = | ||
| 184 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 185 | pfnd_dat->LastModificationTime = | ||
| 186 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | ||
| 187 | pfnd_dat->Type = cpu_to_le32(UNIX_DIR); | ||
| 188 | pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); | ||
| 189 | pfnd_dat->Nlinks = cpu_to_le64(2); | ||
| 190 | if (sb->s_root) | ||
| 191 | pinode = sb->s_root->d_inode; | ||
| 192 | if (pinode == NULL) | ||
| 193 | return; | ||
| 194 | |||
| 195 | /* fill in default values for the remaining based on root | ||
| 196 | inode since we can not query the server for this inode info */ | ||
| 197 | pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); | ||
| 198 | pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); | ||
| 199 | pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); | ||
| 200 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * cifs_new inode - create new inode, initialize, and hash it | ||
| 205 | * @sb - pointer to superblock | ||
| 206 | * @inum - if valid pointer and serverino is enabled, replace i_ino with val | ||
| 207 | * | ||
| 208 | * Create a new inode, initialize it for CIFS and hash it. Returns the new | ||
| 209 | * inode or NULL if one couldn't be allocated. | ||
| 210 | * | 210 | * |
| 211 | * If the share isn't mounted with "serverino" or inum is a NULL pointer then | 211 | * Needed to setup cifs_fattr data for the directory which is the |
| 212 | * we'll just use the inode number assigned by new_inode(). Note that this can | 212 | * junction to the new submount (ie to setup the fake directory |
| 213 | * mean i_ino collisions since the i_ino assigned by new_inode is not | 213 | * which represents a DFS referral). |
| 214 | * guaranteed to be unique. | ||
| 215 | */ | 214 | */ |
| 216 | struct inode * | 215 | static void |
| 217 | cifs_new_inode(struct super_block *sb, __u64 *inum) | 216 | cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) |
| 218 | { | 217 | { |
| 219 | struct inode *inode; | 218 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 220 | |||
| 221 | inode = new_inode(sb); | ||
| 222 | if (inode == NULL) | ||
| 223 | return NULL; | ||
| 224 | |||
| 225 | /* | ||
| 226 | * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we | ||
| 227 | * stop passing inum as ptr. Are there sanity checks we can use to | ||
| 228 | * ensure that the server is really filling in that field? Also, | ||
| 229 | * if serverino is disabled, perhaps we should be using iunique()? | ||
| 230 | */ | ||
| 231 | if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | ||
| 232 | inode->i_ino = (unsigned long) *inum; | ||
| 233 | |||
| 234 | /* | ||
| 235 | * must set this here instead of cifs_alloc_inode since VFS will | ||
| 236 | * clobber i_flags | ||
| 237 | */ | ||
| 238 | if (sb->s_flags & MS_NOATIME) | ||
| 239 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
| 240 | |||
| 241 | insert_inode_hash(inode); | ||
| 242 | 219 | ||
| 243 | return inode; | 220 | cFYI(1, ("creating fake fattr for DFS referral")); |
| 221 | |||
| 222 | memset(fattr, 0, sizeof(*fattr)); | ||
| 223 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; | ||
| 224 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
| 225 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
| 226 | fattr->cf_atime = CURRENT_TIME; | ||
| 227 | fattr->cf_ctime = CURRENT_TIME; | ||
| 228 | fattr->cf_mtime = CURRENT_TIME; | ||
| 229 | fattr->cf_nlink = 2; | ||
| 230 | fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; | ||
| 244 | } | 231 | } |
| 245 | 232 | ||
| 246 | int cifs_get_inode_info_unix(struct inode **pinode, | 233 | int cifs_get_inode_info_unix(struct inode **pinode, |
| 247 | const unsigned char *full_path, struct super_block *sb, int xid) | 234 | const unsigned char *full_path, |
| 235 | struct super_block *sb, int xid) | ||
| 248 | { | 236 | { |
| 249 | int rc = 0; | 237 | int rc; |
| 250 | FILE_UNIX_BASIC_INFO find_data; | 238 | FILE_UNIX_BASIC_INFO find_data; |
| 251 | struct cifsTconInfo *pTcon; | 239 | struct cifs_fattr fattr; |
| 252 | struct inode *inode; | 240 | struct cifsTconInfo *tcon; |
| 253 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 241 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 254 | bool is_dfs_referral = false; | ||
| 255 | struct cifsInodeInfo *cifsInfo; | ||
| 256 | __u64 num_of_bytes; | ||
| 257 | __u64 end_of_file; | ||
| 258 | 242 | ||
| 259 | pTcon = cifs_sb->tcon; | 243 | tcon = cifs_sb->tcon; |
| 260 | cFYI(1, ("Getting info on %s", full_path)); | 244 | cFYI(1, ("Getting info on %s", full_path)); |
| 261 | 245 | ||
| 262 | /* could have done a find first instead but this returns more info */ | 246 | /* could have done a find first instead but this returns more info */ |
| 263 | rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, | 247 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
| 264 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 248 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
| 265 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 249 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 266 | if (rc == -EREMOTE && !is_dfs_referral) { | ||
| 267 | is_dfs_referral = true; | ||
| 268 | cFYI(DBG2, ("DFS ref")); | ||
| 269 | /* for DFS, server does not give us real inode data */ | ||
| 270 | fill_fake_finddataunix(&find_data, sb); | ||
| 271 | rc = 0; | ||
| 272 | } else if (rc) | ||
| 273 | goto cgiiu_exit; | ||
| 274 | 250 | ||
| 275 | num_of_bytes = le64_to_cpu(find_data.NumOfBytes); | 251 | if (!rc) { |
| 276 | end_of_file = le64_to_cpu(find_data.EndOfFile); | 252 | cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); |
| 253 | } else if (rc == -EREMOTE) { | ||
| 254 | cifs_create_dfs_fattr(&fattr, sb); | ||
| 255 | rc = 0; | ||
| 256 | } else { | ||
| 257 | return rc; | ||
| 258 | } | ||
| 277 | 259 | ||
| 278 | /* get new inode */ | ||
| 279 | if (*pinode == NULL) { | 260 | if (*pinode == NULL) { |
| 280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); | 261 | /* get new inode */ |
| 281 | *pinode = cifs_new_inode(sb, &unique_id); | 262 | *pinode = cifs_iget(sb, &fattr); |
| 282 | if (*pinode == NULL) { | 263 | if (!*pinode) |
| 283 | rc = -ENOMEM; | 264 | rc = -ENOMEM; |
| 284 | goto cgiiu_exit; | 265 | } else { |
| 285 | } | 266 | /* we already have inode, update it */ |
| 267 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 286 | } | 268 | } |
| 287 | 269 | ||
| 288 | inode = *pinode; | ||
| 289 | cifsInfo = CIFS_I(inode); | ||
| 290 | |||
| 291 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
| 292 | cifsInfo->time = jiffies; | ||
| 293 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
| 294 | /* this is ok to set on every inode revalidate */ | ||
| 295 | atomic_set(&cifsInfo->inUse, 1); | ||
| 296 | |||
| 297 | cifs_unix_info_to_inode(inode, &find_data, 0); | ||
| 298 | |||
| 299 | if (num_of_bytes < end_of_file) | ||
| 300 | cFYI(1, ("allocation size less than end of file")); | ||
| 301 | cFYI(1, ("Size %ld and blocks %llu", | ||
| 302 | (unsigned long) inode->i_size, | ||
| 303 | (unsigned long long)inode->i_blocks)); | ||
| 304 | |||
| 305 | cifs_set_ops(inode, is_dfs_referral); | ||
| 306 | cgiiu_exit: | ||
| 307 | return rc; | 270 | return rc; |
| 308 | } | 271 | } |
| 309 | 272 | ||
| 310 | static int decode_sfu_inode(struct inode *inode, __u64 size, | 273 | static int |
| 311 | const unsigned char *path, | 274 | cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, |
| 312 | struct cifs_sb_info *cifs_sb, int xid) | 275 | struct cifs_sb_info *cifs_sb, int xid) |
| 313 | { | 276 | { |
| 314 | int rc; | 277 | int rc; |
| 315 | int oplock = 0; | 278 | int oplock = 0; |
| @@ -321,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
| 321 | 284 | ||
| 322 | pbuf = buf; | 285 | pbuf = buf; |
| 323 | 286 | ||
| 324 | if (size == 0) { | 287 | fattr->cf_mode &= ~S_IFMT; |
| 325 | inode->i_mode |= S_IFIFO; | 288 | |
| 289 | if (fattr->cf_eof == 0) { | ||
| 290 | fattr->cf_mode |= S_IFIFO; | ||
| 291 | fattr->cf_dtype = DT_FIFO; | ||
| 326 | return 0; | 292 | return 0; |
| 327 | } else if (size < 8) { | 293 | } else if (fattr->cf_eof < 8) { |
| 294 | fattr->cf_mode |= S_IFREG; | ||
| 295 | fattr->cf_dtype = DT_REG; | ||
| 328 | return -EINVAL; /* EOPNOTSUPP? */ | 296 | return -EINVAL; /* EOPNOTSUPP? */ |
| 329 | } | 297 | } |
| 330 | 298 | ||
| @@ -336,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
| 336 | if (rc == 0) { | 304 | if (rc == 0) { |
| 337 | int buf_type = CIFS_NO_BUFFER; | 305 | int buf_type = CIFS_NO_BUFFER; |
| 338 | /* Read header */ | 306 | /* Read header */ |
| 339 | rc = CIFSSMBRead(xid, pTcon, | 307 | rc = CIFSSMBRead(xid, pTcon, netfid, |
| 340 | netfid, | ||
| 341 | 24 /* length */, 0 /* offset */, | 308 | 24 /* length */, 0 /* offset */, |
| 342 | &bytes_read, &pbuf, &buf_type); | 309 | &bytes_read, &pbuf, &buf_type); |
| 343 | if ((rc == 0) && (bytes_read >= 8)) { | 310 | if ((rc == 0) && (bytes_read >= 8)) { |
| 344 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 311 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
| 345 | cFYI(1, ("Block device")); | 312 | cFYI(1, ("Block device")); |
| 346 | inode->i_mode |= S_IFBLK; | 313 | fattr->cf_mode |= S_IFBLK; |
| 314 | fattr->cf_dtype = DT_BLK; | ||
| 347 | if (bytes_read == 24) { | 315 | if (bytes_read == 24) { |
| 348 | /* we have enough to decode dev num */ | 316 | /* we have enough to decode dev num */ |
| 349 | __u64 mjr; /* major */ | 317 | __u64 mjr; /* major */ |
| 350 | __u64 mnr; /* minor */ | 318 | __u64 mnr; /* minor */ |
| 351 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 319 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
| 352 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 320 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
| 353 | inode->i_rdev = MKDEV(mjr, mnr); | 321 | fattr->cf_rdev = MKDEV(mjr, mnr); |
| 354 | } | 322 | } |
| 355 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 323 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
| 356 | cFYI(1, ("Char device")); | 324 | cFYI(1, ("Char device")); |
| 357 | inode->i_mode |= S_IFCHR; | 325 | fattr->cf_mode |= S_IFCHR; |
| 326 | fattr->cf_dtype = DT_CHR; | ||
| 358 | if (bytes_read == 24) { | 327 | if (bytes_read == 24) { |
| 359 | /* we have enough to decode dev num */ | 328 | /* we have enough to decode dev num */ |
| 360 | __u64 mjr; /* major */ | 329 | __u64 mjr; /* major */ |
| 361 | __u64 mnr; /* minor */ | 330 | __u64 mnr; /* minor */ |
| 362 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); | 331 | mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); |
| 363 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 332 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
| 364 | inode->i_rdev = MKDEV(mjr, mnr); | 333 | fattr->cf_rdev = MKDEV(mjr, mnr); |
| 365 | } | 334 | } |
| 366 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | 335 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
| 367 | cFYI(1, ("Symlink")); | 336 | cFYI(1, ("Symlink")); |
| 368 | inode->i_mode |= S_IFLNK; | 337 | fattr->cf_mode |= S_IFLNK; |
| 338 | fattr->cf_dtype = DT_LNK; | ||
| 369 | } else { | 339 | } else { |
| 370 | inode->i_mode |= S_IFREG; /* file? */ | 340 | fattr->cf_mode |= S_IFREG; /* file? */ |
| 341 | fattr->cf_dtype = DT_REG; | ||
| 371 | rc = -EOPNOTSUPP; | 342 | rc = -EOPNOTSUPP; |
| 372 | } | 343 | } |
| 373 | } else { | 344 | } else { |
| 374 | inode->i_mode |= S_IFREG; /* then it is a file */ | 345 | fattr->cf_mode |= S_IFREG; /* then it is a file */ |
| 346 | fattr->cf_dtype = DT_REG; | ||
| 375 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 347 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
| 376 | } | 348 | } |
| 377 | CIFSSMBClose(xid, pTcon, netfid); | 349 | CIFSSMBClose(xid, pTcon, netfid); |
| @@ -381,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, | |||
| 381 | 353 | ||
| 382 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ | 354 | #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ |
| 383 | 355 | ||
| 384 | static int get_sfu_mode(struct inode *inode, | 356 | /* |
| 385 | const unsigned char *path, | 357 | * Fetch mode bits as provided by SFU. |
| 386 | struct cifs_sb_info *cifs_sb, int xid) | 358 | * |
| 359 | * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ? | ||
| 360 | */ | ||
| 361 | static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | ||
| 362 | struct cifs_sb_info *cifs_sb, int xid) | ||
| 387 | { | 363 | { |
| 388 | #ifdef CONFIG_CIFS_XATTR | 364 | #ifdef CONFIG_CIFS_XATTR |
| 389 | ssize_t rc; | 365 | ssize_t rc; |
| @@ -391,68 +367,80 @@ static int get_sfu_mode(struct inode *inode, | |||
| 391 | __u32 mode; | 367 | __u32 mode; |
| 392 | 368 | ||
| 393 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 369 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", |
| 394 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 370 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
| 395 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 371 | cifs_sb->mnt_cifs_flags & |
| 372 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 396 | if (rc < 0) | 373 | if (rc < 0) |
| 397 | return (int)rc; | 374 | return (int)rc; |
| 398 | else if (rc > 3) { | 375 | else if (rc > 3) { |
| 399 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 376 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
| 400 | inode->i_mode &= ~SFBITS_MASK; | 377 | fattr->cf_mode &= ~SFBITS_MASK; |
| 401 | cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); | 378 | cFYI(1, ("special bits 0%o org mode 0%o", mode, |
| 402 | inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; | 379 | fattr->cf_mode)); |
| 380 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; | ||
| 403 | cFYI(1, ("special mode bits 0%o", mode)); | 381 | cFYI(1, ("special mode bits 0%o", mode)); |
| 404 | return 0; | ||
| 405 | } else { | ||
| 406 | return 0; | ||
| 407 | } | 382 | } |
| 383 | |||
| 384 | return 0; | ||
| 408 | #else | 385 | #else |
| 409 | return -EOPNOTSUPP; | 386 | return -EOPNOTSUPP; |
| 410 | #endif | 387 | #endif |
| 411 | } | 388 | } |
| 412 | 389 | ||
| 413 | /* | 390 | /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ |
| 414 | * Needed to setup inode data for the directory which is the | 391 | static void |
| 415 | * junction to the new submount (ie to setup the fake directory | 392 | cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, |
| 416 | * which represents a DFS referral) | 393 | struct cifs_sb_info *cifs_sb, bool adjust_tz) |
| 417 | */ | ||
| 418 | static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, | ||
| 419 | struct super_block *sb) | ||
| 420 | { | 394 | { |
| 421 | memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); | 395 | memset(fattr, 0, sizeof(*fattr)); |
| 422 | 396 | fattr->cf_cifsattrs = le32_to_cpu(info->Attributes); | |
| 423 | /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); | 397 | if (info->DeletePending) |
| 424 | __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); | 398 | fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING; |
| 425 | __u8 pfnd_dat->DeletePending = 0; | 399 | |
| 426 | __u8 pfnd_data->Directory = 0; | 400 | if (info->LastAccessTime) |
| 427 | __le32 pfnd_dat->EASize = 0; | 401 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
| 428 | __u64 pfnd_dat->IndexNumber = 0; | 402 | else |
| 429 | __u64 pfnd_dat->IndexNumber1 = 0; */ | 403 | fattr->cf_atime = CURRENT_TIME; |
| 430 | pfnd_dat->CreationTime = | 404 | |
| 431 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 405 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
| 432 | pfnd_dat->LastAccessTime = | 406 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
| 433 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 407 | |
| 434 | pfnd_dat->LastWriteTime = | 408 | if (adjust_tz) { |
| 435 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 409 | fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
| 436 | pfnd_dat->ChangeTime = | 410 | fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj; |
| 437 | cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); | 411 | } |
| 438 | pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); | 412 | |
| 439 | pfnd_dat->NumberOfLinks = cpu_to_le32(2); | 413 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
| 414 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | ||
| 415 | |||
| 416 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | ||
| 417 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | ||
| 418 | fattr->cf_dtype = DT_DIR; | ||
| 419 | } else { | ||
| 420 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | ||
| 421 | fattr->cf_dtype = DT_REG; | ||
| 422 | |||
| 423 | /* clear write bits if ATTR_READONLY is set */ | ||
| 424 | if (fattr->cf_cifsattrs & ATTR_READONLY) | ||
| 425 | fattr->cf_mode &= ~(S_IWUGO); | ||
| 426 | } | ||
| 427 | |||
| 428 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | ||
| 429 | |||
| 430 | fattr->cf_uid = cifs_sb->mnt_uid; | ||
| 431 | fattr->cf_gid = cifs_sb->mnt_gid; | ||
| 440 | } | 432 | } |
| 441 | 433 | ||
| 442 | int cifs_get_inode_info(struct inode **pinode, | 434 | int cifs_get_inode_info(struct inode **pinode, |
| 443 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, | 435 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
| 444 | struct super_block *sb, int xid, const __u16 *pfid) | 436 | struct super_block *sb, int xid, const __u16 *pfid) |
| 445 | { | 437 | { |
| 446 | int rc = 0; | 438 | int rc = 0, tmprc; |
| 447 | __u32 attr; | ||
| 448 | struct cifsInodeInfo *cifsInfo; | ||
| 449 | struct cifsTconInfo *pTcon; | 439 | struct cifsTconInfo *pTcon; |
| 450 | struct inode *inode; | ||
| 451 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 440 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 452 | char *buf = NULL; | 441 | char *buf = NULL; |
| 453 | bool adjustTZ = false; | 442 | bool adjustTZ = false; |
| 454 | bool is_dfs_referral = false; | 443 | struct cifs_fattr fattr; |
| 455 | umode_t default_mode; | ||
| 456 | 444 | ||
| 457 | pTcon = cifs_sb->tcon; | 445 | pTcon = cifs_sb->tcon; |
| 458 | cFYI(1, ("Getting info on %s", full_path)); | 446 | cFYI(1, ("Getting info on %s", full_path)); |
| @@ -487,163 +475,85 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 487 | adjustTZ = true; | 475 | adjustTZ = true; |
| 488 | } | 476 | } |
| 489 | } | 477 | } |
| 490 | /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ | 478 | |
| 491 | if (rc == -EREMOTE) { | 479 | if (!rc) { |
| 492 | is_dfs_referral = true; | 480 | cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData, |
| 493 | fill_fake_finddata(pfindData, sb); | 481 | cifs_sb, adjustTZ); |
| 482 | } else if (rc == -EREMOTE) { | ||
| 483 | cifs_create_dfs_fattr(&fattr, sb); | ||
| 494 | rc = 0; | 484 | rc = 0; |
| 495 | } else if (rc) | 485 | } else { |
| 496 | goto cgii_exit; | 486 | goto cgii_exit; |
| 487 | } | ||
| 497 | 488 | ||
| 498 | attr = le32_to_cpu(pfindData->Attributes); | 489 | /* |
| 499 | 490 | * If an inode wasn't passed in, then get the inode number | |
| 500 | /* get new inode */ | 491 | * |
| 492 | * Is an i_ino of zero legal? Can we use that to check if the server | ||
| 493 | * supports returning inode numbers? Are there other sanity checks we | ||
| 494 | * can use to ensure that the server is really filling in that field? | ||
| 495 | * | ||
| 496 | * We can not use the IndexNumber field by default from Windows or | ||
| 497 | * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA | ||
| 498 | * CIFS spec claims that this value is unique within the scope of a | ||
| 499 | * share, and the windows docs hint that it's actually unique | ||
| 500 | * per-machine. | ||
| 501 | * | ||
| 502 | * There may be higher info levels that work but are there Windows | ||
| 503 | * server or network appliances for which IndexNumber field is not | ||
| 504 | * guaranteed unique? | ||
| 505 | */ | ||
| 501 | if (*pinode == NULL) { | 506 | if (*pinode == NULL) { |
| 502 | __u64 inode_num; | ||
| 503 | __u64 *pinum = &inode_num; | ||
| 504 | |||
| 505 | /* Is an i_ino of zero legal? Can we use that to check | ||
| 506 | if the server supports returning inode numbers? Are | ||
| 507 | there other sanity checks we can use to ensure that | ||
| 508 | the server is really filling in that field? */ | ||
| 509 | |||
| 510 | /* We can not use the IndexNumber field by default from | ||
| 511 | Windows or Samba (in ALL_INFO buf) but we can request | ||
| 512 | it explicitly. It may not be unique presumably if | ||
| 513 | the server has multiple devices mounted under one share */ | ||
| 514 | |||
| 515 | /* There may be higher info levels that work but are | ||
| 516 | there Windows server or network appliances for which | ||
| 517 | IndexNumber field is not guaranteed unique? */ | ||
| 518 | |||
| 519 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 507 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
| 520 | int rc1 = 0; | 508 | int rc1 = 0; |
| 521 | 509 | ||
| 522 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 510 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
| 523 | full_path, pinum, | 511 | full_path, &fattr.cf_uniqueid, |
| 524 | cifs_sb->local_nls, | 512 | cifs_sb->local_nls, |
| 525 | cifs_sb->mnt_cifs_flags & | 513 | cifs_sb->mnt_cifs_flags & |
| 526 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 514 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 527 | if (rc1) { | 515 | if (rc1) { |
| 528 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | 516 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); |
| 529 | pinum = NULL; | 517 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
| 530 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 518 | /* disable serverino if call not supported */ |
| 519 | if (rc1 == -EINVAL) | ||
| 520 | cifs_sb->mnt_cifs_flags &= | ||
| 521 | ~CIFS_MOUNT_SERVER_INUM; | ||
| 531 | } | 522 | } |
| 532 | } else { | 523 | } else { |
| 533 | pinum = NULL; | 524 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
| 534 | } | ||
| 535 | |||
| 536 | *pinode = cifs_new_inode(sb, pinum); | ||
| 537 | if (*pinode == NULL) { | ||
| 538 | rc = -ENOMEM; | ||
| 539 | goto cgii_exit; | ||
| 540 | } | 525 | } |
| 541 | } | ||
| 542 | inode = *pinode; | ||
| 543 | cifsInfo = CIFS_I(inode); | ||
| 544 | cifsInfo->cifsAttrs = attr; | ||
| 545 | cifsInfo->delete_pending = pfindData->DeletePending ? true : false; | ||
| 546 | cFYI(1, ("Old time %ld", cifsInfo->time)); | ||
| 547 | cifsInfo->time = jiffies; | ||
| 548 | cFYI(1, ("New time %ld", cifsInfo->time)); | ||
| 549 | |||
| 550 | /* blksize needs to be multiple of two. So safer to default to | ||
| 551 | blksize and blkbits set in superblock so 2**blkbits and blksize | ||
| 552 | will match rather than setting to: | ||
| 553 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | ||
| 554 | |||
| 555 | /* Linux can not store file creation time so ignore it */ | ||
| 556 | if (pfindData->LastAccessTime) | ||
| 557 | inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
| 558 | else /* do not need to use current_fs_time - time not stored */ | ||
| 559 | inode->i_atime = CURRENT_TIME; | ||
| 560 | inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
| 561 | inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
| 562 | cFYI(DBG2, ("Attributes came in as 0x%x", attr)); | ||
| 563 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | ||
| 564 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | ||
| 565 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | ||
| 566 | } | ||
| 567 | |||
| 568 | /* get default inode mode */ | ||
| 569 | if (attr & ATTR_DIRECTORY) | ||
| 570 | default_mode = cifs_sb->mnt_dir_mode; | ||
| 571 | else | ||
| 572 | default_mode = cifs_sb->mnt_file_mode; | ||
| 573 | |||
| 574 | /* set permission bits */ | ||
| 575 | if (atomic_read(&cifsInfo->inUse) == 0 || | ||
| 576 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
| 577 | inode->i_mode = default_mode; | ||
| 578 | else { | ||
| 579 | /* just reenable write bits if !ATTR_READONLY */ | ||
| 580 | if ((inode->i_mode & S_IWUGO) == 0 && | ||
| 581 | (attr & ATTR_READONLY) == 0) | ||
| 582 | inode->i_mode |= (S_IWUGO & default_mode); | ||
| 583 | |||
| 584 | inode->i_mode &= ~S_IFMT; | ||
| 585 | } | ||
| 586 | /* clear write bits if ATTR_READONLY is set */ | ||
| 587 | if (attr & ATTR_READONLY) | ||
| 588 | inode->i_mode &= ~S_IWUGO; | ||
| 589 | |||
| 590 | /* set inode type */ | ||
| 591 | if ((attr & ATTR_SYSTEM) && | ||
| 592 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | ||
| 593 | /* no need to fix endianness on 0 */ | ||
| 594 | if (pfindData->EndOfFile == 0) | ||
| 595 | inode->i_mode |= S_IFIFO; | ||
| 596 | else if (decode_sfu_inode(inode, | ||
| 597 | le64_to_cpu(pfindData->EndOfFile), | ||
| 598 | full_path, cifs_sb, xid)) | ||
| 599 | cFYI(1, ("unknown SFU file type\n")); | ||
| 600 | } else { | 526 | } else { |
| 601 | if (attr & ATTR_DIRECTORY) | 527 | fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid; |
| 602 | inode->i_mode |= S_IFDIR; | ||
| 603 | else | ||
| 604 | inode->i_mode |= S_IFREG; | ||
| 605 | } | 528 | } |
| 606 | 529 | ||
| 607 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | 530 | /* query for SFU type info if supported and needed */ |
| 608 | spin_lock(&inode->i_lock); | 531 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
| 609 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { | 532 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
| 610 | /* can not safely shrink the file size here if the | 533 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
| 611 | client is writing to it due to potential races */ | 534 | if (tmprc) |
| 612 | i_size_write(inode, cifsInfo->server_eof); | 535 | cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); |
| 613 | |||
| 614 | /* 512 bytes (2**9) is the fake blocksize that must be | ||
| 615 | used for this calculation */ | ||
| 616 | inode->i_blocks = (512 - 1 + le64_to_cpu( | ||
| 617 | pfindData->AllocationSize)) >> 9; | ||
| 618 | } | 536 | } |
| 619 | spin_unlock(&inode->i_lock); | ||
| 620 | |||
| 621 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | ||
| 622 | 537 | ||
| 623 | /* BB fill in uid and gid here? with help from winbind? | ||
| 624 | or retrieve from NTFS stream extended attribute */ | ||
| 625 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 538 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 626 | /* fill in 0777 bits from ACL */ | 539 | /* fill in 0777 bits from ACL */ |
| 627 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 540 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
| 628 | cFYI(1, ("Getting mode bits from ACL")); | 541 | cFYI(1, ("Getting mode bits from ACL")); |
| 629 | acl_to_uid_mode(cifs_sb, inode, full_path, pfid); | 542 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
| 630 | } | 543 | } |
| 631 | #endif | 544 | #endif |
| 632 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | ||
| 633 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
| 634 | get_sfu_mode(inode, full_path, cifs_sb, xid); | ||
| 635 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | ||
| 636 | inode->i_uid = cifs_sb->mnt_uid; | ||
| 637 | inode->i_gid = cifs_sb->mnt_gid; | ||
| 638 | /* set so we do not keep refreshing these fields with | ||
| 639 | bad data after user has changed them in memory */ | ||
| 640 | atomic_set(&cifsInfo->inUse, 1); | ||
| 641 | } | ||
| 642 | |||
| 643 | cifs_set_ops(inode, is_dfs_referral); | ||
| 644 | |||
| 645 | 545 | ||
| 546 | /* fill in remaining high mode bits e.g. SUID, VTX */ | ||
| 547 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | ||
| 548 | cifs_sfu_mode(&fattr, full_path, cifs_sb, xid); | ||
| 646 | 549 | ||
| 550 | if (!*pinode) { | ||
| 551 | *pinode = cifs_iget(sb, &fattr); | ||
| 552 | if (!*pinode) | ||
| 553 | rc = -ENOMEM; | ||
| 554 | } else { | ||
| 555 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 556 | } | ||
| 647 | 557 | ||
| 648 | cgii_exit: | 558 | cgii_exit: |
| 649 | kfree(buf); | 559 | kfree(buf); |
| @@ -695,33 +605,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) | |||
| 695 | return full_path; | 605 | return full_path; |
| 696 | } | 606 | } |
| 697 | 607 | ||
| 608 | static int | ||
| 609 | cifs_find_inode(struct inode *inode, void *opaque) | ||
| 610 | { | ||
| 611 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
| 612 | |||
| 613 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | ||
| 614 | return 0; | ||
| 615 | |||
| 616 | return 1; | ||
| 617 | } | ||
| 618 | |||
| 619 | static int | ||
| 620 | cifs_init_inode(struct inode *inode, void *opaque) | ||
| 621 | { | ||
| 622 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | ||
| 623 | |||
| 624 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | ||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | /* Given fattrs, get a corresponding inode */ | ||
| 629 | struct inode * | ||
| 630 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | ||
| 631 | { | ||
| 632 | unsigned long hash; | ||
| 633 | struct inode *inode; | ||
| 634 | |||
| 635 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | ||
| 636 | |||
| 637 | /* hash down to 32-bits on 32-bit arch */ | ||
| 638 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | ||
| 639 | |||
| 640 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | ||
| 641 | |||
| 642 | /* we have fattrs in hand, update the inode */ | ||
| 643 | if (inode) { | ||
| 644 | cifs_fattr_to_inode(inode, fattr); | ||
| 645 | if (sb->s_flags & MS_NOATIME) | ||
| 646 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
| 647 | if (inode->i_state & I_NEW) { | ||
| 648 | inode->i_ino = hash; | ||
| 649 | unlock_new_inode(inode); | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | return inode; | ||
| 654 | } | ||
| 655 | |||
| 698 | /* gets root inode */ | 656 | /* gets root inode */ |
| 699 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 657 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) |
| 700 | { | 658 | { |
| 701 | int xid; | 659 | int xid; |
| 702 | struct cifs_sb_info *cifs_sb; | 660 | struct cifs_sb_info *cifs_sb; |
| 703 | struct inode *inode; | 661 | struct inode *inode = NULL; |
| 704 | long rc; | 662 | long rc; |
| 705 | char *full_path; | 663 | char *full_path; |
| 706 | 664 | ||
| 707 | inode = iget_locked(sb, ino); | 665 | cifs_sb = CIFS_SB(sb); |
| 708 | if (!inode) | ||
| 709 | return ERR_PTR(-ENOMEM); | ||
| 710 | if (!(inode->i_state & I_NEW)) | ||
| 711 | return inode; | ||
| 712 | |||
| 713 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 714 | full_path = cifs_build_path_to_root(cifs_sb); | 666 | full_path = cifs_build_path_to_root(cifs_sb); |
| 715 | if (full_path == NULL) | 667 | if (full_path == NULL) |
| 716 | return ERR_PTR(-ENOMEM); | 668 | return ERR_PTR(-ENOMEM); |
| 717 | 669 | ||
| 718 | xid = GetXid(); | 670 | xid = GetXid(); |
| 719 | if (cifs_sb->tcon->unix_ext) | 671 | if (cifs_sb->tcon->unix_ext) |
| 720 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | 672 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
| 721 | xid); | ||
| 722 | else | 673 | else |
| 723 | rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb, | 674 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
| 724 | xid, NULL); | 675 | xid, NULL); |
| 676 | |||
| 677 | if (!inode) | ||
| 678 | return ERR_PTR(-ENOMEM); | ||
| 679 | |||
| 725 | if (rc && cifs_sb->tcon->ipc) { | 680 | if (rc && cifs_sb->tcon->ipc) { |
| 726 | cFYI(1, ("ipc connection - fake read inode")); | 681 | cFYI(1, ("ipc connection - fake read inode")); |
| 727 | inode->i_mode |= S_IFDIR; | 682 | inode->i_mode |= S_IFDIR; |
| @@ -737,7 +692,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 737 | return ERR_PTR(rc); | 692 | return ERR_PTR(rc); |
| 738 | } | 693 | } |
| 739 | 694 | ||
| 740 | unlock_new_inode(inode); | ||
| 741 | 695 | ||
| 742 | kfree(full_path); | 696 | kfree(full_path); |
| 743 | /* can not call macro FreeXid here since in a void func | 697 | /* can not call macro FreeXid here since in a void func |
| @@ -1063,44 +1017,6 @@ out_reval: | |||
| 1063 | return rc; | 1017 | return rc; |
| 1064 | } | 1018 | } |
| 1065 | 1019 | ||
| 1066 | void posix_fill_in_inode(struct inode *tmp_inode, | ||
| 1067 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | ||
| 1068 | { | ||
| 1069 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
| 1070 | loff_t local_size; | ||
| 1071 | struct timespec local_mtime; | ||
| 1072 | |||
| 1073 | cifsInfo->time = jiffies; | ||
| 1074 | atomic_inc(&cifsInfo->inUse); | ||
| 1075 | |||
| 1076 | /* save mtime and size */ | ||
| 1077 | local_mtime = tmp_inode->i_mtime; | ||
| 1078 | local_size = tmp_inode->i_size; | ||
| 1079 | |||
| 1080 | cifs_unix_info_to_inode(tmp_inode, pData, 1); | ||
| 1081 | cifs_set_ops(tmp_inode, false); | ||
| 1082 | |||
| 1083 | if (!S_ISREG(tmp_inode->i_mode)) | ||
| 1084 | return; | ||
| 1085 | |||
| 1086 | /* | ||
| 1087 | * No sense invalidating pages for new inode | ||
| 1088 | * since we we have not started caching | ||
| 1089 | * readahead file data yet. | ||
| 1090 | */ | ||
| 1091 | if (isNewInode) | ||
| 1092 | return; | ||
| 1093 | |||
| 1094 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
| 1095 | (local_size == tmp_inode->i_size)) { | ||
| 1096 | cFYI(1, ("inode exists but unchanged")); | ||
| 1097 | } else { | ||
| 1098 | /* file may have changed on server */ | ||
| 1099 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
| 1100 | invalidate_remote_inode(tmp_inode); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 1020 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
| 1105 | { | 1021 | { |
| 1106 | int rc = 0, tmprc; | 1022 | int rc = 0, tmprc; |
| @@ -1109,6 +1025,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1109 | struct cifsTconInfo *pTcon; | 1025 | struct cifsTconInfo *pTcon; |
| 1110 | char *full_path = NULL; | 1026 | char *full_path = NULL; |
| 1111 | struct inode *newinode = NULL; | 1027 | struct inode *newinode = NULL; |
| 1028 | struct cifs_fattr fattr; | ||
| 1112 | 1029 | ||
| 1113 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1030 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
| 1114 | 1031 | ||
| @@ -1148,7 +1065,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1148 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1065 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
| 1149 | d_drop(direntry); | 1066 | d_drop(direntry); |
| 1150 | } else { | 1067 | } else { |
| 1151 | __u64 unique_id; | ||
| 1152 | if (pInfo->Type == cpu_to_le32(-1)) { | 1068 | if (pInfo->Type == cpu_to_le32(-1)) { |
| 1153 | /* no return info, go query for it */ | 1069 | /* no return info, go query for it */ |
| 1154 | kfree(pInfo); | 1070 | kfree(pInfo); |
| @@ -1162,20 +1078,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1162 | else | 1078 | else |
| 1163 | direntry->d_op = &cifs_dentry_ops; | 1079 | direntry->d_op = &cifs_dentry_ops; |
| 1164 | 1080 | ||
| 1165 | unique_id = le64_to_cpu(pInfo->UniqueId); | 1081 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
| 1166 | newinode = cifs_new_inode(inode->i_sb, &unique_id); | 1082 | newinode = cifs_iget(inode->i_sb, &fattr); |
| 1167 | if (newinode == NULL) { | 1083 | if (!newinode) { |
| 1168 | kfree(pInfo); | 1084 | kfree(pInfo); |
| 1169 | goto mkdir_get_info; | 1085 | goto mkdir_get_info; |
| 1170 | } | 1086 | } |
| 1171 | 1087 | ||
| 1172 | newinode->i_nlink = 2; | ||
| 1173 | d_instantiate(direntry, newinode); | 1088 | d_instantiate(direntry, newinode); |
| 1174 | 1089 | ||
| 1175 | /* we already checked in POSIXCreate whether | ||
| 1176 | frame was long enough */ | ||
| 1177 | posix_fill_in_inode(direntry->d_inode, | ||
| 1178 | pInfo, 1 /* NewInode */); | ||
| 1179 | #ifdef CONFIG_CIFS_DEBUG2 | 1090 | #ifdef CONFIG_CIFS_DEBUG2 |
| 1180 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1091 | cFYI(1, ("instantiated dentry %p %s to inode %p", |
| 1181 | direntry, direntry->d_name.name, newinode)); | 1092 | direntry, direntry->d_name.name, newinode)); |
| @@ -1238,10 +1149,10 @@ mkdir_get_info: | |||
| 1238 | args.uid = NO_CHANGE_64; | 1149 | args.uid = NO_CHANGE_64; |
| 1239 | args.gid = NO_CHANGE_64; | 1150 | args.gid = NO_CHANGE_64; |
| 1240 | } | 1151 | } |
| 1241 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | 1152 | CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
| 1242 | cifs_sb->local_nls, | 1153 | cifs_sb->local_nls, |
| 1243 | cifs_sb->mnt_cifs_flags & | 1154 | cifs_sb->mnt_cifs_flags & |
| 1244 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1155 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1245 | } else { | 1156 | } else { |
| 1246 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1157 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
| 1247 | (mode & S_IWUGO) == 0) { | 1158 | (mode & S_IWUGO) == 0) { |
| @@ -1622,6 +1533,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1622 | if (!err) { | 1533 | if (!err) { |
| 1623 | generic_fillattr(dentry->d_inode, stat); | 1534 | generic_fillattr(dentry->d_inode, stat); |
| 1624 | stat->blksize = CIFS_MAX_MSGSIZE; | 1535 | stat->blksize = CIFS_MAX_MSGSIZE; |
| 1536 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
| 1625 | } | 1537 | } |
| 1626 | return err; | 1538 | return err; |
| 1627 | } | 1539 | } |
| @@ -1786,6 +1698,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
| 1786 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1698 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1787 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1699 | struct cifsTconInfo *pTcon = cifs_sb->tcon; |
| 1788 | struct cifs_unix_set_info_args *args = NULL; | 1700 | struct cifs_unix_set_info_args *args = NULL; |
| 1701 | struct cifsFileInfo *open_file; | ||
| 1789 | 1702 | ||
| 1790 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1703 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", |
| 1791 | direntry->d_name.name, attrs->ia_valid)); | 1704 | direntry->d_name.name, attrs->ia_valid)); |
| @@ -1872,10 +1785,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
| 1872 | args->ctime = NO_CHANGE_64; | 1785 | args->ctime = NO_CHANGE_64; |
| 1873 | 1786 | ||
| 1874 | args->device = 0; | 1787 | args->device = 0; |
| 1875 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args, | 1788 | open_file = find_writable_file(cifsInode); |
| 1876 | cifs_sb->local_nls, | 1789 | if (open_file) { |
| 1877 | cifs_sb->mnt_cifs_flags & | 1790 | u16 nfid = open_file->netfid; |
| 1878 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1791 | u32 npid = open_file->pid; |
| 1792 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | ||
| 1793 | atomic_dec(&open_file->wrtPending); | ||
| 1794 | } else { | ||
| 1795 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | ||
| 1796 | cifs_sb->local_nls, | ||
| 1797 | cifs_sb->mnt_cifs_flags & | ||
| 1798 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 1799 | } | ||
| 1879 | 1800 | ||
| 1880 | if (!rc) | 1801 | if (!rc) |
| 1881 | rc = inode_setattr(inode, attrs); | 1802 | rc = inode_setattr(inode, attrs); |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 86d0055dc529..f823a4a208a7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -63,374 +63,123 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
| 63 | } | 63 | } |
| 64 | #endif /* DEBUG2 */ | 64 | #endif /* DEBUG2 */ |
| 65 | 65 | ||
| 66 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ | 66 | /* |
| 67 | /* Might check in the future if inode number changed so we can rehash inode */ | 67 | * Find the dentry that matches "name". If there isn't one, create one. If it's |
| 68 | static int | 68 | * a negative dentry or the uniqueid changed, then drop it and recreate it. |
| 69 | construct_dentry(struct qstr *qstring, struct file *file, | 69 | */ |
| 70 | struct inode **ptmp_inode, struct dentry **pnew_dentry, | 70 | static struct dentry * |
| 71 | __u64 *inum) | 71 | cifs_readdir_lookup(struct dentry *parent, struct qstr *name, |
| 72 | struct cifs_fattr *fattr) | ||
| 72 | { | 73 | { |
| 73 | struct dentry *tmp_dentry = NULL; | 74 | struct dentry *dentry, *alias; |
| 74 | struct super_block *sb = file->f_path.dentry->d_sb; | 75 | struct inode *inode; |
| 75 | int rc = 0; | 76 | struct super_block *sb = parent->d_inode->i_sb; |
| 77 | |||
| 78 | cFYI(1, ("For %s", name->name)); | ||
| 79 | |||
| 80 | dentry = d_lookup(parent, name); | ||
| 81 | if (dentry) { | ||
| 82 | /* FIXME: check for inode number changes? */ | ||
| 83 | if (dentry->d_inode != NULL) | ||
| 84 | return dentry; | ||
| 85 | d_drop(dentry); | ||
| 86 | dput(dentry); | ||
| 87 | } | ||
| 76 | 88 | ||
| 77 | cFYI(1, ("For %s", qstring->name)); | 89 | dentry = d_alloc(parent, name); |
| 78 | 90 | if (dentry == NULL) | |
| 79 | qstring->hash = full_name_hash(qstring->name, qstring->len); | 91 | return NULL; |
| 80 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); | ||
| 81 | if (tmp_dentry) { | ||
| 82 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and | ||
| 83 | * tmp_dentry->d_name.len?? | ||
| 84 | */ | ||
| 85 | cFYI(0, ("existing dentry with inode 0x%p", | ||
| 86 | tmp_dentry->d_inode)); | ||
| 87 | *ptmp_inode = tmp_dentry->d_inode; | ||
| 88 | if (*ptmp_inode == NULL) { | ||
| 89 | *ptmp_inode = cifs_new_inode(sb, inum); | ||
| 90 | if (*ptmp_inode == NULL) | ||
| 91 | return rc; | ||
| 92 | rc = 1; | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); | ||
| 96 | if (tmp_dentry == NULL) { | ||
| 97 | cERROR(1, ("Failed allocating dentry")); | ||
| 98 | *ptmp_inode = NULL; | ||
| 99 | return rc; | ||
| 100 | } | ||
| 101 | 92 | ||
| 102 | if (CIFS_SB(sb)->tcon->nocase) | 93 | inode = cifs_iget(sb, fattr); |
| 103 | tmp_dentry->d_op = &cifs_ci_dentry_ops; | 94 | if (!inode) { |
| 104 | else | 95 | dput(dentry); |
| 105 | tmp_dentry->d_op = &cifs_dentry_ops; | 96 | return NULL; |
| 97 | } | ||
| 106 | 98 | ||
| 107 | *ptmp_inode = cifs_new_inode(sb, inum); | 99 | if (CIFS_SB(sb)->tcon->nocase) |
| 108 | if (*ptmp_inode == NULL) | 100 | dentry->d_op = &cifs_ci_dentry_ops; |
| 109 | return rc; | 101 | else |
| 110 | rc = 2; | 102 | dentry->d_op = &cifs_dentry_ops; |
| 103 | |||
| 104 | alias = d_materialise_unique(dentry, inode); | ||
| 105 | if (alias != NULL) { | ||
| 106 | dput(dentry); | ||
| 107 | if (IS_ERR(alias)) | ||
| 108 | return NULL; | ||
| 109 | dentry = alias; | ||
| 111 | } | 110 | } |
| 112 | 111 | ||
| 113 | tmp_dentry->d_time = jiffies; | 112 | return dentry; |
| 114 | *pnew_dentry = tmp_dentry; | ||
| 115 | return rc; | ||
| 116 | } | 113 | } |
| 117 | 114 | ||
| 118 | static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | 115 | static void |
| 119 | char *buf, unsigned int *pobject_type, int isNewInode) | 116 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
| 120 | { | 117 | { |
| 121 | loff_t local_size; | 118 | fattr->cf_uid = cifs_sb->mnt_uid; |
| 122 | struct timespec local_mtime; | 119 | fattr->cf_gid = cifs_sb->mnt_gid; |
| 123 | |||
| 124 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
| 125 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
| 126 | __u32 attr; | ||
| 127 | __u64 allocation_size; | ||
| 128 | __u64 end_of_file; | ||
| 129 | umode_t default_mode; | ||
| 130 | |||
| 131 | /* save mtime and size */ | ||
| 132 | local_mtime = tmp_inode->i_mtime; | ||
| 133 | local_size = tmp_inode->i_size; | ||
| 134 | |||
| 135 | if (new_buf_type) { | ||
| 136 | FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf; | ||
| 137 | |||
| 138 | attr = le32_to_cpu(pfindData->ExtFileAttributes); | ||
| 139 | allocation_size = le64_to_cpu(pfindData->AllocationSize); | ||
| 140 | end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
| 141 | tmp_inode->i_atime = | ||
| 142 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
| 143 | tmp_inode->i_mtime = | ||
| 144 | cifs_NTtimeToUnix(pfindData->LastWriteTime); | ||
| 145 | tmp_inode->i_ctime = | ||
| 146 | cifs_NTtimeToUnix(pfindData->ChangeTime); | ||
| 147 | } else { /* legacy, OS2 and DOS style */ | ||
| 148 | int offset = cifs_sb->tcon->ses->server->timeAdj; | ||
| 149 | FIND_FILE_STANDARD_INFO *pfindData = | ||
| 150 | (FIND_FILE_STANDARD_INFO *)buf; | ||
| 151 | |||
| 152 | tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate, | ||
| 153 | pfindData->LastWriteTime, | ||
| 154 | offset); | ||
| 155 | tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate, | ||
| 156 | pfindData->LastAccessTime, | ||
| 157 | offset); | ||
| 158 | tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate, | ||
| 159 | pfindData->LastWriteTime, | ||
| 160 | offset); | ||
| 161 | attr = le16_to_cpu(pfindData->Attributes); | ||
| 162 | allocation_size = le32_to_cpu(pfindData->AllocationSize); | ||
| 163 | end_of_file = le32_to_cpu(pfindData->DataSize); | ||
| 164 | } | ||
| 165 | 120 | ||
| 166 | /* Linux can not store file creation time unfortunately so ignore it */ | 121 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
| 167 | 122 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | |
| 168 | cifsInfo->cifsAttrs = attr; | 123 | fattr->cf_dtype = DT_DIR; |
| 169 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 124 | } else { |
| 170 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 125 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; |
| 171 | /* get more accurate mode via ACL - so force inode refresh */ | 126 | fattr->cf_dtype = DT_REG; |
| 172 | cifsInfo->time = 0; | ||
| 173 | } else | ||
| 174 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
| 175 | cifsInfo->time = jiffies; | ||
| 176 | |||
| 177 | /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ | ||
| 178 | /* 2767 perms - indicate mandatory locking */ | ||
| 179 | /* BB fill in uid and gid here? with help from winbind? | ||
| 180 | or retrieve from NTFS stream extended attribute */ | ||
| 181 | if (atomic_read(&cifsInfo->inUse) == 0) { | ||
| 182 | tmp_inode->i_uid = cifs_sb->mnt_uid; | ||
| 183 | tmp_inode->i_gid = cifs_sb->mnt_gid; | ||
| 184 | } | ||
| 185 | |||
| 186 | if (attr & ATTR_DIRECTORY) | ||
| 187 | default_mode = cifs_sb->mnt_dir_mode; | ||
| 188 | else | ||
| 189 | default_mode = cifs_sb->mnt_file_mode; | ||
| 190 | |||
| 191 | /* set initial permissions */ | ||
| 192 | if ((atomic_read(&cifsInfo->inUse) == 0) || | ||
| 193 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
| 194 | tmp_inode->i_mode = default_mode; | ||
| 195 | else { | ||
| 196 | /* just reenable write bits if !ATTR_READONLY */ | ||
| 197 | if ((tmp_inode->i_mode & S_IWUGO) == 0 && | ||
| 198 | (attr & ATTR_READONLY) == 0) | ||
| 199 | tmp_inode->i_mode |= (S_IWUGO & default_mode); | ||
| 200 | |||
| 201 | tmp_inode->i_mode &= ~S_IFMT; | ||
| 202 | } | 127 | } |
| 203 | 128 | ||
| 204 | /* clear write bits if ATTR_READONLY is set */ | 129 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
| 205 | if (attr & ATTR_READONLY) | 130 | fattr->cf_mode &= ~S_IWUGO; |
| 206 | tmp_inode->i_mode &= ~S_IWUGO; | ||
| 207 | 131 | ||
| 208 | /* set inode type */ | 132 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && |
| 209 | if ((attr & ATTR_SYSTEM) && | 133 | fattr->cf_cifsattrs & ATTR_SYSTEM) { |
| 210 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { | 134 | if (fattr->cf_eof == 0) { |
| 211 | if (end_of_file == 0) { | 135 | fattr->cf_mode &= ~S_IFMT; |
| 212 | tmp_inode->i_mode |= S_IFIFO; | 136 | fattr->cf_mode |= S_IFIFO; |
| 213 | *pobject_type = DT_FIFO; | 137 | fattr->cf_dtype = DT_FIFO; |
| 214 | } else { | 138 | } else { |
| 215 | /* | 139 | /* |
| 216 | * trying to get the type can be slow, so just call | 140 | * trying to get the type and mode via SFU can be slow, |
| 217 | * this a regular file for now, and mark for reval | 141 | * so just call those regular files for now, and mark |
| 142 | * for reval | ||
| 218 | */ | 143 | */ |
| 219 | tmp_inode->i_mode |= S_IFREG; | 144 | fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; |
| 220 | *pobject_type = DT_REG; | ||
| 221 | cifsInfo->time = 0; | ||
| 222 | } | ||
| 223 | } else { | ||
| 224 | if (attr & ATTR_DIRECTORY) { | ||
| 225 | tmp_inode->i_mode |= S_IFDIR; | ||
| 226 | *pobject_type = DT_DIR; | ||
| 227 | } else { | ||
| 228 | tmp_inode->i_mode |= S_IFREG; | ||
| 229 | *pobject_type = DT_REG; | ||
| 230 | } | 145 | } |
| 231 | } | 146 | } |
| 147 | } | ||
| 232 | 148 | ||
| 233 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 149 | void |
| 234 | if (atomic_read(&cifsInfo->inUse) == 0) | 150 | cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, |
| 235 | atomic_set(&cifsInfo->inUse, 1); | 151 | struct cifs_sb_info *cifs_sb) |
| 236 | 152 | { | |
| 237 | cifsInfo->server_eof = end_of_file; | 153 | memset(fattr, 0, sizeof(*fattr)); |
| 238 | spin_lock(&tmp_inode->i_lock); | 154 | fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); |
| 239 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 155 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
| 240 | /* can not safely change the file size here if the | 156 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
| 241 | client is writing to it due to potential races */ | 157 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
| 242 | i_size_write(tmp_inode, end_of_file); | 158 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
| 243 | 159 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); | |
| 244 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | 160 | |
| 245 | /* for this calculation, even though the reported blocksize is larger */ | 161 | cifs_fill_common_info(fattr, cifs_sb); |
| 246 | tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; | ||
| 247 | } | ||
| 248 | spin_unlock(&tmp_inode->i_lock); | ||
| 249 | |||
| 250 | if (allocation_size < end_of_file) | ||
| 251 | cFYI(1, ("May be sparse file, allocation less than file size")); | ||
| 252 | cFYI(1, ("File Size %ld and blocks %llu", | ||
| 253 | (unsigned long)tmp_inode->i_size, | ||
| 254 | (unsigned long long)tmp_inode->i_blocks)); | ||
| 255 | if (S_ISREG(tmp_inode->i_mode)) { | ||
| 256 | cFYI(1, ("File inode")); | ||
| 257 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
| 258 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
| 259 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 260 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
| 261 | else | ||
| 262 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
| 263 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 264 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
| 265 | else | ||
| 266 | tmp_inode->i_fop = &cifs_file_ops; | ||
| 267 | |||
| 268 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
| 269 | (cifs_sb->tcon->ses->server->maxBuf < | ||
| 270 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
| 271 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
| 272 | else | ||
| 273 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
| 274 | |||
| 275 | if (isNewInode) | ||
| 276 | return; /* No sense invalidating pages for new inode | ||
| 277 | since have not started caching readahead file | ||
| 278 | data yet */ | ||
| 279 | |||
| 280 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
| 281 | (local_size == tmp_inode->i_size)) { | ||
| 282 | cFYI(1, ("inode exists but unchanged")); | ||
| 283 | } else { | ||
| 284 | /* file may have changed on server */ | ||
| 285 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
| 286 | invalidate_remote_inode(tmp_inode); | ||
| 287 | } | ||
| 288 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
| 289 | cFYI(1, ("Directory inode")); | ||
| 290 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
| 291 | tmp_inode->i_fop = &cifs_dir_ops; | ||
| 292 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
| 293 | cFYI(1, ("Symbolic Link inode")); | ||
| 294 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
| 295 | } else { | ||
| 296 | cFYI(1, ("Init special inode")); | ||
| 297 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
| 298 | tmp_inode->i_rdev); | ||
| 299 | } | ||
| 300 | } | 162 | } |
| 301 | 163 | ||
| 302 | static void unix_fill_in_inode(struct inode *tmp_inode, | 164 | void |
| 303 | FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode) | 165 | cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, |
| 166 | struct cifs_sb_info *cifs_sb) | ||
| 304 | { | 167 | { |
| 305 | loff_t local_size; | 168 | int offset = cifs_sb->tcon->ses->server->timeAdj; |
| 306 | struct timespec local_mtime; | ||
| 307 | |||
| 308 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
| 309 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
| 310 | |||
| 311 | __u32 type = le32_to_cpu(pfindData->Type); | ||
| 312 | __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes); | ||
| 313 | __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile); | ||
| 314 | cifsInfo->time = jiffies; | ||
| 315 | atomic_inc(&cifsInfo->inUse); | ||
| 316 | |||
| 317 | /* save mtime and size */ | ||
| 318 | local_mtime = tmp_inode->i_mtime; | ||
| 319 | local_size = tmp_inode->i_size; | ||
| 320 | |||
| 321 | tmp_inode->i_atime = | ||
| 322 | cifs_NTtimeToUnix(pfindData->LastAccessTime); | ||
| 323 | tmp_inode->i_mtime = | ||
| 324 | cifs_NTtimeToUnix(pfindData->LastModificationTime); | ||
| 325 | tmp_inode->i_ctime = | ||
| 326 | cifs_NTtimeToUnix(pfindData->LastStatusChange); | ||
| 327 | |||
| 328 | tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions); | ||
| 329 | /* since we set the inode type below we need to mask off type | ||
| 330 | to avoid strange results if bits above were corrupt */ | ||
| 331 | tmp_inode->i_mode &= ~S_IFMT; | ||
| 332 | if (type == UNIX_FILE) { | ||
| 333 | *pobject_type = DT_REG; | ||
| 334 | tmp_inode->i_mode |= S_IFREG; | ||
| 335 | } else if (type == UNIX_SYMLINK) { | ||
| 336 | *pobject_type = DT_LNK; | ||
| 337 | tmp_inode->i_mode |= S_IFLNK; | ||
| 338 | } else if (type == UNIX_DIR) { | ||
| 339 | *pobject_type = DT_DIR; | ||
| 340 | tmp_inode->i_mode |= S_IFDIR; | ||
| 341 | } else if (type == UNIX_CHARDEV) { | ||
| 342 | *pobject_type = DT_CHR; | ||
| 343 | tmp_inode->i_mode |= S_IFCHR; | ||
| 344 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
| 345 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
| 346 | } else if (type == UNIX_BLOCKDEV) { | ||
| 347 | *pobject_type = DT_BLK; | ||
| 348 | tmp_inode->i_mode |= S_IFBLK; | ||
| 349 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor), | ||
| 350 | le64_to_cpu(pfindData->DevMinor) & MINORMASK); | ||
| 351 | } else if (type == UNIX_FIFO) { | ||
| 352 | *pobject_type = DT_FIFO; | ||
| 353 | tmp_inode->i_mode |= S_IFIFO; | ||
| 354 | } else if (type == UNIX_SOCKET) { | ||
| 355 | *pobject_type = DT_SOCK; | ||
| 356 | tmp_inode->i_mode |= S_IFSOCK; | ||
| 357 | } else { | ||
| 358 | /* safest to just call it a file */ | ||
| 359 | *pobject_type = DT_REG; | ||
| 360 | tmp_inode->i_mode |= S_IFREG; | ||
| 361 | cFYI(1, ("unknown inode type %d", type)); | ||
| 362 | } | ||
| 363 | 169 | ||
| 364 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 170 | memset(fattr, 0, sizeof(*fattr)); |
| 365 | tmp_inode->i_uid = cifs_sb->mnt_uid; | 171 | fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, |
| 366 | else | 172 | info->LastAccessTime, offset); |
| 367 | tmp_inode->i_uid = le64_to_cpu(pfindData->Uid); | 173 | fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, |
| 368 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | 174 | info->LastWriteTime, offset); |
| 369 | tmp_inode->i_gid = cifs_sb->mnt_gid; | 175 | fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, |
| 370 | else | 176 | info->LastWriteTime, offset); |
| 371 | tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); | ||
| 372 | tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); | ||
| 373 | |||
| 374 | cifsInfo->server_eof = end_of_file; | ||
| 375 | spin_lock(&tmp_inode->i_lock); | ||
| 376 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
| 377 | /* can not safely change the file size here if the | ||
| 378 | client is writing to it due to potential races */ | ||
| 379 | i_size_write(tmp_inode, end_of_file); | ||
| 380 | |||
| 381 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
| 382 | /* for this calculation, not the real blocksize */ | ||
| 383 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
| 384 | } | ||
| 385 | spin_unlock(&tmp_inode->i_lock); | ||
| 386 | 177 | ||
| 387 | if (S_ISREG(tmp_inode->i_mode)) { | 178 | fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); |
| 388 | cFYI(1, ("File inode")); | 179 | fattr->cf_bytes = le32_to_cpu(info->AllocationSize); |
| 389 | tmp_inode->i_op = &cifs_file_inode_ops; | 180 | fattr->cf_eof = le32_to_cpu(info->DataSize); |
| 390 | 181 | ||
| 391 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | 182 | cifs_fill_common_info(fattr, cifs_sb); |
| 392 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 393 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
| 394 | else | ||
| 395 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
| 396 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 397 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
| 398 | else | ||
| 399 | tmp_inode->i_fop = &cifs_file_ops; | ||
| 400 | |||
| 401 | if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
| 402 | (cifs_sb->tcon->ses->server->maxBuf < | ||
| 403 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
| 404 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
| 405 | else | ||
| 406 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
| 407 | |||
| 408 | if (isNewInode) | ||
| 409 | return; /* No sense invalidating pages for new inode | ||
| 410 | since we have not started caching readahead | ||
| 411 | file data for it yet */ | ||
| 412 | |||
| 413 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
| 414 | (local_size == tmp_inode->i_size)) { | ||
| 415 | cFYI(1, ("inode exists but unchanged")); | ||
| 416 | } else { | ||
| 417 | /* file may have changed on server */ | ||
| 418 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
| 419 | invalidate_remote_inode(tmp_inode); | ||
| 420 | } | ||
| 421 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
| 422 | cFYI(1, ("Directory inode")); | ||
| 423 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
| 424 | tmp_inode->i_fop = &cifs_dir_ops; | ||
| 425 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
| 426 | cFYI(1, ("Symbolic Link inode")); | ||
| 427 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
| 428 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
| 429 | } else { | ||
| 430 | cFYI(1, ("Special inode")); | ||
| 431 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
| 432 | tmp_inode->i_rdev); | ||
| 433 | } | ||
| 434 | } | 183 | } |
| 435 | 184 | ||
| 436 | /* BB eventually need to add the following helper function to | 185 | /* BB eventually need to add the following helper function to |
| @@ -872,7 +621,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
| 872 | len = strnlen(filename, PATH_MAX); | 621 | len = strnlen(filename, PATH_MAX); |
| 873 | } | 622 | } |
| 874 | 623 | ||
| 875 | *pinum = le64_to_cpu(pFindData->UniqueId); | 624 | *pinum = le64_to_cpu(pFindData->basic.UniqueId); |
| 876 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 625 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
| 877 | FILE_DIRECTORY_INFO *pFindData = | 626 | FILE_DIRECTORY_INFO *pFindData = |
| 878 | (FILE_DIRECTORY_INFO *)current_entry; | 627 | (FILE_DIRECTORY_INFO *)current_entry; |
| @@ -932,11 +681,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
| 932 | int rc = 0; | 681 | int rc = 0; |
| 933 | struct qstr qstring; | 682 | struct qstr qstring; |
| 934 | struct cifsFileInfo *pCifsF; | 683 | struct cifsFileInfo *pCifsF; |
| 935 | unsigned int obj_type; | 684 | u64 inum; |
| 936 | __u64 inum; | 685 | ino_t ino; |
| 686 | struct super_block *sb; | ||
| 937 | struct cifs_sb_info *cifs_sb; | 687 | struct cifs_sb_info *cifs_sb; |
| 938 | struct inode *tmp_inode; | ||
| 939 | struct dentry *tmp_dentry; | 688 | struct dentry *tmp_dentry; |
| 689 | struct cifs_fattr fattr; | ||
| 940 | 690 | ||
| 941 | /* get filename and len into qstring */ | 691 | /* get filename and len into qstring */ |
| 942 | /* get dentry */ | 692 | /* get dentry */ |
| @@ -954,60 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, | |||
| 954 | if (rc != 0) | 704 | if (rc != 0) |
| 955 | return 0; | 705 | return 0; |
| 956 | 706 | ||
| 957 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 707 | sb = file->f_path.dentry->d_sb; |
| 708 | cifs_sb = CIFS_SB(sb); | ||
| 958 | 709 | ||
| 959 | qstring.name = scratch_buf; | 710 | qstring.name = scratch_buf; |
| 960 | rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, | 711 | rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, |
| 961 | pCifsF->srch_inf.info_level, | 712 | pCifsF->srch_inf.info_level, |
| 962 | pCifsF->srch_inf.unicode, cifs_sb, | 713 | pCifsF->srch_inf.unicode, cifs_sb, |
| 963 | max_len, | 714 | max_len, &inum /* returned */); |
| 964 | &inum /* returned */); | ||
| 965 | 715 | ||
| 966 | if (rc) | 716 | if (rc) |
| 967 | return rc; | 717 | return rc; |
| 968 | 718 | ||
| 969 | /* only these two infolevels return valid inode numbers */ | ||
| 970 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || | ||
| 971 | pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) | ||
| 972 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
| 973 | &inum); | ||
| 974 | else | ||
| 975 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
| 976 | NULL); | ||
| 977 | |||
| 978 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) | ||
| 979 | return -ENOMEM; | ||
| 980 | |||
| 981 | /* we pass in rc below, indicating whether it is a new inode, | ||
| 982 | so we can figure out whether to invalidate the inode cached | ||
| 983 | data if the file has changed */ | ||
| 984 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) | 719 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) |
| 985 | unix_fill_in_inode(tmp_inode, | 720 | cifs_unix_basic_to_fattr(&fattr, |
| 986 | (FILE_UNIX_INFO *)pfindEntry, | 721 | &((FILE_UNIX_INFO *) pfindEntry)->basic, |
| 987 | &obj_type, rc); | 722 | cifs_sb); |
| 988 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) | 723 | else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) |
| 989 | fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */, | 724 | cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) |
| 990 | pfindEntry, &obj_type, rc); | 725 | pfindEntry, cifs_sb); |
| 991 | else | 726 | else |
| 992 | fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); | 727 | cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) |
| 728 | pfindEntry, cifs_sb); | ||
| 993 | 729 | ||
| 994 | if (rc) /* new inode - needs to be tied to dentry */ { | 730 | /* FIXME: make _to_fattr functions fill this out */ |
| 995 | d_instantiate(tmp_dentry, tmp_inode); | 731 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) |
| 996 | if (rc == 2) | 732 | fattr.cf_uniqueid = inum; |
| 997 | d_rehash(tmp_dentry); | 733 | else |
| 998 | } | 734 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
| 999 | 735 | ||
| 736 | ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); | ||
| 737 | tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); | ||
| 1000 | 738 | ||
| 1001 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, | 739 | rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, |
| 1002 | tmp_inode->i_ino, obj_type); | 740 | ino, fattr.cf_dtype); |
| 741 | |||
| 742 | /* | ||
| 743 | * we can not return filldir errors to the caller since they are | ||
| 744 | * "normal" when the stat blocksize is too small - we return remapped | ||
| 745 | * error instead | ||
| 746 | * | ||
| 747 | * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above | ||
| 748 | * case already. Why should we be clobbering other errors from it? | ||
| 749 | */ | ||
| 1003 | if (rc) { | 750 | if (rc) { |
| 1004 | cFYI(1, ("filldir rc = %d", rc)); | 751 | cFYI(1, ("filldir rc = %d", rc)); |
| 1005 | /* we can not return filldir errors to the caller | ||
| 1006 | since they are "normal" when the stat blocksize | ||
| 1007 | is too small - we return remapped error instead */ | ||
| 1008 | rc = -EOVERFLOW; | 752 | rc = -EOVERFLOW; |
| 1009 | } | 753 | } |
| 1010 | |||
| 1011 | dput(tmp_dentry); | 754 | dput(tmp_dentry); |
| 1012 | return rc; | 755 | return rc; |
| 1013 | } | 756 | } |
diff --git a/fs/compat.c b/fs/compat.c index cdd51a3a7c53..94502dab972a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <linux/smb_mount.h> | 32 | #include <linux/smb_mount.h> |
| 33 | #include <linux/ncp_mount.h> | 33 | #include <linux/ncp_mount.h> |
| 34 | #include <linux/nfs4_mount.h> | 34 | #include <linux/nfs4_mount.h> |
| 35 | #include <linux/smp_lock.h> | ||
| 36 | #include <linux/syscalls.h> | 35 | #include <linux/syscalls.h> |
| 37 | #include <linux/ctype.h> | 36 | #include <linux/ctype.h> |
| 38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| @@ -1486,8 +1485,8 @@ int compat_do_execve(char * filename, | |||
| 1486 | if (!bprm) | 1485 | if (!bprm) |
| 1487 | goto out_files; | 1486 | goto out_files; |
| 1488 | 1487 | ||
| 1489 | retval = mutex_lock_interruptible(¤t->cred_guard_mutex); | 1488 | retval = -ERESTARTNOINTR; |
| 1490 | if (retval < 0) | 1489 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) |
| 1491 | goto out_free; | 1490 | goto out_free; |
| 1492 | current->in_execve = 1; | 1491 | current->in_execve = 1; |
| 1493 | 1492 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 626c7483b4de..f91fd51b32e3 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/compiler.h> | 19 | #include <linux/compiler.h> |
| 20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 22 | #include <linux/ioctl.h> | 23 | #include <linux/ioctl.h> |
| 23 | #include <linux/if.h> | 24 | #include <linux/if.h> |
| 24 | #include <linux/if_bridge.h> | 25 | #include <linux/if_bridge.h> |
| @@ -1904,6 +1905,7 @@ COMPATIBLE_IOCTL(FIONCLEX) | |||
| 1904 | COMPATIBLE_IOCTL(FIOASYNC) | 1905 | COMPATIBLE_IOCTL(FIOASYNC) |
| 1905 | COMPATIBLE_IOCTL(FIONBIO) | 1906 | COMPATIBLE_IOCTL(FIONBIO) |
| 1906 | COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ | 1907 | COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ |
| 1908 | COMPATIBLE_IOCTL(FS_IOC_FIEMAP) | ||
| 1907 | /* 0x00 */ | 1909 | /* 0x00 */ |
| 1908 | COMPATIBLE_IOCTL(FIBMAP) | 1910 | COMPATIBLE_IOCTL(FIBMAP) |
| 1909 | COMPATIBLE_IOCTL(FIGETBSZ) | 1911 | COMPATIBLE_IOCTL(FIGETBSZ) |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 205ec95b347e..eb507c453c5f 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -435,7 +435,7 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b, | |||
| 435 | static int find_rsb(struct dlm_ls *ls, char *name, int namelen, | 435 | static int find_rsb(struct dlm_ls *ls, char *name, int namelen, |
| 436 | unsigned int flags, struct dlm_rsb **r_ret) | 436 | unsigned int flags, struct dlm_rsb **r_ret) |
| 437 | { | 437 | { |
| 438 | struct dlm_rsb *r, *tmp; | 438 | struct dlm_rsb *r = NULL, *tmp; |
| 439 | uint32_t hash, bucket; | 439 | uint32_t hash, bucket; |
| 440 | int error = -EINVAL; | 440 | int error = -EINVAL; |
| 441 | 441 | ||
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index cdb580a9c7a2..618a60f03886 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
| @@ -902,7 +902,7 @@ static void tcp_connect_to_sock(struct connection *con) | |||
| 902 | int result = -EHOSTUNREACH; | 902 | int result = -EHOSTUNREACH; |
| 903 | struct sockaddr_storage saddr, src_addr; | 903 | struct sockaddr_storage saddr, src_addr; |
| 904 | int addr_len; | 904 | int addr_len; |
| 905 | struct socket *sock; | 905 | struct socket *sock = NULL; |
| 906 | 906 | ||
| 907 | if (con->nodeid == 0) { | 907 | if (con->nodeid == 0) { |
| 908 | log_print("attempt to connect sock 0 foiled"); | 908 | log_print("attempt to connect sock 0 foiled"); |
| @@ -962,6 +962,8 @@ out_err: | |||
| 962 | if (con->sock) { | 962 | if (con->sock) { |
| 963 | sock_release(con->sock); | 963 | sock_release(con->sock); |
| 964 | con->sock = NULL; | 964 | con->sock = NULL; |
| 965 | } else if (sock) { | ||
| 966 | sock_release(sock); | ||
| 965 | } | 967 | } |
| 966 | /* | 968 | /* |
| 967 | * Some errors are fatal and this list might need adjusting. For other | 969 | * Some errors are fatal and this list might need adjusting. For other |
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index 894a32d438d5..16f682e26c07 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c | |||
| @@ -353,7 +353,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count, | |||
| 353 | { | 353 | { |
| 354 | struct dlm_plock_info info; | 354 | struct dlm_plock_info info; |
| 355 | struct plock_op *op; | 355 | struct plock_op *op; |
| 356 | int found = 0; | 356 | int found = 0, do_callback = 0; |
| 357 | 357 | ||
| 358 | if (count != sizeof(info)) | 358 | if (count != sizeof(info)) |
| 359 | return -EINVAL; | 359 | return -EINVAL; |
| @@ -366,21 +366,24 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count, | |||
| 366 | 366 | ||
| 367 | spin_lock(&ops_lock); | 367 | spin_lock(&ops_lock); |
| 368 | list_for_each_entry(op, &recv_list, list) { | 368 | list_for_each_entry(op, &recv_list, list) { |
| 369 | if (op->info.fsid == info.fsid && op->info.number == info.number && | 369 | if (op->info.fsid == info.fsid && |
| 370 | op->info.number == info.number && | ||
| 370 | op->info.owner == info.owner) { | 371 | op->info.owner == info.owner) { |
| 372 | struct plock_xop *xop = (struct plock_xop *)op; | ||
| 371 | list_del_init(&op->list); | 373 | list_del_init(&op->list); |
| 372 | found = 1; | ||
| 373 | op->done = 1; | ||
| 374 | memcpy(&op->info, &info, sizeof(info)); | 374 | memcpy(&op->info, &info, sizeof(info)); |
| 375 | if (xop->callback) | ||
| 376 | do_callback = 1; | ||
| 377 | else | ||
| 378 | op->done = 1; | ||
| 379 | found = 1; | ||
| 375 | break; | 380 | break; |
| 376 | } | 381 | } |
| 377 | } | 382 | } |
| 378 | spin_unlock(&ops_lock); | 383 | spin_unlock(&ops_lock); |
| 379 | 384 | ||
| 380 | if (found) { | 385 | if (found) { |
| 381 | struct plock_xop *xop; | 386 | if (do_callback) |
| 382 | xop = (struct plock_xop *)op; | ||
| 383 | if (xop->callback) | ||
| 384 | dlm_plock_callback(op); | 387 | dlm_plock_callback(op); |
| 385 | else | 388 | else |
| 386 | wake_up(&recv_wq); | 389 | wake_up(&recv_wq); |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index af737bb56cb7..259525c9abb8 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
| @@ -1303,6 +1303,13 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, | |||
| 1303 | } | 1303 | } |
| 1304 | (*new_auth_tok)->session_key.encrypted_key_size = | 1304 | (*new_auth_tok)->session_key.encrypted_key_size = |
| 1305 | (body_size - (ECRYPTFS_SALT_SIZE + 5)); | 1305 | (body_size - (ECRYPTFS_SALT_SIZE + 5)); |
| 1306 | if ((*new_auth_tok)->session_key.encrypted_key_size | ||
| 1307 | > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { | ||
| 1308 | printk(KERN_WARNING "Tag 3 packet contains key larger " | ||
| 1309 | "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n"); | ||
| 1310 | rc = -EINVAL; | ||
| 1311 | goto out_free; | ||
| 1312 | } | ||
| 1306 | if (unlikely(data[(*packet_size)++] != 0x04)) { | 1313 | if (unlikely(data[(*packet_size)++] != 0x04)) { |
| 1307 | printk(KERN_WARNING "Unknown version number [%d]\n", | 1314 | printk(KERN_WARNING "Unknown version number [%d]\n", |
| 1308 | data[(*packet_size) - 1]); | 1315 | data[(*packet_size) - 1]); |
| @@ -1449,6 +1456,12 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents, | |||
| 1449 | rc = -EINVAL; | 1456 | rc = -EINVAL; |
| 1450 | goto out; | 1457 | goto out; |
| 1451 | } | 1458 | } |
| 1459 | if (unlikely((*tag_11_contents_size) > max_contents_bytes)) { | ||
| 1460 | printk(KERN_ERR "Literal data section in tag 11 packet exceeds " | ||
| 1461 | "expected size\n"); | ||
| 1462 | rc = -EINVAL; | ||
| 1463 | goto out; | ||
| 1464 | } | ||
| 1452 | if (data[(*packet_size)++] != 0x62) { | 1465 | if (data[(*packet_size)++] != 0x62) { |
| 1453 | printk(KERN_WARNING "Unrecognizable packet\n"); | 1466 | printk(KERN_WARNING "Unrecognizable packet\n"); |
| 1454 | rc = -EINVAL; | 1467 | rc = -EINVAL; |
| @@ -1277,8 +1277,8 @@ int do_execve(char * filename, | |||
| 1277 | if (!bprm) | 1277 | if (!bprm) |
| 1278 | goto out_files; | 1278 | goto out_files; |
| 1279 | 1279 | ||
| 1280 | retval = mutex_lock_interruptible(¤t->cred_guard_mutex); | 1280 | retval = -ERESTARTNOINTR; |
| 1281 | if (retval < 0) | 1281 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) |
| 1282 | goto out_free; | 1282 | goto out_free; |
| 1283 | current->in_execve = 1; | 1283 | current->in_execve = 1; |
| 1284 | 1284 | ||
diff --git a/fs/exofs/common.h b/fs/exofs/common.h index 24667eedc023..c6718e4817fe 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h | |||
| @@ -2,9 +2,7 @@ | |||
| 2 | * common.h - Common definitions for both Kernel and user-mode utilities | 2 | * common.h - Common definitions for both Kernel and user-mode utilities |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005, 2006 | 4 | * Copyright (C) 2005, 2006 |
| 5 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 5 | * Avishay Traeger (avishay@gmail.com) |
| 6 | * Copyright (C) 2005, 2006 | ||
| 7 | * International Business Machines | ||
| 8 | * Copyright (C) 2008, 2009 | 6 | * Copyright (C) 2008, 2009 |
| 9 | * Boaz Harrosh <bharrosh@panasas.com> | 7 | * Boaz Harrosh <bharrosh@panasas.com> |
| 10 | * | 8 | * |
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index 65b0c8c776a1..4cfab1cc75c0 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 0fd4c7859679..5ec72e020b22 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
| @@ -156,6 +154,9 @@ ino_t exofs_parent_ino(struct dentry *child); | |||
| 156 | int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, | 154 | int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, |
| 157 | struct inode *); | 155 | struct inode *); |
| 158 | 156 | ||
| 157 | /* super.c */ | ||
| 158 | int exofs_sync_fs(struct super_block *sb, int wait); | ||
| 159 | |||
| 159 | /********************* | 160 | /********************* |
| 160 | * operation vectors * | 161 | * operation vectors * |
| 161 | *********************/ | 162 | *********************/ |
diff --git a/fs/exofs/file.c b/fs/exofs/file.c index 6ed7fe484752..839b9dc1e70f 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
| @@ -47,16 +45,23 @@ static int exofs_file_fsync(struct file *filp, struct dentry *dentry, | |||
| 47 | { | 45 | { |
| 48 | int ret; | 46 | int ret; |
| 49 | struct address_space *mapping = filp->f_mapping; | 47 | struct address_space *mapping = filp->f_mapping; |
| 48 | struct inode *inode = dentry->d_inode; | ||
| 49 | struct super_block *sb; | ||
| 50 | 50 | ||
| 51 | ret = filemap_write_and_wait(mapping); | 51 | ret = filemap_write_and_wait(mapping); |
| 52 | if (ret) | 52 | if (ret) |
| 53 | return ret; | 53 | return ret; |
| 54 | 54 | ||
| 55 | /*Note: file_fsync below also calles sync_blockdev, which is a no-op | 55 | /* sync the inode attributes */ |
| 56 | * for exofs, but other then that it does sync_inode and | 56 | ret = write_inode_now(inode, 1); |
| 57 | * sync_superblock which is what we need here. | 57 | |
| 58 | */ | 58 | /* This is a good place to write the sb */ |
| 59 | return file_fsync(filp, dentry, datasync); | 59 | /* TODO: Sechedule an sb-sync on create */ |
| 60 | sb = inode->i_sb; | ||
| 61 | if (sb->s_dirt) | ||
| 62 | exofs_sync_fs(sb, 1); | ||
| 63 | |||
| 64 | return ret; | ||
| 60 | } | 65 | } |
| 61 | 66 | ||
| 62 | static int exofs_flush(struct file *file, fl_owner_t id) | 67 | static int exofs_flush(struct file *file, fl_owner_t id) |
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 77d0a295eb1c..6c10f7476699 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
| @@ -295,6 +293,9 @@ static int read_exec(struct page_collect *pcol, bool is_sync) | |||
| 295 | err: | 293 | err: |
| 296 | if (!is_sync) | 294 | if (!is_sync) |
| 297 | _unlock_pcol_pages(pcol, ret, READ); | 295 | _unlock_pcol_pages(pcol, ret, READ); |
| 296 | else /* Pages unlocked by caller in sync mode only free bio */ | ||
| 297 | pcol_free(pcol); | ||
| 298 | |||
| 298 | kfree(pcol_copy); | 299 | kfree(pcol_copy); |
| 299 | if (or) | 300 | if (or) |
| 300 | osd_end_request(or); | 301 | osd_end_request(or); |
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c index 77fdd765e76d..b7dd0c236863 100644 --- a/fs/exofs/namei.c +++ b/fs/exofs/namei.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
diff --git a/fs/exofs/osd.c b/fs/exofs/osd.c index b3d2ccb87aaa..4372542df284 100644 --- a/fs/exofs/osd.c +++ b/fs/exofs/osd.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 8216c5b77b53..5ab10c3bbebe 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
| @@ -33,6 +31,7 @@ | |||
| 33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 31 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 34 | */ | 32 | */ |
| 35 | 33 | ||
| 34 | #include <linux/smp_lock.h> | ||
| 36 | #include <linux/string.h> | 35 | #include <linux/string.h> |
| 37 | #include <linux/parser.h> | 36 | #include <linux/parser.h> |
| 38 | #include <linux/vfs.h> | 37 | #include <linux/vfs.h> |
| @@ -200,7 +199,7 @@ static const struct export_operations exofs_export_ops; | |||
| 200 | /* | 199 | /* |
| 201 | * Write the superblock to the OSD | 200 | * Write the superblock to the OSD |
| 202 | */ | 201 | */ |
| 203 | static int exofs_sync_fs(struct super_block *sb, int wait) | 202 | int exofs_sync_fs(struct super_block *sb, int wait) |
| 204 | { | 203 | { |
| 205 | struct exofs_sb_info *sbi; | 204 | struct exofs_sb_info *sbi; |
| 206 | struct exofs_fscb *fscb; | 205 | struct exofs_fscb *fscb; |
diff --git a/fs/exofs/symlink.c b/fs/exofs/symlink.c index 36e2d7bc7f7b..4dd687c3e747 100644 --- a/fs/exofs/symlink.c +++ b/fs/exofs/symlink.c | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2005, 2006 | 2 | * Copyright (C) 2005, 2006 |
| 3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | 3 | * Avishay Traeger (avishay@gmail.com) |
| 4 | * Copyright (C) 2005, 2006 | ||
| 5 | * International Business Machines | ||
| 6 | * Copyright (C) 2008, 2009 | 4 | * Copyright (C) 2008, 2009 |
| 7 | * Boaz Harrosh <bharrosh@panasas.com> | 5 | * Boaz Harrosh <bharrosh@panasas.com> |
| 8 | * | 6 | * |
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index 7cb4badef927..e7431309bdca 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | #include <linux/compat.h> | 14 | #include <linux/compat.h> |
| 15 | #include <linux/mount.h> | 15 | #include <linux/mount.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 17 | #include <asm/current.h> | 16 | #include <asm/current.h> |
| 18 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
| 19 | 18 | ||
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 3d724a95882f..373fa90c796a 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
| @@ -130,8 +130,7 @@ static int ext3_readdir(struct file * filp, | |||
| 130 | struct buffer_head *bh = NULL; | 130 | struct buffer_head *bh = NULL; |
| 131 | 131 | ||
| 132 | map_bh.b_state = 0; | 132 | map_bh.b_state = 0; |
| 133 | err = ext3_get_blocks_handle(NULL, inode, blk, 1, | 133 | err = ext3_get_blocks_handle(NULL, inode, blk, 1, &map_bh, 0); |
| 134 | &map_bh, 0, 0); | ||
| 135 | if (err > 0) { | 134 | if (err > 0) { |
| 136 | pgoff_t index = map_bh.b_blocknr >> | 135 | pgoff_t index = map_bh.b_blocknr >> |
| 137 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | 136 | (PAGE_CACHE_SHIFT - inode->i_blkbits); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 5f51fed5c750..b49908a167ae 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -788,7 +788,7 @@ err_out: | |||
| 788 | int ext3_get_blocks_handle(handle_t *handle, struct inode *inode, | 788 | int ext3_get_blocks_handle(handle_t *handle, struct inode *inode, |
| 789 | sector_t iblock, unsigned long maxblocks, | 789 | sector_t iblock, unsigned long maxblocks, |
| 790 | struct buffer_head *bh_result, | 790 | struct buffer_head *bh_result, |
| 791 | int create, int extend_disksize) | 791 | int create) |
| 792 | { | 792 | { |
| 793 | int err = -EIO; | 793 | int err = -EIO; |
| 794 | int offsets[4]; | 794 | int offsets[4]; |
| @@ -911,13 +911,6 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
| 911 | if (!err) | 911 | if (!err) |
| 912 | err = ext3_splice_branch(handle, inode, iblock, | 912 | err = ext3_splice_branch(handle, inode, iblock, |
| 913 | partial, indirect_blks, count); | 913 | partial, indirect_blks, count); |
| 914 | /* | ||
| 915 | * i_disksize growing is protected by truncate_mutex. Don't forget to | ||
| 916 | * protect it if you're about to implement concurrent | ||
| 917 | * ext3_get_block() -bzzz | ||
| 918 | */ | ||
| 919 | if (!err && extend_disksize && inode->i_size > ei->i_disksize) | ||
| 920 | ei->i_disksize = inode->i_size; | ||
| 921 | mutex_unlock(&ei->truncate_mutex); | 914 | mutex_unlock(&ei->truncate_mutex); |
| 922 | if (err) | 915 | if (err) |
| 923 | goto cleanup; | 916 | goto cleanup; |
| @@ -972,7 +965,7 @@ static int ext3_get_block(struct inode *inode, sector_t iblock, | |||
| 972 | } | 965 | } |
| 973 | 966 | ||
| 974 | ret = ext3_get_blocks_handle(handle, inode, iblock, | 967 | ret = ext3_get_blocks_handle(handle, inode, iblock, |
| 975 | max_blocks, bh_result, create, 0); | 968 | max_blocks, bh_result, create); |
| 976 | if (ret > 0) { | 969 | if (ret > 0) { |
| 977 | bh_result->b_size = (ret << inode->i_blkbits); | 970 | bh_result->b_size = (ret << inode->i_blkbits); |
| 978 | ret = 0; | 971 | ret = 0; |
| @@ -1005,7 +998,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode, | |||
| 1005 | dummy.b_blocknr = -1000; | 998 | dummy.b_blocknr = -1000; |
| 1006 | buffer_trace_init(&dummy.b_history); | 999 | buffer_trace_init(&dummy.b_history); |
| 1007 | err = ext3_get_blocks_handle(handle, inode, block, 1, | 1000 | err = ext3_get_blocks_handle(handle, inode, block, 1, |
| 1008 | &dummy, create, 1); | 1001 | &dummy, create); |
| 1009 | /* | 1002 | /* |
| 1010 | * ext3_get_blocks_handle() returns number of blocks | 1003 | * ext3_get_blocks_handle() returns number of blocks |
| 1011 | * mapped. 0 in case of a HOLE. | 1004 | * mapped. 0 in case of a HOLE. |
| @@ -1193,15 +1186,16 @@ write_begin_failed: | |||
| 1193 | * i_size_read because we hold i_mutex. | 1186 | * i_size_read because we hold i_mutex. |
| 1194 | * | 1187 | * |
| 1195 | * Add inode to orphan list in case we crash before truncate | 1188 | * Add inode to orphan list in case we crash before truncate |
| 1196 | * finishes. | 1189 | * finishes. Do this only if ext3_can_truncate() agrees so |
| 1190 | * that orphan processing code is happy. | ||
| 1197 | */ | 1191 | */ |
| 1198 | if (pos + len > inode->i_size) | 1192 | if (pos + len > inode->i_size && ext3_can_truncate(inode)) |
| 1199 | ext3_orphan_add(handle, inode); | 1193 | ext3_orphan_add(handle, inode); |
| 1200 | ext3_journal_stop(handle); | 1194 | ext3_journal_stop(handle); |
| 1201 | unlock_page(page); | 1195 | unlock_page(page); |
| 1202 | page_cache_release(page); | 1196 | page_cache_release(page); |
| 1203 | if (pos + len > inode->i_size) | 1197 | if (pos + len > inode->i_size) |
| 1204 | vmtruncate(inode, inode->i_size); | 1198 | ext3_truncate(inode); |
| 1205 | } | 1199 | } |
| 1206 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) | 1200 | if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) |
| 1207 | goto retry; | 1201 | goto retry; |
| @@ -1287,7 +1281,7 @@ static int ext3_ordered_write_end(struct file *file, | |||
| 1287 | * There may be allocated blocks outside of i_size because | 1281 | * There may be allocated blocks outside of i_size because |
| 1288 | * we failed to copy some data. Prepare for truncate. | 1282 | * we failed to copy some data. Prepare for truncate. |
| 1289 | */ | 1283 | */ |
| 1290 | if (pos + len > inode->i_size) | 1284 | if (pos + len > inode->i_size && ext3_can_truncate(inode)) |
| 1291 | ext3_orphan_add(handle, inode); | 1285 | ext3_orphan_add(handle, inode); |
| 1292 | ret2 = ext3_journal_stop(handle); | 1286 | ret2 = ext3_journal_stop(handle); |
| 1293 | if (!ret) | 1287 | if (!ret) |
| @@ -1296,7 +1290,7 @@ static int ext3_ordered_write_end(struct file *file, | |||
| 1296 | page_cache_release(page); | 1290 | page_cache_release(page); |
| 1297 | 1291 | ||
| 1298 | if (pos + len > inode->i_size) | 1292 | if (pos + len > inode->i_size) |
| 1299 | vmtruncate(inode, inode->i_size); | 1293 | ext3_truncate(inode); |
| 1300 | return ret ? ret : copied; | 1294 | return ret ? ret : copied; |
| 1301 | } | 1295 | } |
| 1302 | 1296 | ||
| @@ -1315,14 +1309,14 @@ static int ext3_writeback_write_end(struct file *file, | |||
| 1315 | * There may be allocated blocks outside of i_size because | 1309 | * There may be allocated blocks outside of i_size because |
| 1316 | * we failed to copy some data. Prepare for truncate. | 1310 | * we failed to copy some data. Prepare for truncate. |
| 1317 | */ | 1311 | */ |
| 1318 | if (pos + len > inode->i_size) | 1312 | if (pos + len > inode->i_size && ext3_can_truncate(inode)) |
| 1319 | ext3_orphan_add(handle, inode); | 1313 | ext3_orphan_add(handle, inode); |
| 1320 | ret = ext3_journal_stop(handle); | 1314 | ret = ext3_journal_stop(handle); |
| 1321 | unlock_page(page); | 1315 | unlock_page(page); |
| 1322 | page_cache_release(page); | 1316 | page_cache_release(page); |
| 1323 | 1317 | ||
| 1324 | if (pos + len > inode->i_size) | 1318 | if (pos + len > inode->i_size) |
| 1325 | vmtruncate(inode, inode->i_size); | 1319 | ext3_truncate(inode); |
| 1326 | return ret ? ret : copied; | 1320 | return ret ? ret : copied; |
| 1327 | } | 1321 | } |
| 1328 | 1322 | ||
| @@ -1358,7 +1352,7 @@ static int ext3_journalled_write_end(struct file *file, | |||
| 1358 | * There may be allocated blocks outside of i_size because | 1352 | * There may be allocated blocks outside of i_size because |
| 1359 | * we failed to copy some data. Prepare for truncate. | 1353 | * we failed to copy some data. Prepare for truncate. |
| 1360 | */ | 1354 | */ |
| 1361 | if (pos + len > inode->i_size) | 1355 | if (pos + len > inode->i_size && ext3_can_truncate(inode)) |
| 1362 | ext3_orphan_add(handle, inode); | 1356 | ext3_orphan_add(handle, inode); |
| 1363 | EXT3_I(inode)->i_state |= EXT3_STATE_JDATA; | 1357 | EXT3_I(inode)->i_state |= EXT3_STATE_JDATA; |
| 1364 | if (inode->i_size > EXT3_I(inode)->i_disksize) { | 1358 | if (inode->i_size > EXT3_I(inode)->i_disksize) { |
| @@ -1375,7 +1369,7 @@ static int ext3_journalled_write_end(struct file *file, | |||
| 1375 | page_cache_release(page); | 1369 | page_cache_release(page); |
| 1376 | 1370 | ||
| 1377 | if (pos + len > inode->i_size) | 1371 | if (pos + len > inode->i_size) |
| 1378 | vmtruncate(inode, inode->i_size); | 1372 | ext3_truncate(inode); |
| 1379 | return ret ? ret : copied; | 1373 | return ret ? ret : copied; |
| 1380 | } | 1374 | } |
| 1381 | 1375 | ||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0ddf7e55abe1..9714db393efe 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -93,20 +93,20 @@ typedef unsigned int ext4_group_t; | |||
| 93 | struct ext4_allocation_request { | 93 | struct ext4_allocation_request { |
| 94 | /* target inode for block we're allocating */ | 94 | /* target inode for block we're allocating */ |
| 95 | struct inode *inode; | 95 | struct inode *inode; |
| 96 | /* how many blocks we want to allocate */ | ||
| 97 | unsigned int len; | ||
| 96 | /* logical block in target inode */ | 98 | /* logical block in target inode */ |
| 97 | ext4_lblk_t logical; | 99 | ext4_lblk_t logical; |
| 98 | /* phys. target (a hint) */ | ||
| 99 | ext4_fsblk_t goal; | ||
| 100 | /* the closest logical allocated block to the left */ | 100 | /* the closest logical allocated block to the left */ |
| 101 | ext4_lblk_t lleft; | 101 | ext4_lblk_t lleft; |
| 102 | /* phys. block for ^^^ */ | ||
| 103 | ext4_fsblk_t pleft; | ||
| 104 | /* the closest logical allocated block to the right */ | 102 | /* the closest logical allocated block to the right */ |
| 105 | ext4_lblk_t lright; | 103 | ext4_lblk_t lright; |
| 106 | /* phys. block for ^^^ */ | 104 | /* phys. target (a hint) */ |
| 105 | ext4_fsblk_t goal; | ||
| 106 | /* phys. block for the closest logical allocated block to the left */ | ||
| 107 | ext4_fsblk_t pleft; | ||
| 108 | /* phys. block for the closest logical allocated block to the right */ | ||
| 107 | ext4_fsblk_t pright; | 109 | ext4_fsblk_t pright; |
| 108 | /* how many blocks we want to allocate */ | ||
| 109 | unsigned int len; | ||
| 110 | /* flags. see above EXT4_MB_HINT_* */ | 110 | /* flags. see above EXT4_MB_HINT_* */ |
| 111 | unsigned int flags; | 111 | unsigned int flags; |
| 112 | }; | 112 | }; |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index ad13a84644e1..eb27fd0f2ee8 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
| @@ -43,6 +43,8 @@ int __ext4_journal_forget(const char *where, handle_t *handle, | |||
| 43 | ext4_journal_abort_handle(where, __func__, bh, | 43 | ext4_journal_abort_handle(where, __func__, bh, |
| 44 | handle, err); | 44 | handle, err); |
| 45 | } | 45 | } |
| 46 | else | ||
| 47 | brelse(bh); | ||
| 46 | return err; | 48 | return err; |
| 47 | } | 49 | } |
| 48 | 50 | ||
| @@ -57,6 +59,8 @@ int __ext4_journal_revoke(const char *where, handle_t *handle, | |||
| 57 | ext4_journal_abort_handle(where, __func__, bh, | 59 | ext4_journal_abort_handle(where, __func__, bh, |
| 58 | handle, err); | 60 | handle, err); |
| 59 | } | 61 | } |
| 62 | else | ||
| 63 | brelse(bh); | ||
| 60 | return err; | 64 | return err; |
| 61 | } | 65 | } |
| 62 | 66 | ||
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index be2f426f6805..139fb8cb87e4 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
| @@ -131,9 +131,11 @@ int __ext4_journal_get_undo_access(const char *where, handle_t *handle, | |||
| 131 | int __ext4_journal_get_write_access(const char *where, handle_t *handle, | 131 | int __ext4_journal_get_write_access(const char *where, handle_t *handle, |
| 132 | struct buffer_head *bh); | 132 | struct buffer_head *bh); |
| 133 | 133 | ||
| 134 | /* When called with an invalid handle, this will still do a put on the BH */ | ||
| 134 | int __ext4_journal_forget(const char *where, handle_t *handle, | 135 | int __ext4_journal_forget(const char *where, handle_t *handle, |
| 135 | struct buffer_head *bh); | 136 | struct buffer_head *bh); |
| 136 | 137 | ||
| 138 | /* When called with an invalid handle, this will still do a put on the BH */ | ||
| 137 | int __ext4_journal_revoke(const char *where, handle_t *handle, | 139 | int __ext4_journal_revoke(const char *where, handle_t *handle, |
| 138 | ext4_fsblk_t blocknr, struct buffer_head *bh); | 140 | ext4_fsblk_t blocknr, struct buffer_head *bh); |
| 139 | 141 | ||
| @@ -281,10 +283,10 @@ static inline int ext4_should_order_data(struct inode *inode) | |||
| 281 | 283 | ||
| 282 | static inline int ext4_should_writeback_data(struct inode *inode) | 284 | static inline int ext4_should_writeback_data(struct inode *inode) |
| 283 | { | 285 | { |
| 284 | if (EXT4_JOURNAL(inode) == NULL) | ||
| 285 | return 0; | ||
| 286 | if (!S_ISREG(inode->i_mode)) | 286 | if (!S_ISREG(inode->i_mode)) |
| 287 | return 0; | 287 | return 0; |
| 288 | if (EXT4_JOURNAL(inode) == NULL) | ||
| 289 | return 1; | ||
| 288 | if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL) | 290 | if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL) |
| 289 | return 0; | 291 | return 0; |
| 290 | if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 292 | if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 50322a09bd01..73ebfb44ad75 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -1977,6 +1977,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks, | |||
| 1977 | */ | 1977 | */ |
| 1978 | /* 1 bitmap, 1 block group descriptor */ | 1978 | /* 1 bitmap, 1 block group descriptor */ |
| 1979 | ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb); | 1979 | ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb); |
| 1980 | return ret; | ||
| 1980 | } | 1981 | } |
| 1981 | } | 1982 | } |
| 1982 | 1983 | ||
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 2f645732e3b7..29e6dc7299b8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -833,7 +833,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode, | |||
| 833 | if (!goal) | 833 | if (!goal) |
| 834 | goal = sbi->s_inode_goal; | 834 | goal = sbi->s_inode_goal; |
| 835 | 835 | ||
| 836 | if (goal && goal < le32_to_cpu(sbi->s_es->s_inodes_count)) { | 836 | if (goal && goal <= le32_to_cpu(sbi->s_es->s_inodes_count)) { |
| 837 | group = (goal - 1) / EXT4_INODES_PER_GROUP(sb); | 837 | group = (goal - 1) / EXT4_INODES_PER_GROUP(sb); |
| 838 | ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb); | 838 | ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb); |
| 839 | ret2 = 0; | 839 | ret2 = 0; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 60a26f3a6f8b..f9c642b22efa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -78,16 +78,14 @@ static int ext4_inode_is_fast_symlink(struct inode *inode) | |||
| 78 | * but there may still be a record of it in the journal, and that record | 78 | * but there may still be a record of it in the journal, and that record |
| 79 | * still needs to be revoked. | 79 | * still needs to be revoked. |
| 80 | * | 80 | * |
| 81 | * If the handle isn't valid we're not journaling so there's nothing to do. | 81 | * If the handle isn't valid we're not journaling, but we still need to |
| 82 | * call into ext4_journal_revoke() to put the buffer head. | ||
| 82 | */ | 83 | */ |
| 83 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, | 84 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, |
| 84 | struct buffer_head *bh, ext4_fsblk_t blocknr) | 85 | struct buffer_head *bh, ext4_fsblk_t blocknr) |
| 85 | { | 86 | { |
| 86 | int err; | 87 | int err; |
| 87 | 88 | ||
| 88 | if (!ext4_handle_valid(handle)) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | might_sleep(); | 89 | might_sleep(); |
| 92 | 90 | ||
| 93 | BUFFER_TRACE(bh, "enter"); | 91 | BUFFER_TRACE(bh, "enter"); |
| @@ -1513,14 +1511,14 @@ retry: | |||
| 1513 | * Add inode to orphan list in case we crash before | 1511 | * Add inode to orphan list in case we crash before |
| 1514 | * truncate finishes | 1512 | * truncate finishes |
| 1515 | */ | 1513 | */ |
| 1516 | if (pos + len > inode->i_size) | 1514 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) |
| 1517 | ext4_orphan_add(handle, inode); | 1515 | ext4_orphan_add(handle, inode); |
| 1518 | 1516 | ||
| 1519 | ext4_journal_stop(handle); | 1517 | ext4_journal_stop(handle); |
| 1520 | if (pos + len > inode->i_size) { | 1518 | if (pos + len > inode->i_size) { |
| 1521 | vmtruncate(inode, inode->i_size); | 1519 | ext4_truncate(inode); |
| 1522 | /* | 1520 | /* |
| 1523 | * If vmtruncate failed early the inode might | 1521 | * If truncate failed early the inode might |
| 1524 | * still be on the orphan list; we need to | 1522 | * still be on the orphan list; we need to |
| 1525 | * make sure the inode is removed from the | 1523 | * make sure the inode is removed from the |
| 1526 | * orphan list in that case. | 1524 | * orphan list in that case. |
| @@ -1614,7 +1612,7 @@ static int ext4_ordered_write_end(struct file *file, | |||
| 1614 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, | 1612 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, |
| 1615 | page, fsdata); | 1613 | page, fsdata); |
| 1616 | copied = ret2; | 1614 | copied = ret2; |
| 1617 | if (pos + len > inode->i_size) | 1615 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) |
| 1618 | /* if we have allocated more blocks and copied | 1616 | /* if we have allocated more blocks and copied |
| 1619 | * less. We will have blocks allocated outside | 1617 | * less. We will have blocks allocated outside |
| 1620 | * inode->i_size. So truncate them | 1618 | * inode->i_size. So truncate them |
| @@ -1628,9 +1626,9 @@ static int ext4_ordered_write_end(struct file *file, | |||
| 1628 | ret = ret2; | 1626 | ret = ret2; |
| 1629 | 1627 | ||
| 1630 | if (pos + len > inode->i_size) { | 1628 | if (pos + len > inode->i_size) { |
| 1631 | vmtruncate(inode, inode->i_size); | 1629 | ext4_truncate(inode); |
| 1632 | /* | 1630 | /* |
| 1633 | * If vmtruncate failed early the inode might still be | 1631 | * If truncate failed early the inode might still be |
| 1634 | * on the orphan list; we need to make sure the inode | 1632 | * on the orphan list; we need to make sure the inode |
| 1635 | * is removed from the orphan list in that case. | 1633 | * is removed from the orphan list in that case. |
| 1636 | */ | 1634 | */ |
| @@ -1655,7 +1653,7 @@ static int ext4_writeback_write_end(struct file *file, | |||
| 1655 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, | 1653 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, |
| 1656 | page, fsdata); | 1654 | page, fsdata); |
| 1657 | copied = ret2; | 1655 | copied = ret2; |
| 1658 | if (pos + len > inode->i_size) | 1656 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) |
| 1659 | /* if we have allocated more blocks and copied | 1657 | /* if we have allocated more blocks and copied |
| 1660 | * less. We will have blocks allocated outside | 1658 | * less. We will have blocks allocated outside |
| 1661 | * inode->i_size. So truncate them | 1659 | * inode->i_size. So truncate them |
| @@ -1670,9 +1668,9 @@ static int ext4_writeback_write_end(struct file *file, | |||
| 1670 | ret = ret2; | 1668 | ret = ret2; |
| 1671 | 1669 | ||
| 1672 | if (pos + len > inode->i_size) { | 1670 | if (pos + len > inode->i_size) { |
| 1673 | vmtruncate(inode, inode->i_size); | 1671 | ext4_truncate(inode); |
| 1674 | /* | 1672 | /* |
| 1675 | * If vmtruncate failed early the inode might still be | 1673 | * If truncate failed early the inode might still be |
| 1676 | * on the orphan list; we need to make sure the inode | 1674 | * on the orphan list; we need to make sure the inode |
| 1677 | * is removed from the orphan list in that case. | 1675 | * is removed from the orphan list in that case. |
| 1678 | */ | 1676 | */ |
| @@ -1722,7 +1720,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1722 | 1720 | ||
| 1723 | unlock_page(page); | 1721 | unlock_page(page); |
| 1724 | page_cache_release(page); | 1722 | page_cache_release(page); |
| 1725 | if (pos + len > inode->i_size) | 1723 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) |
| 1726 | /* if we have allocated more blocks and copied | 1724 | /* if we have allocated more blocks and copied |
| 1727 | * less. We will have blocks allocated outside | 1725 | * less. We will have blocks allocated outside |
| 1728 | * inode->i_size. So truncate them | 1726 | * inode->i_size. So truncate them |
| @@ -1733,9 +1731,9 @@ static int ext4_journalled_write_end(struct file *file, | |||
| 1733 | if (!ret) | 1731 | if (!ret) |
| 1734 | ret = ret2; | 1732 | ret = ret2; |
| 1735 | if (pos + len > inode->i_size) { | 1733 | if (pos + len > inode->i_size) { |
| 1736 | vmtruncate(inode, inode->i_size); | 1734 | ext4_truncate(inode); |
| 1737 | /* | 1735 | /* |
| 1738 | * If vmtruncate failed early the inode might still be | 1736 | * If truncate failed early the inode might still be |
| 1739 | * on the orphan list; we need to make sure the inode | 1737 | * on the orphan list; we need to make sure the inode |
| 1740 | * is removed from the orphan list in that case. | 1738 | * is removed from the orphan list in that case. |
| 1741 | */ | 1739 | */ |
| @@ -2305,15 +2303,9 @@ flush_it: | |||
| 2305 | return; | 2303 | return; |
| 2306 | } | 2304 | } |
| 2307 | 2305 | ||
| 2308 | static int ext4_bh_unmapped_or_delay(handle_t *handle, struct buffer_head *bh) | 2306 | static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh) |
| 2309 | { | 2307 | { |
| 2310 | /* | 2308 | return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh); |
| 2311 | * unmapped buffer is possible for holes. | ||
| 2312 | * delay buffer is possible with delayed allocation. | ||
| 2313 | * We also need to consider unwritten buffer as unmapped. | ||
| 2314 | */ | ||
| 2315 | return (!buffer_mapped(bh) || buffer_delay(bh) || | ||
| 2316 | buffer_unwritten(bh)) && buffer_dirty(bh); | ||
| 2317 | } | 2309 | } |
| 2318 | 2310 | ||
| 2319 | /* | 2311 | /* |
| @@ -2398,9 +2390,9 @@ static int __mpage_da_writepage(struct page *page, | |||
| 2398 | * We need to try to allocate | 2390 | * We need to try to allocate |
| 2399 | * unmapped blocks in the same page. | 2391 | * unmapped blocks in the same page. |
| 2400 | * Otherwise we won't make progress | 2392 | * Otherwise we won't make progress |
| 2401 | * with the page in ext4_da_writepage | 2393 | * with the page in ext4_writepage |
| 2402 | */ | 2394 | */ |
| 2403 | if (ext4_bh_unmapped_or_delay(NULL, bh)) { | 2395 | if (ext4_bh_delay_or_unwritten(NULL, bh)) { |
| 2404 | mpage_add_bh_to_extent(mpd, logical, | 2396 | mpage_add_bh_to_extent(mpd, logical, |
| 2405 | bh->b_size, | 2397 | bh->b_size, |
| 2406 | bh->b_state); | 2398 | bh->b_state); |
| @@ -2517,7 +2509,6 @@ static int noalloc_get_block_write(struct inode *inode, sector_t iblock, | |||
| 2517 | * so call get_block_wrap with create = 0 | 2509 | * so call get_block_wrap with create = 0 |
| 2518 | */ | 2510 | */ |
| 2519 | ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0); | 2511 | ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0); |
| 2520 | BUG_ON(create && ret == 0); | ||
| 2521 | if (ret > 0) { | 2512 | if (ret > 0) { |
| 2522 | bh_result->b_size = (ret << inode->i_blkbits); | 2513 | bh_result->b_size = (ret << inode->i_blkbits); |
| 2523 | ret = 0; | 2514 | ret = 0; |
| @@ -2525,15 +2516,102 @@ static int noalloc_get_block_write(struct inode *inode, sector_t iblock, | |||
| 2525 | return ret; | 2516 | return ret; |
| 2526 | } | 2517 | } |
| 2527 | 2518 | ||
| 2519 | static int bget_one(handle_t *handle, struct buffer_head *bh) | ||
| 2520 | { | ||
| 2521 | get_bh(bh); | ||
| 2522 | return 0; | ||
| 2523 | } | ||
| 2524 | |||
| 2525 | static int bput_one(handle_t *handle, struct buffer_head *bh) | ||
| 2526 | { | ||
| 2527 | put_bh(bh); | ||
| 2528 | return 0; | ||
| 2529 | } | ||
| 2530 | |||
| 2531 | static int __ext4_journalled_writepage(struct page *page, | ||
| 2532 | struct writeback_control *wbc, | ||
| 2533 | unsigned int len) | ||
| 2534 | { | ||
| 2535 | struct address_space *mapping = page->mapping; | ||
| 2536 | struct inode *inode = mapping->host; | ||
| 2537 | struct buffer_head *page_bufs; | ||
| 2538 | handle_t *handle = NULL; | ||
| 2539 | int ret = 0; | ||
| 2540 | int err; | ||
| 2541 | |||
| 2542 | page_bufs = page_buffers(page); | ||
| 2543 | BUG_ON(!page_bufs); | ||
| 2544 | walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); | ||
| 2545 | /* As soon as we unlock the page, it can go away, but we have | ||
| 2546 | * references to buffers so we are safe */ | ||
| 2547 | unlock_page(page); | ||
| 2548 | |||
| 2549 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); | ||
| 2550 | if (IS_ERR(handle)) { | ||
| 2551 | ret = PTR_ERR(handle); | ||
| 2552 | goto out; | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, | ||
| 2556 | do_journal_get_write_access); | ||
| 2557 | |||
| 2558 | err = walk_page_buffers(handle, page_bufs, 0, len, NULL, | ||
| 2559 | write_end_fn); | ||
| 2560 | if (ret == 0) | ||
| 2561 | ret = err; | ||
| 2562 | err = ext4_journal_stop(handle); | ||
| 2563 | if (!ret) | ||
| 2564 | ret = err; | ||
| 2565 | |||
| 2566 | walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one); | ||
| 2567 | EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; | ||
| 2568 | out: | ||
| 2569 | return ret; | ||
| 2570 | } | ||
| 2571 | |||
| 2528 | /* | 2572 | /* |
| 2573 | * Note that we don't need to start a transaction unless we're journaling data | ||
| 2574 | * because we should have holes filled from ext4_page_mkwrite(). We even don't | ||
| 2575 | * need to file the inode to the transaction's list in ordered mode because if | ||
| 2576 | * we are writing back data added by write(), the inode is already there and if | ||
| 2577 | * we are writing back data modified via mmap(), noone guarantees in which | ||
| 2578 | * transaction the data will hit the disk. In case we are journaling data, we | ||
| 2579 | * cannot start transaction directly because transaction start ranks above page | ||
| 2580 | * lock so we have to do some magic. | ||
| 2581 | * | ||
| 2529 | * This function can get called via... | 2582 | * This function can get called via... |
| 2530 | * - ext4_da_writepages after taking page lock (have journal handle) | 2583 | * - ext4_da_writepages after taking page lock (have journal handle) |
| 2531 | * - journal_submit_inode_data_buffers (no journal handle) | 2584 | * - journal_submit_inode_data_buffers (no journal handle) |
| 2532 | * - shrink_page_list via pdflush (no journal handle) | 2585 | * - shrink_page_list via pdflush (no journal handle) |
| 2533 | * - grab_page_cache when doing write_begin (have journal handle) | 2586 | * - grab_page_cache when doing write_begin (have journal handle) |
| 2587 | * | ||
| 2588 | * We don't do any block allocation in this function. If we have page with | ||
| 2589 | * multiple blocks we need to write those buffer_heads that are mapped. This | ||
| 2590 | * is important for mmaped based write. So if we do with blocksize 1K | ||
| 2591 | * truncate(f, 1024); | ||
| 2592 | * a = mmap(f, 0, 4096); | ||
| 2593 | * a[0] = 'a'; | ||
| 2594 | * truncate(f, 4096); | ||
| 2595 | * we have in the page first buffer_head mapped via page_mkwrite call back | ||
| 2596 | * but other bufer_heads would be unmapped but dirty(dirty done via the | ||
| 2597 | * do_wp_page). So writepage should write the first block. If we modify | ||
| 2598 | * the mmap area beyond 1024 we will again get a page_fault and the | ||
| 2599 | * page_mkwrite callback will do the block allocation and mark the | ||
| 2600 | * buffer_heads mapped. | ||
| 2601 | * | ||
| 2602 | * We redirty the page if we have any buffer_heads that is either delay or | ||
| 2603 | * unwritten in the page. | ||
| 2604 | * | ||
| 2605 | * We can get recursively called as show below. | ||
| 2606 | * | ||
| 2607 | * ext4_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() -> | ||
| 2608 | * ext4_writepage() | ||
| 2609 | * | ||
| 2610 | * But since we don't do any block allocation we should not deadlock. | ||
| 2611 | * Page also have the dirty flag cleared so we don't get recurive page_lock. | ||
| 2534 | */ | 2612 | */ |
| 2535 | static int ext4_da_writepage(struct page *page, | 2613 | static int ext4_writepage(struct page *page, |
| 2536 | struct writeback_control *wbc) | 2614 | struct writeback_control *wbc) |
| 2537 | { | 2615 | { |
| 2538 | int ret = 0; | 2616 | int ret = 0; |
| 2539 | loff_t size; | 2617 | loff_t size; |
| @@ -2541,7 +2619,7 @@ static int ext4_da_writepage(struct page *page, | |||
| 2541 | struct buffer_head *page_bufs; | 2619 | struct buffer_head *page_bufs; |
| 2542 | struct inode *inode = page->mapping->host; | 2620 | struct inode *inode = page->mapping->host; |
| 2543 | 2621 | ||
| 2544 | trace_ext4_da_writepage(inode, page); | 2622 | trace_ext4_writepage(inode, page); |
| 2545 | size = i_size_read(inode); | 2623 | size = i_size_read(inode); |
| 2546 | if (page->index == size >> PAGE_CACHE_SHIFT) | 2624 | if (page->index == size >> PAGE_CACHE_SHIFT) |
| 2547 | len = size & ~PAGE_CACHE_MASK; | 2625 | len = size & ~PAGE_CACHE_MASK; |
| @@ -2551,7 +2629,7 @@ static int ext4_da_writepage(struct page *page, | |||
| 2551 | if (page_has_buffers(page)) { | 2629 | if (page_has_buffers(page)) { |
| 2552 | page_bufs = page_buffers(page); | 2630 | page_bufs = page_buffers(page); |
| 2553 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | 2631 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, |
| 2554 | ext4_bh_unmapped_or_delay)) { | 2632 | ext4_bh_delay_or_unwritten)) { |
| 2555 | /* | 2633 | /* |
| 2556 | * We don't want to do block allocation | 2634 | * We don't want to do block allocation |
| 2557 | * So redirty the page and return | 2635 | * So redirty the page and return |
| @@ -2578,13 +2656,13 @@ static int ext4_da_writepage(struct page *page, | |||
| 2578 | * all are mapped and non delay. We don't want to | 2656 | * all are mapped and non delay. We don't want to |
| 2579 | * do block allocation here. | 2657 | * do block allocation here. |
| 2580 | */ | 2658 | */ |
| 2581 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, | 2659 | ret = block_prepare_write(page, 0, len, |
| 2582 | noalloc_get_block_write); | 2660 | noalloc_get_block_write); |
| 2583 | if (!ret) { | 2661 | if (!ret) { |
| 2584 | page_bufs = page_buffers(page); | 2662 | page_bufs = page_buffers(page); |
| 2585 | /* check whether all are mapped and non delay */ | 2663 | /* check whether all are mapped and non delay */ |
| 2586 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, | 2664 | if (walk_page_buffers(NULL, page_bufs, 0, len, NULL, |
| 2587 | ext4_bh_unmapped_or_delay)) { | 2665 | ext4_bh_delay_or_unwritten)) { |
| 2588 | redirty_page_for_writepage(wbc, page); | 2666 | redirty_page_for_writepage(wbc, page); |
| 2589 | unlock_page(page); | 2667 | unlock_page(page); |
| 2590 | return 0; | 2668 | return 0; |
| @@ -2600,7 +2678,16 @@ static int ext4_da_writepage(struct page *page, | |||
| 2600 | return 0; | 2678 | return 0; |
| 2601 | } | 2679 | } |
| 2602 | /* now mark the buffer_heads as dirty and uptodate */ | 2680 | /* now mark the buffer_heads as dirty and uptodate */ |
| 2603 | block_commit_write(page, 0, PAGE_CACHE_SIZE); | 2681 | block_commit_write(page, 0, len); |
| 2682 | } | ||
| 2683 | |||
| 2684 | if (PageChecked(page) && ext4_should_journal_data(inode)) { | ||
| 2685 | /* | ||
| 2686 | * It's mmapped pagecache. Add buffers and journal it. There | ||
| 2687 | * doesn't seem much point in redirtying the page here. | ||
| 2688 | */ | ||
| 2689 | ClearPageChecked(page); | ||
| 2690 | return __ext4_journalled_writepage(page, wbc, len); | ||
| 2604 | } | 2691 | } |
| 2605 | 2692 | ||
| 2606 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 2693 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) |
| @@ -2907,7 +2994,7 @@ retry: | |||
| 2907 | * i_size_read because we hold i_mutex. | 2994 | * i_size_read because we hold i_mutex. |
| 2908 | */ | 2995 | */ |
| 2909 | if (pos + len > inode->i_size) | 2996 | if (pos + len > inode->i_size) |
| 2910 | vmtruncate(inode, inode->i_size); | 2997 | ext4_truncate(inode); |
| 2911 | } | 2998 | } |
| 2912 | 2999 | ||
| 2913 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 3000 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
| @@ -3130,222 +3217,6 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) | |||
| 3130 | return generic_block_bmap(mapping, block, ext4_get_block); | 3217 | return generic_block_bmap(mapping, block, ext4_get_block); |
| 3131 | } | 3218 | } |
| 3132 | 3219 | ||
| 3133 | static int bget_one(handle_t *handle, struct buffer_head *bh) | ||
| 3134 | { | ||
| 3135 | get_bh(bh); | ||
| 3136 | return 0; | ||
| 3137 | } | ||
| 3138 | |||
| 3139 | static int bput_one(handle_t *handle, struct buffer_head *bh) | ||
| 3140 | { | ||
| 3141 | put_bh(bh); | ||
| 3142 | return 0; | ||
| 3143 | } | ||
| 3144 | |||
| 3145 | /* | ||
| 3146 | * Note that we don't need to start a transaction unless we're journaling data | ||
| 3147 | * because we should have holes filled from ext4_page_mkwrite(). We even don't | ||
| 3148 | * need to file the inode to the transaction's list in ordered mode because if | ||
| 3149 | * we are writing back data added by write(), the inode is already there and if | ||
| 3150 | * we are writing back data modified via mmap(), noone guarantees in which | ||
| 3151 | * transaction the data will hit the disk. In case we are journaling data, we | ||
| 3152 | * cannot start transaction directly because transaction start ranks above page | ||
| 3153 | * lock so we have to do some magic. | ||
| 3154 | * | ||
| 3155 | * In all journaling modes block_write_full_page() will start the I/O. | ||
| 3156 | * | ||
| 3157 | * Problem: | ||
| 3158 | * | ||
| 3159 | * ext4_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() -> | ||
| 3160 | * ext4_writepage() | ||
| 3161 | * | ||
| 3162 | * Similar for: | ||
| 3163 | * | ||
| 3164 | * ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ... | ||
| 3165 | * | ||
| 3166 | * Same applies to ext4_get_block(). We will deadlock on various things like | ||
| 3167 | * lock_journal and i_data_sem | ||
| 3168 | * | ||
| 3169 | * Setting PF_MEMALLOC here doesn't work - too many internal memory | ||
| 3170 | * allocations fail. | ||
| 3171 | * | ||
| 3172 | * 16May01: If we're reentered then journal_current_handle() will be | ||
| 3173 | * non-zero. We simply *return*. | ||
| 3174 | * | ||
| 3175 | * 1 July 2001: @@@ FIXME: | ||
| 3176 | * In journalled data mode, a data buffer may be metadata against the | ||
| 3177 | * current transaction. But the same file is part of a shared mapping | ||
| 3178 | * and someone does a writepage() on it. | ||
| 3179 | * | ||
| 3180 | * We will move the buffer onto the async_data list, but *after* it has | ||
| 3181 | * been dirtied. So there's a small window where we have dirty data on | ||
| 3182 | * BJ_Metadata. | ||
| 3183 | * | ||
| 3184 | * Note that this only applies to the last partial page in the file. The | ||
| 3185 | * bit which block_write_full_page() uses prepare/commit for. (That's | ||
| 3186 | * broken code anyway: it's wrong for msync()). | ||
| 3187 | * | ||
| 3188 | * It's a rare case: affects the final partial page, for journalled data | ||
| 3189 | * where the file is subject to bith write() and writepage() in the same | ||
| 3190 | * transction. To fix it we'll need a custom block_write_full_page(). | ||
| 3191 | * We'll probably need that anyway for journalling writepage() output. | ||
| 3192 | * | ||
| 3193 | * We don't honour synchronous mounts for writepage(). That would be | ||
| 3194 | * disastrous. Any write() or metadata operation will sync the fs for | ||
| 3195 | * us. | ||
| 3196 | * | ||
| 3197 | */ | ||
| 3198 | static int __ext4_normal_writepage(struct page *page, | ||
| 3199 | struct writeback_control *wbc) | ||
| 3200 | { | ||
| 3201 | struct inode *inode = page->mapping->host; | ||
| 3202 | |||
| 3203 | if (test_opt(inode->i_sb, NOBH)) | ||
| 3204 | return nobh_writepage(page, noalloc_get_block_write, wbc); | ||
| 3205 | else | ||
| 3206 | return block_write_full_page(page, noalloc_get_block_write, | ||
| 3207 | wbc); | ||
| 3208 | } | ||
| 3209 | |||
| 3210 | static int ext4_normal_writepage(struct page *page, | ||
| 3211 | struct writeback_control *wbc) | ||
| 3212 | { | ||
| 3213 | struct inode *inode = page->mapping->host; | ||
| 3214 | loff_t size = i_size_read(inode); | ||
| 3215 | loff_t len; | ||
| 3216 | |||
| 3217 | trace_ext4_normal_writepage(inode, page); | ||
| 3218 | J_ASSERT(PageLocked(page)); | ||
| 3219 | if (page->index == size >> PAGE_CACHE_SHIFT) | ||
| 3220 | len = size & ~PAGE_CACHE_MASK; | ||
| 3221 | else | ||
| 3222 | len = PAGE_CACHE_SIZE; | ||
| 3223 | |||
| 3224 | if (page_has_buffers(page)) { | ||
| 3225 | /* if page has buffers it should all be mapped | ||
| 3226 | * and allocated. If there are not buffers attached | ||
| 3227 | * to the page we know the page is dirty but it lost | ||
| 3228 | * buffers. That means that at some moment in time | ||
| 3229 | * after write_begin() / write_end() has been called | ||
| 3230 | * all buffers have been clean and thus they must have been | ||
| 3231 | * written at least once. So they are all mapped and we can | ||
| 3232 | * happily proceed with mapping them and writing the page. | ||
| 3233 | */ | ||
| 3234 | BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, | ||
| 3235 | ext4_bh_unmapped_or_delay)); | ||
| 3236 | } | ||
| 3237 | |||
| 3238 | if (!ext4_journal_current_handle()) | ||
| 3239 | return __ext4_normal_writepage(page, wbc); | ||
| 3240 | |||
| 3241 | redirty_page_for_writepage(wbc, page); | ||
| 3242 | unlock_page(page); | ||
| 3243 | return 0; | ||
| 3244 | } | ||
| 3245 | |||
| 3246 | static int __ext4_journalled_writepage(struct page *page, | ||
| 3247 | struct writeback_control *wbc) | ||
| 3248 | { | ||
| 3249 | struct address_space *mapping = page->mapping; | ||
| 3250 | struct inode *inode = mapping->host; | ||
| 3251 | struct buffer_head *page_bufs; | ||
| 3252 | handle_t *handle = NULL; | ||
| 3253 | int ret = 0; | ||
| 3254 | int err; | ||
| 3255 | |||
| 3256 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, | ||
| 3257 | noalloc_get_block_write); | ||
| 3258 | if (ret != 0) | ||
| 3259 | goto out_unlock; | ||
| 3260 | |||
| 3261 | page_bufs = page_buffers(page); | ||
| 3262 | walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL, | ||
| 3263 | bget_one); | ||
| 3264 | /* As soon as we unlock the page, it can go away, but we have | ||
| 3265 | * references to buffers so we are safe */ | ||
| 3266 | unlock_page(page); | ||
| 3267 | |||
| 3268 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); | ||
| 3269 | if (IS_ERR(handle)) { | ||
| 3270 | ret = PTR_ERR(handle); | ||
| 3271 | goto out; | ||
| 3272 | } | ||
| 3273 | |||
| 3274 | ret = walk_page_buffers(handle, page_bufs, 0, | ||
| 3275 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); | ||
| 3276 | |||
| 3277 | err = walk_page_buffers(handle, page_bufs, 0, | ||
| 3278 | PAGE_CACHE_SIZE, NULL, write_end_fn); | ||
| 3279 | if (ret == 0) | ||
| 3280 | ret = err; | ||
| 3281 | err = ext4_journal_stop(handle); | ||
| 3282 | if (!ret) | ||
| 3283 | ret = err; | ||
| 3284 | |||
| 3285 | walk_page_buffers(handle, page_bufs, 0, | ||
| 3286 | PAGE_CACHE_SIZE, NULL, bput_one); | ||
| 3287 | EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; | ||
| 3288 | goto out; | ||
| 3289 | |||
| 3290 | out_unlock: | ||
| 3291 | unlock_page(page); | ||
| 3292 | out: | ||
| 3293 | return ret; | ||
| 3294 | } | ||
| 3295 | |||
| 3296 | static int ext4_journalled_writepage(struct page *page, | ||
| 3297 | struct writeback_control *wbc) | ||
| 3298 | { | ||
| 3299 | struct inode *inode = page->mapping->host; | ||
| 3300 | loff_t size = i_size_read(inode); | ||
| 3301 | loff_t len; | ||
| 3302 | |||
| 3303 | trace_ext4_journalled_writepage(inode, page); | ||
| 3304 | J_ASSERT(PageLocked(page)); | ||
| 3305 | if (page->index == size >> PAGE_CACHE_SHIFT) | ||
| 3306 | len = size & ~PAGE_CACHE_MASK; | ||
| 3307 | else | ||
| 3308 | len = PAGE_CACHE_SIZE; | ||
| 3309 | |||
| 3310 | if (page_has_buffers(page)) { | ||
| 3311 | /* if page has buffers it should all be mapped | ||
| 3312 | * and allocated. If there are not buffers attached | ||
| 3313 | * to the page we know the page is dirty but it lost | ||
| 3314 | * buffers. That means that at some moment in time | ||
| 3315 | * after write_begin() / write_end() has been called | ||
| 3316 | * all buffers have been clean and thus they must have been | ||
| 3317 | * written at least once. So they are all mapped and we can | ||
| 3318 | * happily proceed with mapping them and writing the page. | ||
| 3319 | */ | ||
| 3320 | BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, | ||
| 3321 | ext4_bh_unmapped_or_delay)); | ||
| 3322 | } | ||
| 3323 | |||
| 3324 | if (ext4_journal_current_handle()) | ||
| 3325 | goto no_write; | ||
| 3326 | |||
| 3327 | if (PageChecked(page)) { | ||
| 3328 | /* | ||
| 3329 | * It's mmapped pagecache. Add buffers and journal it. There | ||
| 3330 | * doesn't seem much point in redirtying the page here. | ||
| 3331 | */ | ||
| 3332 | ClearPageChecked(page); | ||
| 3333 | return __ext4_journalled_writepage(page, wbc); | ||
| 3334 | } else { | ||
| 3335 | /* | ||
| 3336 | * It may be a page full of checkpoint-mode buffers. We don't | ||
| 3337 | * really know unless we go poke around in the buffer_heads. | ||
| 3338 | * But block_write_full_page will do the right thing. | ||
| 3339 | */ | ||
| 3340 | return block_write_full_page(page, noalloc_get_block_write, | ||
| 3341 | wbc); | ||
| 3342 | } | ||
| 3343 | no_write: | ||
| 3344 | redirty_page_for_writepage(wbc, page); | ||
| 3345 | unlock_page(page); | ||
| 3346 | return 0; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | static int ext4_readpage(struct file *file, struct page *page) | 3220 | static int ext4_readpage(struct file *file, struct page *page) |
| 3350 | { | 3221 | { |
| 3351 | return mpage_readpage(page, ext4_get_block); | 3222 | return mpage_readpage(page, ext4_get_block); |
| @@ -3492,7 +3363,7 @@ static int ext4_journalled_set_page_dirty(struct page *page) | |||
| 3492 | static const struct address_space_operations ext4_ordered_aops = { | 3363 | static const struct address_space_operations ext4_ordered_aops = { |
| 3493 | .readpage = ext4_readpage, | 3364 | .readpage = ext4_readpage, |
| 3494 | .readpages = ext4_readpages, | 3365 | .readpages = ext4_readpages, |
| 3495 | .writepage = ext4_normal_writepage, | 3366 | .writepage = ext4_writepage, |
| 3496 | .sync_page = block_sync_page, | 3367 | .sync_page = block_sync_page, |
| 3497 | .write_begin = ext4_write_begin, | 3368 | .write_begin = ext4_write_begin, |
| 3498 | .write_end = ext4_ordered_write_end, | 3369 | .write_end = ext4_ordered_write_end, |
| @@ -3507,7 +3378,7 @@ static const struct address_space_operations ext4_ordered_aops = { | |||
| 3507 | static const struct address_space_operations ext4_writeback_aops = { | 3378 | static const struct address_space_operations ext4_writeback_aops = { |
| 3508 | .readpage = ext4_readpage, | 3379 | .readpage = ext4_readpage, |
| 3509 | .readpages = ext4_readpages, | 3380 | .readpages = ext4_readpages, |
| 3510 | .writepage = ext4_normal_writepage, | 3381 | .writepage = ext4_writepage, |
| 3511 | .sync_page = block_sync_page, | 3382 | .sync_page = block_sync_page, |
| 3512 | .write_begin = ext4_write_begin, | 3383 | .write_begin = ext4_write_begin, |
| 3513 | .write_end = ext4_writeback_write_end, | 3384 | .write_end = ext4_writeback_write_end, |
| @@ -3522,7 +3393,7 @@ static const struct address_space_operations ext4_writeback_aops = { | |||
| 3522 | static const struct address_space_operations ext4_journalled_aops = { | 3393 | static const struct address_space_operations ext4_journalled_aops = { |
| 3523 | .readpage = ext4_readpage, | 3394 | .readpage = ext4_readpage, |
| 3524 | .readpages = ext4_readpages, | 3395 | .readpages = ext4_readpages, |
| 3525 | .writepage = ext4_journalled_writepage, | 3396 | .writepage = ext4_writepage, |
| 3526 | .sync_page = block_sync_page, | 3397 | .sync_page = block_sync_page, |
| 3527 | .write_begin = ext4_write_begin, | 3398 | .write_begin = ext4_write_begin, |
| 3528 | .write_end = ext4_journalled_write_end, | 3399 | .write_end = ext4_journalled_write_end, |
| @@ -3536,7 +3407,7 @@ static const struct address_space_operations ext4_journalled_aops = { | |||
| 3536 | static const struct address_space_operations ext4_da_aops = { | 3407 | static const struct address_space_operations ext4_da_aops = { |
| 3537 | .readpage = ext4_readpage, | 3408 | .readpage = ext4_readpage, |
| 3538 | .readpages = ext4_readpages, | 3409 | .readpages = ext4_readpages, |
| 3539 | .writepage = ext4_da_writepage, | 3410 | .writepage = ext4_writepage, |
| 3540 | .writepages = ext4_da_writepages, | 3411 | .writepages = ext4_da_writepages, |
| 3541 | .sync_page = block_sync_page, | 3412 | .sync_page = block_sync_page, |
| 3542 | .write_begin = ext4_da_write_begin, | 3413 | .write_begin = ext4_da_write_begin, |
| @@ -3583,7 +3454,8 @@ int ext4_block_truncate_page(handle_t *handle, | |||
| 3583 | struct page *page; | 3454 | struct page *page; |
| 3584 | int err = 0; | 3455 | int err = 0; |
| 3585 | 3456 | ||
| 3586 | page = grab_cache_page(mapping, from >> PAGE_CACHE_SHIFT); | 3457 | page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT, |
| 3458 | mapping_gfp_mask(mapping) & ~__GFP_FS); | ||
| 3587 | if (!page) | 3459 | if (!page) |
| 3588 | return -EINVAL; | 3460 | return -EINVAL; |
| 3589 | 3461 | ||
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index bb415408fdb6..7050a9cd04a4 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/capability.h> | 12 | #include <linux/capability.h> |
| 13 | #include <linux/time.h> | 13 | #include <linux/time.h> |
| 14 | #include <linux/compat.h> | 14 | #include <linux/compat.h> |
| 15 | #include <linux/smp_lock.h> | ||
| 16 | #include <linux/mount.h> | 15 | #include <linux/mount.h> |
| 17 | #include <linux/file.h> | 16 | #include <linux/file.h> |
| 18 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
| @@ -192,7 +191,7 @@ setversion_out: | |||
| 192 | case EXT4_IOC_GROUP_EXTEND: { | 191 | case EXT4_IOC_GROUP_EXTEND: { |
| 193 | ext4_fsblk_t n_blocks_count; | 192 | ext4_fsblk_t n_blocks_count; |
| 194 | struct super_block *sb = inode->i_sb; | 193 | struct super_block *sb = inode->i_sb; |
| 195 | int err, err2; | 194 | int err, err2=0; |
| 196 | 195 | ||
| 197 | if (!capable(CAP_SYS_RESOURCE)) | 196 | if (!capable(CAP_SYS_RESOURCE)) |
| 198 | return -EPERM; | 197 | return -EPERM; |
| @@ -205,9 +204,11 @@ setversion_out: | |||
| 205 | return err; | 204 | return err; |
| 206 | 205 | ||
| 207 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); | 206 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); |
| 208 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 207 | if (EXT4_SB(sb)->s_journal) { |
| 209 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 208 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
| 210 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 209 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
| 210 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | ||
| 211 | } | ||
| 211 | if (err == 0) | 212 | if (err == 0) |
| 212 | err = err2; | 213 | err = err2; |
| 213 | mnt_drop_write(filp->f_path.mnt); | 214 | mnt_drop_write(filp->f_path.mnt); |
| @@ -252,7 +253,7 @@ setversion_out: | |||
| 252 | case EXT4_IOC_GROUP_ADD: { | 253 | case EXT4_IOC_GROUP_ADD: { |
| 253 | struct ext4_new_group_data input; | 254 | struct ext4_new_group_data input; |
| 254 | struct super_block *sb = inode->i_sb; | 255 | struct super_block *sb = inode->i_sb; |
| 255 | int err, err2; | 256 | int err, err2=0; |
| 256 | 257 | ||
| 257 | if (!capable(CAP_SYS_RESOURCE)) | 258 | if (!capable(CAP_SYS_RESOURCE)) |
| 258 | return -EPERM; | 259 | return -EPERM; |
| @@ -266,9 +267,11 @@ setversion_out: | |||
| 266 | return err; | 267 | return err; |
| 267 | 268 | ||
| 268 | err = ext4_group_add(sb, &input); | 269 | err = ext4_group_add(sb, &input); |
| 269 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 270 | if (EXT4_SB(sb)->s_journal) { |
| 270 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 271 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
| 271 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 272 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
| 273 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | ||
| 274 | } | ||
| 272 | if (err == 0) | 275 | if (err == 0) |
| 273 | err = err2; | 276 | err = err2; |
| 274 | mnt_drop_write(filp->f_path.mnt); | 277 | mnt_drop_write(filp->f_path.mnt); |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 519a0a686d94..cd258463e2a9 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -657,7 +657,8 @@ static void ext4_mb_mark_free_simple(struct super_block *sb, | |||
| 657 | } | 657 | } |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | static void ext4_mb_generate_buddy(struct super_block *sb, | 660 | static noinline_for_stack |
| 661 | void ext4_mb_generate_buddy(struct super_block *sb, | ||
| 661 | void *buddy, void *bitmap, ext4_group_t group) | 662 | void *buddy, void *bitmap, ext4_group_t group) |
| 662 | { | 663 | { |
| 663 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | 664 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); |
| @@ -1480,7 +1481,8 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac, | |||
| 1480 | ext4_mb_check_limits(ac, e4b, 0); | 1481 | ext4_mb_check_limits(ac, e4b, 0); |
| 1481 | } | 1482 | } |
| 1482 | 1483 | ||
| 1483 | static int ext4_mb_try_best_found(struct ext4_allocation_context *ac, | 1484 | static noinline_for_stack |
| 1485 | int ext4_mb_try_best_found(struct ext4_allocation_context *ac, | ||
| 1484 | struct ext4_buddy *e4b) | 1486 | struct ext4_buddy *e4b) |
| 1485 | { | 1487 | { |
| 1486 | struct ext4_free_extent ex = ac->ac_b_ex; | 1488 | struct ext4_free_extent ex = ac->ac_b_ex; |
| @@ -1507,7 +1509,8 @@ static int ext4_mb_try_best_found(struct ext4_allocation_context *ac, | |||
| 1507 | return 0; | 1509 | return 0; |
| 1508 | } | 1510 | } |
| 1509 | 1511 | ||
| 1510 | static int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, | 1512 | static noinline_for_stack |
| 1513 | int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, | ||
| 1511 | struct ext4_buddy *e4b) | 1514 | struct ext4_buddy *e4b) |
| 1512 | { | 1515 | { |
| 1513 | ext4_group_t group = ac->ac_g_ex.fe_group; | 1516 | ext4_group_t group = ac->ac_g_ex.fe_group; |
| @@ -1566,7 +1569,8 @@ static int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, | |||
| 1566 | * The routine scans buddy structures (not bitmap!) from given order | 1569 | * The routine scans buddy structures (not bitmap!) from given order |
| 1567 | * to max order and tries to find big enough chunk to satisfy the req | 1570 | * to max order and tries to find big enough chunk to satisfy the req |
| 1568 | */ | 1571 | */ |
| 1569 | static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | 1572 | static noinline_for_stack |
| 1573 | void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | ||
| 1570 | struct ext4_buddy *e4b) | 1574 | struct ext4_buddy *e4b) |
| 1571 | { | 1575 | { |
| 1572 | struct super_block *sb = ac->ac_sb; | 1576 | struct super_block *sb = ac->ac_sb; |
| @@ -1609,7 +1613,8 @@ static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | |||
| 1609 | * In order to optimize scanning, caller must pass number of | 1613 | * In order to optimize scanning, caller must pass number of |
| 1610 | * free blocks in the group, so the routine can know upper limit. | 1614 | * free blocks in the group, so the routine can know upper limit. |
| 1611 | */ | 1615 | */ |
| 1612 | static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | 1616 | static noinline_for_stack |
| 1617 | void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | ||
| 1613 | struct ext4_buddy *e4b) | 1618 | struct ext4_buddy *e4b) |
| 1614 | { | 1619 | { |
| 1615 | struct super_block *sb = ac->ac_sb; | 1620 | struct super_block *sb = ac->ac_sb; |
| @@ -1668,7 +1673,8 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
| 1668 | * we try to find stripe-aligned chunks for stripe-size requests | 1673 | * we try to find stripe-aligned chunks for stripe-size requests |
| 1669 | * XXX should do so at least for multiples of stripe size as well | 1674 | * XXX should do so at least for multiples of stripe size as well |
| 1670 | */ | 1675 | */ |
| 1671 | static void ext4_mb_scan_aligned(struct ext4_allocation_context *ac, | 1676 | static noinline_for_stack |
| 1677 | void ext4_mb_scan_aligned(struct ext4_allocation_context *ac, | ||
| 1672 | struct ext4_buddy *e4b) | 1678 | struct ext4_buddy *e4b) |
| 1673 | { | 1679 | { |
| 1674 | struct super_block *sb = ac->ac_sb; | 1680 | struct super_block *sb = ac->ac_sb; |
| @@ -1831,7 +1837,8 @@ void ext4_mb_put_buddy_cache_lock(struct super_block *sb, | |||
| 1831 | 1837 | ||
| 1832 | } | 1838 | } |
| 1833 | 1839 | ||
| 1834 | static int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) | 1840 | static noinline_for_stack |
| 1841 | int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) | ||
| 1835 | { | 1842 | { |
| 1836 | 1843 | ||
| 1837 | int ret; | 1844 | int ret; |
| @@ -2902,7 +2909,11 @@ int __init init_ext4_mballoc(void) | |||
| 2902 | 2909 | ||
| 2903 | void exit_ext4_mballoc(void) | 2910 | void exit_ext4_mballoc(void) |
| 2904 | { | 2911 | { |
| 2905 | /* XXX: synchronize_rcu(); */ | 2912 | /* |
| 2913 | * Wait for completion of call_rcu()'s on ext4_pspace_cachep | ||
| 2914 | * before destroying the slab cache. | ||
| 2915 | */ | ||
| 2916 | rcu_barrier(); | ||
| 2906 | kmem_cache_destroy(ext4_pspace_cachep); | 2917 | kmem_cache_destroy(ext4_pspace_cachep); |
| 2907 | kmem_cache_destroy(ext4_ac_cachep); | 2918 | kmem_cache_destroy(ext4_ac_cachep); |
| 2908 | kmem_cache_destroy(ext4_free_ext_cachep); | 2919 | kmem_cache_destroy(ext4_free_ext_cachep); |
| @@ -3457,7 +3468,8 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap, | |||
| 3457 | * used in in-core bitmap. buddy must be generated from this bitmap | 3468 | * used in in-core bitmap. buddy must be generated from this bitmap |
| 3458 | * Need to be called with ext4 group lock held | 3469 | * Need to be called with ext4 group lock held |
| 3459 | */ | 3470 | */ |
| 3460 | static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | 3471 | static noinline_for_stack |
| 3472 | void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | ||
| 3461 | ext4_group_t group) | 3473 | ext4_group_t group) |
| 3462 | { | 3474 | { |
| 3463 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | 3475 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); |
| @@ -4215,14 +4227,9 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac, | |||
| 4215 | ext4_get_group_no_and_offset(sb, goal, &group, &block); | 4227 | ext4_get_group_no_and_offset(sb, goal, &group, &block); |
| 4216 | 4228 | ||
| 4217 | /* set up allocation goals */ | 4229 | /* set up allocation goals */ |
| 4230 | memset(ac, 0, sizeof(struct ext4_allocation_context)); | ||
| 4218 | ac->ac_b_ex.fe_logical = ar->logical; | 4231 | ac->ac_b_ex.fe_logical = ar->logical; |
| 4219 | ac->ac_b_ex.fe_group = 0; | ||
| 4220 | ac->ac_b_ex.fe_start = 0; | ||
| 4221 | ac->ac_b_ex.fe_len = 0; | ||
| 4222 | ac->ac_status = AC_STATUS_CONTINUE; | 4232 | ac->ac_status = AC_STATUS_CONTINUE; |
| 4223 | ac->ac_groups_scanned = 0; | ||
| 4224 | ac->ac_ex_scanned = 0; | ||
| 4225 | ac->ac_found = 0; | ||
| 4226 | ac->ac_sb = sb; | 4233 | ac->ac_sb = sb; |
| 4227 | ac->ac_inode = ar->inode; | 4234 | ac->ac_inode = ar->inode; |
| 4228 | ac->ac_o_ex.fe_logical = ar->logical; | 4235 | ac->ac_o_ex.fe_logical = ar->logical; |
| @@ -4233,15 +4240,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac, | |||
| 4233 | ac->ac_g_ex.fe_group = group; | 4240 | ac->ac_g_ex.fe_group = group; |
| 4234 | ac->ac_g_ex.fe_start = block; | 4241 | ac->ac_g_ex.fe_start = block; |
| 4235 | ac->ac_g_ex.fe_len = len; | 4242 | ac->ac_g_ex.fe_len = len; |
| 4236 | ac->ac_f_ex.fe_len = 0; | ||
| 4237 | ac->ac_flags = ar->flags; | 4243 | ac->ac_flags = ar->flags; |
| 4238 | ac->ac_2order = 0; | ||
| 4239 | ac->ac_criteria = 0; | ||
| 4240 | ac->ac_pa = NULL; | ||
| 4241 | ac->ac_bitmap_page = NULL; | ||
| 4242 | ac->ac_buddy_page = NULL; | ||
| 4243 | ac->alloc_semp = NULL; | ||
| 4244 | ac->ac_lg = NULL; | ||
| 4245 | 4244 | ||
| 4246 | /* we have to define context: we'll we work with a file or | 4245 | /* we have to define context: we'll we work with a file or |
| 4247 | * locality group. this is a policy, actually */ | 4246 | * locality group. this is a policy, actually */ |
| @@ -4509,10 +4508,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
| 4509 | } | 4508 | } |
| 4510 | 4509 | ||
| 4511 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); | 4510 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); |
| 4512 | if (ac) { | 4511 | if (!ac) { |
| 4513 | ac->ac_sb = sb; | ||
| 4514 | ac->ac_inode = ar->inode; | ||
| 4515 | } else { | ||
| 4516 | ar->len = 0; | 4512 | ar->len = 0; |
| 4517 | *errp = -ENOMEM; | 4513 | *errp = -ENOMEM; |
| 4518 | goto out1; | 4514 | goto out1; |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 38ff75a0fe22..530b4ca01510 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
| 19 | #include <linux/smp_lock.h> | ||
| 20 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
| 21 | #include <linux/compat.h> | 20 | #include <linux/compat.h> |
| 22 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
diff --git a/fs/fat/file.c b/fs/fat/file.c index b28ea646ff60..f042b965c95c 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
| @@ -134,7 +134,7 @@ static int fat_file_release(struct inode *inode, struct file *filp) | |||
| 134 | if ((filp->f_mode & FMODE_WRITE) && | 134 | if ((filp->f_mode & FMODE_WRITE) && |
| 135 | MSDOS_SB(inode->i_sb)->options.flush) { | 135 | MSDOS_SB(inode->i_sb)->options.flush) { |
| 136 | fat_flush_inodes(inode->i_sb, inode, NULL); | 136 | fat_flush_inodes(inode->i_sb, inode, NULL); |
| 137 | congestion_wait(WRITE, HZ/10); | 137 | congestion_wait(BLK_RW_ASYNC, HZ/10); |
| 138 | } | 138 | } |
| 139 | return 0; | 139 | return 0; |
| 140 | } | 140 | } |
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index 82f88733b681..bbc94ae4fd77 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
| 11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
| 12 | #include <linux/smp_lock.h> | ||
| 13 | #include "fat.h" | 12 | #include "fat.h" |
| 14 | 13 | ||
| 15 | /* Characters that are undesirable in an MS-DOS file name */ | 14 | /* Characters that are undesirable in an MS-DOS file name */ |
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 73471b7ecc8c..cb6e83557112 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
| 20 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 23 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
| 24 | #include <linux/namei.h> | 23 | #include <linux/namei.h> |
| 25 | #include "fat.h" | 24 | #include "fat.h" |
diff --git a/fs/fcntl.c b/fs/fcntl.c index a040b764f8e3..ae413086db97 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/signal.h> | 19 | #include <linux/signal.h> |
| 20 | #include <linux/rcupdate.h> | 20 | #include <linux/rcupdate.h> |
| 21 | #include <linux/pid_namespace.h> | 21 | #include <linux/pid_namespace.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 23 | 22 | ||
| 24 | #include <asm/poll.h> | 23 | #include <asm/poll.h> |
| 25 | #include <asm/siginfo.h> | 24 | #include <asm/siginfo.h> |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index cdbd1654e4cd..1e8af939b3e4 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/buffer_head.h> | 38 | #include <linux/buffer_head.h> |
| 39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
| 40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 41 | #include <linux/smp_lock.h> | ||
| 41 | #include <linux/stat.h> | 42 | #include <linux/stat.h> |
| 42 | #include <linux/vfs.h> | 43 | #include <linux/vfs.h> |
| 43 | #include <linux/mount.h> | 44 | #include <linux/mount.h> |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index f58ecbc416c8..6484eb75acd6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -286,8 +286,8 @@ __releases(&fc->lock) | |||
| 286 | } | 286 | } |
| 287 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 287 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
| 288 | fc->connected && fc->bdi_initialized) { | 288 | fc->connected && fc->bdi_initialized) { |
| 289 | clear_bdi_congested(&fc->bdi, READ); | 289 | clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); |
| 290 | clear_bdi_congested(&fc->bdi, WRITE); | 290 | clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC); |
| 291 | } | 291 | } |
| 292 | fc->num_background--; | 292 | fc->num_background--; |
| 293 | fc->active_background--; | 293 | fc->active_background--; |
| @@ -414,8 +414,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | |||
| 414 | fc->blocked = 1; | 414 | fc->blocked = 1; |
| 415 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 415 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
| 416 | fc->bdi_initialized) { | 416 | fc->bdi_initialized) { |
| 417 | set_bdi_congested(&fc->bdi, READ); | 417 | set_bdi_congested(&fc->bdi, BLK_RW_SYNC); |
| 418 | set_bdi_congested(&fc->bdi, WRITE); | 418 | set_bdi_congested(&fc->bdi, BLK_RW_ASYNC); |
| 419 | } | 419 | } |
| 420 | list_add_tail(&req->list, &fc->bg_queue); | 420 | list_add_tail(&req->list, &fc->bg_queue); |
| 421 | flush_bg_queue(fc); | 421 | flush_bg_queue(fc); |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 03ebb439ace0..7ebae9a4ecc0 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
| @@ -624,6 +624,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 624 | { | 624 | { |
| 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 625 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
| 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); | 626 | struct gfs2_sbd *sdp = GFS2_SB(mapping->host); |
| 627 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 627 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; | 628 | unsigned int data_blocks = 0, ind_blocks = 0, rblocks; |
| 628 | int alloc_required; | 629 | int alloc_required; |
| 629 | int error = 0; | 630 | int error = 0; |
| @@ -637,6 +638,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 637 | error = gfs2_glock_nq(&ip->i_gh); | 638 | error = gfs2_glock_nq(&ip->i_gh); |
| 638 | if (unlikely(error)) | 639 | if (unlikely(error)) |
| 639 | goto out_uninit; | 640 | goto out_uninit; |
| 641 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 642 | error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, | ||
| 643 | GL_NOCACHE, &m_ip->i_gh); | ||
| 644 | if (unlikely(error)) { | ||
| 645 | gfs2_glock_dq(&ip->i_gh); | ||
| 646 | goto out_uninit; | ||
| 647 | } | ||
| 648 | } | ||
| 640 | 649 | ||
| 641 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 650 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); |
| 642 | if (error) | 651 | if (error) |
| @@ -667,6 +676,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 667 | rblocks += data_blocks ? data_blocks : 1; | 676 | rblocks += data_blocks ? data_blocks : 1; |
| 668 | if (ind_blocks || data_blocks) | 677 | if (ind_blocks || data_blocks) |
| 669 | rblocks += RES_STATFS + RES_QUOTA; | 678 | rblocks += RES_STATFS + RES_QUOTA; |
| 679 | if (&ip->i_inode == sdp->sd_rindex) | ||
| 680 | rblocks += 2 * RES_STATFS; | ||
| 670 | 681 | ||
| 671 | error = gfs2_trans_begin(sdp, rblocks, | 682 | error = gfs2_trans_begin(sdp, rblocks, |
| 672 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); | 683 | PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); |
| @@ -712,6 +723,10 @@ out_alloc_put: | |||
| 712 | gfs2_alloc_put(ip); | 723 | gfs2_alloc_put(ip); |
| 713 | } | 724 | } |
| 714 | out_unlock: | 725 | out_unlock: |
| 726 | if (&ip->i_inode == sdp->sd_rindex) { | ||
| 727 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 728 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 729 | } | ||
| 715 | gfs2_glock_dq(&ip->i_gh); | 730 | gfs2_glock_dq(&ip->i_gh); |
| 716 | out_uninit: | 731 | out_uninit: |
| 717 | gfs2_holder_uninit(&ip->i_gh); | 732 | gfs2_holder_uninit(&ip->i_gh); |
| @@ -725,14 +740,21 @@ out_uninit: | |||
| 725 | static void adjust_fs_space(struct inode *inode) | 740 | static void adjust_fs_space(struct inode *inode) |
| 726 | { | 741 | { |
| 727 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 742 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; |
| 743 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 744 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 728 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | 745 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; |
| 729 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | 746 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; |
| 747 | struct buffer_head *m_bh, *l_bh; | ||
| 730 | u64 fs_total, new_free; | 748 | u64 fs_total, new_free; |
| 731 | 749 | ||
| 732 | /* Total up the file system space, according to the latest rindex. */ | 750 | /* Total up the file system space, according to the latest rindex. */ |
| 733 | fs_total = gfs2_ri_total(sdp); | 751 | fs_total = gfs2_ri_total(sdp); |
| 752 | if (gfs2_meta_inode_buffer(m_ip, &m_bh) != 0) | ||
| 753 | return; | ||
| 734 | 754 | ||
| 735 | spin_lock(&sdp->sd_statfs_spin); | 755 | spin_lock(&sdp->sd_statfs_spin); |
| 756 | gfs2_statfs_change_in(m_sc, m_bh->b_data + | ||
| 757 | sizeof(struct gfs2_dinode)); | ||
| 736 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) | 758 | if (fs_total > (m_sc->sc_total + l_sc->sc_total)) |
| 737 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); | 759 | new_free = fs_total - (m_sc->sc_total + l_sc->sc_total); |
| 738 | else | 760 | else |
| @@ -741,6 +763,13 @@ static void adjust_fs_space(struct inode *inode) | |||
| 741 | fs_warn(sdp, "File system extended by %llu blocks.\n", | 763 | fs_warn(sdp, "File system extended by %llu blocks.\n", |
| 742 | (unsigned long long)new_free); | 764 | (unsigned long long)new_free); |
| 743 | gfs2_statfs_change(sdp, new_free, new_free, 0); | 765 | gfs2_statfs_change(sdp, new_free, new_free, 0); |
| 766 | |||
| 767 | if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0) | ||
| 768 | goto out; | ||
| 769 | update_statfs(sdp, m_bh, l_bh); | ||
| 770 | brelse(l_bh); | ||
| 771 | out: | ||
| 772 | brelse(m_bh); | ||
| 744 | } | 773 | } |
| 745 | 774 | ||
| 746 | /** | 775 | /** |
| @@ -763,6 +792,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 763 | { | 792 | { |
| 764 | struct gfs2_inode *ip = GFS2_I(inode); | 793 | struct gfs2_inode *ip = GFS2_I(inode); |
| 765 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 794 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 795 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 766 | u64 to = pos + copied; | 796 | u64 to = pos + copied; |
| 767 | void *kaddr; | 797 | void *kaddr; |
| 768 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); | 798 | unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode); |
| @@ -794,6 +824,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh, | |||
| 794 | 824 | ||
| 795 | brelse(dibh); | 825 | brelse(dibh); |
| 796 | gfs2_trans_end(sdp); | 826 | gfs2_trans_end(sdp); |
| 827 | if (inode == sdp->sd_rindex) { | ||
| 828 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 829 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 830 | } | ||
| 797 | gfs2_glock_dq(&ip->i_gh); | 831 | gfs2_glock_dq(&ip->i_gh); |
| 798 | gfs2_holder_uninit(&ip->i_gh); | 832 | gfs2_holder_uninit(&ip->i_gh); |
| 799 | return copied; | 833 | return copied; |
| @@ -823,6 +857,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
| 823 | struct inode *inode = page->mapping->host; | 857 | struct inode *inode = page->mapping->host; |
| 824 | struct gfs2_inode *ip = GFS2_I(inode); | 858 | struct gfs2_inode *ip = GFS2_I(inode); |
| 825 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 859 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 860 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 826 | struct buffer_head *dibh; | 861 | struct buffer_head *dibh; |
| 827 | struct gfs2_alloc *al = ip->i_alloc; | 862 | struct gfs2_alloc *al = ip->i_alloc; |
| 828 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); | 863 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); |
| @@ -865,6 +900,10 @@ failed: | |||
| 865 | gfs2_quota_unlock(ip); | 900 | gfs2_quota_unlock(ip); |
| 866 | gfs2_alloc_put(ip); | 901 | gfs2_alloc_put(ip); |
| 867 | } | 902 | } |
| 903 | if (inode == sdp->sd_rindex) { | ||
| 904 | gfs2_glock_dq(&m_ip->i_gh); | ||
| 905 | gfs2_holder_uninit(&m_ip->i_gh); | ||
| 906 | } | ||
| 868 | gfs2_glock_dq(&ip->i_gh); | 907 | gfs2_glock_dq(&ip->i_gh); |
| 869 | gfs2_holder_uninit(&ip->i_gh); | 908 | gfs2_holder_uninit(&ip->i_gh); |
| 870 | return ret; | 909 | return ret; |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 297421c0427a..8b674b1f3a55 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -63,6 +63,7 @@ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int | |||
| 63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | 63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); |
| 64 | static struct dentry *gfs2_root; | 64 | static struct dentry *gfs2_root; |
| 65 | static struct workqueue_struct *glock_workqueue; | 65 | static struct workqueue_struct *glock_workqueue; |
| 66 | struct workqueue_struct *gfs2_delete_workqueue; | ||
| 66 | static LIST_HEAD(lru_list); | 67 | static LIST_HEAD(lru_list); |
| 67 | static atomic_t lru_count = ATOMIC_INIT(0); | 68 | static atomic_t lru_count = ATOMIC_INIT(0); |
| 68 | static DEFINE_SPINLOCK(lru_lock); | 69 | static DEFINE_SPINLOCK(lru_lock); |
| @@ -167,13 +168,33 @@ static void glock_free(struct gfs2_glock *gl) | |||
| 167 | * | 168 | * |
| 168 | */ | 169 | */ |
| 169 | 170 | ||
| 170 | static void gfs2_glock_hold(struct gfs2_glock *gl) | 171 | void gfs2_glock_hold(struct gfs2_glock *gl) |
| 171 | { | 172 | { |
| 172 | GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); | 173 | GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0); |
| 173 | atomic_inc(&gl->gl_ref); | 174 | atomic_inc(&gl->gl_ref); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | /** | 177 | /** |
| 178 | * demote_ok - Check to see if it's ok to unlock a glock | ||
| 179 | * @gl: the glock | ||
| 180 | * | ||
| 181 | * Returns: 1 if it's ok | ||
| 182 | */ | ||
| 183 | |||
| 184 | static int demote_ok(const struct gfs2_glock *gl) | ||
| 185 | { | ||
| 186 | const struct gfs2_glock_operations *glops = gl->gl_ops; | ||
| 187 | |||
| 188 | if (gl->gl_state == LM_ST_UNLOCKED) | ||
| 189 | return 0; | ||
| 190 | if (!list_empty(&gl->gl_holders)) | ||
| 191 | return 0; | ||
| 192 | if (glops->go_demote_ok) | ||
| 193 | return glops->go_demote_ok(gl); | ||
| 194 | return 1; | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 177 | * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list | 198 | * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list |
| 178 | * @gl: the glock | 199 | * @gl: the glock |
| 179 | * | 200 | * |
| @@ -181,8 +202,13 @@ static void gfs2_glock_hold(struct gfs2_glock *gl) | |||
| 181 | 202 | ||
| 182 | static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | 203 | static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) |
| 183 | { | 204 | { |
| 205 | int may_reclaim; | ||
| 206 | may_reclaim = (demote_ok(gl) && | ||
| 207 | (atomic_read(&gl->gl_ref) == 1 || | ||
| 208 | (gl->gl_name.ln_type == LM_TYPE_INODE && | ||
| 209 | atomic_read(&gl->gl_ref) <= 2))); | ||
| 184 | spin_lock(&lru_lock); | 210 | spin_lock(&lru_lock); |
| 185 | if (list_empty(&gl->gl_lru) && gl->gl_state != LM_ST_UNLOCKED) { | 211 | if (list_empty(&gl->gl_lru) && may_reclaim) { |
| 186 | list_add_tail(&gl->gl_lru, &lru_list); | 212 | list_add_tail(&gl->gl_lru, &lru_list); |
| 187 | atomic_inc(&lru_count); | 213 | atomic_inc(&lru_count); |
| 188 | } | 214 | } |
| @@ -190,6 +216,21 @@ static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | |||
| 190 | } | 216 | } |
| 191 | 217 | ||
| 192 | /** | 218 | /** |
| 219 | * gfs2_glock_put_nolock() - Decrement reference count on glock | ||
| 220 | * @gl: The glock to put | ||
| 221 | * | ||
| 222 | * This function should only be used if the caller has its own reference | ||
| 223 | * to the glock, in addition to the one it is dropping. | ||
| 224 | */ | ||
| 225 | |||
| 226 | void gfs2_glock_put_nolock(struct gfs2_glock *gl) | ||
| 227 | { | ||
| 228 | if (atomic_dec_and_test(&gl->gl_ref)) | ||
| 229 | GLOCK_BUG_ON(gl, 1); | ||
| 230 | gfs2_glock_schedule_for_reclaim(gl); | ||
| 231 | } | ||
| 232 | |||
| 233 | /** | ||
| 193 | * gfs2_glock_put() - Decrement reference count on glock | 234 | * gfs2_glock_put() - Decrement reference count on glock |
| 194 | * @gl: The glock to put | 235 | * @gl: The glock to put |
| 195 | * | 236 | * |
| @@ -214,9 +255,9 @@ int gfs2_glock_put(struct gfs2_glock *gl) | |||
| 214 | rv = 1; | 255 | rv = 1; |
| 215 | goto out; | 256 | goto out; |
| 216 | } | 257 | } |
| 217 | /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */ | 258 | spin_lock(&gl->gl_spin); |
| 218 | if (atomic_read(&gl->gl_ref) == 2) | 259 | gfs2_glock_schedule_for_reclaim(gl); |
| 219 | gfs2_glock_schedule_for_reclaim(gl); | 260 | spin_unlock(&gl->gl_spin); |
| 220 | write_unlock(gl_lock_addr(gl->gl_hash)); | 261 | write_unlock(gl_lock_addr(gl->gl_hash)); |
| 221 | out: | 262 | out: |
| 222 | return rv; | 263 | return rv; |
| @@ -398,7 +439,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) | |||
| 398 | if (held2) | 439 | if (held2) |
| 399 | gfs2_glock_hold(gl); | 440 | gfs2_glock_hold(gl); |
| 400 | else | 441 | else |
| 401 | gfs2_glock_put(gl); | 442 | gfs2_glock_put_nolock(gl); |
| 402 | } | 443 | } |
| 403 | 444 | ||
| 404 | gl->gl_state = new_state; | 445 | gl->gl_state = new_state; |
| @@ -633,12 +674,35 @@ out: | |||
| 633 | out_sched: | 674 | out_sched: |
| 634 | gfs2_glock_hold(gl); | 675 | gfs2_glock_hold(gl); |
| 635 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 676 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
| 636 | gfs2_glock_put(gl); | 677 | gfs2_glock_put_nolock(gl); |
| 637 | out_unlock: | 678 | out_unlock: |
| 638 | clear_bit(GLF_LOCK, &gl->gl_flags); | 679 | clear_bit(GLF_LOCK, &gl->gl_flags); |
| 639 | goto out; | 680 | goto out; |
| 640 | } | 681 | } |
| 641 | 682 | ||
| 683 | static void delete_work_func(struct work_struct *work) | ||
| 684 | { | ||
| 685 | struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete); | ||
| 686 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 687 | struct gfs2_inode *ip = NULL; | ||
| 688 | struct inode *inode; | ||
| 689 | u64 no_addr = 0; | ||
| 690 | |||
| 691 | spin_lock(&gl->gl_spin); | ||
| 692 | ip = (struct gfs2_inode *)gl->gl_object; | ||
| 693 | if (ip) | ||
| 694 | no_addr = ip->i_no_addr; | ||
| 695 | spin_unlock(&gl->gl_spin); | ||
| 696 | if (ip) { | ||
| 697 | inode = gfs2_ilookup(sdp->sd_vfs, no_addr); | ||
| 698 | if (inode) { | ||
| 699 | d_prune_aliases(inode); | ||
| 700 | iput(inode); | ||
| 701 | } | ||
| 702 | } | ||
| 703 | gfs2_glock_put(gl); | ||
| 704 | } | ||
| 705 | |||
| 642 | static void glock_work_func(struct work_struct *work) | 706 | static void glock_work_func(struct work_struct *work) |
| 643 | { | 707 | { |
| 644 | unsigned long delay = 0; | 708 | unsigned long delay = 0; |
| @@ -717,6 +781,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 717 | gl->gl_sbd = sdp; | 781 | gl->gl_sbd = sdp; |
| 718 | gl->gl_aspace = NULL; | 782 | gl->gl_aspace = NULL; |
| 719 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 783 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
| 784 | INIT_WORK(&gl->gl_delete, delete_work_func); | ||
| 720 | 785 | ||
| 721 | /* If this glock protects actual on-disk data or metadata blocks, | 786 | /* If this glock protects actual on-disk data or metadata blocks, |
| 722 | create a VFS inode to manage the pages/buffers holding them. */ | 787 | create a VFS inode to manage the pages/buffers holding them. */ |
| @@ -858,6 +923,8 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state, | |||
| 858 | gl->gl_demote_state != state) { | 923 | gl->gl_demote_state != state) { |
| 859 | gl->gl_demote_state = LM_ST_UNLOCKED; | 924 | gl->gl_demote_state = LM_ST_UNLOCKED; |
| 860 | } | 925 | } |
| 926 | if (gl->gl_ops->go_callback) | ||
| 927 | gl->gl_ops->go_callback(gl); | ||
| 861 | trace_gfs2_demote_rq(gl); | 928 | trace_gfs2_demote_rq(gl); |
| 862 | } | 929 | } |
| 863 | 930 | ||
| @@ -1274,33 +1341,12 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | |||
| 1274 | gfs2_glock_put(gl); | 1341 | gfs2_glock_put(gl); |
| 1275 | } | 1342 | } |
| 1276 | 1343 | ||
| 1277 | /** | ||
| 1278 | * demote_ok - Check to see if it's ok to unlock a glock | ||
| 1279 | * @gl: the glock | ||
| 1280 | * | ||
| 1281 | * Returns: 1 if it's ok | ||
| 1282 | */ | ||
| 1283 | |||
| 1284 | static int demote_ok(const struct gfs2_glock *gl) | ||
| 1285 | { | ||
| 1286 | const struct gfs2_glock_operations *glops = gl->gl_ops; | ||
| 1287 | |||
| 1288 | if (gl->gl_state == LM_ST_UNLOCKED) | ||
| 1289 | return 0; | ||
| 1290 | if (!list_empty(&gl->gl_holders)) | ||
| 1291 | return 0; | ||
| 1292 | if (glops->go_demote_ok) | ||
| 1293 | return glops->go_demote_ok(gl); | ||
| 1294 | return 1; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | 1344 | ||
| 1298 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | 1345 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) |
| 1299 | { | 1346 | { |
| 1300 | struct gfs2_glock *gl; | 1347 | struct gfs2_glock *gl; |
| 1301 | int may_demote; | 1348 | int may_demote; |
| 1302 | int nr_skipped = 0; | 1349 | int nr_skipped = 0; |
| 1303 | int got_ref = 0; | ||
| 1304 | LIST_HEAD(skipped); | 1350 | LIST_HEAD(skipped); |
| 1305 | 1351 | ||
| 1306 | if (nr == 0) | 1352 | if (nr == 0) |
| @@ -1315,37 +1361,29 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | |||
| 1315 | list_del_init(&gl->gl_lru); | 1361 | list_del_init(&gl->gl_lru); |
| 1316 | atomic_dec(&lru_count); | 1362 | atomic_dec(&lru_count); |
| 1317 | 1363 | ||
| 1364 | /* Check if glock is about to be freed */ | ||
| 1365 | if (atomic_read(&gl->gl_ref) == 0) | ||
| 1366 | continue; | ||
| 1367 | |||
| 1318 | /* Test for being demotable */ | 1368 | /* Test for being demotable */ |
| 1319 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { | 1369 | if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { |
| 1320 | gfs2_glock_hold(gl); | 1370 | gfs2_glock_hold(gl); |
| 1321 | got_ref = 1; | ||
| 1322 | spin_unlock(&lru_lock); | 1371 | spin_unlock(&lru_lock); |
| 1323 | spin_lock(&gl->gl_spin); | 1372 | spin_lock(&gl->gl_spin); |
| 1324 | may_demote = demote_ok(gl); | 1373 | may_demote = demote_ok(gl); |
| 1325 | spin_unlock(&gl->gl_spin); | ||
| 1326 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 1327 | if (may_demote) { | 1374 | if (may_demote) { |
| 1328 | handle_callback(gl, LM_ST_UNLOCKED, 0); | 1375 | handle_callback(gl, LM_ST_UNLOCKED, 0); |
| 1329 | nr--; | 1376 | nr--; |
| 1330 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | ||
| 1331 | gfs2_glock_put(gl); | ||
| 1332 | got_ref = 0; | ||
| 1333 | } | 1377 | } |
| 1378 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | ||
| 1379 | gfs2_glock_put_nolock(gl); | ||
| 1380 | spin_unlock(&gl->gl_spin); | ||
| 1381 | clear_bit(GLF_LOCK, &gl->gl_flags); | ||
| 1334 | spin_lock(&lru_lock); | 1382 | spin_lock(&lru_lock); |
| 1335 | if (may_demote) | 1383 | continue; |
| 1336 | continue; | ||
| 1337 | } | ||
| 1338 | if (list_empty(&gl->gl_lru) && | ||
| 1339 | (atomic_read(&gl->gl_ref) <= (2 + got_ref))) { | ||
| 1340 | nr_skipped++; | ||
| 1341 | list_add(&gl->gl_lru, &skipped); | ||
| 1342 | } | ||
| 1343 | if (got_ref) { | ||
| 1344 | spin_unlock(&lru_lock); | ||
| 1345 | gfs2_glock_put(gl); | ||
| 1346 | spin_lock(&lru_lock); | ||
| 1347 | got_ref = 0; | ||
| 1348 | } | 1384 | } |
| 1385 | nr_skipped++; | ||
| 1386 | list_add(&gl->gl_lru, &skipped); | ||
| 1349 | } | 1387 | } |
| 1350 | list_splice(&skipped, &lru_list); | 1388 | list_splice(&skipped, &lru_list); |
| 1351 | atomic_add(nr_skipped, &lru_count); | 1389 | atomic_add(nr_skipped, &lru_count); |
| @@ -1727,6 +1765,11 @@ int __init gfs2_glock_init(void) | |||
| 1727 | glock_workqueue = create_workqueue("glock_workqueue"); | 1765 | glock_workqueue = create_workqueue("glock_workqueue"); |
| 1728 | if (IS_ERR(glock_workqueue)) | 1766 | if (IS_ERR(glock_workqueue)) |
| 1729 | return PTR_ERR(glock_workqueue); | 1767 | return PTR_ERR(glock_workqueue); |
| 1768 | gfs2_delete_workqueue = create_workqueue("delete_workqueue"); | ||
| 1769 | if (IS_ERR(gfs2_delete_workqueue)) { | ||
| 1770 | destroy_workqueue(glock_workqueue); | ||
| 1771 | return PTR_ERR(gfs2_delete_workqueue); | ||
| 1772 | } | ||
| 1730 | 1773 | ||
| 1731 | register_shrinker(&glock_shrinker); | 1774 | register_shrinker(&glock_shrinker); |
| 1732 | 1775 | ||
| @@ -1737,6 +1780,7 @@ void gfs2_glock_exit(void) | |||
| 1737 | { | 1780 | { |
| 1738 | unregister_shrinker(&glock_shrinker); | 1781 | unregister_shrinker(&glock_shrinker); |
| 1739 | destroy_workqueue(glock_workqueue); | 1782 | destroy_workqueue(glock_workqueue); |
| 1783 | destroy_workqueue(gfs2_delete_workqueue); | ||
| 1740 | } | 1784 | } |
| 1741 | 1785 | ||
| 1742 | static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) | 1786 | static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi) |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index a602a28f6f08..c609894ec0d0 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
| @@ -143,6 +143,7 @@ struct lm_lockops { | |||
| 143 | 143 | ||
| 144 | #define GLR_TRYFAILED 13 | 144 | #define GLR_TRYFAILED 13 |
| 145 | 145 | ||
| 146 | extern struct workqueue_struct *gfs2_delete_workqueue; | ||
| 146 | static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) | 147 | static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) |
| 147 | { | 148 | { |
| 148 | struct gfs2_holder *gh; | 149 | struct gfs2_holder *gh; |
| @@ -191,6 +192,8 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) | |||
| 191 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 192 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
| 192 | u64 number, const struct gfs2_glock_operations *glops, | 193 | u64 number, const struct gfs2_glock_operations *glops, |
| 193 | int create, struct gfs2_glock **glp); | 194 | int create, struct gfs2_glock **glp); |
| 195 | void gfs2_glock_hold(struct gfs2_glock *gl); | ||
| 196 | void gfs2_glock_put_nolock(struct gfs2_glock *gl); | ||
| 194 | int gfs2_glock_put(struct gfs2_glock *gl); | 197 | int gfs2_glock_put(struct gfs2_glock *gl); |
| 195 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, | 198 | void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, |
| 196 | struct gfs2_holder *gh); | 199 | struct gfs2_holder *gh); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index d5e4ab155ca0..6985eef06c39 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
| @@ -323,6 +323,7 @@ static void trans_go_sync(struct gfs2_glock *gl) | |||
| 323 | 323 | ||
| 324 | if (gl->gl_state != LM_ST_UNLOCKED && | 324 | if (gl->gl_state != LM_ST_UNLOCKED && |
| 325 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 325 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
| 326 | flush_workqueue(gfs2_delete_workqueue); | ||
| 326 | gfs2_meta_syncfs(sdp); | 327 | gfs2_meta_syncfs(sdp); |
| 327 | gfs2_log_shutdown(sdp); | 328 | gfs2_log_shutdown(sdp); |
| 328 | } | 329 | } |
| @@ -372,6 +373,25 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) | |||
| 372 | return 0; | 373 | return 0; |
| 373 | } | 374 | } |
| 374 | 375 | ||
| 376 | /** | ||
| 377 | * iopen_go_callback - schedule the dcache entry for the inode to be deleted | ||
| 378 | * @gl: the glock | ||
| 379 | * | ||
| 380 | * gl_spin lock is held while calling this | ||
| 381 | */ | ||
| 382 | static void iopen_go_callback(struct gfs2_glock *gl) | ||
| 383 | { | ||
| 384 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | ||
| 385 | |||
| 386 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | ||
| 387 | gl->gl_state == LM_ST_SHARED && | ||
| 388 | ip && test_bit(GIF_USER, &ip->i_flags)) { | ||
| 389 | gfs2_glock_hold(gl); | ||
| 390 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) | ||
| 391 | gfs2_glock_put_nolock(gl); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 375 | const struct gfs2_glock_operations gfs2_meta_glops = { | 395 | const struct gfs2_glock_operations gfs2_meta_glops = { |
| 376 | .go_type = LM_TYPE_META, | 396 | .go_type = LM_TYPE_META, |
| 377 | }; | 397 | }; |
| @@ -406,6 +426,7 @@ const struct gfs2_glock_operations gfs2_trans_glops = { | |||
| 406 | 426 | ||
| 407 | const struct gfs2_glock_operations gfs2_iopen_glops = { | 427 | const struct gfs2_glock_operations gfs2_iopen_glops = { |
| 408 | .go_type = LM_TYPE_IOPEN, | 428 | .go_type = LM_TYPE_IOPEN, |
| 429 | .go_callback = iopen_go_callback, | ||
| 409 | }; | 430 | }; |
| 410 | 431 | ||
| 411 | const struct gfs2_glock_operations gfs2_flock_glops = { | 432 | const struct gfs2_glock_operations gfs2_flock_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 225347fbff3c..61801ada36f0 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
| @@ -159,6 +159,7 @@ struct gfs2_glock_operations { | |||
| 159 | int (*go_lock) (struct gfs2_holder *gh); | 159 | int (*go_lock) (struct gfs2_holder *gh); |
| 160 | void (*go_unlock) (struct gfs2_holder *gh); | 160 | void (*go_unlock) (struct gfs2_holder *gh); |
| 161 | int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); | 161 | int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl); |
| 162 | void (*go_callback) (struct gfs2_glock *gl); | ||
| 162 | const int go_type; | 163 | const int go_type; |
| 163 | const unsigned long go_min_hold_time; | 164 | const unsigned long go_min_hold_time; |
| 164 | }; | 165 | }; |
| @@ -228,6 +229,7 @@ struct gfs2_glock { | |||
| 228 | struct list_head gl_ail_list; | 229 | struct list_head gl_ail_list; |
| 229 | atomic_t gl_ail_count; | 230 | atomic_t gl_ail_count; |
| 230 | struct delayed_work gl_work; | 231 | struct delayed_work gl_work; |
| 232 | struct work_struct gl_delete; | ||
| 231 | }; | 233 | }; |
| 232 | 234 | ||
| 233 | #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ | 235 | #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */ |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index daa4ae341a29..fba795798d3a 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
| @@ -285,27 +285,19 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes; | 287 | tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes; |
| 288 | if (count[1] + count[2] != tmp) { | 288 | if (count[1] != tmp) { |
| 289 | if (gfs2_consist_rgrpd(rgd)) | 289 | if (gfs2_consist_rgrpd(rgd)) |
| 290 | fs_err(sdp, "used data mismatch: %u != %u\n", | 290 | fs_err(sdp, "used data mismatch: %u != %u\n", |
| 291 | count[1], tmp); | 291 | count[1], tmp); |
| 292 | return; | 292 | return; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | if (count[3] != rgd->rd_dinodes) { | 295 | if (count[2] + count[3] != rgd->rd_dinodes) { |
| 296 | if (gfs2_consist_rgrpd(rgd)) | 296 | if (gfs2_consist_rgrpd(rgd)) |
| 297 | fs_err(sdp, "used metadata mismatch: %u != %u\n", | 297 | fs_err(sdp, "used metadata mismatch: %u != %u\n", |
| 298 | count[3], rgd->rd_dinodes); | 298 | count[2] + count[3], rgd->rd_dinodes); |
| 299 | return; | 299 | return; |
| 300 | } | 300 | } |
| 301 | |||
| 302 | if (count[2] > count[3]) { | ||
| 303 | if (gfs2_consist_rgrpd(rgd)) | ||
| 304 | fs_err(sdp, "unlinked inodes > inodes: %u\n", | ||
| 305 | count[2]); | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | |||
| 309 | } | 301 | } |
| 310 | 302 | ||
| 311 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) | 303 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) |
| @@ -961,7 +953,8 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
| 961 | * Returns: The inode, if one has been found | 953 | * Returns: The inode, if one has been found |
| 962 | */ | 954 | */ |
| 963 | 955 | ||
| 964 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | 956 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, |
| 957 | u64 skip) | ||
| 965 | { | 958 | { |
| 966 | struct inode *inode; | 959 | struct inode *inode; |
| 967 | u32 goal = 0, block; | 960 | u32 goal = 0, block; |
| @@ -985,6 +978,8 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | |||
| 985 | goal++; | 978 | goal++; |
| 986 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) | 979 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
| 987 | continue; | 980 | continue; |
| 981 | if (no_addr == skip) | ||
| 982 | continue; | ||
| 988 | *last_unlinked = no_addr; | 983 | *last_unlinked = no_addr; |
| 989 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 984 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, |
| 990 | no_addr, -1, 1); | 985 | no_addr, -1, 1); |
| @@ -1104,7 +1099,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1104 | if (try_rgrp_fit(rgd, al)) | 1099 | if (try_rgrp_fit(rgd, al)) |
| 1105 | goto out; | 1100 | goto out; |
| 1106 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1101 | if (rgd->rd_flags & GFS2_RDF_CHECK) |
| 1107 | inode = try_rgrp_unlink(rgd, last_unlinked); | 1102 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
| 1108 | if (!rg_locked) | 1103 | if (!rg_locked) |
| 1109 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1104 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
| 1110 | if (inode) | 1105 | if (inode) |
| @@ -1138,7 +1133,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
| 1138 | if (try_rgrp_fit(rgd, al)) | 1133 | if (try_rgrp_fit(rgd, al)) |
| 1139 | goto out; | 1134 | goto out; |
| 1140 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1135 | if (rgd->rd_flags & GFS2_RDF_CHECK) |
| 1141 | inode = try_rgrp_unlink(rgd, last_unlinked); | 1136 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); |
| 1142 | if (!rg_locked) | 1137 | if (!rg_locked) |
| 1143 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1138 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
| 1144 | if (inode) | 1139 | if (inode) |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0a6801336470..f522bb017973 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -353,7 +353,7 @@ fail: | |||
| 353 | return error; | 353 | return error; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) | 356 | void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf) |
| 357 | { | 357 | { |
| 358 | const struct gfs2_statfs_change *str = buf; | 358 | const struct gfs2_statfs_change *str = buf; |
| 359 | 359 | ||
| @@ -441,6 +441,29 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | |||
| 441 | brelse(l_bh); | 441 | brelse(l_bh); |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 445 | struct buffer_head *l_bh) | ||
| 446 | { | ||
| 447 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | ||
| 448 | struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); | ||
| 449 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
| 450 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
| 451 | |||
| 452 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | ||
| 453 | |||
| 454 | spin_lock(&sdp->sd_statfs_spin); | ||
| 455 | m_sc->sc_total += l_sc->sc_total; | ||
| 456 | m_sc->sc_free += l_sc->sc_free; | ||
| 457 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 458 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 459 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 460 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 461 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 462 | |||
| 463 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 464 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 465 | } | ||
| 466 | |||
| 444 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) | 467 | int gfs2_statfs_sync(struct gfs2_sbd *sdp) |
| 445 | { | 468 | { |
| 446 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); | 469 | struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); |
| @@ -477,19 +500,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp) | |||
| 477 | if (error) | 500 | if (error) |
| 478 | goto out_bh2; | 501 | goto out_bh2; |
| 479 | 502 | ||
| 480 | gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1); | 503 | update_statfs(sdp, m_bh, l_bh); |
| 481 | |||
| 482 | spin_lock(&sdp->sd_statfs_spin); | ||
| 483 | m_sc->sc_total += l_sc->sc_total; | ||
| 484 | m_sc->sc_free += l_sc->sc_free; | ||
| 485 | m_sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 486 | memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); | ||
| 487 | memset(l_bh->b_data + sizeof(struct gfs2_dinode), | ||
| 488 | 0, sizeof(struct gfs2_statfs_change)); | ||
| 489 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 490 | |||
| 491 | gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1); | ||
| 492 | gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); | ||
| 493 | 504 | ||
| 494 | gfs2_trans_end(sdp); | 505 | gfs2_trans_end(sdp); |
| 495 | 506 | ||
| @@ -680,6 +691,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
| 680 | struct gfs2_holder t_gh; | 691 | struct gfs2_holder t_gh; |
| 681 | int error; | 692 | int error; |
| 682 | 693 | ||
| 694 | flush_workqueue(gfs2_delete_workqueue); | ||
| 683 | gfs2_quota_sync(sdp); | 695 | gfs2_quota_sync(sdp); |
| 684 | gfs2_statfs_sync(sdp); | 696 | gfs2_statfs_sync(sdp); |
| 685 | 697 | ||
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index b56413e3e40d..22e0417ed996 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
| @@ -40,6 +40,10 @@ extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp); | |||
| 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); | 40 | extern int gfs2_statfs_init(struct gfs2_sbd *sdp); |
| 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, | 41 | extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, |
| 42 | s64 dinodes); | 42 | s64 dinodes); |
| 43 | extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, | ||
| 44 | const void *buf); | ||
| 45 | extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, | ||
| 46 | struct buffer_head *l_bh); | ||
| 43 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); | 47 | extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); |
| 44 | 48 | ||
| 45 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); | 49 | extern int gfs2_freeze_fs(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 23419dc3027b..a7cbfbd340c7 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
| @@ -386,16 +386,16 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf) | |||
| 386 | #define GDLM_ATTR(_name,_mode,_show,_store) \ | 386 | #define GDLM_ATTR(_name,_mode,_show,_store) \ |
| 387 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) | 387 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) |
| 388 | 388 | ||
| 389 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); | 389 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); |
| 390 | GDLM_ATTR(block, 0644, block_show, block_store); | 390 | GDLM_ATTR(block, 0644, block_show, block_store); |
| 391 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); | 391 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); |
| 392 | GDLM_ATTR(id, 0444, lkid_show, NULL); | 392 | GDLM_ATTR(id, 0444, lkid_show, NULL); |
| 393 | GDLM_ATTR(jid, 0444, jid_show, NULL); | 393 | GDLM_ATTR(jid, 0444, jid_show, NULL); |
| 394 | GDLM_ATTR(first, 0444, lkfirst_show, NULL); | 394 | GDLM_ATTR(first, 0444, lkfirst_show, NULL); |
| 395 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); | 395 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); |
| 396 | GDLM_ATTR(recover, 0200, NULL, recover_store); | 396 | GDLM_ATTR(recover, 0600, NULL, recover_store); |
| 397 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); | 397 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); |
| 398 | GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); | 398 | GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); |
| 399 | 399 | ||
| 400 | static struct attribute *lock_module_attrs[] = { | 400 | static struct attribute *lock_module_attrs[] = { |
| 401 | &gdlm_attr_proto_name.attr, | 401 | &gdlm_attr_proto_name.attr, |
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h index 98d6ef1c1dc0..148d55c14171 100644 --- a/fs/gfs2/trace_gfs2.h +++ b/fs/gfs2/trace_gfs2.h | |||
| @@ -1,12 +1,11 @@ | |||
| 1 | #undef TRACE_SYSTEM | ||
| 2 | #define TRACE_SYSTEM gfs2 | ||
| 3 | |||
| 1 | #if !defined(_TRACE_GFS2_H) || defined(TRACE_HEADER_MULTI_READ) | 4 | #if !defined(_TRACE_GFS2_H) || defined(TRACE_HEADER_MULTI_READ) |
| 2 | #define _TRACE_GFS2_H | 5 | #define _TRACE_GFS2_H |
| 3 | 6 | ||
| 4 | #include <linux/tracepoint.h> | 7 | #include <linux/tracepoint.h> |
| 5 | 8 | ||
| 6 | #undef TRACE_SYSTEM | ||
| 7 | #define TRACE_SYSTEM gfs2 | ||
| 8 | #define TRACE_INCLUDE_FILE trace_gfs2 | ||
| 9 | |||
| 10 | #include <linux/fs.h> | 9 | #include <linux/fs.h> |
| 11 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
| 12 | #include <linux/dlmconstants.h> | 11 | #include <linux/dlmconstants.h> |
| @@ -403,5 +402,6 @@ TRACE_EVENT(gfs2_block_alloc, | |||
| 403 | /* This part must be outside protection */ | 402 | /* This part must be outside protection */ |
| 404 | #undef TRACE_INCLUDE_PATH | 403 | #undef TRACE_INCLUDE_PATH |
| 405 | #define TRACE_INCLUDE_PATH . | 404 | #define TRACE_INCLUDE_PATH . |
| 405 | #define TRACE_INCLUDE_FILE trace_gfs2 | ||
| 406 | #include <trace/define_trace.h> | 406 | #include <trace/define_trace.h> |
| 407 | 407 | ||
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 6f833dc8e910..f7fcbe49da72 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/nls.h> | 19 | #include <linux/nls.h> |
| 20 | #include <linux/parser.h> | 20 | #include <linux/parser.h> |
| 21 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 22 | #include <linux/vfs.h> | 23 | #include <linux/vfs.h> |
| 23 | 24 | ||
| 24 | #include "hfs_fs.h" | 25 | #include "hfs_fs.h" |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 9fc3af0c0dab..c0759fe0855b 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/smp_lock.h> | ||
| 15 | #include <linux/vfs.h> | 16 | #include <linux/vfs.h> |
| 16 | #include <linux/nls.h> | 17 | #include <linux/nls.h> |
| 17 | 18 | ||
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 6916c41d7017..8865c94f55f6 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * directory VFS functions | 6 | * directory VFS functions |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/smp_lock.h> | ||
| 9 | #include "hpfs_fn.h" | 10 | #include "hpfs_fn.h" |
| 10 | 11 | ||
| 11 | static int hpfs_dir_release(struct inode *inode, struct file *filp) | 12 | static int hpfs_dir_release(struct inode *inode, struct file *filp) |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 64ab52259204..3efabff00367 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * file VFS functions | 6 | * file VFS functions |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/smp_lock.h> | ||
| 9 | #include "hpfs_fn.h" | 10 | #include "hpfs_fn.h" |
| 10 | 11 | ||
| 11 | #define BLOCKS(size) (((size) + 511) >> 9) | 12 | #define BLOCKS(size) (((size) + 511) >> 9) |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index c2ea31bae313..701ca54c0867 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
| 14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/smp_lock.h> | ||
| 17 | 16 | ||
| 18 | #include "hpfs.h" | 17 | #include "hpfs.h" |
| 19 | 18 | ||
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 39a1bfbea312..fe703ae46bc7 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * inode VFS functions | 6 | * inode VFS functions |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/smp_lock.h> | ||
| 9 | #include "hpfs_fn.h" | 10 | #include "hpfs_fn.h" |
| 10 | 11 | ||
| 11 | void hpfs_init_inode(struct inode *i) | 12 | void hpfs_init_inode(struct inode *i) |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index b649232dde97..82b9c4ba9ed0 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * adding & removing files & directories | 6 | * adding & removing files & directories |
| 7 | */ | 7 | */ |
| 8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
| 9 | #include <linux/smp_lock.h> | ||
| 9 | #include "hpfs_fn.h" | 10 | #include "hpfs_fn.h" |
| 10 | 11 | ||
| 11 | static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 12 | static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
diff --git a/fs/inode.c b/fs/inode.c index 901bad1e5f12..ae7b67e48661 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -120,12 +120,11 @@ static void wake_up_inode(struct inode *inode) | |||
| 120 | * These are initializations that need to be done on every inode | 120 | * These are initializations that need to be done on every inode |
| 121 | * allocation as the fields are not initialised by slab allocation. | 121 | * allocation as the fields are not initialised by slab allocation. |
| 122 | */ | 122 | */ |
| 123 | struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | 123 | int inode_init_always(struct super_block *sb, struct inode *inode) |
| 124 | { | 124 | { |
| 125 | static const struct address_space_operations empty_aops; | 125 | static const struct address_space_operations empty_aops; |
| 126 | static struct inode_operations empty_iops; | 126 | static struct inode_operations empty_iops; |
| 127 | static const struct file_operations empty_fops; | 127 | static const struct file_operations empty_fops; |
| 128 | |||
| 129 | struct address_space *const mapping = &inode->i_data; | 128 | struct address_space *const mapping = &inode->i_data; |
| 130 | 129 | ||
| 131 | inode->i_sb = sb; | 130 | inode->i_sb = sb; |
| @@ -152,7 +151,7 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 152 | inode->dirtied_when = 0; | 151 | inode->dirtied_when = 0; |
| 153 | 152 | ||
| 154 | if (security_inode_alloc(inode)) | 153 | if (security_inode_alloc(inode)) |
| 155 | goto out_free_inode; | 154 | goto out; |
| 156 | 155 | ||
| 157 | /* allocate and initialize an i_integrity */ | 156 | /* allocate and initialize an i_integrity */ |
| 158 | if (ima_inode_alloc(inode)) | 157 | if (ima_inode_alloc(inode)) |
| @@ -198,16 +197,12 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 198 | inode->i_fsnotify_mask = 0; | 197 | inode->i_fsnotify_mask = 0; |
| 199 | #endif | 198 | #endif |
| 200 | 199 | ||
| 201 | return inode; | 200 | return 0; |
| 202 | 201 | ||
| 203 | out_free_security: | 202 | out_free_security: |
| 204 | security_inode_free(inode); | 203 | security_inode_free(inode); |
| 205 | out_free_inode: | 204 | out: |
| 206 | if (inode->i_sb->s_op->destroy_inode) | 205 | return -ENOMEM; |
| 207 | inode->i_sb->s_op->destroy_inode(inode); | ||
| 208 | else | ||
| 209 | kmem_cache_free(inode_cachep, (inode)); | ||
| 210 | return NULL; | ||
| 211 | } | 206 | } |
| 212 | EXPORT_SYMBOL(inode_init_always); | 207 | EXPORT_SYMBOL(inode_init_always); |
| 213 | 208 | ||
| @@ -220,12 +215,21 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
| 220 | else | 215 | else |
| 221 | inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL); | 216 | inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL); |
| 222 | 217 | ||
| 223 | if (inode) | 218 | if (!inode) |
| 224 | return inode_init_always(sb, inode); | 219 | return NULL; |
| 225 | return NULL; | 220 | |
| 221 | if (unlikely(inode_init_always(sb, inode))) { | ||
| 222 | if (inode->i_sb->s_op->destroy_inode) | ||
| 223 | inode->i_sb->s_op->destroy_inode(inode); | ||
| 224 | else | ||
| 225 | kmem_cache_free(inode_cachep, inode); | ||
| 226 | return NULL; | ||
| 227 | } | ||
| 228 | |||
| 229 | return inode; | ||
| 226 | } | 230 | } |
| 227 | 231 | ||
| 228 | void destroy_inode(struct inode *inode) | 232 | void __destroy_inode(struct inode *inode) |
| 229 | { | 233 | { |
| 230 | BUG_ON(inode_has_buffers(inode)); | 234 | BUG_ON(inode_has_buffers(inode)); |
| 231 | ima_inode_free(inode); | 235 | ima_inode_free(inode); |
| @@ -237,13 +241,17 @@ void destroy_inode(struct inode *inode) | |||
| 237 | if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED) | 241 | if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED) |
| 238 | posix_acl_release(inode->i_default_acl); | 242 | posix_acl_release(inode->i_default_acl); |
| 239 | #endif | 243 | #endif |
| 244 | } | ||
| 245 | EXPORT_SYMBOL(__destroy_inode); | ||
| 246 | |||
| 247 | void destroy_inode(struct inode *inode) | ||
| 248 | { | ||
| 249 | __destroy_inode(inode); | ||
| 240 | if (inode->i_sb->s_op->destroy_inode) | 250 | if (inode->i_sb->s_op->destroy_inode) |
| 241 | inode->i_sb->s_op->destroy_inode(inode); | 251 | inode->i_sb->s_op->destroy_inode(inode); |
| 242 | else | 252 | else |
| 243 | kmem_cache_free(inode_cachep, (inode)); | 253 | kmem_cache_free(inode_cachep, (inode)); |
| 244 | } | 254 | } |
| 245 | EXPORT_SYMBOL(destroy_inode); | ||
| 246 | |||
| 247 | 255 | ||
| 248 | /* | 256 | /* |
| 249 | * These are initializations that only need to be done | 257 | * These are initializations that only need to be done |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 58a7963e168a..85f96bc651c7 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
| @@ -142,6 +142,7 @@ static const struct dentry_operations isofs_dentry_ops[] = { | |||
| 142 | 142 | ||
| 143 | struct iso9660_options{ | 143 | struct iso9660_options{ |
| 144 | unsigned int rock:1; | 144 | unsigned int rock:1; |
| 145 | unsigned int joliet:1; | ||
| 145 | unsigned int cruft:1; | 146 | unsigned int cruft:1; |
| 146 | unsigned int hide:1; | 147 | unsigned int hide:1; |
| 147 | unsigned int showassoc:1; | 148 | unsigned int showassoc:1; |
| @@ -151,7 +152,6 @@ struct iso9660_options{ | |||
| 151 | unsigned int gid_set:1; | 152 | unsigned int gid_set:1; |
| 152 | unsigned int utf8:1; | 153 | unsigned int utf8:1; |
| 153 | unsigned char map; | 154 | unsigned char map; |
| 154 | char joliet; | ||
| 155 | unsigned char check; | 155 | unsigned char check; |
| 156 | unsigned int blocksize; | 156 | unsigned int blocksize; |
| 157 | mode_t fmode; | 157 | mode_t fmode; |
| @@ -632,7 +632,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) | |||
| 632 | else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) { | 632 | else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) { |
| 633 | sec = (struct iso_supplementary_descriptor *)vdp; | 633 | sec = (struct iso_supplementary_descriptor *)vdp; |
| 634 | if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { | 634 | if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { |
| 635 | if (opt.joliet == 'y') { | 635 | if (opt.joliet) { |
| 636 | if (sec->escape[2] == 0x40) | 636 | if (sec->escape[2] == 0x40) |
| 637 | joliet_level = 1; | 637 | joliet_level = 1; |
| 638 | else if (sec->escape[2] == 0x43) | 638 | else if (sec->escape[2] == 0x43) |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 737f7246a4b5..f96f85092d1c 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
| @@ -287,6 +287,7 @@ int journal_write_metadata_buffer(transaction_t *transaction, | |||
| 287 | struct page *new_page; | 287 | struct page *new_page; |
| 288 | unsigned int new_offset; | 288 | unsigned int new_offset; |
| 289 | struct buffer_head *bh_in = jh2bh(jh_in); | 289 | struct buffer_head *bh_in = jh2bh(jh_in); |
| 290 | journal_t *journal = transaction->t_journal; | ||
| 290 | 291 | ||
| 291 | /* | 292 | /* |
| 292 | * The buffer really shouldn't be locked: only the current committing | 293 | * The buffer really shouldn't be locked: only the current committing |
| @@ -300,6 +301,11 @@ int journal_write_metadata_buffer(transaction_t *transaction, | |||
| 300 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); | 301 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); |
| 301 | 302 | ||
| 302 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); | 303 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); |
| 304 | /* keep subsequent assertions sane */ | ||
| 305 | new_bh->b_state = 0; | ||
| 306 | init_buffer(new_bh, NULL, NULL); | ||
| 307 | atomic_set(&new_bh->b_count, 1); | ||
| 308 | new_jh = journal_add_journal_head(new_bh); /* This sleeps */ | ||
| 303 | 309 | ||
| 304 | /* | 310 | /* |
| 305 | * If a new transaction has already done a buffer copy-out, then | 311 | * If a new transaction has already done a buffer copy-out, then |
| @@ -361,14 +367,6 @@ repeat: | |||
| 361 | kunmap_atomic(mapped_data, KM_USER0); | 367 | kunmap_atomic(mapped_data, KM_USER0); |
| 362 | } | 368 | } |
| 363 | 369 | ||
| 364 | /* keep subsequent assertions sane */ | ||
| 365 | new_bh->b_state = 0; | ||
| 366 | init_buffer(new_bh, NULL, NULL); | ||
| 367 | atomic_set(&new_bh->b_count, 1); | ||
| 368 | jbd_unlock_bh_state(bh_in); | ||
| 369 | |||
| 370 | new_jh = journal_add_journal_head(new_bh); /* This sleeps */ | ||
| 371 | |||
| 372 | set_bh_page(new_bh, new_page, new_offset); | 370 | set_bh_page(new_bh, new_page, new_offset); |
| 373 | new_jh->b_transaction = NULL; | 371 | new_jh->b_transaction = NULL; |
| 374 | new_bh->b_size = jh2bh(jh_in)->b_size; | 372 | new_bh->b_size = jh2bh(jh_in)->b_size; |
| @@ -385,7 +383,11 @@ repeat: | |||
| 385 | * copying is moved to the transaction's shadow queue. | 383 | * copying is moved to the transaction's shadow queue. |
| 386 | */ | 384 | */ |
| 387 | JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); | 385 | JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); |
| 388 | journal_file_buffer(jh_in, transaction, BJ_Shadow); | 386 | spin_lock(&journal->j_list_lock); |
| 387 | __journal_file_buffer(jh_in, transaction, BJ_Shadow); | ||
| 388 | spin_unlock(&journal->j_list_lock); | ||
| 389 | jbd_unlock_bh_state(bh_in); | ||
| 390 | |||
| 389 | JBUFFER_TRACE(new_jh, "file as BJ_IO"); | 391 | JBUFFER_TRACE(new_jh, "file as BJ_IO"); |
| 390 | journal_file_buffer(new_jh, transaction, BJ_IO); | 392 | journal_file_buffer(new_jh, transaction, BJ_IO); |
| 391 | 393 | ||
| @@ -848,6 +850,12 @@ static int journal_reset(journal_t *journal) | |||
| 848 | 850 | ||
| 849 | first = be32_to_cpu(sb->s_first); | 851 | first = be32_to_cpu(sb->s_first); |
| 850 | last = be32_to_cpu(sb->s_maxlen); | 852 | last = be32_to_cpu(sb->s_maxlen); |
| 853 | if (first + JFS_MIN_JOURNAL_BLOCKS > last + 1) { | ||
| 854 | printk(KERN_ERR "JBD: Journal too short (blocks %lu-%lu).\n", | ||
| 855 | first, last); | ||
| 856 | journal_fail_superblock(journal); | ||
| 857 | return -EINVAL; | ||
| 858 | } | ||
| 851 | 859 | ||
| 852 | journal->j_first = first; | 860 | journal->j_first = first; |
| 853 | journal->j_last = last; | 861 | journal->j_last = last; |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 73242ba7c7b1..c03ac11f74be 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
| @@ -489,34 +489,15 @@ void journal_unlock_updates (journal_t *journal) | |||
| 489 | wake_up(&journal->j_wait_transaction_locked); | 489 | wake_up(&journal->j_wait_transaction_locked); |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | /* | 492 | static void warn_dirty_buffer(struct buffer_head *bh) |
| 493 | * Report any unexpected dirty buffers which turn up. Normally those | ||
| 494 | * indicate an error, but they can occur if the user is running (say) | ||
| 495 | * tune2fs to modify the live filesystem, so we need the option of | ||
| 496 | * continuing as gracefully as possible. # | ||
| 497 | * | ||
| 498 | * The caller should already hold the journal lock and | ||
| 499 | * j_list_lock spinlock: most callers will need those anyway | ||
| 500 | * in order to probe the buffer's journaling state safely. | ||
| 501 | */ | ||
| 502 | static void jbd_unexpected_dirty_buffer(struct journal_head *jh) | ||
| 503 | { | 493 | { |
| 504 | int jlist; | 494 | char b[BDEVNAME_SIZE]; |
| 505 | |||
| 506 | /* If this buffer is one which might reasonably be dirty | ||
| 507 | * --- ie. data, or not part of this journal --- then | ||
| 508 | * we're OK to leave it alone, but otherwise we need to | ||
| 509 | * move the dirty bit to the journal's own internal | ||
| 510 | * JBDDirty bit. */ | ||
| 511 | jlist = jh->b_jlist; | ||
| 512 | 495 | ||
| 513 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || | 496 | printk(KERN_WARNING |
| 514 | jlist == BJ_Shadow || jlist == BJ_Forget) { | 497 | "JBD: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). " |
| 515 | struct buffer_head *bh = jh2bh(jh); | 498 | "There's a risk of filesystem corruption in case of system " |
| 516 | 499 | "crash.\n", | |
| 517 | if (test_clear_buffer_dirty(bh)) | 500 | bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); |
| 518 | set_buffer_jbddirty(bh); | ||
| 519 | } | ||
| 520 | } | 501 | } |
| 521 | 502 | ||
| 522 | /* | 503 | /* |
| @@ -583,14 +564,16 @@ repeat: | |||
| 583 | if (jh->b_next_transaction) | 564 | if (jh->b_next_transaction) |
| 584 | J_ASSERT_JH(jh, jh->b_next_transaction == | 565 | J_ASSERT_JH(jh, jh->b_next_transaction == |
| 585 | transaction); | 566 | transaction); |
| 567 | warn_dirty_buffer(bh); | ||
| 586 | } | 568 | } |
| 587 | /* | 569 | /* |
| 588 | * In any case we need to clean the dirty flag and we must | 570 | * In any case we need to clean the dirty flag and we must |
| 589 | * do it under the buffer lock to be sure we don't race | 571 | * do it under the buffer lock to be sure we don't race |
| 590 | * with running write-out. | 572 | * with running write-out. |
| 591 | */ | 573 | */ |
| 592 | JBUFFER_TRACE(jh, "Unexpected dirty buffer"); | 574 | JBUFFER_TRACE(jh, "Journalling dirty buffer"); |
| 593 | jbd_unexpected_dirty_buffer(jh); | 575 | clear_buffer_dirty(bh); |
| 576 | set_buffer_jbddirty(bh); | ||
| 594 | } | 577 | } |
| 595 | 578 | ||
| 596 | unlock_buffer(bh); | 579 | unlock_buffer(bh); |
| @@ -826,6 +809,15 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
| 826 | J_ASSERT_JH(jh, buffer_locked(jh2bh(jh))); | 809 | J_ASSERT_JH(jh, buffer_locked(jh2bh(jh))); |
| 827 | 810 | ||
| 828 | if (jh->b_transaction == NULL) { | 811 | if (jh->b_transaction == NULL) { |
| 812 | /* | ||
| 813 | * Previous journal_forget() could have left the buffer | ||
| 814 | * with jbddirty bit set because it was being committed. When | ||
| 815 | * the commit finished, we've filed the buffer for | ||
| 816 | * checkpointing and marked it dirty. Now we are reallocating | ||
| 817 | * the buffer so the transaction freeing it must have | ||
| 818 | * committed and so it's safe to clear the dirty bit. | ||
| 819 | */ | ||
| 820 | clear_buffer_dirty(jh2bh(jh)); | ||
| 829 | jh->b_transaction = transaction; | 821 | jh->b_transaction = transaction; |
| 830 | 822 | ||
| 831 | /* first access by this transaction */ | 823 | /* first access by this transaction */ |
| @@ -1782,8 +1774,13 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) | |||
| 1782 | 1774 | ||
| 1783 | if (jh->b_cp_transaction) { | 1775 | if (jh->b_cp_transaction) { |
| 1784 | JBUFFER_TRACE(jh, "on running+cp transaction"); | 1776 | JBUFFER_TRACE(jh, "on running+cp transaction"); |
| 1777 | /* | ||
| 1778 | * We don't want to write the buffer anymore, clear the | ||
| 1779 | * bit so that we don't confuse checks in | ||
| 1780 | * __journal_file_buffer | ||
| 1781 | */ | ||
| 1782 | clear_buffer_dirty(bh); | ||
| 1785 | __journal_file_buffer(jh, transaction, BJ_Forget); | 1783 | __journal_file_buffer(jh, transaction, BJ_Forget); |
| 1786 | clear_buffer_jbddirty(bh); | ||
| 1787 | may_free = 0; | 1784 | may_free = 0; |
| 1788 | } else { | 1785 | } else { |
| 1789 | JBUFFER_TRACE(jh, "on running transaction"); | 1786 | JBUFFER_TRACE(jh, "on running transaction"); |
| @@ -2041,12 +2038,17 @@ void __journal_file_buffer(struct journal_head *jh, | |||
| 2041 | if (jh->b_transaction && jh->b_jlist == jlist) | 2038 | if (jh->b_transaction && jh->b_jlist == jlist) |
| 2042 | return; | 2039 | return; |
| 2043 | 2040 | ||
| 2044 | /* The following list of buffer states needs to be consistent | ||
| 2045 | * with __jbd_unexpected_dirty_buffer()'s handling of dirty | ||
| 2046 | * state. */ | ||
| 2047 | |||
| 2048 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || | 2041 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || |
| 2049 | jlist == BJ_Shadow || jlist == BJ_Forget) { | 2042 | jlist == BJ_Shadow || jlist == BJ_Forget) { |
| 2043 | /* | ||
| 2044 | * For metadata buffers, we track dirty bit in buffer_jbddirty | ||
| 2045 | * instead of buffer_dirty. We should not see a dirty bit set | ||
| 2046 | * here because we clear it in do_get_write_access but e.g. | ||
| 2047 | * tune2fs can modify the sb and set the dirty bit at any time | ||
| 2048 | * so we try to gracefully handle that. | ||
| 2049 | */ | ||
| 2050 | if (buffer_dirty(bh)) | ||
| 2051 | warn_dirty_buffer(bh); | ||
| 2050 | if (test_clear_buffer_dirty(bh) || | 2052 | if (test_clear_buffer_dirty(bh) || |
| 2051 | test_clear_buffer_jbddirty(bh)) | 2053 | test_clear_buffer_jbddirty(bh)) |
| 2052 | was_dirty = 1; | 2054 | was_dirty = 1; |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 18bfd5dab642..e378cb383979 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -297,6 +297,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, | |||
| 297 | unsigned int new_offset; | 297 | unsigned int new_offset; |
| 298 | struct buffer_head *bh_in = jh2bh(jh_in); | 298 | struct buffer_head *bh_in = jh2bh(jh_in); |
| 299 | struct jbd2_buffer_trigger_type *triggers; | 299 | struct jbd2_buffer_trigger_type *triggers; |
| 300 | journal_t *journal = transaction->t_journal; | ||
| 300 | 301 | ||
| 301 | /* | 302 | /* |
| 302 | * The buffer really shouldn't be locked: only the current committing | 303 | * The buffer really shouldn't be locked: only the current committing |
| @@ -310,6 +311,11 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, | |||
| 310 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); | 311 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); |
| 311 | 312 | ||
| 312 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); | 313 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); |
| 314 | /* keep subsequent assertions sane */ | ||
| 315 | new_bh->b_state = 0; | ||
| 316 | init_buffer(new_bh, NULL, NULL); | ||
| 317 | atomic_set(&new_bh->b_count, 1); | ||
| 318 | new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */ | ||
| 313 | 319 | ||
| 314 | /* | 320 | /* |
| 315 | * If a new transaction has already done a buffer copy-out, then | 321 | * If a new transaction has already done a buffer copy-out, then |
| @@ -388,14 +394,6 @@ repeat: | |||
| 388 | kunmap_atomic(mapped_data, KM_USER0); | 394 | kunmap_atomic(mapped_data, KM_USER0); |
| 389 | } | 395 | } |
| 390 | 396 | ||
| 391 | /* keep subsequent assertions sane */ | ||
| 392 | new_bh->b_state = 0; | ||
| 393 | init_buffer(new_bh, NULL, NULL); | ||
| 394 | atomic_set(&new_bh->b_count, 1); | ||
| 395 | jbd_unlock_bh_state(bh_in); | ||
| 396 | |||
| 397 | new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */ | ||
| 398 | |||
| 399 | set_bh_page(new_bh, new_page, new_offset); | 397 | set_bh_page(new_bh, new_page, new_offset); |
| 400 | new_jh->b_transaction = NULL; | 398 | new_jh->b_transaction = NULL; |
| 401 | new_bh->b_size = jh2bh(jh_in)->b_size; | 399 | new_bh->b_size = jh2bh(jh_in)->b_size; |
| @@ -412,7 +410,11 @@ repeat: | |||
| 412 | * copying is moved to the transaction's shadow queue. | 410 | * copying is moved to the transaction's shadow queue. |
| 413 | */ | 411 | */ |
| 414 | JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); | 412 | JBUFFER_TRACE(jh_in, "file as BJ_Shadow"); |
| 415 | jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow); | 413 | spin_lock(&journal->j_list_lock); |
| 414 | __jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow); | ||
| 415 | spin_unlock(&journal->j_list_lock); | ||
| 416 | jbd_unlock_bh_state(bh_in); | ||
| 417 | |||
| 416 | JBUFFER_TRACE(new_jh, "file as BJ_IO"); | 418 | JBUFFER_TRACE(new_jh, "file as BJ_IO"); |
| 417 | jbd2_journal_file_buffer(new_jh, transaction, BJ_IO); | 419 | jbd2_journal_file_buffer(new_jh, transaction, BJ_IO); |
| 418 | 420 | ||
| @@ -2410,6 +2412,7 @@ const char *jbd2_dev_to_name(dev_t device) | |||
| 2410 | int i = hash_32(device, CACHE_SIZE_BITS); | 2412 | int i = hash_32(device, CACHE_SIZE_BITS); |
| 2411 | char *ret; | 2413 | char *ret; |
| 2412 | struct block_device *bd; | 2414 | struct block_device *bd; |
| 2415 | static struct devname_cache *new_dev; | ||
| 2413 | 2416 | ||
| 2414 | rcu_read_lock(); | 2417 | rcu_read_lock(); |
| 2415 | if (devcache[i] && devcache[i]->device == device) { | 2418 | if (devcache[i] && devcache[i]->device == device) { |
| @@ -2419,20 +2422,20 @@ const char *jbd2_dev_to_name(dev_t device) | |||
| 2419 | } | 2422 | } |
| 2420 | rcu_read_unlock(); | 2423 | rcu_read_unlock(); |
| 2421 | 2424 | ||
| 2425 | new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL); | ||
| 2426 | if (!new_dev) | ||
| 2427 | return "NODEV-ALLOCFAILURE"; /* Something non-NULL */ | ||
| 2422 | spin_lock(&devname_cache_lock); | 2428 | spin_lock(&devname_cache_lock); |
| 2423 | if (devcache[i]) { | 2429 | if (devcache[i]) { |
| 2424 | if (devcache[i]->device == device) { | 2430 | if (devcache[i]->device == device) { |
| 2431 | kfree(new_dev); | ||
| 2425 | ret = devcache[i]->devname; | 2432 | ret = devcache[i]->devname; |
| 2426 | spin_unlock(&devname_cache_lock); | 2433 | spin_unlock(&devname_cache_lock); |
| 2427 | return ret; | 2434 | return ret; |
| 2428 | } | 2435 | } |
| 2429 | call_rcu(&devcache[i]->rcu, free_devcache); | 2436 | call_rcu(&devcache[i]->rcu, free_devcache); |
| 2430 | } | 2437 | } |
| 2431 | devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL); | 2438 | devcache[i] = new_dev; |
| 2432 | if (!devcache[i]) { | ||
| 2433 | spin_unlock(&devname_cache_lock); | ||
| 2434 | return "NODEV-ALLOCFAILURE"; /* Something non-NULL */ | ||
| 2435 | } | ||
| 2436 | devcache[i]->device = device; | 2439 | devcache[i]->device = device; |
| 2437 | bd = bdget(device); | 2440 | bd = bdget(device); |
| 2438 | if (bd) { | 2441 | if (bd) { |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 494501edba6b..6213ac728f30 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -499,34 +499,15 @@ void jbd2_journal_unlock_updates (journal_t *journal) | |||
| 499 | wake_up(&journal->j_wait_transaction_locked); | 499 | wake_up(&journal->j_wait_transaction_locked); |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | /* | 502 | static void warn_dirty_buffer(struct buffer_head *bh) |
| 503 | * Report any unexpected dirty buffers which turn up. Normally those | ||
| 504 | * indicate an error, but they can occur if the user is running (say) | ||
| 505 | * tune2fs to modify the live filesystem, so we need the option of | ||
| 506 | * continuing as gracefully as possible. # | ||
| 507 | * | ||
| 508 | * The caller should already hold the journal lock and | ||
| 509 | * j_list_lock spinlock: most callers will need those anyway | ||
| 510 | * in order to probe the buffer's journaling state safely. | ||
| 511 | */ | ||
| 512 | static void jbd_unexpected_dirty_buffer(struct journal_head *jh) | ||
| 513 | { | 503 | { |
| 514 | int jlist; | 504 | char b[BDEVNAME_SIZE]; |
| 515 | |||
| 516 | /* If this buffer is one which might reasonably be dirty | ||
| 517 | * --- ie. data, or not part of this journal --- then | ||
| 518 | * we're OK to leave it alone, but otherwise we need to | ||
| 519 | * move the dirty bit to the journal's own internal | ||
| 520 | * JBDDirty bit. */ | ||
| 521 | jlist = jh->b_jlist; | ||
| 522 | 505 | ||
| 523 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || | 506 | printk(KERN_WARNING |
| 524 | jlist == BJ_Shadow || jlist == BJ_Forget) { | 507 | "JBD: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). " |
| 525 | struct buffer_head *bh = jh2bh(jh); | 508 | "There's a risk of filesystem corruption in case of system " |
| 526 | 509 | "crash.\n", | |
| 527 | if (test_clear_buffer_dirty(bh)) | 510 | bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); |
| 528 | set_buffer_jbddirty(bh); | ||
| 529 | } | ||
| 530 | } | 511 | } |
| 531 | 512 | ||
| 532 | /* | 513 | /* |
| @@ -593,14 +574,16 @@ repeat: | |||
| 593 | if (jh->b_next_transaction) | 574 | if (jh->b_next_transaction) |
| 594 | J_ASSERT_JH(jh, jh->b_next_transaction == | 575 | J_ASSERT_JH(jh, jh->b_next_transaction == |
| 595 | transaction); | 576 | transaction); |
| 577 | warn_dirty_buffer(bh); | ||
| 596 | } | 578 | } |
| 597 | /* | 579 | /* |
| 598 | * In any case we need to clean the dirty flag and we must | 580 | * In any case we need to clean the dirty flag and we must |
| 599 | * do it under the buffer lock to be sure we don't race | 581 | * do it under the buffer lock to be sure we don't race |
| 600 | * with running write-out. | 582 | * with running write-out. |
| 601 | */ | 583 | */ |
| 602 | JBUFFER_TRACE(jh, "Unexpected dirty buffer"); | 584 | JBUFFER_TRACE(jh, "Journalling dirty buffer"); |
| 603 | jbd_unexpected_dirty_buffer(jh); | 585 | clear_buffer_dirty(bh); |
| 586 | set_buffer_jbddirty(bh); | ||
| 604 | } | 587 | } |
| 605 | 588 | ||
| 606 | unlock_buffer(bh); | 589 | unlock_buffer(bh); |
| @@ -843,6 +826,15 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
| 843 | J_ASSERT_JH(jh, buffer_locked(jh2bh(jh))); | 826 | J_ASSERT_JH(jh, buffer_locked(jh2bh(jh))); |
| 844 | 827 | ||
| 845 | if (jh->b_transaction == NULL) { | 828 | if (jh->b_transaction == NULL) { |
| 829 | /* | ||
| 830 | * Previous jbd2_journal_forget() could have left the buffer | ||
| 831 | * with jbddirty bit set because it was being committed. When | ||
| 832 | * the commit finished, we've filed the buffer for | ||
| 833 | * checkpointing and marked it dirty. Now we are reallocating | ||
| 834 | * the buffer so the transaction freeing it must have | ||
| 835 | * committed and so it's safe to clear the dirty bit. | ||
| 836 | */ | ||
| 837 | clear_buffer_dirty(jh2bh(jh)); | ||
| 846 | jh->b_transaction = transaction; | 838 | jh->b_transaction = transaction; |
| 847 | 839 | ||
| 848 | /* first access by this transaction */ | 840 | /* first access by this transaction */ |
| @@ -1644,8 +1636,13 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) | |||
| 1644 | 1636 | ||
| 1645 | if (jh->b_cp_transaction) { | 1637 | if (jh->b_cp_transaction) { |
| 1646 | JBUFFER_TRACE(jh, "on running+cp transaction"); | 1638 | JBUFFER_TRACE(jh, "on running+cp transaction"); |
| 1639 | /* | ||
| 1640 | * We don't want to write the buffer anymore, clear the | ||
| 1641 | * bit so that we don't confuse checks in | ||
| 1642 | * __journal_file_buffer | ||
| 1643 | */ | ||
| 1644 | clear_buffer_dirty(bh); | ||
| 1647 | __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); | 1645 | __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); |
| 1648 | clear_buffer_jbddirty(bh); | ||
| 1649 | may_free = 0; | 1646 | may_free = 0; |
| 1650 | } else { | 1647 | } else { |
| 1651 | JBUFFER_TRACE(jh, "on running transaction"); | 1648 | JBUFFER_TRACE(jh, "on running transaction"); |
| @@ -1896,12 +1893,17 @@ void __jbd2_journal_file_buffer(struct journal_head *jh, | |||
| 1896 | if (jh->b_transaction && jh->b_jlist == jlist) | 1893 | if (jh->b_transaction && jh->b_jlist == jlist) |
| 1897 | return; | 1894 | return; |
| 1898 | 1895 | ||
| 1899 | /* The following list of buffer states needs to be consistent | ||
| 1900 | * with __jbd_unexpected_dirty_buffer()'s handling of dirty | ||
| 1901 | * state. */ | ||
| 1902 | |||
| 1903 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || | 1896 | if (jlist == BJ_Metadata || jlist == BJ_Reserved || |
| 1904 | jlist == BJ_Shadow || jlist == BJ_Forget) { | 1897 | jlist == BJ_Shadow || jlist == BJ_Forget) { |
| 1898 | /* | ||
| 1899 | * For metadata buffers, we track dirty bit in buffer_jbddirty | ||
| 1900 | * instead of buffer_dirty. We should not see a dirty bit set | ||
| 1901 | * here because we clear it in do_get_write_access but e.g. | ||
| 1902 | * tune2fs can modify the sb and set the dirty bit at any time | ||
| 1903 | * so we try to gracefully handle that. | ||
| 1904 | */ | ||
| 1905 | if (buffer_dirty(bh)) | ||
| 1906 | warn_dirty_buffer(bh); | ||
| 1905 | if (test_clear_buffer_dirty(bh) || | 1907 | if (test_clear_buffer_dirty(bh) || |
| 1906 | test_clear_buffer_jbddirty(bh)) | 1908 | test_clear_buffer_jbddirty(bh)) |
| 1907 | was_dirty = 1; | 1909 | was_dirty = 1; |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a0244740b75a..b47679be118a 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
| @@ -270,19 +270,21 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, | |||
| 270 | D2({ | 270 | D2({ |
| 271 | int i=0; | 271 | int i=0; |
| 272 | struct jffs2_raw_node_ref *this; | 272 | struct jffs2_raw_node_ref *this; |
| 273 | printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); | 273 | printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n"); |
| 274 | 274 | ||
| 275 | this = ic->nodes; | 275 | this = ic->nodes; |
| 276 | 276 | ||
| 277 | printk(KERN_DEBUG); | ||
| 277 | while(this) { | 278 | while(this) { |
| 278 | printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); | 279 | printk(KERN_CONT "0x%08x(%d)->", |
| 280 | ref_offset(this), ref_flags(this)); | ||
| 279 | if (++i == 5) { | 281 | if (++i == 5) { |
| 280 | printk("\n" KERN_DEBUG); | 282 | printk(KERN_DEBUG); |
| 281 | i=0; | 283 | i=0; |
| 282 | } | 284 | } |
| 283 | this = this->next_in_ino; | 285 | this = this->next_in_ino; |
| 284 | } | 286 | } |
| 285 | printk("\n"); | 287 | printk(KERN_CONT "\n"); |
| 286 | }); | 288 | }); |
| 287 | 289 | ||
| 288 | switch (ic->class) { | 290 | switch (ic->class) { |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 5edc2bf20581..23c947539864 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
| @@ -99,7 +99,7 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) | |||
| 99 | kunmap(pg); | 99 | kunmap(pg); |
| 100 | 100 | ||
| 101 | D2(printk(KERN_DEBUG "readpage finished\n")); | 101 | D2(printk(KERN_DEBUG "readpage finished\n")); |
| 102 | return 0; | 102 | return ret; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg) | 105 | int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg) |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 07a22caf2687..0035c021395a 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/smp_lock.h> | ||
| 15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
| 17 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 91fa3ad6e8c2..a29c7c3e3fb8 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c | |||
| @@ -67,10 +67,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) | |||
| 67 | acl = posix_acl_from_xattr(value, size); | 67 | acl = posix_acl_from_xattr(value, size); |
| 68 | } | 68 | } |
| 69 | kfree(value); | 69 | kfree(value); |
| 70 | if (!IS_ERR(acl)) { | 70 | if (!IS_ERR(acl)) |
| 71 | set_cached_acl(inode, type, acl); | 71 | set_cached_acl(inode, type, acl); |
| 72 | posix_acl_release(acl); | ||
| 73 | } | ||
| 74 | return acl; | 72 | return acl; |
| 75 | } | 73 | } |
| 76 | 74 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index ddfa89948c3f..dcec3d3ea64f 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
| @@ -217,7 +217,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name, | |||
| 217 | return PTR_ERR(s); | 217 | return PTR_ERR(s); |
| 218 | 218 | ||
| 219 | s->s_flags = MS_NOUSER; | 219 | s->s_flags = MS_NOUSER; |
| 220 | s->s_maxbytes = ~0ULL; | 220 | s->s_maxbytes = MAX_LFS_FILESIZE; |
| 221 | s->s_blocksize = PAGE_SIZE; | 221 | s->s_blocksize = PAGE_SIZE; |
| 222 | s->s_blocksize_bits = PAGE_SHIFT; | 222 | s->s_blocksize_bits = PAGE_SHIFT; |
| 223 | s->s_magic = magic; | 223 | s->s_magic = magic; |
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index f2fdcbce143e..4336adba952a 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/smp_lock.h> | ||
| 10 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 11 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 12 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 1725037374c5..bd173a6ca3b1 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/smp_lock.h> | ||
| 13 | #include <linux/in.h> | 14 | #include <linux/in.h> |
| 14 | #include <linux/sunrpc/svc.h> | 15 | #include <linux/sunrpc/svc.h> |
| 15 | #include <linux/sunrpc/clnt.h> | 16 | #include <linux/sunrpc/clnt.h> |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3688e55901fc..e1d28ddd2169 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/smp_lock.h> | ||
| 13 | #include <linux/in.h> | 14 | #include <linux/in.h> |
| 14 | #include <linux/sunrpc/svc.h> | 15 | #include <linux/sunrpc/svc.h> |
| 15 | #include <linux/sunrpc/clnt.h> | 16 | #include <linux/sunrpc/clnt.h> |
diff --git a/fs/namespace.c b/fs/namespace.c index 3dc283fd4716..7230787d18b0 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/mnt_namespace.h> | 23 | #include <linux/mnt_namespace.h> |
| 24 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
| 25 | #include <linux/nsproxy.h> | ||
| 25 | #include <linux/security.h> | 26 | #include <linux/security.h> |
| 26 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
| 27 | #include <linux/ramfs.h> | 28 | #include <linux/ramfs.h> |
| @@ -315,7 +316,8 @@ EXPORT_SYMBOL_GPL(mnt_clone_write); | |||
| 315 | */ | 316 | */ |
| 316 | int mnt_want_write_file(struct file *file) | 317 | int mnt_want_write_file(struct file *file) |
| 317 | { | 318 | { |
| 318 | if (!(file->f_mode & FMODE_WRITE)) | 319 | struct inode *inode = file->f_dentry->d_inode; |
| 320 | if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) | ||
| 319 | return mnt_want_write(file->f_path.mnt); | 321 | return mnt_want_write(file->f_path.mnt); |
| 320 | else | 322 | else |
| 321 | return mnt_clone_write(file->f_path.mnt); | 323 | return mnt_clone_write(file->f_path.mnt); |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index c2d061675d80..8d25ccb2d51d 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -1242,20 +1242,6 @@ error: | |||
| 1242 | return error; | 1242 | return error; |
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | /* | ||
| 1246 | * Initialize a session. | ||
| 1247 | * Note: save the mount rsize and wsize for create_server negotiation. | ||
| 1248 | */ | ||
| 1249 | static void nfs4_init_session(struct nfs_client *clp, | ||
| 1250 | unsigned int wsize, unsigned int rsize) | ||
| 1251 | { | ||
| 1252 | #if defined(CONFIG_NFS_V4_1) | ||
| 1253 | if (nfs4_has_session(clp)) { | ||
| 1254 | clp->cl_session->fc_attrs.max_rqst_sz = wsize; | ||
| 1255 | clp->cl_session->fc_attrs.max_resp_sz = rsize; | ||
| 1256 | } | ||
| 1257 | #endif /* CONFIG_NFS_V4_1 */ | ||
| 1258 | } | ||
| 1259 | 1245 | ||
| 1260 | /* | 1246 | /* |
| 1261 | * Session has been established, and the client marked ready. | 1247 | * Session has been established, and the client marked ready. |
| @@ -1350,7 +1336,9 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
| 1350 | BUG_ON(!server->nfs_client->rpc_ops); | 1336 | BUG_ON(!server->nfs_client->rpc_ops); |
| 1351 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1337 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
| 1352 | 1338 | ||
| 1353 | nfs4_init_session(server->nfs_client, server->wsize, server->rsize); | 1339 | error = nfs4_init_session(server); |
| 1340 | if (error < 0) | ||
| 1341 | goto error; | ||
| 1354 | 1342 | ||
| 1355 | /* Probe the root fh to retrieve its FSID */ | 1343 | /* Probe the root fh to retrieve its FSID */ |
| 1356 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); | 1344 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index af05b918cb5b..6dd48a4405b4 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/kthread.h> | 10 | #include <linux/kthread.h> |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
| 13 | #include <linux/smp_lock.h> | ||
| 13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
| 14 | 15 | ||
| 15 | #include <linux/nfs4.h> | 16 | #include <linux/nfs4.h> |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 89f98e9a024b..32062c33c859 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <linux/nfs_fs.h> | 29 | #include <linux/nfs_fs.h> |
| 30 | #include <linux/nfs_mount.h> | 30 | #include <linux/nfs_mount.h> |
| 31 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
| 32 | #include <linux/smp_lock.h> | ||
| 33 | #include <linux/pagevec.h> | 32 | #include <linux/pagevec.h> |
| 34 | #include <linux/namei.h> | 33 | #include <linux/namei.h> |
| 35 | #include <linux/mount.h> | 34 | #include <linux/mount.h> |
| @@ -1026,12 +1025,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
| 1026 | res = NULL; | 1025 | res = NULL; |
| 1027 | goto out; | 1026 | goto out; |
| 1028 | /* This turned out not to be a regular file */ | 1027 | /* This turned out not to be a regular file */ |
| 1029 | case -EISDIR: | ||
| 1030 | case -ENOTDIR: | 1028 | case -ENOTDIR: |
| 1031 | goto no_open; | 1029 | goto no_open; |
| 1032 | case -ELOOP: | 1030 | case -ELOOP: |
| 1033 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1031 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
| 1034 | goto no_open; | 1032 | goto no_open; |
| 1033 | /* case -EISDIR: */ | ||
| 1035 | /* case -EINVAL: */ | 1034 | /* case -EINVAL: */ |
| 1036 | default: | 1035 | default: |
| 1037 | goto out; | 1036 | goto out; |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 489fc01a3204..e4e089a8f294 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -255,7 +255,7 @@ static void nfs_direct_read_release(void *calldata) | |||
| 255 | 255 | ||
| 256 | if (put_dreq(dreq)) | 256 | if (put_dreq(dreq)) |
| 257 | nfs_direct_complete(dreq); | 257 | nfs_direct_complete(dreq); |
| 258 | nfs_readdata_release(calldata); | 258 | nfs_readdata_free(data); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | static const struct rpc_call_ops nfs_read_direct_ops = { | 261 | static const struct rpc_call_ops nfs_read_direct_ops = { |
| @@ -314,14 +314,14 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
| 314 | data->npages, 1, 0, data->pagevec, NULL); | 314 | data->npages, 1, 0, data->pagevec, NULL); |
| 315 | up_read(¤t->mm->mmap_sem); | 315 | up_read(¤t->mm->mmap_sem); |
| 316 | if (result < 0) { | 316 | if (result < 0) { |
| 317 | nfs_readdata_release(data); | 317 | nfs_readdata_free(data); |
| 318 | break; | 318 | break; |
| 319 | } | 319 | } |
| 320 | if ((unsigned)result < data->npages) { | 320 | if ((unsigned)result < data->npages) { |
| 321 | bytes = result * PAGE_SIZE; | 321 | bytes = result * PAGE_SIZE; |
| 322 | if (bytes <= pgbase) { | 322 | if (bytes <= pgbase) { |
| 323 | nfs_direct_release_pages(data->pagevec, result); | 323 | nfs_direct_release_pages(data->pagevec, result); |
| 324 | nfs_readdata_release(data); | 324 | nfs_readdata_free(data); |
| 325 | break; | 325 | break; |
| 326 | } | 326 | } |
| 327 | bytes -= pgbase; | 327 | bytes -= pgbase; |
| @@ -334,7 +334,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
| 334 | data->inode = inode; | 334 | data->inode = inode; |
| 335 | data->cred = msg.rpc_cred; | 335 | data->cred = msg.rpc_cred; |
| 336 | data->args.fh = NFS_FH(inode); | 336 | data->args.fh = NFS_FH(inode); |
| 337 | data->args.context = get_nfs_open_context(ctx); | 337 | data->args.context = ctx; |
| 338 | data->args.offset = pos; | 338 | data->args.offset = pos; |
| 339 | data->args.pgbase = pgbase; | 339 | data->args.pgbase = pgbase; |
| 340 | data->args.pages = data->pagevec; | 340 | data->args.pages = data->pagevec; |
| @@ -441,7 +441,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq) | |||
| 441 | struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages); | 441 | struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages); |
| 442 | list_del(&data->pages); | 442 | list_del(&data->pages); |
| 443 | nfs_direct_release_pages(data->pagevec, data->npages); | 443 | nfs_direct_release_pages(data->pagevec, data->npages); |
| 444 | nfs_writedata_release(data); | 444 | nfs_writedata_free(data); |
| 445 | } | 445 | } |
| 446 | } | 446 | } |
| 447 | 447 | ||
| @@ -534,7 +534,7 @@ static void nfs_direct_commit_release(void *calldata) | |||
| 534 | 534 | ||
| 535 | dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status); | 535 | dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status); |
| 536 | nfs_direct_write_complete(dreq, data->inode); | 536 | nfs_direct_write_complete(dreq, data->inode); |
| 537 | nfs_commitdata_release(calldata); | 537 | nfs_commit_free(data); |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | static const struct rpc_call_ops nfs_commit_direct_ops = { | 540 | static const struct rpc_call_ops nfs_commit_direct_ops = { |
| @@ -570,7 +570,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
| 570 | data->args.fh = NFS_FH(data->inode); | 570 | data->args.fh = NFS_FH(data->inode); |
| 571 | data->args.offset = 0; | 571 | data->args.offset = 0; |
| 572 | data->args.count = 0; | 572 | data->args.count = 0; |
| 573 | data->args.context = get_nfs_open_context(dreq->ctx); | 573 | data->args.context = dreq->ctx; |
| 574 | data->res.count = 0; | 574 | data->res.count = 0; |
| 575 | data->res.fattr = &data->fattr; | 575 | data->res.fattr = &data->fattr; |
| 576 | data->res.verf = &data->verf; | 576 | data->res.verf = &data->verf; |
| @@ -734,14 +734,14 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
| 734 | data->npages, 0, 0, data->pagevec, NULL); | 734 | data->npages, 0, 0, data->pagevec, NULL); |
| 735 | up_read(¤t->mm->mmap_sem); | 735 | up_read(¤t->mm->mmap_sem); |
| 736 | if (result < 0) { | 736 | if (result < 0) { |
| 737 | nfs_writedata_release(data); | 737 | nfs_writedata_free(data); |
| 738 | break; | 738 | break; |
| 739 | } | 739 | } |
| 740 | if ((unsigned)result < data->npages) { | 740 | if ((unsigned)result < data->npages) { |
| 741 | bytes = result * PAGE_SIZE; | 741 | bytes = result * PAGE_SIZE; |
| 742 | if (bytes <= pgbase) { | 742 | if (bytes <= pgbase) { |
| 743 | nfs_direct_release_pages(data->pagevec, result); | 743 | nfs_direct_release_pages(data->pagevec, result); |
| 744 | nfs_writedata_release(data); | 744 | nfs_writedata_free(data); |
| 745 | break; | 745 | break; |
| 746 | } | 746 | } |
| 747 | bytes -= pgbase; | 747 | bytes -= pgbase; |
| @@ -756,7 +756,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
| 756 | data->inode = inode; | 756 | data->inode = inode; |
| 757 | data->cred = msg.rpc_cred; | 757 | data->cred = msg.rpc_cred; |
| 758 | data->args.fh = NFS_FH(inode); | 758 | data->args.fh = NFS_FH(inode); |
| 759 | data->args.context = get_nfs_open_context(ctx); | 759 | data->args.context = ctx; |
| 760 | data->args.offset = pos; | 760 | data->args.offset = pos; |
| 761 | data->args.pgbase = pgbase; | 761 | data->args.pgbase = pgbase; |
| 762 | data->args.pages = data->pagevec; | 762 | data->args.pages = data->pagevec; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 0055b813ec2c..05062329b678 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/pagemap.h> | 28 | #include <linux/pagemap.h> |
| 29 | #include <linux/smp_lock.h> | ||
| 30 | #include <linux/aio.h> | 29 | #include <linux/aio.h> |
| 31 | 30 | ||
| 32 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 46177cb87064..b35d2a616066 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/nfs_idmap.h> | 30 | #include <linux/nfs_idmap.h> |
| 31 | #include <linux/vfs.h> | 31 | #include <linux/vfs.h> |
| 32 | #include <linux/namei.h> | 32 | #include <linux/namei.h> |
| 33 | #include <linux/mnt_namespace.h> | ||
| 34 | #include <linux/security.h> | 33 | #include <linux/security.h> |
| 35 | 34 | ||
| 36 | #include <asm/system.h> | 35 | #include <asm/system.h> |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 64f87194d390..bd7938eda6a8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <linux/nfs_mount.h> | 30 | #include <linux/nfs_mount.h> |
| 31 | #include <linux/nfs4_mount.h> | 31 | #include <linux/nfs4_mount.h> |
| 32 | #include <linux/lockd/bind.h> | 32 | #include <linux/lockd/bind.h> |
| 33 | #include <linux/smp_lock.h> | ||
| 34 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 35 | #include <linux/mount.h> | 34 | #include <linux/mount.h> |
| 36 | #include <linux/nfs_idmap.h> | 35 | #include <linux/nfs_idmap.h> |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 61bc3a32e1e2..6ea07a3c75d4 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -220,6 +220,7 @@ extern void nfs4_destroy_session(struct nfs4_session *session); | |||
| 220 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); | 220 | extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp); |
| 221 | extern int nfs4_proc_create_session(struct nfs_client *, int reset); | 221 | extern int nfs4_proc_create_session(struct nfs_client *, int reset); |
| 222 | extern int nfs4_proc_destroy_session(struct nfs4_session *); | 222 | extern int nfs4_proc_destroy_session(struct nfs4_session *); |
| 223 | extern int nfs4_init_session(struct nfs_server *server); | ||
| 223 | #else /* CONFIG_NFS_v4_1 */ | 224 | #else /* CONFIG_NFS_v4_1 */ |
| 224 | static inline int nfs4_setup_sequence(struct nfs_client *clp, | 225 | static inline int nfs4_setup_sequence(struct nfs_client *clp, |
| 225 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 226 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
| @@ -227,6 +228,11 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp, | |||
| 227 | { | 228 | { |
| 228 | return 0; | 229 | return 0; |
| 229 | } | 230 | } |
| 231 | |||
| 232 | static inline int nfs4_init_session(struct nfs_server *server) | ||
| 233 | { | ||
| 234 | return 0; | ||
| 235 | } | ||
| 230 | #endif /* CONFIG_NFS_V4_1 */ | 236 | #endif /* CONFIG_NFS_V4_1 */ |
| 231 | 237 | ||
| 232 | extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; | 238 | extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 92ce43517814..6917311f201c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -45,7 +45,6 @@ | |||
| 45 | #include <linux/nfs4.h> | 45 | #include <linux/nfs4.h> |
| 46 | #include <linux/nfs_fs.h> | 46 | #include <linux/nfs_fs.h> |
| 47 | #include <linux/nfs_page.h> | 47 | #include <linux/nfs_page.h> |
| 48 | #include <linux/smp_lock.h> | ||
| 49 | #include <linux/namei.h> | 48 | #include <linux/namei.h> |
| 50 | #include <linux/mount.h> | 49 | #include <linux/mount.h> |
| 51 | #include <linux/module.h> | 50 | #include <linux/module.h> |
| @@ -2041,15 +2040,9 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2041 | .rpc_argp = &args, | 2040 | .rpc_argp = &args, |
| 2042 | .rpc_resp = &res, | 2041 | .rpc_resp = &res, |
| 2043 | }; | 2042 | }; |
| 2044 | int status; | ||
| 2045 | 2043 | ||
| 2046 | nfs_fattr_init(info->fattr); | 2044 | nfs_fattr_init(info->fattr); |
| 2047 | status = nfs4_recover_expired_lease(server); | 2045 | return nfs4_call_sync(server, &msg, &args, &res, 0); |
| 2048 | if (!status) | ||
| 2049 | status = nfs4_check_client_ready(server->nfs_client); | ||
| 2050 | if (!status) | ||
| 2051 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | ||
| 2052 | return status; | ||
| 2053 | } | 2046 | } |
| 2054 | 2047 | ||
| 2055 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2048 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
| @@ -4100,15 +4093,23 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) | |||
| 4100 | if (request->fl_start < 0 || request->fl_end < 0) | 4093 | if (request->fl_start < 0 || request->fl_end < 0) |
| 4101 | return -EINVAL; | 4094 | return -EINVAL; |
| 4102 | 4095 | ||
| 4103 | if (IS_GETLK(cmd)) | 4096 | if (IS_GETLK(cmd)) { |
| 4104 | return nfs4_proc_getlk(state, F_GETLK, request); | 4097 | if (state != NULL) |
| 4098 | return nfs4_proc_getlk(state, F_GETLK, request); | ||
| 4099 | return 0; | ||
| 4100 | } | ||
| 4105 | 4101 | ||
| 4106 | if (!(IS_SETLK(cmd) || IS_SETLKW(cmd))) | 4102 | if (!(IS_SETLK(cmd) || IS_SETLKW(cmd))) |
| 4107 | return -EINVAL; | 4103 | return -EINVAL; |
| 4108 | 4104 | ||
| 4109 | if (request->fl_type == F_UNLCK) | 4105 | if (request->fl_type == F_UNLCK) { |
| 4110 | return nfs4_proc_unlck(state, cmd, request); | 4106 | if (state != NULL) |
| 4107 | return nfs4_proc_unlck(state, cmd, request); | ||
| 4108 | return 0; | ||
| 4109 | } | ||
| 4111 | 4110 | ||
| 4111 | if (state == NULL) | ||
| 4112 | return -ENOLCK; | ||
| 4112 | do { | 4113 | do { |
| 4113 | status = nfs4_proc_setlk(state, cmd, request); | 4114 | status = nfs4_proc_setlk(state, cmd, request); |
| 4114 | if ((status != -EAGAIN) || IS_SETLK(cmd)) | 4115 | if ((status != -EAGAIN) || IS_SETLK(cmd)) |
| @@ -4794,6 +4795,22 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
| 4794 | return status; | 4795 | return status; |
| 4795 | } | 4796 | } |
| 4796 | 4797 | ||
| 4798 | int nfs4_init_session(struct nfs_server *server) | ||
| 4799 | { | ||
| 4800 | struct nfs_client *clp = server->nfs_client; | ||
| 4801 | int ret; | ||
| 4802 | |||
| 4803 | if (!nfs4_has_session(clp)) | ||
| 4804 | return 0; | ||
| 4805 | |||
| 4806 | clp->cl_session->fc_attrs.max_rqst_sz = server->wsize; | ||
| 4807 | clp->cl_session->fc_attrs.max_resp_sz = server->rsize; | ||
| 4808 | ret = nfs4_recover_expired_lease(server); | ||
| 4809 | if (!ret) | ||
| 4810 | ret = nfs4_check_client_ready(clp); | ||
| 4811 | return ret; | ||
| 4812 | } | ||
| 4813 | |||
| 4797 | /* | 4814 | /* |
| 4798 | * Renew the cl_session lease. | 4815 | * Renew the cl_session lease. |
| 4799 | */ | 4816 | */ |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index b73c5a728655..65ca8c18476f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -553,6 +553,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
| 553 | INIT_LIST_HEAD(&lsp->ls_sequence.list); | 553 | INIT_LIST_HEAD(&lsp->ls_sequence.list); |
| 554 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | 554 | lsp->ls_seqid.sequence = &lsp->ls_sequence; |
| 555 | atomic_set(&lsp->ls_count, 1); | 555 | atomic_set(&lsp->ls_count, 1); |
| 556 | lsp->ls_state = state; | ||
| 556 | lsp->ls_owner = fl_owner; | 557 | lsp->ls_owner = fl_owner; |
| 557 | spin_lock(&clp->cl_lock); | 558 | spin_lock(&clp->cl_lock); |
| 558 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); | 559 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); |
| @@ -587,7 +588,6 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
| 587 | if (lsp != NULL) | 588 | if (lsp != NULL) |
| 588 | break; | 589 | break; |
| 589 | if (new != NULL) { | 590 | if (new != NULL) { |
| 590 | new->ls_state = state; | ||
| 591 | list_add(&new->ls_locks, &state->lock_states); | 591 | list_add(&new->ls_locks, &state->lock_states); |
| 592 | set_bit(LK_STATE_IN_USE, &state->flags); | 592 | set_bit(LK_STATE_IN_USE, &state->flags); |
| 593 | lsp = new; | 593 | lsp = new; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 96c4ebfa46f4..12c9e66d3f1d 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <linux/sunrpc/clnt.h> | 18 | #include <linux/sunrpc/clnt.h> |
| 19 | #include <linux/nfs_fs.h> | 19 | #include <linux/nfs_fs.h> |
| 20 | #include <linux/nfs_page.h> | 20 | #include <linux/nfs_page.h> |
| 21 | #include <linux/smp_lock.h> | ||
| 22 | 21 | ||
| 23 | #include <asm/system.h> | 22 | #include <asm/system.h> |
| 24 | 23 | ||
| @@ -61,17 +60,15 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
| 61 | return p; | 60 | return p; |
| 62 | } | 61 | } |
| 63 | 62 | ||
| 64 | static void nfs_readdata_free(struct nfs_read_data *p) | 63 | void nfs_readdata_free(struct nfs_read_data *p) |
| 65 | { | 64 | { |
| 66 | if (p && (p->pagevec != &p->page_array[0])) | 65 | if (p && (p->pagevec != &p->page_array[0])) |
| 67 | kfree(p->pagevec); | 66 | kfree(p->pagevec); |
| 68 | mempool_free(p, nfs_rdata_mempool); | 67 | mempool_free(p, nfs_rdata_mempool); |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | void nfs_readdata_release(void *data) | 70 | static void nfs_readdata_release(struct nfs_read_data *rdata) |
| 72 | { | 71 | { |
| 73 | struct nfs_read_data *rdata = data; | ||
| 74 | |||
| 75 | put_nfs_open_context(rdata->args.context); | 72 | put_nfs_open_context(rdata->args.context); |
| 76 | nfs_readdata_free(rdata); | 73 | nfs_readdata_free(rdata); |
| 77 | } | 74 | } |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ce728829f79a..a34fae21fe10 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -87,17 +87,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
| 87 | return p; | 87 | return p; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static void nfs_writedata_free(struct nfs_write_data *p) | 90 | void nfs_writedata_free(struct nfs_write_data *p) |
| 91 | { | 91 | { |
| 92 | if (p && (p->pagevec != &p->page_array[0])) | 92 | if (p && (p->pagevec != &p->page_array[0])) |
| 93 | kfree(p->pagevec); | 93 | kfree(p->pagevec); |
| 94 | mempool_free(p, nfs_wdata_mempool); | 94 | mempool_free(p, nfs_wdata_mempool); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | void nfs_writedata_release(void *data) | 97 | static void nfs_writedata_release(struct nfs_write_data *wdata) |
| 98 | { | 98 | { |
| 99 | struct nfs_write_data *wdata = data; | ||
| 100 | |||
| 101 | put_nfs_open_context(wdata->args.context); | 99 | put_nfs_open_context(wdata->args.context); |
| 102 | nfs_writedata_free(wdata); | 100 | nfs_writedata_free(wdata); |
| 103 | } | 101 | } |
| @@ -202,8 +200,10 @@ static int nfs_set_page_writeback(struct page *page) | |||
| 202 | struct nfs_server *nfss = NFS_SERVER(inode); | 200 | struct nfs_server *nfss = NFS_SERVER(inode); |
| 203 | 201 | ||
| 204 | if (atomic_long_inc_return(&nfss->writeback) > | 202 | if (atomic_long_inc_return(&nfss->writeback) > |
| 205 | NFS_CONGESTION_ON_THRESH) | 203 | NFS_CONGESTION_ON_THRESH) { |
| 206 | set_bdi_congested(&nfss->backing_dev_info, WRITE); | 204 | set_bdi_congested(&nfss->backing_dev_info, |
| 205 | BLK_RW_ASYNC); | ||
| 206 | } | ||
| 207 | } | 207 | } |
| 208 | return ret; | 208 | return ret; |
| 209 | } | 209 | } |
| @@ -215,7 +215,7 @@ static void nfs_end_page_writeback(struct page *page) | |||
| 215 | 215 | ||
| 216 | end_page_writeback(page); | 216 | end_page_writeback(page); |
| 217 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) | 217 | if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
| 218 | clear_bdi_congested(&nfss->backing_dev_info, WRITE); | 218 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* | 221 | /* |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 1250fb978ac1..6d0847562d87 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/inet.h> | 26 | #include <linux/inet.h> |
| 27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 28 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
| 30 | 29 | ||
| 31 | #include <linux/nfs.h> | 30 | #include <linux/nfs.h> |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index d4c9884cd54b..492c79b7800b 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <linux/unistd.h> | 18 | #include <linux/unistd.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
| 21 | #include <linux/smp_lock.h> | ||
| 22 | #include <linux/freezer.h> | 21 | #include <linux/freezer.h> |
| 23 | #include <linux/fs_struct.h> | 22 | #include <linux/fs_struct.h> |
| 24 | #include <linux/kthread.h> | 23 | #include <linux/kthread.h> |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4145083dcf88..23341c1063bc 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -678,7 +678,6 @@ __be32 | |||
| 678 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | 678 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, |
| 679 | int access, struct file **filp) | 679 | int access, struct file **filp) |
| 680 | { | 680 | { |
| 681 | const struct cred *cred = current_cred(); | ||
| 682 | struct dentry *dentry; | 681 | struct dentry *dentry; |
| 683 | struct inode *inode; | 682 | struct inode *inode; |
| 684 | int flags = O_RDONLY|O_LARGEFILE; | 683 | int flags = O_RDONLY|O_LARGEFILE; |
| @@ -733,7 +732,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 733 | vfs_dq_init(inode); | 732 | vfs_dq_init(inode); |
| 734 | } | 733 | } |
| 735 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), | 734 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), |
| 736 | flags, cred); | 735 | flags, current_cred()); |
| 737 | if (IS_ERR(*filp)) | 736 | if (IS_ERR(*filp)) |
| 738 | host_err = PTR_ERR(*filp); | 737 | host_err = PTR_ERR(*filp); |
| 739 | else | 738 | else |
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig new file mode 100644 index 000000000000..72da095d4009 --- /dev/null +++ b/fs/nilfs2/Kconfig | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | config NILFS2_FS | ||
| 2 | tristate "NILFS2 file system support (EXPERIMENTAL)" | ||
| 3 | depends on BLOCK && EXPERIMENTAL | ||
| 4 | select CRC32 | ||
| 5 | help | ||
| 6 | NILFS2 is a log-structured file system (LFS) supporting continuous | ||
| 7 | snapshotting. In addition to versioning capability of the entire | ||
| 8 | file system, users can even restore files mistakenly overwritten or | ||
| 9 | destroyed just a few seconds ago. Since this file system can keep | ||
| 10 | consistency like conventional LFS, it achieves quick recovery after | ||
| 11 | system crashes. | ||
| 12 | |||
| 13 | NILFS2 creates a number of checkpoints every few seconds or per | ||
| 14 | synchronous write basis (unless there is no change). Users can | ||
| 15 | select significant versions among continuously created checkpoints, | ||
| 16 | and can change them into snapshots which will be preserved for long | ||
| 17 | periods until they are changed back to checkpoints. Each | ||
| 18 | snapshot is mountable as a read-only file system concurrently with | ||
| 19 | its writable mount, and this feature is convenient for online backup. | ||
| 20 | |||
| 21 | Some features including atime, extended attributes, and POSIX ACLs, | ||
| 22 | are not supported yet. | ||
| 23 | |||
| 24 | To compile this file system support as a module, choose M here: the | ||
| 25 | module will be called nilfs2. If unsure, say N. | ||
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 36df60b6d8a4..99d58a028b94 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
| @@ -568,6 +568,7 @@ void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap, | |||
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | static struct lock_class_key nilfs_bmap_dat_lock_key; | 570 | static struct lock_class_key nilfs_bmap_dat_lock_key; |
| 571 | static struct lock_class_key nilfs_bmap_mdt_lock_key; | ||
| 571 | 572 | ||
| 572 | /** | 573 | /** |
| 573 | * nilfs_bmap_read - read a bmap from an inode | 574 | * nilfs_bmap_read - read a bmap from an inode |
| @@ -603,7 +604,11 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) | |||
| 603 | bmap->b_ptr_type = NILFS_BMAP_PTR_VS; | 604 | bmap->b_ptr_type = NILFS_BMAP_PTR_VS; |
| 604 | bmap->b_last_allocated_key = 0; | 605 | bmap->b_last_allocated_key = 0; |
| 605 | bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; | 606 | bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; |
| 607 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); | ||
| 606 | break; | 608 | break; |
| 609 | case NILFS_IFILE_INO: | ||
| 610 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); | ||
| 611 | /* Fall through */ | ||
| 607 | default: | 612 | default: |
| 608 | bmap->b_ptr_type = NILFS_BMAP_PTR_VM; | 613 | bmap->b_ptr_type = NILFS_BMAP_PTR_VM; |
| 609 | bmap->b_last_allocated_key = 0; | 614 | bmap->b_last_allocated_key = 0; |
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 7d49813f66d6..aec942cf79e3 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c | |||
| @@ -307,7 +307,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, | |||
| 307 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); | 307 | ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh); |
| 308 | if (ret < 0) { | 308 | if (ret < 0) { |
| 309 | if (ret != -ENOENT) | 309 | if (ret != -ENOENT) |
| 310 | goto out_header; | 310 | break; |
| 311 | /* skip hole */ | 311 | /* skip hole */ |
| 312 | ret = 0; | 312 | ret = 0; |
| 313 | continue; | 313 | continue; |
| @@ -340,7 +340,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, | |||
| 340 | continue; | 340 | continue; |
| 341 | printk(KERN_ERR "%s: cannot delete block\n", | 341 | printk(KERN_ERR "%s: cannot delete block\n", |
| 342 | __func__); | 342 | __func__); |
| 343 | goto out_header; | 343 | break; |
| 344 | } | 344 | } |
| 345 | } | 345 | } |
| 346 | 346 | ||
| @@ -358,7 +358,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, | |||
| 358 | kunmap_atomic(kaddr, KM_USER0); | 358 | kunmap_atomic(kaddr, KM_USER0); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | out_header: | ||
| 362 | brelse(header_bh); | 361 | brelse(header_bh); |
| 363 | 362 | ||
| 364 | out_sem: | 363 | out_sem: |
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 0b2710e2d565..8927ca27e6f7 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c | |||
| @@ -134,15 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, | |||
| 134 | entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, | 134 | entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, |
| 135 | req->pr_entry_bh, kaddr); | 135 | req->pr_entry_bh, kaddr); |
| 136 | entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat)); | 136 | entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat)); |
| 137 | if (entry->de_blocknr != cpu_to_le64(0) || | ||
| 138 | entry->de_end != cpu_to_le64(NILFS_CNO_MAX)) { | ||
| 139 | printk(KERN_CRIT | ||
| 140 | "%s: vbn = %llu, start = %llu, end = %llu, pbn = %llu\n", | ||
| 141 | __func__, (unsigned long long)req->pr_entry_nr, | ||
| 142 | (unsigned long long)le64_to_cpu(entry->de_start), | ||
| 143 | (unsigned long long)le64_to_cpu(entry->de_end), | ||
| 144 | (unsigned long long)le64_to_cpu(entry->de_blocknr)); | ||
| 145 | } | ||
| 146 | entry->de_blocknr = cpu_to_le64(blocknr); | 137 | entry->de_blocknr = cpu_to_le64(blocknr); |
| 147 | kunmap_atomic(kaddr, KM_USER0); | 138 | kunmap_atomic(kaddr, KM_USER0); |
| 148 | 139 | ||
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 54100acc1102..1a4fa04cf071 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
| @@ -43,7 +43,6 @@ | |||
| 43 | */ | 43 | */ |
| 44 | 44 | ||
| 45 | #include <linux/pagemap.h> | 45 | #include <linux/pagemap.h> |
| 46 | #include <linux/smp_lock.h> | ||
| 47 | #include "nilfs.h" | 46 | #include "nilfs.h" |
| 48 | #include "page.h" | 47 | #include "page.h" |
| 49 | 48 | ||
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 3d3ddb3f5177..2dfd47714ae5 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
| @@ -412,8 +412,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) | |||
| 412 | return 0; /* Do not request flush for shadow page cache */ | 412 | return 0; /* Do not request flush for shadow page cache */ |
| 413 | if (!sb) { | 413 | if (!sb) { |
| 414 | writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); | 414 | writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs); |
| 415 | if (!writer) | 415 | if (!writer) { |
| 416 | nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs); | ||
| 416 | return -EROFS; | 417 | return -EROFS; |
| 418 | } | ||
| 417 | sb = writer->s_super; | 419 | sb = writer->s_super; |
| 418 | } | 420 | } |
| 419 | 421 | ||
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index aa977549919e..51ff3d0a4ee2 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -1829,26 +1829,13 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci, | |||
| 1829 | err = nilfs_segbuf_write(segbuf, &wi); | 1829 | err = nilfs_segbuf_write(segbuf, &wi); |
| 1830 | 1830 | ||
| 1831 | res = nilfs_segbuf_wait(segbuf, &wi); | 1831 | res = nilfs_segbuf_wait(segbuf, &wi); |
| 1832 | err = unlikely(err) ? : res; | 1832 | err = err ? : res; |
| 1833 | if (unlikely(err)) | 1833 | if (err) |
| 1834 | return err; | 1834 | return err; |
| 1835 | } | 1835 | } |
| 1836 | return 0; | 1836 | return 0; |
| 1837 | } | 1837 | } |
| 1838 | 1838 | ||
| 1839 | static int nilfs_page_has_uncleared_buffer(struct page *page) | ||
| 1840 | { | ||
| 1841 | struct buffer_head *head, *bh; | ||
| 1842 | |||
| 1843 | head = bh = page_buffers(page); | ||
| 1844 | do { | ||
| 1845 | if (buffer_dirty(bh) && !list_empty(&bh->b_assoc_buffers)) | ||
| 1846 | return 1; | ||
| 1847 | bh = bh->b_this_page; | ||
| 1848 | } while (bh != head); | ||
| 1849 | return 0; | ||
| 1850 | } | ||
| 1851 | |||
| 1852 | static void __nilfs_end_page_io(struct page *page, int err) | 1839 | static void __nilfs_end_page_io(struct page *page, int err) |
| 1853 | { | 1840 | { |
| 1854 | if (!err) { | 1841 | if (!err) { |
| @@ -1872,13 +1859,26 @@ static void nilfs_end_page_io(struct page *page, int err) | |||
| 1872 | if (!page) | 1859 | if (!page) |
| 1873 | return; | 1860 | return; |
| 1874 | 1861 | ||
| 1875 | if (buffer_nilfs_node(page_buffers(page)) && | 1862 | if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) { |
| 1876 | nilfs_page_has_uncleared_buffer(page)) | 1863 | /* |
| 1877 | /* For b-tree node pages, this function may be called twice | 1864 | * For b-tree node pages, this function may be called twice |
| 1878 | or more because they might be split in a segment. | 1865 | * or more because they might be split in a segment. |
| 1879 | This check assures that cleanup has been done for all | 1866 | */ |
| 1880 | buffers in a split btnode page. */ | 1867 | if (PageDirty(page)) { |
| 1868 | /* | ||
| 1869 | * For pages holding split b-tree node buffers, dirty | ||
| 1870 | * flag on the buffers may be cleared discretely. | ||
| 1871 | * In that case, the page is once redirtied for | ||
| 1872 | * remaining buffers, and it must be cancelled if | ||
| 1873 | * all the buffers get cleaned later. | ||
| 1874 | */ | ||
| 1875 | lock_page(page); | ||
| 1876 | if (nilfs_page_buffers_clean(page)) | ||
| 1877 | __nilfs_clear_page_dirty(page); | ||
| 1878 | unlock_page(page); | ||
| 1879 | } | ||
| 1881 | return; | 1880 | return; |
| 1881 | } | ||
| 1882 | 1882 | ||
| 1883 | __nilfs_end_page_io(page, err); | 1883 | __nilfs_end_page_io(page, err); |
| 1884 | } | 1884 | } |
| @@ -1940,7 +1940,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci, | |||
| 1940 | } | 1940 | } |
| 1941 | if (bh->b_page != fs_page) { | 1941 | if (bh->b_page != fs_page) { |
| 1942 | nilfs_end_page_io(fs_page, err); | 1942 | nilfs_end_page_io(fs_page, err); |
| 1943 | if (unlikely(fs_page == failed_page)) | 1943 | if (fs_page && fs_page == failed_page) |
| 1944 | goto done; | 1944 | goto done; |
| 1945 | fs_page = bh->b_page; | 1945 | fs_page = bh->b_page; |
| 1946 | } | 1946 | } |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 8e2ec43b18f4..151964f0de4c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -416,8 +416,10 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
| 416 | if (unlikely(err)) | 416 | if (unlikely(err)) |
| 417 | goto failed; | 417 | goto failed; |
| 418 | 418 | ||
| 419 | down_read(&nilfs->ns_segctor_sem); | ||
| 419 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, | 420 | err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp, |
| 420 | &bh_cp); | 421 | &bh_cp); |
| 422 | up_read(&nilfs->ns_segctor_sem); | ||
| 421 | if (unlikely(err)) { | 423 | if (unlikely(err)) { |
| 422 | if (err == -ENOENT || err == -EINVAL) { | 424 | if (err == -ENOENT || err == -EINVAL) { |
| 423 | printk(KERN_ERR | 425 | printk(KERN_ERR |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index e8adbffc626f..1b9caafb8662 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -253,7 +253,7 @@ nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
| 253 | 253 | ||
| 254 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) | 254 | static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi) |
| 255 | { | 255 | { |
| 256 | if (!atomic_dec_and_test(&sbi->s_count)) | 256 | if (atomic_dec_and_test(&sbi->s_count)) |
| 257 | kfree(sbi); | 257 | kfree(sbi); |
| 258 | } | 258 | } |
| 259 | 259 | ||
diff --git a/fs/notify/Kconfig b/fs/notify/Kconfig index 31dac7e3b0f1..dffbb0911d02 100644 --- a/fs/notify/Kconfig +++ b/fs/notify/Kconfig | |||
| @@ -1,15 +1,5 @@ | |||
| 1 | config FSNOTIFY | 1 | config FSNOTIFY |
| 2 | bool "Filesystem notification backend" | 2 | def_bool n |
| 3 | default y | ||
| 4 | ---help--- | ||
| 5 | fsnotify is a backend for filesystem notification. fsnotify does | ||
| 6 | not provide any userspace interface but does provide the basis | ||
| 7 | needed for other notification schemes such as dnotify, inotify, | ||
| 8 | and fanotify. | ||
| 9 | |||
| 10 | Say Y here to enable fsnotify suport. | ||
| 11 | |||
| 12 | If unsure, say Y. | ||
| 13 | 3 | ||
| 14 | source "fs/notify/dnotify/Kconfig" | 4 | source "fs/notify/dnotify/Kconfig" |
| 15 | source "fs/notify/inotify/Kconfig" | 5 | source "fs/notify/inotify/Kconfig" |
diff --git a/fs/notify/dnotify/Kconfig b/fs/notify/dnotify/Kconfig index 904ff8d5405a..f9c1ca139d8f 100644 --- a/fs/notify/dnotify/Kconfig +++ b/fs/notify/dnotify/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config DNOTIFY | 1 | config DNOTIFY |
| 2 | bool "Dnotify support" | 2 | bool "Dnotify support" |
| 3 | depends on FSNOTIFY | 3 | select FSNOTIFY |
| 4 | default y | 4 | default y |
| 5 | help | 5 | help |
| 6 | Dnotify is a directory-based per-fd file change notification system | 6 | Dnotify is a directory-based per-fd file change notification system |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index ec2f7bd76818..037e878e03fc 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
| @@ -159,7 +159,9 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const | |||
| 159 | if (!group->ops->should_send_event(group, to_tell, mask)) | 159 | if (!group->ops->should_send_event(group, to_tell, mask)) |
| 160 | continue; | 160 | continue; |
| 161 | if (!event) { | 161 | if (!event) { |
| 162 | event = fsnotify_create_event(to_tell, mask, data, data_is, file_name, cookie); | 162 | event = fsnotify_create_event(to_tell, mask, data, |
| 163 | data_is, file_name, cookie, | ||
| 164 | GFP_KERNEL); | ||
| 163 | /* shit, we OOM'd and now we can't tell, maybe | 165 | /* shit, we OOM'd and now we can't tell, maybe |
| 164 | * someday someone else will want to do something | 166 | * someday someone else will want to do something |
| 165 | * here */ | 167 | * here */ |
diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig index 5356884289a1..3e56dbffe729 100644 --- a/fs/notify/inotify/Kconfig +++ b/fs/notify/inotify/Kconfig | |||
| @@ -15,7 +15,7 @@ config INOTIFY | |||
| 15 | 15 | ||
| 16 | config INOTIFY_USER | 16 | config INOTIFY_USER |
| 17 | bool "Inotify support for userspace" | 17 | bool "Inotify support for userspace" |
| 18 | depends on FSNOTIFY | 18 | select FSNOTIFY |
| 19 | default y | 19 | default y |
| 20 | ---help--- | 20 | ---help--- |
| 21 | Say Y here to enable inotify support for userspace, including the | 21 | Say Y here to enable inotify support for userspace, including the |
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 47cd258fd24d..5dcbafe72d71 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c | |||
| @@ -62,13 +62,14 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev | |||
| 62 | event_priv->wd = wd; | 62 | event_priv->wd = wd; |
| 63 | 63 | ||
| 64 | ret = fsnotify_add_notify_event(group, event, fsn_event_priv); | 64 | ret = fsnotify_add_notify_event(group, event, fsn_event_priv); |
| 65 | /* EEXIST is not an error */ | 65 | if (ret) { |
| 66 | if (ret == -EEXIST) | ||
| 67 | ret = 0; | ||
| 68 | |||
| 69 | /* did event_priv get attached? */ | ||
| 70 | if (list_empty(&fsn_event_priv->event_list)) | ||
| 71 | inotify_free_event_priv(fsn_event_priv); | 66 | inotify_free_event_priv(fsn_event_priv); |
| 67 | /* EEXIST says we tail matched, EOVERFLOW isn't something | ||
| 68 | * to report up the stack. */ | ||
| 69 | if ((ret == -EEXIST) || | ||
| 70 | (ret == -EOVERFLOW)) | ||
| 71 | ret = 0; | ||
| 72 | } | ||
| 72 | 73 | ||
| 73 | /* | 74 | /* |
| 74 | * If we hold the entry until after the event is on the queue | 75 | * If we hold the entry until after the event is on the queue |
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index ff27a2965844..dc32ed8323ba 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
| @@ -57,7 +57,6 @@ int inotify_max_user_watches __read_mostly; | |||
| 57 | 57 | ||
| 58 | static struct kmem_cache *inotify_inode_mark_cachep __read_mostly; | 58 | static struct kmem_cache *inotify_inode_mark_cachep __read_mostly; |
| 59 | struct kmem_cache *event_priv_cachep __read_mostly; | 59 | struct kmem_cache *event_priv_cachep __read_mostly; |
| 60 | static struct fsnotify_event *inotify_ignored_event; | ||
| 61 | 60 | ||
| 62 | /* | 61 | /* |
| 63 | * When inotify registers a new group it increments this and uses that | 62 | * When inotify registers a new group it increments this and uses that |
| @@ -365,6 +364,17 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns | |||
| 365 | return error; | 364 | return error; |
| 366 | } | 365 | } |
| 367 | 366 | ||
| 367 | static void inotify_remove_from_idr(struct fsnotify_group *group, | ||
| 368 | struct inotify_inode_mark_entry *ientry) | ||
| 369 | { | ||
| 370 | struct idr *idr; | ||
| 371 | |||
| 372 | spin_lock(&group->inotify_data.idr_lock); | ||
| 373 | idr = &group->inotify_data.idr; | ||
| 374 | idr_remove(idr, ientry->wd); | ||
| 375 | spin_unlock(&group->inotify_data.idr_lock); | ||
| 376 | ientry->wd = -1; | ||
| 377 | } | ||
| 368 | /* | 378 | /* |
| 369 | * Send IN_IGNORED for this wd, remove this wd from the idr, and drop the | 379 | * Send IN_IGNORED for this wd, remove this wd from the idr, and drop the |
| 370 | * internal reference help on the mark because it is in the idr. | 380 | * internal reference help on the mark because it is in the idr. |
| @@ -373,13 +383,20 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, | |||
| 373 | struct fsnotify_group *group) | 383 | struct fsnotify_group *group) |
| 374 | { | 384 | { |
| 375 | struct inotify_inode_mark_entry *ientry; | 385 | struct inotify_inode_mark_entry *ientry; |
| 386 | struct fsnotify_event *ignored_event; | ||
| 376 | struct inotify_event_private_data *event_priv; | 387 | struct inotify_event_private_data *event_priv; |
| 377 | struct fsnotify_event_private_data *fsn_event_priv; | 388 | struct fsnotify_event_private_data *fsn_event_priv; |
| 378 | struct idr *idr; | 389 | int ret; |
| 390 | |||
| 391 | ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL, | ||
| 392 | FSNOTIFY_EVENT_NONE, NULL, 0, | ||
| 393 | GFP_NOFS); | ||
| 394 | if (!ignored_event) | ||
| 395 | return; | ||
| 379 | 396 | ||
| 380 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); | 397 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); |
| 381 | 398 | ||
| 382 | event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL); | 399 | event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS); |
| 383 | if (unlikely(!event_priv)) | 400 | if (unlikely(!event_priv)) |
| 384 | goto skip_send_ignore; | 401 | goto skip_send_ignore; |
| 385 | 402 | ||
| @@ -388,22 +405,22 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, | |||
| 388 | fsn_event_priv->group = group; | 405 | fsn_event_priv->group = group; |
| 389 | event_priv->wd = ientry->wd; | 406 | event_priv->wd = ientry->wd; |
| 390 | 407 | ||
| 391 | fsnotify_add_notify_event(group, inotify_ignored_event, fsn_event_priv); | 408 | ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv); |
| 392 | 409 | if (ret) | |
| 393 | /* did the private data get added? */ | ||
| 394 | if (list_empty(&fsn_event_priv->event_list)) | ||
| 395 | inotify_free_event_priv(fsn_event_priv); | 410 | inotify_free_event_priv(fsn_event_priv); |
| 396 | 411 | ||
| 397 | skip_send_ignore: | 412 | skip_send_ignore: |
| 398 | 413 | ||
| 414 | /* matches the reference taken when the event was created */ | ||
| 415 | fsnotify_put_event(ignored_event); | ||
| 416 | |||
| 399 | /* remove this entry from the idr */ | 417 | /* remove this entry from the idr */ |
| 400 | spin_lock(&group->inotify_data.idr_lock); | 418 | inotify_remove_from_idr(group, ientry); |
| 401 | idr = &group->inotify_data.idr; | ||
| 402 | idr_remove(idr, ientry->wd); | ||
| 403 | spin_unlock(&group->inotify_data.idr_lock); | ||
| 404 | 419 | ||
| 405 | /* removed from idr, drop that reference */ | 420 | /* removed from idr, drop that reference */ |
| 406 | fsnotify_put_mark(entry); | 421 | fsnotify_put_mark(entry); |
| 422 | |||
| 423 | atomic_dec(&group->inotify_data.user->inotify_watches); | ||
| 407 | } | 424 | } |
| 408 | 425 | ||
| 409 | /* ding dong the mark is dead */ | 426 | /* ding dong the mark is dead */ |
| @@ -418,6 +435,7 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod | |||
| 418 | { | 435 | { |
| 419 | struct fsnotify_mark_entry *entry = NULL; | 436 | struct fsnotify_mark_entry *entry = NULL; |
| 420 | struct inotify_inode_mark_entry *ientry; | 437 | struct inotify_inode_mark_entry *ientry; |
| 438 | struct inotify_inode_mark_entry *tmp_ientry; | ||
| 421 | int ret = 0; | 439 | int ret = 0; |
| 422 | int add = (arg & IN_MASK_ADD); | 440 | int add = (arg & IN_MASK_ADD); |
| 423 | __u32 mask; | 441 | __u32 mask; |
| @@ -428,54 +446,66 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod | |||
| 428 | if (unlikely(!mask)) | 446 | if (unlikely(!mask)) |
| 429 | return -EINVAL; | 447 | return -EINVAL; |
| 430 | 448 | ||
| 431 | ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); | 449 | tmp_ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); |
| 432 | if (unlikely(!ientry)) | 450 | if (unlikely(!tmp_ientry)) |
| 433 | return -ENOMEM; | 451 | return -ENOMEM; |
| 434 | /* we set the mask at the end after attaching it */ | 452 | /* we set the mask at the end after attaching it */ |
| 435 | fsnotify_init_mark(&ientry->fsn_entry, inotify_free_mark); | 453 | fsnotify_init_mark(&tmp_ientry->fsn_entry, inotify_free_mark); |
| 436 | ientry->wd = 0; | 454 | tmp_ientry->wd = -1; |
| 437 | 455 | ||
| 438 | find_entry: | 456 | find_entry: |
| 439 | spin_lock(&inode->i_lock); | 457 | spin_lock(&inode->i_lock); |
| 440 | entry = fsnotify_find_mark_entry(group, inode); | 458 | entry = fsnotify_find_mark_entry(group, inode); |
| 441 | spin_unlock(&inode->i_lock); | 459 | spin_unlock(&inode->i_lock); |
| 442 | if (entry) { | 460 | if (entry) { |
| 443 | kmem_cache_free(inotify_inode_mark_cachep, ientry); | ||
| 444 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); | 461 | ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); |
| 445 | } else { | 462 | } else { |
| 446 | if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches) { | 463 | ret = -ENOSPC; |
| 447 | ret = -ENOSPC; | 464 | if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches) |
| 448 | goto out_err; | 465 | goto out_err; |
| 449 | } | ||
| 450 | |||
| 451 | ret = fsnotify_add_mark(&ientry->fsn_entry, group, inode); | ||
| 452 | if (ret == -EEXIST) | ||
| 453 | goto find_entry; | ||
| 454 | else if (ret) | ||
| 455 | goto out_err; | ||
| 456 | |||
| 457 | entry = &ientry->fsn_entry; | ||
| 458 | retry: | 466 | retry: |
| 459 | ret = -ENOMEM; | 467 | ret = -ENOMEM; |
| 460 | if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) | 468 | if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) |
| 461 | goto out_err; | 469 | goto out_err; |
| 462 | 470 | ||
| 463 | spin_lock(&group->inotify_data.idr_lock); | 471 | spin_lock(&group->inotify_data.idr_lock); |
| 464 | /* if entry is added to the idr we keep the reference obtained | 472 | ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, |
| 465 | * through fsnotify_mark_add. remember to drop this reference | 473 | group->inotify_data.last_wd, |
| 466 | * when entry is removed from idr */ | 474 | &tmp_ientry->wd); |
| 467 | ret = idr_get_new_above(&group->inotify_data.idr, entry, | ||
| 468 | ++group->inotify_data.last_wd, | ||
| 469 | &ientry->wd); | ||
| 470 | spin_unlock(&group->inotify_data.idr_lock); | 475 | spin_unlock(&group->inotify_data.idr_lock); |
| 471 | if (ret) { | 476 | if (ret) { |
| 472 | if (ret == -EAGAIN) | 477 | if (ret == -EAGAIN) |
| 473 | goto retry; | 478 | goto retry; |
| 474 | goto out_err; | 479 | goto out_err; |
| 475 | } | 480 | } |
| 481 | |||
| 482 | ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); | ||
| 483 | if (ret) { | ||
| 484 | inotify_remove_from_idr(group, tmp_ientry); | ||
| 485 | if (ret == -EEXIST) | ||
| 486 | goto find_entry; | ||
| 487 | goto out_err; | ||
| 488 | } | ||
| 489 | |||
| 490 | /* tmp_ientry has been added to the inode, so we are all set up. | ||
| 491 | * now we just need to make sure tmp_ientry doesn't get freed and | ||
| 492 | * we need to set up entry and ientry so the generic code can | ||
| 493 | * do its thing. */ | ||
| 494 | ientry = tmp_ientry; | ||
| 495 | entry = &ientry->fsn_entry; | ||
| 496 | tmp_ientry = NULL; | ||
| 497 | |||
| 476 | atomic_inc(&group->inotify_data.user->inotify_watches); | 498 | atomic_inc(&group->inotify_data.user->inotify_watches); |
| 499 | |||
| 500 | /* update the idr hint */ | ||
| 501 | group->inotify_data.last_wd = ientry->wd; | ||
| 502 | |||
| 503 | /* we put the mark on the idr, take a reference */ | ||
| 504 | fsnotify_get_mark(entry); | ||
| 477 | } | 505 | } |
| 478 | 506 | ||
| 507 | ret = ientry->wd; | ||
| 508 | |||
| 479 | spin_lock(&entry->lock); | 509 | spin_lock(&entry->lock); |
| 480 | 510 | ||
| 481 | old_mask = entry->mask; | 511 | old_mask = entry->mask; |
| @@ -506,14 +536,19 @@ retry: | |||
| 506 | fsnotify_recalc_group_mask(group); | 536 | fsnotify_recalc_group_mask(group); |
| 507 | } | 537 | } |
| 508 | 538 | ||
| 509 | return ientry->wd; | 539 | /* this either matches fsnotify_find_mark_entry, or init_mark_entry |
| 540 | * depending on which path we took... */ | ||
| 541 | fsnotify_put_mark(entry); | ||
| 510 | 542 | ||
| 511 | out_err: | 543 | out_err: |
| 512 | /* see this isn't supposed to happen, just kill the watch */ | 544 | /* could be an error, could be that we found an existing mark */ |
| 513 | if (entry) { | 545 | if (tmp_ientry) { |
| 514 | fsnotify_destroy_mark_by_entry(entry); | 546 | /* on the idr but didn't make it on the inode */ |
| 515 | fsnotify_put_mark(entry); | 547 | if (tmp_ientry->wd != -1) |
| 548 | inotify_remove_from_idr(group, tmp_ientry); | ||
| 549 | kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); | ||
| 516 | } | 550 | } |
| 551 | |||
| 517 | return ret; | 552 | return ret; |
| 518 | } | 553 | } |
| 519 | 554 | ||
| @@ -532,7 +567,7 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign | |||
| 532 | 567 | ||
| 533 | spin_lock_init(&group->inotify_data.idr_lock); | 568 | spin_lock_init(&group->inotify_data.idr_lock); |
| 534 | idr_init(&group->inotify_data.idr); | 569 | idr_init(&group->inotify_data.idr); |
| 535 | group->inotify_data.last_wd = 0; | 570 | group->inotify_data.last_wd = 1; |
| 536 | group->inotify_data.user = user; | 571 | group->inotify_data.user = user; |
| 537 | group->inotify_data.fa = NULL; | 572 | group->inotify_data.fa = NULL; |
| 538 | 573 | ||
| @@ -721,9 +756,6 @@ static int __init inotify_user_setup(void) | |||
| 721 | 756 | ||
| 722 | inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark_entry, SLAB_PANIC); | 757 | inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark_entry, SLAB_PANIC); |
| 723 | event_priv_cachep = KMEM_CACHE(inotify_event_private_data, SLAB_PANIC); | 758 | event_priv_cachep = KMEM_CACHE(inotify_event_private_data, SLAB_PANIC); |
| 724 | inotify_ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, NULL, 0); | ||
| 725 | if (!inotify_ignored_event) | ||
| 726 | panic("unable to allocate the inotify ignored event\n"); | ||
| 727 | 759 | ||
| 728 | inotify_max_queued_events = 16384; | 760 | inotify_max_queued_events = 16384; |
| 729 | inotify_max_user_instances = 128; | 761 | inotify_max_user_instances = 128; |
diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 959b73e756fd..3816d5750dd5 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c | |||
| @@ -136,18 +136,28 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new | |||
| 136 | { | 136 | { |
| 137 | if ((old->mask == new->mask) && | 137 | if ((old->mask == new->mask) && |
| 138 | (old->to_tell == new->to_tell) && | 138 | (old->to_tell == new->to_tell) && |
| 139 | (old->data_type == new->data_type)) { | 139 | (old->data_type == new->data_type) && |
| 140 | (old->name_len == new->name_len)) { | ||
| 140 | switch (old->data_type) { | 141 | switch (old->data_type) { |
| 141 | case (FSNOTIFY_EVENT_INODE): | 142 | case (FSNOTIFY_EVENT_INODE): |
| 142 | if (old->inode == new->inode) | 143 | /* remember, after old was put on the wait_q we aren't |
| 144 | * allowed to look at the inode any more, only thing | ||
| 145 | * left to check was if the file_name is the same */ | ||
| 146 | if (old->name_len && | ||
| 147 | !strcmp(old->file_name, new->file_name)) | ||
| 143 | return true; | 148 | return true; |
| 144 | break; | 149 | break; |
| 145 | case (FSNOTIFY_EVENT_PATH): | 150 | case (FSNOTIFY_EVENT_PATH): |
| 146 | if ((old->path.mnt == new->path.mnt) && | 151 | if ((old->path.mnt == new->path.mnt) && |
| 147 | (old->path.dentry == new->path.dentry)) | 152 | (old->path.dentry == new->path.dentry)) |
| 148 | return true; | 153 | return true; |
| 154 | break; | ||
| 149 | case (FSNOTIFY_EVENT_NONE): | 155 | case (FSNOTIFY_EVENT_NONE): |
| 150 | return true; | 156 | if (old->mask & FS_Q_OVERFLOW) |
| 157 | return true; | ||
| 158 | else if (old->mask & FS_IN_IGNORED) | ||
| 159 | return false; | ||
| 160 | return false; | ||
| 151 | }; | 161 | }; |
| 152 | } | 162 | } |
| 153 | return false; | 163 | return false; |
| @@ -165,9 +175,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_even | |||
| 165 | struct list_head *list = &group->notification_list; | 175 | struct list_head *list = &group->notification_list; |
| 166 | struct fsnotify_event_holder *last_holder; | 176 | struct fsnotify_event_holder *last_holder; |
| 167 | struct fsnotify_event *last_event; | 177 | struct fsnotify_event *last_event; |
| 168 | 178 | int ret = 0; | |
| 169 | /* easy to tell if priv was attached to the event */ | ||
| 170 | INIT_LIST_HEAD(&priv->event_list); | ||
| 171 | 179 | ||
| 172 | /* | 180 | /* |
| 173 | * There is one fsnotify_event_holder embedded inside each fsnotify_event. | 181 | * There is one fsnotify_event_holder embedded inside each fsnotify_event. |
| @@ -188,6 +196,7 @@ alloc_holder: | |||
| 188 | 196 | ||
| 189 | if (group->q_len >= group->max_events) { | 197 | if (group->q_len >= group->max_events) { |
| 190 | event = &q_overflow_event; | 198 | event = &q_overflow_event; |
| 199 | ret = -EOVERFLOW; | ||
| 191 | /* sorry, no private data on the overflow event */ | 200 | /* sorry, no private data on the overflow event */ |
| 192 | priv = NULL; | 201 | priv = NULL; |
| 193 | } | 202 | } |
| @@ -229,7 +238,7 @@ alloc_holder: | |||
| 229 | mutex_unlock(&group->notification_mutex); | 238 | mutex_unlock(&group->notification_mutex); |
| 230 | 239 | ||
| 231 | wake_up(&group->notification_waitq); | 240 | wake_up(&group->notification_waitq); |
| 232 | return 0; | 241 | return ret; |
| 233 | } | 242 | } |
| 234 | 243 | ||
| 235 | /* | 244 | /* |
| @@ -339,18 +348,19 @@ static void initialize_event(struct fsnotify_event *event) | |||
| 339 | * @name the filename, if available | 348 | * @name the filename, if available |
| 340 | */ | 349 | */ |
| 341 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data, | 350 | struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data, |
| 342 | int data_type, const char *name, u32 cookie) | 351 | int data_type, const char *name, u32 cookie, |
| 352 | gfp_t gfp) | ||
| 343 | { | 353 | { |
| 344 | struct fsnotify_event *event; | 354 | struct fsnotify_event *event; |
| 345 | 355 | ||
| 346 | event = kmem_cache_alloc(fsnotify_event_cachep, GFP_KERNEL); | 356 | event = kmem_cache_alloc(fsnotify_event_cachep, gfp); |
| 347 | if (!event) | 357 | if (!event) |
| 348 | return NULL; | 358 | return NULL; |
| 349 | 359 | ||
| 350 | initialize_event(event); | 360 | initialize_event(event); |
| 351 | 361 | ||
| 352 | if (name) { | 362 | if (name) { |
| 353 | event->file_name = kstrdup(name, GFP_KERNEL); | 363 | event->file_name = kstrdup(name, gfp); |
| 354 | if (!event->file_name) { | 364 | if (!event->file_name) { |
| 355 | kmem_cache_free(fsnotify_event_cachep, event); | 365 | kmem_cache_free(fsnotify_event_cachep, event); |
| 356 | return NULL; | 366 | return NULL; |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 9edcde4974aa..f9a3e8942669 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec, | |||
| 1914 | * immediately to their right. | 1914 | * immediately to their right. |
| 1915 | */ | 1915 | */ |
| 1916 | left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos); | 1916 | left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos); |
| 1917 | if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) { | 1917 | if (!ocfs2_rec_clusters(right_child_el, &right_child_el->l_recs[0])) { |
| 1918 | BUG_ON(right_child_el->l_tree_depth); | ||
| 1918 | BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1); | 1919 | BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1); |
| 1919 | left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos); | 1920 | left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos); |
| 1920 | } | 1921 | } |
| @@ -2476,15 +2477,37 @@ out_ret_path: | |||
| 2476 | return ret; | 2477 | return ret; |
| 2477 | } | 2478 | } |
| 2478 | 2479 | ||
| 2479 | static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle, | 2480 | static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle, |
| 2480 | struct ocfs2_path *path) | 2481 | int subtree_index, struct ocfs2_path *path) |
| 2481 | { | 2482 | { |
| 2482 | int i, idx; | 2483 | int i, idx, ret; |
| 2483 | struct ocfs2_extent_rec *rec; | 2484 | struct ocfs2_extent_rec *rec; |
| 2484 | struct ocfs2_extent_list *el; | 2485 | struct ocfs2_extent_list *el; |
| 2485 | struct ocfs2_extent_block *eb; | 2486 | struct ocfs2_extent_block *eb; |
| 2486 | u32 range; | 2487 | u32 range; |
| 2487 | 2488 | ||
| 2489 | /* | ||
| 2490 | * In normal tree rotation process, we will never touch the | ||
| 2491 | * tree branch above subtree_index and ocfs2_extend_rotate_transaction | ||
| 2492 | * doesn't reserve the credits for them either. | ||
| 2493 | * | ||
| 2494 | * But we do have a special case here which will update the rightmost | ||
| 2495 | * records for all the bh in the path. | ||
| 2496 | * So we have to allocate extra credits and access them. | ||
| 2497 | */ | ||
| 2498 | ret = ocfs2_extend_trans(handle, | ||
| 2499 | handle->h_buffer_credits + subtree_index); | ||
| 2500 | if (ret) { | ||
| 2501 | mlog_errno(ret); | ||
| 2502 | goto out; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | ret = ocfs2_journal_access_path(inode, handle, path); | ||
| 2506 | if (ret) { | ||
| 2507 | mlog_errno(ret); | ||
| 2508 | goto out; | ||
| 2509 | } | ||
| 2510 | |||
| 2488 | /* Path should always be rightmost. */ | 2511 | /* Path should always be rightmost. */ |
| 2489 | eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data; | 2512 | eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data; |
| 2490 | BUG_ON(eb->h_next_leaf_blk != 0ULL); | 2513 | BUG_ON(eb->h_next_leaf_blk != 0ULL); |
| @@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle, | |||
| 2505 | 2528 | ||
| 2506 | ocfs2_journal_dirty(handle, path->p_node[i].bh); | 2529 | ocfs2_journal_dirty(handle, path->p_node[i].bh); |
| 2507 | } | 2530 | } |
| 2531 | out: | ||
| 2532 | return ret; | ||
| 2508 | } | 2533 | } |
| 2509 | 2534 | ||
| 2510 | static void ocfs2_unlink_path(struct inode *inode, handle_t *handle, | 2535 | static void ocfs2_unlink_path(struct inode *inode, handle_t *handle, |
| @@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle, | |||
| 2717 | if (del_right_subtree) { | 2742 | if (del_right_subtree) { |
| 2718 | ocfs2_unlink_subtree(inode, handle, left_path, right_path, | 2743 | ocfs2_unlink_subtree(inode, handle, left_path, right_path, |
| 2719 | subtree_index, dealloc); | 2744 | subtree_index, dealloc); |
| 2720 | ocfs2_update_edge_lengths(inode, handle, left_path); | 2745 | ret = ocfs2_update_edge_lengths(inode, handle, subtree_index, |
| 2746 | left_path); | ||
| 2747 | if (ret) { | ||
| 2748 | mlog_errno(ret); | ||
| 2749 | goto out; | ||
| 2750 | } | ||
| 2721 | 2751 | ||
| 2722 | eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data; | 2752 | eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data; |
| 2723 | ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno)); | 2753 | ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno)); |
| @@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle, | |||
| 3034 | 3064 | ||
| 3035 | ocfs2_unlink_subtree(inode, handle, left_path, path, | 3065 | ocfs2_unlink_subtree(inode, handle, left_path, path, |
| 3036 | subtree_index, dealloc); | 3066 | subtree_index, dealloc); |
| 3037 | ocfs2_update_edge_lengths(inode, handle, left_path); | 3067 | ret = ocfs2_update_edge_lengths(inode, handle, subtree_index, |
| 3068 | left_path); | ||
| 3069 | if (ret) { | ||
| 3070 | mlog_errno(ret); | ||
| 3071 | goto out; | ||
| 3072 | } | ||
| 3038 | 3073 | ||
| 3039 | eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data; | 3074 | eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data; |
| 3040 | ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno)); | 3075 | ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno)); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index b2c52b3a1484..b401654011a2 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
| 193 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 193 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
| 194 | mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters); | 194 | mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters); |
| 195 | dump_stack(); | 195 | dump_stack(); |
| 196 | goto bail; | ||
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); | 199 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); |
| @@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc { | |||
| 894 | */ | 895 | */ |
| 895 | unsigned c_new; | 896 | unsigned c_new; |
| 896 | unsigned c_unwritten; | 897 | unsigned c_unwritten; |
| 898 | unsigned c_needs_zero; | ||
| 897 | }; | 899 | }; |
| 898 | 900 | ||
| 899 | static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) | ||
| 900 | { | ||
| 901 | return d->c_new || d->c_unwritten; | ||
| 902 | } | ||
| 903 | |||
| 904 | struct ocfs2_write_ctxt { | 901 | struct ocfs2_write_ctxt { |
| 905 | /* Logical cluster position / len of write */ | 902 | /* Logical cluster position / len of write */ |
| 906 | u32 w_cpos; | 903 | u32 w_cpos; |
| 907 | u32 w_clen; | 904 | u32 w_clen; |
| 908 | 905 | ||
| 906 | /* First cluster allocated in a nonsparse extend */ | ||
| 907 | u32 w_first_new_cpos; | ||
| 908 | |||
| 909 | struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; | 909 | struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; |
| 910 | 910 | ||
| 911 | /* | 911 | /* |
| @@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp, | |||
| 983 | return -ENOMEM; | 983 | return -ENOMEM; |
| 984 | 984 | ||
| 985 | wc->w_cpos = pos >> osb->s_clustersize_bits; | 985 | wc->w_cpos = pos >> osb->s_clustersize_bits; |
| 986 | wc->w_first_new_cpos = UINT_MAX; | ||
| 986 | cend = (pos + len - 1) >> osb->s_clustersize_bits; | 987 | cend = (pos + len - 1) >> osb->s_clustersize_bits; |
| 987 | wc->w_clen = cend - wc->w_cpos + 1; | 988 | wc->w_clen = cend - wc->w_cpos + 1; |
| 988 | get_bh(di_bh); | 989 | get_bh(di_bh); |
| @@ -1217,20 +1218,18 @@ out: | |||
| 1217 | */ | 1218 | */ |
| 1218 | static int ocfs2_write_cluster(struct address_space *mapping, | 1219 | static int ocfs2_write_cluster(struct address_space *mapping, |
| 1219 | u32 phys, unsigned int unwritten, | 1220 | u32 phys, unsigned int unwritten, |
| 1221 | unsigned int should_zero, | ||
| 1220 | struct ocfs2_alloc_context *data_ac, | 1222 | struct ocfs2_alloc_context *data_ac, |
| 1221 | struct ocfs2_alloc_context *meta_ac, | 1223 | struct ocfs2_alloc_context *meta_ac, |
| 1222 | struct ocfs2_write_ctxt *wc, u32 cpos, | 1224 | struct ocfs2_write_ctxt *wc, u32 cpos, |
| 1223 | loff_t user_pos, unsigned user_len) | 1225 | loff_t user_pos, unsigned user_len) |
| 1224 | { | 1226 | { |
| 1225 | int ret, i, new, should_zero = 0; | 1227 | int ret, i, new; |
| 1226 | u64 v_blkno, p_blkno; | 1228 | u64 v_blkno, p_blkno; |
| 1227 | struct inode *inode = mapping->host; | 1229 | struct inode *inode = mapping->host; |
| 1228 | struct ocfs2_extent_tree et; | 1230 | struct ocfs2_extent_tree et; |
| 1229 | 1231 | ||
| 1230 | new = phys == 0 ? 1 : 0; | 1232 | new = phys == 0 ? 1 : 0; |
| 1231 | if (new || unwritten) | ||
| 1232 | should_zero = 1; | ||
| 1233 | |||
| 1234 | if (new) { | 1233 | if (new) { |
| 1235 | u32 tmp_pos; | 1234 | u32 tmp_pos; |
| 1236 | 1235 | ||
| @@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping, | |||
| 1301 | if (tmpret) { | 1300 | if (tmpret) { |
| 1302 | mlog_errno(tmpret); | 1301 | mlog_errno(tmpret); |
| 1303 | if (ret == 0) | 1302 | if (ret == 0) |
| 1304 | tmpret = ret; | 1303 | ret = tmpret; |
| 1305 | } | 1304 | } |
| 1306 | } | 1305 | } |
| 1307 | 1306 | ||
| @@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, | |||
| 1341 | local_len = osb->s_clustersize - cluster_off; | 1340 | local_len = osb->s_clustersize - cluster_off; |
| 1342 | 1341 | ||
| 1343 | ret = ocfs2_write_cluster(mapping, desc->c_phys, | 1342 | ret = ocfs2_write_cluster(mapping, desc->c_phys, |
| 1344 | desc->c_unwritten, data_ac, meta_ac, | 1343 | desc->c_unwritten, |
| 1344 | desc->c_needs_zero, | ||
| 1345 | data_ac, meta_ac, | ||
| 1345 | wc, desc->c_cpos, pos, local_len); | 1346 | wc, desc->c_cpos, pos, local_len); |
| 1346 | if (ret) { | 1347 | if (ret) { |
| 1347 | mlog_errno(ret); | 1348 | mlog_errno(ret); |
| @@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb, | |||
| 1391 | * newly allocated cluster. | 1392 | * newly allocated cluster. |
| 1392 | */ | 1393 | */ |
| 1393 | desc = &wc->w_desc[0]; | 1394 | desc = &wc->w_desc[0]; |
| 1394 | if (ocfs2_should_zero_cluster(desc)) | 1395 | if (desc->c_needs_zero) |
| 1395 | ocfs2_figure_cluster_boundaries(osb, | 1396 | ocfs2_figure_cluster_boundaries(osb, |
| 1396 | desc->c_cpos, | 1397 | desc->c_cpos, |
| 1397 | &wc->w_target_from, | 1398 | &wc->w_target_from, |
| 1398 | NULL); | 1399 | NULL); |
| 1399 | 1400 | ||
| 1400 | desc = &wc->w_desc[wc->w_clen - 1]; | 1401 | desc = &wc->w_desc[wc->w_clen - 1]; |
| 1401 | if (ocfs2_should_zero_cluster(desc)) | 1402 | if (desc->c_needs_zero) |
| 1402 | ocfs2_figure_cluster_boundaries(osb, | 1403 | ocfs2_figure_cluster_boundaries(osb, |
| 1403 | desc->c_cpos, | 1404 | desc->c_cpos, |
| 1404 | NULL, | 1405 | NULL, |
| @@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode, | |||
| 1466 | phys++; | 1467 | phys++; |
| 1467 | } | 1468 | } |
| 1468 | 1469 | ||
| 1470 | /* | ||
| 1471 | * If w_first_new_cpos is < UINT_MAX, we have a non-sparse | ||
| 1472 | * file that got extended. w_first_new_cpos tells us | ||
| 1473 | * where the newly allocated clusters are so we can | ||
| 1474 | * zero them. | ||
| 1475 | */ | ||
| 1476 | if (desc->c_cpos >= wc->w_first_new_cpos) { | ||
| 1477 | BUG_ON(phys == 0); | ||
| 1478 | desc->c_needs_zero = 1; | ||
| 1479 | } | ||
| 1480 | |||
| 1469 | desc->c_phys = phys; | 1481 | desc->c_phys = phys; |
| 1470 | if (phys == 0) { | 1482 | if (phys == 0) { |
| 1471 | desc->c_new = 1; | 1483 | desc->c_new = 1; |
| 1484 | desc->c_needs_zero = 1; | ||
| 1472 | *clusters_to_alloc = *clusters_to_alloc + 1; | 1485 | *clusters_to_alloc = *clusters_to_alloc + 1; |
| 1473 | } | 1486 | } |
| 1474 | if (ext_flags & OCFS2_EXT_UNWRITTEN) | 1487 | |
| 1488 | if (ext_flags & OCFS2_EXT_UNWRITTEN) { | ||
| 1475 | desc->c_unwritten = 1; | 1489 | desc->c_unwritten = 1; |
| 1490 | desc->c_needs_zero = 1; | ||
| 1491 | } | ||
| 1476 | 1492 | ||
| 1477 | num_clusters--; | 1493 | num_clusters--; |
| 1478 | } | 1494 | } |
| @@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | |||
| 1632 | if (newsize <= i_size_read(inode)) | 1648 | if (newsize <= i_size_read(inode)) |
| 1633 | return 0; | 1649 | return 0; |
| 1634 | 1650 | ||
| 1635 | ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); | 1651 | ret = ocfs2_extend_no_holes(inode, newsize, pos); |
| 1636 | if (ret) | 1652 | if (ret) |
| 1637 | mlog_errno(ret); | 1653 | mlog_errno(ret); |
| 1638 | 1654 | ||
| 1655 | wc->w_first_new_cpos = | ||
| 1656 | ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); | ||
| 1657 | |||
| 1639 | return ret; | 1658 | return ret; |
| 1640 | } | 1659 | } |
| 1641 | 1660 | ||
| @@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1644 | struct page **pagep, void **fsdata, | 1663 | struct page **pagep, void **fsdata, |
| 1645 | struct buffer_head *di_bh, struct page *mmap_page) | 1664 | struct buffer_head *di_bh, struct page *mmap_page) |
| 1646 | { | 1665 | { |
| 1647 | int ret, credits = OCFS2_INODE_UPDATE_CREDITS; | 1666 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; |
| 1648 | unsigned int clusters_to_alloc, extents_to_split; | 1667 | unsigned int clusters_to_alloc, extents_to_split; |
| 1649 | struct ocfs2_write_ctxt *wc; | 1668 | struct ocfs2_write_ctxt *wc; |
| 1650 | struct inode *inode = mapping->host; | 1669 | struct inode *inode = mapping->host; |
| @@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1722 | 1741 | ||
| 1723 | } | 1742 | } |
| 1724 | 1743 | ||
| 1725 | ocfs2_set_target_boundaries(osb, wc, pos, len, | 1744 | /* |
| 1726 | clusters_to_alloc + extents_to_split); | 1745 | * We have to zero sparse allocated clusters, unwritten extent clusters, |
| 1746 | * and non-sparse clusters we just extended. For non-sparse writes, | ||
| 1747 | * we know zeros will only be needed in the first and/or last cluster. | ||
| 1748 | */ | ||
| 1749 | if (clusters_to_alloc || extents_to_split || | ||
| 1750 | wc->w_desc[0].c_needs_zero || | ||
| 1751 | wc->w_desc[wc->w_clen - 1].c_needs_zero) | ||
| 1752 | cluster_of_pages = 1; | ||
| 1753 | else | ||
| 1754 | cluster_of_pages = 0; | ||
| 1755 | |||
| 1756 | ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages); | ||
| 1727 | 1757 | ||
| 1728 | handle = ocfs2_start_trans(osb, credits); | 1758 | handle = ocfs2_start_trans(osb, credits); |
| 1729 | if (IS_ERR(handle)) { | 1759 | if (IS_ERR(handle)) { |
| @@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1756 | * extent. | 1786 | * extent. |
| 1757 | */ | 1787 | */ |
| 1758 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, | 1788 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, |
| 1759 | clusters_to_alloc + extents_to_split, | 1789 | cluster_of_pages, mmap_page); |
| 1760 | mmap_page); | ||
| 1761 | if (ret) { | 1790 | if (ret) { |
| 1762 | mlog_errno(ret); | 1791 | mlog_errno(ret); |
| 1763 | goto out_quota; | 1792 | goto out_quota; |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b574431a031d..2f28b7de2c8d 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -310,22 +310,19 @@ out_attach: | |||
| 310 | return ret; | 310 | return ret; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static DEFINE_SPINLOCK(dentry_list_lock); | 313 | DEFINE_SPINLOCK(dentry_list_lock); |
| 314 | 314 | ||
| 315 | /* We limit the number of dentry locks to drop in one go. We have | 315 | /* We limit the number of dentry locks to drop in one go. We have |
| 316 | * this limit so that we don't starve other users of ocfs2_wq. */ | 316 | * this limit so that we don't starve other users of ocfs2_wq. */ |
| 317 | #define DL_INODE_DROP_COUNT 64 | 317 | #define DL_INODE_DROP_COUNT 64 |
| 318 | 318 | ||
| 319 | /* Drop inode references from dentry locks */ | 319 | /* Drop inode references from dentry locks */ |
| 320 | void ocfs2_drop_dl_inodes(struct work_struct *work) | 320 | static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count) |
| 321 | { | 321 | { |
| 322 | struct ocfs2_super *osb = container_of(work, struct ocfs2_super, | ||
| 323 | dentry_lock_work); | ||
| 324 | struct ocfs2_dentry_lock *dl; | 322 | struct ocfs2_dentry_lock *dl; |
| 325 | int drop_count = DL_INODE_DROP_COUNT; | ||
| 326 | 323 | ||
| 327 | spin_lock(&dentry_list_lock); | 324 | spin_lock(&dentry_list_lock); |
| 328 | while (osb->dentry_lock_list && drop_count--) { | 325 | while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) { |
| 329 | dl = osb->dentry_lock_list; | 326 | dl = osb->dentry_lock_list; |
| 330 | osb->dentry_lock_list = dl->dl_next; | 327 | osb->dentry_lock_list = dl->dl_next; |
| 331 | spin_unlock(&dentry_list_lock); | 328 | spin_unlock(&dentry_list_lock); |
| @@ -333,11 +330,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work) | |||
| 333 | kfree(dl); | 330 | kfree(dl); |
| 334 | spin_lock(&dentry_list_lock); | 331 | spin_lock(&dentry_list_lock); |
| 335 | } | 332 | } |
| 336 | if (osb->dentry_lock_list) | 333 | spin_unlock(&dentry_list_lock); |
| 334 | } | ||
| 335 | |||
| 336 | void ocfs2_drop_dl_inodes(struct work_struct *work) | ||
| 337 | { | ||
| 338 | struct ocfs2_super *osb = container_of(work, struct ocfs2_super, | ||
| 339 | dentry_lock_work); | ||
| 340 | |||
| 341 | __ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT); | ||
| 342 | /* | ||
| 343 | * Don't queue dropping if umount is in progress. We flush the | ||
| 344 | * list in ocfs2_dismount_volume | ||
| 345 | */ | ||
| 346 | spin_lock(&dentry_list_lock); | ||
| 347 | if (osb->dentry_lock_list && | ||
| 348 | !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED)) | ||
| 337 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | 349 | queue_work(ocfs2_wq, &osb->dentry_lock_work); |
| 338 | spin_unlock(&dentry_list_lock); | 350 | spin_unlock(&dentry_list_lock); |
| 339 | } | 351 | } |
| 340 | 352 | ||
| 353 | /* Flush the whole work queue */ | ||
| 354 | void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb) | ||
| 355 | { | ||
| 356 | __ocfs2_drop_dl_inodes(osb, -1); | ||
| 357 | } | ||
| 358 | |||
| 341 | /* | 359 | /* |
| 342 | * ocfs2_dentry_iput() and friends. | 360 | * ocfs2_dentry_iput() and friends. |
| 343 | * | 361 | * |
| @@ -368,7 +386,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, | |||
| 368 | /* We leave dropping of inode reference to ocfs2_wq as that can | 386 | /* We leave dropping of inode reference to ocfs2_wq as that can |
| 369 | * possibly lead to inode deletion which gets tricky */ | 387 | * possibly lead to inode deletion which gets tricky */ |
| 370 | spin_lock(&dentry_list_lock); | 388 | spin_lock(&dentry_list_lock); |
| 371 | if (!osb->dentry_lock_list) | 389 | if (!osb->dentry_lock_list && |
| 390 | !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED)) | ||
| 372 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | 391 | queue_work(ocfs2_wq, &osb->dentry_lock_work); |
| 373 | dl->dl_next = osb->dentry_lock_list; | 392 | dl->dl_next = osb->dentry_lock_list; |
| 374 | osb->dentry_lock_list = dl; | 393 | osb->dentry_lock_list = dl; |
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index faa12e75f98d..f5dd1789acf1 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h | |||
| @@ -49,10 +49,13 @@ struct ocfs2_dentry_lock { | |||
| 49 | int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, | 49 | int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, |
| 50 | u64 parent_blkno); | 50 | u64 parent_blkno); |
| 51 | 51 | ||
| 52 | extern spinlock_t dentry_list_lock; | ||
| 53 | |||
| 52 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, | 54 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, |
| 53 | struct ocfs2_dentry_lock *dl); | 55 | struct ocfs2_dentry_lock *dl); |
| 54 | 56 | ||
| 55 | void ocfs2_drop_dl_inodes(struct work_struct *work); | 57 | void ocfs2_drop_dl_inodes(struct work_struct *work); |
| 58 | void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb); | ||
| 56 | 59 | ||
| 57 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, | 60 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, |
| 58 | int skip_unhashed); | 61 | int skip_unhashed); |
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c index d07ddbe4b283..81eff8e58322 100644 --- a/fs/ocfs2/dlm/dlmast.c +++ b/fs/ocfs2/dlm/dlmast.c | |||
| @@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock) | |||
| 103 | lock->ast_pending, lock->ml.type); | 103 | lock->ast_pending, lock->ml.type); |
| 104 | BUG(); | 104 | BUG(); |
| 105 | } | 105 | } |
| 106 | BUG_ON(!list_empty(&lock->ast_list)); | ||
| 107 | if (lock->ast_pending) | 106 | if (lock->ast_pending) |
| 108 | mlog(0, "lock has an ast getting flushed right now\n"); | 107 | mlog(0, "lock has an ast getting flushed right now\n"); |
| 109 | 108 | ||
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index bcb9260c3735..43e6e3280569 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
| @@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm, | |||
| 1118 | 1118 | ||
| 1119 | mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n", | 1119 | mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n", |
| 1120 | dlm->name, res->lockname.len, res->lockname.name, | 1120 | dlm->name, res->lockname.len, res->lockname.name, |
| 1121 | orig_flags & DLM_MRES_MIGRATION ? "migrate" : "recovery", | 1121 | orig_flags & DLM_MRES_MIGRATION ? "migration" : "recovery", |
| 1122 | send_to); | 1122 | send_to); |
| 1123 | 1123 | ||
| 1124 | /* send it */ | 1124 | /* send it */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 62442e413a00..aa501d3f93f1 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1851,6 +1851,7 @@ relock: | |||
| 1851 | if (ret) | 1851 | if (ret) |
| 1852 | goto out_dio; | 1852 | goto out_dio; |
| 1853 | 1853 | ||
| 1854 | count = ocount; | ||
| 1854 | ret = generic_write_checks(file, ppos, &count, | 1855 | ret = generic_write_checks(file, ppos, &count, |
| 1855 | S_ISBLK(inode->i_mode)); | 1856 | S_ISBLK(inode->i_mode)); |
| 1856 | if (ret) | 1857 | if (ret) |
| @@ -1918,8 +1919,10 @@ out_sems: | |||
| 1918 | 1919 | ||
| 1919 | mutex_unlock(&inode->i_mutex); | 1920 | mutex_unlock(&inode->i_mutex); |
| 1920 | 1921 | ||
| 1922 | if (written) | ||
| 1923 | ret = written; | ||
| 1921 | mlog_exit(ret); | 1924 | mlog_exit(ret); |
| 1922 | return written ? written : ret; | 1925 | return ret; |
| 1923 | } | 1926 | } |
| 1924 | 1927 | ||
| 1925 | static int ocfs2_splice_to_file(struct pipe_inode_info *pipe, | 1928 | static int ocfs2_splice_to_file(struct pipe_inode_info *pipe, |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 9fcd36dcc9a0..467b413bec21 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
| 9 | #include <linux/mount.h> | 9 | #include <linux/mount.h> |
| 10 | #include <linux/smp_lock.h> | ||
| 11 | 10 | ||
| 12 | #define MLOG_MASK_PREFIX ML_INODE | 11 | #define MLOG_MASK_PREFIX ML_INODE |
| 13 | #include <cluster/masklog.h> | 12 | #include <cluster/masklog.h> |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index f033760ecbea..c48b93ac6b65 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb) | |||
| 1954 | os->os_osb = osb; | 1954 | os->os_osb = osb; |
| 1955 | os->os_count = 0; | 1955 | os->os_count = 0; |
| 1956 | os->os_seqno = 0; | 1956 | os->os_seqno = 0; |
| 1957 | os->os_scantime = CURRENT_TIME; | ||
| 1958 | mutex_init(&os->os_lock); | 1957 | mutex_init(&os->os_lock); |
| 1959 | INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work); | 1958 | INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work); |
| 1959 | } | ||
| 1960 | 1960 | ||
| 1961 | void ocfs2_orphan_scan_start(struct ocfs2_super *osb) | ||
| 1962 | { | ||
| 1963 | struct ocfs2_orphan_scan *os; | ||
| 1964 | |||
| 1965 | os = &osb->osb_orphan_scan; | ||
| 1966 | os->os_scantime = CURRENT_TIME; | ||
| 1961 | if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb)) | 1967 | if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb)) |
| 1962 | atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); | 1968 | atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); |
| 1963 | else { | 1969 | else { |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 5432c7f79cc6..2c3222aec622 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
| @@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, | |||
| 145 | 145 | ||
| 146 | /* Exported only for the journal struct init code in super.c. Do not call. */ | 146 | /* Exported only for the journal struct init code in super.c. Do not call. */ |
| 147 | void ocfs2_orphan_scan_init(struct ocfs2_super *osb); | 147 | void ocfs2_orphan_scan_init(struct ocfs2_super *osb); |
| 148 | void ocfs2_orphan_scan_start(struct ocfs2_super *osb); | ||
| 148 | void ocfs2_orphan_scan_stop(struct ocfs2_super *osb); | 149 | void ocfs2_orphan_scan_stop(struct ocfs2_super *osb); |
| 149 | void ocfs2_orphan_scan_exit(struct ocfs2_super *osb); | 150 | void ocfs2_orphan_scan_exit(struct ocfs2_super *osb); |
| 150 | 151 | ||
| @@ -329,20 +330,27 @@ int ocfs2_journal_dirty(handle_t *handle, | |||
| 329 | /* extended attribute block update */ | 330 | /* extended attribute block update */ |
| 330 | #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1 | 331 | #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1 |
| 331 | 332 | ||
| 333 | /* Update of a single quota block */ | ||
| 334 | #define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1 | ||
| 335 | |||
| 332 | /* global quotafile inode update, data block */ | 336 | /* global quotafile inode update, data block */ |
| 333 | #define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1) | 337 | #define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \ |
| 338 | OCFS2_QUOTA_BLOCK_UPDATE_CREDITS) | ||
| 334 | 339 | ||
| 340 | #define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS | ||
| 335 | /* | 341 | /* |
| 336 | * The two writes below can accidentally see global info dirty due | 342 | * The two writes below can accidentally see global info dirty due |
| 337 | * to set_info() quotactl so make them prepared for the writes. | 343 | * to set_info() quotactl so make them prepared for the writes. |
| 338 | */ | 344 | */ |
| 339 | /* quota data block, global info */ | 345 | /* quota data block, global info */ |
| 340 | /* Write to local quota file */ | 346 | /* Write to local quota file */ |
| 341 | #define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1) | 347 | #define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \ |
| 348 | OCFS2_QUOTA_BLOCK_UPDATE_CREDITS) | ||
| 342 | 349 | ||
| 343 | /* global quota data block, local quota data block, global quota inode, | 350 | /* global quota data block, local quota data block, global quota inode, |
| 344 | * global quota info */ | 351 | * global quota info */ |
| 345 | #define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3) | 352 | #define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \ |
| 353 | 2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS) | ||
| 346 | 354 | ||
| 347 | static inline int ocfs2_quota_trans_credits(struct super_block *sb) | 355 | static inline int ocfs2_quota_trans_credits(struct super_block *sb) |
| 348 | { | 356 | { |
| @@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb) | |||
| 355 | return credits; | 363 | return credits; |
| 356 | } | 364 | } |
| 357 | 365 | ||
| 358 | /* Number of credits needed for removing quota structure from file */ | ||
| 359 | int ocfs2_calc_qdel_credits(struct super_block *sb, int type); | ||
| 360 | /* Number of credits needed for initialization of new quota structure */ | ||
| 361 | int ocfs2_calc_qinit_credits(struct super_block *sb, int type); | ||
| 362 | |||
| 363 | /* group extend. inode update and last group update. */ | 366 | /* group extend. inode update and last group update. */ |
| 364 | #define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1) | 367 | #define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1) |
| 365 | 368 | ||
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index c9345ebb8493..39e1d5a39505 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -224,10 +224,12 @@ enum ocfs2_mount_options | |||
| 224 | OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */ | 224 | OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */ |
| 225 | }; | 225 | }; |
| 226 | 226 | ||
| 227 | #define OCFS2_OSB_SOFT_RO 0x0001 | 227 | #define OCFS2_OSB_SOFT_RO 0x0001 |
| 228 | #define OCFS2_OSB_HARD_RO 0x0002 | 228 | #define OCFS2_OSB_HARD_RO 0x0002 |
| 229 | #define OCFS2_OSB_ERROR_FS 0x0004 | 229 | #define OCFS2_OSB_ERROR_FS 0x0004 |
| 230 | #define OCFS2_DEFAULT_ATIME_QUANTUM 60 | 230 | #define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED 0x0008 |
| 231 | |||
| 232 | #define OCFS2_DEFAULT_ATIME_QUANTUM 60 | ||
| 231 | 233 | ||
| 232 | struct ocfs2_journal; | 234 | struct ocfs2_journal; |
| 233 | struct ocfs2_slot_info; | 235 | struct ocfs2_slot_info; |
| @@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb, | |||
| 490 | spin_unlock(&osb->osb_lock); | 492 | spin_unlock(&osb->osb_lock); |
| 491 | } | 493 | } |
| 492 | 494 | ||
| 495 | |||
| 496 | static inline unsigned long ocfs2_test_osb_flag(struct ocfs2_super *osb, | ||
| 497 | unsigned long flag) | ||
| 498 | { | ||
| 499 | unsigned long ret; | ||
| 500 | |||
| 501 | spin_lock(&osb->osb_lock); | ||
| 502 | ret = osb->osb_flags & flag; | ||
| 503 | spin_unlock(&osb->osb_lock); | ||
| 504 | return ret; | ||
| 505 | } | ||
| 506 | |||
| 493 | static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb, | 507 | static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb, |
| 494 | int hard) | 508 | int hard) |
| 495 | { | 509 | { |
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h index 7365e2e08706..3fb96fcd4c81 100644 --- a/fs/ocfs2/quota.h +++ b/fs/ocfs2/quota.h | |||
| @@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo { | |||
| 50 | unsigned int dqi_chunks; /* Number of chunks in local quota file */ | 50 | unsigned int dqi_chunks; /* Number of chunks in local quota file */ |
| 51 | unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */ | 51 | unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */ |
| 52 | unsigned int dqi_syncms; /* How often should we sync with other nodes */ | 52 | unsigned int dqi_syncms; /* How often should we sync with other nodes */ |
| 53 | unsigned int dqi_syncjiff; /* Precomputed dqi_syncms in jiffies */ | ||
| 54 | struct list_head dqi_chunk; /* List of chunks */ | 53 | struct list_head dqi_chunk; /* List of chunks */ |
| 55 | struct inode *dqi_gqinode; /* Global quota file inode */ | 54 | struct inode *dqi_gqinode; /* Global quota file inode */ |
| 56 | struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */ | 55 | struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */ |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index edfa60cd155c..bf7742d0ee3b 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
| @@ -69,6 +69,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot) | |||
| 69 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); | 69 | d->dqb_curspace = cpu_to_le64(m->dqb_curspace); |
| 70 | d->dqb_btime = cpu_to_le64(m->dqb_btime); | 70 | d->dqb_btime = cpu_to_le64(m->dqb_btime); |
| 71 | d->dqb_itime = cpu_to_le64(m->dqb_itime); | 71 | d->dqb_itime = cpu_to_le64(m->dqb_itime); |
| 72 | d->dqb_pad1 = d->dqb_pad2 = 0; | ||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | static int ocfs2_global_is_id(void *dp, struct dquot *dquot) | 75 | static int ocfs2_global_is_id(void *dp, struct dquot *dquot) |
| @@ -211,14 +212,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, | |||
| 211 | 212 | ||
| 212 | mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA); | 213 | mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA); |
| 213 | if (gqinode->i_size < off + len) { | 214 | if (gqinode->i_size < off + len) { |
| 214 | down_write(&OCFS2_I(gqinode)->ip_alloc_sem); | 215 | loff_t rounded_end = |
| 215 | err = ocfs2_extend_no_holes(gqinode, off + len, off); | 216 | ocfs2_align_bytes_to_blocks(sb, off + len); |
| 216 | up_write(&OCFS2_I(gqinode)->ip_alloc_sem); | 217 | |
| 217 | if (err < 0) | 218 | /* Space is already allocated in ocfs2_global_read_dquot() */ |
| 218 | goto out; | ||
| 219 | err = ocfs2_simple_size_update(gqinode, | 219 | err = ocfs2_simple_size_update(gqinode, |
| 220 | oinfo->dqi_gqi_bh, | 220 | oinfo->dqi_gqi_bh, |
| 221 | off + len); | 221 | rounded_end); |
| 222 | if (err < 0) | 222 | if (err < 0) |
| 223 | goto out; | 223 | goto out; |
| 224 | new = 1; | 224 | new = 1; |
| @@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type, | |||
| 234 | } | 234 | } |
| 235 | if (err) { | 235 | if (err) { |
| 236 | mlog_errno(err); | 236 | mlog_errno(err); |
| 237 | return err; | 237 | goto out; |
| 238 | } | 238 | } |
| 239 | lock_buffer(bh); | 239 | lock_buffer(bh); |
| 240 | if (new) | 240 | if (new) |
| @@ -342,7 +342,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type) | |||
| 342 | info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); | 342 | info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); |
| 343 | info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); | 343 | info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); |
| 344 | oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms); | 344 | oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms); |
| 345 | oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms); | ||
| 346 | oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks); | 345 | oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks); |
| 347 | oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk); | 346 | oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk); |
| 348 | oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry); | 347 | oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry); |
| @@ -352,7 +351,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type) | |||
| 352 | oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi); | 351 | oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi); |
| 353 | INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn); | 352 | INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn); |
| 354 | queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work, | 353 | queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work, |
| 355 | oinfo->dqi_syncjiff); | 354 | msecs_to_jiffies(oinfo->dqi_syncms)); |
| 356 | 355 | ||
| 357 | out_err: | 356 | out_err: |
| 358 | mlog_exit(status); | 357 | mlog_exit(status); |
| @@ -402,13 +401,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type) | |||
| 402 | return err; | 401 | return err; |
| 403 | } | 402 | } |
| 404 | 403 | ||
| 404 | static int ocfs2_global_qinit_alloc(struct super_block *sb, int type) | ||
| 405 | { | ||
| 406 | struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv; | ||
| 407 | |||
| 408 | /* | ||
| 409 | * We may need to allocate tree blocks and a leaf block but not the | ||
| 410 | * root block | ||
| 411 | */ | ||
| 412 | return oinfo->dqi_gi.dqi_qtree_depth; | ||
| 413 | } | ||
| 414 | |||
| 415 | static int ocfs2_calc_global_qinit_credits(struct super_block *sb, int type) | ||
| 416 | { | ||
| 417 | /* We modify all the allocated blocks, tree root, and info block */ | ||
| 418 | return (ocfs2_global_qinit_alloc(sb, type) + 2) * | ||
| 419 | OCFS2_QUOTA_BLOCK_UPDATE_CREDITS; | ||
| 420 | } | ||
| 421 | |||
| 405 | /* Read in information from global quota file and acquire a reference to it. | 422 | /* Read in information from global quota file and acquire a reference to it. |
| 406 | * dquot_acquire() has already started the transaction and locked quota file */ | 423 | * dquot_acquire() has already started the transaction and locked quota file */ |
| 407 | int ocfs2_global_read_dquot(struct dquot *dquot) | 424 | int ocfs2_global_read_dquot(struct dquot *dquot) |
| 408 | { | 425 | { |
| 409 | int err, err2, ex = 0; | 426 | int err, err2, ex = 0; |
| 410 | struct ocfs2_mem_dqinfo *info = | 427 | struct super_block *sb = dquot->dq_sb; |
| 411 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 428 | int type = dquot->dq_type; |
| 429 | struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv; | ||
| 430 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
| 431 | struct inode *gqinode = info->dqi_gqinode; | ||
| 432 | int need_alloc = ocfs2_global_qinit_alloc(sb, type); | ||
| 433 | handle_t *handle = NULL; | ||
| 412 | 434 | ||
| 413 | err = ocfs2_qinfo_lock(info, 0); | 435 | err = ocfs2_qinfo_lock(info, 0); |
| 414 | if (err < 0) | 436 | if (err < 0) |
| @@ -419,14 +441,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot) | |||
| 419 | OCFS2_DQUOT(dquot)->dq_use_count++; | 441 | OCFS2_DQUOT(dquot)->dq_use_count++; |
| 420 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; | 442 | OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace; |
| 421 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; | 443 | OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; |
| 444 | ocfs2_qinfo_unlock(info, 0); | ||
| 445 | |||
| 422 | if (!dquot->dq_off) { /* No real quota entry? */ | 446 | if (!dquot->dq_off) { /* No real quota entry? */ |
| 423 | /* Upgrade to exclusive lock for allocation */ | ||
| 424 | ocfs2_qinfo_unlock(info, 0); | ||
| 425 | err = ocfs2_qinfo_lock(info, 1); | ||
| 426 | if (err < 0) | ||
| 427 | goto out_qlock; | ||
| 428 | ex = 1; | 447 | ex = 1; |
| 448 | /* | ||
| 449 | * Add blocks to quota file before we start a transaction since | ||
| 450 | * locking allocators ranks above a transaction start | ||
| 451 | */ | ||
| 452 | WARN_ON(journal_current_handle()); | ||
| 453 | down_write(&OCFS2_I(gqinode)->ip_alloc_sem); | ||
| 454 | err = ocfs2_extend_no_holes(gqinode, | ||
| 455 | gqinode->i_size + (need_alloc << sb->s_blocksize_bits), | ||
| 456 | gqinode->i_size); | ||
| 457 | up_write(&OCFS2_I(gqinode)->ip_alloc_sem); | ||
| 458 | if (err < 0) | ||
| 459 | goto out; | ||
| 429 | } | 460 | } |
| 461 | |||
| 462 | handle = ocfs2_start_trans(osb, | ||
| 463 | ocfs2_calc_global_qinit_credits(sb, type)); | ||
| 464 | if (IS_ERR(handle)) { | ||
| 465 | err = PTR_ERR(handle); | ||
| 466 | goto out; | ||
| 467 | } | ||
| 468 | err = ocfs2_qinfo_lock(info, ex); | ||
| 469 | if (err < 0) | ||
| 470 | goto out_trans; | ||
| 430 | err = qtree_write_dquot(&info->dqi_gi, dquot); | 471 | err = qtree_write_dquot(&info->dqi_gi, dquot); |
| 431 | if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) { | 472 | if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) { |
| 432 | err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type); | 473 | err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type); |
| @@ -438,6 +479,9 @@ out_qlock: | |||
| 438 | ocfs2_qinfo_unlock(info, 1); | 479 | ocfs2_qinfo_unlock(info, 1); |
| 439 | else | 480 | else |
| 440 | ocfs2_qinfo_unlock(info, 0); | 481 | ocfs2_qinfo_unlock(info, 0); |
| 482 | out_trans: | ||
| 483 | if (handle) | ||
| 484 | ocfs2_commit_trans(osb, handle); | ||
| 441 | out: | 485 | out: |
| 442 | if (err < 0) | 486 | if (err < 0) |
| 443 | mlog_errno(err); | 487 | mlog_errno(err); |
| @@ -607,7 +651,7 @@ static void qsync_work_fn(struct work_struct *work) | |||
| 607 | 651 | ||
| 608 | dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type); | 652 | dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type); |
| 609 | queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work, | 653 | queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work, |
| 610 | oinfo->dqi_syncjiff); | 654 | msecs_to_jiffies(oinfo->dqi_syncms)); |
| 611 | } | 655 | } |
| 612 | 656 | ||
| 613 | /* | 657 | /* |
| @@ -635,20 +679,18 @@ out: | |||
| 635 | return status; | 679 | return status; |
| 636 | } | 680 | } |
| 637 | 681 | ||
| 638 | int ocfs2_calc_qdel_credits(struct super_block *sb, int type) | 682 | static int ocfs2_calc_qdel_credits(struct super_block *sb, int type) |
| 639 | { | 683 | { |
| 640 | struct ocfs2_mem_dqinfo *oinfo; | 684 | struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv; |
| 641 | int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, | 685 | /* |
| 642 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA }; | 686 | * We modify tree, leaf block, global info, local chunk header, |
| 643 | 687 | * global and local inode; OCFS2_QINFO_WRITE_CREDITS already | |
| 644 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type])) | 688 | * accounts for inode update |
| 645 | return 0; | 689 | */ |
| 646 | 690 | return (oinfo->dqi_gi.dqi_qtree_depth + 2) * | |
| 647 | oinfo = sb_dqinfo(sb, type)->dqi_priv; | 691 | OCFS2_QUOTA_BLOCK_UPDATE_CREDITS + |
| 648 | /* We modify tree, leaf block, global info, local chunk header, | 692 | OCFS2_QINFO_WRITE_CREDITS + |
| 649 | * global and local inode */ | 693 | OCFS2_INODE_UPDATE_CREDITS; |
| 650 | return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 + | ||
| 651 | 2 * OCFS2_INODE_UPDATE_CREDITS; | ||
| 652 | } | 694 | } |
| 653 | 695 | ||
| 654 | static int ocfs2_release_dquot(struct dquot *dquot) | 696 | static int ocfs2_release_dquot(struct dquot *dquot) |
| @@ -680,33 +722,10 @@ out: | |||
| 680 | return status; | 722 | return status; |
| 681 | } | 723 | } |
| 682 | 724 | ||
| 683 | int ocfs2_calc_qinit_credits(struct super_block *sb, int type) | ||
| 684 | { | ||
| 685 | struct ocfs2_mem_dqinfo *oinfo; | ||
| 686 | int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, | ||
| 687 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA }; | ||
| 688 | struct ocfs2_dinode *lfe, *gfe; | ||
| 689 | |||
| 690 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type])) | ||
| 691 | return 0; | ||
| 692 | |||
| 693 | oinfo = sb_dqinfo(sb, type)->dqi_priv; | ||
| 694 | gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data; | ||
| 695 | lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data; | ||
| 696 | /* We can extend local file + global file. In local file we | ||
| 697 | * can modify info, chunk header block and dquot block. In | ||
| 698 | * global file we can modify info, tree and leaf block */ | ||
| 699 | return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) + | ||
| 700 | ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) + | ||
| 701 | 3 + oinfo->dqi_gi.dqi_qtree_depth + 2; | ||
| 702 | } | ||
| 703 | |||
| 704 | static int ocfs2_acquire_dquot(struct dquot *dquot) | 725 | static int ocfs2_acquire_dquot(struct dquot *dquot) |
| 705 | { | 726 | { |
| 706 | handle_t *handle; | ||
| 707 | struct ocfs2_mem_dqinfo *oinfo = | 727 | struct ocfs2_mem_dqinfo *oinfo = |
| 708 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; | 728 | sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; |
| 709 | struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); | ||
| 710 | int status = 0; | 729 | int status = 0; |
| 711 | 730 | ||
| 712 | mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); | 731 | mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); |
| @@ -715,16 +734,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) | |||
| 715 | status = ocfs2_lock_global_qf(oinfo, 1); | 734 | status = ocfs2_lock_global_qf(oinfo, 1); |
| 716 | if (status < 0) | 735 | if (status < 0) |
| 717 | goto out; | 736 | goto out; |
| 718 | handle = ocfs2_start_trans(osb, | ||
| 719 | ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type)); | ||
| 720 | if (IS_ERR(handle)) { | ||
| 721 | status = PTR_ERR(handle); | ||
| 722 | mlog_errno(status); | ||
| 723 | goto out_ilock; | ||
| 724 | } | ||
| 725 | status = dquot_acquire(dquot); | 737 | status = dquot_acquire(dquot); |
| 726 | ocfs2_commit_trans(osb, handle); | ||
| 727 | out_ilock: | ||
| 728 | ocfs2_unlock_global_qf(oinfo, 1); | 738 | ocfs2_unlock_global_qf(oinfo, 1); |
| 729 | out: | 739 | out: |
| 730 | mlog_exit(status); | 740 | mlog_exit(status); |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 5a460fa82553..bdb09cb6e1fe 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "sysfile.h" | 20 | #include "sysfile.h" |
| 21 | #include "dlmglue.h" | 21 | #include "dlmglue.h" |
| 22 | #include "quota.h" | 22 | #include "quota.h" |
| 23 | #include "uptodate.h" | ||
| 23 | 24 | ||
| 24 | /* Number of local quota structures per block */ | 25 | /* Number of local quota structures per block */ |
| 25 | static inline unsigned int ol_quota_entries_per_block(struct super_block *sb) | 26 | static inline unsigned int ol_quota_entries_per_block(struct super_block *sb) |
| @@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh, | |||
| 100 | handle_t *handle; | 101 | handle_t *handle; |
| 101 | int status; | 102 | int status; |
| 102 | 103 | ||
| 103 | handle = ocfs2_start_trans(OCFS2_SB(sb), 1); | 104 | handle = ocfs2_start_trans(OCFS2_SB(sb), |
| 105 | OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); | ||
| 104 | if (IS_ERR(handle)) { | 106 | if (IS_ERR(handle)) { |
| 105 | status = PTR_ERR(handle); | 107 | status = PTR_ERR(handle); |
| 106 | mlog_errno(status); | 108 | mlog_errno(status); |
| @@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, | |||
| 610 | goto out_bh; | 612 | goto out_bh; |
| 611 | /* Mark quota file as clean if we are recovering quota file of | 613 | /* Mark quota file as clean if we are recovering quota file of |
| 612 | * some other node. */ | 614 | * some other node. */ |
| 613 | handle = ocfs2_start_trans(osb, 1); | 615 | handle = ocfs2_start_trans(osb, |
| 616 | OCFS2_LOCAL_QINFO_WRITE_CREDITS); | ||
| 614 | if (IS_ERR(handle)) { | 617 | if (IS_ERR(handle)) { |
| 615 | status = PTR_ERR(handle); | 618 | status = PTR_ERR(handle); |
| 616 | mlog_errno(status); | 619 | mlog_errno(status); |
| @@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 940 | struct ocfs2_local_disk_chunk *dchunk; | 943 | struct ocfs2_local_disk_chunk *dchunk; |
| 941 | int status; | 944 | int status; |
| 942 | handle_t *handle; | 945 | handle_t *handle; |
| 943 | struct buffer_head *bh = NULL; | 946 | struct buffer_head *bh = NULL, *dbh = NULL; |
| 944 | u64 p_blkno; | 947 | u64 p_blkno; |
| 945 | 948 | ||
| 946 | /* We are protected by dqio_sem so no locking needed */ | 949 | /* We are protected by dqio_sem so no locking needed */ |
| @@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 964 | mlog_errno(status); | 967 | mlog_errno(status); |
| 965 | goto out; | 968 | goto out; |
| 966 | } | 969 | } |
| 970 | /* Local quota info and two new blocks we initialize */ | ||
| 971 | handle = ocfs2_start_trans(OCFS2_SB(sb), | ||
| 972 | OCFS2_LOCAL_QINFO_WRITE_CREDITS + | ||
| 973 | 2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); | ||
| 974 | if (IS_ERR(handle)) { | ||
| 975 | status = PTR_ERR(handle); | ||
| 976 | mlog_errno(status); | ||
| 977 | goto out; | ||
| 978 | } | ||
| 967 | 979 | ||
| 980 | /* Initialize chunk header */ | ||
| 968 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | 981 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); |
| 969 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, | 982 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, |
| 970 | &p_blkno, NULL, NULL); | 983 | &p_blkno, NULL, NULL); |
| 971 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | 984 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); |
| 972 | if (status < 0) { | 985 | if (status < 0) { |
| 973 | mlog_errno(status); | 986 | mlog_errno(status); |
| 974 | goto out; | 987 | goto out_trans; |
| 975 | } | 988 | } |
| 976 | bh = sb_getblk(sb, p_blkno); | 989 | bh = sb_getblk(sb, p_blkno); |
| 977 | if (!bh) { | 990 | if (!bh) { |
| 978 | status = -ENOMEM; | 991 | status = -ENOMEM; |
| 979 | mlog_errno(status); | 992 | mlog_errno(status); |
| 980 | goto out; | 993 | goto out_trans; |
| 981 | } | 994 | } |
| 982 | dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; | 995 | dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data; |
| 983 | 996 | ocfs2_set_new_buffer_uptodate(lqinode, bh); | |
| 984 | handle = ocfs2_start_trans(OCFS2_SB(sb), 2); | ||
| 985 | if (IS_ERR(handle)) { | ||
| 986 | status = PTR_ERR(handle); | ||
| 987 | mlog_errno(status); | ||
| 988 | goto out; | ||
| 989 | } | ||
| 990 | |||
| 991 | status = ocfs2_journal_access_dq(handle, lqinode, bh, | 997 | status = ocfs2_journal_access_dq(handle, lqinode, bh, |
| 992 | OCFS2_JOURNAL_ACCESS_WRITE); | 998 | OCFS2_JOURNAL_ACCESS_CREATE); |
| 993 | if (status < 0) { | 999 | if (status < 0) { |
| 994 | mlog_errno(status); | 1000 | mlog_errno(status); |
| 995 | goto out_trans; | 1001 | goto out_trans; |
| @@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 999 | memset(dchunk->dqc_bitmap, 0, | 1005 | memset(dchunk->dqc_bitmap, 0, |
| 1000 | sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) - | 1006 | sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) - |
| 1001 | OCFS2_QBLK_RESERVED_SPACE); | 1007 | OCFS2_QBLK_RESERVED_SPACE); |
| 1002 | set_buffer_uptodate(bh); | ||
| 1003 | unlock_buffer(bh); | 1008 | unlock_buffer(bh); |
| 1004 | status = ocfs2_journal_dirty(handle, bh); | 1009 | status = ocfs2_journal_dirty(handle, bh); |
| 1005 | if (status < 0) { | 1010 | if (status < 0) { |
| @@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
| 1007 | goto out_trans; | 1012 | goto out_trans; |
| 1008 | } | 1013 | } |
| 1009 | 1014 | ||
| 1015 | /* Initialize new block with structures */ | ||
| 1016 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1017 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1, | ||
| 1018 | &p_blkno, NULL, NULL); | ||
| 1019 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1020 | if (status < 0) { | ||
| 1021 | mlog_errno(status); | ||
| 1022 | goto out_trans; | ||
| 1023 | } | ||
| 1024 | dbh = sb_getblk(sb, p_blkno); | ||
| 1025 | if (!dbh) { | ||
| 1026 | status = -ENOMEM; | ||
| 1027 | mlog_errno(status); | ||
| 1028 | goto out_trans; | ||
| 1029 | } | ||
| 1030 | ocfs2_set_new_buffer_uptodate(lqinode, dbh); | ||
| 1031 | status = ocfs2_journal_access_dq(handle, lqinode, dbh, | ||
| 1032 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
| 1033 | if (status < 0) { | ||
| 1034 | mlog_errno(status); | ||
| 1035 | goto out_trans; | ||
| 1036 | } | ||
| 1037 | lock_buffer(dbh); | ||
| 1038 | memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE); | ||
| 1039 | unlock_buffer(dbh); | ||
| 1040 | status = ocfs2_journal_dirty(handle, dbh); | ||
| 1041 | if (status < 0) { | ||
| 1042 | mlog_errno(status); | ||
| 1043 | goto out_trans; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* Update local quotafile info */ | ||
| 1010 | oinfo->dqi_blocks += 2; | 1047 | oinfo->dqi_blocks += 2; |
| 1011 | oinfo->dqi_chunks++; | 1048 | oinfo->dqi_chunks++; |
| 1012 | status = ocfs2_local_write_info(sb, type); | 1049 | status = ocfs2_local_write_info(sb, type); |
| @@ -1031,6 +1068,7 @@ out_trans: | |||
| 1031 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | 1068 | ocfs2_commit_trans(OCFS2_SB(sb), handle); |
| 1032 | out: | 1069 | out: |
| 1033 | brelse(bh); | 1070 | brelse(bh); |
| 1071 | brelse(dbh); | ||
| 1034 | kmem_cache_free(ocfs2_qf_chunk_cachep, chunk); | 1072 | kmem_cache_free(ocfs2_qf_chunk_cachep, chunk); |
| 1035 | return ERR_PTR(status); | 1073 | return ERR_PTR(status); |
| 1036 | } | 1074 | } |
| @@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1048 | struct ocfs2_local_disk_chunk *dchunk; | 1086 | struct ocfs2_local_disk_chunk *dchunk; |
| 1049 | int epb = ol_quota_entries_per_block(sb); | 1087 | int epb = ol_quota_entries_per_block(sb); |
| 1050 | unsigned int chunk_blocks; | 1088 | unsigned int chunk_blocks; |
| 1089 | struct buffer_head *bh; | ||
| 1090 | u64 p_blkno; | ||
| 1051 | int status; | 1091 | int status; |
| 1052 | handle_t *handle; | 1092 | handle_t *handle; |
| 1053 | 1093 | ||
| @@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1075 | mlog_errno(status); | 1115 | mlog_errno(status); |
| 1076 | goto out; | 1116 | goto out; |
| 1077 | } | 1117 | } |
| 1078 | handle = ocfs2_start_trans(OCFS2_SB(sb), 2); | 1118 | |
| 1119 | /* Get buffer from the just added block */ | ||
| 1120 | down_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1121 | status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks, | ||
| 1122 | &p_blkno, NULL, NULL); | ||
| 1123 | up_read(&OCFS2_I(lqinode)->ip_alloc_sem); | ||
| 1124 | if (status < 0) { | ||
| 1125 | mlog_errno(status); | ||
| 1126 | goto out; | ||
| 1127 | } | ||
| 1128 | bh = sb_getblk(sb, p_blkno); | ||
| 1129 | if (!bh) { | ||
| 1130 | status = -ENOMEM; | ||
| 1131 | mlog_errno(status); | ||
| 1132 | goto out; | ||
| 1133 | } | ||
| 1134 | ocfs2_set_new_buffer_uptodate(lqinode, bh); | ||
| 1135 | |||
| 1136 | /* Local quota info, chunk header and the new block we initialize */ | ||
| 1137 | handle = ocfs2_start_trans(OCFS2_SB(sb), | ||
| 1138 | OCFS2_LOCAL_QINFO_WRITE_CREDITS + | ||
| 1139 | 2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS); | ||
| 1079 | if (IS_ERR(handle)) { | 1140 | if (IS_ERR(handle)) { |
| 1080 | status = PTR_ERR(handle); | 1141 | status = PTR_ERR(handle); |
| 1081 | mlog_errno(status); | 1142 | mlog_errno(status); |
| 1082 | goto out; | 1143 | goto out; |
| 1083 | } | 1144 | } |
| 1145 | /* Zero created block */ | ||
| 1146 | status = ocfs2_journal_access_dq(handle, lqinode, bh, | ||
| 1147 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
| 1148 | if (status < 0) { | ||
| 1149 | mlog_errno(status); | ||
| 1150 | goto out_trans; | ||
| 1151 | } | ||
| 1152 | lock_buffer(bh); | ||
| 1153 | memset(bh->b_data, 0, sb->s_blocksize); | ||
| 1154 | unlock_buffer(bh); | ||
| 1155 | status = ocfs2_journal_dirty(handle, bh); | ||
| 1156 | if (status < 0) { | ||
| 1157 | mlog_errno(status); | ||
| 1158 | goto out_trans; | ||
| 1159 | } | ||
| 1160 | /* Update chunk header */ | ||
| 1084 | status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh, | 1161 | status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh, |
| 1085 | OCFS2_JOURNAL_ACCESS_WRITE); | 1162 | OCFS2_JOURNAL_ACCESS_WRITE); |
| 1086 | if (status < 0) { | 1163 | if (status < 0) { |
| @@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
| 1097 | mlog_errno(status); | 1174 | mlog_errno(status); |
| 1098 | goto out_trans; | 1175 | goto out_trans; |
| 1099 | } | 1176 | } |
| 1177 | /* Update file header */ | ||
| 1100 | oinfo->dqi_blocks++; | 1178 | oinfo->dqi_blocks++; |
| 1101 | status = ocfs2_local_write_info(sb, type); | 1179 | status = ocfs2_local_write_info(sb, type); |
| 1102 | if (status < 0) { | 1180 | if (status < 0) { |
diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c index 3f661376a2de..e49c41050264 100644 --- a/fs/ocfs2/stack_o2cb.c +++ b/fs/ocfs2/stack_o2cb.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * General Public License for more details. | 17 | * General Public License for more details. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/kernel.h> | ||
| 20 | #include <linux/crc32.h> | 21 | #include <linux/crc32.h> |
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | 23 | ||
| @@ -153,7 +154,7 @@ static int status_map[] = { | |||
| 153 | 154 | ||
| 154 | static int dlm_status_to_errno(enum dlm_status status) | 155 | static int dlm_status_to_errno(enum dlm_status status) |
| 155 | { | 156 | { |
| 156 | BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0]))); | 157 | BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map)); |
| 157 | 158 | ||
| 158 | return status_map[status]; | 159 | return status_map[status]; |
| 159 | } | 160 | } |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 7efb349fb9bd..b0ee0fdf799a 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
| 777 | } | 777 | } |
| 778 | di = (struct ocfs2_dinode *) (*bh)->b_data; | 778 | di = (struct ocfs2_dinode *) (*bh)->b_data; |
| 779 | memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); | 779 | memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); |
| 780 | spin_lock_init(&stats->b_lock); | ||
| 780 | status = ocfs2_verify_volume(di, *bh, blksize, stats); | 781 | status = ocfs2_verify_volume(di, *bh, blksize, stats); |
| 781 | if (status >= 0) | 782 | if (status >= 0) |
| 782 | goto bail; | 783 | goto bail; |
| @@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1182 | wake_up(&osb->osb_mount_event); | 1183 | wake_up(&osb->osb_mount_event); |
| 1183 | 1184 | ||
| 1184 | /* Start this when the mount is almost sure of being successful */ | 1185 | /* Start this when the mount is almost sure of being successful */ |
| 1185 | ocfs2_orphan_scan_init(osb); | 1186 | ocfs2_orphan_scan_start(osb); |
| 1186 | 1187 | ||
| 1187 | mlog_exit(status); | 1188 | mlog_exit(status); |
| 1188 | return status; | 1189 | return status; |
| @@ -1213,14 +1214,27 @@ static int ocfs2_get_sb(struct file_system_type *fs_type, | |||
| 1213 | mnt); | 1214 | mnt); |
| 1214 | } | 1215 | } |
| 1215 | 1216 | ||
| 1217 | static void ocfs2_kill_sb(struct super_block *sb) | ||
| 1218 | { | ||
| 1219 | struct ocfs2_super *osb = OCFS2_SB(sb); | ||
| 1220 | |||
| 1221 | /* Prevent further queueing of inode drop events */ | ||
| 1222 | spin_lock(&dentry_list_lock); | ||
| 1223 | ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED); | ||
| 1224 | spin_unlock(&dentry_list_lock); | ||
| 1225 | /* Wait for work to finish and/or remove it */ | ||
| 1226 | cancel_work_sync(&osb->dentry_lock_work); | ||
| 1227 | |||
| 1228 | kill_block_super(sb); | ||
| 1229 | } | ||
| 1230 | |||
| 1216 | static struct file_system_type ocfs2_fs_type = { | 1231 | static struct file_system_type ocfs2_fs_type = { |
| 1217 | .owner = THIS_MODULE, | 1232 | .owner = THIS_MODULE, |
| 1218 | .name = "ocfs2", | 1233 | .name = "ocfs2", |
| 1219 | .get_sb = ocfs2_get_sb, /* is this called when we mount | 1234 | .get_sb = ocfs2_get_sb, /* is this called when we mount |
| 1220 | * the fs? */ | 1235 | * the fs? */ |
| 1221 | .kill_sb = kill_block_super, /* set to the generic one | 1236 | .kill_sb = ocfs2_kill_sb, |
| 1222 | * right now, but do we | 1237 | |
| 1223 | * need to change that? */ | ||
| 1224 | .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE, | 1238 | .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE, |
| 1225 | .next = NULL | 1239 | .next = NULL |
| 1226 | }; | 1240 | }; |
| @@ -1819,6 +1833,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
| 1819 | 1833 | ||
| 1820 | debugfs_remove(osb->osb_ctxt); | 1834 | debugfs_remove(osb->osb_ctxt); |
| 1821 | 1835 | ||
| 1836 | /* | ||
| 1837 | * Flush inode dropping work queue so that deletes are | ||
| 1838 | * performed while the filesystem is still working | ||
| 1839 | */ | ||
| 1840 | ocfs2_drop_all_dl_inodes(osb); | ||
| 1841 | |||
| 1822 | /* Orphan scan should be stopped as early as possible */ | 1842 | /* Orphan scan should be stopped as early as possible */ |
| 1823 | ocfs2_orphan_scan_stop(osb); | 1843 | ocfs2_orphan_scan_stop(osb); |
| 1824 | 1844 | ||
| @@ -1981,6 +2001,8 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
| 1981 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 2001 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
| 1982 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); | 2002 | MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev)); |
| 1983 | 2003 | ||
| 2004 | ocfs2_orphan_scan_init(osb); | ||
| 2005 | |||
| 1984 | status = ocfs2_recovery_init(osb); | 2006 | status = ocfs2_recovery_init(osb); |
| 1985 | if (status) { | 2007 | if (status) { |
| 1986 | mlog(ML_ERROR, "Unable to initialize recovery state\n"); | 2008 | mlog(ML_ERROR, "Unable to initialize recovery state\n"); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index ba320e250747..d1a27cda984f 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 1052 | struct ocfs2_xattr_block *xb; | 1052 | struct ocfs2_xattr_block *xb; |
| 1053 | struct ocfs2_xattr_value_root *xv; | 1053 | struct ocfs2_xattr_value_root *xv; |
| 1054 | size_t size; | 1054 | size_t size; |
| 1055 | int ret = -ENODATA, name_offset, name_len, block_off, i; | 1055 | int ret = -ENODATA, name_offset, name_len, i; |
| 1056 | int uninitialized_var(block_off); | ||
| 1056 | 1057 | ||
| 1057 | xs->bucket = ocfs2_xattr_bucket_new(inode); | 1058 | xs->bucket = ocfs2_xattr_bucket_new(inode); |
| 1058 | if (!xs->bucket) { | 1059 | if (!xs->bucket) { |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 1a9c7878f864..ea4e6cb29e13 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -436,7 +436,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
| 436 | rcu_assign_pointer(ptbl->part[partno], p); | 436 | rcu_assign_pointer(ptbl->part[partno], p); |
| 437 | 437 | ||
| 438 | /* suppress uevent if the disk supresses it */ | 438 | /* suppress uevent if the disk supresses it */ |
| 439 | if (!dev_get_uevent_suppress(pdev)) | 439 | if (!dev_get_uevent_suppress(ddev)) |
| 440 | kobject_uevent(&pdev->kobj, KOBJ_ADD); | 440 | kobject_uevent(&pdev->kobj, KOBJ_ADD); |
| 441 | 441 | ||
| 442 | return p; | 442 | return p; |
| @@ -68,8 +68,8 @@ void pipe_double_lock(struct pipe_inode_info *pipe1, | |||
| 68 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | 68 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); |
| 69 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | 69 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); |
| 70 | } else { | 70 | } else { |
| 71 | pipe_lock_nested(pipe2, I_MUTEX_CHILD); | 71 | pipe_lock_nested(pipe2, I_MUTEX_PARENT); |
| 72 | pipe_lock_nested(pipe1, I_MUTEX_PARENT); | 72 | pipe_lock_nested(pipe1, I_MUTEX_CHILD); |
| 73 | } | 73 | } |
| 74 | } | 74 | } |
| 75 | 75 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 3ce5ae9e3d2d..6f742f6658a9 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -234,23 +234,20 @@ static int check_mem_permission(struct task_struct *task) | |||
| 234 | 234 | ||
| 235 | struct mm_struct *mm_for_maps(struct task_struct *task) | 235 | struct mm_struct *mm_for_maps(struct task_struct *task) |
| 236 | { | 236 | { |
| 237 | struct mm_struct *mm = get_task_mm(task); | 237 | struct mm_struct *mm; |
| 238 | if (!mm) | 238 | |
| 239 | if (mutex_lock_killable(&task->cred_guard_mutex)) | ||
| 239 | return NULL; | 240 | return NULL; |
| 240 | down_read(&mm->mmap_sem); | 241 | |
| 241 | task_lock(task); | 242 | mm = get_task_mm(task); |
| 242 | if (task->mm != mm) | 243 | if (mm && mm != current->mm && |
| 243 | goto out; | 244 | !ptrace_may_access(task, PTRACE_MODE_READ)) { |
| 244 | if (task->mm != current->mm && | 245 | mmput(mm); |
| 245 | __ptrace_may_access(task, PTRACE_MODE_READ) < 0) | 246 | mm = NULL; |
| 246 | goto out; | 247 | } |
| 247 | task_unlock(task); | 248 | mutex_unlock(&task->cred_guard_mutex); |
| 249 | |||
| 248 | return mm; | 250 | return mm; |
| 249 | out: | ||
| 250 | task_unlock(task); | ||
| 251 | up_read(&mm->mmap_sem); | ||
| 252 | mmput(mm); | ||
| 253 | return NULL; | ||
| 254 | } | 251 | } |
| 255 | 252 | ||
| 256 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 253 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
| @@ -1006,12 +1003,7 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf, | |||
| 1006 | 1003 | ||
| 1007 | if (!task) | 1004 | if (!task) |
| 1008 | return -ESRCH; | 1005 | return -ESRCH; |
| 1009 | task_lock(task); | 1006 | oom_adjust = task->oomkilladj; |
| 1010 | if (task->mm) | ||
| 1011 | oom_adjust = task->mm->oom_adj; | ||
| 1012 | else | ||
| 1013 | oom_adjust = OOM_DISABLE; | ||
| 1014 | task_unlock(task); | ||
| 1015 | put_task_struct(task); | 1007 | put_task_struct(task); |
| 1016 | 1008 | ||
| 1017 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); | 1009 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); |
| @@ -1040,19 +1032,11 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
| 1040 | task = get_proc_task(file->f_path.dentry->d_inode); | 1032 | task = get_proc_task(file->f_path.dentry->d_inode); |
| 1041 | if (!task) | 1033 | if (!task) |
| 1042 | return -ESRCH; | 1034 | return -ESRCH; |
| 1043 | task_lock(task); | 1035 | if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) { |
| 1044 | if (!task->mm) { | ||
| 1045 | task_unlock(task); | ||
| 1046 | put_task_struct(task); | ||
| 1047 | return -EINVAL; | ||
| 1048 | } | ||
| 1049 | if (oom_adjust < task->mm->oom_adj && !capable(CAP_SYS_RESOURCE)) { | ||
| 1050 | task_unlock(task); | ||
| 1051 | put_task_struct(task); | 1036 | put_task_struct(task); |
| 1052 | return -EACCES; | 1037 | return -EACCES; |
| 1053 | } | 1038 | } |
| 1054 | task->mm->oom_adj = oom_adjust; | 1039 | task->oomkilladj = oom_adjust; |
| 1055 | task_unlock(task); | ||
| 1056 | put_task_struct(task); | 1040 | put_task_struct(task); |
| 1057 | if (end - buffer == 0) | 1041 | if (end - buffer == 0) |
| 1058 | return -EIO; | 1042 | return -EIO; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 6f61b7cc32e0..9bd8be1d235c 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -119,6 +119,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
| 119 | mm = mm_for_maps(priv->task); | 119 | mm = mm_for_maps(priv->task); |
| 120 | if (!mm) | 120 | if (!mm) |
| 121 | return NULL; | 121 | return NULL; |
| 122 | down_read(&mm->mmap_sem); | ||
| 122 | 123 | ||
| 123 | tail_vma = get_gate_vma(priv->task); | 124 | tail_vma = get_gate_vma(priv->task); |
| 124 | priv->tail_vma = tail_vma; | 125 | priv->tail_vma = tail_vma; |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 64a72e2e7650..8f5c05d3dbd3 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
| @@ -189,6 +189,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
| 189 | priv->task = NULL; | 189 | priv->task = NULL; |
| 190 | return NULL; | 190 | return NULL; |
| 191 | } | 191 | } |
| 192 | down_read(&mm->mmap_sem); | ||
| 192 | 193 | ||
| 193 | /* start from the Nth VMA */ | 194 | /* start from the Nth VMA */ |
| 194 | for (p = rb_first(&mm->mm_rb); p; p = rb_next(p)) | 195 | for (p = rb_first(&mm->mm_rb); p; p = rb_next(p)) |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 607c579e5eca..38f7bd559f35 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -2042,7 +2042,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2042 | * changes */ | 2042 | * changes */ |
| 2043 | invalidate_bdev(sb->s_bdev); | 2043 | invalidate_bdev(sb->s_bdev); |
| 2044 | } | 2044 | } |
| 2045 | mutex_lock(&inode->i_mutex); | ||
| 2046 | mutex_lock(&dqopt->dqonoff_mutex); | 2045 | mutex_lock(&dqopt->dqonoff_mutex); |
| 2047 | if (sb_has_quota_loaded(sb, type)) { | 2046 | if (sb_has_quota_loaded(sb, type)) { |
| 2048 | error = -EBUSY; | 2047 | error = -EBUSY; |
| @@ -2054,9 +2053,11 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2054 | * possible) Also nobody should write to the file - we use | 2053 | * possible) Also nobody should write to the file - we use |
| 2055 | * special IO operations which ignore the immutable bit. */ | 2054 | * special IO operations which ignore the immutable bit. */ |
| 2056 | down_write(&dqopt->dqptr_sem); | 2055 | down_write(&dqopt->dqptr_sem); |
| 2056 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | ||
| 2057 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | | 2057 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | |
| 2058 | S_NOQUOTA); | 2058 | S_NOQUOTA); |
| 2059 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | 2059 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; |
| 2060 | mutex_unlock(&inode->i_mutex); | ||
| 2060 | up_write(&dqopt->dqptr_sem); | 2061 | up_write(&dqopt->dqptr_sem); |
| 2061 | sb->dq_op->drop(inode); | 2062 | sb->dq_op->drop(inode); |
| 2062 | } | 2063 | } |
| @@ -2080,7 +2081,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
| 2080 | goto out_file_init; | 2081 | goto out_file_init; |
| 2081 | } | 2082 | } |
| 2082 | mutex_unlock(&dqopt->dqio_mutex); | 2083 | mutex_unlock(&dqopt->dqio_mutex); |
| 2083 | mutex_unlock(&inode->i_mutex); | ||
| 2084 | spin_lock(&dq_state_lock); | 2084 | spin_lock(&dq_state_lock); |
| 2085 | dqopt->flags |= dquot_state_flag(flags, type); | 2085 | dqopt->flags |= dquot_state_flag(flags, type); |
| 2086 | spin_unlock(&dq_state_lock); | 2086 | spin_unlock(&dq_state_lock); |
| @@ -2094,16 +2094,17 @@ out_file_init: | |||
| 2094 | dqopt->files[type] = NULL; | 2094 | dqopt->files[type] = NULL; |
| 2095 | iput(inode); | 2095 | iput(inode); |
| 2096 | out_lock: | 2096 | out_lock: |
| 2097 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
| 2098 | if (oldflags != -1) { | 2097 | if (oldflags != -1) { |
| 2099 | down_write(&dqopt->dqptr_sem); | 2098 | down_write(&dqopt->dqptr_sem); |
| 2099 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | ||
| 2100 | /* Set the flags back (in the case of accidental quotaon() | 2100 | /* Set the flags back (in the case of accidental quotaon() |
| 2101 | * on a wrong file we don't want to mess up the flags) */ | 2101 | * on a wrong file we don't want to mess up the flags) */ |
| 2102 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); | 2102 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); |
| 2103 | inode->i_flags |= oldflags; | 2103 | inode->i_flags |= oldflags; |
| 2104 | mutex_unlock(&inode->i_mutex); | ||
| 2104 | up_write(&dqopt->dqptr_sem); | 2105 | up_write(&dqopt->dqptr_sem); |
| 2105 | } | 2106 | } |
| 2106 | mutex_unlock(&inode->i_mutex); | 2107 | mutex_unlock(&dqopt->dqonoff_mutex); |
| 2107 | out_fmt: | 2108 | out_fmt: |
| 2108 | put_quota_format(fmt); | 2109 | put_quota_format(fmt); |
| 2109 | 2110 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index ebb2c417912c..11f0c06316de 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/ramfs.h> | 20 | #include <linux/ramfs.h> |
| 21 | #include <linux/pagevec.h> | 21 | #include <linux/pagevec.h> |
| 22 | #include <linux/mman.h> | 22 | #include <linux/mman.h> |
| 23 | #include <linux/sched.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
| 25 | #include "internal.h" | 26 | #include "internal.h" |
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 77f5bb746bf0..90622200b39c 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -997,7 +997,7 @@ static int reiserfs_async_progress_wait(struct super_block *s) | |||
| 997 | DEFINE_WAIT(wait); | 997 | DEFINE_WAIT(wait); |
| 998 | struct reiserfs_journal *j = SB_JOURNAL(s); | 998 | struct reiserfs_journal *j = SB_JOURNAL(s); |
| 999 | if (atomic_read(&j->j_async_throttle)) | 999 | if (atomic_read(&j->j_async_throttle)) |
| 1000 | congestion_wait(WRITE, HZ / 10); | 1000 | congestion_wait(BLK_RW_ASYNC, HZ / 10); |
| 1001 | return 0; | 1001 | return 0; |
| 1002 | } | 1002 | } |
| 1003 | 1003 | ||
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d3aeb061612b..7adea74d6a8a 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #include <linux/exportfs.h> | 24 | #include <linux/exportfs.h> |
| 25 | #include <linux/quotaops.h> | 25 | #include <linux/quotaops.h> |
| 26 | #include <linux/vfs.h> | 26 | #include <linux/vfs.h> |
| 27 | #include <linux/mnt_namespace.h> | ||
| 28 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
| 29 | #include <linux/namei.h> | 28 | #include <linux/namei.h> |
| 30 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index f3d47d856848..6925b835a43b 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -46,7 +46,6 @@ | |||
| 46 | #include <linux/reiserfs_acl.h> | 46 | #include <linux/reiserfs_acl.h> |
| 47 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| 48 | #include <net/checksum.h> | 48 | #include <net/checksum.h> |
| 49 | #include <linux/smp_lock.h> | ||
| 50 | #include <linux/stat.h> | 49 | #include <linux/stat.h> |
| 51 | #include <linux/quotaops.h> | 50 | #include <linux/quotaops.h> |
| 52 | 51 | ||
diff --git a/fs/select.c b/fs/select.c index d870237e42c7..8084834e123e 100644 --- a/fs/select.c +++ b/fs/select.c | |||
| @@ -110,6 +110,7 @@ void poll_initwait(struct poll_wqueues *pwq) | |||
| 110 | { | 110 | { |
| 111 | init_poll_funcptr(&pwq->pt, __pollwait); | 111 | init_poll_funcptr(&pwq->pt, __pollwait); |
| 112 | pwq->polling_task = current; | 112 | pwq->polling_task = current; |
| 113 | pwq->triggered = 0; | ||
| 113 | pwq->error = 0; | 114 | pwq->error = 0; |
| 114 | pwq->table = NULL; | 115 | pwq->table = NULL; |
| 115 | pwq->inline_index = 0; | 116 | pwq->inline_index = 0; |
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 3b52770f46ff..cb5fc57e370b 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
| 31 | #include <linux/vfs.h> | 31 | #include <linux/vfs.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/smp_lock.h> | ||
| 33 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
| 34 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
| 35 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| @@ -112,8 +112,13 @@ restart: | |||
| 112 | mutex_unlock(&mutex); | 112 | mutex_unlock(&mutex); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | /* | ||
| 116 | * sync everything. Start out by waking pdflush, because that writes back | ||
| 117 | * all queues in parallel. | ||
| 118 | */ | ||
| 115 | SYSCALL_DEFINE0(sync) | 119 | SYSCALL_DEFINE0(sync) |
| 116 | { | 120 | { |
| 121 | wakeup_pdflush(0); | ||
| 117 | sync_filesystems(0); | 122 | sync_filesystems(0); |
| 118 | sync_filesystems(1); | 123 | sync_filesystems(1); |
| 119 | if (unlikely(laptop_mode)) | 124 | if (unlikely(laptop_mode)) |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 9345806c8853..2524714bece1 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -171,6 +171,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
| 171 | if (count > 0) | 171 | if (count > 0) |
| 172 | *off = offs + count; | 172 | *off = offs + count; |
| 173 | 173 | ||
| 174 | kfree(temp); | ||
| 174 | return count; | 175 | return count; |
| 175 | } | 176 | } |
| 176 | 177 | ||
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index d88d0fac9fa5..14f2d71ea3ce 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -939,8 +939,10 @@ again: | |||
| 939 | /* Remove from old parent's list and insert into new parent's list. */ | 939 | /* Remove from old parent's list and insert into new parent's list. */ |
| 940 | sysfs_unlink_sibling(sd); | 940 | sysfs_unlink_sibling(sd); |
| 941 | sysfs_get(new_parent_sd); | 941 | sysfs_get(new_parent_sd); |
| 942 | drop_nlink(old_parent->d_inode); | ||
| 942 | sysfs_put(sd->s_parent); | 943 | sysfs_put(sd->s_parent); |
| 943 | sd->s_parent = new_parent_sd; | 944 | sd->s_parent = new_parent_sd; |
| 945 | inc_nlink(new_parent->d_inode); | ||
| 944 | sysfs_link_sibling(sd); | 946 | sysfs_link_sibling(sd); |
| 945 | 947 | ||
| 946 | out_unlock: | 948 | out_unlock: |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index bc5857199ec2..762a7d6cec73 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
| @@ -297,6 +297,7 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer) | |||
| 297 | { | 297 | { |
| 298 | struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer); | 298 | struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer); |
| 299 | 299 | ||
| 300 | dbg_io("jhead %d", wbuf->jhead); | ||
| 300 | wbuf->need_sync = 1; | 301 | wbuf->need_sync = 1; |
| 301 | wbuf->c->need_wbuf_sync = 1; | 302 | wbuf->c->need_wbuf_sync = 1; |
| 302 | ubifs_wake_up_bgt(wbuf->c); | 303 | ubifs_wake_up_bgt(wbuf->c); |
| @@ -311,8 +312,12 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) | |||
| 311 | { | 312 | { |
| 312 | ubifs_assert(!hrtimer_active(&wbuf->timer)); | 313 | ubifs_assert(!hrtimer_active(&wbuf->timer)); |
| 313 | 314 | ||
| 314 | if (!ktime_to_ns(wbuf->softlimit)) | 315 | if (wbuf->no_timer) |
| 315 | return; | 316 | return; |
| 317 | dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead, | ||
| 318 | div_u64(ktime_to_ns(wbuf->softlimit), USEC_PER_SEC), | ||
| 319 | div_u64(ktime_to_ns(wbuf->softlimit) + wbuf->delta, | ||
| 320 | USEC_PER_SEC)); | ||
| 316 | hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta, | 321 | hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta, |
| 317 | HRTIMER_MODE_REL); | 322 | HRTIMER_MODE_REL); |
| 318 | } | 323 | } |
| @@ -323,11 +328,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) | |||
| 323 | */ | 328 | */ |
| 324 | static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) | 329 | static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) |
| 325 | { | 330 | { |
| 326 | /* | 331 | if (wbuf->no_timer) |
| 327 | * If the syncer is waiting for the lock (from the background thread's | 332 | return; |
| 328 | * context) and another task is changing write-buffer then the syncing | ||
| 329 | * should be canceled. | ||
| 330 | */ | ||
| 331 | wbuf->need_sync = 0; | 333 | wbuf->need_sync = 0; |
| 332 | hrtimer_cancel(&wbuf->timer); | 334 | hrtimer_cancel(&wbuf->timer); |
| 333 | } | 335 | } |
| @@ -349,8 +351,8 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) | |||
| 349 | /* Write-buffer is empty or not seeked */ | 351 | /* Write-buffer is empty or not seeked */ |
| 350 | return 0; | 352 | return 0; |
| 351 | 353 | ||
| 352 | dbg_io("LEB %d:%d, %d bytes", | 354 | dbg_io("LEB %d:%d, %d bytes, jhead %d", |
| 353 | wbuf->lnum, wbuf->offs, wbuf->used); | 355 | wbuf->lnum, wbuf->offs, wbuf->used, wbuf->jhead); |
| 354 | ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); | 356 | ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); |
| 355 | ubifs_assert(!(wbuf->avail & 7)); | 357 | ubifs_assert(!(wbuf->avail & 7)); |
| 356 | ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); | 358 | ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); |
| @@ -390,7 +392,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf) | |||
| 390 | * @offs: logical eraseblock offset to seek to | 392 | * @offs: logical eraseblock offset to seek to |
| 391 | * @dtype: data type | 393 | * @dtype: data type |
| 392 | * | 394 | * |
| 393 | * This function targets the write buffer to logical eraseblock @lnum:@offs. | 395 | * This function targets the write-buffer to logical eraseblock @lnum:@offs. |
| 394 | * The write-buffer is synchronized if it is not empty. Returns zero in case of | 396 | * The write-buffer is synchronized if it is not empty. Returns zero in case of |
| 395 | * success and a negative error code in case of failure. | 397 | * success and a negative error code in case of failure. |
| 396 | */ | 398 | */ |
| @@ -399,7 +401,7 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, | |||
| 399 | { | 401 | { |
| 400 | const struct ubifs_info *c = wbuf->c; | 402 | const struct ubifs_info *c = wbuf->c; |
| 401 | 403 | ||
| 402 | dbg_io("LEB %d:%d", lnum, offs); | 404 | dbg_io("LEB %d:%d, jhead %d", lnum, offs, wbuf->jhead); |
| 403 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt); | 405 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt); |
| 404 | ubifs_assert(offs >= 0 && offs <= c->leb_size); | 406 | ubifs_assert(offs >= 0 && offs <= c->leb_size); |
| 405 | ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7)); | 407 | ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7)); |
| @@ -506,9 +508,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 506 | struct ubifs_info *c = wbuf->c; | 508 | struct ubifs_info *c = wbuf->c; |
| 507 | int err, written, n, aligned_len = ALIGN(len, 8), offs; | 509 | int err, written, n, aligned_len = ALIGN(len, 8), offs; |
| 508 | 510 | ||
| 509 | dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len, | 511 | dbg_io("%d bytes (%s) to jhead %d wbuf at LEB %d:%d", len, |
| 510 | dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum, | 512 | dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->jhead, |
| 511 | wbuf->offs + wbuf->used); | 513 | wbuf->lnum, wbuf->offs + wbuf->used); |
| 512 | ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt); | 514 | ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt); |
| 513 | ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0); | 515 | ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0); |
| 514 | ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); | 516 | ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size); |
| @@ -533,8 +535,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 533 | memcpy(wbuf->buf + wbuf->used, buf, len); | 535 | memcpy(wbuf->buf + wbuf->used, buf, len); |
| 534 | 536 | ||
| 535 | if (aligned_len == wbuf->avail) { | 537 | if (aligned_len == wbuf->avail) { |
| 536 | dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, | 538 | dbg_io("flush jhead %d wbuf to LEB %d:%d", |
| 537 | wbuf->offs); | 539 | wbuf->jhead, wbuf->lnum, wbuf->offs); |
| 538 | err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, | 540 | err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, |
| 539 | wbuf->offs, c->min_io_size, | 541 | wbuf->offs, c->min_io_size, |
| 540 | wbuf->dtype); | 542 | wbuf->dtype); |
| @@ -562,7 +564,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 562 | * minimal I/O unit. We have to fill and flush write-buffer and switch | 564 | * minimal I/O unit. We have to fill and flush write-buffer and switch |
| 563 | * to the next min. I/O unit. | 565 | * to the next min. I/O unit. |
| 564 | */ | 566 | */ |
| 565 | dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs); | 567 | dbg_io("flush jhead %d wbuf to LEB %d:%d", |
| 568 | wbuf->jhead, wbuf->lnum, wbuf->offs); | ||
| 566 | memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); | 569 | memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); |
| 567 | err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, | 570 | err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, |
| 568 | c->min_io_size, wbuf->dtype); | 571 | c->min_io_size, wbuf->dtype); |
| @@ -695,7 +698,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, | |||
| 695 | int err, rlen, overlap; | 698 | int err, rlen, overlap; |
| 696 | struct ubifs_ch *ch = buf; | 699 | struct ubifs_ch *ch = buf; |
| 697 | 700 | ||
| 698 | dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len); | 701 | dbg_io("LEB %d:%d, %s, length %d, jhead %d", lnum, offs, |
| 702 | dbg_ntype(type), len, wbuf->jhead); | ||
| 699 | ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0); | 703 | ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0); |
| 700 | ubifs_assert(!(offs & 7) && offs < c->leb_size); | 704 | ubifs_assert(!(offs & 7) && offs < c->leb_size); |
| 701 | ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); | 705 | ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); |
| @@ -819,13 +823,12 @@ out: | |||
| 819 | * @c: UBIFS file-system description object | 823 | * @c: UBIFS file-system description object |
| 820 | * @wbuf: write-buffer to initialize | 824 | * @wbuf: write-buffer to initialize |
| 821 | * | 825 | * |
| 822 | * This function initializes write buffer. Returns zero in case of success | 826 | * This function initializes write-buffer. Returns zero in case of success |
| 823 | * %-ENOMEM in case of failure. | 827 | * %-ENOMEM in case of failure. |
| 824 | */ | 828 | */ |
| 825 | int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) | 829 | int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) |
| 826 | { | 830 | { |
| 827 | size_t size; | 831 | size_t size; |
| 828 | ktime_t hardlimit; | ||
| 829 | 832 | ||
| 830 | wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); | 833 | wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); |
| 831 | if (!wbuf->buf) | 834 | if (!wbuf->buf) |
| @@ -851,22 +854,16 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) | |||
| 851 | 854 | ||
| 852 | hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 855 | hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
| 853 | wbuf->timer.function = wbuf_timer_callback_nolock; | 856 | wbuf->timer.function = wbuf_timer_callback_nolock; |
| 854 | /* | 857 | wbuf->softlimit = ktime_set(WBUF_TIMEOUT_SOFTLIMIT, 0); |
| 855 | * Make write-buffer soft limit to be 20% of the hard limit. The | 858 | wbuf->delta = WBUF_TIMEOUT_HARDLIMIT - WBUF_TIMEOUT_SOFTLIMIT; |
| 856 | * write-buffer timer is allowed to expire any time between the soft | 859 | wbuf->delta *= 1000000000ULL; |
| 857 | * and hard limits. | 860 | ubifs_assert(wbuf->delta <= ULONG_MAX); |
| 858 | */ | ||
| 859 | hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0); | ||
| 860 | wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10; | ||
| 861 | wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta); | ||
| 862 | hrtimer_set_expires_range_ns(&wbuf->timer, wbuf->softlimit, | ||
| 863 | wbuf->delta); | ||
| 864 | return 0; | 861 | return 0; |
| 865 | } | 862 | } |
| 866 | 863 | ||
| 867 | /** | 864 | /** |
| 868 | * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array. | 865 | * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array. |
| 869 | * @wbuf: the write-buffer whereto add | 866 | * @wbuf: the write-buffer where to add |
| 870 | * @inum: the inode number | 867 | * @inum: the inode number |
| 871 | * | 868 | * |
| 872 | * This function adds an inode number to the inode array of the write-buffer. | 869 | * This function adds an inode number to the inode array of the write-buffer. |
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 6db7a6be6c97..8aacd64957a2 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | /* This file implements EXT2-compatible extended attribute ioctl() calls */ | 25 | /* This file implements EXT2-compatible extended attribute ioctl() calls */ |
| 26 | 26 | ||
| 27 | #include <linux/compat.h> | 27 | #include <linux/compat.h> |
| 28 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
| 30 | #include "ubifs.h" | 29 | #include "ubifs.h" |
| 31 | 30 | ||
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 805605250f12..e5f6cf8a1155 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
| @@ -53,6 +53,25 @@ static int is_empty(void *buf, int len) | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | /** | 55 | /** |
| 56 | * first_non_ff - find offset of the first non-0xff byte. | ||
| 57 | * @buf: buffer to search in | ||
| 58 | * @len: length of buffer | ||
| 59 | * | ||
| 60 | * This function returns offset of the first non-0xff byte in @buf or %-1 if | ||
| 61 | * the buffer contains only 0xff bytes. | ||
| 62 | */ | ||
| 63 | static int first_non_ff(void *buf, int len) | ||
| 64 | { | ||
| 65 | uint8_t *p = buf; | ||
| 66 | int i; | ||
| 67 | |||
| 68 | for (i = 0; i < len; i++) | ||
| 69 | if (*p++ != 0xff) | ||
| 70 | return i; | ||
| 71 | return -1; | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 56 | * get_master_node - get the last valid master node allowing for corruption. | 75 | * get_master_node - get the last valid master node allowing for corruption. |
| 57 | * @c: UBIFS file-system description object | 76 | * @c: UBIFS file-system description object |
| 58 | * @lnum: LEB number | 77 | * @lnum: LEB number |
| @@ -357,11 +376,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs) | |||
| 357 | empty_offs = ALIGN(offs + 1, c->min_io_size); | 376 | empty_offs = ALIGN(offs + 1, c->min_io_size); |
| 358 | check_len = c->leb_size - empty_offs; | 377 | check_len = c->leb_size - empty_offs; |
| 359 | p = buf + empty_offs - offs; | 378 | p = buf + empty_offs - offs; |
| 360 | 379 | return is_empty(p, check_len); | |
| 361 | for (; check_len > 0; check_len--) | ||
| 362 | if (*p++ != 0xff) | ||
| 363 | return 0; | ||
| 364 | return 1; | ||
| 365 | } | 380 | } |
| 366 | 381 | ||
| 367 | /** | 382 | /** |
| @@ -543,8 +558,8 @@ static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs) | |||
| 543 | * | 558 | * |
| 544 | * This function does a scan of a LEB, but caters for errors that might have | 559 | * This function does a scan of a LEB, but caters for errors that might have |
| 545 | * been caused by the unclean unmount from which we are attempting to recover. | 560 | * been caused by the unclean unmount from which we are attempting to recover. |
| 546 | * | 561 | * Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is |
| 547 | * This function returns %0 on success and a negative error code on failure. | 562 | * found, and a negative error code in case of failure. |
| 548 | */ | 563 | */ |
| 549 | struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | 564 | struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, |
| 550 | int offs, void *sbuf, int grouped) | 565 | int offs, void *sbuf, int grouped) |
| @@ -643,7 +658,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
| 643 | goto corrupted; | 658 | goto corrupted; |
| 644 | default: | 659 | default: |
| 645 | dbg_err("unknown"); | 660 | dbg_err("unknown"); |
| 646 | goto corrupted; | 661 | err = -EINVAL; |
| 662 | goto error; | ||
| 647 | } | 663 | } |
| 648 | } | 664 | } |
| 649 | 665 | ||
| @@ -652,8 +668,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
| 652 | clean_buf(c, &buf, lnum, &offs, &len); | 668 | clean_buf(c, &buf, lnum, &offs, &len); |
| 653 | need_clean = 1; | 669 | need_clean = 1; |
| 654 | } else { | 670 | } else { |
| 655 | ubifs_err("corrupt empty space at LEB %d:%d", | 671 | int corruption = first_non_ff(buf, len); |
| 656 | lnum, offs); | 672 | |
| 673 | ubifs_err("corrupt empty space LEB %d:%d, corruption " | ||
| 674 | "starts at %d", lnum, offs, corruption); | ||
| 675 | /* Make sure we dump interesting non-0xFF data */ | ||
| 676 | offs = corruption; | ||
| 677 | buf += corruption; | ||
| 657 | goto corrupted; | 678 | goto corrupted; |
| 658 | } | 679 | } |
| 659 | } | 680 | } |
| @@ -813,7 +834,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, | |||
| 813 | static int recover_head(const struct ubifs_info *c, int lnum, int offs, | 834 | static int recover_head(const struct ubifs_info *c, int lnum, int offs, |
| 814 | void *sbuf) | 835 | void *sbuf) |
| 815 | { | 836 | { |
| 816 | int len, err, need_clean = 0; | 837 | int len, err; |
| 817 | 838 | ||
| 818 | if (c->min_io_size > 1) | 839 | if (c->min_io_size > 1) |
| 819 | len = c->min_io_size; | 840 | len = c->min_io_size; |
| @@ -827,19 +848,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs, | |||
| 827 | 848 | ||
| 828 | /* Read at the head location and check it is empty flash */ | 849 | /* Read at the head location and check it is empty flash */ |
| 829 | err = ubi_read(c->ubi, lnum, sbuf, offs, len); | 850 | err = ubi_read(c->ubi, lnum, sbuf, offs, len); |
| 830 | if (err) | 851 | if (err || !is_empty(sbuf, len)) { |
| 831 | need_clean = 1; | ||
| 832 | else { | ||
| 833 | uint8_t *p = sbuf; | ||
| 834 | |||
| 835 | while (len--) | ||
| 836 | if (*p++ != 0xff) { | ||
| 837 | need_clean = 1; | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | } | ||
| 841 | |||
| 842 | if (need_clean) { | ||
| 843 | dbg_rcvry("cleaning head at %d:%d", lnum, offs); | 852 | dbg_rcvry("cleaning head at %d:%d", lnum, offs); |
| 844 | if (offs == 0) | 853 | if (offs == 0) |
| 845 | return ubifs_leb_unmap(c, lnum); | 854 | return ubifs_leb_unmap(c, lnum); |
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 11cc80125a49..2970500f32df 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c | |||
| @@ -837,9 +837,10 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf) | |||
| 837 | 837 | ||
| 838 | dbg_mnt("replay log LEB %d:%d", lnum, offs); | 838 | dbg_mnt("replay log LEB %d:%d", lnum, offs); |
| 839 | sleb = ubifs_scan(c, lnum, offs, sbuf); | 839 | sleb = ubifs_scan(c, lnum, offs, sbuf); |
| 840 | if (IS_ERR(sleb)) { | 840 | if (IS_ERR(sleb) ) { |
| 841 | if (c->need_recovery) | 841 | if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery) |
| 842 | sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); | 842 | return PTR_ERR(sleb); |
| 843 | sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf); | ||
| 843 | if (IS_ERR(sleb)) | 844 | if (IS_ERR(sleb)) |
| 844 | return PTR_ERR(sleb); | 845 | return PTR_ERR(sleb); |
| 845 | } | 846 | } |
| @@ -957,7 +958,7 @@ out: | |||
| 957 | return err; | 958 | return err; |
| 958 | 959 | ||
| 959 | out_dump: | 960 | out_dump: |
| 960 | ubifs_err("log error detected while replying the log at LEB %d:%d", | 961 | ubifs_err("log error detected while replaying the log at LEB %d:%d", |
| 961 | lnum, offs + snod->offs); | 962 | lnum, offs + snod->offs); |
| 962 | dbg_dump_node(c, snod->node); | 963 | dbg_dump_node(c, snod->node); |
| 963 | ubifs_scan_destroy(sleb); | 964 | ubifs_scan_destroy(sleb); |
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index 0ed82479b44b..892ebfee4fe5 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c | |||
| @@ -238,12 +238,12 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, | |||
| 238 | { | 238 | { |
| 239 | int len; | 239 | int len; |
| 240 | 240 | ||
| 241 | ubifs_err("corrupted data at LEB %d:%d", lnum, offs); | 241 | ubifs_err("corruption at LEB %d:%d", lnum, offs); |
| 242 | if (dbg_failure_mode) | 242 | if (dbg_failure_mode) |
| 243 | return; | 243 | return; |
| 244 | len = c->leb_size - offs; | 244 | len = c->leb_size - offs; |
| 245 | if (len > 4096) | 245 | if (len > 8192) |
| 246 | len = 4096; | 246 | len = 8192; |
| 247 | dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs); | 247 | dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs); |
| 248 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); | 248 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1); |
| 249 | } | 249 | } |
| @@ -256,7 +256,9 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs, | |||
| 256 | * @sbuf: scan buffer (must be c->leb_size) | 256 | * @sbuf: scan buffer (must be c->leb_size) |
| 257 | * | 257 | * |
| 258 | * This function scans LEB number @lnum and returns complete information about | 258 | * This function scans LEB number @lnum and returns complete information about |
| 259 | * its contents. Returns an error code in case of failure. | 259 | * its contents. Returns the scaned information in case of success and, |
| 260 | * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case | ||
| 261 | * of failure. | ||
| 260 | */ | 262 | */ |
| 261 | struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, | 263 | struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, |
| 262 | int offs, void *sbuf) | 264 | int offs, void *sbuf) |
| @@ -279,7 +281,6 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, | |||
| 279 | cond_resched(); | 281 | cond_resched(); |
| 280 | 282 | ||
| 281 | ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); | 283 | ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); |
| 282 | |||
| 283 | if (ret > 0) { | 284 | if (ret > 0) { |
| 284 | /* Padding bytes or a valid padding node */ | 285 | /* Padding bytes or a valid padding node */ |
| 285 | offs += ret; | 286 | offs += ret; |
| @@ -304,7 +305,8 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, | |||
| 304 | goto corrupted; | 305 | goto corrupted; |
| 305 | default: | 306 | default: |
| 306 | dbg_err("unknown"); | 307 | dbg_err("unknown"); |
| 307 | goto corrupted; | 308 | err = -EINVAL; |
| 309 | goto error; | ||
| 308 | } | 310 | } |
| 309 | 311 | ||
| 310 | err = ubifs_add_snod(c, sleb, buf, offs); | 312 | err = ubifs_add_snod(c, sleb, buf, offs); |
| @@ -317,8 +319,10 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum, | |||
| 317 | len -= node_len; | 319 | len -= node_len; |
| 318 | } | 320 | } |
| 319 | 321 | ||
| 320 | if (offs % c->min_io_size) | 322 | if (offs % c->min_io_size) { |
| 321 | goto corrupted; | 323 | ubifs_err("empty space starts at non-aligned offset %d", offs); |
| 324 | goto corrupted;; | ||
| 325 | } | ||
| 322 | 326 | ||
| 323 | ubifs_end_scan(c, sleb, lnum, offs); | 327 | ubifs_end_scan(c, sleb, lnum, offs); |
| 324 | 328 | ||
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 79fad43f3c57..26d2e0d80465 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -797,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c) | |||
| 797 | * does not need to be synchronized by timer. | 797 | * does not need to be synchronized by timer. |
| 798 | */ | 798 | */ |
| 799 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; | 799 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; |
| 800 | c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0); | 800 | c->jheads[GCHD].wbuf.no_timer = 1; |
| 801 | 801 | ||
| 802 | return 0; | 802 | return 0; |
| 803 | } | 803 | } |
| @@ -986,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
| 986 | switch (token) { | 986 | switch (token) { |
| 987 | /* | 987 | /* |
| 988 | * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. | 988 | * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. |
| 989 | * We accepte them in order to be backware-compatible. But this | 989 | * We accept them in order to be backward-compatible. But this |
| 990 | * should be removed at some point. | 990 | * should be removed at some point. |
| 991 | */ | 991 | */ |
| 992 | case Opt_fast_unmount: | 992 | case Opt_fast_unmount: |
| @@ -1287,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1287 | if (err) | 1287 | if (err) |
| 1288 | goto out_journal; | 1288 | goto out_journal; |
| 1289 | 1289 | ||
| 1290 | /* Calculate 'min_idx_lebs' after journal replay */ | ||
| 1291 | c->min_idx_lebs = ubifs_calc_min_idx_lebs(c); | ||
| 1292 | |||
| 1290 | err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); | 1293 | err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only); |
| 1291 | if (err) | 1294 | if (err) |
| 1292 | goto out_orphans; | 1295 | goto out_orphans; |
| @@ -1754,10 +1757,8 @@ static void ubifs_put_super(struct super_block *sb) | |||
| 1754 | 1757 | ||
| 1755 | /* Synchronize write-buffers */ | 1758 | /* Synchronize write-buffers */ |
| 1756 | if (c->jheads) | 1759 | if (c->jheads) |
| 1757 | for (i = 0; i < c->jhead_cnt; i++) { | 1760 | for (i = 0; i < c->jhead_cnt; i++) |
| 1758 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1761 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
| 1759 | hrtimer_cancel(&c->jheads[i].wbuf.timer); | ||
| 1760 | } | ||
| 1761 | 1762 | ||
| 1762 | /* | 1763 | /* |
| 1763 | * On fatal errors c->ro_media is set to 1, in which case we do | 1764 | * On fatal errors c->ro_media is set to 1, in which case we do |
| @@ -1975,7 +1976,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1975 | err = bdi_init(&c->bdi); | 1976 | err = bdi_init(&c->bdi); |
| 1976 | if (err) | 1977 | if (err) |
| 1977 | goto out_close; | 1978 | goto out_close; |
| 1978 | err = bdi_register(&c->bdi, NULL, "ubifs"); | 1979 | err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d", |
| 1980 | c->vi.ubi_num, c->vi.vol_id); | ||
| 1979 | if (err) | 1981 | if (err) |
| 1980 | goto out_bdi; | 1982 | goto out_bdi; |
| 1981 | 1983 | ||
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 1bf01d820066..a29349094422 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -95,8 +95,9 @@ | |||
| 95 | */ | 95 | */ |
| 96 | #define BGT_NAME_PATTERN "ubifs_bgt%d_%d" | 96 | #define BGT_NAME_PATTERN "ubifs_bgt%d_%d" |
| 97 | 97 | ||
| 98 | /* Default write-buffer synchronization timeout in seconds */ | 98 | /* Write-buffer synchronization timeout interval in seconds */ |
| 99 | #define DEFAULT_WBUF_TIMEOUT_SECS 5 | 99 | #define WBUF_TIMEOUT_SOFTLIMIT 3 |
| 100 | #define WBUF_TIMEOUT_HARDLIMIT 5 | ||
| 100 | 101 | ||
| 101 | /* Maximum possible inode number (only 32-bit inodes are supported now) */ | 102 | /* Maximum possible inode number (only 32-bit inodes are supported now) */ |
| 102 | #define MAX_INUM 0xFFFFFFFF | 103 | #define MAX_INUM 0xFFFFFFFF |
| @@ -654,7 +655,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, | |||
| 654 | * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit | 655 | * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit |
| 655 | * and @softlimit + @delta) | 656 | * and @softlimit + @delta) |
| 656 | * @timer: write-buffer timer | 657 | * @timer: write-buffer timer |
| 657 | * @need_sync: it is set if its timer expired and needs sync | 658 | * @no_timer: non-zero if this write-buffer does not have a timer |
| 659 | * @need_sync: non-zero if the timer expired and the wbuf needs sync'ing | ||
| 658 | * @next_ino: points to the next position of the following inode number | 660 | * @next_ino: points to the next position of the following inode number |
| 659 | * @inodes: stores the inode numbers of the nodes which are in wbuf | 661 | * @inodes: stores the inode numbers of the nodes which are in wbuf |
| 660 | * | 662 | * |
| @@ -683,7 +685,8 @@ struct ubifs_wbuf { | |||
| 683 | ktime_t softlimit; | 685 | ktime_t softlimit; |
| 684 | unsigned long long delta; | 686 | unsigned long long delta; |
| 685 | struct hrtimer timer; | 687 | struct hrtimer timer; |
| 686 | int need_sync; | 688 | unsigned int no_timer:1; |
| 689 | unsigned int need_sync:1; | ||
| 687 | int next_ino; | 690 | int next_ino; |
| 688 | ino_t *inodes; | 691 | ino_t *inodes; |
| 689 | }; | 692 | }; |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 6832135159b6..9d1b8c2e6c45 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -1087,11 +1087,23 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
| 1087 | struct udf_inode_info *vati; | 1087 | struct udf_inode_info *vati; |
| 1088 | uint32_t pos; | 1088 | uint32_t pos; |
| 1089 | struct virtualAllocationTable20 *vat20; | 1089 | struct virtualAllocationTable20 *vat20; |
| 1090 | sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; | ||
| 1090 | 1091 | ||
| 1091 | /* VAT file entry is in the last recorded block */ | 1092 | /* VAT file entry is in the last recorded block */ |
| 1092 | ino.partitionReferenceNum = type1_index; | 1093 | ino.partitionReferenceNum = type1_index; |
| 1093 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | 1094 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; |
| 1094 | sbi->s_vat_inode = udf_iget(sb, &ino); | 1095 | sbi->s_vat_inode = udf_iget(sb, &ino); |
| 1096 | if (!sbi->s_vat_inode && | ||
| 1097 | sbi->s_last_block != blocks - 1) { | ||
| 1098 | printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the" | ||
| 1099 | " last recorded block (%lu), retrying with the last " | ||
| 1100 | "block of the device (%lu).\n", | ||
| 1101 | (unsigned long)sbi->s_last_block, | ||
| 1102 | (unsigned long)blocks - 1); | ||
| 1103 | ino.partitionReferenceNum = type1_index; | ||
| 1104 | ino.logicalBlockNum = blocks - 1 - map->s_partition_root; | ||
| 1105 | sbi->s_vat_inode = udf_iget(sb, &ino); | ||
| 1106 | } | ||
| 1095 | if (!sbi->s_vat_inode) | 1107 | if (!sbi->s_vat_inode) |
| 1096 | return 1; | 1108 | return 1; |
| 1097 | 1109 | ||
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 1cd3b55ee3d2..2d3f90afe5f1 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c | |||
| @@ -53,7 +53,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) | |||
| 53 | printk(KERN_ERR "XFS: possible memory allocation " | 53 | printk(KERN_ERR "XFS: possible memory allocation " |
| 54 | "deadlock in %s (mode:0x%x)\n", | 54 | "deadlock in %s (mode:0x%x)\n", |
| 55 | __func__, lflags); | 55 | __func__, lflags); |
| 56 | congestion_wait(WRITE, HZ/50); | 56 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
| 57 | } while (1); | 57 | } while (1); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -130,7 +130,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) | |||
| 130 | printk(KERN_ERR "XFS: possible memory allocation " | 130 | printk(KERN_ERR "XFS: possible memory allocation " |
| 131 | "deadlock in %s (mode:0x%x)\n", | 131 | "deadlock in %s (mode:0x%x)\n", |
| 132 | __func__, lflags); | 132 | __func__, lflags); |
| 133 | congestion_wait(WRITE, HZ/50); | 133 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
| 134 | } while (1); | 134 | } while (1); |
| 135 | } | 135 | } |
| 136 | 136 | ||
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7ec89fc05b2b..aecf2519db76 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -1268,6 +1268,14 @@ xfs_vm_writepage( | |||
| 1268 | if (!page_has_buffers(page)) | 1268 | if (!page_has_buffers(page)) |
| 1269 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); | 1269 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); |
| 1270 | 1270 | ||
| 1271 | |||
| 1272 | /* | ||
| 1273 | * VM calculation for nr_to_write seems off. Bump it way | ||
| 1274 | * up, this gets simple streaming writes zippy again. | ||
| 1275 | * To be reviewed again after Jens' writeback changes. | ||
| 1276 | */ | ||
| 1277 | wbc->nr_to_write *= 4; | ||
| 1278 | |||
| 1271 | /* | 1279 | /* |
| 1272 | * Convert delayed allocate, unwritten or unmapped space | 1280 | * Convert delayed allocate, unwritten or unmapped space |
| 1273 | * to real space and flush out to disk. | 1281 | * to real space and flush out to disk. |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 1418b916fc27..965df1227d64 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -412,7 +412,7 @@ _xfs_buf_lookup_pages( | |||
| 412 | 412 | ||
| 413 | XFS_STATS_INC(xb_page_retries); | 413 | XFS_STATS_INC(xb_page_retries); |
| 414 | xfsbufd_wakeup(0, gfp_mask); | 414 | xfsbufd_wakeup(0, gfp_mask); |
| 415 | congestion_wait(WRITE, HZ/50); | 415 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
| 416 | goto retry; | 416 | goto retry; |
| 417 | } | 417 | } |
| 418 | 418 | ||
| @@ -770,7 +770,7 @@ xfs_buf_associate_memory( | |||
| 770 | bp->b_pages = NULL; | 770 | bp->b_pages = NULL; |
| 771 | bp->b_addr = mem; | 771 | bp->b_addr = mem; |
| 772 | 772 | ||
| 773 | rval = _xfs_buf_get_pages(bp, page_count, 0); | 773 | rval = _xfs_buf_get_pages(bp, page_count, XBF_DONT_BLOCK); |
| 774 | if (rval) | 774 | if (rval) |
| 775 | return rval; | 775 | return rval; |
| 776 | 776 | ||
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4e255441574..0542fd507649 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include "xfs_ioctl.h" | 41 | #include "xfs_ioctl.h" |
| 42 | 42 | ||
| 43 | #include <linux/dcache.h> | 43 | #include <linux/dcache.h> |
| 44 | #include <linux/smp_lock.h> | ||
| 45 | 44 | ||
| 46 | static struct vm_operations_struct xfs_file_vm_ops; | 45 | static struct vm_operations_struct xfs_file_vm_ops; |
| 47 | 46 | ||
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 58973bb46038..8070b34cc287 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
| @@ -680,8 +680,8 @@ xfs_vn_fiemap( | |||
| 680 | else | 680 | else |
| 681 | bm.bmv_length = BTOBB(length); | 681 | bm.bmv_length = BTOBB(length); |
| 682 | 682 | ||
| 683 | /* our formatter will tell xfs_getbmap when to stop. */ | 683 | /* We add one because in getbmap world count includes the header */ |
| 684 | bm.bmv_count = MAXEXTNUM; | 684 | bm.bmv_count = fieinfo->fi_extents_max + 1; |
| 685 | bm.bmv_iflags = BMV_IF_PREALLOC; | 685 | bm.bmv_iflags = BMV_IF_PREALLOC; |
| 686 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) | 686 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) |
| 687 | bm.bmv_iflags |= BMV_IF_ATTRFORK; | 687 | bm.bmv_iflags |= BMV_IF_ATTRFORK; |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index b619d6b8ca43..98ef624d9baf 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
| @@ -708,6 +708,16 @@ xfs_reclaim_inode( | |||
| 708 | return 0; | 708 | return 0; |
| 709 | } | 709 | } |
| 710 | 710 | ||
| 711 | void | ||
| 712 | __xfs_inode_set_reclaim_tag( | ||
| 713 | struct xfs_perag *pag, | ||
| 714 | struct xfs_inode *ip) | ||
| 715 | { | ||
| 716 | radix_tree_tag_set(&pag->pag_ici_root, | ||
| 717 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | ||
| 718 | XFS_ICI_RECLAIM_TAG); | ||
| 719 | } | ||
| 720 | |||
| 711 | /* | 721 | /* |
| 712 | * We set the inode flag atomically with the radix tree tag. | 722 | * We set the inode flag atomically with the radix tree tag. |
| 713 | * Once we get tag lookups on the radix tree, this inode flag | 723 | * Once we get tag lookups on the radix tree, this inode flag |
| @@ -722,8 +732,7 @@ xfs_inode_set_reclaim_tag( | |||
| 722 | 732 | ||
| 723 | read_lock(&pag->pag_ici_lock); | 733 | read_lock(&pag->pag_ici_lock); |
| 724 | spin_lock(&ip->i_flags_lock); | 734 | spin_lock(&ip->i_flags_lock); |
| 725 | radix_tree_tag_set(&pag->pag_ici_root, | 735 | __xfs_inode_set_reclaim_tag(pag, ip); |
| 726 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | ||
| 727 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); | 736 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); |
| 728 | spin_unlock(&ip->i_flags_lock); | 737 | spin_unlock(&ip->i_flags_lock); |
| 729 | read_unlock(&pag->pag_ici_lock); | 738 | read_unlock(&pag->pag_ici_lock); |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 2a10301c99c7..59120602588a 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
| @@ -48,6 +48,7 @@ int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); | |||
| 48 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); | 48 | int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); |
| 49 | 49 | ||
| 50 | void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); | 50 | void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); |
| 51 | void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip); | ||
| 51 | void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip); | 52 | void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip); |
| 52 | void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, | 53 | void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag, |
| 53 | struct xfs_inode *ip); | 54 | struct xfs_inode *ip); |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index db15feb906ff..4ece1906bd41 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
| @@ -2010,7 +2010,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) | |||
| 2010 | dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); | 2010 | dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); |
| 2011 | blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | 2011 | blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); |
| 2012 | error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, | 2012 | error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno, |
| 2013 | blkcnt, XFS_BUF_LOCK, &bp); | 2013 | blkcnt, |
| 2014 | XFS_BUF_LOCK | XBF_DONT_BLOCK, | ||
| 2015 | &bp); | ||
| 2014 | if (error) | 2016 | if (error) |
| 2015 | return(error); | 2017 | return(error); |
| 2016 | 2018 | ||
| @@ -2141,8 +2143,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
| 2141 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), | 2143 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), |
| 2142 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); | 2144 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); |
| 2143 | 2145 | ||
| 2144 | bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, | 2146 | bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, blkcnt, |
| 2145 | blkcnt, XFS_BUF_LOCK); | 2147 | XFS_BUF_LOCK | XBF_DONT_BLOCK); |
| 2146 | ASSERT(bp); | 2148 | ASSERT(bp); |
| 2147 | ASSERT(!XFS_BUF_GETERROR(bp)); | 2149 | ASSERT(!XFS_BUF_GETERROR(bp)); |
| 2148 | 2150 | ||
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 7928b9983c1d..8ee5b5a76a2a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -6009,7 +6009,7 @@ xfs_getbmap( | |||
| 6009 | */ | 6009 | */ |
| 6010 | error = ENOMEM; | 6010 | error = ENOMEM; |
| 6011 | subnex = 16; | 6011 | subnex = 16; |
| 6012 | map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL); | 6012 | map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS); |
| 6013 | if (!map) | 6013 | if (!map) |
| 6014 | goto out_unlock_ilock; | 6014 | goto out_unlock_ilock; |
| 6015 | 6015 | ||
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index e9df99574829..26717388acf5 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
| @@ -120,8 +120,8 @@ xfs_btree_check_sblock( | |||
| 120 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { | 120 | XFS_RANDOM_BTREE_CHECK_SBLOCK))) { |
| 121 | if (bp) | 121 | if (bp) |
| 122 | xfs_buftrace("SBTREE ERROR", bp); | 122 | xfs_buftrace("SBTREE ERROR", bp); |
| 123 | XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW, | 123 | XFS_CORRUPTION_ERROR("xfs_btree_check_sblock", |
| 124 | cur->bc_mp); | 124 | XFS_ERRLEVEL_LOW, cur->bc_mp, block); |
| 125 | return XFS_ERROR(EFSCORRUPTED); | 125 | return XFS_ERROR(EFSCORRUPTED); |
| 126 | } | 126 | } |
| 127 | return 0; | 127 | return 0; |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 9ff6e57a5075..2847bbc1c534 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
| @@ -2201,7 +2201,7 @@ kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */ | |||
| 2201 | xfs_da_state_t * | 2201 | xfs_da_state_t * |
| 2202 | xfs_da_state_alloc(void) | 2202 | xfs_da_state_alloc(void) |
| 2203 | { | 2203 | { |
| 2204 | return kmem_zone_zalloc(xfs_da_state_zone, KM_SLEEP); | 2204 | return kmem_zone_zalloc(xfs_da_state_zone, KM_NOFS); |
| 2205 | } | 2205 | } |
| 2206 | 2206 | ||
| 2207 | /* | 2207 | /* |
| @@ -2261,9 +2261,9 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra) | |||
| 2261 | int off; | 2261 | int off; |
| 2262 | 2262 | ||
| 2263 | if (nbuf == 1) | 2263 | if (nbuf == 1) |
| 2264 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_SLEEP); | 2264 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS); |
| 2265 | else | 2265 | else |
| 2266 | dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_SLEEP); | 2266 | dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS); |
| 2267 | dabuf->dirty = 0; | 2267 | dabuf->dirty = 0; |
| 2268 | #ifdef XFS_DABUF_DEBUG | 2268 | #ifdef XFS_DABUF_DEBUG |
| 2269 | dabuf->ra = ra; | 2269 | dabuf->ra = ra; |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index c657bec6d951..bb1d58eb3982 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
| @@ -256,7 +256,7 @@ xfs_dir_cilookup_result( | |||
| 256 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) | 256 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) |
| 257 | return EEXIST; | 257 | return EEXIST; |
| 258 | 258 | ||
| 259 | args->value = kmem_alloc(len, KM_MAYFAIL); | 259 | args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); |
| 260 | if (!args->value) | 260 | if (!args->value) |
| 261 | return ENOMEM; | 261 | return ENOMEM; |
| 262 | 262 | ||
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cbd451bb4848..2d0b3e1da9e6 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
| @@ -167,17 +167,25 @@ xfs_growfs_data_private( | |||
| 167 | new = nb - mp->m_sb.sb_dblocks; | 167 | new = nb - mp->m_sb.sb_dblocks; |
| 168 | oagcount = mp->m_sb.sb_agcount; | 168 | oagcount = mp->m_sb.sb_agcount; |
| 169 | if (nagcount > oagcount) { | 169 | if (nagcount > oagcount) { |
| 170 | void *new_perag, *old_perag; | ||
| 171 | |||
| 170 | xfs_filestream_flush(mp); | 172 | xfs_filestream_flush(mp); |
| 173 | |||
| 174 | new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount, | ||
| 175 | KM_MAYFAIL); | ||
| 176 | if (!new_perag) | ||
| 177 | return XFS_ERROR(ENOMEM); | ||
| 178 | |||
| 171 | down_write(&mp->m_peraglock); | 179 | down_write(&mp->m_peraglock); |
| 172 | mp->m_perag = kmem_realloc(mp->m_perag, | 180 | memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount); |
| 173 | sizeof(xfs_perag_t) * nagcount, | 181 | old_perag = mp->m_perag; |
| 174 | sizeof(xfs_perag_t) * oagcount, | 182 | mp->m_perag = new_perag; |
| 175 | KM_SLEEP); | 183 | |
| 176 | memset(&mp->m_perag[oagcount], 0, | ||
| 177 | (nagcount - oagcount) * sizeof(xfs_perag_t)); | ||
| 178 | mp->m_flags |= XFS_MOUNT_32BITINODES; | 184 | mp->m_flags |= XFS_MOUNT_32BITINODES; |
| 179 | nagimax = xfs_initialize_perag(mp, nagcount); | 185 | nagimax = xfs_initialize_perag(mp, nagcount); |
| 180 | up_write(&mp->m_peraglock); | 186 | up_write(&mp->m_peraglock); |
| 187 | |||
| 188 | kmem_free(old_perag); | ||
| 181 | } | 189 | } |
| 182 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); | 190 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); |
| 183 | tp->t_flags |= XFS_TRANS_RESERVE; | 191 | tp->t_flags |= XFS_TRANS_RESERVE; |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 5fcec6f020a7..ecbf8b4d2e2e 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
| @@ -64,6 +64,10 @@ xfs_inode_alloc( | |||
| 64 | ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP); | 64 | ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP); |
| 65 | if (!ip) | 65 | if (!ip) |
| 66 | return NULL; | 66 | return NULL; |
| 67 | if (inode_init_always(mp->m_super, VFS_I(ip))) { | ||
| 68 | kmem_zone_free(xfs_inode_zone, ip); | ||
| 69 | return NULL; | ||
| 70 | } | ||
| 67 | 71 | ||
| 68 | ASSERT(atomic_read(&ip->i_iocount) == 0); | 72 | ASSERT(atomic_read(&ip->i_iocount) == 0); |
| 69 | ASSERT(atomic_read(&ip->i_pincount) == 0); | 73 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
| @@ -105,17 +109,6 @@ xfs_inode_alloc( | |||
| 105 | #ifdef XFS_DIR2_TRACE | 109 | #ifdef XFS_DIR2_TRACE |
| 106 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); | 110 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); |
| 107 | #endif | 111 | #endif |
| 108 | /* | ||
| 109 | * Now initialise the VFS inode. We do this after the xfs_inode | ||
| 110 | * initialisation as internal failures will result in ->destroy_inode | ||
| 111 | * being called and that will pass down through the reclaim path and | ||
| 112 | * free the XFS inode. This path requires the XFS inode to already be | ||
| 113 | * initialised. Hence if this call fails, the xfs_inode has already | ||
| 114 | * been freed and we should not reference it at all in the error | ||
| 115 | * handling. | ||
| 116 | */ | ||
| 117 | if (!inode_init_always(mp->m_super, VFS_I(ip))) | ||
| 118 | return NULL; | ||
| 119 | 112 | ||
| 120 | /* prevent anyone from using this yet */ | 113 | /* prevent anyone from using this yet */ |
| 121 | VFS_I(ip)->i_state = I_NEW|I_LOCK; | 114 | VFS_I(ip)->i_state = I_NEW|I_LOCK; |
| @@ -123,6 +116,71 @@ xfs_inode_alloc( | |||
| 123 | return ip; | 116 | return ip; |
| 124 | } | 117 | } |
| 125 | 118 | ||
| 119 | STATIC void | ||
| 120 | xfs_inode_free( | ||
| 121 | struct xfs_inode *ip) | ||
| 122 | { | ||
| 123 | switch (ip->i_d.di_mode & S_IFMT) { | ||
| 124 | case S_IFREG: | ||
| 125 | case S_IFDIR: | ||
| 126 | case S_IFLNK: | ||
| 127 | xfs_idestroy_fork(ip, XFS_DATA_FORK); | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (ip->i_afp) | ||
| 132 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | ||
| 133 | |||
| 134 | #ifdef XFS_INODE_TRACE | ||
| 135 | ktrace_free(ip->i_trace); | ||
| 136 | #endif | ||
| 137 | #ifdef XFS_BMAP_TRACE | ||
| 138 | ktrace_free(ip->i_xtrace); | ||
| 139 | #endif | ||
| 140 | #ifdef XFS_BTREE_TRACE | ||
| 141 | ktrace_free(ip->i_btrace); | ||
| 142 | #endif | ||
| 143 | #ifdef XFS_RW_TRACE | ||
| 144 | ktrace_free(ip->i_rwtrace); | ||
| 145 | #endif | ||
| 146 | #ifdef XFS_ILOCK_TRACE | ||
| 147 | ktrace_free(ip->i_lock_trace); | ||
| 148 | #endif | ||
| 149 | #ifdef XFS_DIR2_TRACE | ||
| 150 | ktrace_free(ip->i_dir_trace); | ||
| 151 | #endif | ||
| 152 | |||
| 153 | if (ip->i_itemp) { | ||
| 154 | /* | ||
| 155 | * Only if we are shutting down the fs will we see an | ||
| 156 | * inode still in the AIL. If it is there, we should remove | ||
| 157 | * it to prevent a use-after-free from occurring. | ||
| 158 | */ | ||
| 159 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | ||
| 160 | struct xfs_ail *ailp = lip->li_ailp; | ||
| 161 | |||
| 162 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | ||
| 163 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | ||
| 164 | if (lip->li_flags & XFS_LI_IN_AIL) { | ||
| 165 | spin_lock(&ailp->xa_lock); | ||
| 166 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
| 167 | xfs_trans_ail_delete(ailp, lip); | ||
| 168 | else | ||
| 169 | spin_unlock(&ailp->xa_lock); | ||
| 170 | } | ||
| 171 | xfs_inode_item_destroy(ip); | ||
| 172 | ip->i_itemp = NULL; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* asserts to verify all state is correct here */ | ||
| 176 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
| 177 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
| 178 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
| 179 | ASSERT(completion_done(&ip->i_flush)); | ||
| 180 | |||
| 181 | kmem_zone_free(xfs_inode_zone, ip); | ||
| 182 | } | ||
| 183 | |||
| 126 | /* | 184 | /* |
| 127 | * Check the validity of the inode we just found it the cache | 185 | * Check the validity of the inode we just found it the cache |
| 128 | */ | 186 | */ |
| @@ -133,80 +191,82 @@ xfs_iget_cache_hit( | |||
| 133 | int flags, | 191 | int flags, |
| 134 | int lock_flags) __releases(pag->pag_ici_lock) | 192 | int lock_flags) __releases(pag->pag_ici_lock) |
| 135 | { | 193 | { |
| 194 | struct inode *inode = VFS_I(ip); | ||
| 136 | struct xfs_mount *mp = ip->i_mount; | 195 | struct xfs_mount *mp = ip->i_mount; |
| 137 | int error = EAGAIN; | 196 | int error; |
| 197 | |||
| 198 | spin_lock(&ip->i_flags_lock); | ||
| 138 | 199 | ||
| 139 | /* | 200 | /* |
| 140 | * If INEW is set this inode is being set up | 201 | * If we are racing with another cache hit that is currently |
| 141 | * If IRECLAIM is set this inode is being torn down | 202 | * instantiating this inode or currently recycling it out of |
| 142 | * Pause and try again. | 203 | * reclaimabe state, wait for the initialisation to complete |
| 204 | * before continuing. | ||
| 205 | * | ||
| 206 | * XXX(hch): eventually we should do something equivalent to | ||
| 207 | * wait_on_inode to wait for these flags to be cleared | ||
| 208 | * instead of polling for it. | ||
| 143 | */ | 209 | */ |
| 144 | if (xfs_iflags_test(ip, (XFS_INEW|XFS_IRECLAIM))) { | 210 | if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) { |
| 145 | XFS_STATS_INC(xs_ig_frecycle); | 211 | XFS_STATS_INC(xs_ig_frecycle); |
| 212 | error = EAGAIN; | ||
| 146 | goto out_error; | 213 | goto out_error; |
| 147 | } | 214 | } |
| 148 | 215 | ||
| 149 | /* If IRECLAIMABLE is set, we've torn down the vfs inode part */ | 216 | /* |
| 150 | if (xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { | 217 | * If lookup is racing with unlink return an error immediately. |
| 151 | 218 | */ | |
| 152 | /* | 219 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { |
| 153 | * If lookup is racing with unlink, then we should return an | 220 | error = ENOENT; |
| 154 | * error immediately so we don't remove it from the reclaim | 221 | goto out_error; |
| 155 | * list and potentially leak the inode. | 222 | } |
| 156 | */ | ||
| 157 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { | ||
| 158 | error = ENOENT; | ||
| 159 | goto out_error; | ||
| 160 | } | ||
| 161 | 223 | ||
| 224 | /* | ||
| 225 | * If IRECLAIMABLE is set, we've torn down the VFS inode already. | ||
| 226 | * Need to carefully get it back into useable state. | ||
| 227 | */ | ||
| 228 | if (ip->i_flags & XFS_IRECLAIMABLE) { | ||
| 162 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | 229 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); |
| 163 | 230 | ||
| 164 | /* | 231 | /* |
| 165 | * We need to re-initialise the VFS inode as it has been | 232 | * We need to set XFS_INEW atomically with clearing the |
| 166 | * 'freed' by the VFS. Do this here so we can deal with | 233 | * reclaimable tag so that we do have an indicator of the |
| 167 | * errors cleanly, then tag it so it can be set up correctly | 234 | * inode still being initialized. |
| 168 | * later. | ||
| 169 | */ | 235 | */ |
| 170 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { | 236 | ip->i_flags |= XFS_INEW; |
| 171 | error = ENOMEM; | 237 | ip->i_flags &= ~XFS_IRECLAIMABLE; |
| 172 | goto out_error; | 238 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); |
| 173 | } | ||
| 174 | 239 | ||
| 175 | /* | 240 | spin_unlock(&ip->i_flags_lock); |
| 176 | * We must set the XFS_INEW flag before clearing the | 241 | read_unlock(&pag->pag_ici_lock); |
| 177 | * XFS_IRECLAIMABLE flag so that if a racing lookup does | ||
| 178 | * not find the XFS_IRECLAIMABLE above but has the igrab() | ||
| 179 | * below succeed we can safely check XFS_INEW to detect | ||
| 180 | * that this inode is still being initialised. | ||
| 181 | */ | ||
| 182 | xfs_iflags_set(ip, XFS_INEW); | ||
| 183 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); | ||
| 184 | 242 | ||
| 185 | /* clear the radix tree reclaim flag as well. */ | 243 | error = -inode_init_always(mp->m_super, inode); |
| 186 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | 244 | if (error) { |
| 187 | } else if (!igrab(VFS_I(ip))) { | 245 | /* |
| 246 | * Re-initializing the inode failed, and we are in deep | ||
| 247 | * trouble. Try to re-add it to the reclaim list. | ||
| 248 | */ | ||
| 249 | read_lock(&pag->pag_ici_lock); | ||
| 250 | spin_lock(&ip->i_flags_lock); | ||
| 251 | |||
| 252 | ip->i_flags &= ~XFS_INEW; | ||
| 253 | ip->i_flags |= XFS_IRECLAIMABLE; | ||
| 254 | __xfs_inode_set_reclaim_tag(pag, ip); | ||
| 255 | goto out_error; | ||
| 256 | } | ||
| 257 | inode->i_state = I_LOCK|I_NEW; | ||
| 258 | } else { | ||
| 188 | /* If the VFS inode is being torn down, pause and try again. */ | 259 | /* If the VFS inode is being torn down, pause and try again. */ |
| 189 | XFS_STATS_INC(xs_ig_frecycle); | 260 | if (!igrab(inode)) { |
| 190 | goto out_error; | 261 | error = EAGAIN; |
| 191 | } else if (xfs_iflags_test(ip, XFS_INEW)) { | 262 | goto out_error; |
| 192 | /* | 263 | } |
| 193 | * We are racing with another cache hit that is | ||
| 194 | * currently recycling this inode out of the XFS_IRECLAIMABLE | ||
| 195 | * state. Wait for the initialisation to complete before | ||
| 196 | * continuing. | ||
| 197 | */ | ||
| 198 | wait_on_inode(VFS_I(ip)); | ||
| 199 | } | ||
| 200 | 264 | ||
| 201 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { | 265 | /* We've got a live one. */ |
| 202 | error = ENOENT; | 266 | spin_unlock(&ip->i_flags_lock); |
| 203 | iput(VFS_I(ip)); | 267 | read_unlock(&pag->pag_ici_lock); |
| 204 | goto out_error; | ||
| 205 | } | 268 | } |
| 206 | 269 | ||
| 207 | /* We've got a live one. */ | ||
| 208 | read_unlock(&pag->pag_ici_lock); | ||
| 209 | |||
| 210 | if (lock_flags != 0) | 270 | if (lock_flags != 0) |
| 211 | xfs_ilock(ip, lock_flags); | 271 | xfs_ilock(ip, lock_flags); |
| 212 | 272 | ||
| @@ -216,6 +276,7 @@ xfs_iget_cache_hit( | |||
| 216 | return 0; | 276 | return 0; |
| 217 | 277 | ||
| 218 | out_error: | 278 | out_error: |
| 279 | spin_unlock(&ip->i_flags_lock); | ||
| 219 | read_unlock(&pag->pag_ici_lock); | 280 | read_unlock(&pag->pag_ici_lock); |
| 220 | return error; | 281 | return error; |
| 221 | } | 282 | } |
| @@ -299,7 +360,8 @@ out_preload_end: | |||
| 299 | if (lock_flags) | 360 | if (lock_flags) |
| 300 | xfs_iunlock(ip, lock_flags); | 361 | xfs_iunlock(ip, lock_flags); |
| 301 | out_destroy: | 362 | out_destroy: |
| 302 | xfs_destroy_inode(ip); | 363 | __destroy_inode(VFS_I(ip)); |
| 364 | xfs_inode_free(ip); | ||
| 303 | return error; | 365 | return error; |
| 304 | } | 366 | } |
| 305 | 367 | ||
| @@ -504,62 +566,7 @@ xfs_ireclaim( | |||
| 504 | xfs_qm_dqdetach(ip); | 566 | xfs_qm_dqdetach(ip); |
| 505 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 567 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
| 506 | 568 | ||
| 507 | switch (ip->i_d.di_mode & S_IFMT) { | 569 | xfs_inode_free(ip); |
| 508 | case S_IFREG: | ||
| 509 | case S_IFDIR: | ||
| 510 | case S_IFLNK: | ||
| 511 | xfs_idestroy_fork(ip, XFS_DATA_FORK); | ||
| 512 | break; | ||
| 513 | } | ||
| 514 | |||
| 515 | if (ip->i_afp) | ||
| 516 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | ||
| 517 | |||
| 518 | #ifdef XFS_INODE_TRACE | ||
| 519 | ktrace_free(ip->i_trace); | ||
| 520 | #endif | ||
| 521 | #ifdef XFS_BMAP_TRACE | ||
| 522 | ktrace_free(ip->i_xtrace); | ||
| 523 | #endif | ||
| 524 | #ifdef XFS_BTREE_TRACE | ||
| 525 | ktrace_free(ip->i_btrace); | ||
| 526 | #endif | ||
| 527 | #ifdef XFS_RW_TRACE | ||
| 528 | ktrace_free(ip->i_rwtrace); | ||
| 529 | #endif | ||
| 530 | #ifdef XFS_ILOCK_TRACE | ||
| 531 | ktrace_free(ip->i_lock_trace); | ||
| 532 | #endif | ||
| 533 | #ifdef XFS_DIR2_TRACE | ||
| 534 | ktrace_free(ip->i_dir_trace); | ||
| 535 | #endif | ||
| 536 | if (ip->i_itemp) { | ||
| 537 | /* | ||
| 538 | * Only if we are shutting down the fs will we see an | ||
| 539 | * inode still in the AIL. If it is there, we should remove | ||
| 540 | * it to prevent a use-after-free from occurring. | ||
| 541 | */ | ||
| 542 | xfs_log_item_t *lip = &ip->i_itemp->ili_item; | ||
| 543 | struct xfs_ail *ailp = lip->li_ailp; | ||
| 544 | |||
| 545 | ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) || | ||
| 546 | XFS_FORCED_SHUTDOWN(ip->i_mount)); | ||
| 547 | if (lip->li_flags & XFS_LI_IN_AIL) { | ||
| 548 | spin_lock(&ailp->xa_lock); | ||
| 549 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
| 550 | xfs_trans_ail_delete(ailp, lip); | ||
| 551 | else | ||
| 552 | spin_unlock(&ailp->xa_lock); | ||
| 553 | } | ||
| 554 | xfs_inode_item_destroy(ip); | ||
| 555 | ip->i_itemp = NULL; | ||
| 556 | } | ||
| 557 | /* asserts to verify all state is correct here */ | ||
| 558 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
| 559 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
| 560 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
| 561 | ASSERT(completion_done(&ip->i_flush)); | ||
| 562 | kmem_zone_free(xfs_inode_zone, ip); | ||
| 563 | } | 570 | } |
| 564 | 571 | ||
| 565 | /* | 572 | /* |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 1f22d65fed0a..da428b3fe0f5 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -343,6 +343,16 @@ xfs_iformat( | |||
| 343 | return XFS_ERROR(EFSCORRUPTED); | 343 | return XFS_ERROR(EFSCORRUPTED); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && | ||
| 347 | !ip->i_mount->m_rtdev_targp)) { | ||
| 348 | xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, | ||
| 349 | "corrupt dinode %Lu, has realtime flag set.", | ||
| 350 | ip->i_ino); | ||
| 351 | XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", | ||
| 352 | XFS_ERRLEVEL_LOW, ip->i_mount, dip); | ||
| 353 | return XFS_ERROR(EFSCORRUPTED); | ||
| 354 | } | ||
| 355 | |||
| 346 | switch (ip->i_d.di_mode & S_IFMT) { | 356 | switch (ip->i_d.di_mode & S_IFMT) { |
| 347 | case S_IFIFO: | 357 | case S_IFIFO: |
| 348 | case S_IFCHR: | 358 | case S_IFCHR: |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 1804f866a71d..65f24a3cc992 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
| @@ -310,23 +310,6 @@ static inline struct inode *VFS_I(struct xfs_inode *ip) | |||
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | /* | 312 | /* |
| 313 | * Get rid of a partially initialized inode. | ||
| 314 | * | ||
| 315 | * We have to go through destroy_inode to make sure allocations | ||
| 316 | * from init_inode_always like the security data are undone. | ||
| 317 | * | ||
| 318 | * We mark the inode bad so that it takes the short cut in | ||
| 319 | * the reclaim path instead of going through the flush path | ||
| 320 | * which doesn't make sense for an inode that has never seen the | ||
| 321 | * light of day. | ||
| 322 | */ | ||
| 323 | static inline void xfs_destroy_inode(struct xfs_inode *ip) | ||
| 324 | { | ||
| 325 | make_bad_inode(VFS_I(ip)); | ||
| 326 | return destroy_inode(VFS_I(ip)); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * i_flags helper functions | 313 | * i_flags helper functions |
| 331 | */ | 314 | */ |
| 332 | static inline void | 315 | static inline void |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 3750f04ede0b..9dbdff3ea484 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -3180,7 +3180,7 @@ try_again: | |||
| 3180 | STATIC void | 3180 | STATIC void |
| 3181 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | 3181 | xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) |
| 3182 | { | 3182 | { |
| 3183 | ASSERT(spin_is_locked(&log->l_icloglock)); | 3183 | assert_spin_locked(&log->l_icloglock); |
| 3184 | 3184 | ||
| 3185 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { | 3185 | if (iclog->ic_state == XLOG_STATE_ACTIVE) { |
| 3186 | xlog_state_switch_iclogs(log, iclog, 0); | 3186 | xlog_state_switch_iclogs(log, iclog, 0); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c4eca5ed5dab..492d75bae2bf 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -538,7 +538,9 @@ xfs_readlink_bmap( | |||
| 538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); | 538 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); |
| 539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); | 539 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); |
| 540 | 540 | ||
| 541 | bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0); | 541 | bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt), |
| 542 | XBF_LOCK | XBF_MAPPED | | ||
| 543 | XBF_DONT_BLOCK); | ||
| 542 | error = XFS_BUF_GETERROR(bp); | 544 | error = XFS_BUF_GETERROR(bp); |
| 543 | if (error) { | 545 | if (error) { |
| 544 | xfs_ioerror_alert("xfs_readlink", | 546 | xfs_ioerror_alert("xfs_readlink", |
