diff options
author | Felix Blyakher <felixb@sgi.com> | 2009-03-03 10:18:47 -0500 |
---|---|---|
committer | Felix Blyakher <felixb@sgi.com> | 2009-03-03 10:18:47 -0500 |
commit | d4fc7cea5dda04ae1a6f36175ec1dd8ff088ed52 (patch) | |
tree | 3d65887b06c575a94feed1fd91216e32a62b31d8 /fs | |
parent | 3a011a171906a3a51a43bb860fb7c66a64cab140 (diff) | |
parent | 2450cf51a1bdba7037e91b1bcc494b01c58aaf66 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs')
41 files changed, 978 insertions, 331 deletions
diff --git a/fs/Makefile b/fs/Makefile index 38bc735c67ad..dc20db348679 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -69,10 +69,12 @@ obj-$(CONFIG_DLM) += dlm/ | |||
69 | # Do not add any filesystems before this line | 69 | # Do not add any filesystems before this line |
70 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ | 70 | obj-$(CONFIG_REISERFS_FS) += reiserfs/ |
71 | obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 | 71 | obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 |
72 | obj-$(CONFIG_EXT4_FS) += ext4/ # Before ext2 so root fs can be ext4 | 72 | obj-$(CONFIG_EXT2_FS) += ext2/ |
73 | # We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 | ||
74 | # unless explicitly requested by rootfstype | ||
75 | obj-$(CONFIG_EXT4_FS) += ext4/ | ||
73 | obj-$(CONFIG_JBD) += jbd/ | 76 | obj-$(CONFIG_JBD) += jbd/ |
74 | obj-$(CONFIG_JBD2) += jbd2/ | 77 | obj-$(CONFIG_JBD2) += jbd2/ |
75 | obj-$(CONFIG_EXT2_FS) += ext2/ | ||
76 | obj-$(CONFIG_CRAMFS) += cramfs/ | 78 | obj-$(CONFIG_CRAMFS) += cramfs/ |
77 | obj-$(CONFIG_SQUASHFS) += squashfs/ | 79 | obj-$(CONFIG_SQUASHFS) += squashfs/ |
78 | obj-y += ramfs/ | 80 | obj-y += ramfs/ |
@@ -302,9 +302,10 @@ void bio_init(struct bio *bio) | |||
302 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | 302 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) |
303 | { | 303 | { |
304 | struct bio *bio = NULL; | 304 | struct bio *bio = NULL; |
305 | void *uninitialized_var(p); | ||
305 | 306 | ||
306 | if (bs) { | 307 | if (bs) { |
307 | void *p = mempool_alloc(bs->bio_pool, gfp_mask); | 308 | p = mempool_alloc(bs->bio_pool, gfp_mask); |
308 | 309 | ||
309 | if (p) | 310 | if (p) |
310 | bio = p + bs->front_pad; | 311 | bio = p + bs->front_pad; |
@@ -329,7 +330,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | |||
329 | } | 330 | } |
330 | if (unlikely(!bvl)) { | 331 | if (unlikely(!bvl)) { |
331 | if (bs) | 332 | if (bs) |
332 | mempool_free(bio, bs->bio_pool); | 333 | mempool_free(p, bs->bio_pool); |
333 | else | 334 | else |
334 | kfree(bio); | 335 | kfree(bio); |
335 | bio = NULL; | 336 | bio = NULL; |
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index a8c9693b75ac..72677ce2b74f 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -66,6 +66,9 @@ struct btrfs_inode { | |||
66 | */ | 66 | */ |
67 | struct list_head delalloc_inodes; | 67 | struct list_head delalloc_inodes; |
68 | 68 | ||
69 | /* the space_info for where this inode's data allocations are done */ | ||
70 | struct btrfs_space_info *space_info; | ||
71 | |||
69 | /* full 64 bit generation number, struct vfs_inode doesn't have a big | 72 | /* full 64 bit generation number, struct vfs_inode doesn't have a big |
70 | * enough field for this. | 73 | * enough field for this. |
71 | */ | 74 | */ |
@@ -94,6 +97,11 @@ struct btrfs_inode { | |||
94 | */ | 97 | */ |
95 | u64 delalloc_bytes; | 98 | u64 delalloc_bytes; |
96 | 99 | ||
100 | /* total number of bytes that may be used for this inode for | ||
101 | * delalloc | ||
102 | */ | ||
103 | u64 reserved_bytes; | ||
104 | |||
97 | /* | 105 | /* |
98 | * the size of the file stored in the metadata on disk. data=ordered | 106 | * the size of the file stored in the metadata on disk. data=ordered |
99 | * means the in-memory i_size might be larger than the size on disk | 107 | * means the in-memory i_size might be larger than the size on disk |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 766b31ae3186..82491ba8fa40 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -596,13 +596,27 @@ struct btrfs_block_group_item { | |||
596 | 596 | ||
597 | struct btrfs_space_info { | 597 | struct btrfs_space_info { |
598 | u64 flags; | 598 | u64 flags; |
599 | u64 total_bytes; | 599 | |
600 | u64 bytes_used; | 600 | u64 total_bytes; /* total bytes in the space */ |
601 | u64 bytes_pinned; | 601 | u64 bytes_used; /* total bytes used on disk */ |
602 | u64 bytes_reserved; | 602 | u64 bytes_pinned; /* total bytes pinned, will be freed when the |
603 | u64 bytes_readonly; | 603 | transaction finishes */ |
604 | int full; | 604 | u64 bytes_reserved; /* total bytes the allocator has reserved for |
605 | int force_alloc; | 605 | current allocations */ |
606 | u64 bytes_readonly; /* total bytes that are read only */ | ||
607 | |||
608 | /* delalloc accounting */ | ||
609 | u64 bytes_delalloc; /* number of bytes reserved for allocation, | ||
610 | this space is not necessarily reserved yet | ||
611 | by the allocator */ | ||
612 | u64 bytes_may_use; /* number of bytes that may be used for | ||
613 | delalloc */ | ||
614 | |||
615 | int full; /* indicates that we cannot allocate any more | ||
616 | chunks for this space */ | ||
617 | int force_alloc; /* set if we need to force a chunk alloc for | ||
618 | this space */ | ||
619 | |||
606 | struct list_head list; | 620 | struct list_head list; |
607 | 621 | ||
608 | /* for block groups in our same type */ | 622 | /* for block groups in our same type */ |
@@ -1782,6 +1796,16 @@ int btrfs_add_dead_reloc_root(struct btrfs_root *root); | |||
1782 | int btrfs_cleanup_reloc_trees(struct btrfs_root *root); | 1796 | int btrfs_cleanup_reloc_trees(struct btrfs_root *root); |
1783 | int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len); | 1797 | int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len); |
1784 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); | 1798 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); |
1799 | void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde); | ||
1800 | int btrfs_check_metadata_free_space(struct btrfs_root *root); | ||
1801 | int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, | ||
1802 | u64 bytes); | ||
1803 | void btrfs_free_reserved_data_space(struct btrfs_root *root, | ||
1804 | struct inode *inode, u64 bytes); | ||
1805 | void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode, | ||
1806 | u64 bytes); | ||
1807 | void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, | ||
1808 | u64 bytes); | ||
1785 | /* ctree.c */ | 1809 | /* ctree.c */ |
1786 | int btrfs_previous_item(struct btrfs_root *root, | 1810 | int btrfs_previous_item(struct btrfs_root *root, |
1787 | struct btrfs_path *path, u64 min_objectid, | 1811 | struct btrfs_path *path, u64 min_objectid, |
@@ -2027,8 +2051,6 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | |||
2027 | unsigned long btrfs_force_ra(struct address_space *mapping, | 2051 | unsigned long btrfs_force_ra(struct address_space *mapping, |
2028 | struct file_ra_state *ra, struct file *file, | 2052 | struct file_ra_state *ra, struct file *file, |
2029 | pgoff_t offset, pgoff_t last_index); | 2053 | pgoff_t offset, pgoff_t last_index); |
2030 | int btrfs_check_free_space(struct btrfs_root *root, u64 num_required, | ||
2031 | int for_del); | ||
2032 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page); | 2054 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page); |
2033 | int btrfs_readpage(struct file *file, struct page *page); | 2055 | int btrfs_readpage(struct file *file, struct page *page); |
2034 | void btrfs_delete_inode(struct inode *inode); | 2056 | void btrfs_delete_inode(struct inode *inode); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0a5d796c9f7e..6b5966aacf44 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -60,6 +60,10 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
60 | u64 bytenr, u64 num_bytes, int alloc, | 60 | u64 bytenr, u64 num_bytes, int alloc, |
61 | int mark_free); | 61 | int mark_free); |
62 | 62 | ||
63 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | ||
64 | struct btrfs_root *extent_root, u64 alloc_bytes, | ||
65 | u64 flags, int force); | ||
66 | |||
63 | static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) | 67 | static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) |
64 | { | 68 | { |
65 | return (cache->flags & bits) == bits; | 69 | return (cache->flags & bits) == bits; |
@@ -1909,6 +1913,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
1909 | found->bytes_pinned = 0; | 1913 | found->bytes_pinned = 0; |
1910 | found->bytes_reserved = 0; | 1914 | found->bytes_reserved = 0; |
1911 | found->bytes_readonly = 0; | 1915 | found->bytes_readonly = 0; |
1916 | found->bytes_delalloc = 0; | ||
1912 | found->full = 0; | 1917 | found->full = 0; |
1913 | found->force_alloc = 0; | 1918 | found->force_alloc = 0; |
1914 | *space_info = found; | 1919 | *space_info = found; |
@@ -1972,6 +1977,233 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags) | |||
1972 | return flags; | 1977 | return flags; |
1973 | } | 1978 | } |
1974 | 1979 | ||
1980 | static u64 btrfs_get_alloc_profile(struct btrfs_root *root, u64 data) | ||
1981 | { | ||
1982 | struct btrfs_fs_info *info = root->fs_info; | ||
1983 | u64 alloc_profile; | ||
1984 | |||
1985 | if (data) { | ||
1986 | alloc_profile = info->avail_data_alloc_bits & | ||
1987 | info->data_alloc_profile; | ||
1988 | data = BTRFS_BLOCK_GROUP_DATA | alloc_profile; | ||
1989 | } else if (root == root->fs_info->chunk_root) { | ||
1990 | alloc_profile = info->avail_system_alloc_bits & | ||
1991 | info->system_alloc_profile; | ||
1992 | data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile; | ||
1993 | } else { | ||
1994 | alloc_profile = info->avail_metadata_alloc_bits & | ||
1995 | info->metadata_alloc_profile; | ||
1996 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; | ||
1997 | } | ||
1998 | |||
1999 | return btrfs_reduce_alloc_profile(root, data); | ||
2000 | } | ||
2001 | |||
2002 | void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *inode) | ||
2003 | { | ||
2004 | u64 alloc_target; | ||
2005 | |||
2006 | alloc_target = btrfs_get_alloc_profile(root, 1); | ||
2007 | BTRFS_I(inode)->space_info = __find_space_info(root->fs_info, | ||
2008 | alloc_target); | ||
2009 | } | ||
2010 | |||
2011 | /* | ||
2012 | * for now this just makes sure we have at least 5% of our metadata space free | ||
2013 | * for use. | ||
2014 | */ | ||
2015 | int btrfs_check_metadata_free_space(struct btrfs_root *root) | ||
2016 | { | ||
2017 | struct btrfs_fs_info *info = root->fs_info; | ||
2018 | struct btrfs_space_info *meta_sinfo; | ||
2019 | u64 alloc_target, thresh; | ||
2020 | int committed = 0, ret; | ||
2021 | |||
2022 | /* get the space info for where the metadata will live */ | ||
2023 | alloc_target = btrfs_get_alloc_profile(root, 0); | ||
2024 | meta_sinfo = __find_space_info(info, alloc_target); | ||
2025 | |||
2026 | again: | ||
2027 | spin_lock(&meta_sinfo->lock); | ||
2028 | if (!meta_sinfo->full) | ||
2029 | thresh = meta_sinfo->total_bytes * 80; | ||
2030 | else | ||
2031 | thresh = meta_sinfo->total_bytes * 95; | ||
2032 | |||
2033 | do_div(thresh, 100); | ||
2034 | |||
2035 | if (meta_sinfo->bytes_used + meta_sinfo->bytes_reserved + | ||
2036 | meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly > thresh) { | ||
2037 | struct btrfs_trans_handle *trans; | ||
2038 | if (!meta_sinfo->full) { | ||
2039 | meta_sinfo->force_alloc = 1; | ||
2040 | spin_unlock(&meta_sinfo->lock); | ||
2041 | |||
2042 | trans = btrfs_start_transaction(root, 1); | ||
2043 | if (!trans) | ||
2044 | return -ENOMEM; | ||
2045 | |||
2046 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | ||
2047 | 2 * 1024 * 1024, alloc_target, 0); | ||
2048 | btrfs_end_transaction(trans, root); | ||
2049 | goto again; | ||
2050 | } | ||
2051 | spin_unlock(&meta_sinfo->lock); | ||
2052 | |||
2053 | if (!committed) { | ||
2054 | committed = 1; | ||
2055 | trans = btrfs_join_transaction(root, 1); | ||
2056 | if (!trans) | ||
2057 | return -ENOMEM; | ||
2058 | ret = btrfs_commit_transaction(trans, root); | ||
2059 | if (ret) | ||
2060 | return ret; | ||
2061 | goto again; | ||
2062 | } | ||
2063 | return -ENOSPC; | ||
2064 | } | ||
2065 | spin_unlock(&meta_sinfo->lock); | ||
2066 | |||
2067 | return 0; | ||
2068 | } | ||
2069 | |||
2070 | /* | ||
2071 | * This will check the space that the inode allocates from to make sure we have | ||
2072 | * enough space for bytes. | ||
2073 | */ | ||
2074 | int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, | ||
2075 | u64 bytes) | ||
2076 | { | ||
2077 | struct btrfs_space_info *data_sinfo; | ||
2078 | int ret = 0, committed = 0; | ||
2079 | |||
2080 | /* make sure bytes are sectorsize aligned */ | ||
2081 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | ||
2082 | |||
2083 | data_sinfo = BTRFS_I(inode)->space_info; | ||
2084 | again: | ||
2085 | /* make sure we have enough space to handle the data first */ | ||
2086 | spin_lock(&data_sinfo->lock); | ||
2087 | if (data_sinfo->total_bytes - data_sinfo->bytes_used - | ||
2088 | data_sinfo->bytes_delalloc - data_sinfo->bytes_reserved - | ||
2089 | data_sinfo->bytes_pinned - data_sinfo->bytes_readonly - | ||
2090 | data_sinfo->bytes_may_use < bytes) { | ||
2091 | struct btrfs_trans_handle *trans; | ||
2092 | |||
2093 | /* | ||
2094 | * if we don't have enough free bytes in this space then we need | ||
2095 | * to alloc a new chunk. | ||
2096 | */ | ||
2097 | if (!data_sinfo->full) { | ||
2098 | u64 alloc_target; | ||
2099 | |||
2100 | data_sinfo->force_alloc = 1; | ||
2101 | spin_unlock(&data_sinfo->lock); | ||
2102 | |||
2103 | alloc_target = btrfs_get_alloc_profile(root, 1); | ||
2104 | trans = btrfs_start_transaction(root, 1); | ||
2105 | if (!trans) | ||
2106 | return -ENOMEM; | ||
2107 | |||
2108 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | ||
2109 | bytes + 2 * 1024 * 1024, | ||
2110 | alloc_target, 0); | ||
2111 | btrfs_end_transaction(trans, root); | ||
2112 | if (ret) | ||
2113 | return ret; | ||
2114 | goto again; | ||
2115 | } | ||
2116 | spin_unlock(&data_sinfo->lock); | ||
2117 | |||
2118 | /* commit the current transaction and try again */ | ||
2119 | if (!committed) { | ||
2120 | committed = 1; | ||
2121 | trans = btrfs_join_transaction(root, 1); | ||
2122 | if (!trans) | ||
2123 | return -ENOMEM; | ||
2124 | ret = btrfs_commit_transaction(trans, root); | ||
2125 | if (ret) | ||
2126 | return ret; | ||
2127 | goto again; | ||
2128 | } | ||
2129 | |||
2130 | printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes" | ||
2131 | ", %llu bytes_used, %llu bytes_reserved, " | ||
2132 | "%llu bytes_pinned, %llu bytes_readonly, %llu may use" | ||
2133 | "%llu total\n", bytes, data_sinfo->bytes_delalloc, | ||
2134 | data_sinfo->bytes_used, data_sinfo->bytes_reserved, | ||
2135 | data_sinfo->bytes_pinned, data_sinfo->bytes_readonly, | ||
2136 | data_sinfo->bytes_may_use, data_sinfo->total_bytes); | ||
2137 | return -ENOSPC; | ||
2138 | } | ||
2139 | data_sinfo->bytes_may_use += bytes; | ||
2140 | BTRFS_I(inode)->reserved_bytes += bytes; | ||
2141 | spin_unlock(&data_sinfo->lock); | ||
2142 | |||
2143 | return btrfs_check_metadata_free_space(root); | ||
2144 | } | ||
2145 | |||
2146 | /* | ||
2147 | * if there was an error for whatever reason after calling | ||
2148 | * btrfs_check_data_free_space, call this so we can cleanup the counters. | ||
2149 | */ | ||
2150 | void btrfs_free_reserved_data_space(struct btrfs_root *root, | ||
2151 | struct inode *inode, u64 bytes) | ||
2152 | { | ||
2153 | struct btrfs_space_info *data_sinfo; | ||
2154 | |||
2155 | /* make sure bytes are sectorsize aligned */ | ||
2156 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | ||
2157 | |||
2158 | data_sinfo = BTRFS_I(inode)->space_info; | ||
2159 | spin_lock(&data_sinfo->lock); | ||
2160 | data_sinfo->bytes_may_use -= bytes; | ||
2161 | BTRFS_I(inode)->reserved_bytes -= bytes; | ||
2162 | spin_unlock(&data_sinfo->lock); | ||
2163 | } | ||
2164 | |||
2165 | /* called when we are adding a delalloc extent to the inode's io_tree */ | ||
2166 | void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode, | ||
2167 | u64 bytes) | ||
2168 | { | ||
2169 | struct btrfs_space_info *data_sinfo; | ||
2170 | |||
2171 | /* get the space info for where this inode will be storing its data */ | ||
2172 | data_sinfo = BTRFS_I(inode)->space_info; | ||
2173 | |||
2174 | /* make sure we have enough space to handle the data first */ | ||
2175 | spin_lock(&data_sinfo->lock); | ||
2176 | data_sinfo->bytes_delalloc += bytes; | ||
2177 | |||
2178 | /* | ||
2179 | * we are adding a delalloc extent without calling | ||
2180 | * btrfs_check_data_free_space first. This happens on a weird | ||
2181 | * writepage condition, but shouldn't hurt our accounting | ||
2182 | */ | ||
2183 | if (unlikely(bytes > BTRFS_I(inode)->reserved_bytes)) { | ||
2184 | data_sinfo->bytes_may_use -= BTRFS_I(inode)->reserved_bytes; | ||
2185 | BTRFS_I(inode)->reserved_bytes = 0; | ||
2186 | } else { | ||
2187 | data_sinfo->bytes_may_use -= bytes; | ||
2188 | BTRFS_I(inode)->reserved_bytes -= bytes; | ||
2189 | } | ||
2190 | |||
2191 | spin_unlock(&data_sinfo->lock); | ||
2192 | } | ||
2193 | |||
2194 | /* called when we are clearing an delalloc extent from the inode's io_tree */ | ||
2195 | void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, | ||
2196 | u64 bytes) | ||
2197 | { | ||
2198 | struct btrfs_space_info *info; | ||
2199 | |||
2200 | info = BTRFS_I(inode)->space_info; | ||
2201 | |||
2202 | spin_lock(&info->lock); | ||
2203 | info->bytes_delalloc -= bytes; | ||
2204 | spin_unlock(&info->lock); | ||
2205 | } | ||
2206 | |||
1975 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 2207 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1976 | struct btrfs_root *extent_root, u64 alloc_bytes, | 2208 | struct btrfs_root *extent_root, u64 alloc_bytes, |
1977 | u64 flags, int force) | 2209 | u64 flags, int force) |
@@ -3105,6 +3337,10 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes) | |||
3105 | (unsigned long long)(info->total_bytes - info->bytes_used - | 3337 | (unsigned long long)(info->total_bytes - info->bytes_used - |
3106 | info->bytes_pinned - info->bytes_reserved), | 3338 | info->bytes_pinned - info->bytes_reserved), |
3107 | (info->full) ? "" : "not "); | 3339 | (info->full) ? "" : "not "); |
3340 | printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu," | ||
3341 | " may_use=%llu, used=%llu\n", info->total_bytes, | ||
3342 | info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use, | ||
3343 | info->bytes_used); | ||
3108 | 3344 | ||
3109 | down_read(&info->groups_sem); | 3345 | down_read(&info->groups_sem); |
3110 | list_for_each_entry(cache, &info->block_groups, list) { | 3346 | list_for_each_entry(cache, &info->block_groups, list) { |
@@ -3131,24 +3367,10 @@ static int __btrfs_reserve_extent(struct btrfs_trans_handle *trans, | |||
3131 | { | 3367 | { |
3132 | int ret; | 3368 | int ret; |
3133 | u64 search_start = 0; | 3369 | u64 search_start = 0; |
3134 | u64 alloc_profile; | ||
3135 | struct btrfs_fs_info *info = root->fs_info; | 3370 | struct btrfs_fs_info *info = root->fs_info; |
3136 | 3371 | ||
3137 | if (data) { | 3372 | data = btrfs_get_alloc_profile(root, data); |
3138 | alloc_profile = info->avail_data_alloc_bits & | ||
3139 | info->data_alloc_profile; | ||
3140 | data = BTRFS_BLOCK_GROUP_DATA | alloc_profile; | ||
3141 | } else if (root == root->fs_info->chunk_root) { | ||
3142 | alloc_profile = info->avail_system_alloc_bits & | ||
3143 | info->system_alloc_profile; | ||
3144 | data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile; | ||
3145 | } else { | ||
3146 | alloc_profile = info->avail_metadata_alloc_bits & | ||
3147 | info->metadata_alloc_profile; | ||
3148 | data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile; | ||
3149 | } | ||
3150 | again: | 3373 | again: |
3151 | data = btrfs_reduce_alloc_profile(root, data); | ||
3152 | /* | 3374 | /* |
3153 | * the only place that sets empty_size is btrfs_realloc_node, which | 3375 | * the only place that sets empty_size is btrfs_realloc_node, which |
3154 | * is not called recursively on allocations | 3376 | * is not called recursively on allocations |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 3e8023efaff7..dc78954861b3 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1091,19 +1091,24 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1091 | WARN_ON(num_pages > nrptrs); | 1091 | WARN_ON(num_pages > nrptrs); |
1092 | memset(pages, 0, sizeof(struct page *) * nrptrs); | 1092 | memset(pages, 0, sizeof(struct page *) * nrptrs); |
1093 | 1093 | ||
1094 | ret = btrfs_check_free_space(root, write_bytes, 0); | 1094 | ret = btrfs_check_data_free_space(root, inode, write_bytes); |
1095 | if (ret) | 1095 | if (ret) |
1096 | goto out; | 1096 | goto out; |
1097 | 1097 | ||
1098 | ret = prepare_pages(root, file, pages, num_pages, | 1098 | ret = prepare_pages(root, file, pages, num_pages, |
1099 | pos, first_index, last_index, | 1099 | pos, first_index, last_index, |
1100 | write_bytes); | 1100 | write_bytes); |
1101 | if (ret) | 1101 | if (ret) { |
1102 | btrfs_free_reserved_data_space(root, inode, | ||
1103 | write_bytes); | ||
1102 | goto out; | 1104 | goto out; |
1105 | } | ||
1103 | 1106 | ||
1104 | ret = btrfs_copy_from_user(pos, num_pages, | 1107 | ret = btrfs_copy_from_user(pos, num_pages, |
1105 | write_bytes, pages, buf); | 1108 | write_bytes, pages, buf); |
1106 | if (ret) { | 1109 | if (ret) { |
1110 | btrfs_free_reserved_data_space(root, inode, | ||
1111 | write_bytes); | ||
1107 | btrfs_drop_pages(pages, num_pages); | 1112 | btrfs_drop_pages(pages, num_pages); |
1108 | goto out; | 1113 | goto out; |
1109 | } | 1114 | } |
@@ -1111,8 +1116,11 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1111 | ret = dirty_and_release_pages(NULL, root, file, pages, | 1116 | ret = dirty_and_release_pages(NULL, root, file, pages, |
1112 | num_pages, pos, write_bytes); | 1117 | num_pages, pos, write_bytes); |
1113 | btrfs_drop_pages(pages, num_pages); | 1118 | btrfs_drop_pages(pages, num_pages); |
1114 | if (ret) | 1119 | if (ret) { |
1120 | btrfs_free_reserved_data_space(root, inode, | ||
1121 | write_bytes); | ||
1115 | goto out; | 1122 | goto out; |
1123 | } | ||
1116 | 1124 | ||
1117 | if (will_write) { | 1125 | if (will_write) { |
1118 | btrfs_fdatawrite_range(inode->i_mapping, pos, | 1126 | btrfs_fdatawrite_range(inode->i_mapping, pos, |
@@ -1136,6 +1144,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1136 | } | 1144 | } |
1137 | out: | 1145 | out: |
1138 | mutex_unlock(&inode->i_mutex); | 1146 | mutex_unlock(&inode->i_mutex); |
1147 | if (ret) | ||
1148 | err = ret; | ||
1139 | 1149 | ||
1140 | out_nolock: | 1150 | out_nolock: |
1141 | kfree(pages); | 1151 | kfree(pages); |
@@ -1222,7 +1232,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1222 | /* | 1232 | /* |
1223 | * ok we haven't committed the transaction yet, lets do a commit | 1233 | * ok we haven't committed the transaction yet, lets do a commit |
1224 | */ | 1234 | */ |
1225 | if (file->private_data) | 1235 | if (file && file->private_data) |
1226 | btrfs_ioctl_trans_end(file); | 1236 | btrfs_ioctl_trans_end(file); |
1227 | 1237 | ||
1228 | trans = btrfs_start_transaction(root, 1); | 1238 | trans = btrfs_start_transaction(root, 1); |
@@ -1231,7 +1241,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1231 | goto out; | 1241 | goto out; |
1232 | } | 1242 | } |
1233 | 1243 | ||
1234 | ret = btrfs_log_dentry_safe(trans, root, file->f_dentry); | 1244 | ret = btrfs_log_dentry_safe(trans, root, dentry); |
1235 | if (ret < 0) | 1245 | if (ret < 0) |
1236 | goto out; | 1246 | goto out; |
1237 | 1247 | ||
@@ -1245,7 +1255,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1245 | * file again, but that will end up using the synchronization | 1255 | * file again, but that will end up using the synchronization |
1246 | * inside btrfs_sync_log to keep things safe. | 1256 | * inside btrfs_sync_log to keep things safe. |
1247 | */ | 1257 | */ |
1248 | mutex_unlock(&file->f_dentry->d_inode->i_mutex); | 1258 | mutex_unlock(&dentry->d_inode->i_mutex); |
1249 | 1259 | ||
1250 | if (ret > 0) { | 1260 | if (ret > 0) { |
1251 | ret = btrfs_commit_transaction(trans, root); | 1261 | ret = btrfs_commit_transaction(trans, root); |
@@ -1253,7 +1263,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
1253 | btrfs_sync_log(trans, root); | 1263 | btrfs_sync_log(trans, root); |
1254 | ret = btrfs_end_transaction(trans, root); | 1264 | ret = btrfs_end_transaction(trans, root); |
1255 | } | 1265 | } |
1256 | mutex_lock(&file->f_dentry->d_inode->i_mutex); | 1266 | mutex_lock(&dentry->d_inode->i_mutex); |
1257 | out: | 1267 | out: |
1258 | return ret > 0 ? EIO : ret; | 1268 | return ret > 0 ? EIO : ret; |
1259 | } | 1269 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3cee77ae03c8..7d4f948bc22a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -102,34 +102,6 @@ static int btrfs_init_inode_security(struct inode *inode, struct inode *dir) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * a very lame attempt at stopping writes when the FS is 85% full. There | ||
106 | * are countless ways this is incorrect, but it is better than nothing. | ||
107 | */ | ||
108 | int btrfs_check_free_space(struct btrfs_root *root, u64 num_required, | ||
109 | int for_del) | ||
110 | { | ||
111 | u64 total; | ||
112 | u64 used; | ||
113 | u64 thresh; | ||
114 | int ret = 0; | ||
115 | |||
116 | spin_lock(&root->fs_info->delalloc_lock); | ||
117 | total = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
118 | used = btrfs_super_bytes_used(&root->fs_info->super_copy); | ||
119 | if (for_del) | ||
120 | thresh = total * 90; | ||
121 | else | ||
122 | thresh = total * 85; | ||
123 | |||
124 | do_div(thresh, 100); | ||
125 | |||
126 | if (used + root->fs_info->delalloc_bytes + num_required > thresh) | ||
127 | ret = -ENOSPC; | ||
128 | spin_unlock(&root->fs_info->delalloc_lock); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * this does all the hard work for inserting an inline extent into | 105 | * this does all the hard work for inserting an inline extent into |
134 | * the btree. The caller should have done a btrfs_drop_extents so that | 106 | * the btree. The caller should have done a btrfs_drop_extents so that |
135 | * no overlapping inline items exist in the btree | 107 | * no overlapping inline items exist in the btree |
@@ -1190,6 +1162,7 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | |||
1190 | */ | 1162 | */ |
1191 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { | 1163 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
1192 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1164 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1165 | btrfs_delalloc_reserve_space(root, inode, end - start + 1); | ||
1193 | spin_lock(&root->fs_info->delalloc_lock); | 1166 | spin_lock(&root->fs_info->delalloc_lock); |
1194 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; | 1167 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; |
1195 | root->fs_info->delalloc_bytes += end - start + 1; | 1168 | root->fs_info->delalloc_bytes += end - start + 1; |
@@ -1223,9 +1196,12 @@ static int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, | |||
1223 | (unsigned long long)end - start + 1, | 1196 | (unsigned long long)end - start + 1, |
1224 | (unsigned long long) | 1197 | (unsigned long long) |
1225 | root->fs_info->delalloc_bytes); | 1198 | root->fs_info->delalloc_bytes); |
1199 | btrfs_delalloc_free_space(root, inode, (u64)-1); | ||
1226 | root->fs_info->delalloc_bytes = 0; | 1200 | root->fs_info->delalloc_bytes = 0; |
1227 | BTRFS_I(inode)->delalloc_bytes = 0; | 1201 | BTRFS_I(inode)->delalloc_bytes = 0; |
1228 | } else { | 1202 | } else { |
1203 | btrfs_delalloc_free_space(root, inode, | ||
1204 | end - start + 1); | ||
1229 | root->fs_info->delalloc_bytes -= end - start + 1; | 1205 | root->fs_info->delalloc_bytes -= end - start + 1; |
1230 | BTRFS_I(inode)->delalloc_bytes -= end - start + 1; | 1206 | BTRFS_I(inode)->delalloc_bytes -= end - start + 1; |
1231 | } | 1207 | } |
@@ -2245,10 +2221,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2245 | 2221 | ||
2246 | root = BTRFS_I(dir)->root; | 2222 | root = BTRFS_I(dir)->root; |
2247 | 2223 | ||
2248 | ret = btrfs_check_free_space(root, 1, 1); | ||
2249 | if (ret) | ||
2250 | goto fail; | ||
2251 | |||
2252 | trans = btrfs_start_transaction(root, 1); | 2224 | trans = btrfs_start_transaction(root, 1); |
2253 | 2225 | ||
2254 | btrfs_set_trans_block_group(trans, dir); | 2226 | btrfs_set_trans_block_group(trans, dir); |
@@ -2261,7 +2233,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2261 | nr = trans->blocks_used; | 2233 | nr = trans->blocks_used; |
2262 | 2234 | ||
2263 | btrfs_end_transaction_throttle(trans, root); | 2235 | btrfs_end_transaction_throttle(trans, root); |
2264 | fail: | ||
2265 | btrfs_btree_balance_dirty(root, nr); | 2236 | btrfs_btree_balance_dirty(root, nr); |
2266 | return ret; | 2237 | return ret; |
2267 | } | 2238 | } |
@@ -2284,10 +2255,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2284 | return -ENOTEMPTY; | 2255 | return -ENOTEMPTY; |
2285 | } | 2256 | } |
2286 | 2257 | ||
2287 | ret = btrfs_check_free_space(root, 1, 1); | ||
2288 | if (ret) | ||
2289 | goto fail; | ||
2290 | |||
2291 | trans = btrfs_start_transaction(root, 1); | 2258 | trans = btrfs_start_transaction(root, 1); |
2292 | btrfs_set_trans_block_group(trans, dir); | 2259 | btrfs_set_trans_block_group(trans, dir); |
2293 | 2260 | ||
@@ -2304,7 +2271,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2304 | fail_trans: | 2271 | fail_trans: |
2305 | nr = trans->blocks_used; | 2272 | nr = trans->blocks_used; |
2306 | ret = btrfs_end_transaction_throttle(trans, root); | 2273 | ret = btrfs_end_transaction_throttle(trans, root); |
2307 | fail: | ||
2308 | btrfs_btree_balance_dirty(root, nr); | 2274 | btrfs_btree_balance_dirty(root, nr); |
2309 | 2275 | ||
2310 | if (ret && !err) | 2276 | if (ret && !err) |
@@ -2818,7 +2784,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) | |||
2818 | if (size <= hole_start) | 2784 | if (size <= hole_start) |
2819 | return 0; | 2785 | return 0; |
2820 | 2786 | ||
2821 | err = btrfs_check_free_space(root, 1, 0); | 2787 | err = btrfs_check_metadata_free_space(root); |
2822 | if (err) | 2788 | if (err) |
2823 | return err; | 2789 | return err; |
2824 | 2790 | ||
@@ -3014,6 +2980,7 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
3014 | bi->last_trans = 0; | 2980 | bi->last_trans = 0; |
3015 | bi->logged_trans = 0; | 2981 | bi->logged_trans = 0; |
3016 | bi->delalloc_bytes = 0; | 2982 | bi->delalloc_bytes = 0; |
2983 | bi->reserved_bytes = 0; | ||
3017 | bi->disk_i_size = 0; | 2984 | bi->disk_i_size = 0; |
3018 | bi->flags = 0; | 2985 | bi->flags = 0; |
3019 | bi->index_cnt = (u64)-1; | 2986 | bi->index_cnt = (u64)-1; |
@@ -3035,6 +3002,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p) | |||
3035 | inode->i_ino = args->ino; | 3002 | inode->i_ino = args->ino; |
3036 | init_btrfs_i(inode); | 3003 | init_btrfs_i(inode); |
3037 | BTRFS_I(inode)->root = args->root; | 3004 | BTRFS_I(inode)->root = args->root; |
3005 | btrfs_set_inode_space_info(args->root, inode); | ||
3038 | return 0; | 3006 | return 0; |
3039 | } | 3007 | } |
3040 | 3008 | ||
@@ -3455,6 +3423,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3455 | BTRFS_I(inode)->index_cnt = 2; | 3423 | BTRFS_I(inode)->index_cnt = 2; |
3456 | BTRFS_I(inode)->root = root; | 3424 | BTRFS_I(inode)->root = root; |
3457 | BTRFS_I(inode)->generation = trans->transid; | 3425 | BTRFS_I(inode)->generation = trans->transid; |
3426 | btrfs_set_inode_space_info(root, inode); | ||
3458 | 3427 | ||
3459 | if (mode & S_IFDIR) | 3428 | if (mode & S_IFDIR) |
3460 | owner = 0; | 3429 | owner = 0; |
@@ -3602,7 +3571,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
3602 | if (!new_valid_dev(rdev)) | 3571 | if (!new_valid_dev(rdev)) |
3603 | return -EINVAL; | 3572 | return -EINVAL; |
3604 | 3573 | ||
3605 | err = btrfs_check_free_space(root, 1, 0); | 3574 | err = btrfs_check_metadata_free_space(root); |
3606 | if (err) | 3575 | if (err) |
3607 | goto fail; | 3576 | goto fail; |
3608 | 3577 | ||
@@ -3665,7 +3634,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
3665 | u64 objectid; | 3634 | u64 objectid; |
3666 | u64 index = 0; | 3635 | u64 index = 0; |
3667 | 3636 | ||
3668 | err = btrfs_check_free_space(root, 1, 0); | 3637 | err = btrfs_check_metadata_free_space(root); |
3669 | if (err) | 3638 | if (err) |
3670 | goto fail; | 3639 | goto fail; |
3671 | trans = btrfs_start_transaction(root, 1); | 3640 | trans = btrfs_start_transaction(root, 1); |
@@ -3733,7 +3702,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
3733 | return -ENOENT; | 3702 | return -ENOENT; |
3734 | 3703 | ||
3735 | btrfs_inc_nlink(inode); | 3704 | btrfs_inc_nlink(inode); |
3736 | err = btrfs_check_free_space(root, 1, 0); | 3705 | err = btrfs_check_metadata_free_space(root); |
3737 | if (err) | 3706 | if (err) |
3738 | goto fail; | 3707 | goto fail; |
3739 | err = btrfs_set_inode_index(dir, &index); | 3708 | err = btrfs_set_inode_index(dir, &index); |
@@ -3779,7 +3748,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
3779 | u64 index = 0; | 3748 | u64 index = 0; |
3780 | unsigned long nr = 1; | 3749 | unsigned long nr = 1; |
3781 | 3750 | ||
3782 | err = btrfs_check_free_space(root, 1, 0); | 3751 | err = btrfs_check_metadata_free_space(root); |
3783 | if (err) | 3752 | if (err) |
3784 | goto out_unlock; | 3753 | goto out_unlock; |
3785 | 3754 | ||
@@ -4336,7 +4305,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
4336 | u64 page_start; | 4305 | u64 page_start; |
4337 | u64 page_end; | 4306 | u64 page_end; |
4338 | 4307 | ||
4339 | ret = btrfs_check_free_space(root, PAGE_CACHE_SIZE, 0); | 4308 | ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE); |
4340 | if (ret) | 4309 | if (ret) |
4341 | goto out; | 4310 | goto out; |
4342 | 4311 | ||
@@ -4349,6 +4318,7 @@ again: | |||
4349 | 4318 | ||
4350 | if ((page->mapping != inode->i_mapping) || | 4319 | if ((page->mapping != inode->i_mapping) || |
4351 | (page_start >= size)) { | 4320 | (page_start >= size)) { |
4321 | btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE); | ||
4352 | /* page got truncated out from underneath us */ | 4322 | /* page got truncated out from underneath us */ |
4353 | goto out_unlock; | 4323 | goto out_unlock; |
4354 | } | 4324 | } |
@@ -4631,7 +4601,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4631 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | 4601 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
4632 | return -EXDEV; | 4602 | return -EXDEV; |
4633 | 4603 | ||
4634 | ret = btrfs_check_free_space(root, 1, 0); | 4604 | ret = btrfs_check_metadata_free_space(root); |
4635 | if (ret) | 4605 | if (ret) |
4636 | goto out_unlock; | 4606 | goto out_unlock; |
4637 | 4607 | ||
@@ -4749,7 +4719,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
4749 | if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root)) | 4719 | if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root)) |
4750 | return -ENAMETOOLONG; | 4720 | return -ENAMETOOLONG; |
4751 | 4721 | ||
4752 | err = btrfs_check_free_space(root, 1, 0); | 4722 | err = btrfs_check_metadata_free_space(root); |
4753 | if (err) | 4723 | if (err) |
4754 | goto out_fail; | 4724 | goto out_fail; |
4755 | 4725 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 988fdc8b49eb..bca729fc80c8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -70,7 +70,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
70 | u64 index = 0; | 70 | u64 index = 0; |
71 | unsigned long nr = 1; | 71 | unsigned long nr = 1; |
72 | 72 | ||
73 | ret = btrfs_check_free_space(root, 1, 0); | 73 | ret = btrfs_check_metadata_free_space(root); |
74 | if (ret) | 74 | if (ret) |
75 | goto fail_commit; | 75 | goto fail_commit; |
76 | 76 | ||
@@ -203,7 +203,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
203 | if (!root->ref_cows) | 203 | if (!root->ref_cows) |
204 | return -EINVAL; | 204 | return -EINVAL; |
205 | 205 | ||
206 | ret = btrfs_check_free_space(root, 1, 0); | 206 | ret = btrfs_check_metadata_free_space(root); |
207 | if (ret) | 207 | if (ret) |
208 | goto fail_unlock; | 208 | goto fail_unlock; |
209 | 209 | ||
@@ -374,7 +374,7 @@ static int btrfs_defrag_file(struct file *file) | |||
374 | unsigned long i; | 374 | unsigned long i; |
375 | int ret; | 375 | int ret; |
376 | 376 | ||
377 | ret = btrfs_check_free_space(root, inode->i_size, 0); | 377 | ret = btrfs_check_data_free_space(root, inode, inode->i_size); |
378 | if (ret) | 378 | if (ret) |
379 | return -ENOSPC; | 379 | return -ENOSPC; |
380 | 380 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 665d446b25bc..9f697419ed8e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -777,6 +777,7 @@ static int __set_page_dirty(struct page *page, | |||
777 | __inc_zone_page_state(page, NR_FILE_DIRTY); | 777 | __inc_zone_page_state(page, NR_FILE_DIRTY); |
778 | __inc_bdi_stat(mapping->backing_dev_info, | 778 | __inc_bdi_stat(mapping->backing_dev_info, |
779 | BDI_RECLAIMABLE); | 779 | BDI_RECLAIMABLE); |
780 | task_dirty_inc(current); | ||
780 | task_io_account_write(PAGE_CACHE_SIZE); | 781 | task_io_account_write(PAGE_CACHE_SIZE); |
781 | } | 782 | } |
782 | radix_tree_tag_set(&mapping->page_tree, | 783 | radix_tree_tag_set(&mapping->page_tree, |
@@ -3108,7 +3109,7 @@ int sync_dirty_buffer(struct buffer_head *bh) | |||
3108 | if (test_clear_buffer_dirty(bh)) { | 3109 | if (test_clear_buffer_dirty(bh)) { |
3109 | get_bh(bh); | 3110 | get_bh(bh); |
3110 | bh->b_end_io = end_buffer_write_sync; | 3111 | bh->b_end_io = end_buffer_write_sync; |
3111 | ret = submit_bh(WRITE_SYNC, bh); | 3112 | ret = submit_bh(WRITE, bh); |
3112 | wait_on_buffer(bh); | 3113 | wait_on_buffer(bh); |
3113 | if (buffer_eopnotsupp(bh)) { | 3114 | if (buffer_eopnotsupp(bh)) { |
3114 | clear_buffer_eopnotsupp(bh); | 3115 | clear_buffer_eopnotsupp(bh); |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 73ac7ebd1dfc..851388fafc73 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,3 +1,13 @@ | |||
1 | Version 1.57 | ||
2 | ------------ | ||
3 | Improve support for multiple security contexts to the same server. We | ||
4 | used to use the same "vcnumber" for all connections which could cause | ||
5 | the server to treat subsequent connections, especially those that | ||
6 | are authenticated as guest, as reconnections, invalidating the earlier | ||
7 | user's smb session. This fix allows cifs to mount multiple times to the | ||
8 | same server with different userids without risking invalidating earlier | ||
9 | established security contexts. | ||
10 | |||
1 | Version 1.56 | 11 | Version 1.56 |
2 | ------------ | 12 | ------------ |
3 | Add "forcemandatorylock" mount option to allow user to use mandatory | 13 | Add "forcemandatorylock" mount option to allow user to use mandatory |
@@ -7,7 +17,10 @@ specified and user does not have access to query information about the | |||
7 | top of the share. Fix problem in 2.6.28 resolving DFS paths to | 17 | top of the share. Fix problem in 2.6.28 resolving DFS paths to |
8 | Samba servers (worked to Windows). Fix rmdir so that pending search | 18 | Samba servers (worked to Windows). Fix rmdir so that pending search |
9 | (readdir) requests do not get invalid results which include the now | 19 | (readdir) requests do not get invalid results which include the now |
10 | removed directory. | 20 | removed directory. Fix oops in cifs_dfs_ref.c when prefixpath is not reachable |
21 | when using DFS. Add better file create support to servers which support | ||
22 | the CIFS POSIX protocol extensions (this adds support for new flags | ||
23 | on create, and improves semantics for write of locked ranges). | ||
11 | 24 | ||
12 | Version 1.55 | 25 | Version 1.55 |
13 | ------------ | 26 | ------------ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 7ac481841f87..2b1d28a9ee28 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
100 | extern const struct export_operations cifs_export_ops; | 100 | extern const struct export_operations cifs_export_ops; |
101 | #endif /* EXPERIMENTAL */ | 101 | #endif /* EXPERIMENTAL */ |
102 | 102 | ||
103 | #define CIFS_VERSION "1.56" | 103 | #define CIFS_VERSION "1.57" |
104 | #endif /* _CIFSFS_H */ | 104 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 94c1ca0ec953..e004f6db5fc8 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -164,9 +164,12 @@ struct TCP_Server_Info { | |||
164 | /* multiplexed reads or writes */ | 164 | /* multiplexed reads or writes */ |
165 | unsigned int maxBuf; /* maxBuf specifies the maximum */ | 165 | unsigned int maxBuf; /* maxBuf specifies the maximum */ |
166 | /* message size the server can send or receive for non-raw SMBs */ | 166 | /* message size the server can send or receive for non-raw SMBs */ |
167 | unsigned int maxRw; /* maxRw specifies the maximum */ | 167 | unsigned int max_rw; /* maxRw specifies the maximum */ |
168 | /* message size the server can send or receive for */ | 168 | /* message size the server can send or receive for */ |
169 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ | 169 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
170 | unsigned int max_vcs; /* maximum number of smb sessions, at least | ||
171 | those that can be specified uniquely with | ||
172 | vcnumbers */ | ||
170 | char sessid[4]; /* unique token id for this session */ | 173 | char sessid[4]; /* unique token id for this session */ |
171 | /* (returned on Negotiate */ | 174 | /* (returned on Negotiate */ |
172 | int capabilities; /* allow selective disabling of caps by smb sess */ | 175 | int capabilities; /* allow selective disabling of caps by smb sess */ |
@@ -210,6 +213,7 @@ struct cifsSesInfo { | |||
210 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ | 213 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
211 | __u16 ipc_tid; /* special tid for connection to IPC share */ | 214 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
212 | __u16 flags; | 215 | __u16 flags; |
216 | __u16 vcnum; | ||
213 | char *serverOS; /* name of operating system underlying server */ | 217 | char *serverOS; /* name of operating system underlying server */ |
214 | char *serverNOS; /* name of network operating system of server */ | 218 | char *serverNOS; /* name of network operating system of server */ |
215 | char *serverDomain; /* security realm of server */ | 219 | char *serverDomain; /* security realm of server */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 382ba6298809..083dfc57c7a3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int); | |||
42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); | 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); |
43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} | 43 | #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} |
44 | extern char *build_path_from_dentry(struct dentry *); | 44 | extern char *build_path_from_dentry(struct dentry *); |
45 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); | ||
45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 46 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ | 47 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ |
47 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | 48 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, |
@@ -91,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec); | |||
91 | extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); | 92 | extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); |
92 | extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); | 93 | extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); |
93 | 94 | ||
95 | extern void posix_fill_in_inode(struct inode *tmp_inode, | ||
96 | FILE_UNIX_BASIC_INFO *pData, int isNewInode); | ||
97 | extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum); | ||
94 | extern int cifs_get_inode_info(struct inode **pinode, | 98 | extern int cifs_get_inode_info(struct inode **pinode, |
95 | const unsigned char *search_path, | 99 | const unsigned char *search_path, |
96 | FILE_ALL_INFO *pfile_info, | 100 | FILE_ALL_INFO *pfile_info, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 552642a507c4..939e2f76b959 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -528,14 +528,15 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
528 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); | 528 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); |
529 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | 529 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), |
530 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 530 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
531 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
531 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); | 532 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); |
532 | /* even though we do not use raw we might as well set this | 533 | /* even though we do not use raw we might as well set this |
533 | accurately, in case we ever find a need for it */ | 534 | accurately, in case we ever find a need for it */ |
534 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | 535 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
535 | server->maxRw = 0xFF00; | 536 | server->max_rw = 0xFF00; |
536 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; | 537 | server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE; |
537 | } else { | 538 | } else { |
538 | server->maxRw = 0;/* we do not need to use raw anyway */ | 539 | server->max_rw = 0;/* do not need to use raw anyway */ |
539 | server->capabilities = CAP_MPX_MODE; | 540 | server->capabilities = CAP_MPX_MODE; |
540 | } | 541 | } |
541 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); | 542 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); |
@@ -638,7 +639,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
638 | /* probably no need to store and check maxvcs */ | 639 | /* probably no need to store and check maxvcs */ |
639 | server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), | 640 | server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), |
640 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 641 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
641 | server->maxRw = le32_to_cpu(pSMBr->MaxRawSize); | 642 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); |
642 | cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); | 643 | cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); |
643 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | 644 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); |
644 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 645 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2209be943051..da0f4ffa0613 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
26 | #include <linux/ipv6.h> | ||
27 | #include <linux/pagemap.h> | 26 | #include <linux/pagemap.h> |
28 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
29 | #include <linux/utsname.h> | 28 | #include <linux/utsname.h> |
@@ -35,6 +34,7 @@ | |||
35 | #include <linux/freezer.h> | 34 | #include <linux/freezer.h> |
36 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
37 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
37 | #include <net/ipv6.h> | ||
38 | #include "cifspdu.h" | 38 | #include "cifspdu.h" |
39 | #include "cifsglob.h" | 39 | #include "cifsglob.h" |
40 | #include "cifsproto.h" | 40 | #include "cifsproto.h" |
@@ -1379,8 +1379,8 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) | |||
1379 | server->addr.sockAddr.sin_addr.s_addr)) | 1379 | server->addr.sockAddr.sin_addr.s_addr)) |
1380 | continue; | 1380 | continue; |
1381 | else if (addr->ss_family == AF_INET6 && | 1381 | else if (addr->ss_family == AF_INET6 && |
1382 | memcmp(&server->addr.sockAddr6.sin6_addr, | 1382 | !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, |
1383 | &addr6->sin6_addr, sizeof(addr6->sin6_addr))) | 1383 | &addr6->sin6_addr)) |
1384 | continue; | 1384 | continue; |
1385 | 1385 | ||
1386 | ++server->srv_count; | 1386 | ++server->srv_count; |
@@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2180 | "mount option supported")); | 2180 | "mount option supported")); |
2181 | } | 2181 | } |
2182 | 2182 | ||
2183 | static int | ||
2184 | is_path_accessible(int xid, struct cifsTconInfo *tcon, | ||
2185 | struct cifs_sb_info *cifs_sb, const char *full_path) | ||
2186 | { | ||
2187 | int rc; | ||
2188 | __u64 inode_num; | ||
2189 | FILE_ALL_INFO *pfile_info; | ||
2190 | |||
2191 | rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num, | ||
2192 | cifs_sb->local_nls, | ||
2193 | cifs_sb->mnt_cifs_flags & | ||
2194 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2195 | if (rc != -EOPNOTSUPP) | ||
2196 | return rc; | ||
2197 | |||
2198 | pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | ||
2199 | if (pfile_info == NULL) | ||
2200 | return -ENOMEM; | ||
2201 | |||
2202 | rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info, | ||
2203 | 0 /* not legacy */, cifs_sb->local_nls, | ||
2204 | cifs_sb->mnt_cifs_flags & | ||
2205 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2206 | kfree(pfile_info); | ||
2207 | return rc; | ||
2208 | } | ||
2209 | |||
2183 | int | 2210 | int |
2184 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2211 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
2185 | char *mount_data, const char *devname) | 2212 | char *mount_data, const char *devname) |
@@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2190 | struct cifsSesInfo *pSesInfo = NULL; | 2217 | struct cifsSesInfo *pSesInfo = NULL; |
2191 | struct cifsTconInfo *tcon = NULL; | 2218 | struct cifsTconInfo *tcon = NULL; |
2192 | struct TCP_Server_Info *srvTcp = NULL; | 2219 | struct TCP_Server_Info *srvTcp = NULL; |
2220 | char *full_path; | ||
2193 | 2221 | ||
2194 | xid = GetXid(); | 2222 | xid = GetXid(); |
2195 | 2223 | ||
@@ -2426,6 +2454,23 @@ mount_fail_check: | |||
2426 | cifs_sb->rsize = min(cifs_sb->rsize, | 2454 | cifs_sb->rsize = min(cifs_sb->rsize, |
2427 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); | 2455 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); |
2428 | 2456 | ||
2457 | if (!rc && cifs_sb->prepathlen) { | ||
2458 | /* build_path_to_root works only when we have a valid tcon */ | ||
2459 | full_path = cifs_build_path_to_root(cifs_sb); | ||
2460 | if (full_path == NULL) { | ||
2461 | rc = -ENOMEM; | ||
2462 | goto mount_fail_check; | ||
2463 | } | ||
2464 | rc = is_path_accessible(xid, tcon, cifs_sb, full_path); | ||
2465 | if (rc) { | ||
2466 | cERROR(1, ("Path %s in not accessible: %d", | ||
2467 | full_path, rc)); | ||
2468 | kfree(full_path); | ||
2469 | goto mount_fail_check; | ||
2470 | } | ||
2471 | kfree(full_path); | ||
2472 | } | ||
2473 | |||
2429 | /* volume_info->password is freed above when existing session found | 2474 | /* volume_info->password is freed above when existing session found |
2430 | (in which case it is not needed anymore) but when new sesion is created | 2475 | (in which case it is not needed anymore) but when new sesion is created |
2431 | the password ptr is put in the new session structure (in which case the | 2476 | the password ptr is put in the new session structure (in which case the |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 964aad03c5ad..89fb72832652 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * vfs operations that deal with dentries | 4 | * vfs operations that deal with dentries |
5 | * | 5 | * |
6 | * Copyright (C) International Business Machines Corp., 2002,2008 | 6 | * Copyright (C) International Business Machines Corp., 2002,2009 |
7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
8 | * | 8 | * |
9 | * This library is free software; you can redistribute it and/or modify | 9 | * This library is free software; you can redistribute it and/or modify |
@@ -129,6 +129,78 @@ cifs_bp_rename_retry: | |||
129 | return full_path; | 129 | return full_path; |
130 | } | 130 | } |
131 | 131 | ||
132 | static int cifs_posix_open(char *full_path, struct inode **pinode, | ||
133 | struct super_block *sb, int mode, int oflags, | ||
134 | int *poplock, __u16 *pnetfid, int xid) | ||
135 | { | ||
136 | int rc; | ||
137 | __u32 oplock; | ||
138 | FILE_UNIX_BASIC_INFO *presp_data; | ||
139 | __u32 posix_flags = 0; | ||
140 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
141 | |||
142 | cFYI(1, ("posix open %s", full_path)); | ||
143 | |||
144 | presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
145 | if (presp_data == NULL) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | /* So far cifs posix extensions can only map the following flags. | ||
149 | There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but | ||
150 | so far we do not seem to need them, and we can treat them as local only */ | ||
151 | if ((oflags & (FMODE_READ | FMODE_WRITE)) == | ||
152 | (FMODE_READ | FMODE_WRITE)) | ||
153 | posix_flags = SMB_O_RDWR; | ||
154 | else if (oflags & FMODE_READ) | ||
155 | posix_flags = SMB_O_RDONLY; | ||
156 | else if (oflags & FMODE_WRITE) | ||
157 | posix_flags = SMB_O_WRONLY; | ||
158 | if (oflags & O_CREAT) | ||
159 | posix_flags |= SMB_O_CREAT; | ||
160 | if (oflags & O_EXCL) | ||
161 | posix_flags |= SMB_O_EXCL; | ||
162 | if (oflags & O_TRUNC) | ||
163 | posix_flags |= SMB_O_TRUNC; | ||
164 | if (oflags & O_APPEND) | ||
165 | posix_flags |= SMB_O_APPEND; | ||
166 | if (oflags & O_SYNC) | ||
167 | posix_flags |= SMB_O_SYNC; | ||
168 | if (oflags & O_DIRECTORY) | ||
169 | posix_flags |= SMB_O_DIRECTORY; | ||
170 | if (oflags & O_NOFOLLOW) | ||
171 | posix_flags |= SMB_O_NOFOLLOW; | ||
172 | if (oflags & O_DIRECT) | ||
173 | posix_flags |= SMB_O_DIRECT; | ||
174 | |||
175 | |||
176 | rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, | ||
177 | pnetfid, presp_data, &oplock, full_path, | ||
178 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
179 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
180 | if (rc) | ||
181 | goto posix_open_ret; | ||
182 | |||
183 | if (presp_data->Type == cpu_to_le32(-1)) | ||
184 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | ||
185 | |||
186 | /* get new inode and set it up */ | ||
187 | if (!pinode) | ||
188 | goto posix_open_ret; /* caller does not need info */ | ||
189 | |||
190 | *pinode = cifs_new_inode(sb, &presp_data->UniqueId); | ||
191 | |||
192 | /* We do not need to close the file if new_inode fails since | ||
193 | the caller will retry qpathinfo as long as inode is null */ | ||
194 | if (*pinode == NULL) | ||
195 | goto posix_open_ret; | ||
196 | |||
197 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
198 | |||
199 | posix_open_ret: | ||
200 | kfree(presp_data); | ||
201 | return rc; | ||
202 | } | ||
203 | |||
132 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, | 204 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, |
133 | struct dentry *direntry, | 205 | struct dentry *direntry, |
134 | struct inode *newinode) | 206 | struct inode *newinode) |
@@ -150,7 +222,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
150 | int xid; | 222 | int xid; |
151 | int create_options = CREATE_NOT_DIR; | 223 | int create_options = CREATE_NOT_DIR; |
152 | int oplock = 0; | 224 | int oplock = 0; |
153 | /* BB below access is too much for the mknod to request */ | 225 | int oflags; |
226 | /* | ||
227 | * BB below access is probably too much for mknod to request | ||
228 | * but we have to do query and setpathinfo so requesting | ||
229 | * less could fail (unless we want to request getatr and setatr | ||
230 | * permissions (only). At least for POSIX we do not have to | ||
231 | * request so much. | ||
232 | */ | ||
154 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; | 233 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; |
155 | __u16 fileHandle; | 234 | __u16 fileHandle; |
156 | struct cifs_sb_info *cifs_sb; | 235 | struct cifs_sb_info *cifs_sb; |
@@ -174,13 +253,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
174 | } | 253 | } |
175 | 254 | ||
176 | mode &= ~current->fs->umask; | 255 | mode &= ~current->fs->umask; |
256 | if (oplockEnabled) | ||
257 | oplock = REQ_OPLOCK; | ||
177 | 258 | ||
178 | if (nd && (nd->flags & LOOKUP_OPEN)) { | 259 | if (nd && (nd->flags & LOOKUP_OPEN)) |
179 | int oflags = nd->intent.open.flags; | 260 | oflags = nd->intent.open.flags; |
261 | else | ||
262 | oflags = FMODE_READ; | ||
263 | |||
264 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | ||
265 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | ||
266 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | ||
267 | rc = cifs_posix_open(full_path, &newinode, inode->i_sb, | ||
268 | mode, oflags, &oplock, &fileHandle, xid); | ||
269 | /* EIO could indicate that (posix open) operation is not | ||
270 | supported, despite what server claimed in capability | ||
271 | negotation. EREMOTE indicates DFS junction, which is not | ||
272 | handled in posix open */ | ||
273 | |||
274 | if ((rc == 0) && (newinode == NULL)) | ||
275 | goto cifs_create_get_file_info; /* query inode info */ | ||
276 | else if (rc == 0) /* success, no need to query */ | ||
277 | goto cifs_create_set_dentry; | ||
278 | else if ((rc != -EIO) && (rc != -EREMOTE) && | ||
279 | (rc != -EOPNOTSUPP)) /* path not found or net err */ | ||
280 | goto cifs_create_out; | ||
281 | /* else fallthrough to retry, using older open call, this is | ||
282 | case where server does not support this SMB level, and | ||
283 | falsely claims capability (also get here for DFS case | ||
284 | which should be rare for path not covered on files) */ | ||
285 | } | ||
180 | 286 | ||
287 | if (nd && (nd->flags & LOOKUP_OPEN)) { | ||
288 | /* if the file is going to stay open, then we | ||
289 | need to set the desired access properly */ | ||
181 | desiredAccess = 0; | 290 | desiredAccess = 0; |
182 | if (oflags & FMODE_READ) | 291 | if (oflags & FMODE_READ) |
183 | desiredAccess |= GENERIC_READ; | 292 | desiredAccess |= GENERIC_READ; /* is this too little? */ |
184 | if (oflags & FMODE_WRITE) { | 293 | if (oflags & FMODE_WRITE) { |
185 | desiredAccess |= GENERIC_WRITE; | 294 | desiredAccess |= GENERIC_WRITE; |
186 | if (!(oflags & FMODE_READ)) | 295 | if (!(oflags & FMODE_READ)) |
@@ -199,8 +308,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
199 | 308 | ||
200 | /* BB add processing to set equivalent of mode - e.g. via CreateX with | 309 | /* BB add processing to set equivalent of mode - e.g. via CreateX with |
201 | ACLs */ | 310 | ACLs */ |
202 | if (oplockEnabled) | ||
203 | oplock = REQ_OPLOCK; | ||
204 | 311 | ||
205 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 312 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
206 | if (buf == NULL) { | 313 | if (buf == NULL) { |
@@ -233,116 +340,112 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
233 | } | 340 | } |
234 | if (rc) { | 341 | if (rc) { |
235 | cFYI(1, ("cifs_create returned 0x%x", rc)); | 342 | cFYI(1, ("cifs_create returned 0x%x", rc)); |
236 | } else { | 343 | goto cifs_create_out; |
237 | /* If Open reported that we actually created a file | 344 | } |
238 | then we now have to set the mode if possible */ | 345 | |
239 | if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { | 346 | /* If Open reported that we actually created a file |
240 | struct cifs_unix_set_info_args args = { | 347 | then we now have to set the mode if possible */ |
348 | if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { | ||
349 | struct cifs_unix_set_info_args args = { | ||
241 | .mode = mode, | 350 | .mode = mode, |
242 | .ctime = NO_CHANGE_64, | 351 | .ctime = NO_CHANGE_64, |
243 | .atime = NO_CHANGE_64, | 352 | .atime = NO_CHANGE_64, |
244 | .mtime = NO_CHANGE_64, | 353 | .mtime = NO_CHANGE_64, |
245 | .device = 0, | 354 | .device = 0, |
246 | }; | 355 | }; |
247 | 356 | ||
248 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 357 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
249 | args.uid = (__u64) current_fsuid(); | 358 | args.uid = (__u64) current_fsuid(); |
250 | if (inode->i_mode & S_ISGID) | 359 | if (inode->i_mode & S_ISGID) |
251 | args.gid = (__u64) inode->i_gid; | 360 | args.gid = (__u64) inode->i_gid; |
252 | else | 361 | else |
253 | args.gid = (__u64) current_fsgid(); | 362 | args.gid = (__u64) current_fsgid(); |
254 | } else { | ||
255 | args.uid = NO_CHANGE_64; | ||
256 | args.gid = NO_CHANGE_64; | ||
257 | } | ||
258 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | ||
259 | cifs_sb->local_nls, | ||
260 | cifs_sb->mnt_cifs_flags & | ||
261 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
262 | } else { | 363 | } else { |
263 | /* BB implement mode setting via Windows security | 364 | args.uid = NO_CHANGE_64; |
264 | descriptors e.g. */ | 365 | args.gid = NO_CHANGE_64; |
265 | /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ | ||
266 | |||
267 | /* Could set r/o dos attribute if mode & 0222 == 0 */ | ||
268 | } | 366 | } |
367 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | ||
368 | cifs_sb->local_nls, | ||
369 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
370 | } else { | ||
371 | /* BB implement mode setting via Windows security | ||
372 | descriptors e.g. */ | ||
373 | /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ | ||
269 | 374 | ||
270 | /* server might mask mode so we have to query for it */ | 375 | /* Could set r/o dos attribute if mode & 0222 == 0 */ |
271 | if (tcon->unix_ext) | 376 | } |
272 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 377 | |
273 | inode->i_sb, xid); | 378 | cifs_create_get_file_info: |
274 | else { | 379 | /* server might mask mode so we have to query for it */ |
275 | rc = cifs_get_inode_info(&newinode, full_path, | 380 | if (tcon->unix_ext) |
276 | buf, inode->i_sb, xid, | 381 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
277 | &fileHandle); | 382 | inode->i_sb, xid); |
278 | if (newinode) { | 383 | else { |
279 | if (cifs_sb->mnt_cifs_flags & | 384 | rc = cifs_get_inode_info(&newinode, full_path, buf, |
280 | CIFS_MOUNT_DYNPERM) | 385 | inode->i_sb, xid, &fileHandle); |
281 | newinode->i_mode = mode; | 386 | if (newinode) { |
282 | if ((oplock & CIFS_CREATE_ACTION) && | 387 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) |
283 | (cifs_sb->mnt_cifs_flags & | 388 | newinode->i_mode = mode; |
284 | CIFS_MOUNT_SET_UID)) { | 389 | if ((oplock & CIFS_CREATE_ACTION) && |
285 | newinode->i_uid = current_fsuid(); | 390 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { |
286 | if (inode->i_mode & S_ISGID) | 391 | newinode->i_uid = current_fsuid(); |
287 | newinode->i_gid = | 392 | if (inode->i_mode & S_ISGID) |
288 | inode->i_gid; | 393 | newinode->i_gid = inode->i_gid; |
289 | else | 394 | else |
290 | newinode->i_gid = | 395 | newinode->i_gid = current_fsgid(); |
291 | current_fsgid(); | ||
292 | } | ||
293 | } | 396 | } |
294 | } | 397 | } |
398 | } | ||
295 | 399 | ||
296 | if (rc != 0) { | 400 | cifs_create_set_dentry: |
297 | cFYI(1, ("Create worked, get_inode_info failed rc = %d", | 401 | if (rc == 0) |
298 | rc)); | 402 | setup_cifs_dentry(tcon, direntry, newinode); |
299 | } else | 403 | else |
300 | setup_cifs_dentry(tcon, direntry, newinode); | 404 | cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc)); |
301 | 405 | ||
302 | if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || | 406 | /* nfsd case - nfs srv does not set nd */ |
303 | (!(nd->flags & LOOKUP_OPEN))) { | 407 | if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { |
304 | /* mknod case - do not leave file open */ | 408 | /* mknod case - do not leave file open */ |
305 | CIFSSMBClose(xid, tcon, fileHandle); | 409 | CIFSSMBClose(xid, tcon, fileHandle); |
306 | } else if (newinode) { | 410 | } else if (newinode) { |
307 | struct cifsFileInfo *pCifsFile = | 411 | struct cifsFileInfo *pCifsFile = |
308 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | 412 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
309 | 413 | ||
310 | if (pCifsFile == NULL) | 414 | if (pCifsFile == NULL) |
311 | goto cifs_create_out; | 415 | goto cifs_create_out; |
312 | pCifsFile->netfid = fileHandle; | 416 | pCifsFile->netfid = fileHandle; |
313 | pCifsFile->pid = current->tgid; | 417 | pCifsFile->pid = current->tgid; |
314 | pCifsFile->pInode = newinode; | 418 | pCifsFile->pInode = newinode; |
315 | pCifsFile->invalidHandle = false; | 419 | pCifsFile->invalidHandle = false; |
316 | pCifsFile->closePend = false; | 420 | pCifsFile->closePend = false; |
317 | init_MUTEX(&pCifsFile->fh_sem); | 421 | init_MUTEX(&pCifsFile->fh_sem); |
318 | mutex_init(&pCifsFile->lock_mutex); | 422 | mutex_init(&pCifsFile->lock_mutex); |
319 | INIT_LIST_HEAD(&pCifsFile->llist); | 423 | INIT_LIST_HEAD(&pCifsFile->llist); |
320 | atomic_set(&pCifsFile->wrtPending, 0); | 424 | atomic_set(&pCifsFile->wrtPending, 0); |
321 | 425 | ||
322 | /* set the following in open now | 426 | /* set the following in open now |
323 | pCifsFile->pfile = file; */ | 427 | pCifsFile->pfile = file; */ |
324 | write_lock(&GlobalSMBSeslock); | 428 | write_lock(&GlobalSMBSeslock); |
325 | list_add(&pCifsFile->tlist, &tcon->openFileList); | 429 | list_add(&pCifsFile->tlist, &tcon->openFileList); |
326 | pCifsInode = CIFS_I(newinode); | 430 | pCifsInode = CIFS_I(newinode); |
327 | if (pCifsInode) { | 431 | if (pCifsInode) { |
328 | /* if readable file instance put first in list*/ | 432 | /* if readable file instance put first in list*/ |
329 | if (write_only) { | 433 | if (write_only) { |
330 | list_add_tail(&pCifsFile->flist, | 434 | list_add_tail(&pCifsFile->flist, |
331 | &pCifsInode->openFileList); | 435 | &pCifsInode->openFileList); |
332 | } else { | 436 | } else { |
333 | list_add(&pCifsFile->flist, | 437 | list_add(&pCifsFile->flist, |
334 | &pCifsInode->openFileList); | 438 | &pCifsInode->openFileList); |
335 | } | ||
336 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | ||
337 | pCifsInode->clientCanCacheAll = true; | ||
338 | pCifsInode->clientCanCacheRead = true; | ||
339 | cFYI(1, ("Exclusive Oplock inode %p", | ||
340 | newinode)); | ||
341 | } else if ((oplock & 0xF) == OPLOCK_READ) | ||
342 | pCifsInode->clientCanCacheRead = true; | ||
343 | } | 439 | } |
344 | write_unlock(&GlobalSMBSeslock); | 440 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
441 | pCifsInode->clientCanCacheAll = true; | ||
442 | pCifsInode->clientCanCacheRead = true; | ||
443 | cFYI(1, ("Exclusive Oplock inode %p", | ||
444 | newinode)); | ||
445 | } else if ((oplock & 0xF) == OPLOCK_READ) | ||
446 | pCifsInode->clientCanCacheRead = true; | ||
345 | } | 447 | } |
448 | write_unlock(&GlobalSMBSeslock); | ||
346 | } | 449 | } |
347 | cifs_create_out: | 450 | cifs_create_out: |
348 | kfree(buf); | 451 | kfree(buf); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index bcf7b5184664..4690a360c855 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, | |||
199 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); | 199 | pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); |
200 | } | 200 | } |
201 | 201 | ||
202 | /** | ||
203 | * cifs_new inode - create new inode, initialize, and hash it | ||
204 | * @sb - pointer to superblock | ||
205 | * @inum - if valid pointer and serverino is enabled, replace i_ino with val | ||
206 | * | ||
207 | * Create a new inode, initialize it for CIFS and hash it. Returns the new | ||
208 | * inode or NULL if one couldn't be allocated. | ||
209 | * | ||
210 | * If the share isn't mounted with "serverino" or inum is a NULL pointer then | ||
211 | * we'll just use the inode number assigned by new_inode(). Note that this can | ||
212 | * mean i_ino collisions since the i_ino assigned by new_inode is not | ||
213 | * guaranteed to be unique. | ||
214 | */ | ||
215 | struct inode * | ||
216 | cifs_new_inode(struct super_block *sb, __u64 *inum) | ||
217 | { | ||
218 | struct inode *inode; | ||
219 | |||
220 | inode = new_inode(sb); | ||
221 | if (inode == NULL) | ||
222 | return NULL; | ||
223 | |||
224 | /* | ||
225 | * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we | ||
226 | * stop passing inum as ptr. Are there sanity checks we can use to | ||
227 | * ensure that the server is really filling in that field? Also, | ||
228 | * if serverino is disabled, perhaps we should be using iunique()? | ||
229 | */ | ||
230 | if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | ||
231 | inode->i_ino = (unsigned long) *inum; | ||
232 | |||
233 | /* | ||
234 | * must set this here instead of cifs_alloc_inode since VFS will | ||
235 | * clobber i_flags | ||
236 | */ | ||
237 | if (sb->s_flags & MS_NOATIME) | ||
238 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
239 | |||
240 | insert_inode_hash(inode); | ||
241 | |||
242 | return inode; | ||
243 | } | ||
244 | |||
202 | int cifs_get_inode_info_unix(struct inode **pinode, | 245 | int cifs_get_inode_info_unix(struct inode **pinode, |
203 | const unsigned char *full_path, struct super_block *sb, int xid) | 246 | const unsigned char *full_path, struct super_block *sb, int xid) |
204 | { | 247 | { |
@@ -233,22 +276,11 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
233 | 276 | ||
234 | /* get new inode */ | 277 | /* get new inode */ |
235 | if (*pinode == NULL) { | 278 | if (*pinode == NULL) { |
236 | *pinode = new_inode(sb); | 279 | *pinode = cifs_new_inode(sb, &find_data.UniqueId); |
237 | if (*pinode == NULL) { | 280 | if (*pinode == NULL) { |
238 | rc = -ENOMEM; | 281 | rc = -ENOMEM; |
239 | goto cgiiu_exit; | 282 | goto cgiiu_exit; |
240 | } | 283 | } |
241 | /* Is an i_ino of zero legal? */ | ||
242 | /* note ino incremented to unique num in new_inode */ | ||
243 | /* Are there sanity checks we can use to ensure that | ||
244 | the server is really filling in that field? */ | ||
245 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
246 | (*pinode)->i_ino = (unsigned long)find_data.UniqueId; | ||
247 | |||
248 | if (sb->s_flags & MS_NOATIME) | ||
249 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
250 | |||
251 | insert_inode_hash(*pinode); | ||
252 | } | 284 | } |
253 | 285 | ||
254 | inode = *pinode; | 286 | inode = *pinode; |
@@ -465,11 +497,9 @@ int cifs_get_inode_info(struct inode **pinode, | |||
465 | 497 | ||
466 | /* get new inode */ | 498 | /* get new inode */ |
467 | if (*pinode == NULL) { | 499 | if (*pinode == NULL) { |
468 | *pinode = new_inode(sb); | 500 | __u64 inode_num; |
469 | if (*pinode == NULL) { | 501 | __u64 *pinum = &inode_num; |
470 | rc = -ENOMEM; | 502 | |
471 | goto cgii_exit; | ||
472 | } | ||
473 | /* Is an i_ino of zero legal? Can we use that to check | 503 | /* Is an i_ino of zero legal? Can we use that to check |
474 | if the server supports returning inode numbers? Are | 504 | if the server supports returning inode numbers? Are |
475 | there other sanity checks we can use to ensure that | 505 | there other sanity checks we can use to ensure that |
@@ -486,22 +516,26 @@ int cifs_get_inode_info(struct inode **pinode, | |||
486 | 516 | ||
487 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 517 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
488 | int rc1 = 0; | 518 | int rc1 = 0; |
489 | __u64 inode_num; | ||
490 | 519 | ||
491 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 520 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
492 | full_path, &inode_num, | 521 | full_path, pinum, |
493 | cifs_sb->local_nls, | 522 | cifs_sb->local_nls, |
494 | cifs_sb->mnt_cifs_flags & | 523 | cifs_sb->mnt_cifs_flags & |
495 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 524 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
496 | if (rc1) { | 525 | if (rc1) { |
497 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | 526 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); |
527 | pinum = NULL; | ||
498 | /* BB EOPNOSUPP disable SERVER_INUM? */ | 528 | /* BB EOPNOSUPP disable SERVER_INUM? */ |
499 | } else /* do we need cast or hash to ino? */ | 529 | } |
500 | (*pinode)->i_ino = inode_num; | 530 | } else { |
501 | } /* else ino incremented to unique num in new_inode*/ | 531 | pinum = NULL; |
502 | if (sb->s_flags & MS_NOATIME) | 532 | } |
503 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | 533 | |
504 | insert_inode_hash(*pinode); | 534 | *pinode = cifs_new_inode(sb, pinum); |
535 | if (*pinode == NULL) { | ||
536 | rc = -ENOMEM; | ||
537 | goto cgii_exit; | ||
538 | } | ||
505 | } | 539 | } |
506 | inode = *pinode; | 540 | inode = *pinode; |
507 | cifsInfo = CIFS_I(inode); | 541 | cifsInfo = CIFS_I(inode); |
@@ -621,7 +655,7 @@ static const struct inode_operations cifs_ipc_inode_ops = { | |||
621 | .lookup = cifs_lookup, | 655 | .lookup = cifs_lookup, |
622 | }; | 656 | }; |
623 | 657 | ||
624 | static char *build_path_to_root(struct cifs_sb_info *cifs_sb) | 658 | char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb) |
625 | { | 659 | { |
626 | int pplen = cifs_sb->prepathlen; | 660 | int pplen = cifs_sb->prepathlen; |
627 | int dfsplen; | 661 | int dfsplen; |
@@ -678,7 +712,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino) | |||
678 | return inode; | 712 | return inode; |
679 | 713 | ||
680 | cifs_sb = CIFS_SB(inode->i_sb); | 714 | cifs_sb = CIFS_SB(inode->i_sb); |
681 | full_path = build_path_to_root(cifs_sb); | 715 | full_path = cifs_build_path_to_root(cifs_sb); |
682 | if (full_path == NULL) | 716 | if (full_path == NULL) |
683 | return ERR_PTR(-ENOMEM); | 717 | return ERR_PTR(-ENOMEM); |
684 | 718 | ||
@@ -1017,7 +1051,7 @@ out_reval: | |||
1017 | return rc; | 1051 | return rc; |
1018 | } | 1052 | } |
1019 | 1053 | ||
1020 | static void posix_fill_in_inode(struct inode *tmp_inode, | 1054 | void posix_fill_in_inode(struct inode *tmp_inode, |
1021 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) | 1055 | FILE_UNIX_BASIC_INFO *pData, int isNewInode) |
1022 | { | 1056 | { |
1023 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | 1057 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); |
@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1114 | else | 1148 | else |
1115 | direntry->d_op = &cifs_dentry_ops; | 1149 | direntry->d_op = &cifs_dentry_ops; |
1116 | 1150 | ||
1117 | newinode = new_inode(inode->i_sb); | 1151 | newinode = cifs_new_inode(inode->i_sb, |
1152 | &pInfo->UniqueId); | ||
1118 | if (newinode == NULL) { | 1153 | if (newinode == NULL) { |
1119 | kfree(pInfo); | 1154 | kfree(pInfo); |
1120 | goto mkdir_get_info; | 1155 | goto mkdir_get_info; |
1121 | } | 1156 | } |
1122 | 1157 | ||
1123 | /* Is an i_ino of zero legal? */ | ||
1124 | /* Are there sanity checks we can use to ensure that | ||
1125 | the server is really filling in that field? */ | ||
1126 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | ||
1127 | newinode->i_ino = | ||
1128 | (unsigned long)pInfo->UniqueId; | ||
1129 | } /* note ino incremented to unique num in new_inode */ | ||
1130 | if (inode->i_sb->s_flags & MS_NOATIME) | ||
1131 | newinode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
1132 | newinode->i_nlink = 2; | 1158 | newinode->i_nlink = 2; |
1133 | |||
1134 | insert_inode_hash(newinode); | ||
1135 | d_instantiate(direntry, newinode); | 1159 | d_instantiate(direntry, newinode); |
1136 | 1160 | ||
1137 | /* we already checked in POSIXCreate whether | 1161 | /* we already checked in POSIXCreate whether |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 9f51f9bf0292..c2c01ff4c32c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
56 | } | 56 | } |
57 | #endif /* DEBUG2 */ | 57 | #endif /* DEBUG2 */ |
58 | 58 | ||
59 | /* Returns one if new inode created (which therefore needs to be hashed) */ | 59 | /* Returns 1 if new inode created, 2 if both dentry and inode were */ |
60 | /* Might check in the future if inode number changed so we can rehash inode */ | 60 | /* Might check in the future if inode number changed so we can rehash inode */ |
61 | static int construct_dentry(struct qstr *qstring, struct file *file, | 61 | static int |
62 | struct inode **ptmp_inode, struct dentry **pnew_dentry) | 62 | construct_dentry(struct qstr *qstring, struct file *file, |
63 | struct inode **ptmp_inode, struct dentry **pnew_dentry, | ||
64 | __u64 *inum) | ||
63 | { | 65 | { |
64 | struct dentry *tmp_dentry; | 66 | struct dentry *tmp_dentry = NULL; |
65 | struct cifs_sb_info *cifs_sb; | 67 | struct super_block *sb = file->f_path.dentry->d_sb; |
66 | struct cifsTconInfo *pTcon; | ||
67 | int rc = 0; | 68 | int rc = 0; |
68 | 69 | ||
69 | cFYI(1, ("For %s", qstring->name)); | 70 | cFYI(1, ("For %s", qstring->name)); |
70 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
71 | pTcon = cifs_sb->tcon; | ||
72 | 71 | ||
73 | qstring->hash = full_name_hash(qstring->name, qstring->len); | 72 | qstring->hash = full_name_hash(qstring->name, qstring->len); |
74 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); | 73 | tmp_dentry = d_lookup(file->f_path.dentry, qstring); |
75 | if (tmp_dentry) { | 74 | if (tmp_dentry) { |
75 | /* BB: overwrite old name? i.e. tmp_dentry->d_name and | ||
76 | * tmp_dentry->d_name.len?? | ||
77 | */ | ||
76 | cFYI(0, ("existing dentry with inode 0x%p", | 78 | cFYI(0, ("existing dentry with inode 0x%p", |
77 | tmp_dentry->d_inode)); | 79 | tmp_dentry->d_inode)); |
78 | *ptmp_inode = tmp_dentry->d_inode; | 80 | *ptmp_inode = tmp_dentry->d_inode; |
79 | /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ | ||
80 | if (*ptmp_inode == NULL) { | 81 | if (*ptmp_inode == NULL) { |
81 | *ptmp_inode = new_inode(file->f_path.dentry->d_sb); | 82 | *ptmp_inode = cifs_new_inode(sb, inum); |
82 | if (*ptmp_inode == NULL) | 83 | if (*ptmp_inode == NULL) |
83 | return rc; | 84 | return rc; |
84 | rc = 1; | 85 | rc = 1; |
85 | } | 86 | } |
86 | if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) | ||
87 | (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
88 | } else { | 87 | } else { |
89 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); | 88 | tmp_dentry = d_alloc(file->f_path.dentry, qstring); |
90 | if (tmp_dentry == NULL) { | 89 | if (tmp_dentry == NULL) { |
@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file, | |||
93 | return rc; | 92 | return rc; |
94 | } | 93 | } |
95 | 94 | ||
96 | *ptmp_inode = new_inode(file->f_path.dentry->d_sb); | 95 | if (CIFS_SB(sb)->tcon->nocase) |
97 | if (pTcon->nocase) | ||
98 | tmp_dentry->d_op = &cifs_ci_dentry_ops; | 96 | tmp_dentry->d_op = &cifs_ci_dentry_ops; |
99 | else | 97 | else |
100 | tmp_dentry->d_op = &cifs_dentry_ops; | 98 | tmp_dentry->d_op = &cifs_dentry_ops; |
99 | |||
100 | *ptmp_inode = cifs_new_inode(sb, inum); | ||
101 | if (*ptmp_inode == NULL) | 101 | if (*ptmp_inode == NULL) |
102 | return rc; | 102 | return rc; |
103 | if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME) | ||
104 | (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME; | ||
105 | rc = 2; | 103 | rc = 2; |
106 | } | 104 | } |
107 | 105 | ||
@@ -822,7 +820,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
822 | /* inode num, inode type and filename returned */ | 820 | /* inode num, inode type and filename returned */ |
823 | static int cifs_get_name_from_search_buf(struct qstr *pqst, | 821 | static int cifs_get_name_from_search_buf(struct qstr *pqst, |
824 | char *current_entry, __u16 level, unsigned int unicode, | 822 | char *current_entry, __u16 level, unsigned int unicode, |
825 | struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum) | 823 | struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) |
826 | { | 824 | { |
827 | int rc = 0; | 825 | int rc = 0; |
828 | unsigned int len = 0; | 826 | unsigned int len = 0; |
@@ -842,9 +840,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
842 | len = strnlen(filename, PATH_MAX); | 840 | len = strnlen(filename, PATH_MAX); |
843 | } | 841 | } |
844 | 842 | ||
845 | /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */ | 843 | *pinum = pFindData->UniqueId; |
846 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
847 | *pinum = pFindData->UniqueId; | ||
848 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { | 844 | } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { |
849 | FILE_DIRECTORY_INFO *pFindData = | 845 | FILE_DIRECTORY_INFO *pFindData = |
850 | (FILE_DIRECTORY_INFO *)current_entry; | 846 | (FILE_DIRECTORY_INFO *)current_entry; |
@@ -907,7 +903,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
907 | struct qstr qstring; | 903 | struct qstr qstring; |
908 | struct cifsFileInfo *pCifsF; | 904 | struct cifsFileInfo *pCifsF; |
909 | unsigned int obj_type; | 905 | unsigned int obj_type; |
910 | ino_t inum; | 906 | __u64 inum; |
911 | struct cifs_sb_info *cifs_sb; | 907 | struct cifs_sb_info *cifs_sb; |
912 | struct inode *tmp_inode; | 908 | struct inode *tmp_inode; |
913 | struct dentry *tmp_dentry; | 909 | struct dentry *tmp_dentry; |
@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file, | |||
940 | if (rc) | 936 | if (rc) |
941 | return rc; | 937 | return rc; |
942 | 938 | ||
943 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry); | 939 | /* only these two infolevels return valid inode numbers */ |
940 | if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX || | ||
941 | pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO) | ||
942 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
943 | &inum); | ||
944 | else | ||
945 | rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry, | ||
946 | NULL); | ||
947 | |||
944 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) | 948 | if ((tmp_inode == NULL) || (tmp_dentry == NULL)) |
945 | return -ENOMEM; | 949 | return -ENOMEM; |
946 | 950 | ||
947 | if (rc) { | ||
948 | /* inode created, we need to hash it with right inode number */ | ||
949 | if (inum != 0) { | ||
950 | /* BB fixme - hash the 2 32 quantities bits together if | ||
951 | * necessary BB */ | ||
952 | tmp_inode->i_ino = inum; | ||
953 | } | ||
954 | insert_inode_hash(tmp_inode); | ||
955 | } | ||
956 | |||
957 | /* we pass in rc below, indicating whether it is a new inode, | 951 | /* we pass in rc below, indicating whether it is a new inode, |
958 | so we can figure out whether to invalidate the inode cached | 952 | so we can figure out whether to invalidate the inode cached |
959 | data if the file has changed */ | 953 | data if the file has changed */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 5f22de7b79a9..5c68b4282be9 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -34,15 +34,99 @@ | |||
34 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 34 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
35 | unsigned char *p24); | 35 | unsigned char *p24); |
36 | 36 | ||
37 | /* Checks if this is the first smb session to be reconnected after | ||
38 | the socket has been reestablished (so we know whether to use vc 0). | ||
39 | Called while holding the cifs_tcp_ses_lock, so do not block */ | ||
40 | static bool is_first_ses_reconnect(struct cifsSesInfo *ses) | ||
41 | { | ||
42 | struct list_head *tmp; | ||
43 | struct cifsSesInfo *tmp_ses; | ||
44 | |||
45 | list_for_each(tmp, &ses->server->smb_ses_list) { | ||
46 | tmp_ses = list_entry(tmp, struct cifsSesInfo, | ||
47 | smb_ses_list); | ||
48 | if (tmp_ses->need_reconnect == false) | ||
49 | return false; | ||
50 | } | ||
51 | /* could not find a session that was already connected, | ||
52 | this must be the first one we are reconnecting */ | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * vc number 0 is treated specially by some servers, and should be the | ||
58 | * first one we request. After that we can use vcnumbers up to maxvcs, | ||
59 | * one for each smb session (some Windows versions set maxvcs incorrectly | ||
60 | * so maxvc=1 can be ignored). If we have too many vcs, we can reuse | ||
61 | * any vc but zero (some servers reset the connection on vcnum zero) | ||
62 | * | ||
63 | */ | ||
64 | static __le16 get_next_vcnum(struct cifsSesInfo *ses) | ||
65 | { | ||
66 | __u16 vcnum = 0; | ||
67 | struct list_head *tmp; | ||
68 | struct cifsSesInfo *tmp_ses; | ||
69 | __u16 max_vcs = ses->server->max_vcs; | ||
70 | __u16 i; | ||
71 | int free_vc_found = 0; | ||
72 | |||
73 | /* Quoting the MS-SMB specification: "Windows-based SMB servers set this | ||
74 | field to one but do not enforce this limit, which allows an SMB client | ||
75 | to establish more virtual circuits than allowed by this value ... but | ||
76 | other server implementations can enforce this limit." */ | ||
77 | if (max_vcs < 2) | ||
78 | max_vcs = 0xFFFF; | ||
79 | |||
80 | write_lock(&cifs_tcp_ses_lock); | ||
81 | if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) | ||
82 | goto get_vc_num_exit; /* vcnum will be zero */ | ||
83 | for (i = ses->server->srv_count - 1; i < max_vcs; i++) { | ||
84 | if (i == 0) /* this is the only connection, use vc 0 */ | ||
85 | break; | ||
86 | |||
87 | free_vc_found = 1; | ||
88 | |||
89 | list_for_each(tmp, &ses->server->smb_ses_list) { | ||
90 | tmp_ses = list_entry(tmp, struct cifsSesInfo, | ||
91 | smb_ses_list); | ||
92 | if (tmp_ses->vcnum == i) { | ||
93 | free_vc_found = 0; | ||
94 | break; /* found duplicate, try next vcnum */ | ||
95 | } | ||
96 | } | ||
97 | if (free_vc_found) | ||
98 | break; /* we found a vcnumber that will work - use it */ | ||
99 | } | ||
100 | |||
101 | if (i == 0) | ||
102 | vcnum = 0; /* for most common case, ie if one smb session, use | ||
103 | vc zero. Also for case when no free vcnum, zero | ||
104 | is safest to send (some clients only send zero) */ | ||
105 | else if (free_vc_found == 0) | ||
106 | vcnum = 1; /* we can not reuse vc=0 safely, since some servers | ||
107 | reset all uids on that, but 1 is ok. */ | ||
108 | else | ||
109 | vcnum = i; | ||
110 | ses->vcnum = vcnum; | ||
111 | get_vc_num_exit: | ||
112 | write_unlock(&cifs_tcp_ses_lock); | ||
113 | |||
114 | return le16_to_cpu(vcnum); | ||
115 | } | ||
116 | |||
37 | static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) | 117 | static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) |
38 | { | 118 | { |
39 | __u32 capabilities = 0; | 119 | __u32 capabilities = 0; |
40 | 120 | ||
41 | /* init fields common to all four types of SessSetup */ | 121 | /* init fields common to all four types of SessSetup */ |
42 | /* note that header is initialized to zero in header_assemble */ | 122 | /* Note that offsets for first seven fields in req struct are same */ |
123 | /* in CIFS Specs so does not matter which of 3 forms of struct */ | ||
124 | /* that we use in next few lines */ | ||
125 | /* Note that header is initialized to zero in header_assemble */ | ||
43 | pSMB->req.AndXCommand = 0xFF; | 126 | pSMB->req.AndXCommand = 0xFF; |
44 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 127 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
45 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 128 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
129 | pSMB->req.VcNumber = get_next_vcnum(ses); | ||
46 | 130 | ||
47 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ | 131 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ |
48 | 132 | ||
@@ -71,7 +155,6 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) | |||
71 | if (ses->capabilities & CAP_UNIX) | 155 | if (ses->capabilities & CAP_UNIX) |
72 | capabilities |= CAP_UNIX; | 156 | capabilities |= CAP_UNIX; |
73 | 157 | ||
74 | /* BB check whether to init vcnum BB */ | ||
75 | return capabilities; | 158 | return capabilities; |
76 | } | 159 | } |
77 | 160 | ||
@@ -228,7 +311,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
228 | 311 | ||
229 | kfree(ses->serverOS); | 312 | kfree(ses->serverOS); |
230 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ | 313 | /* UTF-8 string will not grow more than four times as big as UCS-16 */ |
231 | ses->serverOS = kzalloc(4 * len, GFP_KERNEL); | 314 | ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); |
232 | if (ses->serverOS != NULL) | 315 | if (ses->serverOS != NULL) |
233 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); | 316 | cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); |
234 | data += 2 * (len + 1); | 317 | data += 2 * (len + 1); |
@@ -241,7 +324,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, | |||
241 | return rc; | 324 | return rc; |
242 | 325 | ||
243 | kfree(ses->serverNOS); | 326 | kfree(ses->serverNOS); |
244 | ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ | 327 | ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); |
245 | if (ses->serverNOS != NULL) { | 328 | if (ses->serverNOS != NULL) { |
246 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, | 329 | cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, |
247 | nls_cp); | 330 | nls_cp); |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 9c6d815dd191..45e59d3c7f1f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -1913,6 +1913,9 @@ COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ | |||
1913 | /* 0x00 */ | 1913 | /* 0x00 */ |
1914 | COMPATIBLE_IOCTL(FIBMAP) | 1914 | COMPATIBLE_IOCTL(FIBMAP) |
1915 | COMPATIBLE_IOCTL(FIGETBSZ) | 1915 | COMPATIBLE_IOCTL(FIGETBSZ) |
1916 | /* 'X' - originally XFS but some now in the VFS */ | ||
1917 | COMPATIBLE_IOCTL(FIFREEZE) | ||
1918 | COMPATIBLE_IOCTL(FITHAW) | ||
1916 | /* RAID */ | 1919 | /* RAID */ |
1917 | COMPATIBLE_IOCTL(RAID_VERSION) | 1920 | COMPATIBLE_IOCTL(RAID_VERSION) |
1918 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) | 1921 | COMPATIBLE_IOCTL(GET_ARRAY_INFO) |
@@ -1938,6 +1941,8 @@ ULONG_IOCTL(SET_BITMAP_FILE) | |||
1938 | /* Big K */ | 1941 | /* Big K */ |
1939 | COMPATIBLE_IOCTL(PIO_FONT) | 1942 | COMPATIBLE_IOCTL(PIO_FONT) |
1940 | COMPATIBLE_IOCTL(GIO_FONT) | 1943 | COMPATIBLE_IOCTL(GIO_FONT) |
1944 | COMPATIBLE_IOCTL(PIO_CMAP) | ||
1945 | COMPATIBLE_IOCTL(GIO_CMAP) | ||
1941 | ULONG_IOCTL(KDSIGACCEPT) | 1946 | ULONG_IOCTL(KDSIGACCEPT) |
1942 | COMPATIBLE_IOCTL(KDGETKEYCODE) | 1947 | COMPATIBLE_IOCTL(KDGETKEYCODE) |
1943 | COMPATIBLE_IOCTL(KDSETKEYCODE) | 1948 | COMPATIBLE_IOCTL(KDSETKEYCODE) |
diff --git a/fs/dcache.c b/fs/dcache.c index 937df0fb0da5..07e2d4a44bda 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1180,7 +1180,7 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1180 | iput(inode); | 1180 | iput(inode); |
1181 | return res; | 1181 | return res; |
1182 | } | 1182 | } |
1183 | EXPORT_SYMBOL_GPL(d_obtain_alias); | 1183 | EXPORT_SYMBOL(d_obtain_alias); |
1184 | 1184 | ||
1185 | /** | 1185 | /** |
1186 | * d_splice_alias - splice a disconnected dentry into the tree if one exists | 1186 | * d_splice_alias - splice a disconnected dentry into the tree if one exists |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 9a50b8052dcf..de9459b4cb94 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -609,7 +609,9 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | |||
609 | */ | 609 | */ |
610 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) | 610 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) |
611 | { | 611 | { |
612 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3) | 612 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || |
613 | (*retries)++ > 3 || | ||
614 | !EXT4_SB(sb)->s_journal) | ||
613 | return 0; | 615 | return 0; |
614 | 616 | ||
615 | jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); | 617 | jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4fb86a0061d0..f18a919be70b 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -715,6 +715,13 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) | |||
715 | 715 | ||
716 | if (sbi->s_log_groups_per_flex) { | 716 | if (sbi->s_log_groups_per_flex) { |
717 | ret2 = find_group_flex(sb, dir, &group); | 717 | ret2 = find_group_flex(sb, dir, &group); |
718 | if (ret2 == -1) { | ||
719 | ret2 = find_group_other(sb, dir, &group); | ||
720 | if (ret2 == 0 && printk_ratelimit()) | ||
721 | printk(KERN_NOTICE "ext4: find_group_flex " | ||
722 | "failed, fallback succeeded dir %lu\n", | ||
723 | dir->i_ino); | ||
724 | } | ||
718 | goto got_group; | 725 | goto got_group; |
719 | } | 726 | } |
720 | 727 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cbd2ca99d113..c7fed5b18745 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1368,6 +1368,10 @@ retry: | |||
1368 | goto out; | 1368 | goto out; |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | /* We cannot recurse into the filesystem as the transaction is already | ||
1372 | * started */ | ||
1373 | flags |= AOP_FLAG_NOFS; | ||
1374 | |||
1371 | page = grab_cache_page_write_begin(mapping, index, flags); | 1375 | page = grab_cache_page_write_begin(mapping, index, flags); |
1372 | if (!page) { | 1376 | if (!page) { |
1373 | ext4_journal_stop(handle); | 1377 | ext4_journal_stop(handle); |
@@ -1377,7 +1381,7 @@ retry: | |||
1377 | *pagep = page; | 1381 | *pagep = page; |
1378 | 1382 | ||
1379 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 1383 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
1380 | ext4_get_block); | 1384 | ext4_get_block); |
1381 | 1385 | ||
1382 | if (!ret && ext4_should_journal_data(inode)) { | 1386 | if (!ret && ext4_should_journal_data(inode)) { |
1383 | ret = walk_page_buffers(handle, page_buffers(page), | 1387 | ret = walk_page_buffers(handle, page_buffers(page), |
@@ -2540,7 +2544,7 @@ retry: | |||
2540 | 2544 | ||
2541 | ext4_journal_stop(handle); | 2545 | ext4_journal_stop(handle); |
2542 | 2546 | ||
2543 | if (mpd.retval == -ENOSPC) { | 2547 | if ((mpd.retval == -ENOSPC) && sbi->s_journal) { |
2544 | /* commit the transaction which would | 2548 | /* commit the transaction which would |
2545 | * free blocks released in the transaction | 2549 | * free blocks released in the transaction |
2546 | * and try again | 2550 | * and try again |
@@ -2667,6 +2671,9 @@ retry: | |||
2667 | ret = PTR_ERR(handle); | 2671 | ret = PTR_ERR(handle); |
2668 | goto out; | 2672 | goto out; |
2669 | } | 2673 | } |
2674 | /* We cannot recurse into the filesystem as the transaction is already | ||
2675 | * started */ | ||
2676 | flags |= AOP_FLAG_NOFS; | ||
2670 | 2677 | ||
2671 | page = grab_cache_page_write_begin(mapping, index, flags); | 2678 | page = grab_cache_page_write_begin(mapping, index, flags); |
2672 | if (!page) { | 2679 | if (!page) { |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a5732c58f676..39d1993cfa13 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3091,7 +3091,6 @@ static int ext4_freeze(struct super_block *sb) | |||
3091 | 3091 | ||
3092 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 3092 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
3093 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 3093 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
3094 | ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | ||
3095 | error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | 3094 | error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); |
3096 | if (error) | 3095 | if (error) |
3097 | goto out; | 3096 | goto out; |
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 3cceef4ad2b7..e9580104b6ba 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -95,13 +95,17 @@ static int jffs2_garbage_collect_thread(void *_c) | |||
95 | spin_unlock(&c->erase_completion_lock); | 95 | spin_unlock(&c->erase_completion_lock); |
96 | 96 | ||
97 | 97 | ||
98 | /* This thread is purely an optimisation. But if it runs when | 98 | /* Problem - immediately after bootup, the GCD spends a lot |
99 | other things could be running, it actually makes things a | 99 | * of time in places like jffs2_kill_fragtree(); so much so |
100 | lot worse. Use yield() and put it at the back of the runqueue | 100 | * that userspace processes (like gdm and X) are starved |
101 | every time. Especially during boot, pulling an inode in | 101 | * despite plenty of cond_resched()s and renicing. Yield() |
102 | with read_inode() is much preferable to having the GC thread | 102 | * doesn't help, either (presumably because userspace and GCD |
103 | get there first. */ | 103 | * are generally competing for a higher latency resource - |
104 | yield(); | 104 | * disk). |
105 | * This forces the GCD to slow the hell down. Pulling an | ||
106 | * inode in with read_inode() is much preferable to having | ||
107 | * the GC thread get there first. */ | ||
108 | schedule_timeout_interruptible(msecs_to_jiffies(50)); | ||
105 | 109 | ||
106 | /* Put_super will send a SIGKILL and then wait on the sem. | 110 | /* Put_super will send a SIGKILL and then wait on the sem. |
107 | */ | 111 | */ |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6ca08ad887c0..1fc1e92356ee 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -220,7 +220,7 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
220 | struct jffs2_tmp_dnode_info *tn) | 220 | struct jffs2_tmp_dnode_info *tn) |
221 | { | 221 | { |
222 | uint32_t fn_end = tn->fn->ofs + tn->fn->size; | 222 | uint32_t fn_end = tn->fn->ofs + tn->fn->size; |
223 | struct jffs2_tmp_dnode_info *this; | 223 | struct jffs2_tmp_dnode_info *this, *ptn; |
224 | 224 | ||
225 | dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); | 225 | dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); |
226 | 226 | ||
@@ -251,11 +251,18 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
251 | if (this) { | 251 | if (this) { |
252 | /* If the node is coincident with another at a lower address, | 252 | /* If the node is coincident with another at a lower address, |
253 | back up until the other node is found. It may be relevant */ | 253 | back up until the other node is found. It may be relevant */ |
254 | while (this->overlapped) | 254 | while (this->overlapped) { |
255 | this = tn_prev(this); | 255 | ptn = tn_prev(this); |
256 | 256 | if (!ptn) { | |
257 | /* First node should never be marked overlapped */ | 257 | /* |
258 | BUG_ON(!this); | 258 | * We killed a node which set the overlapped |
259 | * flags during the scan. Fix it up. | ||
260 | */ | ||
261 | this->overlapped = 0; | ||
262 | break; | ||
263 | } | ||
264 | this = ptn; | ||
265 | } | ||
259 | dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); | 266 | dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); |
260 | } | 267 | } |
261 | 268 | ||
@@ -360,7 +367,17 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, | |||
360 | } | 367 | } |
361 | if (!this->overlapped) | 368 | if (!this->overlapped) |
362 | break; | 369 | break; |
363 | this = tn_prev(this); | 370 | |
371 | ptn = tn_prev(this); | ||
372 | if (!ptn) { | ||
373 | /* | ||
374 | * We killed a node which set the overlapped | ||
375 | * flags during the scan. Fix it up. | ||
376 | */ | ||
377 | this->overlapped = 0; | ||
378 | break; | ||
379 | } | ||
380 | this = ptn; | ||
364 | } | 381 | } |
365 | } | 382 | } |
366 | 383 | ||
@@ -456,8 +473,15 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
456 | eat_last(&rii->tn_root, &last->rb); | 473 | eat_last(&rii->tn_root, &last->rb); |
457 | ver_insert(&ver_root, last); | 474 | ver_insert(&ver_root, last); |
458 | 475 | ||
459 | if (unlikely(last->overlapped)) | 476 | if (unlikely(last->overlapped)) { |
460 | continue; | 477 | if (pen) |
478 | continue; | ||
479 | /* | ||
480 | * We killed a node which set the overlapped | ||
481 | * flags during the scan. Fix it up. | ||
482 | */ | ||
483 | last->overlapped = 0; | ||
484 | } | ||
461 | 485 | ||
462 | /* Now we have a bunch of nodes in reverse version | 486 | /* Now we have a bunch of nodes in reverse version |
463 | order, in the tree at ver_root. Most of the time, | 487 | order, in the tree at ver_root. Most of the time, |
diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c index dae3f28f30d4..331f2e88e284 100644 --- a/fs/notify/inotify/inotify.c +++ b/fs/notify/inotify/inotify.c | |||
@@ -156,7 +156,7 @@ static int inotify_handle_get_wd(struct inotify_handle *ih, | |||
156 | int ret; | 156 | int ret; |
157 | 157 | ||
158 | do { | 158 | do { |
159 | if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL))) | 159 | if (unlikely(!idr_pre_get(&ih->idr, GFP_NOFS))) |
160 | return -ENOSPC; | 160 | return -ENOSPC; |
161 | ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd); | 161 | ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd); |
162 | } while (ret == -EAGAIN); | 162 | } while (ret == -EAGAIN); |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 60fe74035db5..3a9e5deed74d 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -4796,6 +4796,29 @@ out: | |||
4796 | return ret; | 4796 | return ret; |
4797 | } | 4797 | } |
4798 | 4798 | ||
4799 | static int ocfs2_replace_extent_rec(struct inode *inode, | ||
4800 | handle_t *handle, | ||
4801 | struct ocfs2_path *path, | ||
4802 | struct ocfs2_extent_list *el, | ||
4803 | int split_index, | ||
4804 | struct ocfs2_extent_rec *split_rec) | ||
4805 | { | ||
4806 | int ret; | ||
4807 | |||
4808 | ret = ocfs2_path_bh_journal_access(handle, inode, path, | ||
4809 | path_num_items(path) - 1); | ||
4810 | if (ret) { | ||
4811 | mlog_errno(ret); | ||
4812 | goto out; | ||
4813 | } | ||
4814 | |||
4815 | el->l_recs[split_index] = *split_rec; | ||
4816 | |||
4817 | ocfs2_journal_dirty(handle, path_leaf_bh(path)); | ||
4818 | out: | ||
4819 | return ret; | ||
4820 | } | ||
4821 | |||
4799 | /* | 4822 | /* |
4800 | * Mark part or all of the extent record at split_index in the leaf | 4823 | * Mark part or all of the extent record at split_index in the leaf |
4801 | * pointed to by path as written. This removes the unwritten | 4824 | * pointed to by path as written. This removes the unwritten |
@@ -4885,7 +4908,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4885 | 4908 | ||
4886 | if (ctxt.c_contig_type == CONTIG_NONE) { | 4909 | if (ctxt.c_contig_type == CONTIG_NONE) { |
4887 | if (ctxt.c_split_covers_rec) | 4910 | if (ctxt.c_split_covers_rec) |
4888 | el->l_recs[split_index] = *split_rec; | 4911 | ret = ocfs2_replace_extent_rec(inode, handle, |
4912 | path, el, | ||
4913 | split_index, split_rec); | ||
4889 | else | 4914 | else |
4890 | ret = ocfs2_split_and_insert(inode, handle, path, et, | 4915 | ret = ocfs2_split_and_insert(inode, handle, path, et, |
4891 | &last_eb_bh, split_index, | 4916 | &last_eb_bh, split_index, |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 54e182a27caf..0a2813947853 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -1849,12 +1849,12 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, | |||
1849 | if (!mle) { | 1849 | if (!mle) { |
1850 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN && | 1850 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN && |
1851 | res->owner != assert->node_idx) { | 1851 | res->owner != assert->node_idx) { |
1852 | mlog(ML_ERROR, "assert_master from " | 1852 | mlog(ML_ERROR, "DIE! Mastery assert from %u, " |
1853 | "%u, but current owner is " | 1853 | "but current owner is %u! (%.*s)\n", |
1854 | "%u! (%.*s)\n", | 1854 | assert->node_idx, res->owner, namelen, |
1855 | assert->node_idx, res->owner, | 1855 | name); |
1856 | namelen, name); | 1856 | __dlm_print_one_lock_resource(res); |
1857 | goto kill; | 1857 | BUG(); |
1858 | } | 1858 | } |
1859 | } else if (mle->type != DLM_MLE_MIGRATION) { | 1859 | } else if (mle->type != DLM_MLE_MIGRATION) { |
1860 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) { | 1860 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) { |
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index d1295203029f..4060bb328bc8 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
@@ -181,8 +181,7 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, | |||
181 | 181 | ||
182 | spin_lock(&res->spinlock); | 182 | spin_lock(&res->spinlock); |
183 | /* This ensures that clear refmap is sent after the set */ | 183 | /* This ensures that clear refmap is sent after the set */ |
184 | __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_SETREF_INPROG | | 184 | __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); |
185 | DLM_LOCK_RES_MIGRATING)); | ||
186 | spin_unlock(&res->spinlock); | 185 | spin_unlock(&res->spinlock); |
187 | 186 | ||
188 | /* clear our bit from the master's refmap, ignore errors */ | 187 | /* clear our bit from the master's refmap, ignore errors */ |
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c index 86ca085ef324..fcf879ed6930 100644 --- a/fs/ocfs2/dlm/dlmunlock.c +++ b/fs/ocfs2/dlm/dlmunlock.c | |||
@@ -117,11 +117,11 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, | |||
117 | else | 117 | else |
118 | BUG_ON(res->owner == dlm->node_num); | 118 | BUG_ON(res->owner == dlm->node_num); |
119 | 119 | ||
120 | spin_lock(&dlm->spinlock); | 120 | spin_lock(&dlm->ast_lock); |
121 | /* We want to be sure that we're not freeing a lock | 121 | /* We want to be sure that we're not freeing a lock |
122 | * that still has AST's pending... */ | 122 | * that still has AST's pending... */ |
123 | in_use = !list_empty(&lock->ast_list); | 123 | in_use = !list_empty(&lock->ast_list); |
124 | spin_unlock(&dlm->spinlock); | 124 | spin_unlock(&dlm->ast_lock); |
125 | if (in_use) { | 125 | if (in_use) { |
126 | mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock " | 126 | mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock " |
127 | "while waiting for an ast!", res->lockname.len, | 127 | "while waiting for an ast!", res->lockname.len, |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 206a2370876a..7219a86d34cc 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -320,9 +320,14 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, | |||
320 | struct ocfs2_lock_res *lockres); | 320 | struct ocfs2_lock_res *lockres); |
321 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, | 321 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, |
322 | int convert); | 322 | int convert); |
323 | #define ocfs2_log_dlm_error(_func, _err, _lockres) do { \ | 323 | #define ocfs2_log_dlm_error(_func, _err, _lockres) do { \ |
324 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \ | 324 | if ((_lockres)->l_type != OCFS2_LOCK_TYPE_DENTRY) \ |
325 | _err, _func, _lockres->l_name); \ | 325 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \ |
326 | _err, _func, _lockres->l_name); \ | ||
327 | else \ | ||
328 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %.*s%08x\n", \ | ||
329 | _err, _func, OCFS2_DENTRY_LOCK_INO_START - 1, (_lockres)->l_name, \ | ||
330 | (unsigned int)ocfs2_get_dentry_lock_ino(_lockres)); \ | ||
326 | } while (0) | 331 | } while (0) |
327 | static int ocfs2_downconvert_thread(void *arg); | 332 | static int ocfs2_downconvert_thread(void *arg); |
328 | static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, | 333 | static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 077384135f4e..946d3c34b90b 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -341,6 +341,9 @@ struct ocfs2_super | |||
341 | struct ocfs2_node_map osb_recovering_orphan_dirs; | 341 | struct ocfs2_node_map osb_recovering_orphan_dirs; |
342 | unsigned int *osb_orphan_wipes; | 342 | unsigned int *osb_orphan_wipes; |
343 | wait_queue_head_t osb_wipe_event; | 343 | wait_queue_head_t osb_wipe_event; |
344 | |||
345 | /* used to protect metaecc calculation check of xattr. */ | ||
346 | spinlock_t osb_xattr_lock; | ||
344 | }; | 347 | }; |
345 | 348 | ||
346 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) | 349 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index b1cb38fbe807..7ac83a81ee55 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1537,6 +1537,13 @@ static int ocfs2_get_sector(struct super_block *sb, | |||
1537 | unlock_buffer(*bh); | 1537 | unlock_buffer(*bh); |
1538 | ll_rw_block(READ, 1, bh); | 1538 | ll_rw_block(READ, 1, bh); |
1539 | wait_on_buffer(*bh); | 1539 | wait_on_buffer(*bh); |
1540 | if (!buffer_uptodate(*bh)) { | ||
1541 | mlog_errno(-EIO); | ||
1542 | brelse(*bh); | ||
1543 | *bh = NULL; | ||
1544 | return -EIO; | ||
1545 | } | ||
1546 | |||
1540 | return 0; | 1547 | return 0; |
1541 | } | 1548 | } |
1542 | 1549 | ||
@@ -1747,6 +1754,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1747 | INIT_LIST_HEAD(&osb->blocked_lock_list); | 1754 | INIT_LIST_HEAD(&osb->blocked_lock_list); |
1748 | osb->blocked_lock_count = 0; | 1755 | osb->blocked_lock_count = 0; |
1749 | spin_lock_init(&osb->osb_lock); | 1756 | spin_lock_init(&osb->osb_lock); |
1757 | spin_lock_init(&osb->osb_xattr_lock); | ||
1750 | ocfs2_init_inode_steal_slot(osb); | 1758 | ocfs2_init_inode_steal_slot(osb); |
1751 | 1759 | ||
1752 | atomic_set(&osb->alloc_stats.moves, 0); | 1760 | atomic_set(&osb->alloc_stats.moves, 0); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 915039fffe6e..4ddd788add67 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -82,13 +82,14 @@ struct ocfs2_xattr_set_ctxt { | |||
82 | 82 | ||
83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) | 83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) |
84 | #define OCFS2_XATTR_INLINE_SIZE 80 | 84 | #define OCFS2_XATTR_INLINE_SIZE 80 |
85 | #define OCFS2_XATTR_HEADER_GAP 4 | ||
85 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ | 86 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ |
86 | - sizeof(struct ocfs2_xattr_header) \ | 87 | - sizeof(struct ocfs2_xattr_header) \ |
87 | - sizeof(__u32)) | 88 | - OCFS2_XATTR_HEADER_GAP) |
88 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ | 89 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ |
89 | - sizeof(struct ocfs2_xattr_block) \ | 90 | - sizeof(struct ocfs2_xattr_block) \ |
90 | - sizeof(struct ocfs2_xattr_header) \ | 91 | - sizeof(struct ocfs2_xattr_header) \ |
91 | - sizeof(__u32)) | 92 | - OCFS2_XATTR_HEADER_GAP) |
92 | 93 | ||
93 | static struct ocfs2_xattr_def_value_root def_xv = { | 94 | static struct ocfs2_xattr_def_value_root def_xv = { |
94 | .xv.xr_list.l_count = cpu_to_le16(1), | 95 | .xv.xr_list.l_count = cpu_to_le16(1), |
@@ -274,10 +275,12 @@ static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket, | |||
274 | bucket->bu_blocks, bucket->bu_bhs, 0, | 275 | bucket->bu_blocks, bucket->bu_bhs, 0, |
275 | NULL); | 276 | NULL); |
276 | if (!rc) { | 277 | if (!rc) { |
278 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
277 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, | 279 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, |
278 | bucket->bu_bhs, | 280 | bucket->bu_bhs, |
279 | bucket->bu_blocks, | 281 | bucket->bu_blocks, |
280 | &bucket_xh(bucket)->xh_check); | 282 | &bucket_xh(bucket)->xh_check); |
283 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
281 | if (rc) | 284 | if (rc) |
282 | mlog_errno(rc); | 285 | mlog_errno(rc); |
283 | } | 286 | } |
@@ -310,9 +313,11 @@ static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle, | |||
310 | { | 313 | { |
311 | int i; | 314 | int i; |
312 | 315 | ||
316 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
313 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, | 317 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, |
314 | bucket->bu_bhs, bucket->bu_blocks, | 318 | bucket->bu_bhs, bucket->bu_blocks, |
315 | &bucket_xh(bucket)->xh_check); | 319 | &bucket_xh(bucket)->xh_check); |
320 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
316 | 321 | ||
317 | for (i = 0; i < bucket->bu_blocks; i++) | 322 | for (i = 0; i < bucket->bu_blocks; i++) |
318 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); | 323 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); |
@@ -1507,7 +1512,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1507 | last += 1; | 1512 | last += 1; |
1508 | } | 1513 | } |
1509 | 1514 | ||
1510 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 1515 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
1511 | if (free < 0) | 1516 | if (free < 0) |
1512 | return -EIO; | 1517 | return -EIO; |
1513 | 1518 | ||
@@ -2190,7 +2195,7 @@ static int ocfs2_xattr_can_be_in_inode(struct inode *inode, | |||
2190 | last += 1; | 2195 | last += 1; |
2191 | } | 2196 | } |
2192 | 2197 | ||
2193 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 2198 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
2194 | if (free < 0) | 2199 | if (free < 0) |
2195 | return 0; | 2200 | return 0; |
2196 | 2201 | ||
@@ -2592,8 +2597,9 @@ static int __ocfs2_xattr_set_handle(struct inode *inode, | |||
2592 | 2597 | ||
2593 | if (!ret) { | 2598 | if (!ret) { |
2594 | /* Update inode ctime. */ | 2599 | /* Update inode ctime. */ |
2595 | ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh, | 2600 | ret = ocfs2_journal_access_di(ctxt->handle, inode, |
2596 | OCFS2_JOURNAL_ACCESS_WRITE); | 2601 | xis->inode_bh, |
2602 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2597 | if (ret) { | 2603 | if (ret) { |
2598 | mlog_errno(ret); | 2604 | mlog_errno(ret); |
2599 | goto out; | 2605 | goto out; |
@@ -5060,8 +5066,8 @@ try_again: | |||
5060 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5066 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5061 | header_size = sizeof(struct ocfs2_xattr_header) + | 5067 | header_size = sizeof(struct ocfs2_xattr_header) + |
5062 | count * sizeof(struct ocfs2_xattr_entry); | 5068 | count * sizeof(struct ocfs2_xattr_entry); |
5063 | max_free = OCFS2_XATTR_BUCKET_SIZE - | 5069 | max_free = OCFS2_XATTR_BUCKET_SIZE - header_size - |
5064 | le16_to_cpu(xh->xh_name_value_len) - header_size; | 5070 | le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP; |
5065 | 5071 | ||
5066 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " | 5072 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " |
5067 | "of %u which exceed block size\n", | 5073 | "of %u which exceed block size\n", |
@@ -5094,7 +5100,7 @@ try_again: | |||
5094 | need = 0; | 5100 | need = 0; |
5095 | } | 5101 | } |
5096 | 5102 | ||
5097 | free = xh_free_start - header_size; | 5103 | free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP; |
5098 | /* | 5104 | /* |
5099 | * We need to make sure the new name/value pair | 5105 | * We need to make sure the new name/value pair |
5100 | * can exist in the same block. | 5106 | * can exist in the same block. |
@@ -5127,7 +5133,8 @@ try_again: | |||
5127 | } | 5133 | } |
5128 | 5134 | ||
5129 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5135 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5130 | free = xh_free_start - header_size; | 5136 | free = xh_free_start - header_size |
5137 | - OCFS2_XATTR_HEADER_GAP; | ||
5131 | if (xh_free_start % blocksize < need) | 5138 | if (xh_free_start % blocksize < need) |
5132 | free -= xh_free_start % blocksize; | 5139 | free -= xh_free_start % blocksize; |
5133 | 5140 | ||
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 3e76bb9b3ad6..d8bb5c671f42 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -485,8 +485,10 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
485 | } | 485 | } |
486 | } | 486 | } |
487 | unlock_new_inode(inode); | 487 | unlock_new_inode(inode); |
488 | } else | 488 | } else { |
489 | module_put(de->owner); | 489 | module_put(de->owner); |
490 | de_put(de); | ||
491 | } | ||
490 | return inode; | 492 | return inode; |
491 | 493 | ||
492 | out_ino: | 494 | out_ino: |
diff --git a/fs/proc/page.c b/fs/proc/page.c index 767d95a6d1b1..2d1345112a42 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c | |||
@@ -107,7 +107,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, | |||
107 | else | 107 | else |
108 | kflags = ppage->flags; | 108 | kflags = ppage->flags; |
109 | 109 | ||
110 | uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) | | 110 | uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) | |
111 | kpf_copy_bit(kflags, KPF_ERROR, PG_error) | | 111 | kpf_copy_bit(kflags, KPF_ERROR, PG_error) | |
112 | kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) | | 112 | kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) | |
113 | kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) | | 113 | kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) | |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 5267098532bf..a1a4cfe19210 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -48,8 +48,16 @@ int seq_open(struct file *file, const struct seq_operations *op) | |||
48 | */ | 48 | */ |
49 | file->f_version = 0; | 49 | file->f_version = 0; |
50 | 50 | ||
51 | /* SEQ files support lseek, but not pread/pwrite */ | 51 | /* |
52 | file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); | 52 | * seq_files support lseek() and pread(). They do not implement |
53 | * write() at all, but we clear FMODE_PWRITE here for historical | ||
54 | * reasons. | ||
55 | * | ||
56 | * If a client of seq_files a) implements file.write() and b) wishes to | ||
57 | * support pwrite() then that client will need to implement its own | ||
58 | * file.open() which calls seq_open() and then sets FMODE_PWRITE. | ||
59 | */ | ||
60 | file->f_mode &= ~FMODE_PWRITE; | ||
53 | return 0; | 61 | return 0; |
54 | } | 62 | } |
55 | EXPORT_SYMBOL(seq_open); | 63 | EXPORT_SYMBOL(seq_open); |
@@ -131,6 +139,22 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) | |||
131 | int err = 0; | 139 | int err = 0; |
132 | 140 | ||
133 | mutex_lock(&m->lock); | 141 | mutex_lock(&m->lock); |
142 | |||
143 | /* Don't assume *ppos is where we left it */ | ||
144 | if (unlikely(*ppos != m->read_pos)) { | ||
145 | m->read_pos = *ppos; | ||
146 | while ((err = traverse(m, *ppos)) == -EAGAIN) | ||
147 | ; | ||
148 | if (err) { | ||
149 | /* With prejudice... */ | ||
150 | m->read_pos = 0; | ||
151 | m->version = 0; | ||
152 | m->index = 0; | ||
153 | m->count = 0; | ||
154 | goto Done; | ||
155 | } | ||
156 | } | ||
157 | |||
134 | /* | 158 | /* |
135 | * seq_file->op->..m_start/m_stop/m_next may do special actions | 159 | * seq_file->op->..m_start/m_stop/m_next may do special actions |
136 | * or optimisations based on the file->f_version, so we want to | 160 | * or optimisations based on the file->f_version, so we want to |
@@ -230,8 +254,10 @@ Fill: | |||
230 | Done: | 254 | Done: |
231 | if (!copied) | 255 | if (!copied) |
232 | copied = err; | 256 | copied = err; |
233 | else | 257 | else { |
234 | *ppos += copied; | 258 | *ppos += copied; |
259 | m->read_pos += copied; | ||
260 | } | ||
235 | file->f_version = m->version; | 261 | file->f_version = m->version; |
236 | mutex_unlock(&m->lock); | 262 | mutex_unlock(&m->lock); |
237 | return copied; | 263 | return copied; |
@@ -266,16 +292,18 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) | |||
266 | if (offset < 0) | 292 | if (offset < 0) |
267 | break; | 293 | break; |
268 | retval = offset; | 294 | retval = offset; |
269 | if (offset != file->f_pos) { | 295 | if (offset != m->read_pos) { |
270 | while ((retval=traverse(m, offset)) == -EAGAIN) | 296 | while ((retval=traverse(m, offset)) == -EAGAIN) |
271 | ; | 297 | ; |
272 | if (retval) { | 298 | if (retval) { |
273 | /* with extreme prejudice... */ | 299 | /* with extreme prejudice... */ |
274 | file->f_pos = 0; | 300 | file->f_pos = 0; |
301 | m->read_pos = 0; | ||
275 | m->version = 0; | 302 | m->version = 0; |
276 | m->index = 0; | 303 | m->index = 0; |
277 | m->count = 0; | 304 | m->count = 0; |
278 | } else { | 305 | } else { |
306 | m->read_pos = offset; | ||
279 | retval = file->f_pos = offset; | 307 | retval = file->f_pos = offset; |
280 | } | 308 | } |
281 | } | 309 | } |
diff --git a/fs/super.c b/fs/super.c index 61dce001dd57..8349ed6b1412 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -82,7 +82,22 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
82 | * lock ordering than usbfs: | 82 | * lock ordering than usbfs: |
83 | */ | 83 | */ |
84 | lockdep_set_class(&s->s_lock, &type->s_lock_key); | 84 | lockdep_set_class(&s->s_lock, &type->s_lock_key); |
85 | down_write(&s->s_umount); | 85 | /* |
86 | * sget() can have s_umount recursion. | ||
87 | * | ||
88 | * When it cannot find a suitable sb, it allocates a new | ||
89 | * one (this one), and tries again to find a suitable old | ||
90 | * one. | ||
91 | * | ||
92 | * In case that succeeds, it will acquire the s_umount | ||
93 | * lock of the old one. Since these are clearly distrinct | ||
94 | * locks, and this object isn't exposed yet, there's no | ||
95 | * risk of deadlocks. | ||
96 | * | ||
97 | * Annotate this by putting this lock in a different | ||
98 | * subclass. | ||
99 | */ | ||
100 | down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING); | ||
86 | s->s_count = S_BIAS; | 101 | s->s_count = S_BIAS; |
87 | atomic_set(&s->s_active, 1); | 102 | atomic_set(&s->s_active, 1); |
88 | mutex_init(&s->s_vfs_rename_mutex); | 103 | mutex_init(&s->s_vfs_rename_mutex); |
diff --git a/fs/timerfd.c b/fs/timerfd.c index 6a123b8ff3f5..b042bd7034b1 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -186,10 +186,9 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
186 | BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC); | 186 | BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC); |
187 | BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK); | 187 | BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK); |
188 | 188 | ||
189 | if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK)) | 189 | if ((flags & ~TFD_CREATE_FLAGS) || |
190 | return -EINVAL; | 190 | (clockid != CLOCK_MONOTONIC && |
191 | if (clockid != CLOCK_MONOTONIC && | 191 | clockid != CLOCK_REALTIME)) |
192 | clockid != CLOCK_REALTIME) | ||
193 | return -EINVAL; | 192 | return -EINVAL; |
194 | 193 | ||
195 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 194 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
@@ -201,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
201 | hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); | 200 | hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); |
202 | 201 | ||
203 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, | 202 | ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, |
204 | flags & (O_CLOEXEC | O_NONBLOCK)); | 203 | flags & TFD_SHARED_FCNTL_FLAGS); |
205 | if (ufd < 0) | 204 | if (ufd < 0) |
206 | kfree(ctx); | 205 | kfree(ctx); |
207 | 206 | ||
@@ -219,7 +218,8 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
219 | if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) | 218 | if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) |
220 | return -EFAULT; | 219 | return -EFAULT; |
221 | 220 | ||
222 | if (!timespec_valid(&ktmr.it_value) || | 221 | if ((flags & ~TFD_SETTIME_FLAGS) || |
222 | !timespec_valid(&ktmr.it_value) || | ||
223 | !timespec_valid(&ktmr.it_interval)) | 223 | !timespec_valid(&ktmr.it_interval)) |
224 | return -EINVAL; | 224 | return -EINVAL; |
225 | 225 | ||