diff options
Diffstat (limited to 'fs')
92 files changed, 1660 insertions, 1383 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 5d505aaa72fb..44ea5b92e1ba 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -178,12 +178,13 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, | |||
178 | 178 | ||
179 | if (value) { | 179 | if (value) { |
180 | acl = posix_acl_from_xattr(value, size); | 180 | acl = posix_acl_from_xattr(value, size); |
181 | if (IS_ERR(acl)) | ||
182 | return PTR_ERR(acl); | ||
183 | |||
181 | if (acl) { | 184 | if (acl) { |
182 | ret = posix_acl_valid(acl); | 185 | ret = posix_acl_valid(acl); |
183 | if (ret) | 186 | if (ret) |
184 | goto out; | 187 | goto out; |
185 | } else if (IS_ERR(acl)) { | ||
186 | return PTR_ERR(acl); | ||
187 | } | 188 | } |
188 | } | 189 | } |
189 | 190 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2e61fe1b6b8c..8f4b81de3ae2 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -718,7 +718,7 @@ struct btrfs_space_info { | |||
718 | u64 total_bytes; /* total bytes in the space, | 718 | u64 total_bytes; /* total bytes in the space, |
719 | this doesn't take mirrors into account */ | 719 | this doesn't take mirrors into account */ |
720 | u64 bytes_used; /* total bytes used, | 720 | u64 bytes_used; /* total bytes used, |
721 | this does't take mirrors into account */ | 721 | this doesn't take mirrors into account */ |
722 | u64 bytes_pinned; /* total bytes pinned, will be freed when the | 722 | u64 bytes_pinned; /* total bytes pinned, will be freed when the |
723 | transaction finishes */ | 723 | transaction finishes */ |
724 | u64 bytes_reserved; /* total bytes the allocator has reserved for | 724 | u64 bytes_reserved; /* total bytes the allocator has reserved for |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 68c84c8c24bd..228cf36ece83 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -2824,6 +2824,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
2824 | 2824 | ||
2825 | spin_lock(&delayed_refs->lock); | 2825 | spin_lock(&delayed_refs->lock); |
2826 | if (delayed_refs->num_entries == 0) { | 2826 | if (delayed_refs->num_entries == 0) { |
2827 | spin_unlock(&delayed_refs->lock); | ||
2827 | printk(KERN_INFO "delayed_refs has NO entry\n"); | 2828 | printk(KERN_INFO "delayed_refs has NO entry\n"); |
2828 | return ret; | 2829 | return ret; |
2829 | } | 2830 | } |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 31f33ba56fe8..9ee6bd55e16c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -8059,6 +8059,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, | |||
8059 | u64 group_start = group->key.objectid; | 8059 | u64 group_start = group->key.objectid; |
8060 | new_extents = kmalloc(sizeof(*new_extents), | 8060 | new_extents = kmalloc(sizeof(*new_extents), |
8061 | GFP_NOFS); | 8061 | GFP_NOFS); |
8062 | if (!new_extents) { | ||
8063 | ret = -ENOMEM; | ||
8064 | goto out; | ||
8065 | } | ||
8062 | nr_extents = 1; | 8066 | nr_extents = 1; |
8063 | ret = get_new_locations(reloc_inode, | 8067 | ret = get_new_locations(reloc_inode, |
8064 | extent_key, | 8068 | extent_key, |
@@ -8852,23 +8856,38 @@ out: | |||
8852 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info) | 8856 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info) |
8853 | { | 8857 | { |
8854 | struct btrfs_space_info *space_info; | 8858 | struct btrfs_space_info *space_info; |
8859 | struct btrfs_super_block *disk_super; | ||
8860 | u64 features; | ||
8861 | u64 flags; | ||
8862 | int mixed = 0; | ||
8855 | int ret; | 8863 | int ret; |
8856 | 8864 | ||
8857 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0, | 8865 | disk_super = &fs_info->super_copy; |
8858 | &space_info); | 8866 | if (!btrfs_super_root(disk_super)) |
8859 | if (ret) | 8867 | return 1; |
8860 | return ret; | ||
8861 | 8868 | ||
8862 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0, | 8869 | features = btrfs_super_incompat_flags(disk_super); |
8863 | &space_info); | 8870 | if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) |
8864 | if (ret) | 8871 | mixed = 1; |
8865 | return ret; | ||
8866 | 8872 | ||
8867 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0, | 8873 | flags = BTRFS_BLOCK_GROUP_SYSTEM; |
8868 | &space_info); | 8874 | ret = update_space_info(fs_info, flags, 0, 0, &space_info); |
8869 | if (ret) | 8875 | if (ret) |
8870 | return ret; | 8876 | goto out; |
8871 | 8877 | ||
8878 | if (mixed) { | ||
8879 | flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; | ||
8880 | ret = update_space_info(fs_info, flags, 0, 0, &space_info); | ||
8881 | } else { | ||
8882 | flags = BTRFS_BLOCK_GROUP_METADATA; | ||
8883 | ret = update_space_info(fs_info, flags, 0, 0, &space_info); | ||
8884 | if (ret) | ||
8885 | goto out; | ||
8886 | |||
8887 | flags = BTRFS_BLOCK_GROUP_DATA; | ||
8888 | ret = update_space_info(fs_info, flags, 0, 0, &space_info); | ||
8889 | } | ||
8890 | out: | ||
8872 | return ret; | 8891 | return ret; |
8873 | } | 8892 | } |
8874 | 8893 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 315138605088..ba41da59e31b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2681,7 +2681,7 @@ int extent_readpages(struct extent_io_tree *tree, | |||
2681 | prefetchw(&page->flags); | 2681 | prefetchw(&page->flags); |
2682 | list_del(&page->lru); | 2682 | list_del(&page->lru); |
2683 | if (!add_to_page_cache_lru(page, mapping, | 2683 | if (!add_to_page_cache_lru(page, mapping, |
2684 | page->index, GFP_KERNEL)) { | 2684 | page->index, GFP_NOFS)) { |
2685 | __extent_read_full_page(tree, page, get_extent, | 2685 | __extent_read_full_page(tree, page, get_extent, |
2686 | &bio, 0, &bio_flags); | 2686 | &bio, 0, &bio_flags); |
2687 | } | 2687 | } |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 11d2e9cea09e..63731a1fb0a1 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -1768,10 +1768,13 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) | |||
1768 | 1768 | ||
1769 | while ((node = rb_last(&block_group->free_space_offset)) != NULL) { | 1769 | while ((node = rb_last(&block_group->free_space_offset)) != NULL) { |
1770 | info = rb_entry(node, struct btrfs_free_space, offset_index); | 1770 | info = rb_entry(node, struct btrfs_free_space, offset_index); |
1771 | unlink_free_space(block_group, info); | 1771 | if (!info->bitmap) { |
1772 | if (info->bitmap) | 1772 | unlink_free_space(block_group, info); |
1773 | kfree(info->bitmap); | 1773 | kmem_cache_free(btrfs_free_space_cachep, info); |
1774 | kmem_cache_free(btrfs_free_space_cachep, info); | 1774 | } else { |
1775 | free_bitmap(block_group, info); | ||
1776 | } | ||
1777 | |||
1775 | if (need_resched()) { | 1778 | if (need_resched()) { |
1776 | spin_unlock(&block_group->tree_lock); | 1779 | spin_unlock(&block_group->tree_lock); |
1777 | cond_resched(); | 1780 | cond_resched(); |
@@ -2301,7 +2304,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, | |||
2301 | start = entry->offset; | 2304 | start = entry->offset; |
2302 | bytes = min(entry->bytes, end - start); | 2305 | bytes = min(entry->bytes, end - start); |
2303 | unlink_free_space(block_group, entry); | 2306 | unlink_free_space(block_group, entry); |
2304 | kfree(entry); | 2307 | kmem_cache_free(btrfs_free_space_cachep, entry); |
2305 | } | 2308 | } |
2306 | 2309 | ||
2307 | spin_unlock(&block_group->tree_lock); | 2310 | spin_unlock(&block_group->tree_lock); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fcd66b6a8086..7cd8ab0ef04d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -954,6 +954,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, | |||
954 | 1, 0, NULL, GFP_NOFS); | 954 | 1, 0, NULL, GFP_NOFS); |
955 | while (start < end) { | 955 | while (start < end) { |
956 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); | 956 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); |
957 | BUG_ON(!async_cow); | ||
957 | async_cow->inode = inode; | 958 | async_cow->inode = inode; |
958 | async_cow->root = root; | 959 | async_cow->root = root; |
959 | async_cow->locked_page = locked_page; | 960 | async_cow->locked_page = locked_page; |
@@ -4731,9 +4732,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
4731 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4732 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
4732 | dentry->d_name.len, dir->i_ino, objectid, | 4733 | dentry->d_name.len, dir->i_ino, objectid, |
4733 | BTRFS_I(dir)->block_group, mode, &index); | 4734 | BTRFS_I(dir)->block_group, mode, &index); |
4734 | err = PTR_ERR(inode); | 4735 | if (IS_ERR(inode)) { |
4735 | if (IS_ERR(inode)) | 4736 | err = PTR_ERR(inode); |
4736 | goto out_unlock; | 4737 | goto out_unlock; |
4738 | } | ||
4737 | 4739 | ||
4738 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 4740 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4739 | if (err) { | 4741 | if (err) { |
@@ -4792,9 +4794,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
4792 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4794 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
4793 | dentry->d_name.len, dir->i_ino, objectid, | 4795 | dentry->d_name.len, dir->i_ino, objectid, |
4794 | BTRFS_I(dir)->block_group, mode, &index); | 4796 | BTRFS_I(dir)->block_group, mode, &index); |
4795 | err = PTR_ERR(inode); | 4797 | if (IS_ERR(inode)) { |
4796 | if (IS_ERR(inode)) | 4798 | err = PTR_ERR(inode); |
4797 | goto out_unlock; | 4799 | goto out_unlock; |
4800 | } | ||
4798 | 4801 | ||
4799 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 4802 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4800 | if (err) { | 4803 | if (err) { |
@@ -4999,6 +5002,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, | |||
4999 | inline_size = btrfs_file_extent_inline_item_len(leaf, | 5002 | inline_size = btrfs_file_extent_inline_item_len(leaf, |
5000 | btrfs_item_nr(leaf, path->slots[0])); | 5003 | btrfs_item_nr(leaf, path->slots[0])); |
5001 | tmp = kmalloc(inline_size, GFP_NOFS); | 5004 | tmp = kmalloc(inline_size, GFP_NOFS); |
5005 | if (!tmp) | ||
5006 | return -ENOMEM; | ||
5002 | ptr = btrfs_file_extent_inline_start(item); | 5007 | ptr = btrfs_file_extent_inline_start(item); |
5003 | 5008 | ||
5004 | read_extent_buffer(leaf, tmp, ptr, inline_size); | 5009 | read_extent_buffer(leaf, tmp, ptr, inline_size); |
@@ -6036,7 +6041,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6036 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, | 6041 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, |
6037 | &map_length, NULL, 0); | 6042 | &map_length, NULL, 0); |
6038 | if (ret) { | 6043 | if (ret) { |
6039 | bio_put(bio); | 6044 | bio_put(orig_bio); |
6040 | return -EIO; | 6045 | return -EIO; |
6041 | } | 6046 | } |
6042 | 6047 | ||
@@ -7273,9 +7278,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
7273 | dentry->d_name.len, dir->i_ino, objectid, | 7278 | dentry->d_name.len, dir->i_ino, objectid, |
7274 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, | 7279 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, |
7275 | &index); | 7280 | &index); |
7276 | err = PTR_ERR(inode); | 7281 | if (IS_ERR(inode)) { |
7277 | if (IS_ERR(inode)) | 7282 | err = PTR_ERR(inode); |
7278 | goto out_unlock; | 7283 | goto out_unlock; |
7284 | } | ||
7279 | 7285 | ||
7280 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 7286 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
7281 | if (err) { | 7287 | if (err) { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ffb48d6c5433..2616f7ed4799 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -81,6 +81,13 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags) | |||
81 | iflags |= FS_NOATIME_FL; | 81 | iflags |= FS_NOATIME_FL; |
82 | if (flags & BTRFS_INODE_DIRSYNC) | 82 | if (flags & BTRFS_INODE_DIRSYNC) |
83 | iflags |= FS_DIRSYNC_FL; | 83 | iflags |= FS_DIRSYNC_FL; |
84 | if (flags & BTRFS_INODE_NODATACOW) | ||
85 | iflags |= FS_NOCOW_FL; | ||
86 | |||
87 | if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS)) | ||
88 | iflags |= FS_COMPR_FL; | ||
89 | else if (flags & BTRFS_INODE_NOCOMPRESS) | ||
90 | iflags |= FS_NOCOMP_FL; | ||
84 | 91 | ||
85 | return iflags; | 92 | return iflags; |
86 | } | 93 | } |
@@ -144,16 +151,13 @@ static int check_flags(unsigned int flags) | |||
144 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | 151 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ |
145 | FS_NOATIME_FL | FS_NODUMP_FL | \ | 152 | FS_NOATIME_FL | FS_NODUMP_FL | \ |
146 | FS_SYNC_FL | FS_DIRSYNC_FL | \ | 153 | FS_SYNC_FL | FS_DIRSYNC_FL | \ |
147 | FS_NOCOMP_FL | FS_COMPR_FL | \ | 154 | FS_NOCOMP_FL | FS_COMPR_FL | |
148 | FS_NOCOW_FL | FS_COW_FL)) | 155 | FS_NOCOW_FL)) |
149 | return -EOPNOTSUPP; | 156 | return -EOPNOTSUPP; |
150 | 157 | ||
151 | if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL)) | 158 | if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL)) |
152 | return -EINVAL; | 159 | return -EINVAL; |
153 | 160 | ||
154 | if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | return 0; | 161 | return 0; |
158 | } | 162 | } |
159 | 163 | ||
@@ -218,6 +222,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
218 | ip->flags |= BTRFS_INODE_DIRSYNC; | 222 | ip->flags |= BTRFS_INODE_DIRSYNC; |
219 | else | 223 | else |
220 | ip->flags &= ~BTRFS_INODE_DIRSYNC; | 224 | ip->flags &= ~BTRFS_INODE_DIRSYNC; |
225 | if (flags & FS_NOCOW_FL) | ||
226 | ip->flags |= BTRFS_INODE_NODATACOW; | ||
227 | else | ||
228 | ip->flags &= ~BTRFS_INODE_NODATACOW; | ||
221 | 229 | ||
222 | /* | 230 | /* |
223 | * The COMPRESS flag can only be changed by users, while the NOCOMPRESS | 231 | * The COMPRESS flag can only be changed by users, while the NOCOMPRESS |
@@ -230,11 +238,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
230 | } else if (flags & FS_COMPR_FL) { | 238 | } else if (flags & FS_COMPR_FL) { |
231 | ip->flags |= BTRFS_INODE_COMPRESS; | 239 | ip->flags |= BTRFS_INODE_COMPRESS; |
232 | ip->flags &= ~BTRFS_INODE_NOCOMPRESS; | 240 | ip->flags &= ~BTRFS_INODE_NOCOMPRESS; |
241 | } else { | ||
242 | ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); | ||
233 | } | 243 | } |
234 | if (flags & FS_NOCOW_FL) | ||
235 | ip->flags |= BTRFS_INODE_NODATACOW; | ||
236 | else if (flags & FS_COW_FL) | ||
237 | ip->flags &= ~BTRFS_INODE_NODATACOW; | ||
238 | 244 | ||
239 | trans = btrfs_join_transaction(root, 1); | 245 | trans = btrfs_join_transaction(root, 1); |
240 | BUG_ON(IS_ERR(trans)); | 246 | BUG_ON(IS_ERR(trans)); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c50271ad3157..f997ec0c1ba4 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2209,8 +2209,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2209 | 2209 | ||
2210 | log = root->log_root; | 2210 | log = root->log_root; |
2211 | path = btrfs_alloc_path(); | 2211 | path = btrfs_alloc_path(); |
2212 | if (!path) | 2212 | if (!path) { |
2213 | return -ENOMEM; | 2213 | err = -ENOMEM; |
2214 | goto out_unlock; | ||
2215 | } | ||
2214 | 2216 | ||
2215 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, | 2217 | di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, |
2216 | name, name_len, -1); | 2218 | name, name_len, -1); |
@@ -2271,6 +2273,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, | |||
2271 | } | 2273 | } |
2272 | fail: | 2274 | fail: |
2273 | btrfs_free_path(path); | 2275 | btrfs_free_path(path); |
2276 | out_unlock: | ||
2274 | mutex_unlock(&BTRFS_I(dir)->log_mutex); | 2277 | mutex_unlock(&BTRFS_I(dir)->log_mutex); |
2275 | if (ret == -ENOSPC) { | 2278 | if (ret == -ENOSPC) { |
2276 | root->fs_info->last_trans_log_full_commit = trans->transid; | 2279 | root->fs_info->last_trans_log_full_commit = trans->transid; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 309a57b9fc85..c7367ae5a3e6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -155,6 +155,15 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
155 | unsigned long limit; | 155 | unsigned long limit; |
156 | unsigned long last_waited = 0; | 156 | unsigned long last_waited = 0; |
157 | int force_reg = 0; | 157 | int force_reg = 0; |
158 | struct blk_plug plug; | ||
159 | |||
160 | /* | ||
161 | * this function runs all the bios we've collected for | ||
162 | * a particular device. We don't want to wander off to | ||
163 | * another device without first sending all of these down. | ||
164 | * So, setup a plug here and finish it off before we return | ||
165 | */ | ||
166 | blk_start_plug(&plug); | ||
158 | 167 | ||
159 | bdi = blk_get_backing_dev_info(device->bdev); | 168 | bdi = blk_get_backing_dev_info(device->bdev); |
160 | fs_info = device->dev_root->fs_info; | 169 | fs_info = device->dev_root->fs_info; |
@@ -294,6 +303,7 @@ loop_lock: | |||
294 | spin_unlock(&device->io_lock); | 303 | spin_unlock(&device->io_lock); |
295 | 304 | ||
296 | done: | 305 | done: |
306 | blk_finish_plug(&plug); | ||
297 | return 0; | 307 | return 0; |
298 | } | 308 | } |
299 | 309 | ||
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e159c529fd2b..38b8ab554924 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -775,6 +775,13 @@ get_more_pages: | |||
775 | ci->i_truncate_seq, | 775 | ci->i_truncate_seq, |
776 | ci->i_truncate_size, | 776 | ci->i_truncate_size, |
777 | &inode->i_mtime, true, 1, 0); | 777 | &inode->i_mtime, true, 1, 0); |
778 | |||
779 | if (!req) { | ||
780 | rc = -ENOMEM; | ||
781 | unlock_page(page); | ||
782 | break; | ||
783 | } | ||
784 | |||
778 | max_pages = req->r_num_pages; | 785 | max_pages = req->r_num_pages; |
779 | 786 | ||
780 | alloc_page_vec(fsc, req); | 787 | alloc_page_vec(fsc, req); |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 5323c330bbf3..2a5404c1c42f 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -819,7 +819,7 @@ int __ceph_caps_used(struct ceph_inode_info *ci) | |||
819 | used |= CEPH_CAP_FILE_CACHE; | 819 | used |= CEPH_CAP_FILE_CACHE; |
820 | if (ci->i_wr_ref) | 820 | if (ci->i_wr_ref) |
821 | used |= CEPH_CAP_FILE_WR; | 821 | used |= CEPH_CAP_FILE_WR; |
822 | if (ci->i_wrbuffer_ref) | 822 | if (ci->i_wb_ref || ci->i_wrbuffer_ref) |
823 | used |= CEPH_CAP_FILE_BUFFER; | 823 | used |= CEPH_CAP_FILE_BUFFER; |
824 | return used; | 824 | return used; |
825 | } | 825 | } |
@@ -1331,10 +1331,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci) | |||
1331 | } | 1331 | } |
1332 | 1332 | ||
1333 | /* | 1333 | /* |
1334 | * Mark caps dirty. If inode is newly dirty, add to the global dirty | 1334 | * Mark caps dirty. If inode is newly dirty, return the dirty flags. |
1335 | * list. | 1335 | * Caller is then responsible for calling __mark_inode_dirty with the |
1336 | * returned flags value. | ||
1336 | */ | 1337 | */ |
1337 | void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | 1338 | int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) |
1338 | { | 1339 | { |
1339 | struct ceph_mds_client *mdsc = | 1340 | struct ceph_mds_client *mdsc = |
1340 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; | 1341 | ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; |
@@ -1357,7 +1358,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1357 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); | 1358 | list_add(&ci->i_dirty_item, &mdsc->cap_dirty); |
1358 | spin_unlock(&mdsc->cap_dirty_lock); | 1359 | spin_unlock(&mdsc->cap_dirty_lock); |
1359 | if (ci->i_flushing_caps == 0) { | 1360 | if (ci->i_flushing_caps == 0) { |
1360 | igrab(inode); | 1361 | ihold(inode); |
1361 | dirty |= I_DIRTY_SYNC; | 1362 | dirty |= I_DIRTY_SYNC; |
1362 | } | 1363 | } |
1363 | } | 1364 | } |
@@ -1365,9 +1366,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) | |||
1365 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && | 1366 | if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) && |
1366 | (mask & CEPH_CAP_FILE_BUFFER)) | 1367 | (mask & CEPH_CAP_FILE_BUFFER)) |
1367 | dirty |= I_DIRTY_DATASYNC; | 1368 | dirty |= I_DIRTY_DATASYNC; |
1368 | if (dirty) | ||
1369 | __mark_inode_dirty(inode, dirty); | ||
1370 | __cap_delay_requeue(mdsc, ci); | 1369 | __cap_delay_requeue(mdsc, ci); |
1370 | return dirty; | ||
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | /* | 1373 | /* |
@@ -1990,11 +1990,11 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got) | |||
1990 | if (got & CEPH_CAP_FILE_WR) | 1990 | if (got & CEPH_CAP_FILE_WR) |
1991 | ci->i_wr_ref++; | 1991 | ci->i_wr_ref++; |
1992 | if (got & CEPH_CAP_FILE_BUFFER) { | 1992 | if (got & CEPH_CAP_FILE_BUFFER) { |
1993 | if (ci->i_wrbuffer_ref == 0) | 1993 | if (ci->i_wb_ref == 0) |
1994 | igrab(&ci->vfs_inode); | 1994 | ihold(&ci->vfs_inode); |
1995 | ci->i_wrbuffer_ref++; | 1995 | ci->i_wb_ref++; |
1996 | dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n", | 1996 | dout("__take_cap_refs %p wb %d -> %d (?)\n", |
1997 | &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref); | 1997 | &ci->vfs_inode, ci->i_wb_ref-1, ci->i_wb_ref); |
1998 | } | 1998 | } |
1999 | } | 1999 | } |
2000 | 2000 | ||
@@ -2169,12 +2169,12 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2169 | if (--ci->i_rdcache_ref == 0) | 2169 | if (--ci->i_rdcache_ref == 0) |
2170 | last++; | 2170 | last++; |
2171 | if (had & CEPH_CAP_FILE_BUFFER) { | 2171 | if (had & CEPH_CAP_FILE_BUFFER) { |
2172 | if (--ci->i_wrbuffer_ref == 0) { | 2172 | if (--ci->i_wb_ref == 0) { |
2173 | last++; | 2173 | last++; |
2174 | put++; | 2174 | put++; |
2175 | } | 2175 | } |
2176 | dout("put_cap_refs %p wrbuffer %d -> %d (?)\n", | 2176 | dout("put_cap_refs %p wb %d -> %d (?)\n", |
2177 | inode, ci->i_wrbuffer_ref+1, ci->i_wrbuffer_ref); | 2177 | inode, ci->i_wb_ref+1, ci->i_wb_ref); |
2178 | } | 2178 | } |
2179 | if (had & CEPH_CAP_FILE_WR) | 2179 | if (had & CEPH_CAP_FILE_WR) |
2180 | if (--ci->i_wr_ref == 0) { | 2180 | if (--ci->i_wr_ref == 0) { |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 159b512d5a27..203252d88d9f 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -734,9 +734,12 @@ retry_snap: | |||
734 | } | 734 | } |
735 | } | 735 | } |
736 | if (ret >= 0) { | 736 | if (ret >= 0) { |
737 | int dirty; | ||
737 | spin_lock(&inode->i_lock); | 738 | spin_lock(&inode->i_lock); |
738 | __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); | 739 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); |
739 | spin_unlock(&inode->i_lock); | 740 | spin_unlock(&inode->i_lock); |
741 | if (dirty) | ||
742 | __mark_inode_dirty(inode, dirty); | ||
740 | } | 743 | } |
741 | 744 | ||
742 | out: | 745 | out: |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index b54c97da1c43..70b6a4839c38 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -355,6 +355,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) | |||
355 | ci->i_rd_ref = 0; | 355 | ci->i_rd_ref = 0; |
356 | ci->i_rdcache_ref = 0; | 356 | ci->i_rdcache_ref = 0; |
357 | ci->i_wr_ref = 0; | 357 | ci->i_wr_ref = 0; |
358 | ci->i_wb_ref = 0; | ||
358 | ci->i_wrbuffer_ref = 0; | 359 | ci->i_wrbuffer_ref = 0; |
359 | ci->i_wrbuffer_ref_head = 0; | 360 | ci->i_wrbuffer_ref_head = 0; |
360 | ci->i_shared_gen = 0; | 361 | ci->i_shared_gen = 0; |
@@ -1567,6 +1568,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1567 | int release = 0, dirtied = 0; | 1568 | int release = 0, dirtied = 0; |
1568 | int mask = 0; | 1569 | int mask = 0; |
1569 | int err = 0; | 1570 | int err = 0; |
1571 | int inode_dirty_flags = 0; | ||
1570 | 1572 | ||
1571 | if (ceph_snap(inode) != CEPH_NOSNAP) | 1573 | if (ceph_snap(inode) != CEPH_NOSNAP) |
1572 | return -EROFS; | 1574 | return -EROFS; |
@@ -1725,13 +1727,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
1725 | dout("setattr %p ATTR_FILE ... hrm!\n", inode); | 1727 | dout("setattr %p ATTR_FILE ... hrm!\n", inode); |
1726 | 1728 | ||
1727 | if (dirtied) { | 1729 | if (dirtied) { |
1728 | __ceph_mark_dirty_caps(ci, dirtied); | 1730 | inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied); |
1729 | inode->i_ctime = CURRENT_TIME; | 1731 | inode->i_ctime = CURRENT_TIME; |
1730 | } | 1732 | } |
1731 | 1733 | ||
1732 | release &= issued; | 1734 | release &= issued; |
1733 | spin_unlock(&inode->i_lock); | 1735 | spin_unlock(&inode->i_lock); |
1734 | 1736 | ||
1737 | if (inode_dirty_flags) | ||
1738 | __mark_inode_dirty(inode, inode_dirty_flags); | ||
1739 | |||
1735 | if (mask) { | 1740 | if (mask) { |
1736 | req->r_inode = igrab(inode); | 1741 | req->r_inode = igrab(inode); |
1737 | req->r_inode_drop = release; | 1742 | req->r_inode_drop = release; |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index f60b07b0feb0..d0fae4ce9ba5 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -3304,8 +3304,8 @@ static void con_put(struct ceph_connection *con) | |||
3304 | { | 3304 | { |
3305 | struct ceph_mds_session *s = con->private; | 3305 | struct ceph_mds_session *s = con->private; |
3306 | 3306 | ||
3307 | dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref) - 1); | ||
3307 | ceph_put_mds_session(s); | 3308 | ceph_put_mds_session(s); |
3308 | dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref)); | ||
3309 | } | 3309 | } |
3310 | 3310 | ||
3311 | /* | 3311 | /* |
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index e86ec1155f8f..24067d68a554 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c | |||
@@ -206,7 +206,7 @@ void ceph_put_snap_realm(struct ceph_mds_client *mdsc, | |||
206 | up_write(&mdsc->snap_rwsem); | 206 | up_write(&mdsc->snap_rwsem); |
207 | } else { | 207 | } else { |
208 | spin_lock(&mdsc->snap_empty_lock); | 208 | spin_lock(&mdsc->snap_empty_lock); |
209 | list_add(&mdsc->snap_empty, &realm->empty_item); | 209 | list_add(&realm->empty_item, &mdsc->snap_empty); |
210 | spin_unlock(&mdsc->snap_empty_lock); | 210 | spin_unlock(&mdsc->snap_empty_lock); |
211 | } | 211 | } |
212 | } | 212 | } |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 619fe719968f..f5cabefa98dc 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -293,7 +293,7 @@ struct ceph_inode_info { | |||
293 | 293 | ||
294 | /* held references to caps */ | 294 | /* held references to caps */ |
295 | int i_pin_ref; | 295 | int i_pin_ref; |
296 | int i_rd_ref, i_rdcache_ref, i_wr_ref; | 296 | int i_rd_ref, i_rdcache_ref, i_wr_ref, i_wb_ref; |
297 | int i_wrbuffer_ref, i_wrbuffer_ref_head; | 297 | int i_wrbuffer_ref, i_wrbuffer_ref_head; |
298 | u32 i_shared_gen; /* increment each time we get FILE_SHARED */ | 298 | u32 i_shared_gen; /* increment each time we get FILE_SHARED */ |
299 | u32 i_rdcache_gen; /* incremented each time we get FILE_CACHE. */ | 299 | u32 i_rdcache_gen; /* incremented each time we get FILE_CACHE. */ |
@@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci) | |||
506 | { | 506 | { |
507 | return ci->i_dirty_caps | ci->i_flushing_caps; | 507 | return ci->i_dirty_caps | ci->i_flushing_caps; |
508 | } | 508 | } |
509 | extern void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask); | 509 | extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask); |
510 | 510 | ||
511 | extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask); | 511 | extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask); |
512 | extern int __ceph_caps_used(struct ceph_inode_info *ci); | 512 | extern int __ceph_caps_used(struct ceph_inode_info *ci); |
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 8c9eba6ef9df..f2b628696180 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
@@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, | |||
703 | struct ceph_inode_xattr *xattr = NULL; | 703 | struct ceph_inode_xattr *xattr = NULL; |
704 | int issued; | 704 | int issued; |
705 | int required_blob_size; | 705 | int required_blob_size; |
706 | int dirty; | ||
706 | 707 | ||
707 | if (ceph_snap(inode) != CEPH_NOSNAP) | 708 | if (ceph_snap(inode) != CEPH_NOSNAP) |
708 | return -EROFS; | 709 | return -EROFS; |
@@ -763,11 +764,12 @@ retry: | |||
763 | dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); | 764 | dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued)); |
764 | err = __set_xattr(ci, newname, name_len, newval, | 765 | err = __set_xattr(ci, newname, name_len, newval, |
765 | val_len, 1, 1, 1, &xattr); | 766 | val_len, 1, 1, 1, &xattr); |
766 | __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 767 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
767 | ci->i_xattrs.dirty = true; | 768 | ci->i_xattrs.dirty = true; |
768 | inode->i_ctime = CURRENT_TIME; | 769 | inode->i_ctime = CURRENT_TIME; |
769 | spin_unlock(&inode->i_lock); | 770 | spin_unlock(&inode->i_lock); |
770 | 771 | if (dirty) | |
772 | __mark_inode_dirty(inode, dirty); | ||
771 | return err; | 773 | return err; |
772 | 774 | ||
773 | do_sync: | 775 | do_sync: |
@@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) | |||
810 | struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); | 812 | struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode); |
811 | int issued; | 813 | int issued; |
812 | int err; | 814 | int err; |
815 | int dirty; | ||
813 | 816 | ||
814 | if (ceph_snap(inode) != CEPH_NOSNAP) | 817 | if (ceph_snap(inode) != CEPH_NOSNAP) |
815 | return -EROFS; | 818 | return -EROFS; |
@@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name) | |||
833 | goto do_sync; | 836 | goto do_sync; |
834 | 837 | ||
835 | err = __remove_xattr_by_name(ceph_inode(inode), name); | 838 | err = __remove_xattr_by_name(ceph_inode(inode), name); |
836 | __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); | 839 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); |
837 | ci->i_xattrs.dirty = true; | 840 | ci->i_xattrs.dirty = true; |
838 | inode->i_ctime = CURRENT_TIME; | 841 | inode->i_ctime = CURRENT_TIME; |
839 | 842 | ||
840 | spin_unlock(&inode->i_lock); | 843 | spin_unlock(&inode->i_lock); |
841 | 844 | if (dirty) | |
845 | __mark_inode_dirty(inode, dirty); | ||
842 | return err; | 846 | return err; |
843 | do_sync: | 847 | do_sync: |
844 | spin_unlock(&inode->i_lock); | 848 | spin_unlock(&inode->i_lock); |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 23d43cde4306..1b2e180b018d 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -277,6 +277,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen, | |||
277 | 277 | ||
278 | for (i = 0, j = 0; i < srclen; j++) { | 278 | for (i = 0, j = 0; i < srclen; j++) { |
279 | src_char = source[i]; | 279 | src_char = source[i]; |
280 | charlen = 1; | ||
280 | switch (src_char) { | 281 | switch (src_char) { |
281 | case 0: | 282 | case 0: |
282 | put_unaligned(0, &target[j]); | 283 | put_unaligned(0, &target[j]); |
@@ -316,16 +317,13 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen, | |||
316 | dst_char = cpu_to_le16(0x003f); | 317 | dst_char = cpu_to_le16(0x003f); |
317 | charlen = 1; | 318 | charlen = 1; |
318 | } | 319 | } |
319 | /* | ||
320 | * character may take more than one byte in the source | ||
321 | * string, but will take exactly two bytes in the | ||
322 | * target string | ||
323 | */ | ||
324 | i += charlen; | ||
325 | continue; | ||
326 | } | 320 | } |
321 | /* | ||
322 | * character may take more than one byte in the source string, | ||
323 | * but will take exactly two bytes in the target string | ||
324 | */ | ||
325 | i += charlen; | ||
327 | put_unaligned(dst_char, &target[j]); | 326 | put_unaligned(dst_char, &target[j]); |
328 | i++; /* move to next char in source string */ | ||
329 | } | 327 | } |
330 | 328 | ||
331 | ctoUCS_out: | 329 | ctoUCS_out: |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index db9d55b507d0..277262a8e82f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -274,7 +274,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
274 | char *data_area_of_target; | 274 | char *data_area_of_target; |
275 | char *data_area_of_buf2; | 275 | char *data_area_of_buf2; |
276 | int remaining; | 276 | int remaining; |
277 | __u16 byte_count, total_data_size, total_in_buf, total_in_buf2; | 277 | unsigned int byte_count, total_in_buf; |
278 | __u16 total_data_size, total_in_buf2; | ||
278 | 279 | ||
279 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | 280 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
280 | 281 | ||
@@ -287,7 +288,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
287 | remaining = total_data_size - total_in_buf; | 288 | remaining = total_data_size - total_in_buf; |
288 | 289 | ||
289 | if (remaining < 0) | 290 | if (remaining < 0) |
290 | return -EINVAL; | 291 | return -EPROTO; |
291 | 292 | ||
292 | if (remaining == 0) /* nothing to do, ignore */ | 293 | if (remaining == 0) /* nothing to do, ignore */ |
293 | return 0; | 294 | return 0; |
@@ -308,20 +309,29 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
308 | data_area_of_target += total_in_buf; | 309 | data_area_of_target += total_in_buf; |
309 | 310 | ||
310 | /* copy second buffer into end of first buffer */ | 311 | /* copy second buffer into end of first buffer */ |
311 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | ||
312 | total_in_buf += total_in_buf2; | 312 | total_in_buf += total_in_buf2; |
313 | /* is the result too big for the field? */ | ||
314 | if (total_in_buf > USHRT_MAX) | ||
315 | return -EPROTO; | ||
313 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); | 316 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); |
317 | |||
318 | /* fix up the BCC */ | ||
314 | byte_count = get_bcc_le(pTargetSMB); | 319 | byte_count = get_bcc_le(pTargetSMB); |
315 | byte_count += total_in_buf2; | 320 | byte_count += total_in_buf2; |
321 | /* is the result too big for the field? */ | ||
322 | if (byte_count > USHRT_MAX) | ||
323 | return -EPROTO; | ||
316 | put_bcc_le(byte_count, pTargetSMB); | 324 | put_bcc_le(byte_count, pTargetSMB); |
317 | 325 | ||
318 | byte_count = pTargetSMB->smb_buf_length; | 326 | byte_count = pTargetSMB->smb_buf_length; |
319 | byte_count += total_in_buf2; | 327 | byte_count += total_in_buf2; |
320 | 328 | /* don't allow buffer to overflow */ | |
321 | /* BB also add check that we are not beyond maximum buffer size */ | 329 | if (byte_count > CIFSMaxBufSize) |
322 | 330 | return -ENOBUFS; | |
323 | pTargetSMB->smb_buf_length = byte_count; | 331 | pTargetSMB->smb_buf_length = byte_count; |
324 | 332 | ||
333 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | ||
334 | |||
325 | if (remaining == total_in_buf2) { | 335 | if (remaining == total_in_buf2) { |
326 | cFYI(1, "found the last secondary response"); | 336 | cFYI(1, "found the last secondary response"); |
327 | return 0; /* we are done */ | 337 | return 0; /* we are done */ |
@@ -607,59 +617,63 @@ incomplete_rcv: | |||
607 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { | 617 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
608 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 618 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
609 | 619 | ||
610 | if ((mid_entry->mid == smb_buffer->Mid) && | 620 | if (mid_entry->mid != smb_buffer->Mid || |
611 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | 621 | mid_entry->midState != MID_REQUEST_SUBMITTED || |
612 | (mid_entry->command == smb_buffer->Command)) { | 622 | mid_entry->command != smb_buffer->Command) { |
613 | if (length == 0 && | 623 | mid_entry = NULL; |
614 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | 624 | continue; |
615 | /* We have a multipart transact2 resp */ | 625 | } |
616 | isMultiRsp = true; | 626 | |
617 | if (mid_entry->resp_buf) { | 627 | if (length == 0 && |
618 | /* merge response - fix up 1st*/ | 628 | check2ndT2(smb_buffer, server->maxBuf) > 0) { |
619 | if (coalesce_t2(smb_buffer, | 629 | /* We have a multipart transact2 resp */ |
620 | mid_entry->resp_buf)) { | 630 | isMultiRsp = true; |
621 | mid_entry->multiRsp = | 631 | if (mid_entry->resp_buf) { |
622 | true; | 632 | /* merge response - fix up 1st*/ |
623 | break; | 633 | length = coalesce_t2(smb_buffer, |
624 | } else { | 634 | mid_entry->resp_buf); |
625 | /* all parts received */ | 635 | if (length > 0) { |
626 | mid_entry->multiEnd = | 636 | length = 0; |
627 | true; | 637 | mid_entry->multiRsp = true; |
628 | goto multi_t2_fnd; | 638 | break; |
629 | } | ||
630 | } else { | 639 | } else { |
631 | if (!isLargeBuf) { | 640 | /* all parts received or |
632 | cERROR(1, "1st trans2 resp needs bigbuf"); | 641 | * packet is malformed |
633 | /* BB maybe we can fix this up, switch | 642 | */ |
634 | to already allocated large buffer? */ | 643 | mid_entry->multiEnd = true; |
635 | } else { | 644 | goto multi_t2_fnd; |
636 | /* Have first buffer */ | 645 | } |
637 | mid_entry->resp_buf = | 646 | } else { |
638 | smb_buffer; | 647 | if (!isLargeBuf) { |
639 | mid_entry->largeBuf = | 648 | /* |
640 | true; | 649 | * FIXME: switch to already |
641 | bigbuf = NULL; | 650 | * allocated largebuf? |
642 | } | 651 | */ |
652 | cERROR(1, "1st trans2 resp " | ||
653 | "needs bigbuf"); | ||
654 | } else { | ||
655 | /* Have first buffer */ | ||
656 | mid_entry->resp_buf = | ||
657 | smb_buffer; | ||
658 | mid_entry->largeBuf = true; | ||
659 | bigbuf = NULL; | ||
643 | } | 660 | } |
644 | break; | ||
645 | } | 661 | } |
646 | mid_entry->resp_buf = smb_buffer; | 662 | break; |
647 | mid_entry->largeBuf = isLargeBuf; | 663 | } |
664 | mid_entry->resp_buf = smb_buffer; | ||
665 | mid_entry->largeBuf = isLargeBuf; | ||
648 | multi_t2_fnd: | 666 | multi_t2_fnd: |
649 | if (length == 0) | 667 | if (length == 0) |
650 | mid_entry->midState = | 668 | mid_entry->midState = MID_RESPONSE_RECEIVED; |
651 | MID_RESPONSE_RECEIVED; | 669 | else |
652 | else | 670 | mid_entry->midState = MID_RESPONSE_MALFORMED; |
653 | mid_entry->midState = | ||
654 | MID_RESPONSE_MALFORMED; | ||
655 | #ifdef CONFIG_CIFS_STATS2 | 671 | #ifdef CONFIG_CIFS_STATS2 |
656 | mid_entry->when_received = jiffies; | 672 | mid_entry->when_received = jiffies; |
657 | #endif | 673 | #endif |
658 | list_del_init(&mid_entry->qhead); | 674 | list_del_init(&mid_entry->qhead); |
659 | mid_entry->callback(mid_entry); | 675 | mid_entry->callback(mid_entry); |
660 | break; | 676 | break; |
661 | } | ||
662 | mid_entry = NULL; | ||
663 | } | 677 | } |
664 | spin_unlock(&GlobalMid_Lock); | 678 | spin_unlock(&GlobalMid_Lock); |
665 | 679 | ||
@@ -807,8 +821,7 @@ static int | |||
807 | cifs_parse_mount_options(char *options, const char *devname, | 821 | cifs_parse_mount_options(char *options, const char *devname, |
808 | struct smb_vol *vol) | 822 | struct smb_vol *vol) |
809 | { | 823 | { |
810 | char *value; | 824 | char *value, *data, *end; |
811 | char *data; | ||
812 | unsigned int temp_len, i, j; | 825 | unsigned int temp_len, i, j; |
813 | char separator[2]; | 826 | char separator[2]; |
814 | short int override_uid = -1; | 827 | short int override_uid = -1; |
@@ -851,6 +864,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
851 | if (!options) | 864 | if (!options) |
852 | return 1; | 865 | return 1; |
853 | 866 | ||
867 | end = options + strlen(options); | ||
854 | if (strncmp(options, "sep=", 4) == 0) { | 868 | if (strncmp(options, "sep=", 4) == 0) { |
855 | if (options[4] != 0) { | 869 | if (options[4] != 0) { |
856 | separator[0] = options[4]; | 870 | separator[0] = options[4]; |
@@ -916,6 +930,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
916 | the only illegal character in a password is null */ | 930 | the only illegal character in a password is null */ |
917 | 931 | ||
918 | if ((value[temp_len] == 0) && | 932 | if ((value[temp_len] == 0) && |
933 | (value + temp_len < end) && | ||
919 | (value[temp_len+1] == separator[0])) { | 934 | (value[temp_len+1] == separator[0])) { |
920 | /* reinsert comma */ | 935 | /* reinsert comma */ |
921 | value[temp_len] = separator[0]; | 936 | value[temp_len] = separator[0]; |
@@ -2658,6 +2673,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, | |||
2658 | 0 /* not legacy */, cifs_sb->local_nls, | 2673 | 0 /* not legacy */, cifs_sb->local_nls, |
2659 | cifs_sb->mnt_cifs_flags & | 2674 | cifs_sb->mnt_cifs_flags & |
2660 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2675 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2676 | |||
2677 | if (rc == -EOPNOTSUPP || rc == -EINVAL) | ||
2678 | rc = SMBQueryInformation(xid, tcon, full_path, pfile_info, | ||
2679 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
2680 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2661 | kfree(pfile_info); | 2681 | kfree(pfile_info); |
2662 | return rc; | 2682 | return rc; |
2663 | } | 2683 | } |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index f6728eb6f4b9..645114ad0a10 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -276,7 +276,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | |||
276 | } | 276 | } |
277 | 277 | ||
278 | static void | 278 | static void |
279 | decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, | 279 | decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, |
280 | const struct nls_table *nls_cp) | 280 | const struct nls_table *nls_cp) |
281 | { | 281 | { |
282 | int len; | 282 | int len; |
@@ -284,19 +284,6 @@ decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, | |||
284 | 284 | ||
285 | cFYI(1, "bleft %d", bleft); | 285 | cFYI(1, "bleft %d", bleft); |
286 | 286 | ||
287 | /* | ||
288 | * Windows servers do not always double null terminate their final | ||
289 | * Unicode string. Check to see if there are an uneven number of bytes | ||
290 | * left. If so, then add an extra NULL pad byte to the end of the | ||
291 | * response. | ||
292 | * | ||
293 | * See section 2.7.2 in "Implementing CIFS" for details | ||
294 | */ | ||
295 | if (bleft % 2) { | ||
296 | data[bleft] = 0; | ||
297 | ++bleft; | ||
298 | } | ||
299 | |||
300 | kfree(ses->serverOS); | 287 | kfree(ses->serverOS); |
301 | ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); | 288 | ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); |
302 | cFYI(1, "serverOS=%s", ses->serverOS); | 289 | cFYI(1, "serverOS=%s", ses->serverOS); |
@@ -929,7 +916,9 @@ ssetup_ntlmssp_authenticate: | |||
929 | } | 916 | } |
930 | 917 | ||
931 | /* BB check if Unicode and decode strings */ | 918 | /* BB check if Unicode and decode strings */ |
932 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) { | 919 | if (bytes_remaining == 0) { |
920 | /* no string area to decode, do nothing */ | ||
921 | } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { | ||
933 | /* unicode string area must be word-aligned */ | 922 | /* unicode string area must be word-aligned */ |
934 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { | 923 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { |
935 | ++bcc_ptr; | 924 | ++bcc_ptr; |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 3313dd19f543..9a37a9b6de3a 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock); | |||
53 | static void configfs_d_iput(struct dentry * dentry, | 53 | static void configfs_d_iput(struct dentry * dentry, |
54 | struct inode * inode) | 54 | struct inode * inode) |
55 | { | 55 | { |
56 | struct configfs_dirent * sd = dentry->d_fsdata; | 56 | struct configfs_dirent *sd = dentry->d_fsdata; |
57 | 57 | ||
58 | if (sd) { | 58 | if (sd) { |
59 | BUG_ON(sd->s_dentry != dentry); | 59 | BUG_ON(sd->s_dentry != dentry); |
60 | /* Coordinate with configfs_readdir */ | ||
61 | spin_lock(&configfs_dirent_lock); | ||
60 | sd->s_dentry = NULL; | 62 | sd->s_dentry = NULL; |
63 | spin_unlock(&configfs_dirent_lock); | ||
61 | configfs_put(sd); | 64 | configfs_put(sd); |
62 | } | 65 | } |
63 | iput(inode); | 66 | iput(inode); |
@@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group, | |||
689 | sd = child->d_fsdata; | 692 | sd = child->d_fsdata; |
690 | sd->s_type |= CONFIGFS_USET_DEFAULT; | 693 | sd->s_type |= CONFIGFS_USET_DEFAULT; |
691 | } else { | 694 | } else { |
692 | d_delete(child); | 695 | BUG_ON(child->d_inode); |
696 | d_drop(child); | ||
693 | dput(child); | 697 | dput(child); |
694 | } | 698 | } |
695 | } | 699 | } |
@@ -1545,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1545 | struct configfs_dirent * parent_sd = dentry->d_fsdata; | 1549 | struct configfs_dirent * parent_sd = dentry->d_fsdata; |
1546 | struct configfs_dirent *cursor = filp->private_data; | 1550 | struct configfs_dirent *cursor = filp->private_data; |
1547 | struct list_head *p, *q = &cursor->s_sibling; | 1551 | struct list_head *p, *q = &cursor->s_sibling; |
1548 | ino_t ino; | 1552 | ino_t ino = 0; |
1549 | int i = filp->f_pos; | 1553 | int i = filp->f_pos; |
1550 | 1554 | ||
1551 | switch (i) { | 1555 | switch (i) { |
@@ -1573,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1573 | struct configfs_dirent *next; | 1577 | struct configfs_dirent *next; |
1574 | const char * name; | 1578 | const char * name; |
1575 | int len; | 1579 | int len; |
1580 | struct inode *inode = NULL; | ||
1576 | 1581 | ||
1577 | next = list_entry(p, struct configfs_dirent, | 1582 | next = list_entry(p, struct configfs_dirent, |
1578 | s_sibling); | 1583 | s_sibling); |
@@ -1581,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1581 | 1586 | ||
1582 | name = configfs_get_name(next); | 1587 | name = configfs_get_name(next); |
1583 | len = strlen(name); | 1588 | len = strlen(name); |
1584 | if (next->s_dentry) | 1589 | |
1585 | ino = next->s_dentry->d_inode->i_ino; | 1590 | /* |
1586 | else | 1591 | * We'll have a dentry and an inode for |
1592 | * PINNED items and for open attribute | ||
1593 | * files. We lock here to prevent a race | ||
1594 | * with configfs_d_iput() clearing | ||
1595 | * s_dentry before calling iput(). | ||
1596 | * | ||
1597 | * Why do we go to the trouble? If | ||
1598 | * someone has an attribute file open, | ||
1599 | * the inode number should match until | ||
1600 | * they close it. Beyond that, we don't | ||
1601 | * care. | ||
1602 | */ | ||
1603 | spin_lock(&configfs_dirent_lock); | ||
1604 | dentry = next->s_dentry; | ||
1605 | if (dentry) | ||
1606 | inode = dentry->d_inode; | ||
1607 | if (inode) | ||
1608 | ino = inode->i_ino; | ||
1609 | spin_unlock(&configfs_dirent_lock); | ||
1610 | if (!inode) | ||
1587 | ino = iunique(configfs_sb, 2); | 1611 | ino = iunique(configfs_sb, 2); |
1588 | 1612 | ||
1589 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1613 | if (filldir(dirent, name, len, filp->f_pos, ino, |
@@ -1683,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
1683 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1707 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
1684 | dentry); | 1708 | dentry); |
1685 | if (err) { | 1709 | if (err) { |
1686 | d_delete(dentry); | 1710 | BUG_ON(dentry->d_inode); |
1711 | d_drop(dentry); | ||
1687 | dput(dentry); | 1712 | dput(dentry); |
1688 | } else { | 1713 | } else { |
1689 | spin_lock(&configfs_dirent_lock); | 1714 | spin_lock(&configfs_dirent_lock); |
diff --git a/fs/dcache.c b/fs/dcache.c index 129a35730994..22a0ef41bad1 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -99,12 +99,9 @@ static struct kmem_cache *dentry_cache __read_mostly; | |||
99 | static unsigned int d_hash_mask __read_mostly; | 99 | static unsigned int d_hash_mask __read_mostly; |
100 | static unsigned int d_hash_shift __read_mostly; | 100 | static unsigned int d_hash_shift __read_mostly; |
101 | 101 | ||
102 | struct dcache_hash_bucket { | 102 | static struct hlist_bl_head *dentry_hashtable __read_mostly; |
103 | struct hlist_bl_head head; | ||
104 | }; | ||
105 | static struct dcache_hash_bucket *dentry_hashtable __read_mostly; | ||
106 | 103 | ||
107 | static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, | 104 | static inline struct hlist_bl_head *d_hash(struct dentry *parent, |
108 | unsigned long hash) | 105 | unsigned long hash) |
109 | { | 106 | { |
110 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; | 107 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; |
@@ -112,16 +109,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, | |||
112 | return dentry_hashtable + (hash & D_HASHMASK); | 109 | return dentry_hashtable + (hash & D_HASHMASK); |
113 | } | 110 | } |
114 | 111 | ||
115 | static inline void spin_lock_bucket(struct dcache_hash_bucket *b) | ||
116 | { | ||
117 | bit_spin_lock(0, (unsigned long *)&b->head.first); | ||
118 | } | ||
119 | |||
120 | static inline void spin_unlock_bucket(struct dcache_hash_bucket *b) | ||
121 | { | ||
122 | __bit_spin_unlock(0, (unsigned long *)&b->head.first); | ||
123 | } | ||
124 | |||
125 | /* Statistics gathering. */ | 112 | /* Statistics gathering. */ |
126 | struct dentry_stat_t dentry_stat = { | 113 | struct dentry_stat_t dentry_stat = { |
127 | .age_limit = 45, | 114 | .age_limit = 45, |
@@ -167,8 +154,8 @@ static void d_free(struct dentry *dentry) | |||
167 | if (dentry->d_op && dentry->d_op->d_release) | 154 | if (dentry->d_op && dentry->d_op->d_release) |
168 | dentry->d_op->d_release(dentry); | 155 | dentry->d_op->d_release(dentry); |
169 | 156 | ||
170 | /* if dentry was never inserted into hash, immediate free is OK */ | 157 | /* if dentry was never visible to RCU, immediate free is OK */ |
171 | if (hlist_bl_unhashed(&dentry->d_hash)) | 158 | if (!(dentry->d_flags & DCACHE_RCUACCESS)) |
172 | __d_free(&dentry->d_u.d_rcu); | 159 | __d_free(&dentry->d_u.d_rcu); |
173 | else | 160 | else |
174 | call_rcu(&dentry->d_u.d_rcu, __d_free); | 161 | call_rcu(&dentry->d_u.d_rcu, __d_free); |
@@ -330,28 +317,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
330 | */ | 317 | */ |
331 | void __d_drop(struct dentry *dentry) | 318 | void __d_drop(struct dentry *dentry) |
332 | { | 319 | { |
333 | if (!(dentry->d_flags & DCACHE_UNHASHED)) { | 320 | if (!d_unhashed(dentry)) { |
334 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) { | 321 | struct hlist_bl_head *b; |
335 | bit_spin_lock(0, | 322 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) |
336 | (unsigned long *)&dentry->d_sb->s_anon.first); | 323 | b = &dentry->d_sb->s_anon; |
337 | dentry->d_flags |= DCACHE_UNHASHED; | 324 | else |
338 | hlist_bl_del_init(&dentry->d_hash); | ||
339 | __bit_spin_unlock(0, | ||
340 | (unsigned long *)&dentry->d_sb->s_anon.first); | ||
341 | } else { | ||
342 | struct dcache_hash_bucket *b; | ||
343 | b = d_hash(dentry->d_parent, dentry->d_name.hash); | 325 | b = d_hash(dentry->d_parent, dentry->d_name.hash); |
344 | spin_lock_bucket(b); | 326 | |
345 | /* | 327 | hlist_bl_lock(b); |
346 | * We may not actually need to put DCACHE_UNHASHED | 328 | __hlist_bl_del(&dentry->d_hash); |
347 | * manipulations under the hash lock, but follow | 329 | dentry->d_hash.pprev = NULL; |
348 | * the principle of least surprise. | 330 | hlist_bl_unlock(b); |
349 | */ | 331 | |
350 | dentry->d_flags |= DCACHE_UNHASHED; | 332 | dentry_rcuwalk_barrier(dentry); |
351 | hlist_bl_del_rcu(&dentry->d_hash); | ||
352 | spin_unlock_bucket(b); | ||
353 | dentry_rcuwalk_barrier(dentry); | ||
354 | } | ||
355 | } | 333 | } |
356 | } | 334 | } |
357 | EXPORT_SYMBOL(__d_drop); | 335 | EXPORT_SYMBOL(__d_drop); |
@@ -1304,7 +1282,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1304 | dname[name->len] = 0; | 1282 | dname[name->len] = 0; |
1305 | 1283 | ||
1306 | dentry->d_count = 1; | 1284 | dentry->d_count = 1; |
1307 | dentry->d_flags = DCACHE_UNHASHED; | 1285 | dentry->d_flags = 0; |
1308 | spin_lock_init(&dentry->d_lock); | 1286 | spin_lock_init(&dentry->d_lock); |
1309 | seqcount_init(&dentry->d_seq); | 1287 | seqcount_init(&dentry->d_seq); |
1310 | dentry->d_inode = NULL; | 1288 | dentry->d_inode = NULL; |
@@ -1606,10 +1584,9 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1606 | tmp->d_inode = inode; | 1584 | tmp->d_inode = inode; |
1607 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1585 | tmp->d_flags |= DCACHE_DISCONNECTED; |
1608 | list_add(&tmp->d_alias, &inode->i_dentry); | 1586 | list_add(&tmp->d_alias, &inode->i_dentry); |
1609 | bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first); | 1587 | hlist_bl_lock(&tmp->d_sb->s_anon); |
1610 | tmp->d_flags &= ~DCACHE_UNHASHED; | ||
1611 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); | 1588 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); |
1612 | __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); | 1589 | hlist_bl_unlock(&tmp->d_sb->s_anon); |
1613 | spin_unlock(&tmp->d_lock); | 1590 | spin_unlock(&tmp->d_lock); |
1614 | spin_unlock(&inode->i_lock); | 1591 | spin_unlock(&inode->i_lock); |
1615 | security_d_instantiate(tmp, inode); | 1592 | security_d_instantiate(tmp, inode); |
@@ -1789,7 +1766,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1789 | unsigned int len = name->len; | 1766 | unsigned int len = name->len; |
1790 | unsigned int hash = name->hash; | 1767 | unsigned int hash = name->hash; |
1791 | const unsigned char *str = name->name; | 1768 | const unsigned char *str = name->name; |
1792 | struct dcache_hash_bucket *b = d_hash(parent, hash); | 1769 | struct hlist_bl_head *b = d_hash(parent, hash); |
1793 | struct hlist_bl_node *node; | 1770 | struct hlist_bl_node *node; |
1794 | struct dentry *dentry; | 1771 | struct dentry *dentry; |
1795 | 1772 | ||
@@ -1813,7 +1790,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1813 | * | 1790 | * |
1814 | * See Documentation/filesystems/path-lookup.txt for more details. | 1791 | * See Documentation/filesystems/path-lookup.txt for more details. |
1815 | */ | 1792 | */ |
1816 | hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { | 1793 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { |
1817 | struct inode *i; | 1794 | struct inode *i; |
1818 | const char *tname; | 1795 | const char *tname; |
1819 | int tlen; | 1796 | int tlen; |
@@ -1908,7 +1885,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) | |||
1908 | unsigned int len = name->len; | 1885 | unsigned int len = name->len; |
1909 | unsigned int hash = name->hash; | 1886 | unsigned int hash = name->hash; |
1910 | const unsigned char *str = name->name; | 1887 | const unsigned char *str = name->name; |
1911 | struct dcache_hash_bucket *b = d_hash(parent, hash); | 1888 | struct hlist_bl_head *b = d_hash(parent, hash); |
1912 | struct hlist_bl_node *node; | 1889 | struct hlist_bl_node *node; |
1913 | struct dentry *found = NULL; | 1890 | struct dentry *found = NULL; |
1914 | struct dentry *dentry; | 1891 | struct dentry *dentry; |
@@ -1935,7 +1912,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) | |||
1935 | */ | 1912 | */ |
1936 | rcu_read_lock(); | 1913 | rcu_read_lock(); |
1937 | 1914 | ||
1938 | hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { | 1915 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { |
1939 | const char *tname; | 1916 | const char *tname; |
1940 | int tlen; | 1917 | int tlen; |
1941 | 1918 | ||
@@ -2086,13 +2063,13 @@ again: | |||
2086 | } | 2063 | } |
2087 | EXPORT_SYMBOL(d_delete); | 2064 | EXPORT_SYMBOL(d_delete); |
2088 | 2065 | ||
2089 | static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b) | 2066 | static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b) |
2090 | { | 2067 | { |
2091 | BUG_ON(!d_unhashed(entry)); | 2068 | BUG_ON(!d_unhashed(entry)); |
2092 | spin_lock_bucket(b); | 2069 | hlist_bl_lock(b); |
2093 | entry->d_flags &= ~DCACHE_UNHASHED; | 2070 | entry->d_flags |= DCACHE_RCUACCESS; |
2094 | hlist_bl_add_head_rcu(&entry->d_hash, &b->head); | 2071 | hlist_bl_add_head_rcu(&entry->d_hash, b); |
2095 | spin_unlock_bucket(b); | 2072 | hlist_bl_unlock(b); |
2096 | } | 2073 | } |
2097 | 2074 | ||
2098 | static void _d_rehash(struct dentry * entry) | 2075 | static void _d_rehash(struct dentry * entry) |
@@ -3025,7 +3002,7 @@ static void __init dcache_init_early(void) | |||
3025 | 3002 | ||
3026 | dentry_hashtable = | 3003 | dentry_hashtable = |
3027 | alloc_large_system_hash("Dentry cache", | 3004 | alloc_large_system_hash("Dentry cache", |
3028 | sizeof(struct dcache_hash_bucket), | 3005 | sizeof(struct hlist_bl_head), |
3029 | dhash_entries, | 3006 | dhash_entries, |
3030 | 13, | 3007 | 13, |
3031 | HASH_EARLY, | 3008 | HASH_EARLY, |
@@ -3034,7 +3011,7 @@ static void __init dcache_init_early(void) | |||
3034 | 0); | 3011 | 0); |
3035 | 3012 | ||
3036 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 3013 | for (loop = 0; loop < (1 << d_hash_shift); loop++) |
3037 | INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); | 3014 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
3038 | } | 3015 | } |
3039 | 3016 | ||
3040 | static void __init dcache_init(void) | 3017 | static void __init dcache_init(void) |
@@ -3057,7 +3034,7 @@ static void __init dcache_init(void) | |||
3057 | 3034 | ||
3058 | dentry_hashtable = | 3035 | dentry_hashtable = |
3059 | alloc_large_system_hash("Dentry cache", | 3036 | alloc_large_system_hash("Dentry cache", |
3060 | sizeof(struct dcache_hash_bucket), | 3037 | sizeof(struct hlist_bl_head), |
3061 | dhash_entries, | 3038 | dhash_entries, |
3062 | 13, | 3039 | 13, |
3063 | 0, | 3040 | 0, |
@@ -3066,7 +3043,7 @@ static void __init dcache_init(void) | |||
3066 | 0); | 3043 | 0); |
3067 | 3044 | ||
3068 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 3045 | for (loop = 0; loop < (1 << d_hash_shift); loop++) |
3069 | INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); | 3046 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
3070 | } | 3047 | } |
3071 | 3048 | ||
3072 | /* SLAB cache for __getname() consumers */ | 3049 | /* SLAB cache for __getname() consumers */ |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index d2a70a4561f9..b8d5c8091024 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) | |||
1452 | crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; | 1452 | crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; |
1453 | } | 1453 | } |
1454 | 1454 | ||
1455 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode) | ||
1456 | { | ||
1457 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
1458 | struct ecryptfs_crypt_stat *crypt_stat; | ||
1459 | u64 file_size; | ||
1460 | |||
1461 | crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; | ||
1462 | mount_crypt_stat = | ||
1463 | &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; | ||
1464 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
1465 | file_size = i_size_read(ecryptfs_inode_to_lower(inode)); | ||
1466 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
1467 | file_size += crypt_stat->metadata_size; | ||
1468 | } else | ||
1469 | file_size = get_unaligned_be64(page_virt); | ||
1470 | i_size_write(inode, (loff_t)file_size); | ||
1471 | crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; | ||
1472 | } | ||
1473 | |||
1455 | /** | 1474 | /** |
1456 | * ecryptfs_read_headers_virt | 1475 | * ecryptfs_read_headers_virt |
1457 | * @page_virt: The virtual address into which to read the headers | 1476 | * @page_virt: The virtual address into which to read the headers |
@@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt, | |||
1482 | rc = -EINVAL; | 1501 | rc = -EINVAL; |
1483 | goto out; | 1502 | goto out; |
1484 | } | 1503 | } |
1504 | if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) | ||
1505 | ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); | ||
1485 | offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; | 1506 | offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; |
1486 | rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), | 1507 | rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset), |
1487 | &bytes_read); | 1508 | &bytes_read); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index bd3cafd0949d..e70282775e2c 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat { | |||
269 | #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 | 269 | #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 |
270 | #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 | 270 | #define ECRYPTFS_ENCFN_USE_FEK 0x00001000 |
271 | #define ECRYPTFS_UNLINK_SIGS 0x00002000 | 271 | #define ECRYPTFS_UNLINK_SIGS 0x00002000 |
272 | #define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000 | ||
272 | u32 flags; | 273 | u32 flags; |
273 | unsigned int file_version; | 274 | unsigned int file_version; |
274 | size_t iv_bytes; | 275 | size_t iv_bytes; |
@@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat { | |||
295 | struct ecryptfs_inode_info { | 296 | struct ecryptfs_inode_info { |
296 | struct inode vfs_inode; | 297 | struct inode vfs_inode; |
297 | struct inode *wii_inode; | 298 | struct inode *wii_inode; |
299 | struct mutex lower_file_mutex; | ||
300 | atomic_t lower_file_count; | ||
298 | struct file *lower_file; | 301 | struct file *lower_file; |
299 | struct ecryptfs_crypt_stat crypt_stat; | 302 | struct ecryptfs_crypt_stat crypt_stat; |
300 | }; | 303 | }; |
@@ -626,6 +629,7 @@ struct ecryptfs_open_req { | |||
626 | int ecryptfs_interpose(struct dentry *hidden_dentry, | 629 | int ecryptfs_interpose(struct dentry *hidden_dentry, |
627 | struct dentry *this_dentry, struct super_block *sb, | 630 | struct dentry *this_dentry, struct super_block *sb, |
628 | u32 flags); | 631 | u32 flags); |
632 | void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); | ||
629 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | 633 | int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, |
630 | struct dentry *lower_dentry, | 634 | struct dentry *lower_dentry, |
631 | struct inode *ecryptfs_dir_inode); | 635 | struct inode *ecryptfs_dir_inode); |
@@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
757 | struct dentry *lower_dentry, | 761 | struct dentry *lower_dentry, |
758 | struct vfsmount *lower_mnt, | 762 | struct vfsmount *lower_mnt, |
759 | const struct cred *cred); | 763 | const struct cred *cred); |
760 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry); | 764 | int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry); |
765 | void ecryptfs_put_lower_file(struct inode *inode); | ||
761 | int | 766 | int |
762 | ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, | 767 | ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, |
763 | size_t *packet_size, | 768 | size_t *packet_size, |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index cedc913d11ba..566e5472f78c 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
191 | | ECRYPTFS_ENCRYPTED); | 191 | | ECRYPTFS_ENCRYPTED); |
192 | } | 192 | } |
193 | mutex_unlock(&crypt_stat->cs_mutex); | 193 | mutex_unlock(&crypt_stat->cs_mutex); |
194 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 194 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
195 | if (rc) { | 195 | if (rc) { |
196 | printk(KERN_ERR "%s: Error attempting to initialize " | 196 | printk(KERN_ERR "%s: Error attempting to initialize " |
197 | "the persistent file for the dentry with name " | 197 | "the lower file for the dentry with name " |
198 | "[%s]; rc = [%d]\n", __func__, | 198 | "[%s]; rc = [%d]\n", __func__, |
199 | ecryptfs_dentry->d_name.name, rc); | 199 | ecryptfs_dentry->d_name.name, rc); |
200 | goto out_free; | 200 | goto out_free; |
@@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
202 | if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) | 202 | if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE) |
203 | == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { | 203 | == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) { |
204 | rc = -EPERM; | 204 | rc = -EPERM; |
205 | printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs " | 205 | printk(KERN_WARNING "%s: Lower file is RO; eCryptfs " |
206 | "file must hence be opened RO\n", __func__); | 206 | "file must hence be opened RO\n", __func__); |
207 | goto out_free; | 207 | goto out_put; |
208 | } | 208 | } |
209 | ecryptfs_set_file_lower( | 209 | ecryptfs_set_file_lower( |
210 | file, ecryptfs_inode_to_private(inode)->lower_file); | 210 | file, ecryptfs_inode_to_private(inode)->lower_file); |
@@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
232 | "Plaintext passthrough mode is not " | 232 | "Plaintext passthrough mode is not " |
233 | "enabled; returning -EIO\n"); | 233 | "enabled; returning -EIO\n"); |
234 | mutex_unlock(&crypt_stat->cs_mutex); | 234 | mutex_unlock(&crypt_stat->cs_mutex); |
235 | goto out_free; | 235 | goto out_put; |
236 | } | 236 | } |
237 | rc = 0; | 237 | rc = 0; |
238 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 238 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED |
239 | | ECRYPTFS_ENCRYPTED); | ||
239 | mutex_unlock(&crypt_stat->cs_mutex); | 240 | mutex_unlock(&crypt_stat->cs_mutex); |
240 | goto out; | 241 | goto out; |
241 | } | 242 | } |
@@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
245 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, | 246 | "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, |
246 | (unsigned long long)i_size_read(inode)); | 247 | (unsigned long long)i_size_read(inode)); |
247 | goto out; | 248 | goto out; |
249 | out_put: | ||
250 | ecryptfs_put_lower_file(inode); | ||
248 | out_free: | 251 | out_free: |
249 | kmem_cache_free(ecryptfs_file_info_cache, | 252 | kmem_cache_free(ecryptfs_file_info_cache, |
250 | ecryptfs_file_to_private(file)); | 253 | ecryptfs_file_to_private(file)); |
@@ -254,17 +257,13 @@ out: | |||
254 | 257 | ||
255 | static int ecryptfs_flush(struct file *file, fl_owner_t td) | 258 | static int ecryptfs_flush(struct file *file, fl_owner_t td) |
256 | { | 259 | { |
257 | int rc = 0; | 260 | return file->f_mode & FMODE_WRITE |
258 | struct file *lower_file = NULL; | 261 | ? filemap_write_and_wait(file->f_mapping) : 0; |
259 | |||
260 | lower_file = ecryptfs_file_to_lower(file); | ||
261 | if (lower_file->f_op && lower_file->f_op->flush) | ||
262 | rc = lower_file->f_op->flush(lower_file, td); | ||
263 | return rc; | ||
264 | } | 262 | } |
265 | 263 | ||
266 | static int ecryptfs_release(struct inode *inode, struct file *file) | 264 | static int ecryptfs_release(struct inode *inode, struct file *file) |
267 | { | 265 | { |
266 | ecryptfs_put_lower_file(inode); | ||
268 | kmem_cache_free(ecryptfs_file_info_cache, | 267 | kmem_cache_free(ecryptfs_file_info_cache, |
269 | ecryptfs_file_to_private(file)); | 268 | ecryptfs_file_to_private(file)); |
270 | return 0; | 269 | return 0; |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f99051b7adab..4d4cc6a90cd5 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) | |||
168 | "context; rc = [%d]\n", rc); | 168 | "context; rc = [%d]\n", rc); |
169 | goto out; | 169 | goto out; |
170 | } | 170 | } |
171 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 171 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
172 | if (rc) { | 172 | if (rc) { |
173 | printk(KERN_ERR "%s: Error attempting to initialize " | 173 | printk(KERN_ERR "%s: Error attempting to initialize " |
174 | "the persistent file for the dentry with name " | 174 | "the lower file for the dentry with name " |
175 | "[%s]; rc = [%d]\n", __func__, | 175 | "[%s]; rc = [%d]\n", __func__, |
176 | ecryptfs_dentry->d_name.name, rc); | 176 | ecryptfs_dentry->d_name.name, rc); |
177 | goto out; | 177 | goto out; |
178 | } | 178 | } |
179 | rc = ecryptfs_write_metadata(ecryptfs_dentry); | 179 | rc = ecryptfs_write_metadata(ecryptfs_dentry); |
180 | if (rc) { | 180 | if (rc) |
181 | printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); | 181 | printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); |
182 | goto out; | 182 | ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); |
183 | } | ||
184 | out: | 183 | out: |
185 | return rc; | 184 | return rc; |
186 | } | 185 | } |
@@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
226 | struct dentry *lower_dir_dentry; | 225 | struct dentry *lower_dir_dentry; |
227 | struct vfsmount *lower_mnt; | 226 | struct vfsmount *lower_mnt; |
228 | struct inode *lower_inode; | 227 | struct inode *lower_inode; |
229 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | ||
230 | struct ecryptfs_crypt_stat *crypt_stat; | 228 | struct ecryptfs_crypt_stat *crypt_stat; |
231 | char *page_virt = NULL; | 229 | char *page_virt = NULL; |
232 | u64 file_size; | 230 | int put_lower = 0, rc = 0; |
233 | int rc = 0; | ||
234 | 231 | ||
235 | lower_dir_dentry = lower_dentry->d_parent; | 232 | lower_dir_dentry = lower_dentry->d_parent; |
236 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( | 233 | lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt( |
@@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
277 | rc = -ENOMEM; | 274 | rc = -ENOMEM; |
278 | goto out; | 275 | goto out; |
279 | } | 276 | } |
280 | rc = ecryptfs_init_persistent_file(ecryptfs_dentry); | 277 | rc = ecryptfs_get_lower_file(ecryptfs_dentry); |
281 | if (rc) { | 278 | if (rc) { |
282 | printk(KERN_ERR "%s: Error attempting to initialize " | 279 | printk(KERN_ERR "%s: Error attempting to initialize " |
283 | "the persistent file for the dentry with name " | 280 | "the lower file for the dentry with name " |
284 | "[%s]; rc = [%d]\n", __func__, | 281 | "[%s]; rc = [%d]\n", __func__, |
285 | ecryptfs_dentry->d_name.name, rc); | 282 | ecryptfs_dentry->d_name.name, rc); |
286 | goto out_free_kmem; | 283 | goto out_free_kmem; |
287 | } | 284 | } |
285 | put_lower = 1; | ||
288 | crypt_stat = &ecryptfs_inode_to_private( | 286 | crypt_stat = &ecryptfs_inode_to_private( |
289 | ecryptfs_dentry->d_inode)->crypt_stat; | 287 | ecryptfs_dentry->d_inode)->crypt_stat; |
290 | /* TODO: lock for crypt_stat comparison */ | 288 | /* TODO: lock for crypt_stat comparison */ |
@@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry, | |||
302 | } | 300 | } |
303 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; | 301 | crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; |
304 | } | 302 | } |
305 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 303 | ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode); |
306 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | ||
307 | if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { | ||
308 | if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) | ||
309 | file_size = (crypt_stat->metadata_size | ||
310 | + i_size_read(lower_dentry->d_inode)); | ||
311 | else | ||
312 | file_size = i_size_read(lower_dentry->d_inode); | ||
313 | } else { | ||
314 | file_size = get_unaligned_be64(page_virt); | ||
315 | } | ||
316 | i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size); | ||
317 | out_free_kmem: | 304 | out_free_kmem: |
318 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); | 305 | kmem_cache_free(ecryptfs_header_cache_2, page_virt); |
319 | goto out; | 306 | goto out; |
@@ -322,6 +309,8 @@ out_put: | |||
322 | mntput(lower_mnt); | 309 | mntput(lower_mnt); |
323 | d_drop(ecryptfs_dentry); | 310 | d_drop(ecryptfs_dentry); |
324 | out: | 311 | out: |
312 | if (put_lower) | ||
313 | ecryptfs_put_lower_file(ecryptfs_dentry->d_inode); | ||
325 | return rc; | 314 | return rc; |
326 | } | 315 | } |
327 | 316 | ||
@@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
538 | dget(lower_dentry); | 527 | dget(lower_dentry); |
539 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); | 528 | rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); |
540 | dput(lower_dentry); | 529 | dput(lower_dentry); |
541 | if (!rc) | ||
542 | d_delete(lower_dentry); | ||
543 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); | 530 | fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode); |
544 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; | 531 | dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; |
545 | unlock_dir(lower_dir_dentry); | 532 | unlock_dir(lower_dir_dentry); |
@@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
610 | fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); | 597 | fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode); |
611 | out_lock: | 598 | out_lock: |
612 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); | 599 | unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); |
613 | dput(lower_new_dentry->d_parent); | 600 | dput(lower_new_dir_dentry); |
614 | dput(lower_old_dentry->d_parent); | 601 | dput(lower_old_dir_dentry); |
615 | dput(lower_new_dentry); | 602 | dput(lower_new_dentry); |
616 | dput(lower_old_dentry); | 603 | dput(lower_old_dentry); |
617 | return rc; | 604 | return rc; |
@@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
759 | 746 | ||
760 | if (unlikely((ia->ia_size == i_size))) { | 747 | if (unlikely((ia->ia_size == i_size))) { |
761 | lower_ia->ia_valid &= ~ATTR_SIZE; | 748 | lower_ia->ia_valid &= ~ATTR_SIZE; |
762 | goto out; | 749 | return 0; |
763 | } | 750 | } |
751 | rc = ecryptfs_get_lower_file(dentry); | ||
752 | if (rc) | ||
753 | return rc; | ||
764 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; | 754 | crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; |
765 | /* Switch on growing or shrinking file */ | 755 | /* Switch on growing or shrinking file */ |
766 | if (ia->ia_size > i_size) { | 756 | if (ia->ia_size > i_size) { |
@@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia, | |||
838 | lower_ia->ia_valid &= ~ATTR_SIZE; | 828 | lower_ia->ia_valid &= ~ATTR_SIZE; |
839 | } | 829 | } |
840 | out: | 830 | out: |
831 | ecryptfs_put_lower_file(inode); | ||
841 | return rc; | 832 | return rc; |
842 | } | 833 | } |
843 | 834 | ||
@@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
913 | 904 | ||
914 | mount_crypt_stat = &ecryptfs_superblock_to_private( | 905 | mount_crypt_stat = &ecryptfs_superblock_to_private( |
915 | dentry->d_sb)->mount_crypt_stat; | 906 | dentry->d_sb)->mount_crypt_stat; |
907 | rc = ecryptfs_get_lower_file(dentry); | ||
908 | if (rc) { | ||
909 | mutex_unlock(&crypt_stat->cs_mutex); | ||
910 | goto out; | ||
911 | } | ||
916 | rc = ecryptfs_read_metadata(dentry); | 912 | rc = ecryptfs_read_metadata(dentry); |
913 | ecryptfs_put_lower_file(inode); | ||
917 | if (rc) { | 914 | if (rc) { |
918 | if (!(mount_crypt_stat->flags | 915 | if (!(mount_crypt_stat->flags |
919 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { | 916 | & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { |
@@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
927 | goto out; | 924 | goto out; |
928 | } | 925 | } |
929 | rc = 0; | 926 | rc = 0; |
930 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 927 | crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED |
928 | | ECRYPTFS_ENCRYPTED); | ||
931 | } | 929 | } |
932 | } | 930 | } |
933 | mutex_unlock(&crypt_stat->cs_mutex); | 931 | mutex_unlock(&crypt_stat->cs_mutex); |
932 | if (S_ISREG(inode->i_mode)) { | ||
933 | rc = filemap_write_and_wait(inode->i_mapping); | ||
934 | if (rc) | ||
935 | goto out; | ||
936 | fsstack_copy_attr_all(inode, lower_inode); | ||
937 | } | ||
934 | memcpy(&lower_ia, ia, sizeof(lower_ia)); | 938 | memcpy(&lower_ia, ia, sizeof(lower_ia)); |
935 | if (ia->ia_valid & ATTR_FILE) | 939 | if (ia->ia_valid & ATTR_FILE) |
936 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); | 940 | lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file); |
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0851ab6980f5..69f994a7d524 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
@@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread; | |||
44 | * @ignored: ignored | 44 | * @ignored: ignored |
45 | * | 45 | * |
46 | * The eCryptfs kernel thread that has the responsibility of getting | 46 | * The eCryptfs kernel thread that has the responsibility of getting |
47 | * the lower persistent file with RW permissions. | 47 | * the lower file with RW permissions. |
48 | * | 48 | * |
49 | * Returns zero on success; non-zero otherwise | 49 | * Returns zero on success; non-zero otherwise |
50 | */ | 50 | */ |
@@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
141 | int rc = 0; | 141 | int rc = 0; |
142 | 142 | ||
143 | /* Corresponding dput() and mntput() are done when the | 143 | /* Corresponding dput() and mntput() are done when the |
144 | * persistent file is fput() when the eCryptfs inode is | 144 | * lower file is fput() when all eCryptfs files for the inode are |
145 | * destroyed. */ | 145 | * released. */ |
146 | dget(lower_dentry); | 146 | dget(lower_dentry); |
147 | mntget(lower_mnt); | 147 | mntget(lower_mnt); |
148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; | 148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index fdb2eb0ad09e..89b93389af8e 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | /** | 98 | /** |
99 | * ecryptfs_init_persistent_file | 99 | * ecryptfs_init_lower_file |
100 | * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with | 100 | * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with |
101 | * the lower dentry and the lower mount set | 101 | * the lower dentry and the lower mount set |
102 | * | 102 | * |
@@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...) | |||
104 | * inode. All I/O operations to the lower inode occur through that | 104 | * inode. All I/O operations to the lower inode occur through that |
105 | * file. When the first eCryptfs dentry that interposes with the first | 105 | * file. When the first eCryptfs dentry that interposes with the first |
106 | * lower dentry for that inode is created, this function creates the | 106 | * lower dentry for that inode is created, this function creates the |
107 | * persistent file struct and associates it with the eCryptfs | 107 | * lower file struct and associates it with the eCryptfs |
108 | * inode. When the eCryptfs inode is destroyed, the file is closed. | 108 | * inode. When all eCryptfs files associated with the inode are released, the |
109 | * file is closed. | ||
109 | * | 110 | * |
110 | * The persistent file will be opened with read/write permissions, if | 111 | * The lower file will be opened with read/write permissions, if |
111 | * possible. Otherwise, it is opened read-only. | 112 | * possible. Otherwise, it is opened read-only. |
112 | * | 113 | * |
113 | * This function does nothing if a lower persistent file is already | 114 | * This function does nothing if a lower file is already |
114 | * associated with the eCryptfs inode. | 115 | * associated with the eCryptfs inode. |
115 | * | 116 | * |
116 | * Returns zero on success; non-zero otherwise | 117 | * Returns zero on success; non-zero otherwise |
117 | */ | 118 | */ |
118 | int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | 119 | static int ecryptfs_init_lower_file(struct dentry *dentry, |
120 | struct file **lower_file) | ||
119 | { | 121 | { |
120 | const struct cred *cred = current_cred(); | 122 | const struct cred *cred = current_cred(); |
121 | struct ecryptfs_inode_info *inode_info = | 123 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
122 | ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); | 124 | struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); |
123 | int rc = 0; | 125 | int rc; |
124 | 126 | ||
125 | if (!inode_info->lower_file) { | 127 | rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, |
126 | struct dentry *lower_dentry; | 128 | cred); |
127 | struct vfsmount *lower_mnt = | 129 | if (rc) { |
128 | ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); | 130 | printk(KERN_ERR "Error opening lower file " |
131 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " | ||
132 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); | ||
133 | (*lower_file) = NULL; | ||
134 | } | ||
135 | return rc; | ||
136 | } | ||
129 | 137 | ||
130 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | 138 | int ecryptfs_get_lower_file(struct dentry *dentry) |
131 | rc = ecryptfs_privileged_open(&inode_info->lower_file, | 139 | { |
132 | lower_dentry, lower_mnt, cred); | 140 | struct ecryptfs_inode_info *inode_info = |
133 | if (rc) { | 141 | ecryptfs_inode_to_private(dentry->d_inode); |
134 | printk(KERN_ERR "Error opening lower persistent file " | 142 | int count, rc = 0; |
135 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " | 143 | |
136 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); | 144 | mutex_lock(&inode_info->lower_file_mutex); |
137 | inode_info->lower_file = NULL; | 145 | count = atomic_inc_return(&inode_info->lower_file_count); |
138 | } | 146 | if (WARN_ON_ONCE(count < 1)) |
147 | rc = -EINVAL; | ||
148 | else if (count == 1) { | ||
149 | rc = ecryptfs_init_lower_file(dentry, | ||
150 | &inode_info->lower_file); | ||
151 | if (rc) | ||
152 | atomic_set(&inode_info->lower_file_count, 0); | ||
139 | } | 153 | } |
154 | mutex_unlock(&inode_info->lower_file_mutex); | ||
140 | return rc; | 155 | return rc; |
141 | } | 156 | } |
142 | 157 | ||
158 | void ecryptfs_put_lower_file(struct inode *inode) | ||
159 | { | ||
160 | struct ecryptfs_inode_info *inode_info; | ||
161 | |||
162 | inode_info = ecryptfs_inode_to_private(inode); | ||
163 | if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, | ||
164 | &inode_info->lower_file_mutex)) { | ||
165 | fput(inode_info->lower_file); | ||
166 | inode_info->lower_file = NULL; | ||
167 | mutex_unlock(&inode_info->lower_file_mutex); | ||
168 | } | ||
169 | } | ||
170 | |||
143 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 171 | static struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
144 | struct super_block *sb) | 172 | struct super_block *sb) |
145 | { | 173 | { |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index bacc882e1ae4..245b517bf1b6 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) | |||
55 | if (unlikely(!inode_info)) | 55 | if (unlikely(!inode_info)) |
56 | goto out; | 56 | goto out; |
57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); | 57 | ecryptfs_init_crypt_stat(&inode_info->crypt_stat); |
58 | mutex_init(&inode_info->lower_file_mutex); | ||
59 | atomic_set(&inode_info->lower_file_count, 0); | ||
58 | inode_info->lower_file = NULL; | 60 | inode_info->lower_file = NULL; |
59 | inode = &inode_info->vfs_inode; | 61 | inode = &inode_info->vfs_inode; |
60 | out: | 62 | out: |
@@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head) | |||
77 | * | 79 | * |
78 | * This is used during the final destruction of the inode. All | 80 | * This is used during the final destruction of the inode. All |
79 | * allocation of memory related to the inode, including allocated | 81 | * allocation of memory related to the inode, including allocated |
80 | * memory in the crypt_stat struct, will be released here. This | 82 | * memory in the crypt_stat struct, will be released here. |
81 | * function also fput()'s the persistent file for the lower inode. | ||
82 | * There should be no chance that this deallocation will be missed. | 83 | * There should be no chance that this deallocation will be missed. |
83 | */ | 84 | */ |
84 | static void ecryptfs_destroy_inode(struct inode *inode) | 85 | static void ecryptfs_destroy_inode(struct inode *inode) |
@@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode) | |||
86 | struct ecryptfs_inode_info *inode_info; | 87 | struct ecryptfs_inode_info *inode_info; |
87 | 88 | ||
88 | inode_info = ecryptfs_inode_to_private(inode); | 89 | inode_info = ecryptfs_inode_to_private(inode); |
89 | if (inode_info->lower_file) { | 90 | BUG_ON(inode_info->lower_file); |
90 | struct dentry *lower_dentry = | ||
91 | inode_info->lower_file->f_dentry; | ||
92 | |||
93 | BUG_ON(!lower_dentry); | ||
94 | if (lower_dentry->d_inode) { | ||
95 | fput(inode_info->lower_file); | ||
96 | inode_info->lower_file = NULL; | ||
97 | } | ||
98 | } | ||
99 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); | 91 | ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat); |
100 | call_rcu(&inode->i_rcu, ecryptfs_i_callback); | 92 | call_rcu(&inode->i_rcu, ecryptfs_i_callback); |
101 | } | 93 | } |
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/mmzone.h> | ||
12 | #include <linux/time.h> | 13 | #include <linux/time.h> |
13 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
@@ -39,14 +40,17 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */ | |||
39 | */ | 40 | */ |
40 | static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); | 41 | static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); |
41 | 42 | ||
42 | static inline void *alloc_fdmem(unsigned int size) | 43 | static void *alloc_fdmem(unsigned int size) |
43 | { | 44 | { |
44 | void *data; | 45 | /* |
45 | 46 | * Very large allocations can stress page reclaim, so fall back to | |
46 | data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); | 47 | * vmalloc() if the allocation size will be considered "large" by the VM. |
47 | if (data != NULL) | 48 | */ |
48 | return data; | 49 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
49 | 50 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); | |
51 | if (data != NULL) | ||
52 | return data; | ||
53 | } | ||
50 | return vmalloc(size); | 54 | return vmalloc(size); |
51 | } | 55 | } |
52 | 56 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c6ba49bd95b3..b32eb29a4e6f 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
174 | if (!inode) | 174 | if (!inode) |
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | if (nd->flags & LOOKUP_RCU) | 177 | if (nd && (nd->flags & LOOKUP_RCU)) |
178 | return -ECHILD; | 178 | return -ECHILD; |
179 | 179 | ||
180 | fc = get_fuse_conn(inode); | 180 | fc = get_fuse_conn(inode); |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index c71995b111bf..0f5c4f9d5d62 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -884,8 +884,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
884 | } | 884 | } |
885 | 885 | ||
886 | brelse(dibh); | 886 | brelse(dibh); |
887 | gfs2_trans_end(sdp); | ||
888 | failed: | 887 | failed: |
888 | gfs2_trans_end(sdp); | ||
889 | if (al) { | 889 | if (al) { |
890 | gfs2_inplace_release(ip); | 890 | gfs2_inplace_release(ip); |
891 | gfs2_quota_unlock(ip); | 891 | gfs2_quota_unlock(ip); |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 5c356d09c321..f789c5732b7c 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1506,7 +1506,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) | |||
1506 | inode = gfs2_inode_lookup(dir->i_sb, | 1506 | inode = gfs2_inode_lookup(dir->i_sb, |
1507 | be16_to_cpu(dent->de_type), | 1507 | be16_to_cpu(dent->de_type), |
1508 | be64_to_cpu(dent->de_inum.no_addr), | 1508 | be64_to_cpu(dent->de_inum.no_addr), |
1509 | be64_to_cpu(dent->de_inum.no_formal_ino)); | 1509 | be64_to_cpu(dent->de_inum.no_formal_ino), 0); |
1510 | brelse(bh); | 1510 | brelse(bh); |
1511 | return inode; | 1511 | return inode; |
1512 | } | 1512 | } |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b2682e073eee..e48310885c48 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -617,18 +617,51 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
617 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | 617 | return generic_file_aio_write(iocb, iov, nr_segs, pos); |
618 | } | 618 | } |
619 | 619 | ||
620 | static void empty_write_end(struct page *page, unsigned from, | 620 | static int empty_write_end(struct page *page, unsigned from, |
621 | unsigned to) | 621 | unsigned to, int mode) |
622 | { | 622 | { |
623 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 623 | struct inode *inode = page->mapping->host; |
624 | struct gfs2_inode *ip = GFS2_I(inode); | ||
625 | struct buffer_head *bh; | ||
626 | unsigned offset, blksize = 1 << inode->i_blkbits; | ||
627 | pgoff_t end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; | ||
624 | 628 | ||
625 | zero_user(page, from, to-from); | 629 | zero_user(page, from, to-from); |
626 | mark_page_accessed(page); | 630 | mark_page_accessed(page); |
627 | 631 | ||
628 | if (!gfs2_is_writeback(ip)) | 632 | if (page->index < end_index || !(mode & FALLOC_FL_KEEP_SIZE)) { |
629 | gfs2_page_add_databufs(ip, page, from, to); | 633 | if (!gfs2_is_writeback(ip)) |
634 | gfs2_page_add_databufs(ip, page, from, to); | ||
635 | |||
636 | block_commit_write(page, from, to); | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | offset = 0; | ||
641 | bh = page_buffers(page); | ||
642 | while (offset < to) { | ||
643 | if (offset >= from) { | ||
644 | set_buffer_uptodate(bh); | ||
645 | mark_buffer_dirty(bh); | ||
646 | clear_buffer_new(bh); | ||
647 | write_dirty_buffer(bh, WRITE); | ||
648 | } | ||
649 | offset += blksize; | ||
650 | bh = bh->b_this_page; | ||
651 | } | ||
630 | 652 | ||
631 | block_commit_write(page, from, to); | 653 | offset = 0; |
654 | bh = page_buffers(page); | ||
655 | while (offset < to) { | ||
656 | if (offset >= from) { | ||
657 | wait_on_buffer(bh); | ||
658 | if (!buffer_uptodate(bh)) | ||
659 | return -EIO; | ||
660 | } | ||
661 | offset += blksize; | ||
662 | bh = bh->b_this_page; | ||
663 | } | ||
664 | return 0; | ||
632 | } | 665 | } |
633 | 666 | ||
634 | static int needs_empty_write(sector_t block, struct inode *inode) | 667 | static int needs_empty_write(sector_t block, struct inode *inode) |
@@ -643,7 +676,8 @@ static int needs_empty_write(sector_t block, struct inode *inode) | |||
643 | return !buffer_mapped(&bh_map); | 676 | return !buffer_mapped(&bh_map); |
644 | } | 677 | } |
645 | 678 | ||
646 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | 679 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to, |
680 | int mode) | ||
647 | { | 681 | { |
648 | struct inode *inode = page->mapping->host; | 682 | struct inode *inode = page->mapping->host; |
649 | unsigned start, end, next, blksize; | 683 | unsigned start, end, next, blksize; |
@@ -668,7 +702,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
668 | gfs2_block_map); | 702 | gfs2_block_map); |
669 | if (unlikely(ret)) | 703 | if (unlikely(ret)) |
670 | return ret; | 704 | return ret; |
671 | empty_write_end(page, start, end); | 705 | ret = empty_write_end(page, start, end, mode); |
706 | if (unlikely(ret)) | ||
707 | return ret; | ||
672 | end = 0; | 708 | end = 0; |
673 | } | 709 | } |
674 | start = next; | 710 | start = next; |
@@ -682,7 +718,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
682 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); | 718 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); |
683 | if (unlikely(ret)) | 719 | if (unlikely(ret)) |
684 | return ret; | 720 | return ret; |
685 | empty_write_end(page, start, end); | 721 | ret = empty_write_end(page, start, end, mode); |
722 | if (unlikely(ret)) | ||
723 | return ret; | ||
686 | } | 724 | } |
687 | 725 | ||
688 | return 0; | 726 | return 0; |
@@ -731,7 +769,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
731 | 769 | ||
732 | if (curr == end) | 770 | if (curr == end) |
733 | to = end_offset; | 771 | to = end_offset; |
734 | error = write_empty_blocks(page, from, to); | 772 | error = write_empty_blocks(page, from, to, mode); |
735 | if (!error && offset + to > inode->i_size && | 773 | if (!error && offset + to > inode->i_size && |
736 | !(mode & FALLOC_FL_KEEP_SIZE)) { | 774 | !(mode & FALLOC_FL_KEEP_SIZE)) { |
737 | i_size_write(inode, offset + to); | 775 | i_size_write(inode, offset + to); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f07643e21bfa..7a4fb630a320 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -93,14 +93,12 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, | |||
93 | 93 | ||
94 | static inline void spin_lock_bucket(unsigned int hash) | 94 | static inline void spin_lock_bucket(unsigned int hash) |
95 | { | 95 | { |
96 | struct hlist_bl_head *bl = &gl_hash_table[hash]; | 96 | hlist_bl_lock(&gl_hash_table[hash]); |
97 | bit_spin_lock(0, (unsigned long *)bl); | ||
98 | } | 97 | } |
99 | 98 | ||
100 | static inline void spin_unlock_bucket(unsigned int hash) | 99 | static inline void spin_unlock_bucket(unsigned int hash) |
101 | { | 100 | { |
102 | struct hlist_bl_head *bl = &gl_hash_table[hash]; | 101 | hlist_bl_unlock(&gl_hash_table[hash]); |
103 | __bit_spin_unlock(0, (unsigned long *)bl); | ||
104 | } | 102 | } |
105 | 103 | ||
106 | static void gfs2_glock_dealloc(struct rcu_head *rcu) | 104 | static void gfs2_glock_dealloc(struct rcu_head *rcu) |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 3754e3cbf02b..25eeb2bcee47 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -385,6 +385,10 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) | |||
385 | static void iopen_go_callback(struct gfs2_glock *gl) | 385 | static void iopen_go_callback(struct gfs2_glock *gl) |
386 | { | 386 | { |
387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
388 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
389 | |||
390 | if (sdp->sd_vfs->s_flags & MS_RDONLY) | ||
391 | return; | ||
388 | 392 | ||
389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 393 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
390 | gl->gl_state == LM_ST_SHARED && ip) { | 394 | gl->gl_state == LM_ST_SHARED && ip) { |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 97d54a28776a..9134dcb89479 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -40,37 +40,61 @@ struct gfs2_inum_range_host { | |||
40 | u64 ir_length; | 40 | u64 ir_length; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | struct gfs2_skip_data { | ||
44 | u64 no_addr; | ||
45 | int skipped; | ||
46 | int non_block; | ||
47 | }; | ||
48 | |||
43 | static int iget_test(struct inode *inode, void *opaque) | 49 | static int iget_test(struct inode *inode, void *opaque) |
44 | { | 50 | { |
45 | struct gfs2_inode *ip = GFS2_I(inode); | 51 | struct gfs2_inode *ip = GFS2_I(inode); |
46 | u64 *no_addr = opaque; | 52 | struct gfs2_skip_data *data = opaque; |
47 | 53 | ||
48 | if (ip->i_no_addr == *no_addr) | 54 | if (ip->i_no_addr == data->no_addr) { |
55 | if (data->non_block && | ||
56 | inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { | ||
57 | data->skipped = 1; | ||
58 | return 0; | ||
59 | } | ||
49 | return 1; | 60 | return 1; |
50 | 61 | } | |
51 | return 0; | 62 | return 0; |
52 | } | 63 | } |
53 | 64 | ||
54 | static int iget_set(struct inode *inode, void *opaque) | 65 | static int iget_set(struct inode *inode, void *opaque) |
55 | { | 66 | { |
56 | struct gfs2_inode *ip = GFS2_I(inode); | 67 | struct gfs2_inode *ip = GFS2_I(inode); |
57 | u64 *no_addr = opaque; | 68 | struct gfs2_skip_data *data = opaque; |
58 | 69 | ||
59 | inode->i_ino = (unsigned long)*no_addr; | 70 | if (data->skipped) |
60 | ip->i_no_addr = *no_addr; | 71 | return -ENOENT; |
72 | inode->i_ino = (unsigned long)(data->no_addr); | ||
73 | ip->i_no_addr = data->no_addr; | ||
61 | return 0; | 74 | return 0; |
62 | } | 75 | } |
63 | 76 | ||
64 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) | 77 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) |
65 | { | 78 | { |
66 | unsigned long hash = (unsigned long)no_addr; | 79 | unsigned long hash = (unsigned long)no_addr; |
67 | return ilookup5(sb, hash, iget_test, &no_addr); | 80 | struct gfs2_skip_data data; |
81 | |||
82 | data.no_addr = no_addr; | ||
83 | data.skipped = 0; | ||
84 | data.non_block = 0; | ||
85 | return ilookup5(sb, hash, iget_test, &data); | ||
68 | } | 86 | } |
69 | 87 | ||
70 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | 88 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr, |
89 | int non_block) | ||
71 | { | 90 | { |
91 | struct gfs2_skip_data data; | ||
72 | unsigned long hash = (unsigned long)no_addr; | 92 | unsigned long hash = (unsigned long)no_addr; |
73 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); | 93 | |
94 | data.no_addr = no_addr; | ||
95 | data.skipped = 0; | ||
96 | data.non_block = non_block; | ||
97 | return iget5_locked(sb, hash, iget_test, iget_set, &data); | ||
74 | } | 98 | } |
75 | 99 | ||
76 | /** | 100 | /** |
@@ -111,19 +135,20 @@ static void gfs2_set_iop(struct inode *inode) | |||
111 | * @sb: The super block | 135 | * @sb: The super block |
112 | * @no_addr: The inode number | 136 | * @no_addr: The inode number |
113 | * @type: The type of the inode | 137 | * @type: The type of the inode |
138 | * non_block: Can we block on inodes that are being freed? | ||
114 | * | 139 | * |
115 | * Returns: A VFS inode, or an error | 140 | * Returns: A VFS inode, or an error |
116 | */ | 141 | */ |
117 | 142 | ||
118 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | 143 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, |
119 | u64 no_addr, u64 no_formal_ino) | 144 | u64 no_addr, u64 no_formal_ino, int non_block) |
120 | { | 145 | { |
121 | struct inode *inode; | 146 | struct inode *inode; |
122 | struct gfs2_inode *ip; | 147 | struct gfs2_inode *ip; |
123 | struct gfs2_glock *io_gl = NULL; | 148 | struct gfs2_glock *io_gl = NULL; |
124 | int error; | 149 | int error; |
125 | 150 | ||
126 | inode = gfs2_iget(sb, no_addr); | 151 | inode = gfs2_iget(sb, no_addr, non_block); |
127 | ip = GFS2_I(inode); | 152 | ip = GFS2_I(inode); |
128 | 153 | ||
129 | if (!inode) | 154 | if (!inode) |
@@ -185,11 +210,12 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
185 | { | 210 | { |
186 | struct super_block *sb = sdp->sd_vfs; | 211 | struct super_block *sb = sdp->sd_vfs; |
187 | struct gfs2_holder i_gh; | 212 | struct gfs2_holder i_gh; |
188 | struct inode *inode; | 213 | struct inode *inode = NULL; |
189 | int error; | 214 | int error; |
190 | 215 | ||
216 | /* Must not read in block until block type is verified */ | ||
191 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, | 217 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, |
192 | LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 218 | LM_ST_EXCLUSIVE, GL_SKIP, &i_gh); |
193 | if (error) | 219 | if (error) |
194 | return ERR_PTR(error); | 220 | return ERR_PTR(error); |
195 | 221 | ||
@@ -197,7 +223,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
197 | if (error) | 223 | if (error) |
198 | goto fail; | 224 | goto fail; |
199 | 225 | ||
200 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0); | 226 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1); |
201 | if (IS_ERR(inode)) | 227 | if (IS_ERR(inode)) |
202 | goto fail; | 228 | goto fail; |
203 | 229 | ||
@@ -843,7 +869,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
843 | goto fail_gunlock2; | 869 | goto fail_gunlock2; |
844 | 870 | ||
845 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, | 871 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, |
846 | inum.no_formal_ino); | 872 | inum.no_formal_ino, 0); |
847 | if (IS_ERR(inode)) | 873 | if (IS_ERR(inode)) |
848 | goto fail_gunlock2; | 874 | goto fail_gunlock2; |
849 | 875 | ||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 3e00a66e7cbd..099ca305e518 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -97,7 +97,8 @@ err: | |||
97 | } | 97 | } |
98 | 98 | ||
99 | extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, | 99 | extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, |
100 | u64 no_addr, u64 no_formal_ino); | 100 | u64 no_addr, u64 no_formal_ino, |
101 | int non_block); | ||
101 | extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | 102 | extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, |
102 | u64 *no_formal_ino, | 103 | u64 *no_formal_ino, |
103 | unsigned int blktype); | 104 | unsigned int blktype); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 42ef24355afb..d3c69eb91c74 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -430,7 +430,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr, | |||
430 | struct dentry *dentry; | 430 | struct dentry *dentry; |
431 | struct inode *inode; | 431 | struct inode *inode; |
432 | 432 | ||
433 | inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); | 433 | inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); |
434 | if (IS_ERR(inode)) { | 434 | if (IS_ERR(inode)) { |
435 | fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); | 435 | fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); |
436 | return PTR_ERR(inode); | 436 | return PTR_ERR(inode); |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index cf930cd9664a..6fcae8469f6d 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -945,7 +945,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip | |||
945 | /* rgblk_search can return a block < goal, so we need to | 945 | /* rgblk_search can return a block < goal, so we need to |
946 | keep it marching forward. */ | 946 | keep it marching forward. */ |
947 | no_addr = block + rgd->rd_data0; | 947 | no_addr = block + rgd->rd_data0; |
948 | goal++; | 948 | goal = max(block + 1, goal + 1); |
949 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) | 949 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
950 | continue; | 950 | continue; |
951 | if (no_addr == skip) | 951 | if (no_addr == skip) |
@@ -971,7 +971,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip | |||
971 | found++; | 971 | found++; |
972 | 972 | ||
973 | /* Limit reclaim to sensible number of tasks */ | 973 | /* Limit reclaim to sensible number of tasks */ |
974 | if (found > 2*NR_CPUS) | 974 | if (found > NR_CPUS) |
975 | return; | 975 | return; |
976 | } | 976 | } |
977 | 977 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a4e23d68a398..b9f28e66dad1 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -1318,15 +1318,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1318 | 1318 | ||
1319 | static void gfs2_evict_inode(struct inode *inode) | 1319 | static void gfs2_evict_inode(struct inode *inode) |
1320 | { | 1320 | { |
1321 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 1321 | struct super_block *sb = inode->i_sb; |
1322 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1322 | struct gfs2_inode *ip = GFS2_I(inode); | 1323 | struct gfs2_inode *ip = GFS2_I(inode); |
1323 | struct gfs2_holder gh; | 1324 | struct gfs2_holder gh; |
1324 | int error; | 1325 | int error; |
1325 | 1326 | ||
1326 | if (inode->i_nlink) | 1327 | if (inode->i_nlink || (sb->s_flags & MS_RDONLY)) |
1327 | goto out; | 1328 | goto out; |
1328 | 1329 | ||
1329 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1330 | /* Must not read inode block until block type has been verified */ |
1331 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); | ||
1330 | if (unlikely(error)) { | 1332 | if (unlikely(error)) { |
1331 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1333 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1332 | goto out; | 1334 | goto out; |
@@ -1336,6 +1338,12 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1336 | if (error) | 1338 | if (error) |
1337 | goto out_truncate; | 1339 | goto out_truncate; |
1338 | 1340 | ||
1341 | if (test_bit(GIF_INVALID, &ip->i_flags)) { | ||
1342 | error = gfs2_inode_refresh(ip); | ||
1343 | if (error) | ||
1344 | goto out_truncate; | ||
1345 | } | ||
1346 | |||
1339 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | 1347 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; |
1340 | gfs2_glock_dq_wait(&ip->i_iopen_gh); | 1348 | gfs2_glock_dq_wait(&ip->i_iopen_gh); |
1341 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); | 1349 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
diff --git a/fs/hpfs/Kconfig b/fs/hpfs/Kconfig index 0c39dc3ef7d7..56bd15c5bf6c 100644 --- a/fs/hpfs/Kconfig +++ b/fs/hpfs/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | config HPFS_FS | 1 | config HPFS_FS |
2 | tristate "OS/2 HPFS file system support" | 2 | tristate "OS/2 HPFS file system support" |
3 | depends on BLOCK | 3 | depends on BLOCK |
4 | depends on BROKEN || !PREEMPT | ||
5 | help | 4 | help |
6 | OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS | 5 | OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS |
7 | is the file system used for organizing files on OS/2 hard disk | 6 | is the file system used for organizing files on OS/2 hard disk |
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index 5503e2c28910..7a5eb2c718c8 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c | |||
@@ -8,8 +8,6 @@ | |||
8 | 8 | ||
9 | #include "hpfs_fn.h" | 9 | #include "hpfs_fn.h" |
10 | 10 | ||
11 | static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec); | ||
12 | |||
13 | /* | 11 | /* |
14 | * Check if a sector is allocated in bitmap | 12 | * Check if a sector is allocated in bitmap |
15 | * This is really slow. Turned on only if chk==2 | 13 | * This is really slow. Turned on only if chk==2 |
@@ -18,9 +16,9 @@ static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec); | |||
18 | static int chk_if_allocated(struct super_block *s, secno sec, char *msg) | 16 | static int chk_if_allocated(struct super_block *s, secno sec, char *msg) |
19 | { | 17 | { |
20 | struct quad_buffer_head qbh; | 18 | struct quad_buffer_head qbh; |
21 | unsigned *bmp; | 19 | u32 *bmp; |
22 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail; | 20 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail; |
23 | if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f)) & 1) { | 21 | if ((cpu_to_le32(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) { |
24 | hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec); | 22 | hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec); |
25 | goto fail1; | 23 | goto fail1; |
26 | } | 24 | } |
@@ -28,7 +26,7 @@ static int chk_if_allocated(struct super_block *s, secno sec, char *msg) | |||
28 | if (sec >= hpfs_sb(s)->sb_dirband_start && sec < hpfs_sb(s)->sb_dirband_start + hpfs_sb(s)->sb_dirband_size) { | 26 | if (sec >= hpfs_sb(s)->sb_dirband_start && sec < hpfs_sb(s)->sb_dirband_start + hpfs_sb(s)->sb_dirband_size) { |
29 | unsigned ssec = (sec - hpfs_sb(s)->sb_dirband_start) / 4; | 27 | unsigned ssec = (sec - hpfs_sb(s)->sb_dirband_start) / 4; |
30 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto fail; | 28 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) goto fail; |
31 | if ((bmp[ssec >> 5] >> (ssec & 0x1f)) & 1) { | 29 | if ((le32_to_cpu(bmp[ssec >> 5]) >> (ssec & 0x1f)) & 1) { |
32 | hpfs_error(s, "sector '%s' - %08x not allocated in directory bitmap", msg, sec); | 30 | hpfs_error(s, "sector '%s' - %08x not allocated in directory bitmap", msg, sec); |
33 | goto fail1; | 31 | goto fail1; |
34 | } | 32 | } |
@@ -75,7 +73,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne | |||
75 | hpfs_error(s, "Bad allocation size: %d", n); | 73 | hpfs_error(s, "Bad allocation size: %d", n); |
76 | return 0; | 74 | return 0; |
77 | } | 75 | } |
78 | lock_super(s); | ||
79 | if (bs != ~0x3fff) { | 76 | if (bs != ~0x3fff) { |
80 | if (!(bmp = hpfs_map_bitmap(s, near >> 14, &qbh, "aib"))) goto uls; | 77 | if (!(bmp = hpfs_map_bitmap(s, near >> 14, &qbh, "aib"))) goto uls; |
81 | } else { | 78 | } else { |
@@ -85,10 +82,6 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne | |||
85 | ret = bs + nr; | 82 | ret = bs + nr; |
86 | goto rt; | 83 | goto rt; |
87 | } | 84 | } |
88 | /*if (!tstbits(bmp, nr + n, n + forward)) { | ||
89 | ret = bs + nr + n; | ||
90 | goto rt; | ||
91 | }*/ | ||
92 | q = nr + n; b = 0; | 85 | q = nr + n; b = 0; |
93 | while ((a = tstbits(bmp, q, n + forward)) != 0) { | 86 | while ((a = tstbits(bmp, q, n + forward)) != 0) { |
94 | q += a; | 87 | q += a; |
@@ -105,14 +98,14 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne | |||
105 | goto rt; | 98 | goto rt; |
106 | } | 99 | } |
107 | nr >>= 5; | 100 | nr >>= 5; |
108 | /*for (i = nr + 1; i != nr; i++, i &= 0x1ff) {*/ | 101 | /*for (i = nr + 1; i != nr; i++, i &= 0x1ff) */ |
109 | i = nr; | 102 | i = nr; |
110 | do { | 103 | do { |
111 | if (!bmp[i]) goto cont; | 104 | if (!le32_to_cpu(bmp[i])) goto cont; |
112 | if (n + forward >= 0x3f && bmp[i] != -1) goto cont; | 105 | if (n + forward >= 0x3f && le32_to_cpu(bmp[i]) != 0xffffffff) goto cont; |
113 | q = i<<5; | 106 | q = i<<5; |
114 | if (i > 0) { | 107 | if (i > 0) { |
115 | unsigned k = bmp[i-1]; | 108 | unsigned k = le32_to_cpu(bmp[i-1]); |
116 | while (k & 0x80000000) { | 109 | while (k & 0x80000000) { |
117 | q--; k <<= 1; | 110 | q--; k <<= 1; |
118 | } | 111 | } |
@@ -132,18 +125,17 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne | |||
132 | } while (i != nr); | 125 | } while (i != nr); |
133 | rt: | 126 | rt: |
134 | if (ret) { | 127 | if (ret) { |
135 | if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (bmp[(ret & 0x3fff) >> 5] | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) { | 128 | if (hpfs_sb(s)->sb_chk && ((ret >> 14) != (bs >> 14) || (le32_to_cpu(bmp[(ret & 0x3fff) >> 5]) | ~(((1 << n) - 1) << (ret & 0x1f))) != 0xffffffff)) { |
136 | hpfs_error(s, "Allocation doesn't work! Wanted %d, allocated at %08x", n, ret); | 129 | hpfs_error(s, "Allocation doesn't work! Wanted %d, allocated at %08x", n, ret); |
137 | ret = 0; | 130 | ret = 0; |
138 | goto b; | 131 | goto b; |
139 | } | 132 | } |
140 | bmp[(ret & 0x3fff) >> 5] &= ~(((1 << n) - 1) << (ret & 0x1f)); | 133 | bmp[(ret & 0x3fff) >> 5] &= cpu_to_le32(~(((1 << n) - 1) << (ret & 0x1f))); |
141 | hpfs_mark_4buffers_dirty(&qbh); | 134 | hpfs_mark_4buffers_dirty(&qbh); |
142 | } | 135 | } |
143 | b: | 136 | b: |
144 | hpfs_brelse4(&qbh); | 137 | hpfs_brelse4(&qbh); |
145 | uls: | 138 | uls: |
146 | unlock_super(s); | ||
147 | return ret; | 139 | return ret; |
148 | } | 140 | } |
149 | 141 | ||
@@ -155,7 +147,7 @@ static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigne | |||
155 | * sectors | 147 | * sectors |
156 | */ | 148 | */ |
157 | 149 | ||
158 | secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward, int lock) | 150 | secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forward) |
159 | { | 151 | { |
160 | secno sec; | 152 | secno sec; |
161 | int i; | 153 | int i; |
@@ -167,7 +159,6 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa | |||
167 | forward = -forward; | 159 | forward = -forward; |
168 | f_p = 1; | 160 | f_p = 1; |
169 | } | 161 | } |
170 | if (lock) hpfs_lock_creation(s); | ||
171 | n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14; | 162 | n_bmps = (sbi->sb_fs_size + 0x4000 - 1) >> 14; |
172 | if (near && near < sbi->sb_fs_size) { | 163 | if (near && near < sbi->sb_fs_size) { |
173 | if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret; | 164 | if ((sec = alloc_in_bmp(s, near, n, f_p ? forward : forward/4))) goto ret; |
@@ -214,18 +205,17 @@ secno hpfs_alloc_sector(struct super_block *s, secno near, unsigned n, int forwa | |||
214 | ret: | 205 | ret: |
215 | if (sec && f_p) { | 206 | if (sec && f_p) { |
216 | for (i = 0; i < forward; i++) { | 207 | for (i = 0; i < forward; i++) { |
217 | if (!hpfs_alloc_if_possible_nolock(s, sec + i + 1)) { | 208 | if (!hpfs_alloc_if_possible(s, sec + i + 1)) { |
218 | hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i); | 209 | hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i); |
219 | sec = 0; | 210 | sec = 0; |
220 | break; | 211 | break; |
221 | } | 212 | } |
222 | } | 213 | } |
223 | } | 214 | } |
224 | if (lock) hpfs_unlock_creation(s); | ||
225 | return sec; | 215 | return sec; |
226 | } | 216 | } |
227 | 217 | ||
228 | static secno alloc_in_dirband(struct super_block *s, secno near, int lock) | 218 | static secno alloc_in_dirband(struct super_block *s, secno near) |
229 | { | 219 | { |
230 | unsigned nr = near; | 220 | unsigned nr = near; |
231 | secno sec; | 221 | secno sec; |
@@ -236,49 +226,35 @@ static secno alloc_in_dirband(struct super_block *s, secno near, int lock) | |||
236 | nr = sbi->sb_dirband_start + sbi->sb_dirband_size - 4; | 226 | nr = sbi->sb_dirband_start + sbi->sb_dirband_size - 4; |
237 | nr -= sbi->sb_dirband_start; | 227 | nr -= sbi->sb_dirband_start; |
238 | nr >>= 2; | 228 | nr >>= 2; |
239 | if (lock) hpfs_lock_creation(s); | ||
240 | sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0); | 229 | sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0); |
241 | if (lock) hpfs_unlock_creation(s); | ||
242 | if (!sec) return 0; | 230 | if (!sec) return 0; |
243 | return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start; | 231 | return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start; |
244 | } | 232 | } |
245 | 233 | ||
246 | /* Alloc sector if it's free */ | 234 | /* Alloc sector if it's free */ |
247 | 235 | ||
248 | static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec) | 236 | int hpfs_alloc_if_possible(struct super_block *s, secno sec) |
249 | { | 237 | { |
250 | struct quad_buffer_head qbh; | 238 | struct quad_buffer_head qbh; |
251 | unsigned *bmp; | 239 | u32 *bmp; |
252 | lock_super(s); | ||
253 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end; | 240 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end; |
254 | if (bmp[(sec & 0x3fff) >> 5] & (1 << (sec & 0x1f))) { | 241 | if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) { |
255 | bmp[(sec & 0x3fff) >> 5] &= ~(1 << (sec & 0x1f)); | 242 | bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f))); |
256 | hpfs_mark_4buffers_dirty(&qbh); | 243 | hpfs_mark_4buffers_dirty(&qbh); |
257 | hpfs_brelse4(&qbh); | 244 | hpfs_brelse4(&qbh); |
258 | unlock_super(s); | ||
259 | return 1; | 245 | return 1; |
260 | } | 246 | } |
261 | hpfs_brelse4(&qbh); | 247 | hpfs_brelse4(&qbh); |
262 | end: | 248 | end: |
263 | unlock_super(s); | ||
264 | return 0; | 249 | return 0; |
265 | } | 250 | } |
266 | 251 | ||
267 | int hpfs_alloc_if_possible(struct super_block *s, secno sec) | ||
268 | { | ||
269 | int r; | ||
270 | hpfs_lock_creation(s); | ||
271 | r = hpfs_alloc_if_possible_nolock(s, sec); | ||
272 | hpfs_unlock_creation(s); | ||
273 | return r; | ||
274 | } | ||
275 | |||
276 | /* Free sectors in bitmaps */ | 252 | /* Free sectors in bitmaps */ |
277 | 253 | ||
278 | void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) | 254 | void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) |
279 | { | 255 | { |
280 | struct quad_buffer_head qbh; | 256 | struct quad_buffer_head qbh; |
281 | unsigned *bmp; | 257 | u32 *bmp; |
282 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 258 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
283 | /*printk("2 - ");*/ | 259 | /*printk("2 - ");*/ |
284 | if (!n) return; | 260 | if (!n) return; |
@@ -286,26 +262,22 @@ void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) | |||
286 | hpfs_error(s, "Trying to free reserved sector %08x", sec); | 262 | hpfs_error(s, "Trying to free reserved sector %08x", sec); |
287 | return; | 263 | return; |
288 | } | 264 | } |
289 | lock_super(s); | ||
290 | sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n; | 265 | sbi->sb_max_fwd_alloc += n > 0xffff ? 0xffff : n; |
291 | if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff; | 266 | if (sbi->sb_max_fwd_alloc > 0xffffff) sbi->sb_max_fwd_alloc = 0xffffff; |
292 | new_map: | 267 | new_map: |
293 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) { | 268 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "free"))) { |
294 | unlock_super(s); | ||
295 | return; | 269 | return; |
296 | } | 270 | } |
297 | new_tst: | 271 | new_tst: |
298 | if ((bmp[(sec & 0x3fff) >> 5] >> (sec & 0x1f) & 1)) { | 272 | if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f) & 1)) { |
299 | hpfs_error(s, "sector %08x not allocated", sec); | 273 | hpfs_error(s, "sector %08x not allocated", sec); |
300 | hpfs_brelse4(&qbh); | 274 | hpfs_brelse4(&qbh); |
301 | unlock_super(s); | ||
302 | return; | 275 | return; |
303 | } | 276 | } |
304 | bmp[(sec & 0x3fff) >> 5] |= 1 << (sec & 0x1f); | 277 | bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f)); |
305 | if (!--n) { | 278 | if (!--n) { |
306 | hpfs_mark_4buffers_dirty(&qbh); | 279 | hpfs_mark_4buffers_dirty(&qbh); |
307 | hpfs_brelse4(&qbh); | 280 | hpfs_brelse4(&qbh); |
308 | unlock_super(s); | ||
309 | return; | 281 | return; |
310 | } | 282 | } |
311 | if (!(++sec & 0x3fff)) { | 283 | if (!(++sec & 0x3fff)) { |
@@ -327,13 +299,13 @@ int hpfs_check_free_dnodes(struct super_block *s, int n) | |||
327 | int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14; | 299 | int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14; |
328 | int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff; | 300 | int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff; |
329 | int i, j; | 301 | int i, j; |
330 | unsigned *bmp; | 302 | u32 *bmp; |
331 | struct quad_buffer_head qbh; | 303 | struct quad_buffer_head qbh; |
332 | if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) { | 304 | if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) { |
333 | for (j = 0; j < 512; j++) { | 305 | for (j = 0; j < 512; j++) { |
334 | unsigned k; | 306 | unsigned k; |
335 | if (!bmp[j]) continue; | 307 | if (!le32_to_cpu(bmp[j])) continue; |
336 | for (k = bmp[j]; k; k >>= 1) if (k & 1) if (!--n) { | 308 | for (k = le32_to_cpu(bmp[j]); k; k >>= 1) if (k & 1) if (!--n) { |
337 | hpfs_brelse4(&qbh); | 309 | hpfs_brelse4(&qbh); |
338 | return 0; | 310 | return 0; |
339 | } | 311 | } |
@@ -352,10 +324,10 @@ int hpfs_check_free_dnodes(struct super_block *s, int n) | |||
352 | chk_bmp: | 324 | chk_bmp: |
353 | if (bmp) { | 325 | if (bmp) { |
354 | for (j = 0; j < 512; j++) { | 326 | for (j = 0; j < 512; j++) { |
355 | unsigned k; | 327 | u32 k; |
356 | if (!bmp[j]) continue; | 328 | if (!le32_to_cpu(bmp[j])) continue; |
357 | for (k = 0xf; k; k <<= 4) | 329 | for (k = 0xf; k; k <<= 4) |
358 | if ((bmp[j] & k) == k) { | 330 | if ((le32_to_cpu(bmp[j]) & k) == k) { |
359 | if (!--n) { | 331 | if (!--n) { |
360 | hpfs_brelse4(&qbh); | 332 | hpfs_brelse4(&qbh); |
361 | return 0; | 333 | return 0; |
@@ -379,44 +351,40 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno) | |||
379 | hpfs_free_sectors(s, dno, 4); | 351 | hpfs_free_sectors(s, dno, 4); |
380 | } else { | 352 | } else { |
381 | struct quad_buffer_head qbh; | 353 | struct quad_buffer_head qbh; |
382 | unsigned *bmp; | 354 | u32 *bmp; |
383 | unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4; | 355 | unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4; |
384 | lock_super(s); | ||
385 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { | 356 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { |
386 | unlock_super(s); | ||
387 | return; | 357 | return; |
388 | } | 358 | } |
389 | bmp[ssec >> 5] |= 1 << (ssec & 0x1f); | 359 | bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f)); |
390 | hpfs_mark_4buffers_dirty(&qbh); | 360 | hpfs_mark_4buffers_dirty(&qbh); |
391 | hpfs_brelse4(&qbh); | 361 | hpfs_brelse4(&qbh); |
392 | unlock_super(s); | ||
393 | } | 362 | } |
394 | } | 363 | } |
395 | 364 | ||
396 | struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near, | 365 | struct dnode *hpfs_alloc_dnode(struct super_block *s, secno near, |
397 | dnode_secno *dno, struct quad_buffer_head *qbh, | 366 | dnode_secno *dno, struct quad_buffer_head *qbh) |
398 | int lock) | ||
399 | { | 367 | { |
400 | struct dnode *d; | 368 | struct dnode *d; |
401 | if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { | 369 | if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) { |
402 | if (!(*dno = alloc_in_dirband(s, near, lock))) | 370 | if (!(*dno = alloc_in_dirband(s, near))) |
403 | if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) return NULL; | 371 | if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL; |
404 | } else { | 372 | } else { |
405 | if (!(*dno = hpfs_alloc_sector(s, near, 4, 0, lock))) | 373 | if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) |
406 | if (!(*dno = alloc_in_dirband(s, near, lock))) return NULL; | 374 | if (!(*dno = alloc_in_dirband(s, near))) return NULL; |
407 | } | 375 | } |
408 | if (!(d = hpfs_get_4sectors(s, *dno, qbh))) { | 376 | if (!(d = hpfs_get_4sectors(s, *dno, qbh))) { |
409 | hpfs_free_dnode(s, *dno); | 377 | hpfs_free_dnode(s, *dno); |
410 | return NULL; | 378 | return NULL; |
411 | } | 379 | } |
412 | memset(d, 0, 2048); | 380 | memset(d, 0, 2048); |
413 | d->magic = DNODE_MAGIC; | 381 | d->magic = cpu_to_le32(DNODE_MAGIC); |
414 | d->first_free = 52; | 382 | d->first_free = cpu_to_le32(52); |
415 | d->dirent[0] = 32; | 383 | d->dirent[0] = 32; |
416 | d->dirent[2] = 8; | 384 | d->dirent[2] = 8; |
417 | d->dirent[30] = 1; | 385 | d->dirent[30] = 1; |
418 | d->dirent[31] = 255; | 386 | d->dirent[31] = 255; |
419 | d->self = *dno; | 387 | d->self = cpu_to_le32(*dno); |
420 | return d; | 388 | return d; |
421 | } | 389 | } |
422 | 390 | ||
@@ -424,16 +392,16 @@ struct fnode *hpfs_alloc_fnode(struct super_block *s, secno near, fnode_secno *f | |||
424 | struct buffer_head **bh) | 392 | struct buffer_head **bh) |
425 | { | 393 | { |
426 | struct fnode *f; | 394 | struct fnode *f; |
427 | if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD, 1))) return NULL; | 395 | if (!(*fno = hpfs_alloc_sector(s, near, 1, FNODE_ALLOC_FWD))) return NULL; |
428 | if (!(f = hpfs_get_sector(s, *fno, bh))) { | 396 | if (!(f = hpfs_get_sector(s, *fno, bh))) { |
429 | hpfs_free_sectors(s, *fno, 1); | 397 | hpfs_free_sectors(s, *fno, 1); |
430 | return NULL; | 398 | return NULL; |
431 | } | 399 | } |
432 | memset(f, 0, 512); | 400 | memset(f, 0, 512); |
433 | f->magic = FNODE_MAGIC; | 401 | f->magic = cpu_to_le32(FNODE_MAGIC); |
434 | f->ea_offs = 0xc4; | 402 | f->ea_offs = cpu_to_le16(0xc4); |
435 | f->btree.n_free_nodes = 8; | 403 | f->btree.n_free_nodes = 8; |
436 | f->btree.first_free = 8; | 404 | f->btree.first_free = cpu_to_le16(8); |
437 | return f; | 405 | return f; |
438 | } | 406 | } |
439 | 407 | ||
@@ -441,16 +409,16 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a | |||
441 | struct buffer_head **bh) | 409 | struct buffer_head **bh) |
442 | { | 410 | { |
443 | struct anode *a; | 411 | struct anode *a; |
444 | if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD, 1))) return NULL; | 412 | if (!(*ano = hpfs_alloc_sector(s, near, 1, ANODE_ALLOC_FWD))) return NULL; |
445 | if (!(a = hpfs_get_sector(s, *ano, bh))) { | 413 | if (!(a = hpfs_get_sector(s, *ano, bh))) { |
446 | hpfs_free_sectors(s, *ano, 1); | 414 | hpfs_free_sectors(s, *ano, 1); |
447 | return NULL; | 415 | return NULL; |
448 | } | 416 | } |
449 | memset(a, 0, 512); | 417 | memset(a, 0, 512); |
450 | a->magic = ANODE_MAGIC; | 418 | a->magic = cpu_to_le32(ANODE_MAGIC); |
451 | a->self = *ano; | 419 | a->self = cpu_to_le32(*ano); |
452 | a->btree.n_free_nodes = 40; | 420 | a->btree.n_free_nodes = 40; |
453 | a->btree.n_used_nodes = 0; | 421 | a->btree.n_used_nodes = 0; |
454 | a->btree.first_free = 8; | 422 | a->btree.first_free = cpu_to_le16(8); |
455 | return a; | 423 | return a; |
456 | } | 424 | } |
diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 6a2f04bf3df0..08b503e8ed29 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c | |||
@@ -22,8 +22,8 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode, | |||
22 | if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1; | 22 | if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1; |
23 | if (btree->internal) { | 23 | if (btree->internal) { |
24 | for (i = 0; i < btree->n_used_nodes; i++) | 24 | for (i = 0; i < btree->n_used_nodes; i++) |
25 | if (btree->u.internal[i].file_secno > sec) { | 25 | if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) { |
26 | a = btree->u.internal[i].down; | 26 | a = le32_to_cpu(btree->u.internal[i].down); |
27 | brelse(bh); | 27 | brelse(bh); |
28 | if (!(anode = hpfs_map_anode(s, a, &bh))) return -1; | 28 | if (!(anode = hpfs_map_anode(s, a, &bh))) return -1; |
29 | btree = &anode->btree; | 29 | btree = &anode->btree; |
@@ -34,18 +34,18 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode, | |||
34 | return -1; | 34 | return -1; |
35 | } | 35 | } |
36 | for (i = 0; i < btree->n_used_nodes; i++) | 36 | for (i = 0; i < btree->n_used_nodes; i++) |
37 | if (btree->u.external[i].file_secno <= sec && | 37 | if (le32_to_cpu(btree->u.external[i].file_secno) <= sec && |
38 | btree->u.external[i].file_secno + btree->u.external[i].length > sec) { | 38 | le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > sec) { |
39 | a = btree->u.external[i].disk_secno + sec - btree->u.external[i].file_secno; | 39 | a = le32_to_cpu(btree->u.external[i].disk_secno) + sec - le32_to_cpu(btree->u.external[i].file_secno); |
40 | if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, a, 1, "data")) { | 40 | if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, a, 1, "data")) { |
41 | brelse(bh); | 41 | brelse(bh); |
42 | return -1; | 42 | return -1; |
43 | } | 43 | } |
44 | if (inode) { | 44 | if (inode) { |
45 | struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); | 45 | struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); |
46 | hpfs_inode->i_file_sec = btree->u.external[i].file_secno; | 46 | hpfs_inode->i_file_sec = le32_to_cpu(btree->u.external[i].file_secno); |
47 | hpfs_inode->i_disk_sec = btree->u.external[i].disk_secno; | 47 | hpfs_inode->i_disk_sec = le32_to_cpu(btree->u.external[i].disk_secno); |
48 | hpfs_inode->i_n_secs = btree->u.external[i].length; | 48 | hpfs_inode->i_n_secs = le32_to_cpu(btree->u.external[i].length); |
49 | } | 49 | } |
50 | brelse(bh); | 50 | brelse(bh); |
51 | return a; | 51 | return a; |
@@ -83,8 +83,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
83 | return -1; | 83 | return -1; |
84 | } | 84 | } |
85 | if (btree->internal) { | 85 | if (btree->internal) { |
86 | a = btree->u.internal[n].down; | 86 | a = le32_to_cpu(btree->u.internal[n].down); |
87 | btree->u.internal[n].file_secno = -1; | 87 | btree->u.internal[n].file_secno = cpu_to_le32(-1); |
88 | mark_buffer_dirty(bh); | 88 | mark_buffer_dirty(bh); |
89 | brelse(bh); | 89 | brelse(bh); |
90 | if (hpfs_sb(s)->sb_chk) | 90 | if (hpfs_sb(s)->sb_chk) |
@@ -94,15 +94,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
94 | goto go_down; | 94 | goto go_down; |
95 | } | 95 | } |
96 | if (n >= 0) { | 96 | if (n >= 0) { |
97 | if (btree->u.external[n].file_secno + btree->u.external[n].length != fsecno) { | 97 | if (le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length) != fsecno) { |
98 | hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x", | 98 | hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x", |
99 | btree->u.external[n].file_secno + btree->u.external[n].length, fsecno, | 99 | le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length), fsecno, |
100 | fnod?'f':'a', node); | 100 | fnod?'f':'a', node); |
101 | brelse(bh); | 101 | brelse(bh); |
102 | return -1; | 102 | return -1; |
103 | } | 103 | } |
104 | if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) { | 104 | if (hpfs_alloc_if_possible(s, se = le32_to_cpu(btree->u.external[n].disk_secno) + le32_to_cpu(btree->u.external[n].length))) { |
105 | btree->u.external[n].length++; | 105 | btree->u.external[n].length = cpu_to_le32(le32_to_cpu(btree->u.external[n].length) + 1); |
106 | mark_buffer_dirty(bh); | 106 | mark_buffer_dirty(bh); |
107 | brelse(bh); | 107 | brelse(bh); |
108 | return se; | 108 | return se; |
@@ -115,20 +115,20 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
115 | } | 115 | } |
116 | se = !fnod ? node : (node + 16384) & ~16383; | 116 | se = !fnod ? node : (node + 16384) & ~16383; |
117 | } | 117 | } |
118 | if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) { | 118 | if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M))) { |
119 | brelse(bh); | 119 | brelse(bh); |
120 | return -1; | 120 | return -1; |
121 | } | 121 | } |
122 | fs = n < 0 ? 0 : btree->u.external[n].file_secno + btree->u.external[n].length; | 122 | fs = n < 0 ? 0 : le32_to_cpu(btree->u.external[n].file_secno) + le32_to_cpu(btree->u.external[n].length); |
123 | if (!btree->n_free_nodes) { | 123 | if (!btree->n_free_nodes) { |
124 | up = a != node ? anode->up : -1; | 124 | up = a != node ? le32_to_cpu(anode->up) : -1; |
125 | if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) { | 125 | if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) { |
126 | brelse(bh); | 126 | brelse(bh); |
127 | hpfs_free_sectors(s, se, 1); | 127 | hpfs_free_sectors(s, se, 1); |
128 | return -1; | 128 | return -1; |
129 | } | 129 | } |
130 | if (a == node && fnod) { | 130 | if (a == node && fnod) { |
131 | anode->up = node; | 131 | anode->up = cpu_to_le32(node); |
132 | anode->btree.fnode_parent = 1; | 132 | anode->btree.fnode_parent = 1; |
133 | anode->btree.n_used_nodes = btree->n_used_nodes; | 133 | anode->btree.n_used_nodes = btree->n_used_nodes; |
134 | anode->btree.first_free = btree->first_free; | 134 | anode->btree.first_free = btree->first_free; |
@@ -137,9 +137,9 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
137 | btree->internal = 1; | 137 | btree->internal = 1; |
138 | btree->n_free_nodes = 11; | 138 | btree->n_free_nodes = 11; |
139 | btree->n_used_nodes = 1; | 139 | btree->n_used_nodes = 1; |
140 | btree->first_free = (char *)&(btree->u.internal[1]) - (char *)btree; | 140 | btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree); |
141 | btree->u.internal[0].file_secno = -1; | 141 | btree->u.internal[0].file_secno = cpu_to_le32(-1); |
142 | btree->u.internal[0].down = na; | 142 | btree->u.internal[0].down = cpu_to_le32(na); |
143 | mark_buffer_dirty(bh); | 143 | mark_buffer_dirty(bh); |
144 | } else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) { | 144 | } else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) { |
145 | brelse(bh); | 145 | brelse(bh); |
@@ -153,15 +153,15 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
153 | btree = &anode->btree; | 153 | btree = &anode->btree; |
154 | } | 154 | } |
155 | btree->n_free_nodes--; n = btree->n_used_nodes++; | 155 | btree->n_free_nodes--; n = btree->n_used_nodes++; |
156 | btree->first_free += 12; | 156 | btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 12); |
157 | btree->u.external[n].disk_secno = se; | 157 | btree->u.external[n].disk_secno = cpu_to_le32(se); |
158 | btree->u.external[n].file_secno = fs; | 158 | btree->u.external[n].file_secno = cpu_to_le32(fs); |
159 | btree->u.external[n].length = 1; | 159 | btree->u.external[n].length = cpu_to_le32(1); |
160 | mark_buffer_dirty(bh); | 160 | mark_buffer_dirty(bh); |
161 | brelse(bh); | 161 | brelse(bh); |
162 | if ((a == node && fnod) || na == -1) return se; | 162 | if ((a == node && fnod) || na == -1) return se; |
163 | c2 = 0; | 163 | c2 = 0; |
164 | while (up != -1) { | 164 | while (up != (anode_secno)-1) { |
165 | struct anode *new_anode; | 165 | struct anode *new_anode; |
166 | if (hpfs_sb(s)->sb_chk) | 166 | if (hpfs_sb(s)->sb_chk) |
167 | if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1; | 167 | if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1; |
@@ -174,47 +174,47 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
174 | } | 174 | } |
175 | if (btree->n_free_nodes) { | 175 | if (btree->n_free_nodes) { |
176 | btree->n_free_nodes--; n = btree->n_used_nodes++; | 176 | btree->n_free_nodes--; n = btree->n_used_nodes++; |
177 | btree->first_free += 8; | 177 | btree->first_free = cpu_to_le16(le16_to_cpu(btree->first_free) + 8); |
178 | btree->u.internal[n].file_secno = -1; | 178 | btree->u.internal[n].file_secno = cpu_to_le32(-1); |
179 | btree->u.internal[n].down = na; | 179 | btree->u.internal[n].down = cpu_to_le32(na); |
180 | btree->u.internal[n-1].file_secno = fs; | 180 | btree->u.internal[n-1].file_secno = cpu_to_le32(fs); |
181 | mark_buffer_dirty(bh); | 181 | mark_buffer_dirty(bh); |
182 | brelse(bh); | 182 | brelse(bh); |
183 | brelse(bh2); | 183 | brelse(bh2); |
184 | hpfs_free_sectors(s, ra, 1); | 184 | hpfs_free_sectors(s, ra, 1); |
185 | if ((anode = hpfs_map_anode(s, na, &bh))) { | 185 | if ((anode = hpfs_map_anode(s, na, &bh))) { |
186 | anode->up = up; | 186 | anode->up = cpu_to_le32(up); |
187 | anode->btree.fnode_parent = up == node && fnod; | 187 | anode->btree.fnode_parent = up == node && fnod; |
188 | mark_buffer_dirty(bh); | 188 | mark_buffer_dirty(bh); |
189 | brelse(bh); | 189 | brelse(bh); |
190 | } | 190 | } |
191 | return se; | 191 | return se; |
192 | } | 192 | } |
193 | up = up != node ? anode->up : -1; | 193 | up = up != node ? le32_to_cpu(anode->up) : -1; |
194 | btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1; | 194 | btree->u.internal[btree->n_used_nodes - 1].file_secno = cpu_to_le32(/*fs*/-1); |
195 | mark_buffer_dirty(bh); | 195 | mark_buffer_dirty(bh); |
196 | brelse(bh); | 196 | brelse(bh); |
197 | a = na; | 197 | a = na; |
198 | if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { | 198 | if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { |
199 | anode = new_anode; | 199 | anode = new_anode; |
200 | /*anode->up = up != -1 ? up : ra;*/ | 200 | /*anode->up = cpu_to_le32(up != -1 ? up : ra);*/ |
201 | anode->btree.internal = 1; | 201 | anode->btree.internal = 1; |
202 | anode->btree.n_used_nodes = 1; | 202 | anode->btree.n_used_nodes = 1; |
203 | anode->btree.n_free_nodes = 59; | 203 | anode->btree.n_free_nodes = 59; |
204 | anode->btree.first_free = 16; | 204 | anode->btree.first_free = cpu_to_le16(16); |
205 | anode->btree.u.internal[0].down = a; | 205 | anode->btree.u.internal[0].down = cpu_to_le32(a); |
206 | anode->btree.u.internal[0].file_secno = -1; | 206 | anode->btree.u.internal[0].file_secno = cpu_to_le32(-1); |
207 | mark_buffer_dirty(bh); | 207 | mark_buffer_dirty(bh); |
208 | brelse(bh); | 208 | brelse(bh); |
209 | if ((anode = hpfs_map_anode(s, a, &bh))) { | 209 | if ((anode = hpfs_map_anode(s, a, &bh))) { |
210 | anode->up = na; | 210 | anode->up = cpu_to_le32(na); |
211 | mark_buffer_dirty(bh); | 211 | mark_buffer_dirty(bh); |
212 | brelse(bh); | 212 | brelse(bh); |
213 | } | 213 | } |
214 | } else na = a; | 214 | } else na = a; |
215 | } | 215 | } |
216 | if ((anode = hpfs_map_anode(s, na, &bh))) { | 216 | if ((anode = hpfs_map_anode(s, na, &bh))) { |
217 | anode->up = node; | 217 | anode->up = cpu_to_le32(node); |
218 | if (fnod) anode->btree.fnode_parent = 1; | 218 | if (fnod) anode->btree.fnode_parent = 1; |
219 | mark_buffer_dirty(bh); | 219 | mark_buffer_dirty(bh); |
220 | brelse(bh); | 220 | brelse(bh); |
@@ -232,14 +232,14 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
232 | } | 232 | } |
233 | btree = &fnode->btree; | 233 | btree = &fnode->btree; |
234 | } | 234 | } |
235 | ranode->up = node; | 235 | ranode->up = cpu_to_le32(node); |
236 | memcpy(&ranode->btree, btree, btree->first_free); | 236 | memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free)); |
237 | if (fnod) ranode->btree.fnode_parent = 1; | 237 | if (fnod) ranode->btree.fnode_parent = 1; |
238 | ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes; | 238 | ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes; |
239 | if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) { | 239 | if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) { |
240 | struct anode *unode; | 240 | struct anode *unode; |
241 | if ((unode = hpfs_map_anode(s, ranode->u.internal[n].down, &bh1))) { | 241 | if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) { |
242 | unode->up = ra; | 242 | unode->up = cpu_to_le32(ra); |
243 | unode->btree.fnode_parent = 0; | 243 | unode->btree.fnode_parent = 0; |
244 | mark_buffer_dirty(bh1); | 244 | mark_buffer_dirty(bh1); |
245 | brelse(bh1); | 245 | brelse(bh1); |
@@ -248,11 +248,11 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
248 | btree->internal = 1; | 248 | btree->internal = 1; |
249 | btree->n_free_nodes = fnod ? 10 : 58; | 249 | btree->n_free_nodes = fnod ? 10 : 58; |
250 | btree->n_used_nodes = 2; | 250 | btree->n_used_nodes = 2; |
251 | btree->first_free = (char *)&btree->u.internal[2] - (char *)btree; | 251 | btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree); |
252 | btree->u.internal[0].file_secno = fs; | 252 | btree->u.internal[0].file_secno = cpu_to_le32(fs); |
253 | btree->u.internal[0].down = ra; | 253 | btree->u.internal[0].down = cpu_to_le32(ra); |
254 | btree->u.internal[1].file_secno = -1; | 254 | btree->u.internal[1].file_secno = cpu_to_le32(-1); |
255 | btree->u.internal[1].down = na; | 255 | btree->u.internal[1].down = cpu_to_le32(na); |
256 | mark_buffer_dirty(bh); | 256 | mark_buffer_dirty(bh); |
257 | brelse(bh); | 257 | brelse(bh); |
258 | mark_buffer_dirty(bh2); | 258 | mark_buffer_dirty(bh2); |
@@ -279,7 +279,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) | |||
279 | go_down: | 279 | go_down: |
280 | d2 = 0; | 280 | d2 = 0; |
281 | while (btree1->internal) { | 281 | while (btree1->internal) { |
282 | ano = btree1->u.internal[pos].down; | 282 | ano = le32_to_cpu(btree1->u.internal[pos].down); |
283 | if (level) brelse(bh); | 283 | if (level) brelse(bh); |
284 | if (hpfs_sb(s)->sb_chk) | 284 | if (hpfs_sb(s)->sb_chk) |
285 | if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1")) | 285 | if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1")) |
@@ -290,7 +290,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) | |||
290 | pos = 0; | 290 | pos = 0; |
291 | } | 291 | } |
292 | for (i = 0; i < btree1->n_used_nodes; i++) | 292 | for (i = 0; i < btree1->n_used_nodes; i++) |
293 | hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length); | 293 | hpfs_free_sectors(s, le32_to_cpu(btree1->u.external[i].disk_secno), le32_to_cpu(btree1->u.external[i].length)); |
294 | go_up: | 294 | go_up: |
295 | if (!level) return; | 295 | if (!level) return; |
296 | brelse(bh); | 296 | brelse(bh); |
@@ -298,13 +298,13 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) | |||
298 | if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return; | 298 | if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return; |
299 | hpfs_free_sectors(s, ano, 1); | 299 | hpfs_free_sectors(s, ano, 1); |
300 | oano = ano; | 300 | oano = ano; |
301 | ano = anode->up; | 301 | ano = le32_to_cpu(anode->up); |
302 | if (--level) { | 302 | if (--level) { |
303 | if (!(anode = hpfs_map_anode(s, ano, &bh))) return; | 303 | if (!(anode = hpfs_map_anode(s, ano, &bh))) return; |
304 | btree1 = &anode->btree; | 304 | btree1 = &anode->btree; |
305 | } else btree1 = btree; | 305 | } else btree1 = btree; |
306 | for (i = 0; i < btree1->n_used_nodes; i++) { | 306 | for (i = 0; i < btree1->n_used_nodes; i++) { |
307 | if (btree1->u.internal[i].down == oano) { | 307 | if (le32_to_cpu(btree1->u.internal[i].down) == oano) { |
308 | if ((pos = i + 1) < btree1->n_used_nodes) | 308 | if ((pos = i + 1) < btree1->n_used_nodes) |
309 | goto go_down; | 309 | goto go_down; |
310 | else | 310 | else |
@@ -411,7 +411,7 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) | |||
411 | if (fno) { | 411 | if (fno) { |
412 | btree->n_free_nodes = 8; | 412 | btree->n_free_nodes = 8; |
413 | btree->n_used_nodes = 0; | 413 | btree->n_used_nodes = 0; |
414 | btree->first_free = 8; | 414 | btree->first_free = cpu_to_le16(8); |
415 | btree->internal = 0; | 415 | btree->internal = 0; |
416 | mark_buffer_dirty(bh); | 416 | mark_buffer_dirty(bh); |
417 | } else hpfs_free_sectors(s, f, 1); | 417 | } else hpfs_free_sectors(s, f, 1); |
@@ -421,22 +421,22 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) | |||
421 | while (btree->internal) { | 421 | while (btree->internal) { |
422 | nodes = btree->n_used_nodes + btree->n_free_nodes; | 422 | nodes = btree->n_used_nodes + btree->n_free_nodes; |
423 | for (i = 0; i < btree->n_used_nodes; i++) | 423 | for (i = 0; i < btree->n_used_nodes; i++) |
424 | if (btree->u.internal[i].file_secno >= secs) goto f; | 424 | if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f; |
425 | brelse(bh); | 425 | brelse(bh); |
426 | hpfs_error(s, "internal btree %08x doesn't end with -1", node); | 426 | hpfs_error(s, "internal btree %08x doesn't end with -1", node); |
427 | return; | 427 | return; |
428 | f: | 428 | f: |
429 | for (j = i + 1; j < btree->n_used_nodes; j++) | 429 | for (j = i + 1; j < btree->n_used_nodes; j++) |
430 | hpfs_ea_remove(s, btree->u.internal[j].down, 1, 0); | 430 | hpfs_ea_remove(s, le32_to_cpu(btree->u.internal[j].down), 1, 0); |
431 | btree->n_used_nodes = i + 1; | 431 | btree->n_used_nodes = i + 1; |
432 | btree->n_free_nodes = nodes - btree->n_used_nodes; | 432 | btree->n_free_nodes = nodes - btree->n_used_nodes; |
433 | btree->first_free = 8 + 8 * btree->n_used_nodes; | 433 | btree->first_free = cpu_to_le16(8 + 8 * btree->n_used_nodes); |
434 | mark_buffer_dirty(bh); | 434 | mark_buffer_dirty(bh); |
435 | if (btree->u.internal[i].file_secno == secs) { | 435 | if (btree->u.internal[i].file_secno == cpu_to_le32(secs)) { |
436 | brelse(bh); | 436 | brelse(bh); |
437 | return; | 437 | return; |
438 | } | 438 | } |
439 | node = btree->u.internal[i].down; | 439 | node = le32_to_cpu(btree->u.internal[i].down); |
440 | brelse(bh); | 440 | brelse(bh); |
441 | if (hpfs_sb(s)->sb_chk) | 441 | if (hpfs_sb(s)->sb_chk) |
442 | if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree")) | 442 | if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree")) |
@@ -446,25 +446,25 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) | |||
446 | } | 446 | } |
447 | nodes = btree->n_used_nodes + btree->n_free_nodes; | 447 | nodes = btree->n_used_nodes + btree->n_free_nodes; |
448 | for (i = 0; i < btree->n_used_nodes; i++) | 448 | for (i = 0; i < btree->n_used_nodes; i++) |
449 | if (btree->u.external[i].file_secno + btree->u.external[i].length >= secs) goto ff; | 449 | if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) >= secs) goto ff; |
450 | brelse(bh); | 450 | brelse(bh); |
451 | return; | 451 | return; |
452 | ff: | 452 | ff: |
453 | if (secs <= btree->u.external[i].file_secno) { | 453 | if (secs <= le32_to_cpu(btree->u.external[i].file_secno)) { |
454 | hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs); | 454 | hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs); |
455 | if (i) i--; | 455 | if (i) i--; |
456 | } | 456 | } |
457 | else if (btree->u.external[i].file_secno + btree->u.external[i].length > secs) { | 457 | else if (le32_to_cpu(btree->u.external[i].file_secno) + le32_to_cpu(btree->u.external[i].length) > secs) { |
458 | hpfs_free_sectors(s, btree->u.external[i].disk_secno + secs - | 458 | hpfs_free_sectors(s, le32_to_cpu(btree->u.external[i].disk_secno) + secs - |
459 | btree->u.external[i].file_secno, btree->u.external[i].length | 459 | le32_to_cpu(btree->u.external[i].file_secno), le32_to_cpu(btree->u.external[i].length) |
460 | - secs + btree->u.external[i].file_secno); /* I hope gcc optimizes this :-) */ | 460 | - secs + le32_to_cpu(btree->u.external[i].file_secno)); /* I hope gcc optimizes this :-) */ |
461 | btree->u.external[i].length = secs - btree->u.external[i].file_secno; | 461 | btree->u.external[i].length = cpu_to_le32(secs - le32_to_cpu(btree->u.external[i].file_secno)); |
462 | } | 462 | } |
463 | for (j = i + 1; j < btree->n_used_nodes; j++) | 463 | for (j = i + 1; j < btree->n_used_nodes; j++) |
464 | hpfs_free_sectors(s, btree->u.external[j].disk_secno, btree->u.external[j].length); | 464 | hpfs_free_sectors(s, le32_to_cpu(btree->u.external[j].disk_secno), le32_to_cpu(btree->u.external[j].length)); |
465 | btree->n_used_nodes = i + 1; | 465 | btree->n_used_nodes = i + 1; |
466 | btree->n_free_nodes = nodes - btree->n_used_nodes; | 466 | btree->n_free_nodes = nodes - btree->n_used_nodes; |
467 | btree->first_free = 8 + 12 * btree->n_used_nodes; | 467 | btree->first_free = cpu_to_le16(8 + 12 * btree->n_used_nodes); |
468 | mark_buffer_dirty(bh); | 468 | mark_buffer_dirty(bh); |
469 | brelse(bh); | 469 | brelse(bh); |
470 | } | 470 | } |
@@ -480,12 +480,12 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno) | |||
480 | struct extended_attribute *ea_end; | 480 | struct extended_attribute *ea_end; |
481 | if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return; | 481 | if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return; |
482 | if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree); | 482 | if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree); |
483 | else hpfs_remove_dtree(s, fnode->u.external[0].disk_secno); | 483 | else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno)); |
484 | ea_end = fnode_end_ea(fnode); | 484 | ea_end = fnode_end_ea(fnode); |
485 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 485 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
486 | if (ea->indirect) | 486 | if (ea->indirect) |
487 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); | 487 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); |
488 | hpfs_ea_ext_remove(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l); | 488 | hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l)); |
489 | brelse(bh); | 489 | brelse(bh); |
490 | hpfs_free_sectors(s, fno, 1); | 490 | hpfs_free_sectors(s, fno, 1); |
491 | } | 491 | } |
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 793cb9d943d2..9ecde27d1e29 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c | |||
@@ -9,22 +9,6 @@ | |||
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include "hpfs_fn.h" | 10 | #include "hpfs_fn.h" |
11 | 11 | ||
12 | void hpfs_lock_creation(struct super_block *s) | ||
13 | { | ||
14 | #ifdef DEBUG_LOCKS | ||
15 | printk("lock creation\n"); | ||
16 | #endif | ||
17 | mutex_lock(&hpfs_sb(s)->hpfs_creation_de); | ||
18 | } | ||
19 | |||
20 | void hpfs_unlock_creation(struct super_block *s) | ||
21 | { | ||
22 | #ifdef DEBUG_LOCKS | ||
23 | printk("unlock creation\n"); | ||
24 | #endif | ||
25 | mutex_unlock(&hpfs_sb(s)->hpfs_creation_de); | ||
26 | } | ||
27 | |||
28 | /* Map a sector into a buffer and return pointers to it and to the buffer. */ | 12 | /* Map a sector into a buffer and return pointers to it and to the buffer. */ |
29 | 13 | ||
30 | void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp, | 14 | void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp, |
@@ -32,6 +16,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
32 | { | 16 | { |
33 | struct buffer_head *bh; | 17 | struct buffer_head *bh; |
34 | 18 | ||
19 | hpfs_lock_assert(s); | ||
20 | |||
35 | cond_resched(); | 21 | cond_resched(); |
36 | 22 | ||
37 | *bhp = bh = sb_bread(s, secno); | 23 | *bhp = bh = sb_bread(s, secno); |
@@ -50,6 +36,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head | |||
50 | struct buffer_head *bh; | 36 | struct buffer_head *bh; |
51 | /*return hpfs_map_sector(s, secno, bhp, 0);*/ | 37 | /*return hpfs_map_sector(s, secno, bhp, 0);*/ |
52 | 38 | ||
39 | hpfs_lock_assert(s); | ||
40 | |||
53 | cond_resched(); | 41 | cond_resched(); |
54 | 42 | ||
55 | if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { | 43 | if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { |
@@ -70,6 +58,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe | |||
70 | struct buffer_head *bh; | 58 | struct buffer_head *bh; |
71 | char *data; | 59 | char *data; |
72 | 60 | ||
61 | hpfs_lock_assert(s); | ||
62 | |||
73 | cond_resched(); | 63 | cond_resched(); |
74 | 64 | ||
75 | if (secno & 3) { | 65 | if (secno & 3) { |
@@ -125,6 +115,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno, | |||
125 | { | 115 | { |
126 | cond_resched(); | 116 | cond_resched(); |
127 | 117 | ||
118 | hpfs_lock_assert(s); | ||
119 | |||
128 | if (secno & 3) { | 120 | if (secno & 3) { |
129 | printk("HPFS: hpfs_get_4sectors: unaligned read\n"); | 121 | printk("HPFS: hpfs_get_4sectors: unaligned read\n"); |
130 | return NULL; | 122 | return NULL; |
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index b3d7c0ddb609..f46ae025bfb5 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
@@ -88,9 +88,9 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
88 | hpfs_error(inode->i_sb, "not a directory, fnode %08lx", | 88 | hpfs_error(inode->i_sb, "not a directory, fnode %08lx", |
89 | (unsigned long)inode->i_ino); | 89 | (unsigned long)inode->i_ino); |
90 | } | 90 | } |
91 | if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) { | 91 | if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) { |
92 | e = 1; | 92 | e = 1; |
93 | hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, fno->u.external[0].disk_secno); | 93 | hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno)); |
94 | } | 94 | } |
95 | brelse(bh); | 95 | brelse(bh); |
96 | if (e) { | 96 | if (e) { |
@@ -156,7 +156,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
156 | goto again; | 156 | goto again; |
157 | } | 157 | } |
158 | tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); | 158 | tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); |
159 | if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) { | 159 | if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) { |
160 | filp->f_pos = old_pos; | 160 | filp->f_pos = old_pos; |
161 | if (tempname != de->name) kfree(tempname); | 161 | if (tempname != de->name) kfree(tempname); |
162 | hpfs_brelse4(&qbh); | 162 | hpfs_brelse4(&qbh); |
@@ -221,7 +221,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
221 | * Get inode number, what we're after. | 221 | * Get inode number, what we're after. |
222 | */ | 222 | */ |
223 | 223 | ||
224 | ino = de->fnode; | 224 | ino = le32_to_cpu(de->fnode); |
225 | 225 | ||
226 | /* | 226 | /* |
227 | * Go find or make an inode. | 227 | * Go find or make an inode. |
@@ -236,7 +236,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
236 | hpfs_init_inode(result); | 236 | hpfs_init_inode(result); |
237 | if (de->directory) | 237 | if (de->directory) |
238 | hpfs_read_inode(result); | 238 | hpfs_read_inode(result); |
239 | else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas) | 239 | else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas) |
240 | hpfs_read_inode(result); | 240 | hpfs_read_inode(result); |
241 | else { | 241 | else { |
242 | result->i_mode |= S_IFREG; | 242 | result->i_mode |= S_IFREG; |
@@ -250,8 +250,6 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
250 | hpfs_result = hpfs_i(result); | 250 | hpfs_result = hpfs_i(result); |
251 | if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; | 251 | if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; |
252 | 252 | ||
253 | hpfs_decide_conv(result, name, len); | ||
254 | |||
255 | if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) { | 253 | if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) { |
256 | hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures"); | 254 | hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures"); |
257 | goto bail1; | 255 | goto bail1; |
@@ -263,19 +261,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
263 | */ | 261 | */ |
264 | 262 | ||
265 | if (!result->i_ctime.tv_sec) { | 263 | if (!result->i_ctime.tv_sec) { |
266 | if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date))) | 264 | if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date)))) |
267 | result->i_ctime.tv_sec = 1; | 265 | result->i_ctime.tv_sec = 1; |
268 | result->i_ctime.tv_nsec = 0; | 266 | result->i_ctime.tv_nsec = 0; |
269 | result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date); | 267 | result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date)); |
270 | result->i_mtime.tv_nsec = 0; | 268 | result->i_mtime.tv_nsec = 0; |
271 | result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date); | 269 | result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date)); |
272 | result->i_atime.tv_nsec = 0; | 270 | result->i_atime.tv_nsec = 0; |
273 | hpfs_result->i_ea_size = de->ea_size; | 271 | hpfs_result->i_ea_size = le32_to_cpu(de->ea_size); |
274 | if (!hpfs_result->i_ea_mode && de->read_only) | 272 | if (!hpfs_result->i_ea_mode && de->read_only) |
275 | result->i_mode &= ~0222; | 273 | result->i_mode &= ~0222; |
276 | if (!de->directory) { | 274 | if (!de->directory) { |
277 | if (result->i_size == -1) { | 275 | if (result->i_size == -1) { |
278 | result->i_size = de->file_size; | 276 | result->i_size = le32_to_cpu(de->file_size); |
279 | result->i_data.a_ops = &hpfs_aops; | 277 | result->i_data.a_ops = &hpfs_aops; |
280 | hpfs_i(result)->mmu_private = result->i_size; | 278 | hpfs_i(result)->mmu_private = result->i_size; |
281 | /* | 279 | /* |
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 9b2ffadfc8c4..1e0e2ac30fd3 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c | |||
@@ -14,11 +14,11 @@ static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde) | |||
14 | struct hpfs_dirent *de_end = dnode_end_de(d); | 14 | struct hpfs_dirent *de_end = dnode_end_de(d); |
15 | int i = 1; | 15 | int i = 1; |
16 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { | 16 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { |
17 | if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i; | 17 | if (de == fde) return ((loff_t) le32_to_cpu(d->self) << 4) | (loff_t)i; |
18 | i++; | 18 | i++; |
19 | } | 19 | } |
20 | printk("HPFS: get_pos: not_found\n"); | 20 | printk("HPFS: get_pos: not_found\n"); |
21 | return ((loff_t)d->self << 4) | (loff_t)1; | 21 | return ((loff_t)le32_to_cpu(d->self) << 4) | (loff_t)1; |
22 | } | 22 | } |
23 | 23 | ||
24 | void hpfs_add_pos(struct inode *inode, loff_t *pos) | 24 | void hpfs_add_pos(struct inode *inode, loff_t *pos) |
@@ -130,29 +130,30 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno | |||
130 | { | 130 | { |
131 | struct hpfs_dirent *de; | 131 | struct hpfs_dirent *de; |
132 | if (!(de = dnode_last_de(d))) { | 132 | if (!(de = dnode_last_de(d))) { |
133 | hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self); | 133 | hpfs_error(s, "set_last_pointer: empty dnode %08x", le32_to_cpu(d->self)); |
134 | return; | 134 | return; |
135 | } | 135 | } |
136 | if (hpfs_sb(s)->sb_chk) { | 136 | if (hpfs_sb(s)->sb_chk) { |
137 | if (de->down) { | 137 | if (de->down) { |
138 | hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x", | 138 | hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x", |
139 | d->self, de_down_pointer(de)); | 139 | le32_to_cpu(d->self), de_down_pointer(de)); |
140 | return; | 140 | return; |
141 | } | 141 | } |
142 | if (de->length != 32) { | 142 | if (le16_to_cpu(de->length) != 32) { |
143 | hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self); | 143 | hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", le32_to_cpu(d->self)); |
144 | return; | 144 | return; |
145 | } | 145 | } |
146 | } | 146 | } |
147 | if (ptr) { | 147 | if (ptr) { |
148 | if ((d->first_free += 4) > 2048) { | 148 | d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + 4); |
149 | hpfs_error(s,"set_last_pointer: too long dnode %08x", d->self); | 149 | if (le32_to_cpu(d->first_free) > 2048) { |
150 | d->first_free -= 4; | 150 | hpfs_error(s, "set_last_pointer: too long dnode %08x", le32_to_cpu(d->self)); |
151 | d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - 4); | ||
151 | return; | 152 | return; |
152 | } | 153 | } |
153 | de->length = 36; | 154 | de->length = cpu_to_le16(36); |
154 | de->down = 1; | 155 | de->down = 1; |
155 | *(dnode_secno *)((char *)de + 32) = ptr; | 156 | *(dnode_secno *)((char *)de + 32) = cpu_to_le32(ptr); |
156 | } | 157 | } |
157 | } | 158 | } |
158 | 159 | ||
@@ -168,7 +169,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, | |||
168 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { | 169 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) { |
169 | int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last); | 170 | int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last); |
170 | if (!c) { | 171 | if (!c) { |
171 | hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self); | 172 | hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, le32_to_cpu(d->self)); |
172 | return NULL; | 173 | return NULL; |
173 | } | 174 | } |
174 | if (c < 0) break; | 175 | if (c < 0) break; |
@@ -176,15 +177,14 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, | |||
176 | memmove((char *)de + d_size, de, (char *)de_end - (char *)de); | 177 | memmove((char *)de + d_size, de, (char *)de_end - (char *)de); |
177 | memset(de, 0, d_size); | 178 | memset(de, 0, d_size); |
178 | if (down_ptr) { | 179 | if (down_ptr) { |
179 | *(int *)((char *)de + d_size - 4) = down_ptr; | 180 | *(dnode_secno *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr); |
180 | de->down = 1; | 181 | de->down = 1; |
181 | } | 182 | } |
182 | de->length = d_size; | 183 | de->length = cpu_to_le16(d_size); |
183 | if (down_ptr) de->down = 1; | ||
184 | de->not_8x3 = hpfs_is_name_long(name, namelen); | 184 | de->not_8x3 = hpfs_is_name_long(name, namelen); |
185 | de->namelen = namelen; | 185 | de->namelen = namelen; |
186 | memcpy(de->name, name, namelen); | 186 | memcpy(de->name, name, namelen); |
187 | d->first_free += d_size; | 187 | d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + d_size); |
188 | return de; | 188 | return de; |
189 | } | 189 | } |
190 | 190 | ||
@@ -194,25 +194,25 @@ static void hpfs_delete_de(struct super_block *s, struct dnode *d, | |||
194 | struct hpfs_dirent *de) | 194 | struct hpfs_dirent *de) |
195 | { | 195 | { |
196 | if (de->last) { | 196 | if (de->last) { |
197 | hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self); | 197 | hpfs_error(s, "attempt to delete last dirent in dnode %08x", le32_to_cpu(d->self)); |
198 | return; | 198 | return; |
199 | } | 199 | } |
200 | d->first_free -= de->length; | 200 | d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - le16_to_cpu(de->length)); |
201 | memmove(de, de_next_de(de), d->first_free + (char *)d - (char *)de); | 201 | memmove(de, de_next_de(de), le32_to_cpu(d->first_free) + (char *)d - (char *)de); |
202 | } | 202 | } |
203 | 203 | ||
204 | static void fix_up_ptrs(struct super_block *s, struct dnode *d) | 204 | static void fix_up_ptrs(struct super_block *s, struct dnode *d) |
205 | { | 205 | { |
206 | struct hpfs_dirent *de; | 206 | struct hpfs_dirent *de; |
207 | struct hpfs_dirent *de_end = dnode_end_de(d); | 207 | struct hpfs_dirent *de_end = dnode_end_de(d); |
208 | dnode_secno dno = d->self; | 208 | dnode_secno dno = le32_to_cpu(d->self); |
209 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) | 209 | for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) |
210 | if (de->down) { | 210 | if (de->down) { |
211 | struct quad_buffer_head qbh; | 211 | struct quad_buffer_head qbh; |
212 | struct dnode *dd; | 212 | struct dnode *dd; |
213 | if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) { | 213 | if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) { |
214 | if (dd->up != dno || dd->root_dnode) { | 214 | if (le32_to_cpu(dd->up) != dno || dd->root_dnode) { |
215 | dd->up = dno; | 215 | dd->up = cpu_to_le32(dno); |
216 | dd->root_dnode = 0; | 216 | dd->root_dnode = 0; |
217 | hpfs_mark_4buffers_dirty(&qbh); | 217 | hpfs_mark_4buffers_dirty(&qbh); |
218 | } | 218 | } |
@@ -262,7 +262,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
262 | kfree(nname); | 262 | kfree(nname); |
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
265 | if (d->first_free + de_size(namelen, down_ptr) <= 2048) { | 265 | if (le32_to_cpu(d->first_free) + de_size(namelen, down_ptr) <= 2048) { |
266 | loff_t t; | 266 | loff_t t; |
267 | copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de); | 267 | copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de); |
268 | t = get_pos(d, de); | 268 | t = get_pos(d, de); |
@@ -286,11 +286,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
286 | kfree(nname); | 286 | kfree(nname); |
287 | return 1; | 287 | return 1; |
288 | } | 288 | } |
289 | memcpy(nd, d, d->first_free); | 289 | memcpy(nd, d, le32_to_cpu(d->first_free)); |
290 | copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de); | 290 | copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de); |
291 | for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1); | 291 | for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1); |
292 | h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10; | 292 | h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10; |
293 | if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1, 0))) { | 293 | if (!(ad = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &adno, &qbh1))) { |
294 | hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); | 294 | hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); |
295 | hpfs_brelse4(&qbh); | 295 | hpfs_brelse4(&qbh); |
296 | kfree(nd); | 296 | kfree(nd); |
@@ -313,20 +313,21 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
313 | down_ptr = adno; | 313 | down_ptr = adno; |
314 | set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0); | 314 | set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0); |
315 | de = de_next_de(de); | 315 | de = de_next_de(de); |
316 | memmove((char *)nd + 20, de, nd->first_free + (char *)nd - (char *)de); | 316 | memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de); |
317 | nd->first_free -= (char *)de - (char *)nd - 20; | 317 | nd->first_free = cpu_to_le32(le32_to_cpu(nd->first_free) - ((char *)de - (char *)nd - 20)); |
318 | memcpy(d, nd, nd->first_free); | 318 | memcpy(d, nd, le32_to_cpu(nd->first_free)); |
319 | for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos); | 319 | for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos); |
320 | fix_up_ptrs(i->i_sb, ad); | 320 | fix_up_ptrs(i->i_sb, ad); |
321 | if (!d->root_dnode) { | 321 | if (!d->root_dnode) { |
322 | dno = ad->up = d->up; | 322 | ad->up = d->up; |
323 | dno = le32_to_cpu(ad->up); | ||
323 | hpfs_mark_4buffers_dirty(&qbh); | 324 | hpfs_mark_4buffers_dirty(&qbh); |
324 | hpfs_brelse4(&qbh); | 325 | hpfs_brelse4(&qbh); |
325 | hpfs_mark_4buffers_dirty(&qbh1); | 326 | hpfs_mark_4buffers_dirty(&qbh1); |
326 | hpfs_brelse4(&qbh1); | 327 | hpfs_brelse4(&qbh1); |
327 | goto go_up; | 328 | goto go_up; |
328 | } | 329 | } |
329 | if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2, 0))) { | 330 | if (!(rd = hpfs_alloc_dnode(i->i_sb, le32_to_cpu(d->up), &rdno, &qbh2))) { |
330 | hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); | 331 | hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted"); |
331 | hpfs_brelse4(&qbh); | 332 | hpfs_brelse4(&qbh); |
332 | hpfs_brelse4(&qbh1); | 333 | hpfs_brelse4(&qbh1); |
@@ -338,7 +339,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
338 | i->i_blocks += 4; | 339 | i->i_blocks += 4; |
339 | rd->root_dnode = 1; | 340 | rd->root_dnode = 1; |
340 | rd->up = d->up; | 341 | rd->up = d->up; |
341 | if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) { | 342 | if (!(fnode = hpfs_map_fnode(i->i_sb, le32_to_cpu(d->up), &bh))) { |
342 | hpfs_free_dnode(i->i_sb, rdno); | 343 | hpfs_free_dnode(i->i_sb, rdno); |
343 | hpfs_brelse4(&qbh); | 344 | hpfs_brelse4(&qbh); |
344 | hpfs_brelse4(&qbh1); | 345 | hpfs_brelse4(&qbh1); |
@@ -347,10 +348,11 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
347 | kfree(nname); | 348 | kfree(nname); |
348 | return 1; | 349 | return 1; |
349 | } | 350 | } |
350 | fnode->u.external[0].disk_secno = rdno; | 351 | fnode->u.external[0].disk_secno = cpu_to_le32(rdno); |
351 | mark_buffer_dirty(bh); | 352 | mark_buffer_dirty(bh); |
352 | brelse(bh); | 353 | brelse(bh); |
353 | d->up = ad->up = hpfs_i(i)->i_dno = rdno; | 354 | hpfs_i(i)->i_dno = rdno; |
355 | d->up = ad->up = cpu_to_le32(rdno); | ||
354 | d->root_dnode = ad->root_dnode = 0; | 356 | d->root_dnode = ad->root_dnode = 0; |
355 | hpfs_mark_4buffers_dirty(&qbh); | 357 | hpfs_mark_4buffers_dirty(&qbh); |
356 | hpfs_brelse4(&qbh); | 358 | hpfs_brelse4(&qbh); |
@@ -373,7 +375,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, | |||
373 | 375 | ||
374 | int hpfs_add_dirent(struct inode *i, | 376 | int hpfs_add_dirent(struct inode *i, |
375 | const unsigned char *name, unsigned namelen, | 377 | const unsigned char *name, unsigned namelen, |
376 | struct hpfs_dirent *new_de, int cdepth) | 378 | struct hpfs_dirent *new_de) |
377 | { | 379 | { |
378 | struct hpfs_inode_info *hpfs_inode = hpfs_i(i); | 380 | struct hpfs_inode_info *hpfs_inode = hpfs_i(i); |
379 | struct dnode *d; | 381 | struct dnode *d; |
@@ -403,7 +405,6 @@ int hpfs_add_dirent(struct inode *i, | |||
403 | } | 405 | } |
404 | } | 406 | } |
405 | hpfs_brelse4(&qbh); | 407 | hpfs_brelse4(&qbh); |
406 | if (!cdepth) hpfs_lock_creation(i->i_sb); | ||
407 | if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) { | 408 | if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) { |
408 | c = 1; | 409 | c = 1; |
409 | goto ret; | 410 | goto ret; |
@@ -411,7 +412,6 @@ int hpfs_add_dirent(struct inode *i, | |||
411 | i->i_version++; | 412 | i->i_version++; |
412 | c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0); | 413 | c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0); |
413 | ret: | 414 | ret: |
414 | if (!cdepth) hpfs_unlock_creation(i->i_sb); | ||
415 | return c; | 415 | return c; |
416 | } | 416 | } |
417 | 417 | ||
@@ -437,9 +437,9 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) | |||
437 | return 0; | 437 | return 0; |
438 | if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0; | 438 | if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0; |
439 | if (hpfs_sb(i->i_sb)->sb_chk) { | 439 | if (hpfs_sb(i->i_sb)->sb_chk) { |
440 | if (dnode->up != chk_up) { | 440 | if (le32_to_cpu(dnode->up) != chk_up) { |
441 | hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x", | 441 | hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x", |
442 | dno, chk_up, dnode->up); | 442 | dno, chk_up, le32_to_cpu(dnode->up)); |
443 | hpfs_brelse4(&qbh); | 443 | hpfs_brelse4(&qbh); |
444 | return 0; | 444 | return 0; |
445 | } | 445 | } |
@@ -455,7 +455,7 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) | |||
455 | hpfs_brelse4(&qbh); | 455 | hpfs_brelse4(&qbh); |
456 | } | 456 | } |
457 | while (!(de = dnode_pre_last_de(dnode))) { | 457 | while (!(de = dnode_pre_last_de(dnode))) { |
458 | dnode_secno up = dnode->up; | 458 | dnode_secno up = le32_to_cpu(dnode->up); |
459 | hpfs_brelse4(&qbh); | 459 | hpfs_brelse4(&qbh); |
460 | hpfs_free_dnode(i->i_sb, dno); | 460 | hpfs_free_dnode(i->i_sb, dno); |
461 | i->i_size -= 2048; | 461 | i->i_size -= 2048; |
@@ -474,8 +474,8 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) | |||
474 | hpfs_brelse4(&qbh); | 474 | hpfs_brelse4(&qbh); |
475 | return 0; | 475 | return 0; |
476 | } | 476 | } |
477 | dnode->first_free -= 4; | 477 | dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4); |
478 | de->length -= 4; | 478 | de->length = cpu_to_le16(le16_to_cpu(de->length) - 4); |
479 | de->down = 0; | 479 | de->down = 0; |
480 | hpfs_mark_4buffers_dirty(&qbh); | 480 | hpfs_mark_4buffers_dirty(&qbh); |
481 | dno = up; | 481 | dno = up; |
@@ -483,12 +483,12 @@ static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to) | |||
483 | t = get_pos(dnode, de); | 483 | t = get_pos(dnode, de); |
484 | for_all_poss(i, hpfs_pos_subst, t, 4); | 484 | for_all_poss(i, hpfs_pos_subst, t, 4); |
485 | for_all_poss(i, hpfs_pos_subst, t + 1, 5); | 485 | for_all_poss(i, hpfs_pos_subst, t + 1, 5); |
486 | if (!(nde = kmalloc(de->length, GFP_NOFS))) { | 486 | if (!(nde = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) { |
487 | hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted"); | 487 | hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted"); |
488 | hpfs_brelse4(&qbh); | 488 | hpfs_brelse4(&qbh); |
489 | return 0; | 489 | return 0; |
490 | } | 490 | } |
491 | memcpy(nde, de, de->length); | 491 | memcpy(nde, de, le16_to_cpu(de->length)); |
492 | ddno = de->down ? de_down_pointer(de) : 0; | 492 | ddno = de->down ? de_down_pointer(de) : 0; |
493 | hpfs_delete_de(i->i_sb, dnode, de); | 493 | hpfs_delete_de(i->i_sb, dnode, de); |
494 | set_last_pointer(i->i_sb, dnode, ddno); | 494 | set_last_pointer(i->i_sb, dnode, ddno); |
@@ -517,11 +517,11 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
517 | try_it_again: | 517 | try_it_again: |
518 | if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return; | 518 | if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return; |
519 | if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return; | 519 | if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return; |
520 | if (dnode->first_free > 56) goto end; | 520 | if (le32_to_cpu(dnode->first_free) > 56) goto end; |
521 | if (dnode->first_free == 52 || dnode->first_free == 56) { | 521 | if (le32_to_cpu(dnode->first_free) == 52 || le32_to_cpu(dnode->first_free) == 56) { |
522 | struct hpfs_dirent *de_end; | 522 | struct hpfs_dirent *de_end; |
523 | int root = dnode->root_dnode; | 523 | int root = dnode->root_dnode; |
524 | up = dnode->up; | 524 | up = le32_to_cpu(dnode->up); |
525 | de = dnode_first_de(dnode); | 525 | de = dnode_first_de(dnode); |
526 | down = de->down ? de_down_pointer(de) : 0; | 526 | down = de->down ? de_down_pointer(de) : 0; |
527 | if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) { | 527 | if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) { |
@@ -545,13 +545,13 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
545 | return; | 545 | return; |
546 | } | 546 | } |
547 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { | 547 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { |
548 | d1->up = up; | 548 | d1->up = cpu_to_le32(up); |
549 | d1->root_dnode = 1; | 549 | d1->root_dnode = 1; |
550 | hpfs_mark_4buffers_dirty(&qbh1); | 550 | hpfs_mark_4buffers_dirty(&qbh1); |
551 | hpfs_brelse4(&qbh1); | 551 | hpfs_brelse4(&qbh1); |
552 | } | 552 | } |
553 | if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) { | 553 | if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) { |
554 | fnode->u.external[0].disk_secno = down; | 554 | fnode->u.external[0].disk_secno = cpu_to_le32(down); |
555 | mark_buffer_dirty(bh); | 555 | mark_buffer_dirty(bh); |
556 | brelse(bh); | 556 | brelse(bh); |
557 | } | 557 | } |
@@ -570,22 +570,22 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
570 | for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p); | 570 | for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p); |
571 | if (!down) { | 571 | if (!down) { |
572 | de->down = 0; | 572 | de->down = 0; |
573 | de->length -= 4; | 573 | de->length = cpu_to_le16(le16_to_cpu(de->length) - 4); |
574 | dnode->first_free -= 4; | 574 | dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4); |
575 | memmove(de_next_de(de), (char *)de_next_de(de) + 4, | 575 | memmove(de_next_de(de), (char *)de_next_de(de) + 4, |
576 | (char *)dnode + dnode->first_free - (char *)de_next_de(de)); | 576 | (char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de)); |
577 | } else { | 577 | } else { |
578 | struct dnode *d1; | 578 | struct dnode *d1; |
579 | struct quad_buffer_head qbh1; | 579 | struct quad_buffer_head qbh1; |
580 | *(dnode_secno *) ((void *) de + de->length - 4) = down; | 580 | *(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4) = down; |
581 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { | 581 | if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) { |
582 | d1->up = up; | 582 | d1->up = cpu_to_le32(up); |
583 | hpfs_mark_4buffers_dirty(&qbh1); | 583 | hpfs_mark_4buffers_dirty(&qbh1); |
584 | hpfs_brelse4(&qbh1); | 584 | hpfs_brelse4(&qbh1); |
585 | } | 585 | } |
586 | } | 586 | } |
587 | } else { | 587 | } else { |
588 | hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, dnode->first_free); | 588 | hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, le32_to_cpu(dnode->first_free)); |
589 | goto end; | 589 | goto end; |
590 | } | 590 | } |
591 | 591 | ||
@@ -596,18 +596,18 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
596 | struct quad_buffer_head qbh1; | 596 | struct quad_buffer_head qbh1; |
597 | if (!de_next->down) goto endm; | 597 | if (!de_next->down) goto endm; |
598 | ndown = de_down_pointer(de_next); | 598 | ndown = de_down_pointer(de_next); |
599 | if (!(de_cp = kmalloc(de->length, GFP_NOFS))) { | 599 | if (!(de_cp = kmalloc(le16_to_cpu(de->length), GFP_NOFS))) { |
600 | printk("HPFS: out of memory for dtree balancing\n"); | 600 | printk("HPFS: out of memory for dtree balancing\n"); |
601 | goto endm; | 601 | goto endm; |
602 | } | 602 | } |
603 | memcpy(de_cp, de, de->length); | 603 | memcpy(de_cp, de, le16_to_cpu(de->length)); |
604 | hpfs_delete_de(i->i_sb, dnode, de); | 604 | hpfs_delete_de(i->i_sb, dnode, de); |
605 | hpfs_mark_4buffers_dirty(&qbh); | 605 | hpfs_mark_4buffers_dirty(&qbh); |
606 | hpfs_brelse4(&qbh); | 606 | hpfs_brelse4(&qbh); |
607 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4); | 607 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4); |
608 | for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1); | 608 | for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1); |
609 | if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) { | 609 | if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) { |
610 | d1->up = ndown; | 610 | d1->up = cpu_to_le32(ndown); |
611 | hpfs_mark_4buffers_dirty(&qbh1); | 611 | hpfs_mark_4buffers_dirty(&qbh1); |
612 | hpfs_brelse4(&qbh1); | 612 | hpfs_brelse4(&qbh1); |
613 | } | 613 | } |
@@ -635,7 +635,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
635 | struct hpfs_dirent *del = dnode_last_de(d1); | 635 | struct hpfs_dirent *del = dnode_last_de(d1); |
636 | dlp = del->down ? de_down_pointer(del) : 0; | 636 | dlp = del->down ? de_down_pointer(del) : 0; |
637 | if (!dlp && down) { | 637 | if (!dlp && down) { |
638 | if (d1->first_free > 2044) { | 638 | if (le32_to_cpu(d1->first_free) > 2044) { |
639 | if (hpfs_sb(i->i_sb)->sb_chk >= 2) { | 639 | if (hpfs_sb(i->i_sb)->sb_chk >= 2) { |
640 | printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); | 640 | printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); |
641 | printk("HPFS: warning: terminating balancing operation\n"); | 641 | printk("HPFS: warning: terminating balancing operation\n"); |
@@ -647,38 +647,38 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
647 | printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); | 647 | printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n"); |
648 | printk("HPFS: warning: goin'on\n"); | 648 | printk("HPFS: warning: goin'on\n"); |
649 | } | 649 | } |
650 | del->length += 4; | 650 | del->length = cpu_to_le16(le16_to_cpu(del->length) + 4); |
651 | del->down = 1; | 651 | del->down = 1; |
652 | d1->first_free += 4; | 652 | d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) + 4); |
653 | } | 653 | } |
654 | if (dlp && !down) { | 654 | if (dlp && !down) { |
655 | del->length -= 4; | 655 | del->length = cpu_to_le16(le16_to_cpu(del->length) - 4); |
656 | del->down = 0; | 656 | del->down = 0; |
657 | d1->first_free -= 4; | 657 | d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4); |
658 | } else if (down) | 658 | } else if (down) |
659 | *(dnode_secno *) ((void *) del + del->length - 4) = down; | 659 | *(dnode_secno *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down); |
660 | } else goto endm; | 660 | } else goto endm; |
661 | if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) { | 661 | if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) { |
662 | printk("HPFS: out of memory for dtree balancing\n"); | 662 | printk("HPFS: out of memory for dtree balancing\n"); |
663 | hpfs_brelse4(&qbh1); | 663 | hpfs_brelse4(&qbh1); |
664 | goto endm; | 664 | goto endm; |
665 | } | 665 | } |
666 | hpfs_mark_4buffers_dirty(&qbh1); | 666 | hpfs_mark_4buffers_dirty(&qbh1); |
667 | hpfs_brelse4(&qbh1); | 667 | hpfs_brelse4(&qbh1); |
668 | memcpy(de_cp, de_prev, de_prev->length); | 668 | memcpy(de_cp, de_prev, le16_to_cpu(de_prev->length)); |
669 | hpfs_delete_de(i->i_sb, dnode, de_prev); | 669 | hpfs_delete_de(i->i_sb, dnode, de_prev); |
670 | if (!de_prev->down) { | 670 | if (!de_prev->down) { |
671 | de_prev->length += 4; | 671 | de_prev->length = cpu_to_le16(le16_to_cpu(de_prev->length) + 4); |
672 | de_prev->down = 1; | 672 | de_prev->down = 1; |
673 | dnode->first_free += 4; | 673 | dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4); |
674 | } | 674 | } |
675 | *(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown; | 675 | *(dnode_secno *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown); |
676 | hpfs_mark_4buffers_dirty(&qbh); | 676 | hpfs_mark_4buffers_dirty(&qbh); |
677 | hpfs_brelse4(&qbh); | 677 | hpfs_brelse4(&qbh); |
678 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4); | 678 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4); |
679 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1)); | 679 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1)); |
680 | if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) { | 680 | if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) { |
681 | d1->up = ndown; | 681 | d1->up = cpu_to_le32(ndown); |
682 | hpfs_mark_4buffers_dirty(&qbh1); | 682 | hpfs_mark_4buffers_dirty(&qbh1); |
683 | hpfs_brelse4(&qbh1); | 683 | hpfs_brelse4(&qbh1); |
684 | } | 684 | } |
@@ -701,7 +701,6 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de, | |||
701 | { | 701 | { |
702 | struct dnode *dnode = qbh->data; | 702 | struct dnode *dnode = qbh->data; |
703 | dnode_secno down = 0; | 703 | dnode_secno down = 0; |
704 | int lock = 0; | ||
705 | loff_t t; | 704 | loff_t t; |
706 | if (de->first || de->last) { | 705 | if (de->first || de->last) { |
707 | hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno); | 706 | hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno); |
@@ -710,11 +709,8 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de, | |||
710 | } | 709 | } |
711 | if (de->down) down = de_down_pointer(de); | 710 | if (de->down) down = de_down_pointer(de); |
712 | if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) { | 711 | if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) { |
713 | lock = 1; | ||
714 | hpfs_lock_creation(i->i_sb); | ||
715 | if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) { | 712 | if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) { |
716 | hpfs_brelse4(qbh); | 713 | hpfs_brelse4(qbh); |
717 | hpfs_unlock_creation(i->i_sb); | ||
718 | return 2; | 714 | return 2; |
719 | } | 715 | } |
720 | } | 716 | } |
@@ -727,11 +723,9 @@ int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de, | |||
727 | dnode_secno a = move_to_top(i, down, dno); | 723 | dnode_secno a = move_to_top(i, down, dno); |
728 | for_all_poss(i, hpfs_pos_subst, 5, t); | 724 | for_all_poss(i, hpfs_pos_subst, 5, t); |
729 | if (a) delete_empty_dnode(i, a); | 725 | if (a) delete_empty_dnode(i, a); |
730 | if (lock) hpfs_unlock_creation(i->i_sb); | ||
731 | return !a; | 726 | return !a; |
732 | } | 727 | } |
733 | delete_empty_dnode(i, dno); | 728 | delete_empty_dnode(i, dno); |
734 | if (lock) hpfs_unlock_creation(i->i_sb); | ||
735 | return 0; | 729 | return 0; |
736 | } | 730 | } |
737 | 731 | ||
@@ -751,8 +745,8 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes, | |||
751 | ptr = 0; | 745 | ptr = 0; |
752 | go_up: | 746 | go_up: |
753 | if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return; | 747 | if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return; |
754 | if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno) | 748 | if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && le32_to_cpu(dnode->up) != odno) |
755 | hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up); | 749 | hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, le32_to_cpu(dnode->up)); |
756 | de = dnode_first_de(dnode); | 750 | de = dnode_first_de(dnode); |
757 | if (ptr) while(1) { | 751 | if (ptr) while(1) { |
758 | if (de->down) if (de_down_pointer(de) == ptr) goto process_de; | 752 | if (de->down) if (de_down_pointer(de) == ptr) goto process_de; |
@@ -776,7 +770,7 @@ void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes, | |||
776 | if (!de->first && !de->last && n_items) (*n_items)++; | 770 | if (!de->first && !de->last && n_items) (*n_items)++; |
777 | if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de; | 771 | if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de; |
778 | ptr = dno; | 772 | ptr = dno; |
779 | dno = dnode->up; | 773 | dno = le32_to_cpu(dnode->up); |
780 | if (dnode->root_dnode) { | 774 | if (dnode->root_dnode) { |
781 | hpfs_brelse4(&qbh); | 775 | hpfs_brelse4(&qbh); |
782 | return; | 776 | return; |
@@ -824,8 +818,8 @@ dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno) | |||
824 | return d; | 818 | return d; |
825 | if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno; | 819 | if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno; |
826 | if (hpfs_sb(s)->sb_chk) | 820 | if (hpfs_sb(s)->sb_chk) |
827 | if (up && ((struct dnode *)qbh.data)->up != up) | 821 | if (up && le32_to_cpu(((struct dnode *)qbh.data)->up) != up) |
828 | hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up); | 822 | hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, le32_to_cpu(((struct dnode *)qbh.data)->up)); |
829 | if (!de->down) { | 823 | if (!de->down) { |
830 | hpfs_brelse4(&qbh); | 824 | hpfs_brelse4(&qbh); |
831 | return d; | 825 | return d; |
@@ -874,7 +868,7 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp, | |||
874 | /* Going up */ | 868 | /* Going up */ |
875 | if (dnode->root_dnode) goto bail; | 869 | if (dnode->root_dnode) goto bail; |
876 | 870 | ||
877 | if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0))) | 871 | if (!(up_dnode = hpfs_map_dnode(inode->i_sb, le32_to_cpu(dnode->up), &qbh0))) |
878 | goto bail; | 872 | goto bail; |
879 | 873 | ||
880 | end_up_de = dnode_end_de(up_dnode); | 874 | end_up_de = dnode_end_de(up_dnode); |
@@ -882,16 +876,16 @@ struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp, | |||
882 | for (up_de = dnode_first_de(up_dnode); up_de < end_up_de; | 876 | for (up_de = dnode_first_de(up_dnode); up_de < end_up_de; |
883 | up_de = de_next_de(up_de)) { | 877 | up_de = de_next_de(up_de)) { |
884 | if (!(++c & 077)) hpfs_error(inode->i_sb, | 878 | if (!(++c & 077)) hpfs_error(inode->i_sb, |
885 | "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up); | 879 | "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", le32_to_cpu(dnode->up)); |
886 | if (up_de->down && de_down_pointer(up_de) == dno) { | 880 | if (up_de->down && de_down_pointer(up_de) == dno) { |
887 | *posp = ((loff_t) dnode->up << 4) + c; | 881 | *posp = ((loff_t) le32_to_cpu(dnode->up) << 4) + c; |
888 | hpfs_brelse4(&qbh0); | 882 | hpfs_brelse4(&qbh0); |
889 | return de; | 883 | return de; |
890 | } | 884 | } |
891 | } | 885 | } |
892 | 886 | ||
893 | hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x", | 887 | hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x", |
894 | dno, dnode->up); | 888 | dno, le32_to_cpu(dnode->up)); |
895 | hpfs_brelse4(&qbh0); | 889 | hpfs_brelse4(&qbh0); |
896 | 890 | ||
897 | bail: | 891 | bail: |
@@ -1017,17 +1011,17 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
1017 | /*name2[15] = 0xff;*/ | 1011 | /*name2[15] = 0xff;*/ |
1018 | name1len = 15; name2len = 256; | 1012 | name1len = 15; name2len = 256; |
1019 | } | 1013 | } |
1020 | if (!(upf = hpfs_map_fnode(s, f->up, &bh))) { | 1014 | if (!(upf = hpfs_map_fnode(s, le32_to_cpu(f->up), &bh))) { |
1021 | kfree(name2); | 1015 | kfree(name2); |
1022 | return NULL; | 1016 | return NULL; |
1023 | } | 1017 | } |
1024 | if (!upf->dirflag) { | 1018 | if (!upf->dirflag) { |
1025 | brelse(bh); | 1019 | brelse(bh); |
1026 | hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up); | 1020 | hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up)); |
1027 | kfree(name2); | 1021 | kfree(name2); |
1028 | return NULL; | 1022 | return NULL; |
1029 | } | 1023 | } |
1030 | dno = upf->u.external[0].disk_secno; | 1024 | dno = le32_to_cpu(upf->u.external[0].disk_secno); |
1031 | brelse(bh); | 1025 | brelse(bh); |
1032 | go_down: | 1026 | go_down: |
1033 | downd = 0; | 1027 | downd = 0; |
@@ -1049,7 +1043,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
1049 | return NULL; | 1043 | return NULL; |
1050 | } | 1044 | } |
1051 | next_de: | 1045 | next_de: |
1052 | if (de->fnode == fno) { | 1046 | if (le32_to_cpu(de->fnode) == fno) { |
1053 | kfree(name2); | 1047 | kfree(name2); |
1054 | return de; | 1048 | return de; |
1055 | } | 1049 | } |
@@ -1065,7 +1059,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
1065 | goto go_down; | 1059 | goto go_down; |
1066 | } | 1060 | } |
1067 | f: | 1061 | f: |
1068 | if (de->fnode == fno) { | 1062 | if (le32_to_cpu(de->fnode) == fno) { |
1069 | kfree(name2); | 1063 | kfree(name2); |
1070 | return de; | 1064 | return de; |
1071 | } | 1065 | } |
@@ -1074,7 +1068,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
1074 | if ((de = de_next_de(de)) < de_end) goto next_de; | 1068 | if ((de = de_next_de(de)) < de_end) goto next_de; |
1075 | if (d->root_dnode) goto not_found; | 1069 | if (d->root_dnode) goto not_found; |
1076 | downd = dno; | 1070 | downd = dno; |
1077 | dno = d->up; | 1071 | dno = le32_to_cpu(d->up); |
1078 | hpfs_brelse4(qbh); | 1072 | hpfs_brelse4(qbh); |
1079 | if (hpfs_sb(s)->sb_chk) | 1073 | if (hpfs_sb(s)->sb_chk) |
1080 | if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) { | 1074 | if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) { |
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index 45e53d972b42..d8b84d113c89 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c | |||
@@ -24,7 +24,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) | |||
24 | } | 24 | } |
25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; | 25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; |
26 | if (ea->indirect) { | 26 | if (ea->indirect) { |
27 | if (ea->valuelen != 8) { | 27 | if (ea_valuelen(ea) != 8) { |
28 | hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", | 28 | hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", |
29 | ano ? "anode" : "sectors", a, pos); | 29 | ano ? "anode" : "sectors", a, pos); |
30 | return; | 30 | return; |
@@ -33,7 +33,7 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) | |||
33 | return; | 33 | return; |
34 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); | 34 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); |
35 | } | 35 | } |
36 | pos += ea->namelen + ea->valuelen + 5; | 36 | pos += ea->namelen + ea_valuelen(ea) + 5; |
37 | } | 37 | } |
38 | if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9); | 38 | if (!ano) hpfs_free_sectors(s, a, (len+511) >> 9); |
39 | else { | 39 | else { |
@@ -76,24 +76,24 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
76 | unsigned pos; | 76 | unsigned pos; |
77 | int ano, len; | 77 | int ano, len; |
78 | secno a; | 78 | secno a; |
79 | char ex[4 + 255 + 1 + 8]; | ||
79 | struct extended_attribute *ea; | 80 | struct extended_attribute *ea; |
80 | struct extended_attribute *ea_end = fnode_end_ea(fnode); | 81 | struct extended_attribute *ea_end = fnode_end_ea(fnode); |
81 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 82 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
82 | if (!strcmp(ea->name, key)) { | 83 | if (!strcmp(ea->name, key)) { |
83 | if (ea->indirect) | 84 | if (ea->indirect) |
84 | goto indirect; | 85 | goto indirect; |
85 | if (ea->valuelen >= size) | 86 | if (ea_valuelen(ea) >= size) |
86 | return -EINVAL; | 87 | return -EINVAL; |
87 | memcpy(buf, ea_data(ea), ea->valuelen); | 88 | memcpy(buf, ea_data(ea), ea_valuelen(ea)); |
88 | buf[ea->valuelen] = 0; | 89 | buf[ea_valuelen(ea)] = 0; |
89 | return 0; | 90 | return 0; |
90 | } | 91 | } |
91 | a = fnode->ea_secno; | 92 | a = le32_to_cpu(fnode->ea_secno); |
92 | len = fnode->ea_size_l; | 93 | len = le32_to_cpu(fnode->ea_size_l); |
93 | ano = fnode->ea_anode; | 94 | ano = fnode->ea_anode; |
94 | pos = 0; | 95 | pos = 0; |
95 | while (pos < len) { | 96 | while (pos < len) { |
96 | char ex[4 + 255 + 1 + 8]; | ||
97 | ea = (struct extended_attribute *)ex; | 97 | ea = (struct extended_attribute *)ex; |
98 | if (pos + 4 > len) { | 98 | if (pos + 4 > len) { |
99 | hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", | 99 | hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x", |
@@ -106,14 +106,14 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
106 | if (!strcmp(ea->name, key)) { | 106 | if (!strcmp(ea->name, key)) { |
107 | if (ea->indirect) | 107 | if (ea->indirect) |
108 | goto indirect; | 108 | goto indirect; |
109 | if (ea->valuelen >= size) | 109 | if (ea_valuelen(ea) >= size) |
110 | return -EINVAL; | 110 | return -EINVAL; |
111 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf)) | 111 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), buf)) |
112 | return -EIO; | 112 | return -EIO; |
113 | buf[ea->valuelen] = 0; | 113 | buf[ea_valuelen(ea)] = 0; |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | pos += ea->namelen + ea->valuelen + 5; | 116 | pos += ea->namelen + ea_valuelen(ea) + 5; |
117 | } | 117 | } |
118 | return -ENOENT; | 118 | return -ENOENT; |
119 | indirect: | 119 | indirect: |
@@ -138,16 +138,16 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
138 | if (!strcmp(ea->name, key)) { | 138 | if (!strcmp(ea->name, key)) { |
139 | if (ea->indirect) | 139 | if (ea->indirect) |
140 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 140 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); |
141 | if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { | 141 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
142 | printk("HPFS: out of memory for EA\n"); | 142 | printk("HPFS: out of memory for EA\n"); |
143 | return NULL; | 143 | return NULL; |
144 | } | 144 | } |
145 | memcpy(ret, ea_data(ea), ea->valuelen); | 145 | memcpy(ret, ea_data(ea), ea_valuelen(ea)); |
146 | ret[ea->valuelen] = 0; | 146 | ret[ea_valuelen(ea)] = 0; |
147 | return ret; | 147 | return ret; |
148 | } | 148 | } |
149 | a = fnode->ea_secno; | 149 | a = le32_to_cpu(fnode->ea_secno); |
150 | len = fnode->ea_size_l; | 150 | len = le32_to_cpu(fnode->ea_size_l); |
151 | ano = fnode->ea_anode; | 151 | ano = fnode->ea_anode; |
152 | pos = 0; | 152 | pos = 0; |
153 | while (pos < len) { | 153 | while (pos < len) { |
@@ -164,18 +164,18 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
164 | if (!strcmp(ea->name, key)) { | 164 | if (!strcmp(ea->name, key)) { |
165 | if (ea->indirect) | 165 | if (ea->indirect) |
166 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 166 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); |
167 | if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) { | 167 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
168 | printk("HPFS: out of memory for EA\n"); | 168 | printk("HPFS: out of memory for EA\n"); |
169 | return NULL; | 169 | return NULL; |
170 | } | 170 | } |
171 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, ret)) { | 171 | if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea_valuelen(ea), ret)) { |
172 | kfree(ret); | 172 | kfree(ret); |
173 | return NULL; | 173 | return NULL; |
174 | } | 174 | } |
175 | ret[ea->valuelen] = 0; | 175 | ret[ea_valuelen(ea)] = 0; |
176 | return ret; | 176 | return ret; |
177 | } | 177 | } |
178 | pos += ea->namelen + ea->valuelen + 5; | 178 | pos += ea->namelen + ea_valuelen(ea) + 5; |
179 | } | 179 | } |
180 | return NULL; | 180 | return NULL; |
181 | } | 181 | } |
@@ -202,13 +202,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
202 | if (ea->indirect) { | 202 | if (ea->indirect) { |
203 | if (ea_len(ea) == size) | 203 | if (ea_len(ea) == size) |
204 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 204 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); |
205 | } else if (ea->valuelen == size) { | 205 | } else if (ea_valuelen(ea) == size) { |
206 | memcpy(ea_data(ea), data, size); | 206 | memcpy(ea_data(ea), data, size); |
207 | } | 207 | } |
208 | return; | 208 | return; |
209 | } | 209 | } |
210 | a = fnode->ea_secno; | 210 | a = le32_to_cpu(fnode->ea_secno); |
211 | len = fnode->ea_size_l; | 211 | len = le32_to_cpu(fnode->ea_size_l); |
212 | ano = fnode->ea_anode; | 212 | ano = fnode->ea_anode; |
213 | pos = 0; | 213 | pos = 0; |
214 | while (pos < len) { | 214 | while (pos < len) { |
@@ -228,68 +228,70 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
228 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 228 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); |
229 | } | 229 | } |
230 | else { | 230 | else { |
231 | if (ea->valuelen == size) | 231 | if (ea_valuelen(ea) == size) |
232 | hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data); | 232 | hpfs_ea_write(s, a, ano, pos + 4 + ea->namelen + 1, size, data); |
233 | } | 233 | } |
234 | return; | 234 | return; |
235 | } | 235 | } |
236 | pos += ea->namelen + ea->valuelen + 5; | 236 | pos += ea->namelen + ea_valuelen(ea) + 5; |
237 | } | 237 | } |
238 | if (!fnode->ea_offs) { | 238 | if (!le16_to_cpu(fnode->ea_offs)) { |
239 | /*if (fnode->ea_size_s) { | 239 | /*if (le16_to_cpu(fnode->ea_size_s)) { |
240 | hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0", | 240 | hpfs_error(s, "fnode %08x: ea_size_s == %03x, ea_offs == 0", |
241 | inode->i_ino, fnode->ea_size_s); | 241 | inode->i_ino, le16_to_cpu(fnode->ea_size_s)); |
242 | return; | 242 | return; |
243 | }*/ | 243 | }*/ |
244 | fnode->ea_offs = 0xc4; | 244 | fnode->ea_offs = cpu_to_le16(0xc4); |
245 | } | 245 | } |
246 | if (fnode->ea_offs < 0xc4 || fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200) { | 246 | if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) { |
247 | hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x", | 247 | hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x", |
248 | (unsigned long)inode->i_ino, | 248 | (unsigned long)inode->i_ino, |
249 | fnode->ea_offs, fnode->ea_size_s); | 249 | le32_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); |
250 | return; | 250 | return; |
251 | } | 251 | } |
252 | if ((fnode->ea_size_s || !fnode->ea_size_l) && | 252 | if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) && |
253 | fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s + strlen(key) + size + 5 <= 0x200) { | 253 | le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5 <= 0x200) { |
254 | ea = fnode_end_ea(fnode); | 254 | ea = fnode_end_ea(fnode); |
255 | *(char *)ea = 0; | 255 | *(char *)ea = 0; |
256 | ea->namelen = strlen(key); | 256 | ea->namelen = strlen(key); |
257 | ea->valuelen = size; | 257 | ea->valuelen_lo = size; |
258 | ea->valuelen_hi = size >> 8; | ||
258 | strcpy(ea->name, key); | 259 | strcpy(ea->name, key); |
259 | memcpy(ea_data(ea), data, size); | 260 | memcpy(ea_data(ea), data, size); |
260 | fnode->ea_size_s += strlen(key) + size + 5; | 261 | fnode->ea_size_s = cpu_to_le16(le16_to_cpu(fnode->ea_size_s) + strlen(key) + size + 5); |
261 | goto ret; | 262 | goto ret; |
262 | } | 263 | } |
263 | /* Most the code here is 99.9993422% unused. I hope there are no bugs. | 264 | /* Most the code here is 99.9993422% unused. I hope there are no bugs. |
264 | But what .. HPFS.IFS has also bugs in ea management. */ | 265 | But what .. HPFS.IFS has also bugs in ea management. */ |
265 | if (fnode->ea_size_s && !fnode->ea_size_l) { | 266 | if (le16_to_cpu(fnode->ea_size_s) && !le32_to_cpu(fnode->ea_size_l)) { |
266 | secno n; | 267 | secno n; |
267 | struct buffer_head *bh; | 268 | struct buffer_head *bh; |
268 | char *data; | 269 | char *data; |
269 | if (!(n = hpfs_alloc_sector(s, fno, 1, 0, 1))) return; | 270 | if (!(n = hpfs_alloc_sector(s, fno, 1, 0))) return; |
270 | if (!(data = hpfs_get_sector(s, n, &bh))) { | 271 | if (!(data = hpfs_get_sector(s, n, &bh))) { |
271 | hpfs_free_sectors(s, n, 1); | 272 | hpfs_free_sectors(s, n, 1); |
272 | return; | 273 | return; |
273 | } | 274 | } |
274 | memcpy(data, fnode_ea(fnode), fnode->ea_size_s); | 275 | memcpy(data, fnode_ea(fnode), le16_to_cpu(fnode->ea_size_s)); |
275 | fnode->ea_size_l = fnode->ea_size_s; | 276 | fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s)); |
276 | fnode->ea_size_s = 0; | 277 | fnode->ea_size_s = cpu_to_le16(0); |
277 | fnode->ea_secno = n; | 278 | fnode->ea_secno = cpu_to_le32(n); |
278 | fnode->ea_anode = 0; | 279 | fnode->ea_anode = cpu_to_le32(0); |
279 | mark_buffer_dirty(bh); | 280 | mark_buffer_dirty(bh); |
280 | brelse(bh); | 281 | brelse(bh); |
281 | } | 282 | } |
282 | pos = fnode->ea_size_l + 5 + strlen(key) + size; | 283 | pos = le32_to_cpu(fnode->ea_size_l) + 5 + strlen(key) + size; |
283 | len = (fnode->ea_size_l + 511) >> 9; | 284 | len = (le32_to_cpu(fnode->ea_size_l) + 511) >> 9; |
284 | if (pos >= 30000) goto bail; | 285 | if (pos >= 30000) goto bail; |
285 | while (((pos + 511) >> 9) > len) { | 286 | while (((pos + 511) >> 9) > len) { |
286 | if (!len) { | 287 | if (!len) { |
287 | if (!(fnode->ea_secno = hpfs_alloc_sector(s, fno, 1, 0, 1))) | 288 | secno q = hpfs_alloc_sector(s, fno, 1, 0); |
288 | goto bail; | 289 | if (!q) goto bail; |
290 | fnode->ea_secno = cpu_to_le32(q); | ||
289 | fnode->ea_anode = 0; | 291 | fnode->ea_anode = 0; |
290 | len++; | 292 | len++; |
291 | } else if (!fnode->ea_anode) { | 293 | } else if (!fnode->ea_anode) { |
292 | if (hpfs_alloc_if_possible(s, fnode->ea_secno + len)) { | 294 | if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) { |
293 | len++; | 295 | len++; |
294 | } else { | 296 | } else { |
295 | /* Aargh... don't know how to create ea anodes :-( */ | 297 | /* Aargh... don't know how to create ea anodes :-( */ |
@@ -298,26 +300,26 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
298 | anode_secno a_s; | 300 | anode_secno a_s; |
299 | if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh))) | 301 | if (!(anode = hpfs_alloc_anode(s, fno, &a_s, &bh))) |
300 | goto bail; | 302 | goto bail; |
301 | anode->up = fno; | 303 | anode->up = cpu_to_le32(fno); |
302 | anode->btree.fnode_parent = 1; | 304 | anode->btree.fnode_parent = 1; |
303 | anode->btree.n_free_nodes--; | 305 | anode->btree.n_free_nodes--; |
304 | anode->btree.n_used_nodes++; | 306 | anode->btree.n_used_nodes++; |
305 | anode->btree.first_free += 12; | 307 | anode->btree.first_free = cpu_to_le16(le16_to_cpu(anode->btree.first_free) + 12); |
306 | anode->u.external[0].disk_secno = fnode->ea_secno; | 308 | anode->u.external[0].disk_secno = cpu_to_le32(le32_to_cpu(fnode->ea_secno)); |
307 | anode->u.external[0].file_secno = 0; | 309 | anode->u.external[0].file_secno = cpu_to_le32(0); |
308 | anode->u.external[0].length = len; | 310 | anode->u.external[0].length = cpu_to_le32(len); |
309 | mark_buffer_dirty(bh); | 311 | mark_buffer_dirty(bh); |
310 | brelse(bh); | 312 | brelse(bh); |
311 | fnode->ea_anode = 1; | 313 | fnode->ea_anode = 1; |
312 | fnode->ea_secno = a_s;*/ | 314 | fnode->ea_secno = cpu_to_le32(a_s);*/ |
313 | secno new_sec; | 315 | secno new_sec; |
314 | int i; | 316 | int i; |
315 | if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9), 1))) | 317 | if (!(new_sec = hpfs_alloc_sector(s, fno, 1, 1 - ((pos + 511) >> 9)))) |
316 | goto bail; | 318 | goto bail; |
317 | for (i = 0; i < len; i++) { | 319 | for (i = 0; i < len; i++) { |
318 | struct buffer_head *bh1, *bh2; | 320 | struct buffer_head *bh1, *bh2; |
319 | void *b1, *b2; | 321 | void *b1, *b2; |
320 | if (!(b1 = hpfs_map_sector(s, fnode->ea_secno + i, &bh1, len - i - 1))) { | 322 | if (!(b1 = hpfs_map_sector(s, le32_to_cpu(fnode->ea_secno) + i, &bh1, len - i - 1))) { |
321 | hpfs_free_sectors(s, new_sec, (pos + 511) >> 9); | 323 | hpfs_free_sectors(s, new_sec, (pos + 511) >> 9); |
322 | goto bail; | 324 | goto bail; |
323 | } | 325 | } |
@@ -331,13 +333,13 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
331 | mark_buffer_dirty(bh2); | 333 | mark_buffer_dirty(bh2); |
332 | brelse(bh2); | 334 | brelse(bh2); |
333 | } | 335 | } |
334 | hpfs_free_sectors(s, fnode->ea_secno, len); | 336 | hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno), len); |
335 | fnode->ea_secno = new_sec; | 337 | fnode->ea_secno = cpu_to_le32(new_sec); |
336 | len = (pos + 511) >> 9; | 338 | len = (pos + 511) >> 9; |
337 | } | 339 | } |
338 | } | 340 | } |
339 | if (fnode->ea_anode) { | 341 | if (fnode->ea_anode) { |
340 | if (hpfs_add_sector_to_btree(s, fnode->ea_secno, | 342 | if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno), |
341 | 0, len) != -1) { | 343 | 0, len) != -1) { |
342 | len++; | 344 | len++; |
343 | } else { | 345 | } else { |
@@ -349,17 +351,17 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
349 | h[1] = strlen(key); | 351 | h[1] = strlen(key); |
350 | h[2] = size & 0xff; | 352 | h[2] = size & 0xff; |
351 | h[3] = size >> 8; | 353 | h[3] = size >> 8; |
352 | if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l, 4, h)) goto bail; | 354 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail; |
353 | if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 4, h[1] + 1, key)) goto bail; | 355 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail; |
354 | if (hpfs_ea_write(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l + 5 + h[1], size, data)) goto bail; | 356 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail; |
355 | fnode->ea_size_l = pos; | 357 | fnode->ea_size_l = cpu_to_le32(pos); |
356 | ret: | 358 | ret: |
357 | hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size; | 359 | hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size; |
358 | return; | 360 | return; |
359 | bail: | 361 | bail: |
360 | if (fnode->ea_secno) | 362 | if (le32_to_cpu(fnode->ea_secno)) |
361 | if (fnode->ea_anode) hpfs_truncate_btree(s, fnode->ea_secno, 1, (fnode->ea_size_l + 511) >> 9); | 363 | if (fnode->ea_anode) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9); |
362 | else hpfs_free_sectors(s, fnode->ea_secno + ((fnode->ea_size_l + 511) >> 9), len - ((fnode->ea_size_l + 511) >> 9)); | 364 | else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9)); |
363 | else fnode->ea_secno = fnode->ea_size_l = 0; | 365 | else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0); |
364 | } | 366 | } |
365 | 367 | ||
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 9b9eb6933e43..89c500ee5213 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
@@ -20,8 +20,8 @@ static int hpfs_file_release(struct inode *inode, struct file *file) | |||
20 | 20 | ||
21 | int hpfs_file_fsync(struct file *file, int datasync) | 21 | int hpfs_file_fsync(struct file *file, int datasync) |
22 | { | 22 | { |
23 | /*return file_fsync(file, datasync);*/ | 23 | struct inode *inode = file->f_mapping->host; |
24 | return 0; /* Don't fsync :-) */ | 24 | return sync_blockdev(inode->i_sb->s_bdev); |
25 | } | 25 | } |
26 | 26 | ||
27 | /* | 27 | /* |
@@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno) | |||
48 | static void hpfs_truncate(struct inode *i) | 48 | static void hpfs_truncate(struct inode *i) |
49 | { | 49 | { |
50 | if (IS_IMMUTABLE(i)) return /*-EPERM*/; | 50 | if (IS_IMMUTABLE(i)) return /*-EPERM*/; |
51 | hpfs_lock(i->i_sb); | 51 | hpfs_lock_assert(i->i_sb); |
52 | |||
52 | hpfs_i(i)->i_n_secs = 0; | 53 | hpfs_i(i)->i_n_secs = 0; |
53 | i->i_blocks = 1 + ((i->i_size + 511) >> 9); | 54 | i->i_blocks = 1 + ((i->i_size + 511) >> 9); |
54 | hpfs_i(i)->mmu_private = i->i_size; | 55 | hpfs_i(i)->mmu_private = i->i_size; |
55 | hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); | 56 | hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); |
56 | hpfs_write_inode(i); | 57 | hpfs_write_inode(i); |
57 | hpfs_i(i)->i_n_secs = 0; | 58 | hpfs_i(i)->i_n_secs = 0; |
58 | hpfs_unlock(i->i_sb); | ||
59 | } | 59 | } |
60 | 60 | ||
61 | static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) | 61 | static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) |
62 | { | 62 | { |
63 | int r; | ||
63 | secno s; | 64 | secno s; |
65 | hpfs_lock(inode->i_sb); | ||
64 | s = hpfs_bmap(inode, iblock); | 66 | s = hpfs_bmap(inode, iblock); |
65 | if (s) { | 67 | if (s) { |
66 | map_bh(bh_result, inode->i_sb, s); | 68 | map_bh(bh_result, inode->i_sb, s); |
67 | return 0; | 69 | goto ret_0; |
68 | } | 70 | } |
69 | if (!create) return 0; | 71 | if (!create) goto ret_0; |
70 | if (iblock<<9 != hpfs_i(inode)->mmu_private) { | 72 | if (iblock<<9 != hpfs_i(inode)->mmu_private) { |
71 | BUG(); | 73 | BUG(); |
72 | return -EIO; | 74 | r = -EIO; |
75 | goto ret_r; | ||
73 | } | 76 | } |
74 | if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { | 77 | if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { |
75 | hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); | 78 | hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); |
76 | return -ENOSPC; | 79 | r = -ENOSPC; |
80 | goto ret_r; | ||
77 | } | 81 | } |
78 | inode->i_blocks++; | 82 | inode->i_blocks++; |
79 | hpfs_i(inode)->mmu_private += 512; | 83 | hpfs_i(inode)->mmu_private += 512; |
80 | set_buffer_new(bh_result); | 84 | set_buffer_new(bh_result); |
81 | map_bh(bh_result, inode->i_sb, s); | 85 | map_bh(bh_result, inode->i_sb, s); |
82 | return 0; | 86 | ret_0: |
87 | r = 0; | ||
88 | ret_r: | ||
89 | hpfs_unlock(inode->i_sb); | ||
90 | return r; | ||
83 | } | 91 | } |
84 | 92 | ||
85 | static int hpfs_writepage(struct page *page, struct writeback_control *wbc) | 93 | static int hpfs_writepage(struct page *page, struct writeback_control *wbc) |
@@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, | |||
130 | ssize_t retval; | 138 | ssize_t retval; |
131 | 139 | ||
132 | retval = do_sync_write(file, buf, count, ppos); | 140 | retval = do_sync_write(file, buf, count, ppos); |
133 | if (retval > 0) | 141 | if (retval > 0) { |
142 | hpfs_lock(file->f_path.dentry->d_sb); | ||
134 | hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; | 143 | hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; |
144 | hpfs_unlock(file->f_path.dentry->d_sb); | ||
145 | } | ||
135 | return retval; | 146 | return retval; |
136 | } | 147 | } |
137 | 148 | ||
diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h index 0e84c73cd9c4..8b0650aae328 100644 --- a/fs/hpfs/hpfs.h +++ b/fs/hpfs/hpfs.h | |||
@@ -19,9 +19,13 @@ | |||
19 | For definitive information on HPFS, ask somebody else -- this is guesswork. | 19 | For definitive information on HPFS, ask somebody else -- this is guesswork. |
20 | There are certain to be many mistakes. */ | 20 | There are certain to be many mistakes. */ |
21 | 21 | ||
22 | #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) | ||
23 | #error unknown endian | ||
24 | #endif | ||
25 | |||
22 | /* Notation */ | 26 | /* Notation */ |
23 | 27 | ||
24 | typedef unsigned secno; /* sector number, partition relative */ | 28 | typedef u32 secno; /* sector number, partition relative */ |
25 | 29 | ||
26 | typedef secno dnode_secno; /* sector number of a dnode */ | 30 | typedef secno dnode_secno; /* sector number of a dnode */ |
27 | typedef secno fnode_secno; /* sector number of an fnode */ | 31 | typedef secno fnode_secno; /* sector number of an fnode */ |
@@ -38,28 +42,28 @@ typedef u32 time32_t; /* 32-bit time_t type */ | |||
38 | 42 | ||
39 | struct hpfs_boot_block | 43 | struct hpfs_boot_block |
40 | { | 44 | { |
41 | unsigned char jmp[3]; | 45 | u8 jmp[3]; |
42 | unsigned char oem_id[8]; | 46 | u8 oem_id[8]; |
43 | unsigned char bytes_per_sector[2]; /* 512 */ | 47 | u8 bytes_per_sector[2]; /* 512 */ |
44 | unsigned char sectors_per_cluster; | 48 | u8 sectors_per_cluster; |
45 | unsigned char n_reserved_sectors[2]; | 49 | u8 n_reserved_sectors[2]; |
46 | unsigned char n_fats; | 50 | u8 n_fats; |
47 | unsigned char n_rootdir_entries[2]; | 51 | u8 n_rootdir_entries[2]; |
48 | unsigned char n_sectors_s[2]; | 52 | u8 n_sectors_s[2]; |
49 | unsigned char media_byte; | 53 | u8 media_byte; |
50 | unsigned short sectors_per_fat; | 54 | u16 sectors_per_fat; |
51 | unsigned short sectors_per_track; | 55 | u16 sectors_per_track; |
52 | unsigned short heads_per_cyl; | 56 | u16 heads_per_cyl; |
53 | unsigned int n_hidden_sectors; | 57 | u32 n_hidden_sectors; |
54 | unsigned int n_sectors_l; /* size of partition */ | 58 | u32 n_sectors_l; /* size of partition */ |
55 | unsigned char drive_number; | 59 | u8 drive_number; |
56 | unsigned char mbz; | 60 | u8 mbz; |
57 | unsigned char sig_28h; /* 28h */ | 61 | u8 sig_28h; /* 28h */ |
58 | unsigned char vol_serno[4]; | 62 | u8 vol_serno[4]; |
59 | unsigned char vol_label[11]; | 63 | u8 vol_label[11]; |
60 | unsigned char sig_hpfs[8]; /* "HPFS " */ | 64 | u8 sig_hpfs[8]; /* "HPFS " */ |
61 | unsigned char pad[448]; | 65 | u8 pad[448]; |
62 | unsigned short magic; /* aa55 */ | 66 | u16 magic; /* aa55 */ |
63 | }; | 67 | }; |
64 | 68 | ||
65 | 69 | ||
@@ -71,31 +75,29 @@ struct hpfs_boot_block | |||
71 | 75 | ||
72 | struct hpfs_super_block | 76 | struct hpfs_super_block |
73 | { | 77 | { |
74 | unsigned magic; /* f995 e849 */ | 78 | u32 magic; /* f995 e849 */ |
75 | unsigned magic1; /* fa53 e9c5, more magic? */ | 79 | u32 magic1; /* fa53 e9c5, more magic? */ |
76 | /*unsigned huh202;*/ /* ?? 202 = N. of B. in 1.00390625 S.*/ | 80 | u8 version; /* version of a filesystem usually 2 */ |
77 | char version; /* version of a filesystem usually 2 */ | 81 | u8 funcversion; /* functional version - oldest version |
78 | char funcversion; /* functional version - oldest version | ||
79 | of filesystem that can understand | 82 | of filesystem that can understand |
80 | this disk */ | 83 | this disk */ |
81 | unsigned short int zero; /* 0 */ | 84 | u16 zero; /* 0 */ |
82 | fnode_secno root; /* fnode of root directory */ | 85 | fnode_secno root; /* fnode of root directory */ |
83 | secno n_sectors; /* size of filesystem */ | 86 | secno n_sectors; /* size of filesystem */ |
84 | unsigned n_badblocks; /* number of bad blocks */ | 87 | u32 n_badblocks; /* number of bad blocks */ |
85 | secno bitmaps; /* pointers to free space bit maps */ | 88 | secno bitmaps; /* pointers to free space bit maps */ |
86 | unsigned zero1; /* 0 */ | 89 | u32 zero1; /* 0 */ |
87 | secno badblocks; /* bad block list */ | 90 | secno badblocks; /* bad block list */ |
88 | unsigned zero3; /* 0 */ | 91 | u32 zero3; /* 0 */ |
89 | time32_t last_chkdsk; /* date last checked, 0 if never */ | 92 | time32_t last_chkdsk; /* date last checked, 0 if never */ |
90 | /*unsigned zero4;*/ /* 0 */ | 93 | time32_t last_optimize; /* date last optimized, 0 if never */ |
91 | time32_t last_optimize; /* date last optimized, 0 if never */ | ||
92 | secno n_dir_band; /* number of sectors in dir band */ | 94 | secno n_dir_band; /* number of sectors in dir band */ |
93 | secno dir_band_start; /* first sector in dir band */ | 95 | secno dir_band_start; /* first sector in dir band */ |
94 | secno dir_band_end; /* last sector in dir band */ | 96 | secno dir_band_end; /* last sector in dir band */ |
95 | secno dir_band_bitmap; /* free space map, 1 dnode per bit */ | 97 | secno dir_band_bitmap; /* free space map, 1 dnode per bit */ |
96 | char volume_name[32]; /* not used */ | 98 | u8 volume_name[32]; /* not used */ |
97 | secno user_id_table; /* 8 preallocated sectors - user id */ | 99 | secno user_id_table; /* 8 preallocated sectors - user id */ |
98 | unsigned zero6[103]; /* 0 */ | 100 | u32 zero6[103]; /* 0 */ |
99 | }; | 101 | }; |
100 | 102 | ||
101 | 103 | ||
@@ -107,44 +109,65 @@ struct hpfs_super_block | |||
107 | 109 | ||
108 | struct hpfs_spare_block | 110 | struct hpfs_spare_block |
109 | { | 111 | { |
110 | unsigned magic; /* f991 1849 */ | 112 | u32 magic; /* f991 1849 */ |
111 | unsigned magic1; /* fa52 29c5, more magic? */ | 113 | u32 magic1; /* fa52 29c5, more magic? */ |
112 | 114 | ||
113 | unsigned dirty: 1; /* 0 clean, 1 "improperly stopped" */ | 115 | #ifdef __LITTLE_ENDIAN |
114 | /*unsigned flag1234: 4;*/ /* unknown flags */ | 116 | u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */ |
115 | unsigned sparedir_used: 1; /* spare dirblks used */ | 117 | u8 sparedir_used: 1; /* spare dirblks used */ |
116 | unsigned hotfixes_used: 1; /* hotfixes used */ | 118 | u8 hotfixes_used: 1; /* hotfixes used */ |
117 | unsigned bad_sector: 1; /* bad sector, corrupted disk (???) */ | 119 | u8 bad_sector: 1; /* bad sector, corrupted disk (???) */ |
118 | unsigned bad_bitmap: 1; /* bad bitmap */ | 120 | u8 bad_bitmap: 1; /* bad bitmap */ |
119 | unsigned fast: 1; /* partition was fast formatted */ | 121 | u8 fast: 1; /* partition was fast formatted */ |
120 | unsigned old_wrote: 1; /* old version wrote to partion */ | 122 | u8 old_wrote: 1; /* old version wrote to partion */ |
121 | unsigned old_wrote_1: 1; /* old version wrote to partion (?) */ | 123 | u8 old_wrote_1: 1; /* old version wrote to partion (?) */ |
122 | unsigned install_dasd_limits: 1; /* HPFS386 flags */ | 124 | #else |
123 | unsigned resynch_dasd_limits: 1; | 125 | u8 old_wrote_1: 1; /* old version wrote to partion (?) */ |
124 | unsigned dasd_limits_operational: 1; | 126 | u8 old_wrote: 1; /* old version wrote to partion */ |
125 | unsigned multimedia_active: 1; | 127 | u8 fast: 1; /* partition was fast formatted */ |
126 | unsigned dce_acls_active: 1; | 128 | u8 bad_bitmap: 1; /* bad bitmap */ |
127 | unsigned dasd_limits_dirty: 1; | 129 | u8 bad_sector: 1; /* bad sector, corrupted disk (???) */ |
128 | unsigned flag67: 2; | 130 | u8 hotfixes_used: 1; /* hotfixes used */ |
129 | unsigned char mm_contlgulty; | 131 | u8 sparedir_used: 1; /* spare dirblks used */ |
130 | unsigned char unused; | 132 | u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */ |
133 | #endif | ||
134 | |||
135 | #ifdef __LITTLE_ENDIAN | ||
136 | u8 install_dasd_limits: 1; /* HPFS386 flags */ | ||
137 | u8 resynch_dasd_limits: 1; | ||
138 | u8 dasd_limits_operational: 1; | ||
139 | u8 multimedia_active: 1; | ||
140 | u8 dce_acls_active: 1; | ||
141 | u8 dasd_limits_dirty: 1; | ||
142 | u8 flag67: 2; | ||
143 | #else | ||
144 | u8 flag67: 2; | ||
145 | u8 dasd_limits_dirty: 1; | ||
146 | u8 dce_acls_active: 1; | ||
147 | u8 multimedia_active: 1; | ||
148 | u8 dasd_limits_operational: 1; | ||
149 | u8 resynch_dasd_limits: 1; | ||
150 | u8 install_dasd_limits: 1; /* HPFS386 flags */ | ||
151 | #endif | ||
152 | |||
153 | u8 mm_contlgulty; | ||
154 | u8 unused; | ||
131 | 155 | ||
132 | secno hotfix_map; /* info about remapped bad sectors */ | 156 | secno hotfix_map; /* info about remapped bad sectors */ |
133 | unsigned n_spares_used; /* number of hotfixes */ | 157 | u32 n_spares_used; /* number of hotfixes */ |
134 | unsigned n_spares; /* number of spares in hotfix map */ | 158 | u32 n_spares; /* number of spares in hotfix map */ |
135 | unsigned n_dnode_spares_free; /* spare dnodes unused */ | 159 | u32 n_dnode_spares_free; /* spare dnodes unused */ |
136 | unsigned n_dnode_spares; /* length of spare_dnodes[] list, | 160 | u32 n_dnode_spares; /* length of spare_dnodes[] list, |
137 | follows in this block*/ | 161 | follows in this block*/ |
138 | secno code_page_dir; /* code page directory block */ | 162 | secno code_page_dir; /* code page directory block */ |
139 | unsigned n_code_pages; /* number of code pages */ | 163 | u32 n_code_pages; /* number of code pages */ |
140 | /*unsigned large_numbers[2];*/ /* ?? */ | 164 | u32 super_crc; /* on HPFS386 and LAN Server this is |
141 | unsigned super_crc; /* on HPFS386 and LAN Server this is | ||
142 | checksum of superblock, on normal | 165 | checksum of superblock, on normal |
143 | OS/2 unused */ | 166 | OS/2 unused */ |
144 | unsigned spare_crc; /* on HPFS386 checksum of spareblock */ | 167 | u32 spare_crc; /* on HPFS386 checksum of spareblock */ |
145 | unsigned zero1[15]; /* unused */ | 168 | u32 zero1[15]; /* unused */ |
146 | dnode_secno spare_dnodes[100]; /* emergency free dnode list */ | 169 | dnode_secno spare_dnodes[100]; /* emergency free dnode list */ |
147 | unsigned zero2[1]; /* room for more? */ | 170 | u32 zero2[1]; /* room for more? */ |
148 | }; | 171 | }; |
149 | 172 | ||
150 | /* The bad block list is 4 sectors long. The first word must be zero, | 173 | /* The bad block list is 4 sectors long. The first word must be zero, |
@@ -179,18 +202,18 @@ struct hpfs_spare_block | |||
179 | 202 | ||
180 | struct code_page_directory | 203 | struct code_page_directory |
181 | { | 204 | { |
182 | unsigned magic; /* 4945 21f7 */ | 205 | u32 magic; /* 4945 21f7 */ |
183 | unsigned n_code_pages; /* number of pointers following */ | 206 | u32 n_code_pages; /* number of pointers following */ |
184 | unsigned zero1[2]; | 207 | u32 zero1[2]; |
185 | struct { | 208 | struct { |
186 | unsigned short ix; /* index */ | 209 | u16 ix; /* index */ |
187 | unsigned short code_page_number; /* code page number */ | 210 | u16 code_page_number; /* code page number */ |
188 | unsigned bounds; /* matches corresponding word | 211 | u32 bounds; /* matches corresponding word |
189 | in data block */ | 212 | in data block */ |
190 | secno code_page_data; /* sector number of a code_page_data | 213 | secno code_page_data; /* sector number of a code_page_data |
191 | containing c.p. array */ | 214 | containing c.p. array */ |
192 | unsigned short index; /* index in c.p. array in that sector*/ | 215 | u16 index; /* index in c.p. array in that sector*/ |
193 | unsigned short unknown; /* some unknown value; usually 0; | 216 | u16 unknown; /* some unknown value; usually 0; |
194 | 2 in Japanese version */ | 217 | 2 in Japanese version */ |
195 | } array[31]; /* unknown length */ | 218 | } array[31]; /* unknown length */ |
196 | }; | 219 | }; |
@@ -201,21 +224,21 @@ struct code_page_directory | |||
201 | 224 | ||
202 | struct code_page_data | 225 | struct code_page_data |
203 | { | 226 | { |
204 | unsigned magic; /* 8945 21f7 */ | 227 | u32 magic; /* 8945 21f7 */ |
205 | unsigned n_used; /* # elements used in c_p_data[] */ | 228 | u32 n_used; /* # elements used in c_p_data[] */ |
206 | unsigned bounds[3]; /* looks a bit like | 229 | u32 bounds[3]; /* looks a bit like |
207 | (beg1,end1), (beg2,end2) | 230 | (beg1,end1), (beg2,end2) |
208 | one byte each */ | 231 | one byte each */ |
209 | unsigned short offs[3]; /* offsets from start of sector | 232 | u16 offs[3]; /* offsets from start of sector |
210 | to start of c_p_data[ix] */ | 233 | to start of c_p_data[ix] */ |
211 | struct { | 234 | struct { |
212 | unsigned short ix; /* index */ | 235 | u16 ix; /* index */ |
213 | unsigned short code_page_number; /* code page number */ | 236 | u16 code_page_number; /* code page number */ |
214 | unsigned short unknown; /* the same as in cp directory */ | 237 | u16 unknown; /* the same as in cp directory */ |
215 | unsigned char map[128]; /* upcase table for chars 80..ff */ | 238 | u8 map[128]; /* upcase table for chars 80..ff */ |
216 | unsigned short zero2; | 239 | u16 zero2; |
217 | } code_page[3]; | 240 | } code_page[3]; |
218 | unsigned char incognita[78]; | 241 | u8 incognita[78]; |
219 | }; | 242 | }; |
220 | 243 | ||
221 | 244 | ||
@@ -255,50 +278,84 @@ struct code_page_data | |||
255 | #define DNODE_MAGIC 0x77e40aae | 278 | #define DNODE_MAGIC 0x77e40aae |
256 | 279 | ||
257 | struct dnode { | 280 | struct dnode { |
258 | unsigned magic; /* 77e4 0aae */ | 281 | u32 magic; /* 77e4 0aae */ |
259 | unsigned first_free; /* offset from start of dnode to | 282 | u32 first_free; /* offset from start of dnode to |
260 | first free dir entry */ | 283 | first free dir entry */ |
261 | unsigned root_dnode:1; /* Is it root dnode? */ | 284 | #ifdef __LITTLE_ENDIAN |
262 | unsigned increment_me:31; /* some kind of activity counter? | 285 | u8 root_dnode: 1; /* Is it root dnode? */ |
263 | Neither HPFS.IFS nor CHKDSK cares | 286 | u8 increment_me: 7; /* some kind of activity counter? */ |
287 | /* Neither HPFS.IFS nor CHKDSK cares | ||
288 | if you change this word */ | ||
289 | #else | ||
290 | u8 increment_me: 7; /* some kind of activity counter? */ | ||
291 | /* Neither HPFS.IFS nor CHKDSK cares | ||
264 | if you change this word */ | 292 | if you change this word */ |
293 | u8 root_dnode: 1; /* Is it root dnode? */ | ||
294 | #endif | ||
295 | u8 increment_me2[3]; | ||
265 | secno up; /* (root dnode) directory's fnode | 296 | secno up; /* (root dnode) directory's fnode |
266 | (nonroot) parent dnode */ | 297 | (nonroot) parent dnode */ |
267 | dnode_secno self; /* pointer to this dnode */ | 298 | dnode_secno self; /* pointer to this dnode */ |
268 | unsigned char dirent[2028]; /* one or more dirents */ | 299 | u8 dirent[2028]; /* one or more dirents */ |
269 | }; | 300 | }; |
270 | 301 | ||
271 | struct hpfs_dirent { | 302 | struct hpfs_dirent { |
272 | unsigned short length; /* offset to next dirent */ | 303 | u16 length; /* offset to next dirent */ |
273 | unsigned first: 1; /* set on phony ^A^A (".") entry */ | 304 | |
274 | unsigned has_acl: 1; | 305 | #ifdef __LITTLE_ENDIAN |
275 | unsigned down: 1; /* down pointer present (after name) */ | 306 | u8 first: 1; /* set on phony ^A^A (".") entry */ |
276 | unsigned last: 1; /* set on phony \377 entry */ | 307 | u8 has_acl: 1; |
277 | unsigned has_ea: 1; /* entry has EA */ | 308 | u8 down: 1; /* down pointer present (after name) */ |
278 | unsigned has_xtd_perm: 1; /* has extended perm list (???) */ | 309 | u8 last: 1; /* set on phony \377 entry */ |
279 | unsigned has_explicit_acl: 1; | 310 | u8 has_ea: 1; /* entry has EA */ |
280 | unsigned has_needea: 1; /* ?? some EA has NEEDEA set | 311 | u8 has_xtd_perm: 1; /* has extended perm list (???) */ |
312 | u8 has_explicit_acl: 1; | ||
313 | u8 has_needea: 1; /* ?? some EA has NEEDEA set | ||
314 | I have no idea why this is | ||
315 | interesting in a dir entry */ | ||
316 | #else | ||
317 | u8 has_needea: 1; /* ?? some EA has NEEDEA set | ||
281 | I have no idea why this is | 318 | I have no idea why this is |
282 | interesting in a dir entry */ | 319 | interesting in a dir entry */ |
283 | unsigned read_only: 1; /* dos attrib */ | 320 | u8 has_explicit_acl: 1; |
284 | unsigned hidden: 1; /* dos attrib */ | 321 | u8 has_xtd_perm: 1; /* has extended perm list (???) */ |
285 | unsigned system: 1; /* dos attrib */ | 322 | u8 has_ea: 1; /* entry has EA */ |
286 | unsigned flag11: 1; /* would be volume label dos attrib */ | 323 | u8 last: 1; /* set on phony \377 entry */ |
287 | unsigned directory: 1; /* dos attrib */ | 324 | u8 down: 1; /* down pointer present (after name) */ |
288 | unsigned archive: 1; /* dos attrib */ | 325 | u8 has_acl: 1; |
289 | unsigned not_8x3: 1; /* name is not 8.3 */ | 326 | u8 first: 1; /* set on phony ^A^A (".") entry */ |
290 | unsigned flag15: 1; | 327 | #endif |
328 | |||
329 | #ifdef __LITTLE_ENDIAN | ||
330 | u8 read_only: 1; /* dos attrib */ | ||
331 | u8 hidden: 1; /* dos attrib */ | ||
332 | u8 system: 1; /* dos attrib */ | ||
333 | u8 flag11: 1; /* would be volume label dos attrib */ | ||
334 | u8 directory: 1; /* dos attrib */ | ||
335 | u8 archive: 1; /* dos attrib */ | ||
336 | u8 not_8x3: 1; /* name is not 8.3 */ | ||
337 | u8 flag15: 1; | ||
338 | #else | ||
339 | u8 flag15: 1; | ||
340 | u8 not_8x3: 1; /* name is not 8.3 */ | ||
341 | u8 archive: 1; /* dos attrib */ | ||
342 | u8 directory: 1; /* dos attrib */ | ||
343 | u8 flag11: 1; /* would be volume label dos attrib */ | ||
344 | u8 system: 1; /* dos attrib */ | ||
345 | u8 hidden: 1; /* dos attrib */ | ||
346 | u8 read_only: 1; /* dos attrib */ | ||
347 | #endif | ||
348 | |||
291 | fnode_secno fnode; /* fnode giving allocation info */ | 349 | fnode_secno fnode; /* fnode giving allocation info */ |
292 | time32_t write_date; /* mtime */ | 350 | time32_t write_date; /* mtime */ |
293 | unsigned file_size; /* file length, bytes */ | 351 | u32 file_size; /* file length, bytes */ |
294 | time32_t read_date; /* atime */ | 352 | time32_t read_date; /* atime */ |
295 | time32_t creation_date; /* ctime */ | 353 | time32_t creation_date; /* ctime */ |
296 | unsigned ea_size; /* total EA length, bytes */ | 354 | u32 ea_size; /* total EA length, bytes */ |
297 | unsigned char no_of_acls : 3; /* number of ACL's */ | 355 | u8 no_of_acls; /* number of ACL's (low 3 bits) */ |
298 | unsigned char reserver : 5; | 356 | u8 ix; /* code page index (of filename), see |
299 | unsigned char ix; /* code page index (of filename), see | ||
300 | struct code_page_data */ | 357 | struct code_page_data */ |
301 | unsigned char namelen, name[1]; /* file name */ | 358 | u8 namelen, name[1]; /* file name */ |
302 | /* dnode_secno down; btree down pointer, if present, | 359 | /* dnode_secno down; btree down pointer, if present, |
303 | follows name on next word boundary, or maybe it | 360 | follows name on next word boundary, or maybe it |
304 | precedes next dirent, which is on a word boundary. */ | 361 | precedes next dirent, which is on a word boundary. */ |
@@ -318,38 +375,50 @@ struct hpfs_dirent { | |||
318 | 375 | ||
319 | struct bplus_leaf_node | 376 | struct bplus_leaf_node |
320 | { | 377 | { |
321 | unsigned file_secno; /* first file sector in extent */ | 378 | u32 file_secno; /* first file sector in extent */ |
322 | unsigned length; /* length, sectors */ | 379 | u32 length; /* length, sectors */ |
323 | secno disk_secno; /* first corresponding disk sector */ | 380 | secno disk_secno; /* first corresponding disk sector */ |
324 | }; | 381 | }; |
325 | 382 | ||
326 | struct bplus_internal_node | 383 | struct bplus_internal_node |
327 | { | 384 | { |
328 | unsigned file_secno; /* subtree maps sectors < this */ | 385 | u32 file_secno; /* subtree maps sectors < this */ |
329 | anode_secno down; /* pointer to subtree */ | 386 | anode_secno down; /* pointer to subtree */ |
330 | }; | 387 | }; |
331 | 388 | ||
332 | struct bplus_header | 389 | struct bplus_header |
333 | { | 390 | { |
334 | unsigned hbff: 1; /* high bit of first free entry offset */ | 391 | #ifdef __LITTLE_ENDIAN |
335 | unsigned flag1: 1; | 392 | u8 hbff: 1; /* high bit of first free entry offset */ |
336 | unsigned flag2: 1; | 393 | u8 flag1234: 4; |
337 | unsigned flag3: 1; | 394 | u8 fnode_parent: 1; /* ? we're pointed to by an fnode, |
338 | unsigned flag4: 1; | ||
339 | unsigned fnode_parent: 1; /* ? we're pointed to by an fnode, | ||
340 | the data btree or some ea or the | 395 | the data btree or some ea or the |
341 | main ea bootage pointer ea_secno */ | 396 | main ea bootage pointer ea_secno */ |
342 | /* also can get set in fnodes, which | 397 | /* also can get set in fnodes, which |
343 | may be a chkdsk glitch or may mean | 398 | may be a chkdsk glitch or may mean |
344 | this bit is irrelevant in fnodes, | 399 | this bit is irrelevant in fnodes, |
345 | or this interpretation is all wet */ | 400 | or this interpretation is all wet */ |
346 | unsigned binary_search: 1; /* suggest binary search (unused) */ | 401 | u8 binary_search: 1; /* suggest binary search (unused) */ |
347 | unsigned internal: 1; /* 1 -> (internal) tree of anodes | 402 | u8 internal: 1; /* 1 -> (internal) tree of anodes |
403 | 0 -> (leaf) list of extents */ | ||
404 | #else | ||
405 | u8 internal: 1; /* 1 -> (internal) tree of anodes | ||
348 | 0 -> (leaf) list of extents */ | 406 | 0 -> (leaf) list of extents */ |
349 | unsigned char fill[3]; | 407 | u8 binary_search: 1; /* suggest binary search (unused) */ |
350 | unsigned char n_free_nodes; /* free nodes in following array */ | 408 | u8 fnode_parent: 1; /* ? we're pointed to by an fnode, |
351 | unsigned char n_used_nodes; /* used nodes in following array */ | 409 | the data btree or some ea or the |
352 | unsigned short first_free; /* offset from start of header to | 410 | main ea bootage pointer ea_secno */ |
411 | /* also can get set in fnodes, which | ||
412 | may be a chkdsk glitch or may mean | ||
413 | this bit is irrelevant in fnodes, | ||
414 | or this interpretation is all wet */ | ||
415 | u8 flag1234: 4; | ||
416 | u8 hbff: 1; /* high bit of first free entry offset */ | ||
417 | #endif | ||
418 | u8 fill[3]; | ||
419 | u8 n_free_nodes; /* free nodes in following array */ | ||
420 | u8 n_used_nodes; /* used nodes in following array */ | ||
421 | u16 first_free; /* offset from start of header to | ||
353 | first free node in array */ | 422 | first free node in array */ |
354 | union { | 423 | union { |
355 | struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving | 424 | struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving |
@@ -369,37 +438,38 @@ struct bplus_header | |||
369 | 438 | ||
370 | struct fnode | 439 | struct fnode |
371 | { | 440 | { |
372 | unsigned magic; /* f7e4 0aae */ | 441 | u32 magic; /* f7e4 0aae */ |
373 | unsigned zero1[2]; /* read history */ | 442 | u32 zero1[2]; /* read history */ |
374 | unsigned char len, name[15]; /* true length, truncated name */ | 443 | u8 len, name[15]; /* true length, truncated name */ |
375 | fnode_secno up; /* pointer to file's directory fnode */ | 444 | fnode_secno up; /* pointer to file's directory fnode */ |
376 | /*unsigned zero2[3];*/ | ||
377 | secno acl_size_l; | 445 | secno acl_size_l; |
378 | secno acl_secno; | 446 | secno acl_secno; |
379 | unsigned short acl_size_s; | 447 | u16 acl_size_s; |
380 | char acl_anode; | 448 | u8 acl_anode; |
381 | char zero2; /* history bit count */ | 449 | u8 zero2; /* history bit count */ |
382 | unsigned ea_size_l; /* length of disk-resident ea's */ | 450 | u32 ea_size_l; /* length of disk-resident ea's */ |
383 | secno ea_secno; /* first sector of disk-resident ea's*/ | 451 | secno ea_secno; /* first sector of disk-resident ea's*/ |
384 | unsigned short ea_size_s; /* length of fnode-resident ea's */ | 452 | u16 ea_size_s; /* length of fnode-resident ea's */ |
385 | 453 | ||
386 | unsigned flag0: 1; | 454 | #ifdef __LITTLE_ENDIAN |
387 | unsigned ea_anode: 1; /* 1 -> ea_secno is an anode */ | 455 | u8 flag0: 1; |
388 | unsigned flag2: 1; | 456 | u8 ea_anode: 1; /* 1 -> ea_secno is an anode */ |
389 | unsigned flag3: 1; | 457 | u8 flag234567: 6; |
390 | unsigned flag4: 1; | 458 | #else |
391 | unsigned flag5: 1; | 459 | u8 flag234567: 6; |
392 | unsigned flag6: 1; | 460 | u8 ea_anode: 1; /* 1 -> ea_secno is an anode */ |
393 | unsigned flag7: 1; | 461 | u8 flag0: 1; |
394 | unsigned dirflag: 1; /* 1 -> directory. first & only extent | 462 | #endif |
463 | |||
464 | #ifdef __LITTLE_ENDIAN | ||
465 | u8 dirflag: 1; /* 1 -> directory. first & only extent | ||
395 | points to dnode. */ | 466 | points to dnode. */ |
396 | unsigned flag9: 1; | 467 | u8 flag9012345: 7; |
397 | unsigned flag10: 1; | 468 | #else |
398 | unsigned flag11: 1; | 469 | u8 flag9012345: 7; |
399 | unsigned flag12: 1; | 470 | u8 dirflag: 1; /* 1 -> directory. first & only extent |
400 | unsigned flag13: 1; | 471 | points to dnode. */ |
401 | unsigned flag14: 1; | 472 | #endif |
402 | unsigned flag15: 1; | ||
403 | 473 | ||
404 | struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */ | 474 | struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */ |
405 | union { | 475 | union { |
@@ -407,17 +477,16 @@ struct fnode | |||
407 | struct bplus_internal_node internal[12]; | 477 | struct bplus_internal_node internal[12]; |
408 | } u; | 478 | } u; |
409 | 479 | ||
410 | unsigned file_size; /* file length, bytes */ | 480 | u32 file_size; /* file length, bytes */ |
411 | unsigned n_needea; /* number of EA's with NEEDEA set */ | 481 | u32 n_needea; /* number of EA's with NEEDEA set */ |
412 | char user_id[16]; /* unused */ | 482 | u8 user_id[16]; /* unused */ |
413 | unsigned short ea_offs; /* offset from start of fnode | 483 | u16 ea_offs; /* offset from start of fnode |
414 | to first fnode-resident ea */ | 484 | to first fnode-resident ea */ |
415 | char dasd_limit_treshhold; | 485 | u8 dasd_limit_treshhold; |
416 | char dasd_limit_delta; | 486 | u8 dasd_limit_delta; |
417 | unsigned dasd_limit; | 487 | u32 dasd_limit; |
418 | unsigned dasd_usage; | 488 | u32 dasd_usage; |
419 | /*unsigned zero5[2];*/ | 489 | u8 ea[316]; /* zero or more EA's, packed together |
420 | unsigned char ea[316]; /* zero or more EA's, packed together | ||
421 | with no alignment padding. | 490 | with no alignment padding. |
422 | (Do not use this name, get here | 491 | (Do not use this name, get here |
423 | via fnode + ea_offs. I think.) */ | 492 | via fnode + ea_offs. I think.) */ |
@@ -430,7 +499,7 @@ struct fnode | |||
430 | 499 | ||
431 | struct anode | 500 | struct anode |
432 | { | 501 | { |
433 | unsigned magic; /* 37e4 0aae */ | 502 | u32 magic; /* 37e4 0aae */ |
434 | anode_secno self; /* pointer to this anode */ | 503 | anode_secno self; /* pointer to this anode */ |
435 | secno up; /* parent anode or fnode */ | 504 | secno up; /* parent anode or fnode */ |
436 | 505 | ||
@@ -440,7 +509,7 @@ struct anode | |||
440 | struct bplus_internal_node internal[60]; | 509 | struct bplus_internal_node internal[60]; |
441 | } u; | 510 | } u; |
442 | 511 | ||
443 | unsigned fill[3]; /* unused */ | 512 | u32 fill[3]; /* unused */ |
444 | }; | 513 | }; |
445 | 514 | ||
446 | 515 | ||
@@ -461,25 +530,31 @@ struct anode | |||
461 | 530 | ||
462 | struct extended_attribute | 531 | struct extended_attribute |
463 | { | 532 | { |
464 | unsigned indirect: 1; /* 1 -> value gives sector number | 533 | #ifdef __LITTLE_ENDIAN |
534 | u8 indirect: 1; /* 1 -> value gives sector number | ||
465 | where real value starts */ | 535 | where real value starts */ |
466 | unsigned anode: 1; /* 1 -> sector is an anode | 536 | u8 anode: 1; /* 1 -> sector is an anode |
537 | that points to fragmented value */ | ||
538 | u8 flag23456: 5; | ||
539 | u8 needea: 1; /* required ea */ | ||
540 | #else | ||
541 | u8 needea: 1; /* required ea */ | ||
542 | u8 flag23456: 5; | ||
543 | u8 anode: 1; /* 1 -> sector is an anode | ||
467 | that points to fragmented value */ | 544 | that points to fragmented value */ |
468 | unsigned flag2: 1; | 545 | u8 indirect: 1; /* 1 -> value gives sector number |
469 | unsigned flag3: 1; | 546 | where real value starts */ |
470 | unsigned flag4: 1; | 547 | #endif |
471 | unsigned flag5: 1; | 548 | u8 namelen; /* length of name, bytes */ |
472 | unsigned flag6: 1; | 549 | u8 valuelen_lo; /* length of value, bytes */ |
473 | unsigned needea: 1; /* required ea */ | 550 | u8 valuelen_hi; /* length of value, bytes */ |
474 | unsigned char namelen; /* length of name, bytes */ | 551 | u8 name[0]; |
475 | unsigned short valuelen; /* length of value, bytes */ | ||
476 | unsigned char name[0]; | ||
477 | /* | 552 | /* |
478 | unsigned char name[namelen]; ascii attrib name | 553 | u8 name[namelen]; ascii attrib name |
479 | unsigned char nul; terminating '\0', not counted | 554 | u8 nul; terminating '\0', not counted |
480 | unsigned char value[valuelen]; value, arbitrary | 555 | u8 value[valuelen]; value, arbitrary |
481 | if this.indirect, valuelen is 8 and the value is | 556 | if this.indirect, valuelen is 8 and the value is |
482 | unsigned length; real length of value, bytes | 557 | u32 length; real length of value, bytes |
483 | secno secno; sector address where it starts | 558 | secno secno; sector address where it starts |
484 | if this.anode, the above sector number is the root of an anode tree | 559 | if this.anode, the above sector number is the root of an anode tree |
485 | which points to the value. | 560 | which points to the value. |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index c15adbca07ff..dd552f862c8f 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/pagemap.h> | 13 | #include <linux/pagemap.h> |
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <asm/unaligned.h> | ||
16 | 17 | ||
17 | #include "hpfs.h" | 18 | #include "hpfs.h" |
18 | 19 | ||
@@ -51,18 +52,16 @@ struct hpfs_inode_info { | |||
51 | unsigned i_disk_sec; /* (files) minimalist cache of alloc info */ | 52 | unsigned i_disk_sec; /* (files) minimalist cache of alloc info */ |
52 | unsigned i_n_secs; /* (files) minimalist cache of alloc info */ | 53 | unsigned i_n_secs; /* (files) minimalist cache of alloc info */ |
53 | unsigned i_ea_size; /* size of extended attributes */ | 54 | unsigned i_ea_size; /* size of extended attributes */ |
54 | unsigned i_conv : 2; /* (files) crlf->newline hackery */ | ||
55 | unsigned i_ea_mode : 1; /* file's permission is stored in ea */ | 55 | unsigned i_ea_mode : 1; /* file's permission is stored in ea */ |
56 | unsigned i_ea_uid : 1; /* file's uid is stored in ea */ | 56 | unsigned i_ea_uid : 1; /* file's uid is stored in ea */ |
57 | unsigned i_ea_gid : 1; /* file's gid is stored in ea */ | 57 | unsigned i_ea_gid : 1; /* file's gid is stored in ea */ |
58 | unsigned i_dirty : 1; | 58 | unsigned i_dirty : 1; |
59 | struct mutex i_mutex; | ||
60 | struct mutex i_parent_mutex; | ||
61 | loff_t **i_rddir_off; | 59 | loff_t **i_rddir_off; |
62 | struct inode vfs_inode; | 60 | struct inode vfs_inode; |
63 | }; | 61 | }; |
64 | 62 | ||
65 | struct hpfs_sb_info { | 63 | struct hpfs_sb_info { |
64 | struct mutex hpfs_mutex; /* global hpfs lock */ | ||
66 | ino_t sb_root; /* inode number of root dir */ | 65 | ino_t sb_root; /* inode number of root dir */ |
67 | unsigned sb_fs_size; /* file system size, sectors */ | 66 | unsigned sb_fs_size; /* file system size, sectors */ |
68 | unsigned sb_bitmaps; /* sector number of bitmap list */ | 67 | unsigned sb_bitmaps; /* sector number of bitmap list */ |
@@ -74,7 +73,6 @@ struct hpfs_sb_info { | |||
74 | uid_t sb_uid; /* uid from mount options */ | 73 | uid_t sb_uid; /* uid from mount options */ |
75 | gid_t sb_gid; /* gid from mount options */ | 74 | gid_t sb_gid; /* gid from mount options */ |
76 | umode_t sb_mode; /* mode from mount options */ | 75 | umode_t sb_mode; /* mode from mount options */ |
77 | unsigned sb_conv : 2; /* crlf->newline hackery */ | ||
78 | unsigned sb_eas : 2; /* eas: 0-ignore, 1-ro, 2-rw */ | 76 | unsigned sb_eas : 2; /* eas: 0-ignore, 1-ro, 2-rw */ |
79 | unsigned sb_err : 2; /* on errs: 0-cont, 1-ro, 2-panic */ | 77 | unsigned sb_err : 2; /* on errs: 0-cont, 1-ro, 2-panic */ |
80 | unsigned sb_chk : 2; /* checks: 0-no, 1-normal, 2-strict */ | 78 | unsigned sb_chk : 2; /* checks: 0-no, 1-normal, 2-strict */ |
@@ -87,20 +85,9 @@ struct hpfs_sb_info { | |||
87 | unsigned *sb_bmp_dir; /* main bitmap directory */ | 85 | unsigned *sb_bmp_dir; /* main bitmap directory */ |
88 | unsigned sb_c_bitmap; /* current bitmap */ | 86 | unsigned sb_c_bitmap; /* current bitmap */ |
89 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ | 87 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ |
90 | struct mutex hpfs_creation_de; /* when creating dirents, nobody else | ||
91 | can alloc blocks */ | ||
92 | /*unsigned sb_mounting : 1;*/ | ||
93 | int sb_timeshift; | 88 | int sb_timeshift; |
94 | }; | 89 | }; |
95 | 90 | ||
96 | /* | ||
97 | * conv= options | ||
98 | */ | ||
99 | |||
100 | #define CONV_BINARY 0 /* no conversion */ | ||
101 | #define CONV_TEXT 1 /* crlf->newline */ | ||
102 | #define CONV_AUTO 2 /* decide based on file contents */ | ||
103 | |||
104 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ | 91 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ |
105 | 92 | ||
106 | struct quad_buffer_head { | 93 | struct quad_buffer_head { |
@@ -113,7 +100,7 @@ struct quad_buffer_head { | |||
113 | static inline dnode_secno de_down_pointer (struct hpfs_dirent *de) | 100 | static inline dnode_secno de_down_pointer (struct hpfs_dirent *de) |
114 | { | 101 | { |
115 | CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); | 102 | CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); |
116 | return *(dnode_secno *) ((void *) de + de->length - 4); | 103 | return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4)); |
117 | } | 104 | } |
118 | 105 | ||
119 | /* The first dir entry in a dnode */ | 106 | /* The first dir entry in a dnode */ |
@@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode) | |||
127 | 114 | ||
128 | static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode) | 115 | static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode) |
129 | { | 116 | { |
130 | CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free)); | 117 | CHKCOND(le32_to_cpu(dnode->first_free)>=0x14 && le32_to_cpu(dnode->first_free)<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %x\n",(unsigned)le32_to_cpu(dnode->first_free))); |
131 | return (void *) dnode + dnode->first_free; | 118 | return (void *) dnode + le32_to_cpu(dnode->first_free); |
132 | } | 119 | } |
133 | 120 | ||
134 | /* The dir entry after dir entry de */ | 121 | /* The dir entry after dir entry de */ |
135 | 122 | ||
136 | static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de) | 123 | static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de) |
137 | { | 124 | { |
138 | CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length)); | 125 | CHKCOND(le16_to_cpu(de->length)>=0x20 && le16_to_cpu(de->length)<0x800,("HPFS: de_next_de: de->length = %x\n",(unsigned)le16_to_cpu(de->length))); |
139 | return (void *) de + de->length; | 126 | return (void *) de + le16_to_cpu(de->length); |
140 | } | 127 | } |
141 | 128 | ||
142 | static inline struct extended_attribute *fnode_ea(struct fnode *fnode) | 129 | static inline struct extended_attribute *fnode_ea(struct fnode *fnode) |
143 | { | 130 | { |
144 | return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s); | 131 | return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s)); |
145 | } | 132 | } |
146 | 133 | ||
147 | static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode) | 134 | static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode) |
148 | { | 135 | { |
149 | return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s); | 136 | return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s)); |
137 | } | ||
138 | |||
139 | static unsigned ea_valuelen(struct extended_attribute *ea) | ||
140 | { | ||
141 | return ea->valuelen_lo + 256 * ea->valuelen_hi; | ||
150 | } | 142 | } |
151 | 143 | ||
152 | static inline struct extended_attribute *next_ea(struct extended_attribute *ea) | 144 | static inline struct extended_attribute *next_ea(struct extended_attribute *ea) |
153 | { | 145 | { |
154 | return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen); | 146 | return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea)); |
155 | } | 147 | } |
156 | 148 | ||
157 | static inline secno ea_sec(struct extended_attribute *ea) | 149 | static inline secno ea_sec(struct extended_attribute *ea) |
158 | { | 150 | { |
159 | return *(secno *)((char *)ea + 9 + ea->namelen); | 151 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen))); |
160 | } | 152 | } |
161 | 153 | ||
162 | static inline secno ea_len(struct extended_attribute *ea) | 154 | static inline secno ea_len(struct extended_attribute *ea) |
163 | { | 155 | { |
164 | return *(secno *)((char *)ea + 5 + ea->namelen); | 156 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen))); |
165 | } | 157 | } |
166 | 158 | ||
167 | static inline char *ea_data(struct extended_attribute *ea) | 159 | static inline char *ea_data(struct extended_attribute *ea) |
@@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src) | |||
186 | dst->not_8x3 = n; | 178 | dst->not_8x3 = n; |
187 | } | 179 | } |
188 | 180 | ||
189 | static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n) | 181 | static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n) |
190 | { | 182 | { |
191 | int i; | 183 | int i; |
192 | if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; | 184 | if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; |
193 | if (!((bmp[(b & 0x3fff) >> 5] >> (b & 0x1f)) & 1)) return 1; | 185 | if (!((le32_to_cpu(bmp[(b & 0x3fff) >> 5]) >> (b & 0x1f)) & 1)) return 1; |
194 | for (i = 1; i < n; i++) | 186 | for (i = 1; i < n; i++) |
195 | if (/*b+i < 0x4000 &&*/ !((bmp[((b+i) & 0x3fff) >> 5] >> ((b+i) & 0x1f)) & 1)) | 187 | if (!((le32_to_cpu(bmp[((b+i) & 0x3fff) >> 5]) >> ((b+i) & 0x1f)) & 1)) |
196 | return i + 1; | 188 | return i + 1; |
197 | return 0; | 189 | return 0; |
198 | } | 190 | } |
@@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n) | |||
200 | /* alloc.c */ | 192 | /* alloc.c */ |
201 | 193 | ||
202 | int hpfs_chk_sectors(struct super_block *, secno, int, char *); | 194 | int hpfs_chk_sectors(struct super_block *, secno, int, char *); |
203 | secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int); | 195 | secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int); |
204 | int hpfs_alloc_if_possible(struct super_block *, secno); | 196 | int hpfs_alloc_if_possible(struct super_block *, secno); |
205 | void hpfs_free_sectors(struct super_block *, secno, unsigned); | 197 | void hpfs_free_sectors(struct super_block *, secno, unsigned); |
206 | int hpfs_check_free_dnodes(struct super_block *, int); | 198 | int hpfs_check_free_dnodes(struct super_block *, int); |
207 | void hpfs_free_dnode(struct super_block *, secno); | 199 | void hpfs_free_dnode(struct super_block *, secno); |
208 | struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *, int); | 200 | struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *); |
209 | struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); | 201 | struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); |
210 | struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); | 202 | struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); |
211 | 203 | ||
@@ -222,8 +214,6 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno); | |||
222 | 214 | ||
223 | /* buffer.c */ | 215 | /* buffer.c */ |
224 | 216 | ||
225 | void hpfs_lock_creation(struct super_block *); | ||
226 | void hpfs_unlock_creation(struct super_block *); | ||
227 | void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); | 217 | void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); |
228 | void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); | 218 | void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); |
229 | void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int); | 219 | void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int); |
@@ -247,7 +237,7 @@ void hpfs_del_pos(struct inode *, loff_t *); | |||
247 | struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, | 237 | struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, |
248 | const unsigned char *, unsigned, secno); | 238 | const unsigned char *, unsigned, secno); |
249 | int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned, | 239 | int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned, |
250 | struct hpfs_dirent *, int); | 240 | struct hpfs_dirent *); |
251 | int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int); | 241 | int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int); |
252 | void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *); | 242 | void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *); |
253 | dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno); | 243 | dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno); |
@@ -303,7 +293,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned, | |||
303 | const unsigned char *, unsigned, int); | 293 | const unsigned char *, unsigned, int); |
304 | int hpfs_is_name_long(const unsigned char *, unsigned); | 294 | int hpfs_is_name_long(const unsigned char *, unsigned); |
305 | void hpfs_adjust_length(const unsigned char *, unsigned *); | 295 | void hpfs_adjust_length(const unsigned char *, unsigned *); |
306 | void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned); | ||
307 | 296 | ||
308 | /* namei.c */ | 297 | /* namei.c */ |
309 | 298 | ||
@@ -346,21 +335,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t) | |||
346 | /* | 335 | /* |
347 | * Locking: | 336 | * Locking: |
348 | * | 337 | * |
349 | * hpfs_lock() is a leftover from the big kernel lock. | 338 | * hpfs_lock() locks the whole filesystem. It must be taken |
350 | * Right now, these functions are empty and only left | 339 | * on any method called by the VFS. |
351 | * for documentation purposes. The file system no longer | ||
352 | * works on SMP systems, so the lock is not needed | ||
353 | * any more. | ||
354 | * | 340 | * |
355 | * If someone is interested in making it work again, this | 341 | * We don't do any per-file locking anymore, it is hard to |
356 | * would be the place to start by adding a per-superblock | 342 | * review and HPFS is not performance-sensitive anyway. |
357 | * mutex and fixing all the bugs and performance issues | ||
358 | * caused by that. | ||
359 | */ | 343 | */ |
360 | static inline void hpfs_lock(struct super_block *s) | 344 | static inline void hpfs_lock(struct super_block *s) |
361 | { | 345 | { |
346 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
347 | mutex_lock(&sbi->hpfs_mutex); | ||
362 | } | 348 | } |
363 | 349 | ||
364 | static inline void hpfs_unlock(struct super_block *s) | 350 | static inline void hpfs_unlock(struct super_block *s) |
365 | { | 351 | { |
352 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
353 | mutex_unlock(&sbi->hpfs_mutex); | ||
354 | } | ||
355 | |||
356 | static inline void hpfs_lock_assert(struct super_block *s) | ||
357 | { | ||
358 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
359 | WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex)); | ||
366 | } | 360 | } |
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 87f1f787e767..338cd8368451 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c | |||
@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i) | |||
17 | i->i_uid = hpfs_sb(sb)->sb_uid; | 17 | i->i_uid = hpfs_sb(sb)->sb_uid; |
18 | i->i_gid = hpfs_sb(sb)->sb_gid; | 18 | i->i_gid = hpfs_sb(sb)->sb_gid; |
19 | i->i_mode = hpfs_sb(sb)->sb_mode; | 19 | i->i_mode = hpfs_sb(sb)->sb_mode; |
20 | hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv; | ||
21 | i->i_size = -1; | 20 | i->i_size = -1; |
22 | i->i_blocks = -1; | 21 | i->i_blocks = -1; |
23 | 22 | ||
@@ -116,8 +115,8 @@ void hpfs_read_inode(struct inode *i) | |||
116 | i->i_mode |= S_IFDIR; | 115 | i->i_mode |= S_IFDIR; |
117 | i->i_op = &hpfs_dir_iops; | 116 | i->i_op = &hpfs_dir_iops; |
118 | i->i_fop = &hpfs_dir_ops; | 117 | i->i_fop = &hpfs_dir_ops; |
119 | hpfs_inode->i_parent_dir = fnode->up; | 118 | hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up); |
120 | hpfs_inode->i_dno = fnode->u.external[0].disk_secno; | 119 | hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno); |
121 | if (hpfs_sb(sb)->sb_chk >= 2) { | 120 | if (hpfs_sb(sb)->sb_chk >= 2) { |
122 | struct buffer_head *bh0; | 121 | struct buffer_head *bh0; |
123 | if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); | 122 | if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); |
@@ -133,7 +132,7 @@ void hpfs_read_inode(struct inode *i) | |||
133 | i->i_op = &hpfs_file_iops; | 132 | i->i_op = &hpfs_file_iops; |
134 | i->i_fop = &hpfs_file_ops; | 133 | i->i_fop = &hpfs_file_ops; |
135 | i->i_nlink = 1; | 134 | i->i_nlink = 1; |
136 | i->i_size = fnode->file_size; | 135 | i->i_size = le32_to_cpu(fnode->file_size); |
137 | i->i_blocks = ((i->i_size + 511) >> 9) + 1; | 136 | i->i_blocks = ((i->i_size + 511) >> 9) + 1; |
138 | i->i_data.a_ops = &hpfs_aops; | 137 | i->i_data.a_ops = &hpfs_aops; |
139 | hpfs_i(i)->mmu_private = i->i_size; | 138 | hpfs_i(i)->mmu_private = i->i_size; |
@@ -144,7 +143,7 @@ void hpfs_read_inode(struct inode *i) | |||
144 | static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) | 143 | static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) |
145 | { | 144 | { |
146 | struct hpfs_inode_info *hpfs_inode = hpfs_i(i); | 145 | struct hpfs_inode_info *hpfs_inode = hpfs_i(i); |
147 | /*if (fnode->acl_size_l || fnode->acl_size_s) { | 146 | /*if (le32_to_cpu(fnode->acl_size_l) || le16_to_cpu(fnode->acl_size_s)) { |
148 | Some unknown structures like ACL may be in fnode, | 147 | Some unknown structures like ACL may be in fnode, |
149 | we'd better not overwrite them | 148 | we'd better not overwrite them |
150 | hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); | 149 | hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); |
@@ -187,9 +186,7 @@ void hpfs_write_inode(struct inode *i) | |||
187 | kfree(hpfs_inode->i_rddir_off); | 186 | kfree(hpfs_inode->i_rddir_off); |
188 | hpfs_inode->i_rddir_off = NULL; | 187 | hpfs_inode->i_rddir_off = NULL; |
189 | } | 188 | } |
190 | mutex_lock(&hpfs_inode->i_parent_mutex); | ||
191 | if (!i->i_nlink) { | 189 | if (!i->i_nlink) { |
192 | mutex_unlock(&hpfs_inode->i_parent_mutex); | ||
193 | return; | 190 | return; |
194 | } | 191 | } |
195 | parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir); | 192 | parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir); |
@@ -200,14 +197,9 @@ void hpfs_write_inode(struct inode *i) | |||
200 | hpfs_read_inode(parent); | 197 | hpfs_read_inode(parent); |
201 | unlock_new_inode(parent); | 198 | unlock_new_inode(parent); |
202 | } | 199 | } |
203 | mutex_lock(&hpfs_inode->i_mutex); | ||
204 | hpfs_write_inode_nolock(i); | 200 | hpfs_write_inode_nolock(i); |
205 | mutex_unlock(&hpfs_inode->i_mutex); | ||
206 | iput(parent); | 201 | iput(parent); |
207 | } else { | ||
208 | mark_inode_dirty(i); | ||
209 | } | 202 | } |
210 | mutex_unlock(&hpfs_inode->i_parent_mutex); | ||
211 | } | 203 | } |
212 | 204 | ||
213 | void hpfs_write_inode_nolock(struct inode *i) | 205 | void hpfs_write_inode_nolock(struct inode *i) |
@@ -226,30 +218,30 @@ void hpfs_write_inode_nolock(struct inode *i) | |||
226 | } | 218 | } |
227 | } else de = NULL; | 219 | } else de = NULL; |
228 | if (S_ISREG(i->i_mode)) { | 220 | if (S_ISREG(i->i_mode)) { |
229 | fnode->file_size = i->i_size; | 221 | fnode->file_size = cpu_to_le32(i->i_size); |
230 | if (de) de->file_size = i->i_size; | 222 | if (de) de->file_size = cpu_to_le32(i->i_size); |
231 | } else if (S_ISDIR(i->i_mode)) { | 223 | } else if (S_ISDIR(i->i_mode)) { |
232 | fnode->file_size = 0; | 224 | fnode->file_size = cpu_to_le32(0); |
233 | if (de) de->file_size = 0; | 225 | if (de) de->file_size = cpu_to_le32(0); |
234 | } | 226 | } |
235 | hpfs_write_inode_ea(i, fnode); | 227 | hpfs_write_inode_ea(i, fnode); |
236 | if (de) { | 228 | if (de) { |
237 | de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); | 229 | de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec)); |
238 | de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); | 230 | de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec)); |
239 | de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); | 231 | de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec)); |
240 | de->read_only = !(i->i_mode & 0222); | 232 | de->read_only = !(i->i_mode & 0222); |
241 | de->ea_size = hpfs_inode->i_ea_size; | 233 | de->ea_size = cpu_to_le32(hpfs_inode->i_ea_size); |
242 | hpfs_mark_4buffers_dirty(&qbh); | 234 | hpfs_mark_4buffers_dirty(&qbh); |
243 | hpfs_brelse4(&qbh); | 235 | hpfs_brelse4(&qbh); |
244 | } | 236 | } |
245 | if (S_ISDIR(i->i_mode)) { | 237 | if (S_ISDIR(i->i_mode)) { |
246 | if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) { | 238 | if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) { |
247 | de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); | 239 | de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec)); |
248 | de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); | 240 | de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec)); |
249 | de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); | 241 | de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec)); |
250 | de->read_only = !(i->i_mode & 0222); | 242 | de->read_only = !(i->i_mode & 0222); |
251 | de->ea_size = /*hpfs_inode->i_ea_size*/0; | 243 | de->ea_size = cpu_to_le32(/*hpfs_inode->i_ea_size*/0); |
252 | de->file_size = 0; | 244 | de->file_size = cpu_to_le32(0); |
253 | hpfs_mark_4buffers_dirty(&qbh); | 245 | hpfs_mark_4buffers_dirty(&qbh); |
254 | hpfs_brelse4(&qbh); | 246 | hpfs_brelse4(&qbh); |
255 | } else | 247 | } else |
@@ -269,6 +261,10 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
269 | hpfs_lock(inode->i_sb); | 261 | hpfs_lock(inode->i_sb); |
270 | if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root) | 262 | if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root) |
271 | goto out_unlock; | 263 | goto out_unlock; |
264 | if ((attr->ia_valid & ATTR_UID) && attr->ia_uid >= 0x10000) | ||
265 | goto out_unlock; | ||
266 | if ((attr->ia_valid & ATTR_GID) && attr->ia_gid >= 0x10000) | ||
267 | goto out_unlock; | ||
272 | if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) | 268 | if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) |
273 | goto out_unlock; | 269 | goto out_unlock; |
274 | 270 | ||
@@ -284,7 +280,6 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
284 | } | 280 | } |
285 | 281 | ||
286 | setattr_copy(inode, attr); | 282 | setattr_copy(inode, attr); |
287 | mark_inode_dirty(inode); | ||
288 | 283 | ||
289 | hpfs_write_inode(inode); | 284 | hpfs_write_inode(inode); |
290 | 285 | ||
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index 840d033ecee8..a790821366a7 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c | |||
@@ -21,7 +21,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, | |||
21 | hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); | 21 | hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); |
22 | return NULL; | 22 | return NULL; |
23 | } | 23 | } |
24 | sec = hpfs_sb(s)->sb_bmp_dir[bmp_block]; | 24 | sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]); |
25 | if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) { | 25 | if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) { |
26 | hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id); | 26 | hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id); |
27 | return NULL; | 27 | return NULL; |
@@ -46,18 +46,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) | |||
46 | struct code_page_data *cpd; | 46 | struct code_page_data *cpd; |
47 | struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0); | 47 | struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0); |
48 | if (!cp) return NULL; | 48 | if (!cp) return NULL; |
49 | if (cp->magic != CP_DIR_MAGIC) { | 49 | if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) { |
50 | printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic); | 50 | printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", le32_to_cpu(cp->magic)); |
51 | brelse(bh); | 51 | brelse(bh); |
52 | return NULL; | 52 | return NULL; |
53 | } | 53 | } |
54 | if (!cp->n_code_pages) { | 54 | if (!le32_to_cpu(cp->n_code_pages)) { |
55 | printk("HPFS: n_code_pages == 0\n"); | 55 | printk("HPFS: n_code_pages == 0\n"); |
56 | brelse(bh); | 56 | brelse(bh); |
57 | return NULL; | 57 | return NULL; |
58 | } | 58 | } |
59 | cpds = cp->array[0].code_page_data; | 59 | cpds = le32_to_cpu(cp->array[0].code_page_data); |
60 | cpi = cp->array[0].index; | 60 | cpi = le16_to_cpu(cp->array[0].index); |
61 | brelse(bh); | 61 | brelse(bh); |
62 | 62 | ||
63 | if (cpi >= 3) { | 63 | if (cpi >= 3) { |
@@ -66,12 +66,12 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; | 68 | if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; |
69 | if ((unsigned)cpd->offs[cpi] > 0x178) { | 69 | if (le16_to_cpu(cpd->offs[cpi]) > 0x178) { |
70 | printk("HPFS: Code page index out of sector\n"); | 70 | printk("HPFS: Code page index out of sector\n"); |
71 | brelse(bh); | 71 | brelse(bh); |
72 | return NULL; | 72 | return NULL; |
73 | } | 73 | } |
74 | ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6; | 74 | ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6; |
75 | if (!(cp_table = kmalloc(256, GFP_KERNEL))) { | 75 | if (!(cp_table = kmalloc(256, GFP_KERNEL))) { |
76 | printk("HPFS: out of memory for code page table\n"); | 76 | printk("HPFS: out of memory for code page table\n"); |
77 | brelse(bh); | 77 | brelse(bh); |
@@ -125,7 +125,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea | |||
125 | if (hpfs_sb(s)->sb_chk) { | 125 | if (hpfs_sb(s)->sb_chk) { |
126 | struct extended_attribute *ea; | 126 | struct extended_attribute *ea; |
127 | struct extended_attribute *ea_end; | 127 | struct extended_attribute *ea_end; |
128 | if (fnode->magic != FNODE_MAGIC) { | 128 | if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) { |
129 | hpfs_error(s, "bad magic on fnode %08lx", | 129 | hpfs_error(s, "bad magic on fnode %08lx", |
130 | (unsigned long)ino); | 130 | (unsigned long)ino); |
131 | goto bail; | 131 | goto bail; |
@@ -138,7 +138,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea | |||
138 | (unsigned long)ino); | 138 | (unsigned long)ino); |
139 | goto bail; | 139 | goto bail; |
140 | } | 140 | } |
141 | if (fnode->btree.first_free != | 141 | if (le16_to_cpu(fnode->btree.first_free) != |
142 | 8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { | 142 | 8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { |
143 | hpfs_error(s, | 143 | hpfs_error(s, |
144 | "bad first_free pointer in fnode %08lx", | 144 | "bad first_free pointer in fnode %08lx", |
@@ -146,12 +146,12 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea | |||
146 | goto bail; | 146 | goto bail; |
147 | } | 147 | } |
148 | } | 148 | } |
149 | if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 || | 149 | if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 || |
150 | (signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) { | 150 | le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) { |
151 | hpfs_error(s, | 151 | hpfs_error(s, |
152 | "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x", | 152 | "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x", |
153 | (unsigned long)ino, | 153 | (unsigned long)ino, |
154 | fnode->ea_offs, fnode->ea_size_s); | 154 | le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); |
155 | goto bail; | 155 | goto bail; |
156 | } | 156 | } |
157 | ea = fnode_ea(fnode); | 157 | ea = fnode_ea(fnode); |
@@ -178,16 +178,20 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff | |||
178 | if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL; | 178 | if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL; |
179 | if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD))) | 179 | if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD))) |
180 | if (hpfs_sb(s)->sb_chk) { | 180 | if (hpfs_sb(s)->sb_chk) { |
181 | if (anode->magic != ANODE_MAGIC || anode->self != ano) { | 181 | if (le32_to_cpu(anode->magic) != ANODE_MAGIC) { |
182 | hpfs_error(s, "bad magic on anode %08x", ano); | 182 | hpfs_error(s, "bad magic on anode %08x", ano); |
183 | goto bail; | 183 | goto bail; |
184 | } | 184 | } |
185 | if (le32_to_cpu(anode->self) != ano) { | ||
186 | hpfs_error(s, "self pointer invalid on anode %08x", ano); | ||
187 | goto bail; | ||
188 | } | ||
185 | if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != | 189 | if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != |
186 | (anode->btree.internal ? 60 : 40)) { | 190 | (anode->btree.internal ? 60 : 40)) { |
187 | hpfs_error(s, "bad number of nodes in anode %08x", ano); | 191 | hpfs_error(s, "bad number of nodes in anode %08x", ano); |
188 | goto bail; | 192 | goto bail; |
189 | } | 193 | } |
190 | if (anode->btree.first_free != | 194 | if (le16_to_cpu(anode->btree.first_free) != |
191 | 8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { | 195 | 8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { |
192 | hpfs_error(s, "bad first_free pointer in anode %08x", ano); | 196 | hpfs_error(s, "bad first_free pointer in anode %08x", ano); |
193 | goto bail; | 197 | goto bail; |
@@ -219,26 +223,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, | |||
219 | unsigned p, pp = 0; | 223 | unsigned p, pp = 0; |
220 | unsigned char *d = (unsigned char *)dnode; | 224 | unsigned char *d = (unsigned char *)dnode; |
221 | int b = 0; | 225 | int b = 0; |
222 | if (dnode->magic != DNODE_MAGIC) { | 226 | if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) { |
223 | hpfs_error(s, "bad magic on dnode %08x", secno); | 227 | hpfs_error(s, "bad magic on dnode %08x", secno); |
224 | goto bail; | 228 | goto bail; |
225 | } | 229 | } |
226 | if (dnode->self != secno) | 230 | if (le32_to_cpu(dnode->self) != secno) |
227 | hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self); | 231 | hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self)); |
228 | /* Check dirents - bad dirents would cause infinite | 232 | /* Check dirents - bad dirents would cause infinite |
229 | loops or shooting to memory */ | 233 | loops or shooting to memory */ |
230 | if (dnode->first_free > 2048/* || dnode->first_free < 84*/) { | 234 | if (le32_to_cpu(dnode->first_free) > 2048) { |
231 | hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free); | 235 | hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free)); |
232 | goto bail; | 236 | goto bail; |
233 | } | 237 | } |
234 | for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) { | 238 | for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) { |
235 | struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); | 239 | struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); |
236 | if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) { | 240 | if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) { |
237 | hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); | 241 | hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); |
238 | goto bail; | 242 | goto bail; |
239 | } | 243 | } |
240 | if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) { | 244 | if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) { |
241 | if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok; | 245 | if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & MS_RDONLY) goto ok; |
242 | hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); | 246 | hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); |
243 | goto bail; | 247 | goto bail; |
244 | } | 248 | } |
@@ -251,7 +255,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, | |||
251 | pp = p; | 255 | pp = p; |
252 | 256 | ||
253 | } | 257 | } |
254 | if (p != dnode->first_free) { | 258 | if (p != le32_to_cpu(dnode->first_free)) { |
255 | hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno); | 259 | hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno); |
256 | goto bail; | 260 | goto bail; |
257 | } | 261 | } |
@@ -277,7 +281,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino) | |||
277 | if (!fnode) | 281 | if (!fnode) |
278 | return 0; | 282 | return 0; |
279 | 283 | ||
280 | dno = fnode->u.external[0].disk_secno; | 284 | dno = le32_to_cpu(fnode->u.external[0].disk_secno); |
281 | brelse(bh); | 285 | brelse(bh); |
282 | return dno; | 286 | return dno; |
283 | } | 287 | } |
diff --git a/fs/hpfs/name.c b/fs/hpfs/name.c index f24736d7a439..9acdf338def0 100644 --- a/fs/hpfs/name.c +++ b/fs/hpfs/name.c | |||
@@ -8,39 +8,6 @@ | |||
8 | 8 | ||
9 | #include "hpfs_fn.h" | 9 | #include "hpfs_fn.h" |
10 | 10 | ||
11 | static const char *text_postfix[]={ | ||
12 | ".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF", | ||
13 | ".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS", | ||
14 | ".RC", ".TEX", ".TXT", ".Y", ""}; | ||
15 | |||
16 | static const char *text_prefix[]={ | ||
17 | "AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ", | ||
18 | "MAKEFILE", "READ.ME", "README", "TERMCAP", ""}; | ||
19 | |||
20 | void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len) | ||
21 | { | ||
22 | struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); | ||
23 | int i; | ||
24 | if (hpfs_inode->i_conv != CONV_AUTO) return; | ||
25 | for (i = 0; *text_postfix[i]; i++) { | ||
26 | int l = strlen(text_postfix[i]); | ||
27 | if (l <= len) | ||
28 | if (!hpfs_compare_names(inode->i_sb, text_postfix[i], l, name + len - l, l, 0)) | ||
29 | goto text; | ||
30 | } | ||
31 | for (i = 0; *text_prefix[i]; i++) { | ||
32 | int l = strlen(text_prefix[i]); | ||
33 | if (l <= len) | ||
34 | if (!hpfs_compare_names(inode->i_sb, text_prefix[i], l, name, l, 0)) | ||
35 | goto text; | ||
36 | } | ||
37 | hpfs_inode->i_conv = CONV_BINARY; | ||
38 | return; | ||
39 | text: | ||
40 | hpfs_inode->i_conv = CONV_TEXT; | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | static inline int not_allowed_char(unsigned char c) | 11 | static inline int not_allowed_char(unsigned char c) |
45 | { | 12 | { |
46 | return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' || | 13 | return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' || |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index d5f8c8a19023..1f05839c27a7 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
@@ -29,7 +29,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
29 | fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh); | 29 | fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh); |
30 | if (!fnode) | 30 | if (!fnode) |
31 | goto bail; | 31 | goto bail; |
32 | dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1); | 32 | dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0); |
33 | if (!dnode) | 33 | if (!dnode) |
34 | goto bail1; | 34 | goto bail1; |
35 | memset(&dee, 0, sizeof dee); | 35 | memset(&dee, 0, sizeof dee); |
@@ -37,8 +37,8 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
37 | if (!(mode & 0222)) dee.read_only = 1; | 37 | if (!(mode & 0222)) dee.read_only = 1; |
38 | /*dee.archive = 0;*/ | 38 | /*dee.archive = 0;*/ |
39 | dee.hidden = name[0] == '.'; | 39 | dee.hidden = name[0] == '.'; |
40 | dee.fnode = fno; | 40 | dee.fnode = cpu_to_le32(fno); |
41 | dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); | 41 | dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds())); |
42 | result = new_inode(dir->i_sb); | 42 | result = new_inode(dir->i_sb); |
43 | if (!result) | 43 | if (!result) |
44 | goto bail2; | 44 | goto bail2; |
@@ -46,7 +46,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
46 | result->i_ino = fno; | 46 | result->i_ino = fno; |
47 | hpfs_i(result)->i_parent_dir = dir->i_ino; | 47 | hpfs_i(result)->i_parent_dir = dir->i_ino; |
48 | hpfs_i(result)->i_dno = dno; | 48 | hpfs_i(result)->i_dno = dno; |
49 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); | 49 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)); |
50 | result->i_ctime.tv_nsec = 0; | 50 | result->i_ctime.tv_nsec = 0; |
51 | result->i_mtime.tv_nsec = 0; | 51 | result->i_mtime.tv_nsec = 0; |
52 | result->i_atime.tv_nsec = 0; | 52 | result->i_atime.tv_nsec = 0; |
@@ -60,8 +60,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
60 | if (dee.read_only) | 60 | if (dee.read_only) |
61 | result->i_mode &= ~0222; | 61 | result->i_mode &= ~0222; |
62 | 62 | ||
63 | mutex_lock(&hpfs_i(dir)->i_mutex); | 63 | r = hpfs_add_dirent(dir, name, len, &dee); |
64 | r = hpfs_add_dirent(dir, name, len, &dee, 0); | ||
65 | if (r == 1) | 64 | if (r == 1) |
66 | goto bail3; | 65 | goto bail3; |
67 | if (r == -1) { | 66 | if (r == -1) { |
@@ -70,21 +69,21 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
70 | } | 69 | } |
71 | fnode->len = len; | 70 | fnode->len = len; |
72 | memcpy(fnode->name, name, len > 15 ? 15 : len); | 71 | memcpy(fnode->name, name, len > 15 ? 15 : len); |
73 | fnode->up = dir->i_ino; | 72 | fnode->up = cpu_to_le32(dir->i_ino); |
74 | fnode->dirflag = 1; | 73 | fnode->dirflag = 1; |
75 | fnode->btree.n_free_nodes = 7; | 74 | fnode->btree.n_free_nodes = 7; |
76 | fnode->btree.n_used_nodes = 1; | 75 | fnode->btree.n_used_nodes = 1; |
77 | fnode->btree.first_free = 0x14; | 76 | fnode->btree.first_free = cpu_to_le16(0x14); |
78 | fnode->u.external[0].disk_secno = dno; | 77 | fnode->u.external[0].disk_secno = cpu_to_le32(dno); |
79 | fnode->u.external[0].file_secno = -1; | 78 | fnode->u.external[0].file_secno = cpu_to_le32(-1); |
80 | dnode->root_dnode = 1; | 79 | dnode->root_dnode = 1; |
81 | dnode->up = fno; | 80 | dnode->up = cpu_to_le32(fno); |
82 | de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0); | 81 | de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0); |
83 | de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, get_seconds()); | 82 | de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds())); |
84 | if (!(mode & 0222)) de->read_only = 1; | 83 | if (!(mode & 0222)) de->read_only = 1; |
85 | de->first = de->directory = 1; | 84 | de->first = de->directory = 1; |
86 | /*de->hidden = de->system = 0;*/ | 85 | /*de->hidden = de->system = 0;*/ |
87 | de->fnode = fno; | 86 | de->fnode = cpu_to_le32(fno); |
88 | mark_buffer_dirty(bh); | 87 | mark_buffer_dirty(bh); |
89 | brelse(bh); | 88 | brelse(bh); |
90 | hpfs_mark_4buffers_dirty(&qbh0); | 89 | hpfs_mark_4buffers_dirty(&qbh0); |
@@ -101,11 +100,9 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
101 | hpfs_write_inode_nolock(result); | 100 | hpfs_write_inode_nolock(result); |
102 | } | 101 | } |
103 | d_instantiate(dentry, result); | 102 | d_instantiate(dentry, result); |
104 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
105 | hpfs_unlock(dir->i_sb); | 103 | hpfs_unlock(dir->i_sb); |
106 | return 0; | 104 | return 0; |
107 | bail3: | 105 | bail3: |
108 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
109 | iput(result); | 106 | iput(result); |
110 | bail2: | 107 | bail2: |
111 | hpfs_brelse4(&qbh0); | 108 | hpfs_brelse4(&qbh0); |
@@ -140,8 +137,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc | |||
140 | if (!(mode & 0222)) dee.read_only = 1; | 137 | if (!(mode & 0222)) dee.read_only = 1; |
141 | dee.archive = 1; | 138 | dee.archive = 1; |
142 | dee.hidden = name[0] == '.'; | 139 | dee.hidden = name[0] == '.'; |
143 | dee.fnode = fno; | 140 | dee.fnode = cpu_to_le32(fno); |
144 | dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); | 141 | dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds())); |
145 | 142 | ||
146 | result = new_inode(dir->i_sb); | 143 | result = new_inode(dir->i_sb); |
147 | if (!result) | 144 | if (!result) |
@@ -154,9 +151,8 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc | |||
154 | result->i_op = &hpfs_file_iops; | 151 | result->i_op = &hpfs_file_iops; |
155 | result->i_fop = &hpfs_file_ops; | 152 | result->i_fop = &hpfs_file_ops; |
156 | result->i_nlink = 1; | 153 | result->i_nlink = 1; |
157 | hpfs_decide_conv(result, name, len); | ||
158 | hpfs_i(result)->i_parent_dir = dir->i_ino; | 154 | hpfs_i(result)->i_parent_dir = dir->i_ino; |
159 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); | 155 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)); |
160 | result->i_ctime.tv_nsec = 0; | 156 | result->i_ctime.tv_nsec = 0; |
161 | result->i_mtime.tv_nsec = 0; | 157 | result->i_mtime.tv_nsec = 0; |
162 | result->i_atime.tv_nsec = 0; | 158 | result->i_atime.tv_nsec = 0; |
@@ -168,8 +164,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc | |||
168 | result->i_data.a_ops = &hpfs_aops; | 164 | result->i_data.a_ops = &hpfs_aops; |
169 | hpfs_i(result)->mmu_private = 0; | 165 | hpfs_i(result)->mmu_private = 0; |
170 | 166 | ||
171 | mutex_lock(&hpfs_i(dir)->i_mutex); | 167 | r = hpfs_add_dirent(dir, name, len, &dee); |
172 | r = hpfs_add_dirent(dir, name, len, &dee, 0); | ||
173 | if (r == 1) | 168 | if (r == 1) |
174 | goto bail2; | 169 | goto bail2; |
175 | if (r == -1) { | 170 | if (r == -1) { |
@@ -178,7 +173,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc | |||
178 | } | 173 | } |
179 | fnode->len = len; | 174 | fnode->len = len; |
180 | memcpy(fnode->name, name, len > 15 ? 15 : len); | 175 | memcpy(fnode->name, name, len > 15 ? 15 : len); |
181 | fnode->up = dir->i_ino; | 176 | fnode->up = cpu_to_le32(dir->i_ino); |
182 | mark_buffer_dirty(bh); | 177 | mark_buffer_dirty(bh); |
183 | brelse(bh); | 178 | brelse(bh); |
184 | 179 | ||
@@ -193,12 +188,10 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc | |||
193 | hpfs_write_inode_nolock(result); | 188 | hpfs_write_inode_nolock(result); |
194 | } | 189 | } |
195 | d_instantiate(dentry, result); | 190 | d_instantiate(dentry, result); |
196 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
197 | hpfs_unlock(dir->i_sb); | 191 | hpfs_unlock(dir->i_sb); |
198 | return 0; | 192 | return 0; |
199 | 193 | ||
200 | bail2: | 194 | bail2: |
201 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
202 | iput(result); | 195 | iput(result); |
203 | bail1: | 196 | bail1: |
204 | brelse(bh); | 197 | brelse(bh); |
@@ -232,8 +225,8 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t | |||
232 | if (!(mode & 0222)) dee.read_only = 1; | 225 | if (!(mode & 0222)) dee.read_only = 1; |
233 | dee.archive = 1; | 226 | dee.archive = 1; |
234 | dee.hidden = name[0] == '.'; | 227 | dee.hidden = name[0] == '.'; |
235 | dee.fnode = fno; | 228 | dee.fnode = cpu_to_le32(fno); |
236 | dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); | 229 | dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds())); |
237 | 230 | ||
238 | result = new_inode(dir->i_sb); | 231 | result = new_inode(dir->i_sb); |
239 | if (!result) | 232 | if (!result) |
@@ -242,7 +235,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t | |||
242 | hpfs_init_inode(result); | 235 | hpfs_init_inode(result); |
243 | result->i_ino = fno; | 236 | result->i_ino = fno; |
244 | hpfs_i(result)->i_parent_dir = dir->i_ino; | 237 | hpfs_i(result)->i_parent_dir = dir->i_ino; |
245 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); | 238 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)); |
246 | result->i_ctime.tv_nsec = 0; | 239 | result->i_ctime.tv_nsec = 0; |
247 | result->i_mtime.tv_nsec = 0; | 240 | result->i_mtime.tv_nsec = 0; |
248 | result->i_atime.tv_nsec = 0; | 241 | result->i_atime.tv_nsec = 0; |
@@ -254,8 +247,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t | |||
254 | result->i_blocks = 1; | 247 | result->i_blocks = 1; |
255 | init_special_inode(result, mode, rdev); | 248 | init_special_inode(result, mode, rdev); |
256 | 249 | ||
257 | mutex_lock(&hpfs_i(dir)->i_mutex); | 250 | r = hpfs_add_dirent(dir, name, len, &dee); |
258 | r = hpfs_add_dirent(dir, name, len, &dee, 0); | ||
259 | if (r == 1) | 251 | if (r == 1) |
260 | goto bail2; | 252 | goto bail2; |
261 | if (r == -1) { | 253 | if (r == -1) { |
@@ -264,19 +256,17 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t | |||
264 | } | 256 | } |
265 | fnode->len = len; | 257 | fnode->len = len; |
266 | memcpy(fnode->name, name, len > 15 ? 15 : len); | 258 | memcpy(fnode->name, name, len > 15 ? 15 : len); |
267 | fnode->up = dir->i_ino; | 259 | fnode->up = cpu_to_le32(dir->i_ino); |
268 | mark_buffer_dirty(bh); | 260 | mark_buffer_dirty(bh); |
269 | 261 | ||
270 | insert_inode_hash(result); | 262 | insert_inode_hash(result); |
271 | 263 | ||
272 | hpfs_write_inode_nolock(result); | 264 | hpfs_write_inode_nolock(result); |
273 | d_instantiate(dentry, result); | 265 | d_instantiate(dentry, result); |
274 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
275 | brelse(bh); | 266 | brelse(bh); |
276 | hpfs_unlock(dir->i_sb); | 267 | hpfs_unlock(dir->i_sb); |
277 | return 0; | 268 | return 0; |
278 | bail2: | 269 | bail2: |
279 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
280 | iput(result); | 270 | iput(result); |
281 | bail1: | 271 | bail1: |
282 | brelse(bh); | 272 | brelse(bh); |
@@ -310,8 +300,8 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
310 | memset(&dee, 0, sizeof dee); | 300 | memset(&dee, 0, sizeof dee); |
311 | dee.archive = 1; | 301 | dee.archive = 1; |
312 | dee.hidden = name[0] == '.'; | 302 | dee.hidden = name[0] == '.'; |
313 | dee.fnode = fno; | 303 | dee.fnode = cpu_to_le32(fno); |
314 | dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds()); | 304 | dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds())); |
315 | 305 | ||
316 | result = new_inode(dir->i_sb); | 306 | result = new_inode(dir->i_sb); |
317 | if (!result) | 307 | if (!result) |
@@ -319,7 +309,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
319 | result->i_ino = fno; | 309 | result->i_ino = fno; |
320 | hpfs_init_inode(result); | 310 | hpfs_init_inode(result); |
321 | hpfs_i(result)->i_parent_dir = dir->i_ino; | 311 | hpfs_i(result)->i_parent_dir = dir->i_ino; |
322 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date); | 312 | result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)); |
323 | result->i_ctime.tv_nsec = 0; | 313 | result->i_ctime.tv_nsec = 0; |
324 | result->i_mtime.tv_nsec = 0; | 314 | result->i_mtime.tv_nsec = 0; |
325 | result->i_atime.tv_nsec = 0; | 315 | result->i_atime.tv_nsec = 0; |
@@ -333,8 +323,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
333 | result->i_op = &page_symlink_inode_operations; | 323 | result->i_op = &page_symlink_inode_operations; |
334 | result->i_data.a_ops = &hpfs_symlink_aops; | 324 | result->i_data.a_ops = &hpfs_symlink_aops; |
335 | 325 | ||
336 | mutex_lock(&hpfs_i(dir)->i_mutex); | 326 | r = hpfs_add_dirent(dir, name, len, &dee); |
337 | r = hpfs_add_dirent(dir, name, len, &dee, 0); | ||
338 | if (r == 1) | 327 | if (r == 1) |
339 | goto bail2; | 328 | goto bail2; |
340 | if (r == -1) { | 329 | if (r == -1) { |
@@ -343,7 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
343 | } | 332 | } |
344 | fnode->len = len; | 333 | fnode->len = len; |
345 | memcpy(fnode->name, name, len > 15 ? 15 : len); | 334 | memcpy(fnode->name, name, len > 15 ? 15 : len); |
346 | fnode->up = dir->i_ino; | 335 | fnode->up = cpu_to_le32(dir->i_ino); |
347 | hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink)); | 336 | hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink)); |
348 | mark_buffer_dirty(bh); | 337 | mark_buffer_dirty(bh); |
349 | brelse(bh); | 338 | brelse(bh); |
@@ -352,11 +341,9 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy | |||
352 | 341 | ||
353 | hpfs_write_inode_nolock(result); | 342 | hpfs_write_inode_nolock(result); |
354 | d_instantiate(dentry, result); | 343 | d_instantiate(dentry, result); |
355 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
356 | hpfs_unlock(dir->i_sb); | 344 | hpfs_unlock(dir->i_sb); |
357 | return 0; | 345 | return 0; |
358 | bail2: | 346 | bail2: |
359 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
360 | iput(result); | 347 | iput(result); |
361 | bail1: | 348 | bail1: |
362 | brelse(bh); | 349 | brelse(bh); |
@@ -374,7 +361,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) | |||
374 | struct hpfs_dirent *de; | 361 | struct hpfs_dirent *de; |
375 | struct inode *inode = dentry->d_inode; | 362 | struct inode *inode = dentry->d_inode; |
376 | dnode_secno dno; | 363 | dnode_secno dno; |
377 | fnode_secno fno; | ||
378 | int r; | 364 | int r; |
379 | int rep = 0; | 365 | int rep = 0; |
380 | int err; | 366 | int err; |
@@ -382,8 +368,6 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry) | |||
382 | hpfs_lock(dir->i_sb); | 368 | hpfs_lock(dir->i_sb); |
383 | hpfs_adjust_length(name, &len); | 369 | hpfs_adjust_length(name, &len); |
384 | again: | 370 | again: |
385 | mutex_lock(&hpfs_i(inode)->i_parent_mutex); | ||
386 | mutex_lock(&hpfs_i(dir)->i_mutex); | ||
387 | err = -ENOENT; | 371 | err = -ENOENT; |
388 | de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); | 372 | de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); |
389 | if (!de) | 373 | if (!de) |
@@ -397,7 +381,6 @@ again: | |||
397 | if (de->directory) | 381 | if (de->directory) |
398 | goto out1; | 382 | goto out1; |
399 | 383 | ||
400 | fno = de->fnode; | ||
401 | r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); | 384 | r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); |
402 | switch (r) { | 385 | switch (r) { |
403 | case 1: | 386 | case 1: |
@@ -410,8 +393,6 @@ again: | |||
410 | if (rep++) | 393 | if (rep++) |
411 | break; | 394 | break; |
412 | 395 | ||
413 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
414 | mutex_unlock(&hpfs_i(inode)->i_parent_mutex); | ||
415 | dentry_unhash(dentry); | 396 | dentry_unhash(dentry); |
416 | if (!d_unhashed(dentry)) { | 397 | if (!d_unhashed(dentry)) { |
417 | dput(dentry); | 398 | dput(dentry); |
@@ -445,8 +426,6 @@ again: | |||
445 | out1: | 426 | out1: |
446 | hpfs_brelse4(&qbh); | 427 | hpfs_brelse4(&qbh); |
447 | out: | 428 | out: |
448 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
449 | mutex_unlock(&hpfs_i(inode)->i_parent_mutex); | ||
450 | hpfs_unlock(dir->i_sb); | 429 | hpfs_unlock(dir->i_sb); |
451 | return err; | 430 | return err; |
452 | } | 431 | } |
@@ -459,15 +438,12 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
459 | struct hpfs_dirent *de; | 438 | struct hpfs_dirent *de; |
460 | struct inode *inode = dentry->d_inode; | 439 | struct inode *inode = dentry->d_inode; |
461 | dnode_secno dno; | 440 | dnode_secno dno; |
462 | fnode_secno fno; | ||
463 | int n_items = 0; | 441 | int n_items = 0; |
464 | int err; | 442 | int err; |
465 | int r; | 443 | int r; |
466 | 444 | ||
467 | hpfs_adjust_length(name, &len); | 445 | hpfs_adjust_length(name, &len); |
468 | hpfs_lock(dir->i_sb); | 446 | hpfs_lock(dir->i_sb); |
469 | mutex_lock(&hpfs_i(inode)->i_parent_mutex); | ||
470 | mutex_lock(&hpfs_i(dir)->i_mutex); | ||
471 | err = -ENOENT; | 447 | err = -ENOENT; |
472 | de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); | 448 | de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); |
473 | if (!de) | 449 | if (!de) |
@@ -486,7 +462,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
486 | if (n_items) | 462 | if (n_items) |
487 | goto out1; | 463 | goto out1; |
488 | 464 | ||
489 | fno = de->fnode; | ||
490 | r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); | 465 | r = hpfs_remove_dirent(dir, dno, de, &qbh, 1); |
491 | switch (r) { | 466 | switch (r) { |
492 | case 1: | 467 | case 1: |
@@ -505,8 +480,6 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
505 | out1: | 480 | out1: |
506 | hpfs_brelse4(&qbh); | 481 | hpfs_brelse4(&qbh); |
507 | out: | 482 | out: |
508 | mutex_unlock(&hpfs_i(dir)->i_mutex); | ||
509 | mutex_unlock(&hpfs_i(inode)->i_parent_mutex); | ||
510 | hpfs_unlock(dir->i_sb); | 483 | hpfs_unlock(dir->i_sb); |
511 | return err; | 484 | return err; |
512 | } | 485 | } |
@@ -568,12 +541,6 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
568 | 541 | ||
569 | hpfs_lock(i->i_sb); | 542 | hpfs_lock(i->i_sb); |
570 | /* order doesn't matter, due to VFS exclusion */ | 543 | /* order doesn't matter, due to VFS exclusion */ |
571 | mutex_lock(&hpfs_i(i)->i_parent_mutex); | ||
572 | if (new_inode) | ||
573 | mutex_lock(&hpfs_i(new_inode)->i_parent_mutex); | ||
574 | mutex_lock(&hpfs_i(old_dir)->i_mutex); | ||
575 | if (new_dir != old_dir) | ||
576 | mutex_lock(&hpfs_i(new_dir)->i_mutex); | ||
577 | 544 | ||
578 | /* Erm? Moving over the empty non-busy directory is perfectly legal */ | 545 | /* Erm? Moving over the empty non-busy directory is perfectly legal */ |
579 | if (new_inode && S_ISDIR(new_inode->i_mode)) { | 546 | if (new_inode && S_ISDIR(new_inode->i_mode)) { |
@@ -610,9 +577,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
610 | 577 | ||
611 | if (new_dir == old_dir) hpfs_brelse4(&qbh); | 578 | if (new_dir == old_dir) hpfs_brelse4(&qbh); |
612 | 579 | ||
613 | hpfs_lock_creation(i->i_sb); | 580 | if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) { |
614 | if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) { | ||
615 | hpfs_unlock_creation(i->i_sb); | ||
616 | if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!"); | 581 | if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!"); |
617 | err = r == 1 ? -ENOSPC : -EFSERROR; | 582 | err = r == 1 ? -ENOSPC : -EFSERROR; |
618 | if (new_dir != old_dir) hpfs_brelse4(&qbh); | 583 | if (new_dir != old_dir) hpfs_brelse4(&qbh); |
@@ -621,20 +586,17 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
621 | 586 | ||
622 | if (new_dir == old_dir) | 587 | if (new_dir == old_dir) |
623 | if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) { | 588 | if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) { |
624 | hpfs_unlock_creation(i->i_sb); | ||
625 | hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2"); | 589 | hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2"); |
626 | err = -ENOENT; | 590 | err = -ENOENT; |
627 | goto end1; | 591 | goto end1; |
628 | } | 592 | } |
629 | 593 | ||
630 | if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) { | 594 | if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) { |
631 | hpfs_unlock_creation(i->i_sb); | ||
632 | hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent"); | 595 | hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent"); |
633 | err = r == 2 ? -ENOSPC : -EFSERROR; | 596 | err = r == 2 ? -ENOSPC : -EFSERROR; |
634 | goto end1; | 597 | goto end1; |
635 | } | 598 | } |
636 | hpfs_unlock_creation(i->i_sb); | 599 | |
637 | |||
638 | end: | 600 | end: |
639 | hpfs_i(i)->i_parent_dir = new_dir->i_ino; | 601 | hpfs_i(i)->i_parent_dir = new_dir->i_ino; |
640 | if (S_ISDIR(i->i_mode)) { | 602 | if (S_ISDIR(i->i_mode)) { |
@@ -642,22 +604,14 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
642 | drop_nlink(old_dir); | 604 | drop_nlink(old_dir); |
643 | } | 605 | } |
644 | if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) { | 606 | if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) { |
645 | fnode->up = new_dir->i_ino; | 607 | fnode->up = cpu_to_le32(new_dir->i_ino); |
646 | fnode->len = new_len; | 608 | fnode->len = new_len; |
647 | memcpy(fnode->name, new_name, new_len>15?15:new_len); | 609 | memcpy(fnode->name, new_name, new_len>15?15:new_len); |
648 | if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len); | 610 | if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len); |
649 | mark_buffer_dirty(bh); | 611 | mark_buffer_dirty(bh); |
650 | brelse(bh); | 612 | brelse(bh); |
651 | } | 613 | } |
652 | hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv; | ||
653 | hpfs_decide_conv(i, new_name, new_len); | ||
654 | end1: | 614 | end1: |
655 | if (old_dir != new_dir) | ||
656 | mutex_unlock(&hpfs_i(new_dir)->i_mutex); | ||
657 | mutex_unlock(&hpfs_i(old_dir)->i_mutex); | ||
658 | mutex_unlock(&hpfs_i(i)->i_parent_mutex); | ||
659 | if (new_inode) | ||
660 | mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex); | ||
661 | hpfs_unlock(i->i_sb); | 615 | hpfs_unlock(i->i_sb); |
662 | return err; | 616 | return err; |
663 | } | 617 | } |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index c89b40808587..98580a3b5005 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -18,15 +18,16 @@ | |||
18 | 18 | ||
19 | /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ | 19 | /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ |
20 | 20 | ||
21 | static void mark_dirty(struct super_block *s) | 21 | static void mark_dirty(struct super_block *s, int remount) |
22 | { | 22 | { |
23 | if (hpfs_sb(s)->sb_chkdsk && !(s->s_flags & MS_RDONLY)) { | 23 | if (hpfs_sb(s)->sb_chkdsk && (remount || !(s->s_flags & MS_RDONLY))) { |
24 | struct buffer_head *bh; | 24 | struct buffer_head *bh; |
25 | struct hpfs_spare_block *sb; | 25 | struct hpfs_spare_block *sb; |
26 | if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { | 26 | if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { |
27 | sb->dirty = 1; | 27 | sb->dirty = 1; |
28 | sb->old_wrote = 0; | 28 | sb->old_wrote = 0; |
29 | mark_buffer_dirty(bh); | 29 | mark_buffer_dirty(bh); |
30 | sync_dirty_buffer(bh); | ||
30 | brelse(bh); | 31 | brelse(bh); |
31 | } | 32 | } |
32 | } | 33 | } |
@@ -40,10 +41,12 @@ static void unmark_dirty(struct super_block *s) | |||
40 | struct buffer_head *bh; | 41 | struct buffer_head *bh; |
41 | struct hpfs_spare_block *sb; | 42 | struct hpfs_spare_block *sb; |
42 | if (s->s_flags & MS_RDONLY) return; | 43 | if (s->s_flags & MS_RDONLY) return; |
44 | sync_blockdev(s->s_bdev); | ||
43 | if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { | 45 | if ((sb = hpfs_map_sector(s, 17, &bh, 0))) { |
44 | sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error; | 46 | sb->dirty = hpfs_sb(s)->sb_chkdsk > 1 - hpfs_sb(s)->sb_was_error; |
45 | sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error; | 47 | sb->old_wrote = hpfs_sb(s)->sb_chkdsk >= 2 && !hpfs_sb(s)->sb_was_error; |
46 | mark_buffer_dirty(bh); | 48 | mark_buffer_dirty(bh); |
49 | sync_dirty_buffer(bh); | ||
47 | brelse(bh); | 50 | brelse(bh); |
48 | } | 51 | } |
49 | } | 52 | } |
@@ -63,13 +66,13 @@ void hpfs_error(struct super_block *s, const char *fmt, ...) | |||
63 | if (!hpfs_sb(s)->sb_was_error) { | 66 | if (!hpfs_sb(s)->sb_was_error) { |
64 | if (hpfs_sb(s)->sb_err == 2) { | 67 | if (hpfs_sb(s)->sb_err == 2) { |
65 | printk("; crashing the system because you wanted it\n"); | 68 | printk("; crashing the system because you wanted it\n"); |
66 | mark_dirty(s); | 69 | mark_dirty(s, 0); |
67 | panic("HPFS panic"); | 70 | panic("HPFS panic"); |
68 | } else if (hpfs_sb(s)->sb_err == 1) { | 71 | } else if (hpfs_sb(s)->sb_err == 1) { |
69 | if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n"); | 72 | if (s->s_flags & MS_RDONLY) printk("; already mounted read-only\n"); |
70 | else { | 73 | else { |
71 | printk("; remounting read-only\n"); | 74 | printk("; remounting read-only\n"); |
72 | mark_dirty(s); | 75 | mark_dirty(s, 0); |
73 | s->s_flags |= MS_RDONLY; | 76 | s->s_flags |= MS_RDONLY; |
74 | } | 77 | } |
75 | } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n"); | 78 | } else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n"); |
@@ -102,9 +105,12 @@ static void hpfs_put_super(struct super_block *s) | |||
102 | { | 105 | { |
103 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 106 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
104 | 107 | ||
108 | hpfs_lock(s); | ||
109 | unmark_dirty(s); | ||
110 | hpfs_unlock(s); | ||
111 | |||
105 | kfree(sbi->sb_cp_table); | 112 | kfree(sbi->sb_cp_table); |
106 | kfree(sbi->sb_bmp_dir); | 113 | kfree(sbi->sb_bmp_dir); |
107 | unmark_dirty(s); | ||
108 | s->s_fs_info = NULL; | 114 | s->s_fs_info = NULL; |
109 | kfree(sbi); | 115 | kfree(sbi); |
110 | } | 116 | } |
@@ -129,7 +135,7 @@ static unsigned count_bitmaps(struct super_block *s) | |||
129 | n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; | 135 | n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; |
130 | count = 0; | 136 | count = 0; |
131 | for (n = 0; n < n_bands; n++) | 137 | for (n = 0; n < n_bands; n++) |
132 | count += hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_bmp_dir[n]); | 138 | count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n])); |
133 | return count; | 139 | return count; |
134 | } | 140 | } |
135 | 141 | ||
@@ -188,8 +194,6 @@ static void init_once(void *foo) | |||
188 | { | 194 | { |
189 | struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; | 195 | struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; |
190 | 196 | ||
191 | mutex_init(&ei->i_mutex); | ||
192 | mutex_init(&ei->i_parent_mutex); | ||
193 | inode_init_once(&ei->vfs_inode); | 197 | inode_init_once(&ei->vfs_inode); |
194 | } | 198 | } |
195 | 199 | ||
@@ -218,7 +222,6 @@ static void destroy_inodecache(void) | |||
218 | 222 | ||
219 | enum { | 223 | enum { |
220 | Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis, | 224 | Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis, |
221 | Opt_conv_binary, Opt_conv_text, Opt_conv_auto, | ||
222 | Opt_check_none, Opt_check_normal, Opt_check_strict, | 225 | Opt_check_none, Opt_check_normal, Opt_check_strict, |
223 | Opt_err_cont, Opt_err_ro, Opt_err_panic, | 226 | Opt_err_cont, Opt_err_ro, Opt_err_panic, |
224 | Opt_eas_no, Opt_eas_ro, Opt_eas_rw, | 227 | Opt_eas_no, Opt_eas_ro, Opt_eas_rw, |
@@ -233,9 +236,6 @@ static const match_table_t tokens = { | |||
233 | {Opt_umask, "umask=%o"}, | 236 | {Opt_umask, "umask=%o"}, |
234 | {Opt_case_lower, "case=lower"}, | 237 | {Opt_case_lower, "case=lower"}, |
235 | {Opt_case_asis, "case=asis"}, | 238 | {Opt_case_asis, "case=asis"}, |
236 | {Opt_conv_binary, "conv=binary"}, | ||
237 | {Opt_conv_text, "conv=text"}, | ||
238 | {Opt_conv_auto, "conv=auto"}, | ||
239 | {Opt_check_none, "check=none"}, | 239 | {Opt_check_none, "check=none"}, |
240 | {Opt_check_normal, "check=normal"}, | 240 | {Opt_check_normal, "check=normal"}, |
241 | {Opt_check_strict, "check=strict"}, | 241 | {Opt_check_strict, "check=strict"}, |
@@ -253,7 +253,7 @@ static const match_table_t tokens = { | |||
253 | }; | 253 | }; |
254 | 254 | ||
255 | static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask, | 255 | static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask, |
256 | int *lowercase, int *conv, int *eas, int *chk, int *errs, | 256 | int *lowercase, int *eas, int *chk, int *errs, |
257 | int *chkdsk, int *timeshift) | 257 | int *chkdsk, int *timeshift) |
258 | { | 258 | { |
259 | char *p; | 259 | char *p; |
@@ -295,15 +295,6 @@ static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask, | |||
295 | case Opt_case_asis: | 295 | case Opt_case_asis: |
296 | *lowercase = 0; | 296 | *lowercase = 0; |
297 | break; | 297 | break; |
298 | case Opt_conv_binary: | ||
299 | *conv = CONV_BINARY; | ||
300 | break; | ||
301 | case Opt_conv_text: | ||
302 | *conv = CONV_TEXT; | ||
303 | break; | ||
304 | case Opt_conv_auto: | ||
305 | *conv = CONV_AUTO; | ||
306 | break; | ||
307 | case Opt_check_none: | 298 | case Opt_check_none: |
308 | *chk = 0; | 299 | *chk = 0; |
309 | break; | 300 | break; |
@@ -370,9 +361,6 @@ HPFS filesystem options:\n\ | |||
370 | umask=xxx set mode of files that don't have mode specified in eas\n\ | 361 | umask=xxx set mode of files that don't have mode specified in eas\n\ |
371 | case=lower lowercase all files\n\ | 362 | case=lower lowercase all files\n\ |
372 | case=asis do not lowercase files (default)\n\ | 363 | case=asis do not lowercase files (default)\n\ |
373 | conv=binary do not convert CR/LF -> LF (default)\n\ | ||
374 | conv=auto convert only files with known text extensions\n\ | ||
375 | conv=text convert all files\n\ | ||
376 | check=none no fs checks - kernel may crash on corrupted filesystem\n\ | 364 | check=none no fs checks - kernel may crash on corrupted filesystem\n\ |
377 | check=normal do some checks - it should not crash (default)\n\ | 365 | check=normal do some checks - it should not crash (default)\n\ |
378 | check=strict do extra time-consuming checks, used for debugging\n\ | 366 | check=strict do extra time-consuming checks, used for debugging\n\ |
@@ -394,7 +382,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
394 | uid_t uid; | 382 | uid_t uid; |
395 | gid_t gid; | 383 | gid_t gid; |
396 | umode_t umask; | 384 | umode_t umask; |
397 | int lowercase, conv, eas, chk, errs, chkdsk, timeshift; | 385 | int lowercase, eas, chk, errs, chkdsk, timeshift; |
398 | int o; | 386 | int o; |
399 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 387 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
400 | char *new_opts = kstrdup(data, GFP_KERNEL); | 388 | char *new_opts = kstrdup(data, GFP_KERNEL); |
@@ -405,11 +393,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
405 | lock_super(s); | 393 | lock_super(s); |
406 | uid = sbi->sb_uid; gid = sbi->sb_gid; | 394 | uid = sbi->sb_uid; gid = sbi->sb_gid; |
407 | umask = 0777 & ~sbi->sb_mode; | 395 | umask = 0777 & ~sbi->sb_mode; |
408 | lowercase = sbi->sb_lowercase; conv = sbi->sb_conv; | 396 | lowercase = sbi->sb_lowercase; |
409 | eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk; | 397 | eas = sbi->sb_eas; chk = sbi->sb_chk; chkdsk = sbi->sb_chkdsk; |
410 | errs = sbi->sb_err; timeshift = sbi->sb_timeshift; | 398 | errs = sbi->sb_err; timeshift = sbi->sb_timeshift; |
411 | 399 | ||
412 | if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, &conv, | 400 | if (!(o = parse_opts(data, &uid, &gid, &umask, &lowercase, |
413 | &eas, &chk, &errs, &chkdsk, ×hift))) { | 401 | &eas, &chk, &errs, &chkdsk, ×hift))) { |
414 | printk("HPFS: bad mount options.\n"); | 402 | printk("HPFS: bad mount options.\n"); |
415 | goto out_err; | 403 | goto out_err; |
@@ -427,11 +415,11 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
427 | 415 | ||
428 | sbi->sb_uid = uid; sbi->sb_gid = gid; | 416 | sbi->sb_uid = uid; sbi->sb_gid = gid; |
429 | sbi->sb_mode = 0777 & ~umask; | 417 | sbi->sb_mode = 0777 & ~umask; |
430 | sbi->sb_lowercase = lowercase; sbi->sb_conv = conv; | 418 | sbi->sb_lowercase = lowercase; |
431 | sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk; | 419 | sbi->sb_eas = eas; sbi->sb_chk = chk; sbi->sb_chkdsk = chkdsk; |
432 | sbi->sb_err = errs; sbi->sb_timeshift = timeshift; | 420 | sbi->sb_err = errs; sbi->sb_timeshift = timeshift; |
433 | 421 | ||
434 | if (!(*flags & MS_RDONLY)) mark_dirty(s); | 422 | if (!(*flags & MS_RDONLY)) mark_dirty(s, 1); |
435 | 423 | ||
436 | replace_mount_options(s, new_opts); | 424 | replace_mount_options(s, new_opts); |
437 | 425 | ||
@@ -471,7 +459,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
471 | uid_t uid; | 459 | uid_t uid; |
472 | gid_t gid; | 460 | gid_t gid; |
473 | umode_t umask; | 461 | umode_t umask; |
474 | int lowercase, conv, eas, chk, errs, chkdsk, timeshift; | 462 | int lowercase, eas, chk, errs, chkdsk, timeshift; |
475 | 463 | ||
476 | dnode_secno root_dno; | 464 | dnode_secno root_dno; |
477 | struct hpfs_dirent *de = NULL; | 465 | struct hpfs_dirent *de = NULL; |
@@ -479,11 +467,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
479 | 467 | ||
480 | int o; | 468 | int o; |
481 | 469 | ||
482 | if (num_possible_cpus() > 1) { | ||
483 | printk(KERN_ERR "HPFS is not SMP safe\n"); | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | save_mount_options(s, options); | 470 | save_mount_options(s, options); |
488 | 471 | ||
489 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 472 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
@@ -495,20 +478,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
495 | sbi->sb_bmp_dir = NULL; | 478 | sbi->sb_bmp_dir = NULL; |
496 | sbi->sb_cp_table = NULL; | 479 | sbi->sb_cp_table = NULL; |
497 | 480 | ||
498 | mutex_init(&sbi->hpfs_creation_de); | 481 | mutex_init(&sbi->hpfs_mutex); |
482 | hpfs_lock(s); | ||
499 | 483 | ||
500 | uid = current_uid(); | 484 | uid = current_uid(); |
501 | gid = current_gid(); | 485 | gid = current_gid(); |
502 | umask = current_umask(); | 486 | umask = current_umask(); |
503 | lowercase = 0; | 487 | lowercase = 0; |
504 | conv = CONV_BINARY; | ||
505 | eas = 2; | 488 | eas = 2; |
506 | chk = 1; | 489 | chk = 1; |
507 | errs = 1; | 490 | errs = 1; |
508 | chkdsk = 1; | 491 | chkdsk = 1; |
509 | timeshift = 0; | 492 | timeshift = 0; |
510 | 493 | ||
511 | if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, &conv, | 494 | if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase, |
512 | &eas, &chk, &errs, &chkdsk, ×hift))) { | 495 | &eas, &chk, &errs, &chkdsk, ×hift))) { |
513 | printk("HPFS: bad mount options.\n"); | 496 | printk("HPFS: bad mount options.\n"); |
514 | goto bail0; | 497 | goto bail0; |
@@ -526,9 +509,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
526 | if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3; | 509 | if (!(spareblock = hpfs_map_sector(s, 17, &bh2, 0))) goto bail3; |
527 | 510 | ||
528 | /* Check magics */ | 511 | /* Check magics */ |
529 | if (/*bootblock->magic != BB_MAGIC | 512 | if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC |
530 | ||*/ superblock->magic != SB_MAGIC | 513 | ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC |
531 | || spareblock->magic != SP_MAGIC) { | 514 | || le32_to_cpu(spareblock->magic) != SP_MAGIC) { |
532 | if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n"); | 515 | if (!silent) printk("HPFS: Bad magic ... probably not HPFS\n"); |
533 | goto bail4; | 516 | goto bail4; |
534 | } | 517 | } |
@@ -549,19 +532,18 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
549 | s->s_op = &hpfs_sops; | 532 | s->s_op = &hpfs_sops; |
550 | s->s_d_op = &hpfs_dentry_operations; | 533 | s->s_d_op = &hpfs_dentry_operations; |
551 | 534 | ||
552 | sbi->sb_root = superblock->root; | 535 | sbi->sb_root = le32_to_cpu(superblock->root); |
553 | sbi->sb_fs_size = superblock->n_sectors; | 536 | sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors); |
554 | sbi->sb_bitmaps = superblock->bitmaps; | 537 | sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps); |
555 | sbi->sb_dirband_start = superblock->dir_band_start; | 538 | sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start); |
556 | sbi->sb_dirband_size = superblock->n_dir_band; | 539 | sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band); |
557 | sbi->sb_dmap = superblock->dir_band_bitmap; | 540 | sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap); |
558 | sbi->sb_uid = uid; | 541 | sbi->sb_uid = uid; |
559 | sbi->sb_gid = gid; | 542 | sbi->sb_gid = gid; |
560 | sbi->sb_mode = 0777 & ~umask; | 543 | sbi->sb_mode = 0777 & ~umask; |
561 | sbi->sb_n_free = -1; | 544 | sbi->sb_n_free = -1; |
562 | sbi->sb_n_free_dnodes = -1; | 545 | sbi->sb_n_free_dnodes = -1; |
563 | sbi->sb_lowercase = lowercase; | 546 | sbi->sb_lowercase = lowercase; |
564 | sbi->sb_conv = conv; | ||
565 | sbi->sb_eas = eas; | 547 | sbi->sb_eas = eas; |
566 | sbi->sb_chk = chk; | 548 | sbi->sb_chk = chk; |
567 | sbi->sb_chkdsk = chkdsk; | 549 | sbi->sb_chkdsk = chkdsk; |
@@ -573,7 +555,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
573 | sbi->sb_max_fwd_alloc = 0xffffff; | 555 | sbi->sb_max_fwd_alloc = 0xffffff; |
574 | 556 | ||
575 | /* Load bitmap directory */ | 557 | /* Load bitmap directory */ |
576 | if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, superblock->bitmaps))) | 558 | if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) |
577 | goto bail4; | 559 | goto bail4; |
578 | 560 | ||
579 | /* Check for general fs errors*/ | 561 | /* Check for general fs errors*/ |
@@ -591,20 +573,20 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
591 | mark_buffer_dirty(bh2); | 573 | mark_buffer_dirty(bh2); |
592 | } | 574 | } |
593 | 575 | ||
594 | if (spareblock->hotfixes_used || spareblock->n_spares_used) { | 576 | if (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) { |
595 | if (errs >= 2) { | 577 | if (errs >= 2) { |
596 | printk("HPFS: Hotfixes not supported here, try chkdsk\n"); | 578 | printk("HPFS: Hotfixes not supported here, try chkdsk\n"); |
597 | mark_dirty(s); | 579 | mark_dirty(s, 0); |
598 | goto bail4; | 580 | goto bail4; |
599 | } | 581 | } |
600 | hpfs_error(s, "hotfixes not supported here, try chkdsk"); | 582 | hpfs_error(s, "hotfixes not supported here, try chkdsk"); |
601 | if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n"); | 583 | if (errs == 0) printk("HPFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n"); |
602 | else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n"); | 584 | else printk("HPFS: This driver may read bad files or crash when operating on disk with hotfixes.\n"); |
603 | } | 585 | } |
604 | if (spareblock->n_dnode_spares != spareblock->n_dnode_spares_free) { | 586 | if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) { |
605 | if (errs >= 2) { | 587 | if (errs >= 2) { |
606 | printk("HPFS: Spare dnodes used, try chkdsk\n"); | 588 | printk("HPFS: Spare dnodes used, try chkdsk\n"); |
607 | mark_dirty(s); | 589 | mark_dirty(s, 0); |
608 | goto bail4; | 590 | goto bail4; |
609 | } | 591 | } |
610 | hpfs_error(s, "warning: spare dnodes used, try chkdsk"); | 592 | hpfs_error(s, "warning: spare dnodes used, try chkdsk"); |
@@ -612,26 +594,26 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
612 | } | 594 | } |
613 | if (chk) { | 595 | if (chk) { |
614 | unsigned a; | 596 | unsigned a; |
615 | if (superblock->dir_band_end - superblock->dir_band_start + 1 != superblock->n_dir_band || | 597 | if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) || |
616 | superblock->dir_band_end < superblock->dir_band_start || superblock->n_dir_band > 0x4000) { | 598 | le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) { |
617 | hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x", | 599 | hpfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x", |
618 | superblock->dir_band_start, superblock->dir_band_end, superblock->n_dir_band); | 600 | le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band)); |
619 | goto bail4; | 601 | goto bail4; |
620 | } | 602 | } |
621 | a = sbi->sb_dirband_size; | 603 | a = sbi->sb_dirband_size; |
622 | sbi->sb_dirband_size = 0; | 604 | sbi->sb_dirband_size = 0; |
623 | if (hpfs_chk_sectors(s, superblock->dir_band_start, superblock->n_dir_band, "dir_band") || | 605 | if (hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") || |
624 | hpfs_chk_sectors(s, superblock->dir_band_bitmap, 4, "dir_band_bitmap") || | 606 | hpfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") || |
625 | hpfs_chk_sectors(s, superblock->bitmaps, 4, "bitmaps")) { | 607 | hpfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) { |
626 | mark_dirty(s); | 608 | mark_dirty(s, 0); |
627 | goto bail4; | 609 | goto bail4; |
628 | } | 610 | } |
629 | sbi->sb_dirband_size = a; | 611 | sbi->sb_dirband_size = a; |
630 | } else printk("HPFS: You really don't want any checks? You are crazy...\n"); | 612 | } else printk("HPFS: You really don't want any checks? You are crazy...\n"); |
631 | 613 | ||
632 | /* Load code page table */ | 614 | /* Load code page table */ |
633 | if (spareblock->n_code_pages) | 615 | if (le32_to_cpu(spareblock->n_code_pages)) |
634 | if (!(sbi->sb_cp_table = hpfs_load_code_page(s, spareblock->code_page_dir))) | 616 | if (!(sbi->sb_cp_table = hpfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir)))) |
635 | printk("HPFS: Warning: code page support is disabled\n"); | 617 | printk("HPFS: Warning: code page support is disabled\n"); |
636 | 618 | ||
637 | brelse(bh2); | 619 | brelse(bh2); |
@@ -660,13 +642,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
660 | if (!de) | 642 | if (!de) |
661 | hpfs_error(s, "unable to find root dir"); | 643 | hpfs_error(s, "unable to find root dir"); |
662 | else { | 644 | else { |
663 | root->i_atime.tv_sec = local_to_gmt(s, de->read_date); | 645 | root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date)); |
664 | root->i_atime.tv_nsec = 0; | 646 | root->i_atime.tv_nsec = 0; |
665 | root->i_mtime.tv_sec = local_to_gmt(s, de->write_date); | 647 | root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date)); |
666 | root->i_mtime.tv_nsec = 0; | 648 | root->i_mtime.tv_nsec = 0; |
667 | root->i_ctime.tv_sec = local_to_gmt(s, de->creation_date); | 649 | root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date)); |
668 | root->i_ctime.tv_nsec = 0; | 650 | root->i_ctime.tv_nsec = 0; |
669 | hpfs_i(root)->i_ea_size = de->ea_size; | 651 | hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size); |
670 | hpfs_i(root)->i_parent_dir = root->i_ino; | 652 | hpfs_i(root)->i_parent_dir = root->i_ino; |
671 | if (root->i_size == -1) | 653 | if (root->i_size == -1) |
672 | root->i_size = 2048; | 654 | root->i_size = 2048; |
@@ -674,6 +656,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
674 | root->i_blocks = 5; | 656 | root->i_blocks = 5; |
675 | hpfs_brelse4(&qbh); | 657 | hpfs_brelse4(&qbh); |
676 | } | 658 | } |
659 | hpfs_unlock(s); | ||
677 | return 0; | 660 | return 0; |
678 | 661 | ||
679 | bail4: brelse(bh2); | 662 | bail4: brelse(bh2); |
@@ -681,6 +664,7 @@ bail3: brelse(bh1); | |||
681 | bail2: brelse(bh0); | 664 | bail2: brelse(bh0); |
682 | bail1: | 665 | bail1: |
683 | bail0: | 666 | bail0: |
667 | hpfs_unlock(s); | ||
684 | kfree(sbi->sb_bmp_dir); | 668 | kfree(sbi->sb_bmp_dir); |
685 | kfree(sbi->sb_cp_table); | 669 | kfree(sbi->sb_cp_table); |
686 | s->s_fs_info = NULL; | 670 | s->s_fs_info = NULL; |
diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 33435e4b14d2..ce03a182c771 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c | |||
@@ -480,10 +480,6 @@ static int logfs_read_sb(struct super_block *sb, int read_only) | |||
480 | !read_only) | 480 | !read_only) |
481 | return -EIO; | 481 | return -EIO; |
482 | 482 | ||
483 | mutex_init(&super->s_dirop_mutex); | ||
484 | mutex_init(&super->s_object_alias_mutex); | ||
485 | INIT_LIST_HEAD(&super->s_freeing_list); | ||
486 | |||
487 | ret = logfs_init_rw(sb); | 483 | ret = logfs_init_rw(sb); |
488 | if (ret) | 484 | if (ret) |
489 | return ret; | 485 | return ret; |
@@ -601,6 +597,10 @@ static struct dentry *logfs_mount(struct file_system_type *type, int flags, | |||
601 | if (!super) | 597 | if (!super) |
602 | return ERR_PTR(-ENOMEM); | 598 | return ERR_PTR(-ENOMEM); |
603 | 599 | ||
600 | mutex_init(&super->s_dirop_mutex); | ||
601 | mutex_init(&super->s_object_alias_mutex); | ||
602 | INIT_LIST_HEAD(&super->s_freeing_list); | ||
603 | |||
604 | if (!devname) | 604 | if (!devname) |
605 | err = logfs_get_sb_bdev(super, type, devname); | 605 | err = logfs_get_sb_bdev(super, type, devname); |
606 | else if (strncmp(devname, "mtd", 3)) | 606 | else if (strncmp(devname, "mtd", 3)) |
diff --git a/fs/namei.c b/fs/namei.c index 54fc993e3027..e3c4f112ebf7 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -179,7 +179,7 @@ EXPORT_SYMBOL(putname); | |||
179 | static int acl_permission_check(struct inode *inode, int mask, unsigned int flags, | 179 | static int acl_permission_check(struct inode *inode, int mask, unsigned int flags, |
180 | int (*check_acl)(struct inode *inode, int mask, unsigned int flags)) | 180 | int (*check_acl)(struct inode *inode, int mask, unsigned int flags)) |
181 | { | 181 | { |
182 | umode_t mode = inode->i_mode; | 182 | unsigned int mode = inode->i_mode; |
183 | 183 | ||
184 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 184 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
185 | 185 | ||
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 89fc160fd5b0..1f063bacd285 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -119,7 +119,7 @@ Elong: | |||
119 | } | 119 | } |
120 | 120 | ||
121 | #ifdef CONFIG_NFS_V4 | 121 | #ifdef CONFIG_NFS_V4 |
122 | static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode) | 122 | static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors) |
123 | { | 123 | { |
124 | struct gss_api_mech *mech; | 124 | struct gss_api_mech *mech; |
125 | struct xdr_netobj oid; | 125 | struct xdr_netobj oid; |
@@ -166,7 +166,7 @@ static int nfs_negotiate_security(const struct dentry *parent, | |||
166 | } | 166 | } |
167 | flavors = page_address(page); | 167 | flavors = page_address(page); |
168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); | 168 | ret = secinfo(parent->d_inode, &dentry->d_name, flavors); |
169 | *flavor = nfs_find_best_sec(flavors, dentry->d_inode); | 169 | *flavor = nfs_find_best_sec(flavors); |
170 | put_page(page); | 170 | put_page(page); |
171 | } | 171 | } |
172 | 172 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index e1c261ddd65d..c4a69833dd0d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -47,6 +47,7 @@ enum nfs4_client_state { | |||
47 | NFS4CLNT_LAYOUTRECALL, | 47 | NFS4CLNT_LAYOUTRECALL, |
48 | NFS4CLNT_SESSION_RESET, | 48 | NFS4CLNT_SESSION_RESET, |
49 | NFS4CLNT_RECALL_SLOT, | 49 | NFS4CLNT_RECALL_SLOT, |
50 | NFS4CLNT_LEASE_CONFIRM, | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | enum nfs4_session_state { | 53 | enum nfs4_session_state { |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 6f8192f4cfc7..be79dc9f386d 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -117,6 +117,8 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
117 | case -EKEYEXPIRED: | 117 | case -EKEYEXPIRED: |
118 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); | 118 | rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); |
119 | break; | 119 | break; |
120 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
121 | break; | ||
120 | default: | 122 | default: |
121 | dprintk("%s DS error. Retry through MDS %d\n", __func__, | 123 | dprintk("%s DS error. Retry through MDS %d\n", __func__, |
122 | task->tk_status); | 124 | task->tk_status); |
@@ -416,7 +418,8 @@ static int | |||
416 | filelayout_check_layout(struct pnfs_layout_hdr *lo, | 418 | filelayout_check_layout(struct pnfs_layout_hdr *lo, |
417 | struct nfs4_filelayout_segment *fl, | 419 | struct nfs4_filelayout_segment *fl, |
418 | struct nfs4_layoutget_res *lgr, | 420 | struct nfs4_layoutget_res *lgr, |
419 | struct nfs4_deviceid *id) | 421 | struct nfs4_deviceid *id, |
422 | gfp_t gfp_flags) | ||
420 | { | 423 | { |
421 | struct nfs4_file_layout_dsaddr *dsaddr; | 424 | struct nfs4_file_layout_dsaddr *dsaddr; |
422 | int status = -EINVAL; | 425 | int status = -EINVAL; |
@@ -439,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
439 | /* find and reference the deviceid */ | 442 | /* find and reference the deviceid */ |
440 | dsaddr = nfs4_fl_find_get_deviceid(id); | 443 | dsaddr = nfs4_fl_find_get_deviceid(id); |
441 | if (dsaddr == NULL) { | 444 | if (dsaddr == NULL) { |
442 | dsaddr = get_device_info(lo->plh_inode, id); | 445 | dsaddr = get_device_info(lo->plh_inode, id, gfp_flags); |
443 | if (dsaddr == NULL) | 446 | if (dsaddr == NULL) |
444 | goto out; | 447 | goto out; |
445 | } | 448 | } |
@@ -500,7 +503,8 @@ static int | |||
500 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, | 503 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, |
501 | struct nfs4_filelayout_segment *fl, | 504 | struct nfs4_filelayout_segment *fl, |
502 | struct nfs4_layoutget_res *lgr, | 505 | struct nfs4_layoutget_res *lgr, |
503 | struct nfs4_deviceid *id) | 506 | struct nfs4_deviceid *id, |
507 | gfp_t gfp_flags) | ||
504 | { | 508 | { |
505 | struct xdr_stream stream; | 509 | struct xdr_stream stream; |
506 | struct xdr_buf buf = { | 510 | struct xdr_buf buf = { |
@@ -516,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
516 | 520 | ||
517 | dprintk("%s: set_layout_map Begin\n", __func__); | 521 | dprintk("%s: set_layout_map Begin\n", __func__); |
518 | 522 | ||
519 | scratch = alloc_page(GFP_KERNEL); | 523 | scratch = alloc_page(gfp_flags); |
520 | if (!scratch) | 524 | if (!scratch) |
521 | return -ENOMEM; | 525 | return -ENOMEM; |
522 | 526 | ||
@@ -554,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
554 | goto out_err; | 558 | goto out_err; |
555 | 559 | ||
556 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 560 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
557 | GFP_KERNEL); | 561 | gfp_flags); |
558 | if (!fl->fh_array) | 562 | if (!fl->fh_array) |
559 | goto out_err; | 563 | goto out_err; |
560 | 564 | ||
561 | for (i = 0; i < fl->num_fh; i++) { | 565 | for (i = 0; i < fl->num_fh; i++) { |
562 | /* Do we want to use a mempool here? */ | 566 | /* Do we want to use a mempool here? */ |
563 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); | 567 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags); |
564 | if (!fl->fh_array[i]) | 568 | if (!fl->fh_array[i]) |
565 | goto out_err_free; | 569 | goto out_err_free; |
566 | 570 | ||
@@ -605,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
605 | 609 | ||
606 | static struct pnfs_layout_segment * | 610 | static struct pnfs_layout_segment * |
607 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | 611 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, |
608 | struct nfs4_layoutget_res *lgr) | 612 | struct nfs4_layoutget_res *lgr, |
613 | gfp_t gfp_flags) | ||
609 | { | 614 | { |
610 | struct nfs4_filelayout_segment *fl; | 615 | struct nfs4_filelayout_segment *fl; |
611 | int rc; | 616 | int rc; |
612 | struct nfs4_deviceid id; | 617 | struct nfs4_deviceid id; |
613 | 618 | ||
614 | dprintk("--> %s\n", __func__); | 619 | dprintk("--> %s\n", __func__); |
615 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); | 620 | fl = kzalloc(sizeof(*fl), gfp_flags); |
616 | if (!fl) | 621 | if (!fl) |
617 | return NULL; | 622 | return NULL; |
618 | 623 | ||
619 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id); | 624 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags); |
620 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) { | 625 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) { |
621 | _filelayout_free_lseg(fl); | 626 | _filelayout_free_lseg(fl); |
622 | return NULL; | 627 | return NULL; |
623 | } | 628 | } |
@@ -633,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | |||
633 | int size = (fl->stripe_type == STRIPE_SPARSE) ? | 638 | int size = (fl->stripe_type == STRIPE_SPARSE) ? |
634 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; | 639 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
635 | 640 | ||
636 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); | 641 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), gfp_flags); |
637 | if (!fl->commit_buckets) { | 642 | if (!fl->commit_buckets) { |
638 | filelayout_free_lseg(&fl->generic_hdr); | 643 | filelayout_free_lseg(&fl->generic_hdr); |
639 | return NULL; | 644 | return NULL; |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 7c44579f5832..2b461d77b43a 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
@@ -104,6 +104,6 @@ extern struct nfs4_file_layout_dsaddr * | |||
104 | nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id); | 104 | nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id); |
105 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 105 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
106 | struct nfs4_file_layout_dsaddr * | 106 | struct nfs4_file_layout_dsaddr * |
107 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id); | 107 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); |
108 | 108 | ||
109 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 109 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index de5350f2b249..db07c7af1395 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -225,11 +225,11 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | |||
225 | } | 225 | } |
226 | 226 | ||
227 | static struct nfs4_pnfs_ds * | 227 | static struct nfs4_pnfs_ds * |
228 | nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) | 228 | nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port, gfp_t gfp_flags) |
229 | { | 229 | { |
230 | struct nfs4_pnfs_ds *tmp_ds, *ds; | 230 | struct nfs4_pnfs_ds *tmp_ds, *ds; |
231 | 231 | ||
232 | ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL); | 232 | ds = kzalloc(sizeof(*tmp_ds), gfp_flags); |
233 | if (!ds) | 233 | if (!ds) |
234 | goto out; | 234 | goto out; |
235 | 235 | ||
@@ -261,7 +261,7 @@ out: | |||
261 | * Currently only support ipv4, and one multi-path address. | 261 | * Currently only support ipv4, and one multi-path address. |
262 | */ | 262 | */ |
263 | static struct nfs4_pnfs_ds * | 263 | static struct nfs4_pnfs_ds * |
264 | decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | 264 | decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode, gfp_t gfp_flags) |
265 | { | 265 | { |
266 | struct nfs4_pnfs_ds *ds = NULL; | 266 | struct nfs4_pnfs_ds *ds = NULL; |
267 | char *buf; | 267 | char *buf; |
@@ -303,7 +303,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | |||
303 | rlen); | 303 | rlen); |
304 | goto out_err; | 304 | goto out_err; |
305 | } | 305 | } |
306 | buf = kmalloc(rlen + 1, GFP_KERNEL); | 306 | buf = kmalloc(rlen + 1, gfp_flags); |
307 | if (!buf) { | 307 | if (!buf) { |
308 | dprintk("%s: Not enough memory\n", __func__); | 308 | dprintk("%s: Not enough memory\n", __func__); |
309 | goto out_err; | 309 | goto out_err; |
@@ -333,7 +333,7 @@ decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) | |||
333 | sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]); | 333 | sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]); |
334 | port = htons((tmp[0] << 8) | (tmp[1])); | 334 | port = htons((tmp[0] << 8) | (tmp[1])); |
335 | 335 | ||
336 | ds = nfs4_pnfs_ds_add(inode, ip_addr, port); | 336 | ds = nfs4_pnfs_ds_add(inode, ip_addr, port, gfp_flags); |
337 | dprintk("%s: Decoded address and port %s\n", __func__, buf); | 337 | dprintk("%s: Decoded address and port %s\n", __func__, buf); |
338 | out_free: | 338 | out_free: |
339 | kfree(buf); | 339 | kfree(buf); |
@@ -343,7 +343,7 @@ out_err: | |||
343 | 343 | ||
344 | /* Decode opaque device data and return the result */ | 344 | /* Decode opaque device data and return the result */ |
345 | static struct nfs4_file_layout_dsaddr* | 345 | static struct nfs4_file_layout_dsaddr* |
346 | decode_device(struct inode *ino, struct pnfs_device *pdev) | 346 | decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) |
347 | { | 347 | { |
348 | int i; | 348 | int i; |
349 | u32 cnt, num; | 349 | u32 cnt, num; |
@@ -362,7 +362,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
362 | struct page *scratch; | 362 | struct page *scratch; |
363 | 363 | ||
364 | /* set up xdr stream */ | 364 | /* set up xdr stream */ |
365 | scratch = alloc_page(GFP_KERNEL); | 365 | scratch = alloc_page(gfp_flags); |
366 | if (!scratch) | 366 | if (!scratch) |
367 | goto out_err; | 367 | goto out_err; |
368 | 368 | ||
@@ -384,7 +384,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | /* read stripe indices */ | 386 | /* read stripe indices */ |
387 | stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL); | 387 | stripe_indices = kcalloc(cnt, sizeof(u8), gfp_flags); |
388 | if (!stripe_indices) | 388 | if (!stripe_indices) |
389 | goto out_err_free_scratch; | 389 | goto out_err_free_scratch; |
390 | 390 | ||
@@ -423,7 +423,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
423 | 423 | ||
424 | dsaddr = kzalloc(sizeof(*dsaddr) + | 424 | dsaddr = kzalloc(sizeof(*dsaddr) + |
425 | (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), | 425 | (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), |
426 | GFP_KERNEL); | 426 | gfp_flags); |
427 | if (!dsaddr) | 427 | if (!dsaddr) |
428 | goto out_err_free_stripe_indices; | 428 | goto out_err_free_stripe_indices; |
429 | 429 | ||
@@ -452,7 +452,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev) | |||
452 | for (j = 0; j < mp_count; j++) { | 452 | for (j = 0; j < mp_count; j++) { |
453 | if (j == 0) { | 453 | if (j == 0) { |
454 | dsaddr->ds_list[i] = decode_and_add_ds(&stream, | 454 | dsaddr->ds_list[i] = decode_and_add_ds(&stream, |
455 | ino); | 455 | ino, gfp_flags); |
456 | if (dsaddr->ds_list[i] == NULL) | 456 | if (dsaddr->ds_list[i] == NULL) |
457 | goto out_err_free_deviceid; | 457 | goto out_err_free_deviceid; |
458 | } else { | 458 | } else { |
@@ -503,12 +503,12 @@ out_err: | |||
503 | * available devices. | 503 | * available devices. |
504 | */ | 504 | */ |
505 | static struct nfs4_file_layout_dsaddr * | 505 | static struct nfs4_file_layout_dsaddr * |
506 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev) | 506 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) |
507 | { | 507 | { |
508 | struct nfs4_file_layout_dsaddr *d, *new; | 508 | struct nfs4_file_layout_dsaddr *d, *new; |
509 | long hash; | 509 | long hash; |
510 | 510 | ||
511 | new = decode_device(inode, dev); | 511 | new = decode_device(inode, dev, gfp_flags); |
512 | if (!new) { | 512 | if (!new) { |
513 | printk(KERN_WARNING "%s: Could not decode or add device\n", | 513 | printk(KERN_WARNING "%s: Could not decode or add device\n", |
514 | __func__); | 514 | __func__); |
@@ -537,7 +537,7 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev) | |||
537 | * of available devices, and return it. | 537 | * of available devices, and return it. |
538 | */ | 538 | */ |
539 | struct nfs4_file_layout_dsaddr * | 539 | struct nfs4_file_layout_dsaddr * |
540 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | 540 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags) |
541 | { | 541 | { |
542 | struct pnfs_device *pdev = NULL; | 542 | struct pnfs_device *pdev = NULL; |
543 | u32 max_resp_sz; | 543 | u32 max_resp_sz; |
@@ -556,17 +556,17 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | |||
556 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", | 556 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", |
557 | __func__, inode, max_resp_sz, max_pages); | 557 | __func__, inode, max_resp_sz, max_pages); |
558 | 558 | ||
559 | pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL); | 559 | pdev = kzalloc(sizeof(struct pnfs_device), gfp_flags); |
560 | if (pdev == NULL) | 560 | if (pdev == NULL) |
561 | return NULL; | 561 | return NULL; |
562 | 562 | ||
563 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); | 563 | pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags); |
564 | if (pages == NULL) { | 564 | if (pages == NULL) { |
565 | kfree(pdev); | 565 | kfree(pdev); |
566 | return NULL; | 566 | return NULL; |
567 | } | 567 | } |
568 | for (i = 0; i < max_pages; i++) { | 568 | for (i = 0; i < max_pages; i++) { |
569 | pages[i] = alloc_page(GFP_KERNEL); | 569 | pages[i] = alloc_page(gfp_flags); |
570 | if (!pages[i]) | 570 | if (!pages[i]) |
571 | goto out_free; | 571 | goto out_free; |
572 | } | 572 | } |
@@ -587,7 +587,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) | |||
587 | * Found new device, need to decode it and then add it to the | 587 | * Found new device, need to decode it and then add it to the |
588 | * list of known devices for this mountpoint. | 588 | * list of known devices for this mountpoint. |
589 | */ | 589 | */ |
590 | dsaddr = decode_and_add_device(inode, pdev); | 590 | dsaddr = decode_and_add_device(inode, pdev, gfp_flags); |
591 | out_free: | 591 | out_free: |
592 | for (i = 0; i < max_pages; i++) | 592 | for (i = 0; i < max_pages; i++) |
593 | __free_page(pages[i]); | 593 | __free_page(pages[i]); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9bf41eab3e46..cf1b339c3937 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/nfs4.h> | 46 | #include <linux/nfs4.h> |
47 | #include <linux/nfs_fs.h> | 47 | #include <linux/nfs_fs.h> |
48 | #include <linux/nfs_page.h> | 48 | #include <linux/nfs_page.h> |
49 | #include <linux/nfs_mount.h> | ||
49 | #include <linux/namei.h> | 50 | #include <linux/namei.h> |
50 | #include <linux/mount.h> | 51 | #include <linux/mount.h> |
51 | #include <linux/module.h> | 52 | #include <linux/module.h> |
@@ -299,6 +300,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
299 | ret = nfs4_delay(server->client, &exception->timeout); | 300 | ret = nfs4_delay(server->client, &exception->timeout); |
300 | if (ret != 0) | 301 | if (ret != 0) |
301 | break; | 302 | break; |
303 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
302 | case -NFS4ERR_OLD_STATEID: | 304 | case -NFS4ERR_OLD_STATEID: |
303 | exception->retry = 1; | 305 | exception->retry = 1; |
304 | break; | 306 | break; |
@@ -443,8 +445,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
443 | if (res->sr_status == 1) | 445 | if (res->sr_status == 1) |
444 | res->sr_status = NFS_OK; | 446 | res->sr_status = NFS_OK; |
445 | 447 | ||
446 | /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */ | 448 | /* don't increment the sequence number if the task wasn't sent */ |
447 | if (!res->sr_slot) | 449 | if (!RPC_WAS_SENT(task)) |
448 | goto out; | 450 | goto out; |
449 | 451 | ||
450 | /* Check the SEQUENCE operation status */ | 452 | /* Check the SEQUENCE operation status */ |
@@ -2185,9 +2187,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2185 | struct nfs4_exception exception = { }; | 2187 | struct nfs4_exception exception = { }; |
2186 | int err; | 2188 | int err; |
2187 | do { | 2189 | do { |
2188 | err = nfs4_handle_exception(server, | 2190 | err = _nfs4_lookup_root(server, fhandle, info); |
2189 | _nfs4_lookup_root(server, fhandle, info), | 2191 | switch (err) { |
2190 | &exception); | 2192 | case 0: |
2193 | case -NFS4ERR_WRONGSEC: | ||
2194 | break; | ||
2195 | default: | ||
2196 | err = nfs4_handle_exception(server, err, &exception); | ||
2197 | } | ||
2191 | } while (exception.retry); | 2198 | } while (exception.retry); |
2192 | return err; | 2199 | return err; |
2193 | } | 2200 | } |
@@ -2208,25 +2215,47 @@ out: | |||
2208 | return ret; | 2215 | return ret; |
2209 | } | 2216 | } |
2210 | 2217 | ||
2211 | /* | 2218 | static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2212 | * get the file handle for the "/" directory on the server | ||
2213 | */ | ||
2214 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2215 | struct nfs_fsinfo *info) | 2219 | struct nfs_fsinfo *info) |
2216 | { | 2220 | { |
2217 | int i, len, status = 0; | 2221 | int i, len, status = 0; |
2218 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; | 2222 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2219 | 2223 | ||
2220 | flav_array[0] = RPC_AUTH_UNIX; | 2224 | len = gss_mech_list_pseudoflavors(&flav_array[0]); |
2221 | len = gss_mech_list_pseudoflavors(&flav_array[1]); | 2225 | flav_array[len] = RPC_AUTH_NULL; |
2222 | flav_array[1+len] = RPC_AUTH_NULL; | 2226 | len += 1; |
2223 | len += 2; | ||
2224 | 2227 | ||
2225 | for (i = 0; i < len; i++) { | 2228 | for (i = 0; i < len; i++) { |
2226 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2229 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2227 | if (status != -EPERM) | 2230 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2228 | break; | 2231 | continue; |
2232 | break; | ||
2229 | } | 2233 | } |
2234 | /* | ||
2235 | * -EACCESS could mean that the user doesn't have correct permissions | ||
2236 | * to access the mount. It could also mean that we tried to mount | ||
2237 | * with a gss auth flavor, but rpc.gssd isn't running. Either way, | ||
2238 | * existing mount programs don't handle -EACCES very well so it should | ||
2239 | * be mapped to -EPERM instead. | ||
2240 | */ | ||
2241 | if (status == -EACCES) | ||
2242 | status = -EPERM; | ||
2243 | return status; | ||
2244 | } | ||
2245 | |||
2246 | /* | ||
2247 | * get the file handle for the "/" directory on the server | ||
2248 | */ | ||
2249 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2250 | struct nfs_fsinfo *info) | ||
2251 | { | ||
2252 | int status = nfs4_lookup_root(server, fhandle, info); | ||
2253 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) | ||
2254 | /* | ||
2255 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM | ||
2256 | * by nfs4_map_errors() as this function exits. | ||
2257 | */ | ||
2258 | status = nfs4_find_root_sec(server, fhandle, info); | ||
2230 | if (status == 0) | 2259 | if (status == 0) |
2231 | status = nfs4_server_capabilities(server, fhandle); | 2260 | status = nfs4_server_capabilities(server, fhandle); |
2232 | if (status == 0) | 2261 | if (status == 0) |
@@ -3667,6 +3696,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3667 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3696 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
3668 | task->tk_status = 0; | 3697 | task->tk_status = 0; |
3669 | return -EAGAIN; | 3698 | return -EAGAIN; |
3699 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
3670 | case -NFS4ERR_OLD_STATEID: | 3700 | case -NFS4ERR_OLD_STATEID: |
3671 | task->tk_status = 0; | 3701 | task->tk_status = 0; |
3672 | return -EAGAIN; | 3702 | return -EAGAIN; |
@@ -3723,21 +3753,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3723 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 3753 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
3724 | clp->cl_ipaddr, port >> 8, port & 255); | 3754 | clp->cl_ipaddr, port >> 8, port & 255); |
3725 | 3755 | ||
3726 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3756 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3727 | if (status != -NFS4ERR_CLID_INUSE) | 3757 | if (status != -NFS4ERR_CLID_INUSE) |
3728 | break; | 3758 | break; |
3729 | if (signalled()) | 3759 | if (loop != 0) { |
3760 | ++clp->cl_id_uniquifier; | ||
3730 | break; | 3761 | break; |
3731 | if (loop++ & 1) | 3762 | } |
3732 | ssleep(clp->cl_lease_time / HZ + 1); | 3763 | ++loop; |
3733 | else | 3764 | ssleep(clp->cl_lease_time / HZ + 1); |
3734 | if (++clp->cl_id_uniquifier == 0) | ||
3735 | break; | ||
3736 | } | 3765 | } |
3737 | return status; | 3766 | return status; |
3738 | } | 3767 | } |
3739 | 3768 | ||
3740 | static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | 3769 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
3741 | struct nfs4_setclientid_res *arg, | 3770 | struct nfs4_setclientid_res *arg, |
3742 | struct rpc_cred *cred) | 3771 | struct rpc_cred *cred) |
3743 | { | 3772 | { |
@@ -3752,7 +3781,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3752 | int status; | 3781 | int status; |
3753 | 3782 | ||
3754 | now = jiffies; | 3783 | now = jiffies; |
3755 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3784 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
3756 | if (status == 0) { | 3785 | if (status == 0) { |
3757 | spin_lock(&clp->cl_lock); | 3786 | spin_lock(&clp->cl_lock); |
3758 | clp->cl_lease_time = fsinfo.lease_time * HZ; | 3787 | clp->cl_lease_time = fsinfo.lease_time * HZ; |
@@ -3762,26 +3791,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
3762 | return status; | 3791 | return status; |
3763 | } | 3792 | } |
3764 | 3793 | ||
3765 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | ||
3766 | struct nfs4_setclientid_res *arg, | ||
3767 | struct rpc_cred *cred) | ||
3768 | { | ||
3769 | long timeout = 0; | ||
3770 | int err; | ||
3771 | do { | ||
3772 | err = _nfs4_proc_setclientid_confirm(clp, arg, cred); | ||
3773 | switch (err) { | ||
3774 | case 0: | ||
3775 | return err; | ||
3776 | case -NFS4ERR_RESOURCE: | ||
3777 | /* The IBM lawyers misread another document! */ | ||
3778 | case -NFS4ERR_DELAY: | ||
3779 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
3780 | } | ||
3781 | } while (err == 0); | ||
3782 | return err; | ||
3783 | } | ||
3784 | |||
3785 | struct nfs4_delegreturndata { | 3794 | struct nfs4_delegreturndata { |
3786 | struct nfs4_delegreturnargs args; | 3795 | struct nfs4_delegreturnargs args; |
3787 | struct nfs4_delegreturnres res; | 3796 | struct nfs4_delegreturnres res; |
@@ -4786,7 +4795,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
4786 | init_utsname()->domainname, | 4795 | init_utsname()->domainname, |
4787 | clp->cl_rpcclient->cl_auth->au_flavor); | 4796 | clp->cl_rpcclient->cl_auth->au_flavor); |
4788 | 4797 | ||
4789 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 4798 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4790 | if (!status) | 4799 | if (!status) |
4791 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 4800 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); |
4792 | dprintk("<-- %s status= %d\n", __func__, status); | 4801 | dprintk("<-- %s status= %d\n", __func__, status); |
@@ -4837,6 +4846,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4837 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); | 4846 | dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); |
4838 | rpc_delay(task, NFS4_POLL_RETRY_MIN); | 4847 | rpc_delay(task, NFS4_POLL_RETRY_MIN); |
4839 | task->tk_status = 0; | 4848 | task->tk_status = 0; |
4849 | /* fall through */ | ||
4850 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
4840 | nfs_restart_rpc(task, data->clp); | 4851 | nfs_restart_rpc(task, data->clp); |
4841 | return; | 4852 | return; |
4842 | } | 4853 | } |
@@ -4869,7 +4880,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo) | |||
4869 | .rpc_client = clp->cl_rpcclient, | 4880 | .rpc_client = clp->cl_rpcclient, |
4870 | .rpc_message = &msg, | 4881 | .rpc_message = &msg, |
4871 | .callback_ops = &nfs4_get_lease_time_ops, | 4882 | .callback_ops = &nfs4_get_lease_time_ops, |
4872 | .callback_data = &data | 4883 | .callback_data = &data, |
4884 | .flags = RPC_TASK_TIMEOUT, | ||
4873 | }; | 4885 | }; |
4874 | int status; | 4886 | int status; |
4875 | 4887 | ||
@@ -5171,7 +5183,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) | |||
5171 | nfs4_init_channel_attrs(&args); | 5183 | nfs4_init_channel_attrs(&args); |
5172 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); | 5184 | args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN); |
5173 | 5185 | ||
5174 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5186 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5175 | 5187 | ||
5176 | if (!status) | 5188 | if (!status) |
5177 | /* Verify the session's negotiated channel_attrs values */ | 5189 | /* Verify the session's negotiated channel_attrs values */ |
@@ -5194,20 +5206,10 @@ int nfs4_proc_create_session(struct nfs_client *clp) | |||
5194 | int status; | 5206 | int status; |
5195 | unsigned *ptr; | 5207 | unsigned *ptr; |
5196 | struct nfs4_session *session = clp->cl_session; | 5208 | struct nfs4_session *session = clp->cl_session; |
5197 | long timeout = 0; | ||
5198 | int err; | ||
5199 | 5209 | ||
5200 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | 5210 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); |
5201 | 5211 | ||
5202 | do { | 5212 | status = _nfs4_proc_create_session(clp); |
5203 | status = _nfs4_proc_create_session(clp); | ||
5204 | if (status == -NFS4ERR_DELAY) { | ||
5205 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
5206 | if (err) | ||
5207 | status = err; | ||
5208 | } | ||
5209 | } while (status == -NFS4ERR_DELAY); | ||
5210 | |||
5211 | if (status) | 5213 | if (status) |
5212 | goto out; | 5214 | goto out; |
5213 | 5215 | ||
@@ -5248,7 +5250,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
5248 | msg.rpc_argp = session; | 5250 | msg.rpc_argp = session; |
5249 | msg.rpc_resp = NULL; | 5251 | msg.rpc_resp = NULL; |
5250 | msg.rpc_cred = NULL; | 5252 | msg.rpc_cred = NULL; |
5251 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0); | 5253 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5252 | 5254 | ||
5253 | if (status) | 5255 | if (status) |
5254 | printk(KERN_WARNING | 5256 | printk(KERN_WARNING |
@@ -5481,6 +5483,8 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5481 | break; | 5483 | break; |
5482 | case -NFS4ERR_DELAY: | 5484 | case -NFS4ERR_DELAY: |
5483 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5485 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5486 | /* fall through */ | ||
5487 | case -NFS4ERR_RETRY_UNCACHED_REP: | ||
5484 | return -EAGAIN; | 5488 | return -EAGAIN; |
5485 | default: | 5489 | default: |
5486 | nfs4_schedule_lease_recovery(clp); | 5490 | nfs4_schedule_lease_recovery(clp); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index a6804f704d9d..036f5adc9e1f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list); | |||
64 | 64 | ||
65 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | 65 | int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) |
66 | { | 66 | { |
67 | struct nfs4_setclientid_res clid; | 67 | struct nfs4_setclientid_res clid = { |
68 | .clientid = clp->cl_clientid, | ||
69 | .confirm = clp->cl_confirm, | ||
70 | }; | ||
68 | unsigned short port; | 71 | unsigned short port; |
69 | int status; | 72 | int status; |
70 | 73 | ||
74 | if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) | ||
75 | goto do_confirm; | ||
71 | port = nfs_callback_tcpport; | 76 | port = nfs_callback_tcpport; |
72 | if (clp->cl_addr.ss_family == AF_INET6) | 77 | if (clp->cl_addr.ss_family == AF_INET6) |
73 | port = nfs_callback_tcpport6; | 78 | port = nfs_callback_tcpport6; |
@@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
75 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); | 80 | status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); |
76 | if (status != 0) | 81 | if (status != 0) |
77 | goto out; | 82 | goto out; |
83 | clp->cl_clientid = clid.clientid; | ||
84 | clp->cl_confirm = clid.confirm; | ||
85 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
86 | do_confirm: | ||
78 | status = nfs4_proc_setclientid_confirm(clp, &clid, cred); | 87 | status = nfs4_proc_setclientid_confirm(clp, &clid, cred); |
79 | if (status != 0) | 88 | if (status != 0) |
80 | goto out; | 89 | goto out; |
81 | clp->cl_clientid = clid.clientid; | 90 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
82 | nfs4_schedule_state_renewal(clp); | 91 | nfs4_schedule_state_renewal(clp); |
83 | out: | 92 | out: |
84 | return status; | 93 | return status; |
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) | |||
230 | { | 239 | { |
231 | int status; | 240 | int status; |
232 | 241 | ||
242 | if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) | ||
243 | goto do_confirm; | ||
233 | nfs4_begin_drain_session(clp); | 244 | nfs4_begin_drain_session(clp); |
234 | status = nfs4_proc_exchange_id(clp, cred); | 245 | status = nfs4_proc_exchange_id(clp, cred); |
235 | if (status != 0) | 246 | if (status != 0) |
236 | goto out; | 247 | goto out; |
248 | set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
249 | do_confirm: | ||
237 | status = nfs4_proc_create_session(clp); | 250 | status = nfs4_proc_create_session(clp); |
238 | if (status != 0) | 251 | if (status != 0) |
239 | goto out; | 252 | goto out; |
253 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); | ||
240 | nfs41_setup_state_renewal(clp); | 254 | nfs41_setup_state_renewal(clp); |
241 | nfs_mark_client_ready(clp, NFS_CS_READY); | 255 | nfs_mark_client_ready(clp, NFS_CS_READY); |
242 | out: | 256 | out: |
@@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | |||
1584 | */ | 1598 | */ |
1585 | static void nfs4_set_lease_expired(struct nfs_client *clp, int status) | 1599 | static void nfs4_set_lease_expired(struct nfs_client *clp, int status) |
1586 | { | 1600 | { |
1587 | if (nfs4_has_session(clp)) { | 1601 | switch (status) { |
1588 | switch (status) { | 1602 | case -NFS4ERR_CLID_INUSE: |
1589 | case -NFS4ERR_DELAY: | 1603 | case -NFS4ERR_STALE_CLIENTID: |
1590 | case -NFS4ERR_CLID_INUSE: | 1604 | clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); |
1591 | case -EAGAIN: | 1605 | break; |
1592 | break; | 1606 | case -NFS4ERR_DELAY: |
1607 | case -ETIMEDOUT: | ||
1608 | case -EAGAIN: | ||
1609 | ssleep(1); | ||
1610 | break; | ||
1593 | 1611 | ||
1594 | case -EKEYEXPIRED: | 1612 | case -EKEYEXPIRED: |
1595 | nfs4_warn_keyexpired(clp->cl_hostname); | 1613 | nfs4_warn_keyexpired(clp->cl_hostname); |
1596 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery | 1614 | case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery |
1597 | * in nfs4_exchange_id */ | 1615 | * in nfs4_exchange_id */ |
1598 | default: | 1616 | default: |
1599 | return; | 1617 | return; |
1600 | } | ||
1601 | } | 1618 | } |
1602 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1619 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1603 | } | 1620 | } |
@@ -1607,7 +1624,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1607 | int status = 0; | 1624 | int status = 0; |
1608 | 1625 | ||
1609 | /* Ensure exclusive access to NFSv4 state */ | 1626 | /* Ensure exclusive access to NFSv4 state */ |
1610 | for(;;) { | 1627 | do { |
1611 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1628 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
1612 | /* We're going to have to re-establish a clientid */ | 1629 | /* We're going to have to re-establish a clientid */ |
1613 | status = nfs4_reclaim_lease(clp); | 1630 | status = nfs4_reclaim_lease(clp); |
@@ -1691,7 +1708,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1691 | break; | 1708 | break; |
1692 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | 1709 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) |
1693 | break; | 1710 | break; |
1694 | } | 1711 | } while (atomic_read(&clp->cl_count) > 1); |
1695 | return; | 1712 | return; |
1696 | out_error: | 1713 | out_error: |
1697 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" | 1714 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index dddfb5795d7b..c3ccd2c46834 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1452,26 +1452,25 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1452 | 1452 | ||
1453 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1453 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1454 | { | 1454 | { |
1455 | uint32_t attrs[2] = {0, 0}; | 1455 | uint32_t attrs[2] = { |
1456 | FATTR4_WORD0_RDATTR_ERROR, | ||
1457 | FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
1458 | }; | ||
1456 | uint32_t dircount = readdir->count >> 1; | 1459 | uint32_t dircount = readdir->count >> 1; |
1457 | __be32 *p; | 1460 | __be32 *p; |
1458 | 1461 | ||
1459 | if (readdir->plus) { | 1462 | if (readdir->plus) { |
1460 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| | 1463 | attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| |
1461 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE; | 1464 | FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID; |
1462 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| | 1465 | attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER| |
1463 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| | 1466 | FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV| |
1464 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| | 1467 | FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS| |
1465 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 1468 | FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
1466 | dircount >>= 1; | 1469 | dircount >>= 1; |
1467 | } | 1470 | } |
1468 | attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID; | 1471 | /* Use mounted_on_fileid only if the server supports it */ |
1469 | attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; | 1472 | if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) |
1470 | /* Switch to mounted_on_fileid if the server supports it */ | 1473 | attrs[0] |= FATTR4_WORD0_FILEID; |
1471 | if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) | ||
1472 | attrs[0] &= ~FATTR4_WORD0_FILEID; | ||
1473 | else | ||
1474 | attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | ||
1475 | 1474 | ||
1476 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); | 1475 | p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); |
1477 | *p++ = cpu_to_be32(OP_READDIR); | 1476 | *p++ = cpu_to_be32(OP_READDIR); |
@@ -3140,7 +3139,7 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma | |||
3140 | goto out_overflow; | 3139 | goto out_overflow; |
3141 | xdr_decode_hyper(p, fileid); | 3140 | xdr_decode_hyper(p, fileid); |
3142 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; | 3141 | bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
3143 | ret = NFS_ATTR_FATTR_FILEID; | 3142 | ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID; |
3144 | } | 3143 | } |
3145 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); | 3144 | dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid); |
3146 | return ret; | 3145 | return ret; |
@@ -4002,7 +4001,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4002 | { | 4001 | { |
4003 | int status; | 4002 | int status; |
4004 | umode_t fmode = 0; | 4003 | umode_t fmode = 0; |
4005 | uint64_t fileid; | ||
4006 | uint32_t type; | 4004 | uint32_t type; |
4007 | 4005 | ||
4008 | status = decode_attr_type(xdr, bitmap, &type); | 4006 | status = decode_attr_type(xdr, bitmap, &type); |
@@ -4101,13 +4099,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4101 | goto xdr_error; | 4099 | goto xdr_error; |
4102 | fattr->valid |= status; | 4100 | fattr->valid |= status; |
4103 | 4101 | ||
4104 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid); | 4102 | status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid); |
4105 | if (status < 0) | 4103 | if (status < 0) |
4106 | goto xdr_error; | 4104 | goto xdr_error; |
4107 | if (status != 0 && !(fattr->valid & status)) { | 4105 | fattr->valid |= status; |
4108 | fattr->fileid = fileid; | ||
4109 | fattr->valid |= status; | ||
4110 | } | ||
4111 | 4106 | ||
4112 | xdr_error: | 4107 | xdr_error: |
4113 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4108 | dprintk("%s: xdr returned %d\n", __func__, -status); |
@@ -4838,17 +4833,21 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
4838 | struct nfs4_secinfo_flavor *sec_flavor; | 4833 | struct nfs4_secinfo_flavor *sec_flavor; |
4839 | int status; | 4834 | int status; |
4840 | __be32 *p; | 4835 | __be32 *p; |
4841 | int i; | 4836 | int i, num_flavors; |
4842 | 4837 | ||
4843 | status = decode_op_hdr(xdr, OP_SECINFO); | 4838 | status = decode_op_hdr(xdr, OP_SECINFO); |
4839 | if (status) | ||
4840 | goto out; | ||
4844 | p = xdr_inline_decode(xdr, 4); | 4841 | p = xdr_inline_decode(xdr, 4); |
4845 | if (unlikely(!p)) | 4842 | if (unlikely(!p)) |
4846 | goto out_overflow; | 4843 | goto out_overflow; |
4847 | res->flavors->num_flavors = be32_to_cpup(p); | ||
4848 | 4844 | ||
4849 | for (i = 0; i < res->flavors->num_flavors; i++) { | 4845 | res->flavors->num_flavors = 0; |
4846 | num_flavors = be32_to_cpup(p); | ||
4847 | |||
4848 | for (i = 0; i < num_flavors; i++) { | ||
4850 | sec_flavor = &res->flavors->flavors[i]; | 4849 | sec_flavor = &res->flavors->flavors[i]; |
4851 | if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE) | 4850 | if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE) |
4852 | break; | 4851 | break; |
4853 | 4852 | ||
4854 | p = xdr_inline_decode(xdr, 4); | 4853 | p = xdr_inline_decode(xdr, 4); |
@@ -4857,13 +4856,15 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) | |||
4857 | sec_flavor->flavor = be32_to_cpup(p); | 4856 | sec_flavor->flavor = be32_to_cpup(p); |
4858 | 4857 | ||
4859 | if (sec_flavor->flavor == RPC_AUTH_GSS) { | 4858 | if (sec_flavor->flavor == RPC_AUTH_GSS) { |
4860 | if (decode_secinfo_gss(xdr, sec_flavor)) | 4859 | status = decode_secinfo_gss(xdr, sec_flavor); |
4861 | break; | 4860 | if (status) |
4861 | goto out; | ||
4862 | } | 4862 | } |
4863 | res->flavors->num_flavors++; | ||
4863 | } | 4864 | } |
4864 | 4865 | ||
4865 | return 0; | 4866 | out: |
4866 | 4867 | return status; | |
4867 | out_overflow: | 4868 | out_overflow: |
4868 | print_overflow_msg(__func__, xdr); | 4869 | print_overflow_msg(__func__, xdr); |
4869 | return -EIO; | 4870 | return -EIO; |
@@ -6408,7 +6409,9 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
6408 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 6409 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
6409 | entry->server, 1) < 0) | 6410 | entry->server, 1) < 0) |
6410 | goto out_overflow; | 6411 | goto out_overflow; |
6411 | if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | 6412 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
6413 | entry->ino = entry->fattr->mounted_on_fileid; | ||
6414 | else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | ||
6412 | entry->ino = entry->fattr->fileid; | 6415 | entry->ino = entry->fattr->fileid; |
6413 | 6416 | ||
6414 | entry->d_type = DT_UNKNOWN; | 6417 | entry->d_type = DT_UNKNOWN; |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index d9ab97269ce6..f57f5281a520 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -383,6 +383,7 @@ pnfs_destroy_all_layouts(struct nfs_client *clp) | |||
383 | plh_layouts); | 383 | plh_layouts); |
384 | dprintk("%s freeing layout for inode %lu\n", __func__, | 384 | dprintk("%s freeing layout for inode %lu\n", __func__, |
385 | lo->plh_inode->i_ino); | 385 | lo->plh_inode->i_ino); |
386 | list_del_init(&lo->plh_layouts); | ||
386 | pnfs_destroy_layout(NFS_I(lo->plh_inode)); | 387 | pnfs_destroy_layout(NFS_I(lo->plh_inode)); |
387 | } | 388 | } |
388 | } | 389 | } |
@@ -466,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, | |||
466 | static struct pnfs_layout_segment * | 467 | static struct pnfs_layout_segment * |
467 | send_layoutget(struct pnfs_layout_hdr *lo, | 468 | send_layoutget(struct pnfs_layout_hdr *lo, |
468 | struct nfs_open_context *ctx, | 469 | struct nfs_open_context *ctx, |
469 | u32 iomode) | 470 | u32 iomode, |
471 | gfp_t gfp_flags) | ||
470 | { | 472 | { |
471 | struct inode *ino = lo->plh_inode; | 473 | struct inode *ino = lo->plh_inode; |
472 | struct nfs_server *server = NFS_SERVER(ino); | 474 | struct nfs_server *server = NFS_SERVER(ino); |
@@ -479,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
479 | dprintk("--> %s\n", __func__); | 481 | dprintk("--> %s\n", __func__); |
480 | 482 | ||
481 | BUG_ON(ctx == NULL); | 483 | BUG_ON(ctx == NULL); |
482 | lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); | 484 | lgp = kzalloc(sizeof(*lgp), gfp_flags); |
483 | if (lgp == NULL) | 485 | if (lgp == NULL) |
484 | return NULL; | 486 | return NULL; |
485 | 487 | ||
@@ -487,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
487 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | 489 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; |
488 | max_pages = max_resp_sz >> PAGE_SHIFT; | 490 | max_pages = max_resp_sz >> PAGE_SHIFT; |
489 | 491 | ||
490 | pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); | 492 | pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags); |
491 | if (!pages) | 493 | if (!pages) |
492 | goto out_err_free; | 494 | goto out_err_free; |
493 | 495 | ||
494 | for (i = 0; i < max_pages; i++) { | 496 | for (i = 0; i < max_pages; i++) { |
495 | pages[i] = alloc_page(GFP_KERNEL); | 497 | pages[i] = alloc_page(gfp_flags); |
496 | if (!pages[i]) | 498 | if (!pages[i]) |
497 | goto out_err_free; | 499 | goto out_err_free; |
498 | } | 500 | } |
@@ -508,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
508 | lgp->args.layout.pages = pages; | 510 | lgp->args.layout.pages = pages; |
509 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | 511 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; |
510 | lgp->lsegpp = &lseg; | 512 | lgp->lsegpp = &lseg; |
513 | lgp->gfp_flags = gfp_flags; | ||
511 | 514 | ||
512 | /* Synchronously retrieve layout information from server and | 515 | /* Synchronously retrieve layout information from server and |
513 | * store in lseg. | 516 | * store in lseg. |
@@ -665,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo, | |||
665 | } | 668 | } |
666 | 669 | ||
667 | static struct pnfs_layout_hdr * | 670 | static struct pnfs_layout_hdr * |
668 | alloc_init_layout_hdr(struct inode *ino) | 671 | alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) |
669 | { | 672 | { |
670 | struct pnfs_layout_hdr *lo; | 673 | struct pnfs_layout_hdr *lo; |
671 | 674 | ||
672 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); | 675 | lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags); |
673 | if (!lo) | 676 | if (!lo) |
674 | return NULL; | 677 | return NULL; |
675 | atomic_set(&lo->plh_refcount, 1); | 678 | atomic_set(&lo->plh_refcount, 1); |
@@ -681,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino) | |||
681 | } | 684 | } |
682 | 685 | ||
683 | static struct pnfs_layout_hdr * | 686 | static struct pnfs_layout_hdr * |
684 | pnfs_find_alloc_layout(struct inode *ino) | 687 | pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags) |
685 | { | 688 | { |
686 | struct nfs_inode *nfsi = NFS_I(ino); | 689 | struct nfs_inode *nfsi = NFS_I(ino); |
687 | struct pnfs_layout_hdr *new = NULL; | 690 | struct pnfs_layout_hdr *new = NULL; |
@@ -696,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino) | |||
696 | return nfsi->layout; | 699 | return nfsi->layout; |
697 | } | 700 | } |
698 | spin_unlock(&ino->i_lock); | 701 | spin_unlock(&ino->i_lock); |
699 | new = alloc_init_layout_hdr(ino); | 702 | new = alloc_init_layout_hdr(ino, gfp_flags); |
700 | spin_lock(&ino->i_lock); | 703 | spin_lock(&ino->i_lock); |
701 | 704 | ||
702 | if (likely(nfsi->layout == NULL)) /* Won the race? */ | 705 | if (likely(nfsi->layout == NULL)) /* Won the race? */ |
@@ -756,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode) | |||
756 | struct pnfs_layout_segment * | 759 | struct pnfs_layout_segment * |
757 | pnfs_update_layout(struct inode *ino, | 760 | pnfs_update_layout(struct inode *ino, |
758 | struct nfs_open_context *ctx, | 761 | struct nfs_open_context *ctx, |
759 | enum pnfs_iomode iomode) | 762 | enum pnfs_iomode iomode, |
763 | gfp_t gfp_flags) | ||
760 | { | 764 | { |
761 | struct nfs_inode *nfsi = NFS_I(ino); | 765 | struct nfs_inode *nfsi = NFS_I(ino); |
762 | struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; | 766 | struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; |
@@ -767,7 +771,7 @@ pnfs_update_layout(struct inode *ino, | |||
767 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) | 771 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) |
768 | return NULL; | 772 | return NULL; |
769 | spin_lock(&ino->i_lock); | 773 | spin_lock(&ino->i_lock); |
770 | lo = pnfs_find_alloc_layout(ino); | 774 | lo = pnfs_find_alloc_layout(ino, gfp_flags); |
771 | if (lo == NULL) { | 775 | if (lo == NULL) { |
772 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); | 776 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); |
773 | goto out_unlock; | 777 | goto out_unlock; |
@@ -807,7 +811,7 @@ pnfs_update_layout(struct inode *ino, | |||
807 | spin_unlock(&clp->cl_lock); | 811 | spin_unlock(&clp->cl_lock); |
808 | } | 812 | } |
809 | 813 | ||
810 | lseg = send_layoutget(lo, ctx, iomode); | 814 | lseg = send_layoutget(lo, ctx, iomode, gfp_flags); |
811 | if (!lseg && first) { | 815 | if (!lseg && first) { |
812 | spin_lock(&clp->cl_lock); | 816 | spin_lock(&clp->cl_lock); |
813 | list_del_init(&lo->plh_layouts); | 817 | list_del_init(&lo->plh_layouts); |
@@ -846,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) | |||
846 | goto out; | 850 | goto out; |
847 | } | 851 | } |
848 | /* Inject layout blob into I/O device driver */ | 852 | /* Inject layout blob into I/O device driver */ |
849 | lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res); | 853 | lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags); |
850 | if (!lseg || IS_ERR(lseg)) { | 854 | if (!lseg || IS_ERR(lseg)) { |
851 | if (!lseg) | 855 | if (!lseg) |
852 | status = -ENOMEM; | 856 | status = -ENOMEM; |
@@ -899,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio, | |||
899 | /* This is first coelesce call for a series of nfs_pages */ | 903 | /* This is first coelesce call for a series of nfs_pages */ |
900 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 904 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
901 | prev->wb_context, | 905 | prev->wb_context, |
902 | IOMODE_READ); | 906 | IOMODE_READ, |
907 | GFP_KERNEL); | ||
903 | } | 908 | } |
904 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); | 909 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); |
905 | } | 910 | } |
@@ -921,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio, | |||
921 | /* This is first coelesce call for a series of nfs_pages */ | 926 | /* This is first coelesce call for a series of nfs_pages */ |
922 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 927 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
923 | prev->wb_context, | 928 | prev->wb_context, |
924 | IOMODE_RW); | 929 | IOMODE_RW, |
930 | GFP_NOFS); | ||
925 | } | 931 | } |
926 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); | 932 | return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); |
927 | } | 933 | } |
@@ -1004,6 +1010,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1004 | { | 1010 | { |
1005 | struct nfs_inode *nfsi = NFS_I(wdata->inode); | 1011 | struct nfs_inode *nfsi = NFS_I(wdata->inode); |
1006 | loff_t end_pos = wdata->args.offset + wdata->res.count; | 1012 | loff_t end_pos = wdata->args.offset + wdata->res.count; |
1013 | bool mark_as_dirty = false; | ||
1007 | 1014 | ||
1008 | spin_lock(&nfsi->vfs_inode.i_lock); | 1015 | spin_lock(&nfsi->vfs_inode.i_lock); |
1009 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1016 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
@@ -1011,13 +1018,18 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1011 | get_lseg(wdata->lseg); | 1018 | get_lseg(wdata->lseg); |
1012 | wdata->lseg->pls_lc_cred = | 1019 | wdata->lseg->pls_lc_cred = |
1013 | get_rpccred(wdata->args.context->state->owner->so_cred); | 1020 | get_rpccred(wdata->args.context->state->owner->so_cred); |
1014 | mark_inode_dirty_sync(wdata->inode); | 1021 | mark_as_dirty = true; |
1015 | dprintk("%s: Set layoutcommit for inode %lu ", | 1022 | dprintk("%s: Set layoutcommit for inode %lu ", |
1016 | __func__, wdata->inode->i_ino); | 1023 | __func__, wdata->inode->i_ino); |
1017 | } | 1024 | } |
1018 | if (end_pos > wdata->lseg->pls_end_pos) | 1025 | if (end_pos > wdata->lseg->pls_end_pos) |
1019 | wdata->lseg->pls_end_pos = end_pos; | 1026 | wdata->lseg->pls_end_pos = end_pos; |
1020 | spin_unlock(&nfsi->vfs_inode.i_lock); | 1027 | spin_unlock(&nfsi->vfs_inode.i_lock); |
1028 | |||
1029 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | ||
1030 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | ||
1031 | if (mark_as_dirty) | ||
1032 | mark_inode_dirty_sync(wdata->inode); | ||
1021 | } | 1033 | } |
1022 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | 1034 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
1023 | 1035 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index bc4827202e7a..0c015bad9e7a 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -70,7 +70,7 @@ struct pnfs_layoutdriver_type { | |||
70 | const u32 id; | 70 | const u32 id; |
71 | const char *name; | 71 | const char *name; |
72 | struct module *owner; | 72 | struct module *owner; |
73 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); | 73 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr, gfp_t gfp_flags); |
74 | void (*free_lseg) (struct pnfs_layout_segment *lseg); | 74 | void (*free_lseg) (struct pnfs_layout_segment *lseg); |
75 | 75 | ||
76 | /* test for nfs page cache coalescing */ | 76 | /* test for nfs page cache coalescing */ |
@@ -126,7 +126,7 @@ void get_layout_hdr(struct pnfs_layout_hdr *lo); | |||
126 | void put_lseg(struct pnfs_layout_segment *lseg); | 126 | void put_lseg(struct pnfs_layout_segment *lseg); |
127 | struct pnfs_layout_segment * | 127 | struct pnfs_layout_segment * |
128 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | 128 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, |
129 | enum pnfs_iomode access_type); | 129 | enum pnfs_iomode access_type, gfp_t gfp_flags); |
130 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); | 130 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
131 | void unset_pnfs_layoutdriver(struct nfs_server *); | 131 | void unset_pnfs_layoutdriver(struct nfs_server *); |
132 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, | 132 | enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *, |
@@ -245,7 +245,7 @@ static inline void put_lseg(struct pnfs_layout_segment *lseg) | |||
245 | 245 | ||
246 | static inline struct pnfs_layout_segment * | 246 | static inline struct pnfs_layout_segment * |
247 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | 247 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, |
248 | enum pnfs_iomode access_type) | 248 | enum pnfs_iomode access_type, gfp_t gfp_flags) |
249 | { | 249 | { |
250 | return NULL; | 250 | return NULL; |
251 | } | 251 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 7cded2b12a05..2bcf0dc306a1 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -288,7 +288,7 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc) | |||
288 | atomic_set(&req->wb_complete, requests); | 288 | atomic_set(&req->wb_complete, requests); |
289 | 289 | ||
290 | BUG_ON(desc->pg_lseg != NULL); | 290 | BUG_ON(desc->pg_lseg != NULL); |
291 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); | 291 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL); |
292 | ClearPageError(page); | 292 | ClearPageError(page); |
293 | offset = 0; | 293 | offset = 0; |
294 | nbytes = desc->pg_count; | 294 | nbytes = desc->pg_count; |
@@ -351,7 +351,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc) | |||
351 | } | 351 | } |
352 | req = nfs_list_entry(data->pages.next); | 352 | req = nfs_list_entry(data->pages.next); |
353 | if ((!lseg) && list_is_singular(&data->pages)) | 353 | if ((!lseg) && list_is_singular(&data->pages)) |
354 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ); | 354 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ, GFP_KERNEL); |
355 | 355 | ||
356 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, | 356 | ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count, |
357 | 0, lseg); | 357 | 0, lseg); |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2b8e9a5e366a..e288f06d3fa7 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1004,6 +1004,7 @@ static int nfs_parse_security_flavors(char *value, | |||
1004 | return 0; | 1004 | return 0; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | mnt->flags |= NFS_MOUNT_SECFLAVOUR; | ||
1007 | mnt->auth_flavor_len = 1; | 1008 | mnt->auth_flavor_len = 1; |
1008 | return 1; | 1009 | return 1; |
1009 | } | 1010 | } |
@@ -1976,6 +1977,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
1976 | if (error < 0) | 1977 | if (error < 0) |
1977 | goto out; | 1978 | goto out; |
1978 | 1979 | ||
1980 | /* | ||
1981 | * noac is a special case. It implies -o sync, but that's not | ||
1982 | * necessarily reflected in the mtab options. do_remount_sb | ||
1983 | * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the | ||
1984 | * remount options, so we have to explicitly reset it. | ||
1985 | */ | ||
1986 | if (data->flags & NFS_MOUNT_NOAC) | ||
1987 | *flags |= MS_SYNCHRONOUS; | ||
1988 | |||
1979 | /* compare new mount options with old ones */ | 1989 | /* compare new mount options with old ones */ |
1980 | error = nfs_compare_remount_data(nfss, data); | 1990 | error = nfs_compare_remount_data(nfss, data); |
1981 | out: | 1991 | out: |
@@ -2235,8 +2245,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2235 | if (!s->s_root) { | 2245 | if (!s->s_root) { |
2236 | /* initial superblock/root creation */ | 2246 | /* initial superblock/root creation */ |
2237 | nfs_fill_super(s, data); | 2247 | nfs_fill_super(s, data); |
2238 | nfs_fscache_get_super_cookie( | 2248 | nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL); |
2239 | s, data ? data->fscache_uniq : NULL, NULL); | ||
2240 | } | 2249 | } |
2241 | 2250 | ||
2242 | mntroot = nfs_get_root(s, mntfh, dev_name); | 2251 | mntroot = nfs_get_root(s, mntfh, dev_name); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e4cbc11a74ab..49c715b4ac92 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -680,7 +680,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
680 | req = nfs_setup_write_request(ctx, page, offset, count); | 680 | req = nfs_setup_write_request(ctx, page, offset, count); |
681 | if (IS_ERR(req)) | 681 | if (IS_ERR(req)) |
682 | return PTR_ERR(req); | 682 | return PTR_ERR(req); |
683 | nfs_mark_request_dirty(req); | ||
684 | /* Update file length */ | 683 | /* Update file length */ |
685 | nfs_grow_file(page, offset, count); | 684 | nfs_grow_file(page, offset, count); |
686 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | 685 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
@@ -940,7 +939,7 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
940 | atomic_set(&req->wb_complete, requests); | 939 | atomic_set(&req->wb_complete, requests); |
941 | 940 | ||
942 | BUG_ON(desc->pg_lseg); | 941 | BUG_ON(desc->pg_lseg); |
943 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 942 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS); |
944 | ClearPageError(page); | 943 | ClearPageError(page); |
945 | offset = 0; | 944 | offset = 0; |
946 | nbytes = desc->pg_count; | 945 | nbytes = desc->pg_count; |
@@ -1014,7 +1013,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
1014 | } | 1013 | } |
1015 | req = nfs_list_entry(data->pages.next); | 1014 | req = nfs_list_entry(data->pages.next); |
1016 | if ((!lseg) && list_is_singular(&data->pages)) | 1015 | if ((!lseg) && list_is_singular(&data->pages)) |
1017 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 1016 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW, GFP_NOFS); |
1018 | 1017 | ||
1019 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | 1018 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
1020 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | 1019 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) |
@@ -1418,8 +1417,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1418 | task->tk_pid, task->tk_status); | 1417 | task->tk_pid, task->tk_status); |
1419 | 1418 | ||
1420 | /* Call the NFS version-specific code */ | 1419 | /* Call the NFS version-specific code */ |
1421 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) | 1420 | NFS_PROTO(data->inode)->commit_done(task, data); |
1422 | return; | ||
1423 | } | 1421 | } |
1424 | 1422 | ||
1425 | void nfs_commit_release_pages(struct nfs_write_data *data) | 1423 | void nfs_commit_release_pages(struct nfs_write_data *data) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index aa309aa93fe8..4cf04e11c66c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -258,6 +258,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp) | |||
258 | if (atomic_dec_and_test(&fp->fi_delegees)) { | 258 | if (atomic_dec_and_test(&fp->fi_delegees)) { |
259 | vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); | 259 | vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); |
260 | fp->fi_lease = NULL; | 260 | fp->fi_lease = NULL; |
261 | fput(fp->fi_deleg_file); | ||
261 | fp->fi_deleg_file = NULL; | 262 | fp->fi_deleg_file = NULL; |
262 | } | 263 | } |
263 | } | 264 | } |
@@ -402,8 +403,8 @@ static void free_generic_stateid(struct nfs4_stateid *stp) | |||
402 | if (stp->st_access_bmap) { | 403 | if (stp->st_access_bmap) { |
403 | oflag = nfs4_access_bmap_to_omode(stp); | 404 | oflag = nfs4_access_bmap_to_omode(stp); |
404 | nfs4_file_put_access(stp->st_file, oflag); | 405 | nfs4_file_put_access(stp->st_file, oflag); |
405 | put_nfs4_file(stp->st_file); | ||
406 | } | 406 | } |
407 | put_nfs4_file(stp->st_file); | ||
407 | kmem_cache_free(stateid_slab, stp); | 408 | kmem_cache_free(stateid_slab, stp); |
408 | } | 409 | } |
409 | 410 | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2e1cebde90df..129f3c9f62d5 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1363,7 +1363,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1363 | goto out; | 1363 | goto out; |
1364 | if (!(iap->ia_valid & ATTR_MODE)) | 1364 | if (!(iap->ia_valid & ATTR_MODE)) |
1365 | iap->ia_mode = 0; | 1365 | iap->ia_mode = 0; |
1366 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); | 1366 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC); |
1367 | if (err) | 1367 | if (err) |
1368 | goto out; | 1368 | goto out; |
1369 | 1369 | ||
@@ -1385,6 +1385,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1385 | if (IS_ERR(dchild)) | 1385 | if (IS_ERR(dchild)) |
1386 | goto out_nfserr; | 1386 | goto out_nfserr; |
1387 | 1387 | ||
1388 | /* If file doesn't exist, check for permissions to create one */ | ||
1389 | if (!dchild->d_inode) { | ||
1390 | err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); | ||
1391 | if (err) | ||
1392 | goto out; | ||
1393 | } | ||
1394 | |||
1388 | err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); | 1395 | err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); |
1389 | if (err) | 1396 | if (err) |
1390 | goto out; | 1397 | goto out; |
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index 0a0a66d98cce..f7684483785e 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c | |||
@@ -646,7 +646,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) | |||
646 | unsigned long group, group_offset; | 646 | unsigned long group, group_offset; |
647 | int i, j, n, ret; | 647 | int i, j, n, ret; |
648 | 648 | ||
649 | for (i = 0; i < nitems; i += n) { | 649 | for (i = 0; i < nitems; i = j) { |
650 | group = nilfs_palloc_group(inode, entry_nrs[i], &group_offset); | 650 | group = nilfs_palloc_group(inode, entry_nrs[i], &group_offset); |
651 | ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh); | 651 | ret = nilfs_palloc_get_desc_block(inode, group, 0, &desc_bh); |
652 | if (ret < 0) | 652 | if (ret < 0) |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 643720209a98..9a3e6bbff27b 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -539,25 +539,41 @@ static int o2hb_verify_crc(struct o2hb_region *reg, | |||
539 | 539 | ||
540 | /* We want to make sure that nobody is heartbeating on top of us -- | 540 | /* We want to make sure that nobody is heartbeating on top of us -- |
541 | * this will help detect an invalid configuration. */ | 541 | * this will help detect an invalid configuration. */ |
542 | static int o2hb_check_last_timestamp(struct o2hb_region *reg) | 542 | static void o2hb_check_last_timestamp(struct o2hb_region *reg) |
543 | { | 543 | { |
544 | int node_num, ret; | ||
545 | struct o2hb_disk_slot *slot; | 544 | struct o2hb_disk_slot *slot; |
546 | struct o2hb_disk_heartbeat_block *hb_block; | 545 | struct o2hb_disk_heartbeat_block *hb_block; |
546 | char *errstr; | ||
547 | 547 | ||
548 | node_num = o2nm_this_node(); | 548 | slot = ®->hr_slots[o2nm_this_node()]; |
549 | |||
550 | ret = 1; | ||
551 | slot = ®->hr_slots[node_num]; | ||
552 | /* Don't check on our 1st timestamp */ | 549 | /* Don't check on our 1st timestamp */ |
553 | if (slot->ds_last_time) { | 550 | if (!slot->ds_last_time) |
554 | hb_block = slot->ds_raw_block; | 551 | return; |
555 | 552 | ||
556 | if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time) | 553 | hb_block = slot->ds_raw_block; |
557 | ret = 0; | 554 | if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time && |
558 | } | 555 | le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation && |
556 | hb_block->hb_node == slot->ds_node_num) | ||
557 | return; | ||
559 | 558 | ||
560 | return ret; | 559 | #define ERRSTR1 "Another node is heartbeating on device" |
560 | #define ERRSTR2 "Heartbeat generation mismatch on device" | ||
561 | #define ERRSTR3 "Heartbeat sequence mismatch on device" | ||
562 | |||
563 | if (hb_block->hb_node != slot->ds_node_num) | ||
564 | errstr = ERRSTR1; | ||
565 | else if (le64_to_cpu(hb_block->hb_generation) != | ||
566 | slot->ds_last_generation) | ||
567 | errstr = ERRSTR2; | ||
568 | else | ||
569 | errstr = ERRSTR3; | ||
570 | |||
571 | mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), " | ||
572 | "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name, | ||
573 | slot->ds_node_num, (unsigned long long)slot->ds_last_generation, | ||
574 | (unsigned long long)slot->ds_last_time, hb_block->hb_node, | ||
575 | (unsigned long long)le64_to_cpu(hb_block->hb_generation), | ||
576 | (unsigned long long)le64_to_cpu(hb_block->hb_seq)); | ||
561 | } | 577 | } |
562 | 578 | ||
563 | static inline void o2hb_prepare_block(struct o2hb_region *reg, | 579 | static inline void o2hb_prepare_block(struct o2hb_region *reg, |
@@ -983,9 +999,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
983 | /* With an up to date view of the slots, we can check that no | 999 | /* With an up to date view of the slots, we can check that no |
984 | * other node has been improperly configured to heartbeat in | 1000 | * other node has been improperly configured to heartbeat in |
985 | * our slot. */ | 1001 | * our slot. */ |
986 | if (!o2hb_check_last_timestamp(reg)) | 1002 | o2hb_check_last_timestamp(reg); |
987 | mlog(ML_ERROR, "Device \"%s\": another node is heartbeating " | ||
988 | "in our slot!\n", reg->hr_dev_name); | ||
989 | 1003 | ||
990 | /* fill in the proper info for our next heartbeat */ | 1004 | /* fill in the proper info for our next heartbeat */ |
991 | o2hb_prepare_block(reg, reg->hr_generation); | 1005 | o2hb_prepare_block(reg, reg->hr_generation); |
@@ -999,8 +1013,8 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
999 | } | 1013 | } |
1000 | 1014 | ||
1001 | i = -1; | 1015 | i = -1; |
1002 | while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { | 1016 | while((i = find_next_bit(configured_nodes, |
1003 | 1017 | O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) { | |
1004 | change |= o2hb_check_slot(reg, ®->hr_slots[i]); | 1018 | change |= o2hb_check_slot(reg, ®->hr_slots[i]); |
1005 | } | 1019 | } |
1006 | 1020 | ||
@@ -1690,6 +1704,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, | |||
1690 | struct file *filp = NULL; | 1704 | struct file *filp = NULL; |
1691 | struct inode *inode = NULL; | 1705 | struct inode *inode = NULL; |
1692 | ssize_t ret = -EINVAL; | 1706 | ssize_t ret = -EINVAL; |
1707 | int live_threshold; | ||
1693 | 1708 | ||
1694 | if (reg->hr_bdev) | 1709 | if (reg->hr_bdev) |
1695 | goto out; | 1710 | goto out; |
@@ -1766,8 +1781,18 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg, | |||
1766 | * A node is considered live after it has beat LIVE_THRESHOLD | 1781 | * A node is considered live after it has beat LIVE_THRESHOLD |
1767 | * times. We're not steady until we've given them a chance | 1782 | * times. We're not steady until we've given them a chance |
1768 | * _after_ our first read. | 1783 | * _after_ our first read. |
1784 | * The default threshold is bare minimum so as to limit the delay | ||
1785 | * during mounts. For global heartbeat, the threshold doubled for the | ||
1786 | * first region. | ||
1769 | */ | 1787 | */ |
1770 | atomic_set(®->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); | 1788 | live_threshold = O2HB_LIVE_THRESHOLD; |
1789 | if (o2hb_global_heartbeat_active()) { | ||
1790 | spin_lock(&o2hb_live_lock); | ||
1791 | if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1) | ||
1792 | live_threshold <<= 1; | ||
1793 | spin_unlock(&o2hb_live_lock); | ||
1794 | } | ||
1795 | atomic_set(®->hr_steady_iterations, live_threshold + 1); | ||
1771 | 1796 | ||
1772 | hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", | 1797 | hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s", |
1773 | reg->hr_item.ci_name); | 1798 | reg->hr_item.ci_name); |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 9fe5b8fd658f..8582e3f4f120 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -2868,7 +2868,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, | |||
2868 | bytes = blocks_wanted << sb->s_blocksize_bits; | 2868 | bytes = blocks_wanted << sb->s_blocksize_bits; |
2869 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 2869 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
2870 | struct ocfs2_inode_info *oi = OCFS2_I(dir); | 2870 | struct ocfs2_inode_info *oi = OCFS2_I(dir); |
2871 | struct ocfs2_alloc_context *data_ac; | 2871 | struct ocfs2_alloc_context *data_ac = NULL; |
2872 | struct ocfs2_alloc_context *meta_ac = NULL; | 2872 | struct ocfs2_alloc_context *meta_ac = NULL; |
2873 | struct buffer_head *dirdata_bh = NULL; | 2873 | struct buffer_head *dirdata_bh = NULL; |
2874 | struct buffer_head *dx_root_bh = NULL; | 2874 | struct buffer_head *dx_root_bh = NULL; |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 7540a492eaba..3b179d6cbde0 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -1614,7 +1614,8 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) | |||
1614 | spin_unlock(&dlm->spinlock); | 1614 | spin_unlock(&dlm->spinlock); |
1615 | 1615 | ||
1616 | /* Support for global heartbeat and node info was added in 1.1 */ | 1616 | /* Support for global heartbeat and node info was added in 1.1 */ |
1617 | if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) { | 1617 | if (dlm->dlm_locking_proto.pv_major > 1 || |
1618 | dlm->dlm_locking_proto.pv_minor > 0) { | ||
1618 | status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map); | 1619 | status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map); |
1619 | if (status) { | 1620 | if (status) { |
1620 | mlog_errno(status); | 1621 | mlog_errno(status); |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index fede57ed005f..84d166328cf7 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -2574,6 +2574,9 @@ fail: | |||
2574 | res->state &= ~DLM_LOCK_RES_MIGRATING; | 2574 | res->state &= ~DLM_LOCK_RES_MIGRATING; |
2575 | wake = 1; | 2575 | wake = 1; |
2576 | spin_unlock(&res->spinlock); | 2576 | spin_unlock(&res->spinlock); |
2577 | if (dlm_is_host_down(ret)) | ||
2578 | dlm_wait_for_node_death(dlm, target, | ||
2579 | DLM_NODE_DEATH_WAIT_MAX); | ||
2577 | goto leave; | 2580 | goto leave; |
2578 | } | 2581 | } |
2579 | 2582 | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 41565ae52856..89659d6dc206 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1607,6 +1607,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode, | |||
1607 | range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec); | 1607 | range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec); |
1608 | 1608 | ||
1609 | if (le32_to_cpu(rec->e_cpos) >= trunc_start) { | 1609 | if (le32_to_cpu(rec->e_cpos) >= trunc_start) { |
1610 | /* | ||
1611 | * remove an entire extent record. | ||
1612 | */ | ||
1610 | *trunc_cpos = le32_to_cpu(rec->e_cpos); | 1613 | *trunc_cpos = le32_to_cpu(rec->e_cpos); |
1611 | /* | 1614 | /* |
1612 | * Skip holes if any. | 1615 | * Skip holes if any. |
@@ -1617,7 +1620,16 @@ static void ocfs2_calc_trunc_pos(struct inode *inode, | |||
1617 | *blkno = le64_to_cpu(rec->e_blkno); | 1620 | *blkno = le64_to_cpu(rec->e_blkno); |
1618 | *trunc_end = le32_to_cpu(rec->e_cpos); | 1621 | *trunc_end = le32_to_cpu(rec->e_cpos); |
1619 | } else if (range > trunc_start) { | 1622 | } else if (range > trunc_start) { |
1623 | /* | ||
1624 | * remove a partial extent record, which means we're | ||
1625 | * removing the last extent record. | ||
1626 | */ | ||
1620 | *trunc_cpos = trunc_start; | 1627 | *trunc_cpos = trunc_start; |
1628 | /* | ||
1629 | * skip hole if any. | ||
1630 | */ | ||
1631 | if (range < *trunc_end) | ||
1632 | *trunc_end = range; | ||
1621 | *trunc_len = *trunc_end - trunc_start; | 1633 | *trunc_len = *trunc_end - trunc_start; |
1622 | coff = trunc_start - le32_to_cpu(rec->e_cpos); | 1634 | coff = trunc_start - le32_to_cpu(rec->e_cpos); |
1623 | *blkno = le64_to_cpu(rec->e_blkno) + | 1635 | *blkno = le64_to_cpu(rec->e_blkno) + |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index b141a44605ca..295d56454e8b 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -1260,6 +1260,9 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb) | |||
1260 | { | 1260 | { |
1261 | struct ocfs2_journal *journal = osb->journal; | 1261 | struct ocfs2_journal *journal = osb->journal; |
1262 | 1262 | ||
1263 | if (ocfs2_is_hard_readonly(osb)) | ||
1264 | return; | ||
1265 | |||
1263 | /* No need to queue up our truncate_log as regular cleanup will catch | 1266 | /* No need to queue up our truncate_log as regular cleanup will catch |
1264 | * that */ | 1267 | * that */ |
1265 | ocfs2_queue_recovery_completion(journal, osb->slot_num, | 1268 | ocfs2_queue_recovery_completion(journal, osb->slot_num, |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index b68f87a83924..938387a10d5d 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -1019,7 +1019,7 @@ struct ocfs2_xattr_entry { | |||
1019 | __le16 xe_name_offset; /* byte offset from the 1st entry in the | 1019 | __le16 xe_name_offset; /* byte offset from the 1st entry in the |
1020 | local xattr storage(inode, xattr block or | 1020 | local xattr storage(inode, xattr block or |
1021 | xattr bucket). */ | 1021 | xattr bucket). */ |
1022 | __u8 xe_name_len; /* xattr name len, does't include prefix. */ | 1022 | __u8 xe_name_len; /* xattr name len, doesn't include prefix. */ |
1023 | __u8 xe_type; /* the low 7 bits indicate the name prefix | 1023 | __u8 xe_type; /* the low 7 bits indicate the name prefix |
1024 | * type and the highest bit indicates whether | 1024 | * type and the highest bit indicates whether |
1025 | * the EA is stored in the local storage. */ | 1025 | * the EA is stored in the local storage. */ |
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index ac0ccb5026a2..19d6750d1d6c 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c | |||
@@ -348,6 +348,12 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, | |||
348 | goto fail; | 348 | goto fail; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* Check that sizeof_partition_entry has the correct value */ | ||
352 | if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { | ||
353 | pr_debug("GUID Partitition Entry Size check failed.\n"); | ||
354 | goto fail; | ||
355 | } | ||
356 | |||
351 | if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) | 357 | if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) |
352 | goto fail; | 358 | goto fail; |
353 | 359 | ||
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 2e7addfd9803..318d8654989b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -214,7 +214,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) | |||
214 | int flags = vma->vm_flags; | 214 | int flags = vma->vm_flags; |
215 | unsigned long ino = 0; | 215 | unsigned long ino = 0; |
216 | unsigned long long pgoff = 0; | 216 | unsigned long long pgoff = 0; |
217 | unsigned long start; | 217 | unsigned long start, end; |
218 | dev_t dev = 0; | 218 | dev_t dev = 0; |
219 | int len; | 219 | int len; |
220 | 220 | ||
@@ -227,13 +227,15 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) | |||
227 | 227 | ||
228 | /* We don't show the stack guard page in /proc/maps */ | 228 | /* We don't show the stack guard page in /proc/maps */ |
229 | start = vma->vm_start; | 229 | start = vma->vm_start; |
230 | if (vma->vm_flags & VM_GROWSDOWN) | 230 | if (stack_guard_page_start(vma, start)) |
231 | if (!vma_stack_continue(vma->vm_prev, vma->vm_start)) | 231 | start += PAGE_SIZE; |
232 | start += PAGE_SIZE; | 232 | end = vma->vm_end; |
233 | if (stack_guard_page_end(vma, end)) | ||
234 | end -= PAGE_SIZE; | ||
233 | 235 | ||
234 | seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", | 236 | seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", |
235 | start, | 237 | start, |
236 | vma->vm_end, | 238 | end, |
237 | flags & VM_READ ? 'r' : '-', | 239 | flags & VM_READ ? 'r' : '-', |
238 | flags & VM_WRITE ? 'w' : '-', | 240 | flags & VM_WRITE ? 'w' : '-', |
239 | flags & VM_EXEC ? 'x' : '-', | 241 | flags & VM_EXEC ? 'x' : '-', |
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index 4d0cb1241460..40fa780ebea7 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c | |||
@@ -175,26 +175,6 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud) | |||
175 | } | 175 | } |
176 | 176 | ||
177 | /** | 177 | /** |
178 | * ubifs_create_buds_lists - create journal head buds lists for remount rw. | ||
179 | * @c: UBIFS file-system description object | ||
180 | */ | ||
181 | void ubifs_create_buds_lists(struct ubifs_info *c) | ||
182 | { | ||
183 | struct rb_node *p; | ||
184 | |||
185 | spin_lock(&c->buds_lock); | ||
186 | p = rb_first(&c->buds); | ||
187 | while (p) { | ||
188 | struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb); | ||
189 | struct ubifs_jhead *jhead = &c->jheads[bud->jhead]; | ||
190 | |||
191 | list_add_tail(&bud->list, &jhead->buds_list); | ||
192 | p = rb_next(p); | ||
193 | } | ||
194 | spin_unlock(&c->buds_lock); | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * ubifs_add_bud_to_log - add a new bud to the log. | 178 | * ubifs_add_bud_to_log - add a new bud to the log. |
199 | * @c: UBIFS file-system description object | 179 | * @c: UBIFS file-system description object |
200 | * @jhead: journal head the bud belongs to | 180 | * @jhead: journal head the bud belongs to |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 936f2cbfe6b6..3dbad6fbd1eb 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c) | |||
317 | goto out_free; | 317 | goto out_free; |
318 | } | 318 | } |
319 | memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); | 319 | memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); |
320 | |||
321 | /* | ||
322 | * We had to recover the master node, which means there was an | ||
323 | * unclean reboot. However, it is possible that the master node | ||
324 | * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. | ||
325 | * E.g., consider the following chain of events: | ||
326 | * | ||
327 | * 1. UBIFS was cleanly unmounted, so the master node is clean | ||
328 | * 2. UBIFS is being mounted R/W and starts changing the master | ||
329 | * node in the first (%UBIFS_MST_LNUM). A power cut happens, | ||
330 | * so this LEB ends up with some amount of garbage at the | ||
331 | * end. | ||
332 | * 3. UBIFS is being mounted R/O. We reach this place and | ||
333 | * recover the master node from the second LEB | ||
334 | * (%UBIFS_MST_LNUM + 1). But we cannot update the media | ||
335 | * because we are being mounted R/O. We have to defer the | ||
336 | * operation. | ||
337 | * 4. However, this master node (@c->mst_node) is marked as | ||
338 | * clean (since the step 1). And if we just return, the | ||
339 | * mount code will be confused and won't recover the master | ||
340 | * node when it is re-mounter R/W later. | ||
341 | * | ||
342 | * Thus, to force the recovery by marking the master node as | ||
343 | * dirty. | ||
344 | */ | ||
345 | c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); | ||
320 | } else { | 346 | } else { |
321 | /* Write the recovered master node */ | 347 | /* Write the recovered master node */ |
322 | c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; | 348 | c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; |
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index eed0fcff8d73..d3d6d365bfc1 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c | |||
@@ -59,6 +59,7 @@ enum { | |||
59 | * @new_size: truncation new size | 59 | * @new_size: truncation new size |
60 | * @free: amount of free space in a bud | 60 | * @free: amount of free space in a bud |
61 | * @dirty: amount of dirty space in a bud from padding and deletion nodes | 61 | * @dirty: amount of dirty space in a bud from padding and deletion nodes |
62 | * @jhead: journal head number of the bud | ||
62 | * | 63 | * |
63 | * UBIFS journal replay must compare node sequence numbers, which means it must | 64 | * UBIFS journal replay must compare node sequence numbers, which means it must |
64 | * build a tree of node information to insert into the TNC. | 65 | * build a tree of node information to insert into the TNC. |
@@ -80,6 +81,7 @@ struct replay_entry { | |||
80 | struct { | 81 | struct { |
81 | int free; | 82 | int free; |
82 | int dirty; | 83 | int dirty; |
84 | int jhead; | ||
83 | }; | 85 | }; |
84 | }; | 86 | }; |
85 | }; | 87 | }; |
@@ -159,6 +161,11 @@ static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r) | |||
159 | err = PTR_ERR(lp); | 161 | err = PTR_ERR(lp); |
160 | goto out; | 162 | goto out; |
161 | } | 163 | } |
164 | |||
165 | /* Make sure the journal head points to the latest bud */ | ||
166 | err = ubifs_wbuf_seek_nolock(&c->jheads[r->jhead].wbuf, r->lnum, | ||
167 | c->leb_size - r->free, UBI_SHORTTERM); | ||
168 | |||
162 | out: | 169 | out: |
163 | ubifs_release_lprops(c); | 170 | ubifs_release_lprops(c); |
164 | return err; | 171 | return err; |
@@ -627,10 +634,6 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead, | |||
627 | ubifs_assert(sleb->endpt - offs >= used); | 634 | ubifs_assert(sleb->endpt - offs >= used); |
628 | ubifs_assert(sleb->endpt % c->min_io_size == 0); | 635 | ubifs_assert(sleb->endpt % c->min_io_size == 0); |
629 | 636 | ||
630 | if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount) | ||
631 | err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum, | ||
632 | sleb->endpt, UBI_SHORTTERM); | ||
633 | |||
634 | *dirty = sleb->endpt - offs - used; | 637 | *dirty = sleb->endpt - offs - used; |
635 | *free = c->leb_size - sleb->endpt; | 638 | *free = c->leb_size - sleb->endpt; |
636 | 639 | ||
@@ -653,12 +656,14 @@ out_dump: | |||
653 | * @sqnum: sequence number | 656 | * @sqnum: sequence number |
654 | * @free: amount of free space in bud | 657 | * @free: amount of free space in bud |
655 | * @dirty: amount of dirty space from padding and deletion nodes | 658 | * @dirty: amount of dirty space from padding and deletion nodes |
659 | * @jhead: journal head number for the bud | ||
656 | * | 660 | * |
657 | * This function inserts a reference node to the replay tree and returns zero | 661 | * This function inserts a reference node to the replay tree and returns zero |
658 | * in case of success or a negative error code in case of failure. | 662 | * in case of success or a negative error code in case of failure. |
659 | */ | 663 | */ |
660 | static int insert_ref_node(struct ubifs_info *c, int lnum, int offs, | 664 | static int insert_ref_node(struct ubifs_info *c, int lnum, int offs, |
661 | unsigned long long sqnum, int free, int dirty) | 665 | unsigned long long sqnum, int free, int dirty, |
666 | int jhead) | ||
662 | { | 667 | { |
663 | struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; | 668 | struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL; |
664 | struct replay_entry *r; | 669 | struct replay_entry *r; |
@@ -688,6 +693,7 @@ static int insert_ref_node(struct ubifs_info *c, int lnum, int offs, | |||
688 | r->flags = REPLAY_REF; | 693 | r->flags = REPLAY_REF; |
689 | r->free = free; | 694 | r->free = free; |
690 | r->dirty = dirty; | 695 | r->dirty = dirty; |
696 | r->jhead = jhead; | ||
691 | 697 | ||
692 | rb_link_node(&r->rb, parent, p); | 698 | rb_link_node(&r->rb, parent, p); |
693 | rb_insert_color(&r->rb, &c->replay_tree); | 699 | rb_insert_color(&r->rb, &c->replay_tree); |
@@ -712,7 +718,7 @@ static int replay_buds(struct ubifs_info *c) | |||
712 | if (err) | 718 | if (err) |
713 | return err; | 719 | return err; |
714 | err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum, | 720 | err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum, |
715 | free, dirty); | 721 | free, dirty, b->bud->jhead); |
716 | if (err) | 722 | if (err) |
717 | return err; | 723 | return err; |
718 | } | 724 | } |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index c75f6133206c..04ad07f4fcc3 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -1257,12 +1257,12 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1257 | goto out_free; | 1257 | goto out_free; |
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | err = alloc_wbufs(c); | ||
1261 | if (err) | ||
1262 | goto out_cbuf; | ||
1263 | |||
1260 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); | 1264 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); |
1261 | if (!c->ro_mount) { | 1265 | if (!c->ro_mount) { |
1262 | err = alloc_wbufs(c); | ||
1263 | if (err) | ||
1264 | goto out_cbuf; | ||
1265 | |||
1266 | /* Create background thread */ | 1266 | /* Create background thread */ |
1267 | c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); | 1267 | c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); |
1268 | if (IS_ERR(c->bgt)) { | 1268 | if (IS_ERR(c->bgt)) { |
@@ -1631,12 +1631,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1631 | if (err) | 1631 | if (err) |
1632 | goto out; | 1632 | goto out; |
1633 | 1633 | ||
1634 | err = alloc_wbufs(c); | ||
1635 | if (err) | ||
1636 | goto out; | ||
1637 | |||
1638 | ubifs_create_buds_lists(c); | ||
1639 | |||
1640 | /* Create background thread */ | 1634 | /* Create background thread */ |
1641 | c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); | 1635 | c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); |
1642 | if (IS_ERR(c->bgt)) { | 1636 | if (IS_ERR(c->bgt)) { |
@@ -1671,14 +1665,25 @@ static int ubifs_remount_rw(struct ubifs_info *c) | |||
1671 | if (err) | 1665 | if (err) |
1672 | goto out; | 1666 | goto out; |
1673 | 1667 | ||
1668 | dbg_gen("re-mounted read-write"); | ||
1669 | c->remounting_rw = 0; | ||
1670 | |||
1674 | if (c->need_recovery) { | 1671 | if (c->need_recovery) { |
1675 | c->need_recovery = 0; | 1672 | c->need_recovery = 0; |
1676 | ubifs_msg("deferred recovery completed"); | 1673 | ubifs_msg("deferred recovery completed"); |
1674 | } else { | ||
1675 | /* | ||
1676 | * Do not run the debugging space check if the were doing | ||
1677 | * recovery, because when we saved the information we had the | ||
1678 | * file-system in a state where the TNC and lprops has been | ||
1679 | * modified in memory, but all the I/O operations (including a | ||
1680 | * commit) were deferred. So the file-system was in | ||
1681 | * "non-committed" state. Now the file-system is in committed | ||
1682 | * state, and of course the amount of free space will change | ||
1683 | * because, for example, the old index size was imprecise. | ||
1684 | */ | ||
1685 | err = dbg_check_space_info(c); | ||
1677 | } | 1686 | } |
1678 | |||
1679 | dbg_gen("re-mounted read-write"); | ||
1680 | c->remounting_rw = 0; | ||
1681 | err = dbg_check_space_info(c); | ||
1682 | mutex_unlock(&c->umount_mutex); | 1687 | mutex_unlock(&c->umount_mutex); |
1683 | return err; | 1688 | return err; |
1684 | 1689 | ||
@@ -1733,7 +1738,6 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
1733 | if (err) | 1738 | if (err) |
1734 | ubifs_ro_mode(c, err); | 1739 | ubifs_ro_mode(c, err); |
1735 | 1740 | ||
1736 | free_wbufs(c); | ||
1737 | vfree(c->orph_buf); | 1741 | vfree(c->orph_buf); |
1738 | c->orph_buf = NULL; | 1742 | c->orph_buf = NULL; |
1739 | kfree(c->write_reserve_buf); | 1743 | kfree(c->write_reserve_buf); |
@@ -1761,10 +1765,12 @@ static void ubifs_put_super(struct super_block *sb) | |||
1761 | * of the media. For example, there will be dirty inodes if we failed | 1765 | * of the media. For example, there will be dirty inodes if we failed |
1762 | * to write them back because of I/O errors. | 1766 | * to write them back because of I/O errors. |
1763 | */ | 1767 | */ |
1764 | ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); | 1768 | if (!c->ro_error) { |
1765 | ubifs_assert(c->budg_idx_growth == 0); | 1769 | ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0); |
1766 | ubifs_assert(c->budg_dd_growth == 0); | 1770 | ubifs_assert(c->budg_idx_growth == 0); |
1767 | ubifs_assert(c->budg_data_growth == 0); | 1771 | ubifs_assert(c->budg_dd_growth == 0); |
1772 | ubifs_assert(c->budg_data_growth == 0); | ||
1773 | } | ||
1768 | 1774 | ||
1769 | /* | 1775 | /* |
1770 | * The 'c->umount_lock' prevents races between UBIFS memory shrinker | 1776 | * The 'c->umount_lock' prevents races between UBIFS memory shrinker |
diff --git a/fs/xattr.c b/fs/xattr.c index a19acdb81cd1..f1ef94974dea 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -666,7 +666,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz | |||
666 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 666 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); |
667 | if (!handler) | 667 | if (!handler) |
668 | return -EOPNOTSUPP; | 668 | return -EOPNOTSUPP; |
669 | return handler->set(dentry, name, value, size, 0, handler->flags); | 669 | return handler->set(dentry, name, value, size, flags, handler->flags); |
670 | } | 670 | } |
671 | 671 | ||
672 | /* | 672 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c index 3ca795609113..9f76cceb678d 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/linux-2.6/xfs_message.c | |||
@@ -34,8 +34,10 @@ __xfs_printk( | |||
34 | const struct xfs_mount *mp, | 34 | const struct xfs_mount *mp, |
35 | struct va_format *vaf) | 35 | struct va_format *vaf) |
36 | { | 36 | { |
37 | if (mp && mp->m_fsname) | 37 | if (mp && mp->m_fsname) { |
38 | printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf); | 38 | printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf); |
39 | return; | ||
40 | } | ||
39 | printk("%sXFS: %pV\n", level, vaf); | 41 | printk("%sXFS: %pV\n", level, vaf); |
40 | } | 42 | } |
41 | 43 | ||
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index e4f9c1b0836c..3e898a48122d 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -926,6 +926,7 @@ restart: | |||
926 | XFS_LOOKUP_BATCH, | 926 | XFS_LOOKUP_BATCH, |
927 | XFS_ICI_RECLAIM_TAG); | 927 | XFS_ICI_RECLAIM_TAG); |
928 | if (!nr_found) { | 928 | if (!nr_found) { |
929 | done = 1; | ||
929 | rcu_read_unlock(); | 930 | rcu_read_unlock(); |
930 | break; | 931 | break; |
931 | } | 932 | } |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index acdb92f14d51..5fc2380092c8 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -346,20 +346,23 @@ xfs_ail_delete( | |||
346 | */ | 346 | */ |
347 | STATIC void | 347 | STATIC void |
348 | xfs_ail_worker( | 348 | xfs_ail_worker( |
349 | struct work_struct *work) | 349 | struct work_struct *work) |
350 | { | 350 | { |
351 | struct xfs_ail *ailp = container_of(to_delayed_work(work), | 351 | struct xfs_ail *ailp = container_of(to_delayed_work(work), |
352 | struct xfs_ail, xa_work); | 352 | struct xfs_ail, xa_work); |
353 | long tout; | 353 | xfs_mount_t *mp = ailp->xa_mount; |
354 | xfs_lsn_t target = ailp->xa_target; | ||
355 | xfs_lsn_t lsn; | ||
356 | xfs_log_item_t *lip; | ||
357 | int flush_log, count, stuck; | ||
358 | xfs_mount_t *mp = ailp->xa_mount; | ||
359 | struct xfs_ail_cursor *cur = &ailp->xa_cursors; | 354 | struct xfs_ail_cursor *cur = &ailp->xa_cursors; |
360 | int push_xfsbufd = 0; | 355 | xfs_log_item_t *lip; |
356 | xfs_lsn_t lsn; | ||
357 | xfs_lsn_t target; | ||
358 | long tout = 10; | ||
359 | int flush_log = 0; | ||
360 | int stuck = 0; | ||
361 | int count = 0; | ||
362 | int push_xfsbufd = 0; | ||
361 | 363 | ||
362 | spin_lock(&ailp->xa_lock); | 364 | spin_lock(&ailp->xa_lock); |
365 | target = ailp->xa_target; | ||
363 | xfs_trans_ail_cursor_init(ailp, cur); | 366 | xfs_trans_ail_cursor_init(ailp, cur); |
364 | lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn); | 367 | lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn); |
365 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { | 368 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { |
@@ -368,8 +371,7 @@ xfs_ail_worker( | |||
368 | */ | 371 | */ |
369 | xfs_trans_ail_cursor_done(ailp, cur); | 372 | xfs_trans_ail_cursor_done(ailp, cur); |
370 | spin_unlock(&ailp->xa_lock); | 373 | spin_unlock(&ailp->xa_lock); |
371 | ailp->xa_last_pushed_lsn = 0; | 374 | goto out_done; |
372 | return; | ||
373 | } | 375 | } |
374 | 376 | ||
375 | XFS_STATS_INC(xs_push_ail); | 377 | XFS_STATS_INC(xs_push_ail); |
@@ -386,8 +388,7 @@ xfs_ail_worker( | |||
386 | * lots of contention on the AIL lists. | 388 | * lots of contention on the AIL lists. |
387 | */ | 389 | */ |
388 | lsn = lip->li_lsn; | 390 | lsn = lip->li_lsn; |
389 | flush_log = stuck = count = 0; | 391 | while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { |
390 | while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) { | ||
391 | int lock_result; | 392 | int lock_result; |
392 | /* | 393 | /* |
393 | * If we can lock the item without sleeping, unlock the AIL | 394 | * If we can lock the item without sleeping, unlock the AIL |
@@ -480,21 +481,25 @@ xfs_ail_worker( | |||
480 | } | 481 | } |
481 | 482 | ||
482 | /* assume we have more work to do in a short while */ | 483 | /* assume we have more work to do in a short while */ |
483 | tout = 10; | 484 | out_done: |
484 | if (!count) { | 485 | if (!count) { |
485 | /* We're past our target or empty, so idle */ | 486 | /* We're past our target or empty, so idle */ |
486 | ailp->xa_last_pushed_lsn = 0; | 487 | ailp->xa_last_pushed_lsn = 0; |
487 | 488 | ||
488 | /* | 489 | /* |
489 | * Check for an updated push target before clearing the | 490 | * We clear the XFS_AIL_PUSHING_BIT first before checking |
490 | * XFS_AIL_PUSHING_BIT. If the target changed, we've got more | 491 | * whether the target has changed. If the target has changed, |
491 | * work to do. Wait a bit longer before starting that work. | 492 | * this pushes the requeue race directly onto the result of the |
493 | * atomic test/set bit, so we are guaranteed that either the | ||
494 | * the pusher that changed the target or ourselves will requeue | ||
495 | * the work (but not both). | ||
492 | */ | 496 | */ |
497 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | ||
493 | smp_rmb(); | 498 | smp_rmb(); |
494 | if (ailp->xa_target == target) { | 499 | if (XFS_LSN_CMP(ailp->xa_target, target) == 0 || |
495 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | 500 | test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) |
496 | return; | 501 | return; |
497 | } | 502 | |
498 | tout = 50; | 503 | tout = 50; |
499 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { | 504 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { |
500 | /* | 505 | /* |
@@ -553,7 +558,7 @@ xfs_ail_push( | |||
553 | * the XFS_AIL_PUSHING_BIT. | 558 | * the XFS_AIL_PUSHING_BIT. |
554 | */ | 559 | */ |
555 | smp_wmb(); | 560 | smp_wmb(); |
556 | ailp->xa_target = threshold_lsn; | 561 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); |
557 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | 562 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) |
558 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); | 563 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); |
559 | } | 564 | } |