diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-05-22 22:35:33 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-05-22 22:35:33 -0400 |
commit | 8ace5c4698ec8da53e69095596718d5a936433de (patch) | |
tree | 1f5959b3ac289e3bde420cc14109be0cc518a75a /fs | |
parent | a375b15164dd9264f724ad941825e52c90145151 (diff) | |
parent | 71a8638480eb8fb6cfabe2ee9ca3fbc6e3453a14 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into sh-latest
Diffstat (limited to 'fs')
148 files changed, 5274 insertions, 4789 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5147bdd3b8e1..257b00e98428 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1102,6 +1102,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1102 | if (!bdev->bd_part) | 1102 | if (!bdev->bd_part) |
1103 | goto out_clear; | 1103 | goto out_clear; |
1104 | 1104 | ||
1105 | ret = 0; | ||
1105 | if (disk->fops->open) { | 1106 | if (disk->fops->open) { |
1106 | ret = disk->fops->open(bdev, mode); | 1107 | ret = disk->fops->open(bdev, mode); |
1107 | if (ret == -ERESTARTSYS) { | 1108 | if (ret == -ERESTARTSYS) { |
@@ -1118,9 +1119,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1118 | put_disk(disk); | 1119 | put_disk(disk); |
1119 | goto restart; | 1120 | goto restart; |
1120 | } | 1121 | } |
1121 | if (ret) | ||
1122 | goto out_clear; | ||
1123 | } | 1122 | } |
1123 | /* | ||
1124 | * If the device is invalidated, rescan partition | ||
1125 | * if open succeeded or failed with -ENOMEDIUM. | ||
1126 | * The latter is necessary to prevent ghost | ||
1127 | * partitions on a removed medium. | ||
1128 | */ | ||
1129 | if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) | ||
1130 | rescan_partitions(disk, bdev); | ||
1131 | if (ret) | ||
1132 | goto out_clear; | ||
1133 | |||
1124 | if (!bdev->bd_openers) { | 1134 | if (!bdev->bd_openers) { |
1125 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); | 1135 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); |
1126 | bdi = blk_get_backing_dev_info(bdev); | 1136 | bdi = blk_get_backing_dev_info(bdev); |
@@ -1128,8 +1138,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1128 | bdi = &default_backing_dev_info; | 1138 | bdi = &default_backing_dev_info; |
1129 | bdev_inode_switch_bdi(bdev->bd_inode, bdi); | 1139 | bdev_inode_switch_bdi(bdev->bd_inode, bdi); |
1130 | } | 1140 | } |
1131 | if (bdev->bd_invalidated) | ||
1132 | rescan_partitions(disk, bdev); | ||
1133 | } else { | 1141 | } else { |
1134 | struct block_device *whole; | 1142 | struct block_device *whole; |
1135 | whole = bdget_disk(disk, 0); | 1143 | whole = bdget_disk(disk, 0); |
@@ -1153,13 +1161,14 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
1153 | } | 1161 | } |
1154 | } else { | 1162 | } else { |
1155 | if (bdev->bd_contains == bdev) { | 1163 | if (bdev->bd_contains == bdev) { |
1156 | if (bdev->bd_disk->fops->open) { | 1164 | ret = 0; |
1165 | if (bdev->bd_disk->fops->open) | ||
1157 | ret = bdev->bd_disk->fops->open(bdev, mode); | 1166 | ret = bdev->bd_disk->fops->open(bdev, mode); |
1158 | if (ret) | 1167 | /* the same as first opener case, read comment there */ |
1159 | goto out_unlock_bdev; | 1168 | if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) |
1160 | } | ||
1161 | if (bdev->bd_invalidated) | ||
1162 | rescan_partitions(bdev->bd_disk, bdev); | 1169 | rescan_partitions(bdev->bd_disk, bdev); |
1170 | if (ret) | ||
1171 | goto out_unlock_bdev; | ||
1163 | } | 1172 | } |
1164 | /* only one opener holds refs to the module and disk */ | 1173 | /* only one opener holds refs to the module and disk */ |
1165 | module_put(disk->fops->owner); | 1174 | module_put(disk->fops->owner); |
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index de34bfad9ec3..44ea5b92e1ba 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -178,16 +178,18 @@ 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 (acl == NULL) { | 181 | if (IS_ERR(acl)) |
182 | value = NULL; | ||
183 | size = 0; | ||
184 | } else if (IS_ERR(acl)) { | ||
185 | return PTR_ERR(acl); | 182 | return PTR_ERR(acl); |
183 | |||
184 | if (acl) { | ||
185 | ret = posix_acl_valid(acl); | ||
186 | if (ret) | ||
187 | goto out; | ||
186 | } | 188 | } |
187 | } | 189 | } |
188 | 190 | ||
189 | ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type); | 191 | ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type); |
190 | 192 | out: | |
191 | posix_acl_release(acl); | 193 | posix_acl_release(acl); |
192 | 194 | ||
193 | return ret; | 195 | return ret; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 3458b5725540..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 |
@@ -740,8 +740,10 @@ struct btrfs_space_info { | |||
740 | */ | 740 | */ |
741 | unsigned long reservation_progress; | 741 | unsigned long reservation_progress; |
742 | 742 | ||
743 | int full; /* indicates that we cannot allocate any more | 743 | int full:1; /* indicates that we cannot allocate any more |
744 | chunks for this space */ | 744 | chunks for this space */ |
745 | int chunk_alloc:1; /* set if we are allocating a chunk */ | ||
746 | |||
745 | int force_alloc; /* set if we need to force a chunk alloc for | 747 | int force_alloc; /* set if we need to force a chunk alloc for |
746 | this space */ | 748 | this space */ |
747 | 749 | ||
@@ -2576,6 +2578,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode, | |||
2576 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, | 2578 | int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, |
2577 | struct inode *inode, u64 start, u64 end); | 2579 | struct inode *inode, u64 start, u64 end); |
2578 | int btrfs_release_file(struct inode *inode, struct file *file); | 2580 | int btrfs_release_file(struct inode *inode, struct file *file); |
2581 | void btrfs_drop_pages(struct page **pages, size_t num_pages); | ||
2582 | int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, | ||
2583 | struct page **pages, size_t num_pages, | ||
2584 | loff_t pos, size_t write_bytes, | ||
2585 | struct extent_state **cached); | ||
2579 | 2586 | ||
2580 | /* tree-defrag.c */ | 2587 | /* tree-defrag.c */ |
2581 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | 2588 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8f1d44ba332f..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 | } |
@@ -3057,7 +3058,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3057 | btrfs_destroy_pinned_extent(root, | 3058 | btrfs_destroy_pinned_extent(root, |
3058 | root->fs_info->pinned_extents); | 3059 | root->fs_info->pinned_extents); |
3059 | 3060 | ||
3060 | t->use_count = 0; | 3061 | atomic_set(&t->use_count, 0); |
3061 | list_del_init(&t->list); | 3062 | list_del_init(&t->list); |
3062 | memset(t, 0, sizeof(*t)); | 3063 | memset(t, 0, sizeof(*t)); |
3063 | kmem_cache_free(btrfs_transaction_cachep, t); | 3064 | kmem_cache_free(btrfs_transaction_cachep, t); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index f619c3cb13b7..9ee6bd55e16c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -33,6 +33,25 @@ | |||
33 | #include "locking.h" | 33 | #include "locking.h" |
34 | #include "free-space-cache.h" | 34 | #include "free-space-cache.h" |
35 | 35 | ||
36 | /* control flags for do_chunk_alloc's force field | ||
37 | * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk | ||
38 | * if we really need one. | ||
39 | * | ||
40 | * CHUNK_ALLOC_FORCE means it must try to allocate one | ||
41 | * | ||
42 | * CHUNK_ALLOC_LIMITED means to only try and allocate one | ||
43 | * if we have very few chunks already allocated. This is | ||
44 | * used as part of the clustering code to help make sure | ||
45 | * we have a good pool of storage to cluster in, without | ||
46 | * filling the FS with empty chunks | ||
47 | * | ||
48 | */ | ||
49 | enum { | ||
50 | CHUNK_ALLOC_NO_FORCE = 0, | ||
51 | CHUNK_ALLOC_FORCE = 1, | ||
52 | CHUNK_ALLOC_LIMITED = 2, | ||
53 | }; | ||
54 | |||
36 | static int update_block_group(struct btrfs_trans_handle *trans, | 55 | static int update_block_group(struct btrfs_trans_handle *trans, |
37 | struct btrfs_root *root, | 56 | struct btrfs_root *root, |
38 | u64 bytenr, u64 num_bytes, int alloc); | 57 | u64 bytenr, u64 num_bytes, int alloc); |
@@ -3019,7 +3038,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
3019 | found->bytes_readonly = 0; | 3038 | found->bytes_readonly = 0; |
3020 | found->bytes_may_use = 0; | 3039 | found->bytes_may_use = 0; |
3021 | found->full = 0; | 3040 | found->full = 0; |
3022 | found->force_alloc = 0; | 3041 | found->force_alloc = CHUNK_ALLOC_NO_FORCE; |
3042 | found->chunk_alloc = 0; | ||
3023 | *space_info = found; | 3043 | *space_info = found; |
3024 | list_add_rcu(&found->list, &info->space_info); | 3044 | list_add_rcu(&found->list, &info->space_info); |
3025 | atomic_set(&found->caching_threads, 0); | 3045 | atomic_set(&found->caching_threads, 0); |
@@ -3150,7 +3170,7 @@ again: | |||
3150 | if (!data_sinfo->full && alloc_chunk) { | 3170 | if (!data_sinfo->full && alloc_chunk) { |
3151 | u64 alloc_target; | 3171 | u64 alloc_target; |
3152 | 3172 | ||
3153 | data_sinfo->force_alloc = 1; | 3173 | data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; |
3154 | spin_unlock(&data_sinfo->lock); | 3174 | spin_unlock(&data_sinfo->lock); |
3155 | alloc: | 3175 | alloc: |
3156 | alloc_target = btrfs_get_alloc_profile(root, 1); | 3176 | alloc_target = btrfs_get_alloc_profile(root, 1); |
@@ -3160,7 +3180,8 @@ alloc: | |||
3160 | 3180 | ||
3161 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 3181 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
3162 | bytes + 2 * 1024 * 1024, | 3182 | bytes + 2 * 1024 * 1024, |
3163 | alloc_target, 0); | 3183 | alloc_target, |
3184 | CHUNK_ALLOC_NO_FORCE); | ||
3164 | btrfs_end_transaction(trans, root); | 3185 | btrfs_end_transaction(trans, root); |
3165 | if (ret < 0) { | 3186 | if (ret < 0) { |
3166 | if (ret != -ENOSPC) | 3187 | if (ret != -ENOSPC) |
@@ -3239,31 +3260,56 @@ static void force_metadata_allocation(struct btrfs_fs_info *info) | |||
3239 | rcu_read_lock(); | 3260 | rcu_read_lock(); |
3240 | list_for_each_entry_rcu(found, head, list) { | 3261 | list_for_each_entry_rcu(found, head, list) { |
3241 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) | 3262 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) |
3242 | found->force_alloc = 1; | 3263 | found->force_alloc = CHUNK_ALLOC_FORCE; |
3243 | } | 3264 | } |
3244 | rcu_read_unlock(); | 3265 | rcu_read_unlock(); |
3245 | } | 3266 | } |
3246 | 3267 | ||
3247 | static int should_alloc_chunk(struct btrfs_root *root, | 3268 | static int should_alloc_chunk(struct btrfs_root *root, |
3248 | struct btrfs_space_info *sinfo, u64 alloc_bytes) | 3269 | struct btrfs_space_info *sinfo, u64 alloc_bytes, |
3270 | int force) | ||
3249 | { | 3271 | { |
3250 | u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; | 3272 | u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; |
3273 | u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved; | ||
3251 | u64 thresh; | 3274 | u64 thresh; |
3252 | 3275 | ||
3253 | if (sinfo->bytes_used + sinfo->bytes_reserved + | 3276 | if (force == CHUNK_ALLOC_FORCE) |
3254 | alloc_bytes + 256 * 1024 * 1024 < num_bytes) | 3277 | return 1; |
3278 | |||
3279 | /* | ||
3280 | * in limited mode, we want to have some free space up to | ||
3281 | * about 1% of the FS size. | ||
3282 | */ | ||
3283 | if (force == CHUNK_ALLOC_LIMITED) { | ||
3284 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
3285 | thresh = max_t(u64, 64 * 1024 * 1024, | ||
3286 | div_factor_fine(thresh, 1)); | ||
3287 | |||
3288 | if (num_bytes - num_allocated < thresh) | ||
3289 | return 1; | ||
3290 | } | ||
3291 | |||
3292 | /* | ||
3293 | * we have two similar checks here, one based on percentage | ||
3294 | * and once based on a hard number of 256MB. The idea | ||
3295 | * is that if we have a good amount of free | ||
3296 | * room, don't allocate a chunk. A good mount is | ||
3297 | * less than 80% utilized of the chunks we have allocated, | ||
3298 | * or more than 256MB free | ||
3299 | */ | ||
3300 | if (num_allocated + alloc_bytes + 256 * 1024 * 1024 < num_bytes) | ||
3255 | return 0; | 3301 | return 0; |
3256 | 3302 | ||
3257 | if (sinfo->bytes_used + sinfo->bytes_reserved + | 3303 | if (num_allocated + alloc_bytes < div_factor(num_bytes, 8)) |
3258 | alloc_bytes < div_factor(num_bytes, 8)) | ||
3259 | return 0; | 3304 | return 0; |
3260 | 3305 | ||
3261 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); | 3306 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); |
3307 | |||
3308 | /* 256MB or 5% of the FS */ | ||
3262 | thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5)); | 3309 | thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5)); |
3263 | 3310 | ||
3264 | if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3)) | 3311 | if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3)) |
3265 | return 0; | 3312 | return 0; |
3266 | |||
3267 | return 1; | 3313 | return 1; |
3268 | } | 3314 | } |
3269 | 3315 | ||
@@ -3273,10 +3319,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3273 | { | 3319 | { |
3274 | struct btrfs_space_info *space_info; | 3320 | struct btrfs_space_info *space_info; |
3275 | struct btrfs_fs_info *fs_info = extent_root->fs_info; | 3321 | struct btrfs_fs_info *fs_info = extent_root->fs_info; |
3322 | int wait_for_alloc = 0; | ||
3276 | int ret = 0; | 3323 | int ret = 0; |
3277 | 3324 | ||
3278 | mutex_lock(&fs_info->chunk_mutex); | ||
3279 | |||
3280 | flags = btrfs_reduce_alloc_profile(extent_root, flags); | 3325 | flags = btrfs_reduce_alloc_profile(extent_root, flags); |
3281 | 3326 | ||
3282 | space_info = __find_space_info(extent_root->fs_info, flags); | 3327 | space_info = __find_space_info(extent_root->fs_info, flags); |
@@ -3287,21 +3332,40 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3287 | } | 3332 | } |
3288 | BUG_ON(!space_info); | 3333 | BUG_ON(!space_info); |
3289 | 3334 | ||
3335 | again: | ||
3290 | spin_lock(&space_info->lock); | 3336 | spin_lock(&space_info->lock); |
3291 | if (space_info->force_alloc) | 3337 | if (space_info->force_alloc) |
3292 | force = 1; | 3338 | force = space_info->force_alloc; |
3293 | if (space_info->full) { | 3339 | if (space_info->full) { |
3294 | spin_unlock(&space_info->lock); | 3340 | spin_unlock(&space_info->lock); |
3295 | goto out; | 3341 | return 0; |
3296 | } | 3342 | } |
3297 | 3343 | ||
3298 | if (!force && !should_alloc_chunk(extent_root, space_info, | 3344 | if (!should_alloc_chunk(extent_root, space_info, alloc_bytes, force)) { |
3299 | alloc_bytes)) { | ||
3300 | spin_unlock(&space_info->lock); | 3345 | spin_unlock(&space_info->lock); |
3301 | goto out; | 3346 | return 0; |
3347 | } else if (space_info->chunk_alloc) { | ||
3348 | wait_for_alloc = 1; | ||
3349 | } else { | ||
3350 | space_info->chunk_alloc = 1; | ||
3302 | } | 3351 | } |
3352 | |||
3303 | spin_unlock(&space_info->lock); | 3353 | spin_unlock(&space_info->lock); |
3304 | 3354 | ||
3355 | mutex_lock(&fs_info->chunk_mutex); | ||
3356 | |||
3357 | /* | ||
3358 | * The chunk_mutex is held throughout the entirety of a chunk | ||
3359 | * allocation, so once we've acquired the chunk_mutex we know that the | ||
3360 | * other guy is done and we need to recheck and see if we should | ||
3361 | * allocate. | ||
3362 | */ | ||
3363 | if (wait_for_alloc) { | ||
3364 | mutex_unlock(&fs_info->chunk_mutex); | ||
3365 | wait_for_alloc = 0; | ||
3366 | goto again; | ||
3367 | } | ||
3368 | |||
3305 | /* | 3369 | /* |
3306 | * If we have mixed data/metadata chunks we want to make sure we keep | 3370 | * If we have mixed data/metadata chunks we want to make sure we keep |
3307 | * allocating mixed chunks instead of individual chunks. | 3371 | * allocating mixed chunks instead of individual chunks. |
@@ -3327,9 +3391,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3327 | space_info->full = 1; | 3391 | space_info->full = 1; |
3328 | else | 3392 | else |
3329 | ret = 1; | 3393 | ret = 1; |
3330 | space_info->force_alloc = 0; | 3394 | |
3395 | space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; | ||
3396 | space_info->chunk_alloc = 0; | ||
3331 | spin_unlock(&space_info->lock); | 3397 | spin_unlock(&space_info->lock); |
3332 | out: | ||
3333 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | 3398 | mutex_unlock(&extent_root->fs_info->chunk_mutex); |
3334 | return ret; | 3399 | return ret; |
3335 | } | 3400 | } |
@@ -5303,11 +5368,13 @@ loop: | |||
5303 | 5368 | ||
5304 | if (allowed_chunk_alloc) { | 5369 | if (allowed_chunk_alloc) { |
5305 | ret = do_chunk_alloc(trans, root, num_bytes + | 5370 | ret = do_chunk_alloc(trans, root, num_bytes + |
5306 | 2 * 1024 * 1024, data, 1); | 5371 | 2 * 1024 * 1024, data, |
5372 | CHUNK_ALLOC_LIMITED); | ||
5307 | allowed_chunk_alloc = 0; | 5373 | allowed_chunk_alloc = 0; |
5308 | done_chunk_alloc = 1; | 5374 | done_chunk_alloc = 1; |
5309 | } else if (!done_chunk_alloc) { | 5375 | } else if (!done_chunk_alloc && |
5310 | space_info->force_alloc = 1; | 5376 | space_info->force_alloc == CHUNK_ALLOC_NO_FORCE) { |
5377 | space_info->force_alloc = CHUNK_ALLOC_LIMITED; | ||
5311 | } | 5378 | } |
5312 | 5379 | ||
5313 | if (loop < LOOP_NO_EMPTY_SIZE) { | 5380 | if (loop < LOOP_NO_EMPTY_SIZE) { |
@@ -5393,7 +5460,8 @@ again: | |||
5393 | */ | 5460 | */ |
5394 | if (empty_size || root->ref_cows) | 5461 | if (empty_size || root->ref_cows) |
5395 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 5462 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
5396 | num_bytes + 2 * 1024 * 1024, data, 0); | 5463 | num_bytes + 2 * 1024 * 1024, data, |
5464 | CHUNK_ALLOC_NO_FORCE); | ||
5397 | 5465 | ||
5398 | WARN_ON(num_bytes < root->sectorsize); | 5466 | WARN_ON(num_bytes < root->sectorsize); |
5399 | ret = find_free_extent(trans, root, num_bytes, empty_size, | 5467 | ret = find_free_extent(trans, root, num_bytes, empty_size, |
@@ -5405,7 +5473,7 @@ again: | |||
5405 | num_bytes = num_bytes & ~(root->sectorsize - 1); | 5473 | num_bytes = num_bytes & ~(root->sectorsize - 1); |
5406 | num_bytes = max(num_bytes, min_alloc_size); | 5474 | num_bytes = max(num_bytes, min_alloc_size); |
5407 | do_chunk_alloc(trans, root->fs_info->extent_root, | 5475 | do_chunk_alloc(trans, root->fs_info->extent_root, |
5408 | num_bytes, data, 1); | 5476 | num_bytes, data, CHUNK_ALLOC_FORCE); |
5409 | goto again; | 5477 | goto again; |
5410 | } | 5478 | } |
5411 | if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { | 5479 | if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { |
@@ -7991,6 +8059,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, | |||
7991 | u64 group_start = group->key.objectid; | 8059 | u64 group_start = group->key.objectid; |
7992 | new_extents = kmalloc(sizeof(*new_extents), | 8060 | new_extents = kmalloc(sizeof(*new_extents), |
7993 | GFP_NOFS); | 8061 | GFP_NOFS); |
8062 | if (!new_extents) { | ||
8063 | ret = -ENOMEM; | ||
8064 | goto out; | ||
8065 | } | ||
7994 | nr_extents = 1; | 8066 | nr_extents = 1; |
7995 | ret = get_new_locations(reloc_inode, | 8067 | ret = get_new_locations(reloc_inode, |
7996 | extent_key, | 8068 | extent_key, |
@@ -8109,13 +8181,15 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, | |||
8109 | 8181 | ||
8110 | alloc_flags = update_block_group_flags(root, cache->flags); | 8182 | alloc_flags = update_block_group_flags(root, cache->flags); |
8111 | if (alloc_flags != cache->flags) | 8183 | if (alloc_flags != cache->flags) |
8112 | do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8184 | do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
8185 | CHUNK_ALLOC_FORCE); | ||
8113 | 8186 | ||
8114 | ret = set_block_group_ro(cache); | 8187 | ret = set_block_group_ro(cache); |
8115 | if (!ret) | 8188 | if (!ret) |
8116 | goto out; | 8189 | goto out; |
8117 | alloc_flags = get_alloc_profile(root, cache->space_info->flags); | 8190 | alloc_flags = get_alloc_profile(root, cache->space_info->flags); |
8118 | ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8191 | ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
8192 | CHUNK_ALLOC_FORCE); | ||
8119 | if (ret < 0) | 8193 | if (ret < 0) |
8120 | goto out; | 8194 | goto out; |
8121 | ret = set_block_group_ro(cache); | 8195 | ret = set_block_group_ro(cache); |
@@ -8128,7 +8202,8 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, | |||
8128 | struct btrfs_root *root, u64 type) | 8202 | struct btrfs_root *root, u64 type) |
8129 | { | 8203 | { |
8130 | u64 alloc_flags = get_alloc_profile(root, type); | 8204 | u64 alloc_flags = get_alloc_profile(root, type); |
8131 | return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8205 | return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
8206 | CHUNK_ALLOC_FORCE); | ||
8132 | } | 8207 | } |
8133 | 8208 | ||
8134 | /* | 8209 | /* |
@@ -8781,23 +8856,38 @@ out: | |||
8781 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info) | 8856 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info) |
8782 | { | 8857 | { |
8783 | 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; | ||
8784 | int ret; | 8863 | int ret; |
8785 | 8864 | ||
8786 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0, | 8865 | disk_super = &fs_info->super_copy; |
8787 | &space_info); | 8866 | if (!btrfs_super_root(disk_super)) |
8788 | if (ret) | 8867 | return 1; |
8789 | return ret; | ||
8790 | 8868 | ||
8791 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0, | 8869 | features = btrfs_super_incompat_flags(disk_super); |
8792 | &space_info); | 8870 | if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) |
8793 | if (ret) | 8871 | mixed = 1; |
8794 | return ret; | ||
8795 | 8872 | ||
8796 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0, | 8873 | flags = BTRFS_BLOCK_GROUP_SYSTEM; |
8797 | &space_info); | 8874 | ret = update_space_info(fs_info, flags, 0, 0, &space_info); |
8798 | if (ret) | 8875 | if (ret) |
8799 | return ret; | 8876 | goto out; |
8800 | 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: | ||
8801 | return ret; | 8891 | return ret; |
8802 | } | 8892 | } |
8803 | 8893 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 20ddb28602a8..96fcfa522dab 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/swap.h> | 10 | #include <linux/swap.h> |
11 | #include <linux/writeback.h> | 11 | #include <linux/writeback.h> |
12 | #include <linux/pagevec.h> | 12 | #include <linux/pagevec.h> |
13 | #include <linux/prefetch.h> | ||
13 | #include "extent_io.h" | 14 | #include "extent_io.h" |
14 | #include "extent_map.h" | 15 | #include "extent_map.h" |
15 | #include "compat.h" | 16 | #include "compat.h" |
@@ -690,6 +691,15 @@ static void cache_state(struct extent_state *state, | |||
690 | } | 691 | } |
691 | } | 692 | } |
692 | 693 | ||
694 | static void uncache_state(struct extent_state **cached_ptr) | ||
695 | { | ||
696 | if (cached_ptr && (*cached_ptr)) { | ||
697 | struct extent_state *state = *cached_ptr; | ||
698 | *cached_ptr = NULL; | ||
699 | free_extent_state(state); | ||
700 | } | ||
701 | } | ||
702 | |||
693 | /* | 703 | /* |
694 | * set some bits on a range in the tree. This may require allocations or | 704 | * set some bits on a range in the tree. This may require allocations or |
695 | * sleeping, so the gfp mask is used to indicate what is allowed. | 705 | * sleeping, so the gfp mask is used to indicate what is allowed. |
@@ -940,10 +950,10 @@ static int clear_extent_new(struct extent_io_tree *tree, u64 start, u64 end, | |||
940 | } | 950 | } |
941 | 951 | ||
942 | int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, | 952 | int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, |
943 | gfp_t mask) | 953 | struct extent_state **cached_state, gfp_t mask) |
944 | { | 954 | { |
945 | return set_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, NULL, | 955 | return set_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, |
946 | NULL, mask); | 956 | NULL, cached_state, mask); |
947 | } | 957 | } |
948 | 958 | ||
949 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, | 959 | static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start, |
@@ -1012,8 +1022,7 @@ int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end, | |||
1012 | mask); | 1022 | mask); |
1013 | } | 1023 | } |
1014 | 1024 | ||
1015 | int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, | 1025 | int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask) |
1016 | gfp_t mask) | ||
1017 | { | 1026 | { |
1018 | return clear_extent_bit(tree, start, end, EXTENT_LOCKED, 1, 0, NULL, | 1027 | return clear_extent_bit(tree, start, end, EXTENT_LOCKED, 1, 0, NULL, |
1019 | mask); | 1028 | mask); |
@@ -1735,6 +1744,9 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
1735 | 1744 | ||
1736 | do { | 1745 | do { |
1737 | struct page *page = bvec->bv_page; | 1746 | struct page *page = bvec->bv_page; |
1747 | struct extent_state *cached = NULL; | ||
1748 | struct extent_state *state; | ||
1749 | |||
1738 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 1750 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
1739 | 1751 | ||
1740 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + | 1752 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + |
@@ -1749,9 +1761,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
1749 | if (++bvec <= bvec_end) | 1761 | if (++bvec <= bvec_end) |
1750 | prefetchw(&bvec->bv_page->flags); | 1762 | prefetchw(&bvec->bv_page->flags); |
1751 | 1763 | ||
1764 | spin_lock(&tree->lock); | ||
1765 | state = find_first_extent_bit_state(tree, start, EXTENT_LOCKED); | ||
1766 | if (state && state->start == start) { | ||
1767 | /* | ||
1768 | * take a reference on the state, unlock will drop | ||
1769 | * the ref | ||
1770 | */ | ||
1771 | cache_state(state, &cached); | ||
1772 | } | ||
1773 | spin_unlock(&tree->lock); | ||
1774 | |||
1752 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { | 1775 | if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) { |
1753 | ret = tree->ops->readpage_end_io_hook(page, start, end, | 1776 | ret = tree->ops->readpage_end_io_hook(page, start, end, |
1754 | NULL); | 1777 | state); |
1755 | if (ret) | 1778 | if (ret) |
1756 | uptodate = 0; | 1779 | uptodate = 0; |
1757 | } | 1780 | } |
@@ -1764,15 +1787,16 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
1764 | test_bit(BIO_UPTODATE, &bio->bi_flags); | 1787 | test_bit(BIO_UPTODATE, &bio->bi_flags); |
1765 | if (err) | 1788 | if (err) |
1766 | uptodate = 0; | 1789 | uptodate = 0; |
1790 | uncache_state(&cached); | ||
1767 | continue; | 1791 | continue; |
1768 | } | 1792 | } |
1769 | } | 1793 | } |
1770 | 1794 | ||
1771 | if (uptodate) { | 1795 | if (uptodate) { |
1772 | set_extent_uptodate(tree, start, end, | 1796 | set_extent_uptodate(tree, start, end, &cached, |
1773 | GFP_ATOMIC); | 1797 | GFP_ATOMIC); |
1774 | } | 1798 | } |
1775 | unlock_extent(tree, start, end, GFP_ATOMIC); | 1799 | unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC); |
1776 | 1800 | ||
1777 | if (whole_page) { | 1801 | if (whole_page) { |
1778 | if (uptodate) { | 1802 | if (uptodate) { |
@@ -1811,6 +1835,7 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err) | |||
1811 | 1835 | ||
1812 | do { | 1836 | do { |
1813 | struct page *page = bvec->bv_page; | 1837 | struct page *page = bvec->bv_page; |
1838 | struct extent_state *cached = NULL; | ||
1814 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 1839 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
1815 | 1840 | ||
1816 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + | 1841 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + |
@@ -1821,13 +1846,14 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err) | |||
1821 | prefetchw(&bvec->bv_page->flags); | 1846 | prefetchw(&bvec->bv_page->flags); |
1822 | 1847 | ||
1823 | if (uptodate) { | 1848 | if (uptodate) { |
1824 | set_extent_uptodate(tree, start, end, GFP_ATOMIC); | 1849 | set_extent_uptodate(tree, start, end, &cached, |
1850 | GFP_ATOMIC); | ||
1825 | } else { | 1851 | } else { |
1826 | ClearPageUptodate(page); | 1852 | ClearPageUptodate(page); |
1827 | SetPageError(page); | 1853 | SetPageError(page); |
1828 | } | 1854 | } |
1829 | 1855 | ||
1830 | unlock_extent(tree, start, end, GFP_ATOMIC); | 1856 | unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC); |
1831 | 1857 | ||
1832 | } while (bvec >= bio->bi_io_vec); | 1858 | } while (bvec >= bio->bi_io_vec); |
1833 | 1859 | ||
@@ -2016,14 +2042,17 @@ static int __extent_read_full_page(struct extent_io_tree *tree, | |||
2016 | while (cur <= end) { | 2042 | while (cur <= end) { |
2017 | if (cur >= last_byte) { | 2043 | if (cur >= last_byte) { |
2018 | char *userpage; | 2044 | char *userpage; |
2045 | struct extent_state *cached = NULL; | ||
2046 | |||
2019 | iosize = PAGE_CACHE_SIZE - page_offset; | 2047 | iosize = PAGE_CACHE_SIZE - page_offset; |
2020 | userpage = kmap_atomic(page, KM_USER0); | 2048 | userpage = kmap_atomic(page, KM_USER0); |
2021 | memset(userpage + page_offset, 0, iosize); | 2049 | memset(userpage + page_offset, 0, iosize); |
2022 | flush_dcache_page(page); | 2050 | flush_dcache_page(page); |
2023 | kunmap_atomic(userpage, KM_USER0); | 2051 | kunmap_atomic(userpage, KM_USER0); |
2024 | set_extent_uptodate(tree, cur, cur + iosize - 1, | 2052 | set_extent_uptodate(tree, cur, cur + iosize - 1, |
2025 | GFP_NOFS); | 2053 | &cached, GFP_NOFS); |
2026 | unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS); | 2054 | unlock_extent_cached(tree, cur, cur + iosize - 1, |
2055 | &cached, GFP_NOFS); | ||
2027 | break; | 2056 | break; |
2028 | } | 2057 | } |
2029 | em = get_extent(inode, page, page_offset, cur, | 2058 | em = get_extent(inode, page, page_offset, cur, |
@@ -2063,14 +2092,17 @@ static int __extent_read_full_page(struct extent_io_tree *tree, | |||
2063 | /* we've found a hole, just zero and go on */ | 2092 | /* we've found a hole, just zero and go on */ |
2064 | if (block_start == EXTENT_MAP_HOLE) { | 2093 | if (block_start == EXTENT_MAP_HOLE) { |
2065 | char *userpage; | 2094 | char *userpage; |
2095 | struct extent_state *cached = NULL; | ||
2096 | |||
2066 | userpage = kmap_atomic(page, KM_USER0); | 2097 | userpage = kmap_atomic(page, KM_USER0); |
2067 | memset(userpage + page_offset, 0, iosize); | 2098 | memset(userpage + page_offset, 0, iosize); |
2068 | flush_dcache_page(page); | 2099 | flush_dcache_page(page); |
2069 | kunmap_atomic(userpage, KM_USER0); | 2100 | kunmap_atomic(userpage, KM_USER0); |
2070 | 2101 | ||
2071 | set_extent_uptodate(tree, cur, cur + iosize - 1, | 2102 | set_extent_uptodate(tree, cur, cur + iosize - 1, |
2072 | GFP_NOFS); | 2103 | &cached, GFP_NOFS); |
2073 | unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS); | 2104 | unlock_extent_cached(tree, cur, cur + iosize - 1, |
2105 | &cached, GFP_NOFS); | ||
2074 | cur = cur + iosize; | 2106 | cur = cur + iosize; |
2075 | page_offset += iosize; | 2107 | page_offset += iosize; |
2076 | continue; | 2108 | continue; |
@@ -2650,7 +2682,7 @@ int extent_readpages(struct extent_io_tree *tree, | |||
2650 | prefetchw(&page->flags); | 2682 | prefetchw(&page->flags); |
2651 | list_del(&page->lru); | 2683 | list_del(&page->lru); |
2652 | if (!add_to_page_cache_lru(page, mapping, | 2684 | if (!add_to_page_cache_lru(page, mapping, |
2653 | page->index, GFP_KERNEL)) { | 2685 | page->index, GFP_NOFS)) { |
2654 | __extent_read_full_page(tree, page, get_extent, | 2686 | __extent_read_full_page(tree, page, get_extent, |
2655 | &bio, 0, &bio_flags); | 2687 | &bio, 0, &bio_flags); |
2656 | } | 2688 | } |
@@ -2789,9 +2821,12 @@ int extent_prepare_write(struct extent_io_tree *tree, | |||
2789 | iocount++; | 2821 | iocount++; |
2790 | block_start = block_start + iosize; | 2822 | block_start = block_start + iosize; |
2791 | } else { | 2823 | } else { |
2792 | set_extent_uptodate(tree, block_start, cur_end, | 2824 | struct extent_state *cached = NULL; |
2825 | |||
2826 | set_extent_uptodate(tree, block_start, cur_end, &cached, | ||
2793 | GFP_NOFS); | 2827 | GFP_NOFS); |
2794 | unlock_extent(tree, block_start, cur_end, GFP_NOFS); | 2828 | unlock_extent_cached(tree, block_start, cur_end, |
2829 | &cached, GFP_NOFS); | ||
2795 | block_start = cur_end + 1; | 2830 | block_start = cur_end + 1; |
2796 | } | 2831 | } |
2797 | page_offset = block_start & (PAGE_CACHE_SIZE - 1); | 2832 | page_offset = block_start & (PAGE_CACHE_SIZE - 1); |
@@ -3457,7 +3492,7 @@ int set_extent_buffer_uptodate(struct extent_io_tree *tree, | |||
3457 | num_pages = num_extent_pages(eb->start, eb->len); | 3492 | num_pages = num_extent_pages(eb->start, eb->len); |
3458 | 3493 | ||
3459 | set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, | 3494 | set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, |
3460 | GFP_NOFS); | 3495 | NULL, GFP_NOFS); |
3461 | for (i = 0; i < num_pages; i++) { | 3496 | for (i = 0; i < num_pages; i++) { |
3462 | page = extent_buffer_page(eb, i); | 3497 | page = extent_buffer_page(eb, i); |
3463 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || | 3498 | if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) || |
@@ -3885,6 +3920,12 @@ static void move_pages(struct page *dst_page, struct page *src_page, | |||
3885 | kunmap_atomic(dst_kaddr, KM_USER0); | 3920 | kunmap_atomic(dst_kaddr, KM_USER0); |
3886 | } | 3921 | } |
3887 | 3922 | ||
3923 | static inline bool areas_overlap(unsigned long src, unsigned long dst, unsigned long len) | ||
3924 | { | ||
3925 | unsigned long distance = (src > dst) ? src - dst : dst - src; | ||
3926 | return distance < len; | ||
3927 | } | ||
3928 | |||
3888 | static void copy_pages(struct page *dst_page, struct page *src_page, | 3929 | static void copy_pages(struct page *dst_page, struct page *src_page, |
3889 | unsigned long dst_off, unsigned long src_off, | 3930 | unsigned long dst_off, unsigned long src_off, |
3890 | unsigned long len) | 3931 | unsigned long len) |
@@ -3892,10 +3933,12 @@ static void copy_pages(struct page *dst_page, struct page *src_page, | |||
3892 | char *dst_kaddr = kmap_atomic(dst_page, KM_USER0); | 3933 | char *dst_kaddr = kmap_atomic(dst_page, KM_USER0); |
3893 | char *src_kaddr; | 3934 | char *src_kaddr; |
3894 | 3935 | ||
3895 | if (dst_page != src_page) | 3936 | if (dst_page != src_page) { |
3896 | src_kaddr = kmap_atomic(src_page, KM_USER1); | 3937 | src_kaddr = kmap_atomic(src_page, KM_USER1); |
3897 | else | 3938 | } else { |
3898 | src_kaddr = dst_kaddr; | 3939 | src_kaddr = dst_kaddr; |
3940 | BUG_ON(areas_overlap(src_off, dst_off, len)); | ||
3941 | } | ||
3899 | 3942 | ||
3900 | memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len); | 3943 | memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len); |
3901 | kunmap_atomic(dst_kaddr, KM_USER0); | 3944 | kunmap_atomic(dst_kaddr, KM_USER0); |
@@ -3970,7 +4013,7 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | |||
3970 | "len %lu len %lu\n", dst_offset, len, dst->len); | 4013 | "len %lu len %lu\n", dst_offset, len, dst->len); |
3971 | BUG_ON(1); | 4014 | BUG_ON(1); |
3972 | } | 4015 | } |
3973 | if (dst_offset < src_offset) { | 4016 | if (!areas_overlap(src_offset, dst_offset, len)) { |
3974 | memcpy_extent_buffer(dst, dst_offset, src_offset, len); | 4017 | memcpy_extent_buffer(dst, dst_offset, src_offset, len); |
3975 | return; | 4018 | return; |
3976 | } | 4019 | } |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index f62c5442835d..af2d7179c372 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -208,7 +208,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
208 | int bits, int exclusive_bits, u64 *failed_start, | 208 | int bits, int exclusive_bits, u64 *failed_start, |
209 | struct extent_state **cached_state, gfp_t mask); | 209 | struct extent_state **cached_state, gfp_t mask); |
210 | int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, | 210 | int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end, |
211 | gfp_t mask); | 211 | struct extent_state **cached_state, gfp_t mask); |
212 | int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end, | 212 | int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end, |
213 | gfp_t mask); | 213 | gfp_t mask); |
214 | int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | 214 | int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e621ea54a3fd..75899a01dded 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
104 | /* | 104 | /* |
105 | * unlocks pages after btrfs_file_write is done with them | 105 | * unlocks pages after btrfs_file_write is done with them |
106 | */ | 106 | */ |
107 | static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) | 107 | void btrfs_drop_pages(struct page **pages, size_t num_pages) |
108 | { | 108 | { |
109 | size_t i; | 109 | size_t i; |
110 | for (i = 0; i < num_pages; i++) { | 110 | for (i = 0; i < num_pages; i++) { |
@@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) | |||
127 | * this also makes the decision about creating an inline extent vs | 127 | * this also makes the decision about creating an inline extent vs |
128 | * doing real data extents, marking pages dirty and delalloc as required. | 128 | * doing real data extents, marking pages dirty and delalloc as required. |
129 | */ | 129 | */ |
130 | static noinline int dirty_and_release_pages(struct btrfs_root *root, | 130 | int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, |
131 | struct file *file, | 131 | struct page **pages, size_t num_pages, |
132 | struct page **pages, | 132 | loff_t pos, size_t write_bytes, |
133 | size_t num_pages, | 133 | struct extent_state **cached) |
134 | loff_t pos, | ||
135 | size_t write_bytes) | ||
136 | { | 134 | { |
137 | int err = 0; | 135 | int err = 0; |
138 | int i; | 136 | int i; |
139 | struct inode *inode = fdentry(file)->d_inode; | ||
140 | u64 num_bytes; | 137 | u64 num_bytes; |
141 | u64 start_pos; | 138 | u64 start_pos; |
142 | u64 end_of_last_block; | 139 | u64 end_of_last_block; |
@@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct btrfs_root *root, | |||
149 | 146 | ||
150 | end_of_last_block = start_pos + num_bytes - 1; | 147 | end_of_last_block = start_pos + num_bytes - 1; |
151 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, | 148 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
152 | NULL); | 149 | cached); |
153 | if (err) | 150 | if (err) |
154 | return err; | 151 | return err; |
155 | 152 | ||
@@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
992 | } | 989 | } |
993 | 990 | ||
994 | if (copied > 0) { | 991 | if (copied > 0) { |
995 | ret = dirty_and_release_pages(root, file, pages, | 992 | ret = btrfs_dirty_pages(root, inode, pages, |
996 | dirty_pages, pos, | 993 | dirty_pages, pos, copied, |
997 | copied); | 994 | NULL); |
998 | if (ret) { | 995 | if (ret) { |
999 | btrfs_delalloc_release_space(inode, | 996 | btrfs_delalloc_release_space(inode, |
1000 | dirty_pages << PAGE_CACHE_SHIFT); | 997 | dirty_pages << PAGE_CACHE_SHIFT); |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f561c953205b..63731a1fb0a1 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
508 | struct inode *inode; | 508 | struct inode *inode; |
509 | struct rb_node *node; | 509 | struct rb_node *node; |
510 | struct list_head *pos, *n; | 510 | struct list_head *pos, *n; |
511 | struct page **pages; | ||
511 | struct page *page; | 512 | struct page *page; |
512 | struct extent_state *cached_state = NULL; | 513 | struct extent_state *cached_state = NULL; |
513 | struct btrfs_free_cluster *cluster = NULL; | 514 | struct btrfs_free_cluster *cluster = NULL; |
@@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
517 | u64 start, end, len; | 518 | u64 start, end, len; |
518 | u64 bytes = 0; | 519 | u64 bytes = 0; |
519 | u32 *crc, *checksums; | 520 | u32 *crc, *checksums; |
520 | pgoff_t index = 0, last_index = 0; | ||
521 | unsigned long first_page_offset; | 521 | unsigned long first_page_offset; |
522 | int num_checksums; | 522 | int index = 0, num_pages = 0; |
523 | int entries = 0; | 523 | int entries = 0; |
524 | int bitmaps = 0; | 524 | int bitmaps = 0; |
525 | int ret = 0; | 525 | int ret = 0; |
526 | bool next_page = false; | 526 | bool next_page = false; |
527 | bool out_of_space = false; | ||
527 | 528 | ||
528 | root = root->fs_info->tree_root; | 529 | root = root->fs_info->tree_root; |
529 | 530 | ||
@@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
551 | return 0; | 552 | return 0; |
552 | } | 553 | } |
553 | 554 | ||
554 | last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT; | 555 | num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> |
556 | PAGE_CACHE_SHIFT; | ||
555 | filemap_write_and_wait(inode->i_mapping); | 557 | filemap_write_and_wait(inode->i_mapping); |
556 | btrfs_wait_ordered_range(inode, inode->i_size & | 558 | btrfs_wait_ordered_range(inode, inode->i_size & |
557 | ~(root->sectorsize - 1), (u64)-1); | 559 | ~(root->sectorsize - 1), (u64)-1); |
558 | 560 | ||
559 | /* We need a checksum per page. */ | 561 | /* We need a checksum per page. */ |
560 | num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE; | 562 | crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS); |
561 | crc = checksums = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS); | ||
562 | if (!crc) { | 563 | if (!crc) { |
563 | iput(inode); | 564 | iput(inode); |
564 | return 0; | 565 | return 0; |
565 | } | 566 | } |
566 | 567 | ||
568 | pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS); | ||
569 | if (!pages) { | ||
570 | kfree(crc); | ||
571 | iput(inode); | ||
572 | return 0; | ||
573 | } | ||
574 | |||
567 | /* Since the first page has all of our checksums and our generation we | 575 | /* Since the first page has all of our checksums and our generation we |
568 | * need to calculate the offset into the page that we can start writing | 576 | * need to calculate the offset into the page that we can start writing |
569 | * our entries. | 577 | * our entries. |
570 | */ | 578 | */ |
571 | first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64); | 579 | first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64); |
572 | 580 | ||
573 | /* Get the cluster for this block_group if it exists */ | 581 | /* Get the cluster for this block_group if it exists */ |
574 | if (!list_empty(&block_group->cluster_list)) | 582 | if (!list_empty(&block_group->cluster_list)) |
@@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
590 | * after find_get_page at this point. Just putting this here so people | 598 | * after find_get_page at this point. Just putting this here so people |
591 | * know and don't freak out. | 599 | * know and don't freak out. |
592 | */ | 600 | */ |
593 | while (index <= last_index) { | 601 | while (index < num_pages) { |
594 | page = grab_cache_page(inode->i_mapping, index); | 602 | page = grab_cache_page(inode->i_mapping, index); |
595 | if (!page) { | 603 | if (!page) { |
596 | pgoff_t i = 0; | 604 | int i; |
597 | 605 | ||
598 | while (i < index) { | 606 | for (i = 0; i < num_pages; i++) { |
599 | page = find_get_page(inode->i_mapping, i); | 607 | unlock_page(pages[i]); |
600 | unlock_page(page); | 608 | page_cache_release(pages[i]); |
601 | page_cache_release(page); | ||
602 | page_cache_release(page); | ||
603 | i++; | ||
604 | } | 609 | } |
605 | goto out_free; | 610 | goto out_free; |
606 | } | 611 | } |
612 | pages[index] = page; | ||
607 | index++; | 613 | index++; |
608 | } | 614 | } |
609 | 615 | ||
@@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
631 | offset = start_offset; | 637 | offset = start_offset; |
632 | } | 638 | } |
633 | 639 | ||
634 | page = find_get_page(inode->i_mapping, index); | 640 | if (index >= num_pages) { |
641 | out_of_space = true; | ||
642 | break; | ||
643 | } | ||
644 | |||
645 | page = pages[index]; | ||
635 | 646 | ||
636 | addr = kmap(page); | 647 | addr = kmap(page); |
637 | entry = addr + start_offset; | 648 | entry = addr + start_offset; |
@@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
708 | 719 | ||
709 | bytes += PAGE_CACHE_SIZE; | 720 | bytes += PAGE_CACHE_SIZE; |
710 | 721 | ||
711 | ClearPageChecked(page); | ||
712 | set_page_extent_mapped(page); | ||
713 | SetPageUptodate(page); | ||
714 | set_page_dirty(page); | ||
715 | |||
716 | /* | ||
717 | * We need to release our reference we got for grab_cache_page, | ||
718 | * except for the first page which will hold our checksums, we | ||
719 | * do that below. | ||
720 | */ | ||
721 | if (index != 0) { | ||
722 | unlock_page(page); | ||
723 | page_cache_release(page); | ||
724 | } | ||
725 | |||
726 | page_cache_release(page); | ||
727 | |||
728 | index++; | 722 | index++; |
729 | } while (node || next_page); | 723 | } while (node || next_page); |
730 | 724 | ||
@@ -734,7 +728,11 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
734 | struct btrfs_free_space *entry = | 728 | struct btrfs_free_space *entry = |
735 | list_entry(pos, struct btrfs_free_space, list); | 729 | list_entry(pos, struct btrfs_free_space, list); |
736 | 730 | ||
737 | page = find_get_page(inode->i_mapping, index); | 731 | if (index >= num_pages) { |
732 | out_of_space = true; | ||
733 | break; | ||
734 | } | ||
735 | page = pages[index]; | ||
738 | 736 | ||
739 | addr = kmap(page); | 737 | addr = kmap(page); |
740 | memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE); | 738 | memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE); |
@@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
745 | crc++; | 743 | crc++; |
746 | bytes += PAGE_CACHE_SIZE; | 744 | bytes += PAGE_CACHE_SIZE; |
747 | 745 | ||
748 | ClearPageChecked(page); | ||
749 | set_page_extent_mapped(page); | ||
750 | SetPageUptodate(page); | ||
751 | set_page_dirty(page); | ||
752 | unlock_page(page); | ||
753 | page_cache_release(page); | ||
754 | page_cache_release(page); | ||
755 | list_del_init(&entry->list); | 746 | list_del_init(&entry->list); |
756 | index++; | 747 | index++; |
757 | } | 748 | } |
758 | 749 | ||
750 | if (out_of_space) { | ||
751 | btrfs_drop_pages(pages, num_pages); | ||
752 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | ||
753 | i_size_read(inode) - 1, &cached_state, | ||
754 | GFP_NOFS); | ||
755 | ret = 0; | ||
756 | goto out_free; | ||
757 | } | ||
758 | |||
759 | /* Zero out the rest of the pages just to make sure */ | 759 | /* Zero out the rest of the pages just to make sure */ |
760 | while (index <= last_index) { | 760 | while (index < num_pages) { |
761 | void *addr; | 761 | void *addr; |
762 | 762 | ||
763 | page = find_get_page(inode->i_mapping, index); | 763 | page = pages[index]; |
764 | |||
765 | addr = kmap(page); | 764 | addr = kmap(page); |
766 | memset(addr, 0, PAGE_CACHE_SIZE); | 765 | memset(addr, 0, PAGE_CACHE_SIZE); |
767 | kunmap(page); | 766 | kunmap(page); |
768 | ClearPageChecked(page); | ||
769 | set_page_extent_mapped(page); | ||
770 | SetPageUptodate(page); | ||
771 | set_page_dirty(page); | ||
772 | unlock_page(page); | ||
773 | page_cache_release(page); | ||
774 | page_cache_release(page); | ||
775 | bytes += PAGE_CACHE_SIZE; | 767 | bytes += PAGE_CACHE_SIZE; |
776 | index++; | 768 | index++; |
777 | } | 769 | } |
778 | 770 | ||
779 | btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state); | ||
780 | |||
781 | /* Write the checksums and trans id to the first page */ | 771 | /* Write the checksums and trans id to the first page */ |
782 | { | 772 | { |
783 | void *addr; | 773 | void *addr; |
784 | u64 *gen; | 774 | u64 *gen; |
785 | 775 | ||
786 | page = find_get_page(inode->i_mapping, 0); | 776 | page = pages[0]; |
787 | 777 | ||
788 | addr = kmap(page); | 778 | addr = kmap(page); |
789 | memcpy(addr, checksums, sizeof(u32) * num_checksums); | 779 | memcpy(addr, checksums, sizeof(u32) * num_pages); |
790 | gen = addr + (sizeof(u32) * num_checksums); | 780 | gen = addr + (sizeof(u32) * num_pages); |
791 | *gen = trans->transid; | 781 | *gen = trans->transid; |
792 | kunmap(page); | 782 | kunmap(page); |
793 | ClearPageChecked(page); | ||
794 | set_page_extent_mapped(page); | ||
795 | SetPageUptodate(page); | ||
796 | set_page_dirty(page); | ||
797 | unlock_page(page); | ||
798 | page_cache_release(page); | ||
799 | page_cache_release(page); | ||
800 | } | 783 | } |
801 | BTRFS_I(inode)->generation = trans->transid; | ||
802 | 784 | ||
785 | ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0, | ||
786 | bytes, &cached_state); | ||
787 | btrfs_drop_pages(pages, num_pages); | ||
803 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, | 788 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
804 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); | 789 | i_size_read(inode) - 1, &cached_state, GFP_NOFS); |
805 | 790 | ||
791 | if (ret) { | ||
792 | ret = 0; | ||
793 | goto out_free; | ||
794 | } | ||
795 | |||
796 | BTRFS_I(inode)->generation = trans->transid; | ||
797 | |||
806 | filemap_write_and_wait(inode->i_mapping); | 798 | filemap_write_and_wait(inode->i_mapping); |
807 | 799 | ||
808 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; | 800 | key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
@@ -853,6 +845,7 @@ out_free: | |||
853 | BTRFS_I(inode)->generation = 0; | 845 | BTRFS_I(inode)->generation = 0; |
854 | } | 846 | } |
855 | kfree(checksums); | 847 | kfree(checksums); |
848 | kfree(pages); | ||
856 | btrfs_update_inode(trans, root, inode); | 849 | btrfs_update_inode(trans, root, inode); |
857 | iput(inode); | 850 | iput(inode); |
858 | return ret; | 851 | return ret; |
@@ -1775,10 +1768,13 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) | |||
1775 | 1768 | ||
1776 | while ((node = rb_last(&block_group->free_space_offset)) != NULL) { | 1769 | while ((node = rb_last(&block_group->free_space_offset)) != NULL) { |
1777 | info = rb_entry(node, struct btrfs_free_space, offset_index); | 1770 | info = rb_entry(node, struct btrfs_free_space, offset_index); |
1778 | unlink_free_space(block_group, info); | 1771 | if (!info->bitmap) { |
1779 | if (info->bitmap) | 1772 | unlink_free_space(block_group, info); |
1780 | kfree(info->bitmap); | 1773 | kmem_cache_free(btrfs_free_space_cachep, info); |
1781 | kmem_cache_free(btrfs_free_space_cachep, info); | 1774 | } else { |
1775 | free_bitmap(block_group, info); | ||
1776 | } | ||
1777 | |||
1782 | if (need_resched()) { | 1778 | if (need_resched()) { |
1783 | spin_unlock(&block_group->tree_lock); | 1779 | spin_unlock(&block_group->tree_lock); |
1784 | cond_resched(); | 1780 | cond_resched(); |
@@ -2308,7 +2304,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, | |||
2308 | start = entry->offset; | 2304 | start = entry->offset; |
2309 | bytes = min(entry->bytes, end - start); | 2305 | bytes = min(entry->bytes, end - start); |
2310 | unlink_free_space(block_group, entry); | 2306 | unlink_free_space(block_group, entry); |
2311 | kfree(entry); | 2307 | kmem_cache_free(btrfs_free_space_cachep, entry); |
2312 | } | 2308 | } |
2313 | 2309 | ||
2314 | 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 5cc64ab9c485..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; |
@@ -1770,9 +1771,12 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1770 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 1771 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
1771 | &ordered_extent->list); | 1772 | &ordered_extent->list); |
1772 | 1773 | ||
1773 | btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1774 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
1774 | ret = btrfs_update_inode(trans, root, inode); | 1775 | if (!ret) { |
1775 | BUG_ON(ret); | 1776 | ret = btrfs_update_inode(trans, root, inode); |
1777 | BUG_ON(ret); | ||
1778 | } | ||
1779 | ret = 0; | ||
1776 | out: | 1780 | out: |
1777 | if (nolock) { | 1781 | if (nolock) { |
1778 | if (trans) | 1782 | if (trans) |
@@ -2590,6 +2594,13 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2590 | struct btrfs_inode_item *item, | 2594 | struct btrfs_inode_item *item, |
2591 | struct inode *inode) | 2595 | struct inode *inode) |
2592 | { | 2596 | { |
2597 | if (!leaf->map_token) | ||
2598 | map_private_extent_buffer(leaf, (unsigned long)item, | ||
2599 | sizeof(struct btrfs_inode_item), | ||
2600 | &leaf->map_token, &leaf->kaddr, | ||
2601 | &leaf->map_start, &leaf->map_len, | ||
2602 | KM_USER1); | ||
2603 | |||
2593 | btrfs_set_inode_uid(leaf, item, inode->i_uid); | 2604 | btrfs_set_inode_uid(leaf, item, inode->i_uid); |
2594 | btrfs_set_inode_gid(leaf, item, inode->i_gid); | 2605 | btrfs_set_inode_gid(leaf, item, inode->i_gid); |
2595 | btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size); | 2606 | btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size); |
@@ -2618,6 +2629,11 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2618 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); | 2629 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); |
2619 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); | 2630 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); |
2620 | btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); | 2631 | btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); |
2632 | |||
2633 | if (leaf->map_token) { | ||
2634 | unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); | ||
2635 | leaf->map_token = NULL; | ||
2636 | } | ||
2621 | } | 2637 | } |
2622 | 2638 | ||
2623 | /* | 2639 | /* |
@@ -4207,10 +4223,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4207 | struct btrfs_key found_key; | 4223 | struct btrfs_key found_key; |
4208 | struct btrfs_path *path; | 4224 | struct btrfs_path *path; |
4209 | int ret; | 4225 | int ret; |
4210 | u32 nritems; | ||
4211 | struct extent_buffer *leaf; | 4226 | struct extent_buffer *leaf; |
4212 | int slot; | 4227 | int slot; |
4213 | int advance; | ||
4214 | unsigned char d_type; | 4228 | unsigned char d_type; |
4215 | int over = 0; | 4229 | int over = 0; |
4216 | u32 di_cur; | 4230 | u32 di_cur; |
@@ -4253,27 +4267,19 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4253 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 4267 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
4254 | if (ret < 0) | 4268 | if (ret < 0) |
4255 | goto err; | 4269 | goto err; |
4256 | advance = 0; | ||
4257 | 4270 | ||
4258 | while (1) { | 4271 | while (1) { |
4259 | leaf = path->nodes[0]; | 4272 | leaf = path->nodes[0]; |
4260 | nritems = btrfs_header_nritems(leaf); | ||
4261 | slot = path->slots[0]; | 4273 | slot = path->slots[0]; |
4262 | if (advance || slot >= nritems) { | 4274 | if (slot >= btrfs_header_nritems(leaf)) { |
4263 | if (slot >= nritems - 1) { | 4275 | ret = btrfs_next_leaf(root, path); |
4264 | ret = btrfs_next_leaf(root, path); | 4276 | if (ret < 0) |
4265 | if (ret) | 4277 | goto err; |
4266 | break; | 4278 | else if (ret > 0) |
4267 | leaf = path->nodes[0]; | 4279 | break; |
4268 | nritems = btrfs_header_nritems(leaf); | 4280 | continue; |
4269 | slot = path->slots[0]; | ||
4270 | } else { | ||
4271 | slot++; | ||
4272 | path->slots[0]++; | ||
4273 | } | ||
4274 | } | 4281 | } |
4275 | 4282 | ||
4276 | advance = 1; | ||
4277 | item = btrfs_item_nr(leaf, slot); | 4283 | item = btrfs_item_nr(leaf, slot); |
4278 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 4284 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
4279 | 4285 | ||
@@ -4282,7 +4288,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4282 | if (btrfs_key_type(&found_key) != key_type) | 4288 | if (btrfs_key_type(&found_key) != key_type) |
4283 | break; | 4289 | break; |
4284 | if (found_key.offset < filp->f_pos) | 4290 | if (found_key.offset < filp->f_pos) |
4285 | continue; | 4291 | goto next; |
4286 | 4292 | ||
4287 | filp->f_pos = found_key.offset; | 4293 | filp->f_pos = found_key.offset; |
4288 | 4294 | ||
@@ -4335,6 +4341,8 @@ skip: | |||
4335 | di_cur += di_len; | 4341 | di_cur += di_len; |
4336 | di = (struct btrfs_dir_item *)((char *)di + di_len); | 4342 | di = (struct btrfs_dir_item *)((char *)di + di_len); |
4337 | } | 4343 | } |
4344 | next: | ||
4345 | path->slots[0]++; | ||
4338 | } | 4346 | } |
4339 | 4347 | ||
4340 | /* Reached end of directory/root. Bump pos past the last item. */ | 4348 | /* Reached end of directory/root. Bump pos past the last item. */ |
@@ -4527,14 +4535,17 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4527 | BUG_ON(!path); | 4535 | BUG_ON(!path); |
4528 | 4536 | ||
4529 | inode = new_inode(root->fs_info->sb); | 4537 | inode = new_inode(root->fs_info->sb); |
4530 | if (!inode) | 4538 | if (!inode) { |
4539 | btrfs_free_path(path); | ||
4531 | return ERR_PTR(-ENOMEM); | 4540 | return ERR_PTR(-ENOMEM); |
4541 | } | ||
4532 | 4542 | ||
4533 | if (dir) { | 4543 | if (dir) { |
4534 | trace_btrfs_inode_request(dir); | 4544 | trace_btrfs_inode_request(dir); |
4535 | 4545 | ||
4536 | ret = btrfs_set_inode_index(dir, index); | 4546 | ret = btrfs_set_inode_index(dir, index); |
4537 | if (ret) { | 4547 | if (ret) { |
4548 | btrfs_free_path(path); | ||
4538 | iput(inode); | 4549 | iput(inode); |
4539 | return ERR_PTR(ret); | 4550 | return ERR_PTR(ret); |
4540 | } | 4551 | } |
@@ -4721,9 +4732,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
4721 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4732 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
4722 | dentry->d_name.len, dir->i_ino, objectid, | 4733 | dentry->d_name.len, dir->i_ino, objectid, |
4723 | BTRFS_I(dir)->block_group, mode, &index); | 4734 | BTRFS_I(dir)->block_group, mode, &index); |
4724 | err = PTR_ERR(inode); | 4735 | if (IS_ERR(inode)) { |
4725 | if (IS_ERR(inode)) | 4736 | err = PTR_ERR(inode); |
4726 | goto out_unlock; | 4737 | goto out_unlock; |
4738 | } | ||
4727 | 4739 | ||
4728 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 4740 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4729 | if (err) { | 4741 | if (err) { |
@@ -4782,9 +4794,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
4782 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4794 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
4783 | dentry->d_name.len, dir->i_ino, objectid, | 4795 | dentry->d_name.len, dir->i_ino, objectid, |
4784 | BTRFS_I(dir)->block_group, mode, &index); | 4796 | BTRFS_I(dir)->block_group, mode, &index); |
4785 | err = PTR_ERR(inode); | 4797 | if (IS_ERR(inode)) { |
4786 | if (IS_ERR(inode)) | 4798 | err = PTR_ERR(inode); |
4787 | goto out_unlock; | 4799 | goto out_unlock; |
4800 | } | ||
4788 | 4801 | ||
4789 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 4802 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
4790 | if (err) { | 4803 | if (err) { |
@@ -4834,9 +4847,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4834 | if (inode->i_nlink == ~0U) | 4847 | if (inode->i_nlink == ~0U) |
4835 | return -EMLINK; | 4848 | return -EMLINK; |
4836 | 4849 | ||
4837 | btrfs_inc_nlink(inode); | ||
4838 | inode->i_ctime = CURRENT_TIME; | ||
4839 | |||
4840 | err = btrfs_set_inode_index(dir, &index); | 4850 | err = btrfs_set_inode_index(dir, &index); |
4841 | if (err) | 4851 | if (err) |
4842 | goto fail; | 4852 | goto fail; |
@@ -4852,6 +4862,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4852 | goto fail; | 4862 | goto fail; |
4853 | } | 4863 | } |
4854 | 4864 | ||
4865 | btrfs_inc_nlink(inode); | ||
4866 | inode->i_ctime = CURRENT_TIME; | ||
4867 | |||
4855 | btrfs_set_trans_block_group(trans, dir); | 4868 | btrfs_set_trans_block_group(trans, dir); |
4856 | ihold(inode); | 4869 | ihold(inode); |
4857 | 4870 | ||
@@ -4989,6 +5002,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, | |||
4989 | inline_size = btrfs_file_extent_inline_item_len(leaf, | 5002 | inline_size = btrfs_file_extent_inline_item_len(leaf, |
4990 | btrfs_item_nr(leaf, path->slots[0])); | 5003 | btrfs_item_nr(leaf, path->slots[0])); |
4991 | tmp = kmalloc(inline_size, GFP_NOFS); | 5004 | tmp = kmalloc(inline_size, GFP_NOFS); |
5005 | if (!tmp) | ||
5006 | return -ENOMEM; | ||
4992 | ptr = btrfs_file_extent_inline_start(item); | 5007 | ptr = btrfs_file_extent_inline_start(item); |
4993 | 5008 | ||
4994 | read_extent_buffer(leaf, tmp, ptr, inline_size); | 5009 | read_extent_buffer(leaf, tmp, ptr, inline_size); |
@@ -5221,7 +5236,7 @@ again: | |||
5221 | btrfs_mark_buffer_dirty(leaf); | 5236 | btrfs_mark_buffer_dirty(leaf); |
5222 | } | 5237 | } |
5223 | set_extent_uptodate(io_tree, em->start, | 5238 | set_extent_uptodate(io_tree, em->start, |
5224 | extent_map_end(em) - 1, GFP_NOFS); | 5239 | extent_map_end(em) - 1, NULL, GFP_NOFS); |
5225 | goto insert; | 5240 | goto insert; |
5226 | } else { | 5241 | } else { |
5227 | printk(KERN_ERR "btrfs unknown found_type %d\n", found_type); | 5242 | printk(KERN_ERR "btrfs unknown found_type %d\n", found_type); |
@@ -5428,17 +5443,30 @@ out: | |||
5428 | } | 5443 | } |
5429 | 5444 | ||
5430 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | 5445 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, |
5446 | struct extent_map *em, | ||
5431 | u64 start, u64 len) | 5447 | u64 start, u64 len) |
5432 | { | 5448 | { |
5433 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5449 | struct btrfs_root *root = BTRFS_I(inode)->root; |
5434 | struct btrfs_trans_handle *trans; | 5450 | struct btrfs_trans_handle *trans; |
5435 | struct extent_map *em; | ||
5436 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 5451 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
5437 | struct btrfs_key ins; | 5452 | struct btrfs_key ins; |
5438 | u64 alloc_hint; | 5453 | u64 alloc_hint; |
5439 | int ret; | 5454 | int ret; |
5455 | bool insert = false; | ||
5440 | 5456 | ||
5441 | btrfs_drop_extent_cache(inode, start, start + len - 1, 0); | 5457 | /* |
5458 | * Ok if the extent map we looked up is a hole and is for the exact | ||
5459 | * range we want, there is no reason to allocate a new one, however if | ||
5460 | * it is not right then we need to free this one and drop the cache for | ||
5461 | * our range. | ||
5462 | */ | ||
5463 | if (em->block_start != EXTENT_MAP_HOLE || em->start != start || | ||
5464 | em->len != len) { | ||
5465 | free_extent_map(em); | ||
5466 | em = NULL; | ||
5467 | insert = true; | ||
5468 | btrfs_drop_extent_cache(inode, start, start + len - 1, 0); | ||
5469 | } | ||
5442 | 5470 | ||
5443 | trans = btrfs_join_transaction(root, 0); | 5471 | trans = btrfs_join_transaction(root, 0); |
5444 | if (IS_ERR(trans)) | 5472 | if (IS_ERR(trans)) |
@@ -5454,10 +5482,12 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
5454 | goto out; | 5482 | goto out; |
5455 | } | 5483 | } |
5456 | 5484 | ||
5457 | em = alloc_extent_map(GFP_NOFS); | ||
5458 | if (!em) { | 5485 | if (!em) { |
5459 | em = ERR_PTR(-ENOMEM); | 5486 | em = alloc_extent_map(GFP_NOFS); |
5460 | goto out; | 5487 | if (!em) { |
5488 | em = ERR_PTR(-ENOMEM); | ||
5489 | goto out; | ||
5490 | } | ||
5461 | } | 5491 | } |
5462 | 5492 | ||
5463 | em->start = start; | 5493 | em->start = start; |
@@ -5467,9 +5497,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
5467 | em->block_start = ins.objectid; | 5497 | em->block_start = ins.objectid; |
5468 | em->block_len = ins.offset; | 5498 | em->block_len = ins.offset; |
5469 | em->bdev = root->fs_info->fs_devices->latest_bdev; | 5499 | em->bdev = root->fs_info->fs_devices->latest_bdev; |
5500 | |||
5501 | /* | ||
5502 | * We need to do this because if we're using the original em we searched | ||
5503 | * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that. | ||
5504 | */ | ||
5505 | em->flags = 0; | ||
5470 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | 5506 | set_bit(EXTENT_FLAG_PINNED, &em->flags); |
5471 | 5507 | ||
5472 | while (1) { | 5508 | while (insert) { |
5473 | write_lock(&em_tree->lock); | 5509 | write_lock(&em_tree->lock); |
5474 | ret = add_extent_mapping(em_tree, em); | 5510 | ret = add_extent_mapping(em_tree, em); |
5475 | write_unlock(&em_tree->lock); | 5511 | write_unlock(&em_tree->lock); |
@@ -5687,8 +5723,7 @@ must_cow: | |||
5687 | * it above | 5723 | * it above |
5688 | */ | 5724 | */ |
5689 | len = bh_result->b_size; | 5725 | len = bh_result->b_size; |
5690 | free_extent_map(em); | 5726 | em = btrfs_new_extent_direct(inode, em, start, len); |
5691 | em = btrfs_new_extent_direct(inode, start, len); | ||
5692 | if (IS_ERR(em)) | 5727 | if (IS_ERR(em)) |
5693 | return PTR_ERR(em); | 5728 | return PTR_ERR(em); |
5694 | len = min(len, em->len - (start - em->start)); | 5729 | len = min(len, em->len - (start - em->start)); |
@@ -5851,8 +5886,10 @@ again: | |||
5851 | } | 5886 | } |
5852 | 5887 | ||
5853 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5888 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
5854 | btrfs_ordered_update_i_size(inode, 0, ordered); | 5889 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5855 | btrfs_update_inode(trans, root, inode); | 5890 | if (!ret) |
5891 | btrfs_update_inode(trans, root, inode); | ||
5892 | ret = 0; | ||
5856 | out_unlock: | 5893 | out_unlock: |
5857 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, | 5894 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, |
5858 | ordered->file_offset + ordered->len - 1, | 5895 | ordered->file_offset + ordered->len - 1, |
@@ -5938,7 +5975,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev, | |||
5938 | 5975 | ||
5939 | static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | 5976 | static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, |
5940 | int rw, u64 file_offset, int skip_sum, | 5977 | int rw, u64 file_offset, int skip_sum, |
5941 | u32 *csums) | 5978 | u32 *csums, int async_submit) |
5942 | { | 5979 | { |
5943 | int write = rw & REQ_WRITE; | 5980 | int write = rw & REQ_WRITE; |
5944 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5981 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -5949,13 +5986,24 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | |||
5949 | if (ret) | 5986 | if (ret) |
5950 | goto err; | 5987 | goto err; |
5951 | 5988 | ||
5952 | if (write && !skip_sum) { | 5989 | if (skip_sum) |
5990 | goto map; | ||
5991 | |||
5992 | if (write && async_submit) { | ||
5953 | ret = btrfs_wq_submit_bio(root->fs_info, | 5993 | ret = btrfs_wq_submit_bio(root->fs_info, |
5954 | inode, rw, bio, 0, 0, | 5994 | inode, rw, bio, 0, 0, |
5955 | file_offset, | 5995 | file_offset, |
5956 | __btrfs_submit_bio_start_direct_io, | 5996 | __btrfs_submit_bio_start_direct_io, |
5957 | __btrfs_submit_bio_done); | 5997 | __btrfs_submit_bio_done); |
5958 | goto err; | 5998 | goto err; |
5999 | } else if (write) { | ||
6000 | /* | ||
6001 | * If we aren't doing async submit, calculate the csum of the | ||
6002 | * bio now. | ||
6003 | */ | ||
6004 | ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1); | ||
6005 | if (ret) | ||
6006 | goto err; | ||
5959 | } else if (!skip_sum) { | 6007 | } else if (!skip_sum) { |
5960 | ret = btrfs_lookup_bio_sums_dio(root, inode, bio, | 6008 | ret = btrfs_lookup_bio_sums_dio(root, inode, bio, |
5961 | file_offset, csums); | 6009 | file_offset, csums); |
@@ -5963,7 +6011,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | |||
5963 | goto err; | 6011 | goto err; |
5964 | } | 6012 | } |
5965 | 6013 | ||
5966 | ret = btrfs_map_bio(root, rw, bio, 0, 1); | 6014 | map: |
6015 | ret = btrfs_map_bio(root, rw, bio, 0, async_submit); | ||
5967 | err: | 6016 | err: |
5968 | bio_put(bio); | 6017 | bio_put(bio); |
5969 | return ret; | 6018 | return ret; |
@@ -5985,23 +6034,30 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
5985 | int nr_pages = 0; | 6034 | int nr_pages = 0; |
5986 | u32 *csums = dip->csums; | 6035 | u32 *csums = dip->csums; |
5987 | int ret = 0; | 6036 | int ret = 0; |
6037 | int async_submit = 0; | ||
5988 | int write = rw & REQ_WRITE; | 6038 | int write = rw & REQ_WRITE; |
5989 | 6039 | ||
5990 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); | ||
5991 | if (!bio) | ||
5992 | return -ENOMEM; | ||
5993 | bio->bi_private = dip; | ||
5994 | bio->bi_end_io = btrfs_end_dio_bio; | ||
5995 | atomic_inc(&dip->pending_bios); | ||
5996 | |||
5997 | map_length = orig_bio->bi_size; | 6040 | map_length = orig_bio->bi_size; |
5998 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, | 6041 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, |
5999 | &map_length, NULL, 0); | 6042 | &map_length, NULL, 0); |
6000 | if (ret) { | 6043 | if (ret) { |
6001 | bio_put(bio); | 6044 | bio_put(orig_bio); |
6002 | return -EIO; | 6045 | return -EIO; |
6003 | } | 6046 | } |
6004 | 6047 | ||
6048 | if (map_length >= orig_bio->bi_size) { | ||
6049 | bio = orig_bio; | ||
6050 | goto submit; | ||
6051 | } | ||
6052 | |||
6053 | async_submit = 1; | ||
6054 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); | ||
6055 | if (!bio) | ||
6056 | return -ENOMEM; | ||
6057 | bio->bi_private = dip; | ||
6058 | bio->bi_end_io = btrfs_end_dio_bio; | ||
6059 | atomic_inc(&dip->pending_bios); | ||
6060 | |||
6005 | while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { | 6061 | while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { |
6006 | if (unlikely(map_length < submit_len + bvec->bv_len || | 6062 | if (unlikely(map_length < submit_len + bvec->bv_len || |
6007 | bio_add_page(bio, bvec->bv_page, bvec->bv_len, | 6063 | bio_add_page(bio, bvec->bv_page, bvec->bv_len, |
@@ -6015,7 +6071,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6015 | atomic_inc(&dip->pending_bios); | 6071 | atomic_inc(&dip->pending_bios); |
6016 | ret = __btrfs_submit_dio_bio(bio, inode, rw, | 6072 | ret = __btrfs_submit_dio_bio(bio, inode, rw, |
6017 | file_offset, skip_sum, | 6073 | file_offset, skip_sum, |
6018 | csums); | 6074 | csums, async_submit); |
6019 | if (ret) { | 6075 | if (ret) { |
6020 | bio_put(bio); | 6076 | bio_put(bio); |
6021 | atomic_dec(&dip->pending_bios); | 6077 | atomic_dec(&dip->pending_bios); |
@@ -6052,8 +6108,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6052 | } | 6108 | } |
6053 | } | 6109 | } |
6054 | 6110 | ||
6111 | submit: | ||
6055 | ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, | 6112 | ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, |
6056 | csums); | 6113 | csums, async_submit); |
6057 | if (!ret) | 6114 | if (!ret) |
6058 | return 0; | 6115 | return 0; |
6059 | 6116 | ||
@@ -6148,6 +6205,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io | |||
6148 | unsigned long nr_segs) | 6205 | unsigned long nr_segs) |
6149 | { | 6206 | { |
6150 | int seg; | 6207 | int seg; |
6208 | int i; | ||
6151 | size_t size; | 6209 | size_t size; |
6152 | unsigned long addr; | 6210 | unsigned long addr; |
6153 | unsigned blocksize_mask = root->sectorsize - 1; | 6211 | unsigned blocksize_mask = root->sectorsize - 1; |
@@ -6162,8 +6220,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io | |||
6162 | addr = (unsigned long)iov[seg].iov_base; | 6220 | addr = (unsigned long)iov[seg].iov_base; |
6163 | size = iov[seg].iov_len; | 6221 | size = iov[seg].iov_len; |
6164 | end += size; | 6222 | end += size; |
6165 | if ((addr & blocksize_mask) || (size & blocksize_mask)) | 6223 | if ((addr & blocksize_mask) || (size & blocksize_mask)) |
6166 | goto out; | 6224 | goto out; |
6225 | |||
6226 | /* If this is a write we don't need to check anymore */ | ||
6227 | if (rw & WRITE) | ||
6228 | continue; | ||
6229 | |||
6230 | /* | ||
6231 | * Check to make sure we don't have duplicate iov_base's in this | ||
6232 | * iovec, if so return EINVAL, otherwise we'll get csum errors | ||
6233 | * when reading back. | ||
6234 | */ | ||
6235 | for (i = seg + 1; i < nr_segs; i++) { | ||
6236 | if (iov[seg].iov_base == iov[i].iov_base) | ||
6237 | goto out; | ||
6238 | } | ||
6167 | } | 6239 | } |
6168 | retval = 0; | 6240 | retval = 0; |
6169 | out: | 6241 | out: |
@@ -7206,9 +7278,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
7206 | dentry->d_name.len, dir->i_ino, objectid, | 7278 | dentry->d_name.len, dir->i_ino, objectid, |
7207 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, | 7279 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, |
7208 | &index); | 7280 | &index); |
7209 | err = PTR_ERR(inode); | 7281 | if (IS_ERR(inode)) { |
7210 | if (IS_ERR(inode)) | 7282 | err = PTR_ERR(inode); |
7211 | goto out_unlock; | 7283 | goto out_unlock; |
7284 | } | ||
7212 | 7285 | ||
7213 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); | 7286 | err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); |
7214 | if (err) { | 7287 | if (err) { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index cfc264fefdb0..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)); |
@@ -2287,7 +2293,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2287 | struct btrfs_ioctl_space_info space; | 2293 | struct btrfs_ioctl_space_info space; |
2288 | struct btrfs_ioctl_space_info *dest; | 2294 | struct btrfs_ioctl_space_info *dest; |
2289 | struct btrfs_ioctl_space_info *dest_orig; | 2295 | struct btrfs_ioctl_space_info *dest_orig; |
2290 | struct btrfs_ioctl_space_info *user_dest; | 2296 | struct btrfs_ioctl_space_info __user *user_dest; |
2291 | struct btrfs_space_info *info; | 2297 | struct btrfs_space_info *info; |
2292 | u64 types[] = {BTRFS_BLOCK_GROUP_DATA, | 2298 | u64 types[] = {BTRFS_BLOCK_GROUP_DATA, |
2293 | BTRFS_BLOCK_GROUP_SYSTEM, | 2299 | BTRFS_BLOCK_GROUP_SYSTEM, |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 58e7de9cc90c..0ac712efcdf2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -159,7 +159,7 @@ enum { | |||
159 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, | 159 | Opt_compress_type, Opt_compress_force, Opt_compress_force_type, |
160 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, | 160 | Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, |
161 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, | 161 | Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, |
162 | Opt_enospc_debug, Opt_err, | 162 | Opt_enospc_debug, Opt_subvolrootid, Opt_err, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static match_table_t tokens = { | 165 | static match_table_t tokens = { |
@@ -189,6 +189,7 @@ static match_table_t tokens = { | |||
189 | {Opt_clear_cache, "clear_cache"}, | 189 | {Opt_clear_cache, "clear_cache"}, |
190 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, | 190 | {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, |
191 | {Opt_enospc_debug, "enospc_debug"}, | 191 | {Opt_enospc_debug, "enospc_debug"}, |
192 | {Opt_subvolrootid, "subvolrootid=%d"}, | ||
192 | {Opt_err, NULL}, | 193 | {Opt_err, NULL}, |
193 | }; | 194 | }; |
194 | 195 | ||
@@ -232,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
232 | break; | 233 | break; |
233 | case Opt_subvol: | 234 | case Opt_subvol: |
234 | case Opt_subvolid: | 235 | case Opt_subvolid: |
236 | case Opt_subvolrootid: | ||
235 | case Opt_device: | 237 | case Opt_device: |
236 | /* | 238 | /* |
237 | * These are parsed by btrfs_parse_early_options | 239 | * These are parsed by btrfs_parse_early_options |
@@ -388,7 +390,7 @@ out: | |||
388 | */ | 390 | */ |
389 | static int btrfs_parse_early_options(const char *options, fmode_t flags, | 391 | static int btrfs_parse_early_options(const char *options, fmode_t flags, |
390 | void *holder, char **subvol_name, u64 *subvol_objectid, | 392 | void *holder, char **subvol_name, u64 *subvol_objectid, |
391 | struct btrfs_fs_devices **fs_devices) | 393 | u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices) |
392 | { | 394 | { |
393 | substring_t args[MAX_OPT_ARGS]; | 395 | substring_t args[MAX_OPT_ARGS]; |
394 | char *opts, *orig, *p; | 396 | char *opts, *orig, *p; |
@@ -429,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
429 | *subvol_objectid = intarg; | 431 | *subvol_objectid = intarg; |
430 | } | 432 | } |
431 | break; | 433 | break; |
434 | case Opt_subvolrootid: | ||
435 | intarg = 0; | ||
436 | error = match_int(&args[0], &intarg); | ||
437 | if (!error) { | ||
438 | /* we want the original fs_tree */ | ||
439 | if (!intarg) | ||
440 | *subvol_rootid = | ||
441 | BTRFS_FS_TREE_OBJECTID; | ||
442 | else | ||
443 | *subvol_rootid = intarg; | ||
444 | } | ||
445 | break; | ||
432 | case Opt_device: | 446 | case Opt_device: |
433 | error = btrfs_scan_one_device(match_strdup(&args[0]), | 447 | error = btrfs_scan_one_device(match_strdup(&args[0]), |
434 | flags, holder, fs_devices); | 448 | flags, holder, fs_devices); |
@@ -736,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
736 | fmode_t mode = FMODE_READ; | 750 | fmode_t mode = FMODE_READ; |
737 | char *subvol_name = NULL; | 751 | char *subvol_name = NULL; |
738 | u64 subvol_objectid = 0; | 752 | u64 subvol_objectid = 0; |
753 | u64 subvol_rootid = 0; | ||
739 | int error = 0; | 754 | int error = 0; |
740 | 755 | ||
741 | if (!(flags & MS_RDONLY)) | 756 | if (!(flags & MS_RDONLY)) |
@@ -743,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
743 | 758 | ||
744 | error = btrfs_parse_early_options(data, mode, fs_type, | 759 | error = btrfs_parse_early_options(data, mode, fs_type, |
745 | &subvol_name, &subvol_objectid, | 760 | &subvol_name, &subvol_objectid, |
746 | &fs_devices); | 761 | &subvol_rootid, &fs_devices); |
747 | if (error) | 762 | if (error) |
748 | return ERR_PTR(error); | 763 | return ERR_PTR(error); |
749 | 764 | ||
@@ -807,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
807 | s->s_flags |= MS_ACTIVE; | 822 | s->s_flags |= MS_ACTIVE; |
808 | } | 823 | } |
809 | 824 | ||
810 | root = get_default_root(s, subvol_objectid); | ||
811 | if (IS_ERR(root)) { | ||
812 | error = PTR_ERR(root); | ||
813 | deactivate_locked_super(s); | ||
814 | goto error_free_subvol_name; | ||
815 | } | ||
816 | /* if they gave us a subvolume name bind mount into that */ | 825 | /* if they gave us a subvolume name bind mount into that */ |
817 | if (strcmp(subvol_name, ".")) { | 826 | if (strcmp(subvol_name, ".")) { |
818 | struct dentry *new_root; | 827 | struct dentry *new_root; |
828 | |||
829 | root = get_default_root(s, subvol_rootid); | ||
830 | if (IS_ERR(root)) { | ||
831 | error = PTR_ERR(root); | ||
832 | deactivate_locked_super(s); | ||
833 | goto error_free_subvol_name; | ||
834 | } | ||
835 | |||
819 | mutex_lock(&root->d_inode->i_mutex); | 836 | mutex_lock(&root->d_inode->i_mutex); |
820 | new_root = lookup_one_len(subvol_name, root, | 837 | new_root = lookup_one_len(subvol_name, root, |
821 | strlen(subvol_name)); | 838 | strlen(subvol_name)); |
@@ -836,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
836 | } | 853 | } |
837 | dput(root); | 854 | dput(root); |
838 | root = new_root; | 855 | root = new_root; |
856 | } else { | ||
857 | root = get_default_root(s, subvol_objectid); | ||
858 | if (IS_ERR(root)) { | ||
859 | error = PTR_ERR(root); | ||
860 | deactivate_locked_super(s); | ||
861 | goto error_free_subvol_name; | ||
862 | } | ||
839 | } | 863 | } |
840 | 864 | ||
841 | kfree(subvol_name); | 865 | kfree(subvol_name); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 5b158da7e0bb..c571734d5e5a 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -32,10 +32,8 @@ | |||
32 | 32 | ||
33 | static noinline void put_transaction(struct btrfs_transaction *transaction) | 33 | static noinline void put_transaction(struct btrfs_transaction *transaction) |
34 | { | 34 | { |
35 | WARN_ON(transaction->use_count == 0); | 35 | WARN_ON(atomic_read(&transaction->use_count) == 0); |
36 | transaction->use_count--; | 36 | if (atomic_dec_and_test(&transaction->use_count)) { |
37 | if (transaction->use_count == 0) { | ||
38 | list_del_init(&transaction->list); | ||
39 | memset(transaction, 0, sizeof(*transaction)); | 37 | memset(transaction, 0, sizeof(*transaction)); |
40 | kmem_cache_free(btrfs_transaction_cachep, transaction); | 38 | kmem_cache_free(btrfs_transaction_cachep, transaction); |
41 | } | 39 | } |
@@ -60,14 +58,14 @@ static noinline int join_transaction(struct btrfs_root *root) | |||
60 | if (!cur_trans) | 58 | if (!cur_trans) |
61 | return -ENOMEM; | 59 | return -ENOMEM; |
62 | root->fs_info->generation++; | 60 | root->fs_info->generation++; |
63 | cur_trans->num_writers = 1; | 61 | atomic_set(&cur_trans->num_writers, 1); |
64 | cur_trans->num_joined = 0; | 62 | cur_trans->num_joined = 0; |
65 | cur_trans->transid = root->fs_info->generation; | 63 | cur_trans->transid = root->fs_info->generation; |
66 | init_waitqueue_head(&cur_trans->writer_wait); | 64 | init_waitqueue_head(&cur_trans->writer_wait); |
67 | init_waitqueue_head(&cur_trans->commit_wait); | 65 | init_waitqueue_head(&cur_trans->commit_wait); |
68 | cur_trans->in_commit = 0; | 66 | cur_trans->in_commit = 0; |
69 | cur_trans->blocked = 0; | 67 | cur_trans->blocked = 0; |
70 | cur_trans->use_count = 1; | 68 | atomic_set(&cur_trans->use_count, 1); |
71 | cur_trans->commit_done = 0; | 69 | cur_trans->commit_done = 0; |
72 | cur_trans->start_time = get_seconds(); | 70 | cur_trans->start_time = get_seconds(); |
73 | 71 | ||
@@ -88,7 +86,7 @@ static noinline int join_transaction(struct btrfs_root *root) | |||
88 | root->fs_info->running_transaction = cur_trans; | 86 | root->fs_info->running_transaction = cur_trans; |
89 | spin_unlock(&root->fs_info->new_trans_lock); | 87 | spin_unlock(&root->fs_info->new_trans_lock); |
90 | } else { | 88 | } else { |
91 | cur_trans->num_writers++; | 89 | atomic_inc(&cur_trans->num_writers); |
92 | cur_trans->num_joined++; | 90 | cur_trans->num_joined++; |
93 | } | 91 | } |
94 | 92 | ||
@@ -145,7 +143,7 @@ static void wait_current_trans(struct btrfs_root *root) | |||
145 | cur_trans = root->fs_info->running_transaction; | 143 | cur_trans = root->fs_info->running_transaction; |
146 | if (cur_trans && cur_trans->blocked) { | 144 | if (cur_trans && cur_trans->blocked) { |
147 | DEFINE_WAIT(wait); | 145 | DEFINE_WAIT(wait); |
148 | cur_trans->use_count++; | 146 | atomic_inc(&cur_trans->use_count); |
149 | while (1) { | 147 | while (1) { |
150 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, | 148 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, |
151 | TASK_UNINTERRUPTIBLE); | 149 | TASK_UNINTERRUPTIBLE); |
@@ -181,6 +179,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | |||
181 | { | 179 | { |
182 | struct btrfs_trans_handle *h; | 180 | struct btrfs_trans_handle *h; |
183 | struct btrfs_transaction *cur_trans; | 181 | struct btrfs_transaction *cur_trans; |
182 | int retries = 0; | ||
184 | int ret; | 183 | int ret; |
185 | 184 | ||
186 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | 185 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) |
@@ -204,7 +203,7 @@ again: | |||
204 | } | 203 | } |
205 | 204 | ||
206 | cur_trans = root->fs_info->running_transaction; | 205 | cur_trans = root->fs_info->running_transaction; |
207 | cur_trans->use_count++; | 206 | atomic_inc(&cur_trans->use_count); |
208 | if (type != TRANS_JOIN_NOLOCK) | 207 | if (type != TRANS_JOIN_NOLOCK) |
209 | mutex_unlock(&root->fs_info->trans_mutex); | 208 | mutex_unlock(&root->fs_info->trans_mutex); |
210 | 209 | ||
@@ -224,10 +223,18 @@ again: | |||
224 | 223 | ||
225 | if (num_items > 0) { | 224 | if (num_items > 0) { |
226 | ret = btrfs_trans_reserve_metadata(h, root, num_items); | 225 | ret = btrfs_trans_reserve_metadata(h, root, num_items); |
227 | if (ret == -EAGAIN) { | 226 | if (ret == -EAGAIN && !retries) { |
227 | retries++; | ||
228 | btrfs_commit_transaction(h, root); | 228 | btrfs_commit_transaction(h, root); |
229 | goto again; | 229 | goto again; |
230 | } else if (ret == -EAGAIN) { | ||
231 | /* | ||
232 | * We have already retried and got EAGAIN, so really we | ||
233 | * don't have space, so set ret to -ENOSPC. | ||
234 | */ | ||
235 | ret = -ENOSPC; | ||
230 | } | 236 | } |
237 | |||
231 | if (ret < 0) { | 238 | if (ret < 0) { |
232 | btrfs_end_transaction(h, root); | 239 | btrfs_end_transaction(h, root); |
233 | return ERR_PTR(ret); | 240 | return ERR_PTR(ret); |
@@ -327,7 +334,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) | |||
327 | goto out_unlock; /* nothing committing|committed */ | 334 | goto out_unlock; /* nothing committing|committed */ |
328 | } | 335 | } |
329 | 336 | ||
330 | cur_trans->use_count++; | 337 | atomic_inc(&cur_trans->use_count); |
331 | mutex_unlock(&root->fs_info->trans_mutex); | 338 | mutex_unlock(&root->fs_info->trans_mutex); |
332 | 339 | ||
333 | wait_for_commit(root, cur_trans); | 340 | wait_for_commit(root, cur_trans); |
@@ -457,18 +464,14 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
457 | wake_up_process(info->transaction_kthread); | 464 | wake_up_process(info->transaction_kthread); |
458 | } | 465 | } |
459 | 466 | ||
460 | if (lock) | ||
461 | mutex_lock(&info->trans_mutex); | ||
462 | WARN_ON(cur_trans != info->running_transaction); | 467 | WARN_ON(cur_trans != info->running_transaction); |
463 | WARN_ON(cur_trans->num_writers < 1); | 468 | WARN_ON(atomic_read(&cur_trans->num_writers) < 1); |
464 | cur_trans->num_writers--; | 469 | atomic_dec(&cur_trans->num_writers); |
465 | 470 | ||
466 | smp_mb(); | 471 | smp_mb(); |
467 | if (waitqueue_active(&cur_trans->writer_wait)) | 472 | if (waitqueue_active(&cur_trans->writer_wait)) |
468 | wake_up(&cur_trans->writer_wait); | 473 | wake_up(&cur_trans->writer_wait); |
469 | put_transaction(cur_trans); | 474 | put_transaction(cur_trans); |
470 | if (lock) | ||
471 | mutex_unlock(&info->trans_mutex); | ||
472 | 475 | ||
473 | if (current->journal_info == trans) | 476 | if (current->journal_info == trans) |
474 | current->journal_info = NULL; | 477 | current->journal_info = NULL; |
@@ -1178,7 +1181,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, | |||
1178 | /* take transaction reference */ | 1181 | /* take transaction reference */ |
1179 | mutex_lock(&root->fs_info->trans_mutex); | 1182 | mutex_lock(&root->fs_info->trans_mutex); |
1180 | cur_trans = trans->transaction; | 1183 | cur_trans = trans->transaction; |
1181 | cur_trans->use_count++; | 1184 | atomic_inc(&cur_trans->use_count); |
1182 | mutex_unlock(&root->fs_info->trans_mutex); | 1185 | mutex_unlock(&root->fs_info->trans_mutex); |
1183 | 1186 | ||
1184 | btrfs_end_transaction(trans, root); | 1187 | btrfs_end_transaction(trans, root); |
@@ -1237,7 +1240,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1237 | 1240 | ||
1238 | mutex_lock(&root->fs_info->trans_mutex); | 1241 | mutex_lock(&root->fs_info->trans_mutex); |
1239 | if (cur_trans->in_commit) { | 1242 | if (cur_trans->in_commit) { |
1240 | cur_trans->use_count++; | 1243 | atomic_inc(&cur_trans->use_count); |
1241 | mutex_unlock(&root->fs_info->trans_mutex); | 1244 | mutex_unlock(&root->fs_info->trans_mutex); |
1242 | btrfs_end_transaction(trans, root); | 1245 | btrfs_end_transaction(trans, root); |
1243 | 1246 | ||
@@ -1259,7 +1262,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1259 | prev_trans = list_entry(cur_trans->list.prev, | 1262 | prev_trans = list_entry(cur_trans->list.prev, |
1260 | struct btrfs_transaction, list); | 1263 | struct btrfs_transaction, list); |
1261 | if (!prev_trans->commit_done) { | 1264 | if (!prev_trans->commit_done) { |
1262 | prev_trans->use_count++; | 1265 | atomic_inc(&prev_trans->use_count); |
1263 | mutex_unlock(&root->fs_info->trans_mutex); | 1266 | mutex_unlock(&root->fs_info->trans_mutex); |
1264 | 1267 | ||
1265 | wait_for_commit(root, prev_trans); | 1268 | wait_for_commit(root, prev_trans); |
@@ -1300,14 +1303,14 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1300 | TASK_UNINTERRUPTIBLE); | 1303 | TASK_UNINTERRUPTIBLE); |
1301 | 1304 | ||
1302 | smp_mb(); | 1305 | smp_mb(); |
1303 | if (cur_trans->num_writers > 1) | 1306 | if (atomic_read(&cur_trans->num_writers) > 1) |
1304 | schedule_timeout(MAX_SCHEDULE_TIMEOUT); | 1307 | schedule_timeout(MAX_SCHEDULE_TIMEOUT); |
1305 | else if (should_grow) | 1308 | else if (should_grow) |
1306 | schedule_timeout(1); | 1309 | schedule_timeout(1); |
1307 | 1310 | ||
1308 | mutex_lock(&root->fs_info->trans_mutex); | 1311 | mutex_lock(&root->fs_info->trans_mutex); |
1309 | finish_wait(&cur_trans->writer_wait, &wait); | 1312 | finish_wait(&cur_trans->writer_wait, &wait); |
1310 | } while (cur_trans->num_writers > 1 || | 1313 | } while (atomic_read(&cur_trans->num_writers) > 1 || |
1311 | (should_grow && cur_trans->num_joined != joined)); | 1314 | (should_grow && cur_trans->num_joined != joined)); |
1312 | 1315 | ||
1313 | ret = create_pending_snapshots(trans, root->fs_info); | 1316 | ret = create_pending_snapshots(trans, root->fs_info); |
@@ -1394,6 +1397,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1394 | 1397 | ||
1395 | wake_up(&cur_trans->commit_wait); | 1398 | wake_up(&cur_trans->commit_wait); |
1396 | 1399 | ||
1400 | list_del_init(&cur_trans->list); | ||
1397 | put_transaction(cur_trans); | 1401 | put_transaction(cur_trans); |
1398 | put_transaction(cur_trans); | 1402 | put_transaction(cur_trans); |
1399 | 1403 | ||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 229a594cacd5..e441acc6c584 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -27,11 +27,11 @@ struct btrfs_transaction { | |||
27 | * total writers in this transaction, it must be zero before the | 27 | * total writers in this transaction, it must be zero before the |
28 | * transaction can end | 28 | * transaction can end |
29 | */ | 29 | */ |
30 | unsigned long num_writers; | 30 | atomic_t num_writers; |
31 | 31 | ||
32 | unsigned long num_joined; | 32 | unsigned long num_joined; |
33 | int in_commit; | 33 | int in_commit; |
34 | int use_count; | 34 | atomic_t use_count; |
35 | int commit_done; | 35 | int commit_done; |
36 | int blocked; | 36 | int blocked; |
37 | struct list_head list; | 37 | struct list_head list; |
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/btrfs/xattr.c b/fs/btrfs/xattr.c index a5303b871b13..cfd660550ded 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -180,11 +180,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
180 | struct btrfs_path *path; | 180 | struct btrfs_path *path; |
181 | struct extent_buffer *leaf; | 181 | struct extent_buffer *leaf; |
182 | struct btrfs_dir_item *di; | 182 | struct btrfs_dir_item *di; |
183 | int ret = 0, slot, advance; | 183 | int ret = 0, slot; |
184 | size_t total_size = 0, size_left = size; | 184 | size_t total_size = 0, size_left = size; |
185 | unsigned long name_ptr; | 185 | unsigned long name_ptr; |
186 | size_t name_len; | 186 | size_t name_len; |
187 | u32 nritems; | ||
188 | 187 | ||
189 | /* | 188 | /* |
190 | * ok we want all objects associated with this id. | 189 | * ok we want all objects associated with this id. |
@@ -204,34 +203,24 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
204 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 203 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
205 | if (ret < 0) | 204 | if (ret < 0) |
206 | goto err; | 205 | goto err; |
207 | advance = 0; | 206 | |
208 | while (1) { | 207 | while (1) { |
209 | leaf = path->nodes[0]; | 208 | leaf = path->nodes[0]; |
210 | nritems = btrfs_header_nritems(leaf); | ||
211 | slot = path->slots[0]; | 209 | slot = path->slots[0]; |
212 | 210 | ||
213 | /* this is where we start walking through the path */ | 211 | /* this is where we start walking through the path */ |
214 | if (advance || slot >= nritems) { | 212 | if (slot >= btrfs_header_nritems(leaf)) { |
215 | /* | 213 | /* |
216 | * if we've reached the last slot in this leaf we need | 214 | * if we've reached the last slot in this leaf we need |
217 | * to go to the next leaf and reset everything | 215 | * to go to the next leaf and reset everything |
218 | */ | 216 | */ |
219 | if (slot >= nritems-1) { | 217 | ret = btrfs_next_leaf(root, path); |
220 | ret = btrfs_next_leaf(root, path); | 218 | if (ret < 0) |
221 | if (ret) | 219 | goto err; |
222 | break; | 220 | else if (ret > 0) |
223 | leaf = path->nodes[0]; | 221 | break; |
224 | nritems = btrfs_header_nritems(leaf); | 222 | continue; |
225 | slot = path->slots[0]; | ||
226 | } else { | ||
227 | /* | ||
228 | * just walking through the slots on this leaf | ||
229 | */ | ||
230 | slot++; | ||
231 | path->slots[0]++; | ||
232 | } | ||
233 | } | 223 | } |
234 | advance = 1; | ||
235 | 224 | ||
236 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 225 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
237 | 226 | ||
@@ -250,7 +239,7 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
250 | 239 | ||
251 | /* we are just looking for how big our buffer needs to be */ | 240 | /* we are just looking for how big our buffer needs to be */ |
252 | if (!size) | 241 | if (!size) |
253 | continue; | 242 | goto next; |
254 | 243 | ||
255 | if (!buffer || (name_len + 1) > size_left) { | 244 | if (!buffer || (name_len + 1) > size_left) { |
256 | ret = -ERANGE; | 245 | ret = -ERANGE; |
@@ -263,6 +252,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
263 | 252 | ||
264 | size_left -= name_len + 1; | 253 | size_left -= name_len + 1; |
265 | buffer += name_len + 1; | 254 | buffer += name_len + 1; |
255 | next: | ||
256 | path->slots[0]++; | ||
266 | } | 257 | } |
267 | ret = total_size; | 258 | ret = total_size; |
268 | 259 | ||
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/Kconfig b/fs/cifs/Kconfig index 7cb0f7f847e4..75c47cd8d086 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -7,6 +7,7 @@ config CIFS | |||
7 | select CRYPTO_MD5 | 7 | select CRYPTO_MD5 |
8 | select CRYPTO_HMAC | 8 | select CRYPTO_HMAC |
9 | select CRYPTO_ARC4 | 9 | select CRYPTO_ARC4 |
10 | select CRYPTO_DES | ||
10 | help | 11 | help |
11 | This is the client VFS module for the Common Internet File System | 12 | This is the client VFS module for the Common Internet File System |
12 | (CIFS) protocol which is the successor to the Server Message Block | 13 | (CIFS) protocol which is the successor to the Server Message Block |
@@ -152,16 +153,28 @@ config CIFS_ACL | |||
152 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | 153 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob |
153 | is handed over to the application/caller. | 154 | is handed over to the application/caller. |
154 | 155 | ||
155 | config CIFS_EXPERIMENTAL | 156 | config CIFS_SMB2 |
156 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 157 | bool "SMB2 network file system support (EXPERIMENTAL)" |
158 | depends on EXPERIMENTAL && INET && BROKEN | ||
159 | select NLS | ||
160 | select KEYS | ||
161 | select FSCACHE | ||
162 | select DNS_RESOLVER | ||
163 | |||
164 | help | ||
165 | This enables experimental support for the SMB2 (Server Message Block | ||
166 | version 2) protocol. The SMB2 protocol is the successor to the | ||
167 | popular CIFS and SMB network file sharing protocols. SMB2 is the | ||
168 | native file sharing mechanism for recent versions of Windows | ||
169 | operating systems (since Vista). SMB2 enablement will eventually | ||
170 | allow users better performance, security and features, than would be | ||
171 | possible with cifs. Note that smb2 mount options also are simpler | ||
172 | (compared to cifs) due to protocol improvements. | ||
173 | |||
174 | Unless you are a developer or tester, say N. | ||
175 | |||
176 | config CIFS_NFSD_EXPORT | ||
177 | bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" | ||
157 | depends on CIFS && EXPERIMENTAL | 178 | depends on CIFS && EXPERIMENTAL |
158 | help | 179 | help |
159 | Enables cifs features under testing. These features are | 180 | Allows NFS server to export a CIFS mounted share (nfsd over cifs) |
160 | experimental and currently include DFS support and directory | ||
161 | change notification ie fcntl(F_DNOTIFY), as well as the upcall | ||
162 | mechanism which will be used for Kerberos session negotiation | ||
163 | and uid remapping. Some of these features also may depend on | ||
164 | setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental | ||
165 | (which is disabled by default). See the file fs/cifs/README | ||
166 | for more details. If unsure, say N. | ||
167 | |||
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index d87558448e3d..005d524c3a4a 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
5 | 5 | ||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ |
8 | cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ | 8 | cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
9 | readdir.o ioctl.o sess.o export.o | 9 | readdir.o ioctl.o sess.o export.o |
10 | 10 | ||
diff --git a/fs/cifs/README b/fs/cifs/README index 74ab165fc646..4a3ca0e5ca24 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -704,18 +704,6 @@ the start of smb requests and responses can be enabled via: | |||
704 | 704 | ||
705 | echo 1 > /proc/fs/cifs/traceSMB | 705 | echo 1 > /proc/fs/cifs/traceSMB |
706 | 706 | ||
707 | Two other experimental features are under development. To test these | ||
708 | requires enabling CONFIG_CIFS_EXPERIMENTAL | ||
709 | |||
710 | cifsacl support needed to retrieve approximated mode bits based on | ||
711 | the contents on the CIFS ACL. | ||
712 | |||
713 | lease support: cifs will check the oplock state before calling into | ||
714 | the vfs to see if we can grant a lease on a file. | ||
715 | |||
716 | DNOTIFY fcntl: needed for support of directory change | ||
717 | notification and perhaps later for file leases) | ||
718 | |||
719 | Per share (per client mount) statistics are available in /proc/fs/cifs/Stats | 707 | Per share (per client mount) statistics are available in /proc/fs/cifs/Stats |
720 | if the kernel was configured with cifs statistics enabled. The statistics | 708 | if the kernel was configured with cifs statistics enabled. The statistics |
721 | represent the number of successful (ie non-zero return code from the server) | 709 | represent the number of successful (ie non-zero return code from the server) |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 30d01bc90855..18f4272d9047 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -63,7 +63,7 @@ void cifs_dump_detail(struct smb_hdr *smb) | |||
63 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", | 63 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", |
64 | smb->Command, smb->Status.CifsError, | 64 | smb->Command, smb->Status.CifsError, |
65 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); | 65 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); |
66 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize_LE(smb)); | 66 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); |
67 | } | 67 | } |
68 | 68 | ||
69 | 69 | ||
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ac51cd2d33ae..a9d5692e0c20 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -58,9 +58,7 @@ struct cifs_sb_info { | |||
58 | unsigned int mnt_cifs_flags; | 58 | unsigned int mnt_cifs_flags; |
59 | int prepathlen; | 59 | int prepathlen; |
60 | char *prepath; /* relative path under the share to mount to */ | 60 | char *prepath; /* relative path under the share to mount to */ |
61 | #ifdef CONFIG_CIFS_DFS_UPCALL | 61 | char *mountdata; /* options received at mount time or via DFS refs */ |
62 | char *mountdata; /* mount options received at mount time */ | ||
63 | #endif | ||
64 | struct backing_dev_info bdi; | 62 | struct backing_dev_info bdi; |
65 | struct delayed_work prune_tlinks; | 63 | struct delayed_work prune_tlinks; |
66 | }; | 64 | }; |
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/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 644dd882a560..6d02fd560566 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h | |||
@@ -82,6 +82,9 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); | |||
82 | char *cifs_strndup_from_ucs(const char *src, const int maxlen, | 82 | char *cifs_strndup_from_ucs(const char *src, const int maxlen, |
83 | const bool is_unicode, | 83 | const bool is_unicode, |
84 | const struct nls_table *codepage); | 84 | const struct nls_table *codepage); |
85 | extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
86 | const struct nls_table *cp, int mapChars); | ||
87 | |||
85 | #endif | 88 | #endif |
86 | 89 | ||
87 | /* | 90 | /* |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index beeebf194234..f3c6fb9942ac 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -23,24 +23,16 @@ | |||
23 | 23 | ||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/string.h> | ||
27 | #include <linux/keyctl.h> | ||
28 | #include <linux/key-type.h> | ||
29 | #include <keys/user-type.h> | ||
26 | #include "cifspdu.h" | 30 | #include "cifspdu.h" |
27 | #include "cifsglob.h" | 31 | #include "cifsglob.h" |
28 | #include "cifsacl.h" | 32 | #include "cifsacl.h" |
29 | #include "cifsproto.h" | 33 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 34 | #include "cifs_debug.h" |
31 | 35 | ||
32 | |||
33 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | ||
34 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | ||
35 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | ||
36 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"}, | ||
37 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"}, | ||
38 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"}, | ||
39 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"}, | ||
40 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} } | ||
41 | ; | ||
42 | |||
43 | |||
44 | /* security id for everyone/world system group */ | 36 | /* security id for everyone/world system group */ |
45 | static const struct cifs_sid sid_everyone = { | 37 | static const struct cifs_sid sid_everyone = { |
46 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | 38 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; |
@@ -50,50 +42,385 @@ static const struct cifs_sid sid_authusers = { | |||
50 | /* group users */ | 42 | /* group users */ |
51 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 43 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
52 | 44 | ||
45 | const struct cred *root_cred; | ||
53 | 46 | ||
54 | int match_sid(struct cifs_sid *ctsid) | 47 | static void |
48 | shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem, | ||
49 | int *nr_del) | ||
55 | { | 50 | { |
56 | int i, j; | 51 | struct rb_node *node; |
57 | int num_subauth, num_sat, num_saw; | 52 | struct rb_node *tmp; |
58 | struct cifs_sid *cwsid; | 53 | struct cifs_sid_id *psidid; |
54 | |||
55 | node = rb_first(root); | ||
56 | while (node) { | ||
57 | tmp = node; | ||
58 | node = rb_next(tmp); | ||
59 | psidid = rb_entry(tmp, struct cifs_sid_id, rbnode); | ||
60 | if (nr_to_scan == 0 || *nr_del == nr_to_scan) | ||
61 | ++(*nr_rem); | ||
62 | else { | ||
63 | if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE) | ||
64 | && psidid->refcount == 0) { | ||
65 | rb_erase(tmp, root); | ||
66 | ++(*nr_del); | ||
67 | } else | ||
68 | ++(*nr_rem); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Run idmap cache shrinker. | ||
75 | */ | ||
76 | static int | ||
77 | cifs_idmap_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | ||
78 | { | ||
79 | int nr_del = 0; | ||
80 | int nr_rem = 0; | ||
81 | struct rb_root *root; | ||
82 | |||
83 | root = &uidtree; | ||
84 | spin_lock(&siduidlock); | ||
85 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
86 | spin_unlock(&siduidlock); | ||
87 | |||
88 | root = &gidtree; | ||
89 | spin_lock(&sidgidlock); | ||
90 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
91 | spin_unlock(&sidgidlock); | ||
92 | |||
93 | return nr_rem; | ||
94 | } | ||
95 | |||
96 | static struct shrinker cifs_shrinker = { | ||
97 | .shrink = cifs_idmap_shrinker, | ||
98 | .seeks = DEFAULT_SEEKS, | ||
99 | }; | ||
100 | |||
101 | static int | ||
102 | cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
103 | { | ||
104 | char *payload; | ||
105 | |||
106 | payload = kmalloc(datalen, GFP_KERNEL); | ||
107 | if (!payload) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | memcpy(payload, data, datalen); | ||
111 | key->payload.data = payload; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static inline void | ||
116 | cifs_idmap_key_destroy(struct key *key) | ||
117 | { | ||
118 | kfree(key->payload.data); | ||
119 | } | ||
59 | 120 | ||
60 | if (!ctsid) | 121 | struct key_type cifs_idmap_key_type = { |
61 | return -1; | 122 | .name = "cifs.idmap", |
123 | .instantiate = cifs_idmap_key_instantiate, | ||
124 | .destroy = cifs_idmap_key_destroy, | ||
125 | .describe = user_describe, | ||
126 | .match = user_match, | ||
127 | }; | ||
128 | |||
129 | static void | ||
130 | sid_to_str(struct cifs_sid *sidptr, char *sidstr) | ||
131 | { | ||
132 | int i; | ||
133 | unsigned long saval; | ||
134 | char *strptr; | ||
62 | 135 | ||
63 | for (i = 0; i < NUM_WK_SIDS; ++i) { | 136 | strptr = sidstr; |
64 | cwsid = &(wksidarr[i].cifssid); | ||
65 | 137 | ||
66 | /* compare the revision */ | 138 | sprintf(strptr, "%s", "S"); |
67 | if (ctsid->revision != cwsid->revision) | 139 | strptr = sidstr + strlen(sidstr); |
68 | continue; | ||
69 | 140 | ||
70 | /* compare all of the six auth values */ | 141 | sprintf(strptr, "-%d", sidptr->revision); |
71 | for (j = 0; j < 6; ++j) { | 142 | strptr = sidstr + strlen(sidstr); |
72 | if (ctsid->authority[j] != cwsid->authority[j]) | 143 | |
73 | break; | 144 | for (i = 0; i < 6; ++i) { |
145 | if (sidptr->authority[i]) { | ||
146 | sprintf(strptr, "-%d", sidptr->authority[i]); | ||
147 | strptr = sidstr + strlen(sidstr); | ||
74 | } | 148 | } |
75 | if (j < 6) | 149 | } |
76 | continue; /* all of the auth values did not match */ | 150 | |
77 | 151 | for (i = 0; i < sidptr->num_subauth; ++i) { | |
78 | /* compare all of the subauth values if any */ | 152 | saval = le32_to_cpu(sidptr->sub_auth[i]); |
79 | num_sat = ctsid->num_subauth; | 153 | sprintf(strptr, "-%ld", saval); |
80 | num_saw = cwsid->num_subauth; | 154 | strptr = sidstr + strlen(sidstr); |
81 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 155 | } |
82 | if (num_subauth) { | 156 | } |
83 | for (j = 0; j < num_subauth; ++j) { | 157 | |
84 | if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) | 158 | static void |
85 | break; | 159 | id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, |
86 | } | 160 | struct cifs_sid_id **psidid, char *typestr) |
87 | if (j < num_subauth) | 161 | { |
88 | continue; /* all sub_auth values do not match */ | 162 | int rc; |
163 | char *strptr; | ||
164 | struct rb_node *node = root->rb_node; | ||
165 | struct rb_node *parent = NULL; | ||
166 | struct rb_node **linkto = &(root->rb_node); | ||
167 | struct cifs_sid_id *lsidid; | ||
168 | |||
169 | while (node) { | ||
170 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
171 | parent = node; | ||
172 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
173 | if (rc > 0) { | ||
174 | linkto = &(node->rb_left); | ||
175 | node = node->rb_left; | ||
176 | } else if (rc < 0) { | ||
177 | linkto = &(node->rb_right); | ||
178 | node = node->rb_right; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); | ||
183 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); | ||
184 | (*psidid)->refcount = 0; | ||
185 | |||
186 | sprintf((*psidid)->sidstr, "%s", typestr); | ||
187 | strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); | ||
188 | sid_to_str(&(*psidid)->sid, strptr); | ||
189 | |||
190 | clear_bit(SID_ID_PENDING, &(*psidid)->state); | ||
191 | clear_bit(SID_ID_MAPPED, &(*psidid)->state); | ||
192 | |||
193 | rb_link_node(&(*psidid)->rbnode, parent, linkto); | ||
194 | rb_insert_color(&(*psidid)->rbnode, root); | ||
195 | } | ||
196 | |||
197 | static struct cifs_sid_id * | ||
198 | id_rb_search(struct rb_root *root, struct cifs_sid *sidptr) | ||
199 | { | ||
200 | int rc; | ||
201 | struct rb_node *node = root->rb_node; | ||
202 | struct cifs_sid_id *lsidid; | ||
203 | |||
204 | while (node) { | ||
205 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
206 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
207 | if (rc > 0) { | ||
208 | node = node->rb_left; | ||
209 | } else if (rc < 0) { | ||
210 | node = node->rb_right; | ||
211 | } else /* node found */ | ||
212 | return lsidid; | ||
213 | } | ||
214 | |||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | static int | ||
219 | sidid_pending_wait(void *unused) | ||
220 | { | ||
221 | schedule(); | ||
222 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | ||
227 | struct cifs_fattr *fattr, uint sidtype) | ||
228 | { | ||
229 | int rc; | ||
230 | unsigned long cid; | ||
231 | struct key *idkey; | ||
232 | const struct cred *saved_cred; | ||
233 | struct cifs_sid_id *psidid, *npsidid; | ||
234 | struct rb_root *cidtree; | ||
235 | spinlock_t *cidlock; | ||
236 | |||
237 | if (sidtype == SIDOWNER) { | ||
238 | cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */ | ||
239 | cidlock = &siduidlock; | ||
240 | cidtree = &uidtree; | ||
241 | } else if (sidtype == SIDGROUP) { | ||
242 | cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */ | ||
243 | cidlock = &sidgidlock; | ||
244 | cidtree = &gidtree; | ||
245 | } else | ||
246 | return -ENOENT; | ||
247 | |||
248 | spin_lock(cidlock); | ||
249 | psidid = id_rb_search(cidtree, psid); | ||
250 | |||
251 | if (!psidid) { /* node does not exist, allocate one & attempt adding */ | ||
252 | spin_unlock(cidlock); | ||
253 | npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); | ||
254 | if (!npsidid) | ||
255 | return -ENOMEM; | ||
256 | |||
257 | npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); | ||
258 | if (!npsidid->sidstr) { | ||
259 | kfree(npsidid); | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | |||
263 | spin_lock(cidlock); | ||
264 | psidid = id_rb_search(cidtree, psid); | ||
265 | if (psidid) { /* node happened to get inserted meanwhile */ | ||
266 | ++psidid->refcount; | ||
267 | spin_unlock(cidlock); | ||
268 | kfree(npsidid->sidstr); | ||
269 | kfree(npsidid); | ||
270 | } else { | ||
271 | psidid = npsidid; | ||
272 | id_rb_insert(cidtree, psid, &psidid, | ||
273 | sidtype == SIDOWNER ? "os:" : "gs:"); | ||
274 | ++psidid->refcount; | ||
275 | spin_unlock(cidlock); | ||
89 | } | 276 | } |
277 | } else { | ||
278 | ++psidid->refcount; | ||
279 | spin_unlock(cidlock); | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * If we are here, it is safe to access psidid and its fields | ||
284 | * since a reference was taken earlier while holding the spinlock. | ||
285 | * A reference on the node is put without holding the spinlock | ||
286 | * and it is OK to do so in this case, shrinker will not erase | ||
287 | * this node until all references are put and we do not access | ||
288 | * any fields of the node after a reference is put . | ||
289 | */ | ||
290 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { | ||
291 | cid = psidid->id; | ||
292 | psidid->time = jiffies; /* update ts for accessing */ | ||
293 | goto sid_to_id_out; | ||
294 | } | ||
90 | 295 | ||
91 | cFYI(1, "matching sid: %s\n", wksidarr[i].sidname); | 296 | if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) |
92 | return 0; /* sids compare/match */ | 297 | goto sid_to_id_out; |
298 | |||
299 | if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { | ||
300 | saved_cred = override_creds(root_cred); | ||
301 | idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); | ||
302 | if (IS_ERR(idkey)) | ||
303 | cFYI(1, "%s: Can't map SID to an id", __func__); | ||
304 | else { | ||
305 | cid = *(unsigned long *)idkey->payload.value; | ||
306 | psidid->id = cid; | ||
307 | set_bit(SID_ID_MAPPED, &psidid->state); | ||
308 | key_put(idkey); | ||
309 | kfree(psidid->sidstr); | ||
310 | } | ||
311 | revert_creds(saved_cred); | ||
312 | psidid->time = jiffies; /* update ts for accessing */ | ||
313 | clear_bit(SID_ID_PENDING, &psidid->state); | ||
314 | wake_up_bit(&psidid->state, SID_ID_PENDING); | ||
315 | } else { | ||
316 | rc = wait_on_bit(&psidid->state, SID_ID_PENDING, | ||
317 | sidid_pending_wait, TASK_INTERRUPTIBLE); | ||
318 | if (rc) { | ||
319 | cFYI(1, "%s: sidid_pending_wait interrupted %d", | ||
320 | __func__, rc); | ||
321 | --psidid->refcount; /* decremented without spinlock */ | ||
322 | return rc; | ||
323 | } | ||
324 | if (test_bit(SID_ID_MAPPED, &psidid->state)) | ||
325 | cid = psidid->id; | ||
93 | } | 326 | } |
94 | 327 | ||
95 | cFYI(1, "No matching sid"); | 328 | sid_to_id_out: |
96 | return -1; | 329 | --psidid->refcount; /* decremented without spinlock */ |
330 | if (sidtype == SIDOWNER) | ||
331 | fattr->cf_uid = cid; | ||
332 | else | ||
333 | fattr->cf_gid = cid; | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int | ||
339 | init_cifs_idmap(void) | ||
340 | { | ||
341 | struct cred *cred; | ||
342 | struct key *keyring; | ||
343 | int ret; | ||
344 | |||
345 | cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); | ||
346 | |||
347 | /* create an override credential set with a special thread keyring in | ||
348 | * which requests are cached | ||
349 | * | ||
350 | * this is used to prevent malicious redirections from being installed | ||
351 | * with add_key(). | ||
352 | */ | ||
353 | cred = prepare_kernel_cred(NULL); | ||
354 | if (!cred) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, | ||
358 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
359 | KEY_USR_VIEW | KEY_USR_READ, | ||
360 | KEY_ALLOC_NOT_IN_QUOTA); | ||
361 | if (IS_ERR(keyring)) { | ||
362 | ret = PTR_ERR(keyring); | ||
363 | goto failed_put_cred; | ||
364 | } | ||
365 | |||
366 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
367 | if (ret < 0) | ||
368 | goto failed_put_key; | ||
369 | |||
370 | ret = register_key_type(&cifs_idmap_key_type); | ||
371 | if (ret < 0) | ||
372 | goto failed_put_key; | ||
373 | |||
374 | /* instruct request_key() to use this special keyring as a cache for | ||
375 | * the results it looks up */ | ||
376 | cred->thread_keyring = keyring; | ||
377 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | ||
378 | root_cred = cred; | ||
379 | |||
380 | spin_lock_init(&siduidlock); | ||
381 | uidtree = RB_ROOT; | ||
382 | spin_lock_init(&sidgidlock); | ||
383 | gidtree = RB_ROOT; | ||
384 | |||
385 | register_shrinker(&cifs_shrinker); | ||
386 | |||
387 | cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); | ||
388 | return 0; | ||
389 | |||
390 | failed_put_key: | ||
391 | key_put(keyring); | ||
392 | failed_put_cred: | ||
393 | put_cred(cred); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | void | ||
398 | exit_cifs_idmap(void) | ||
399 | { | ||
400 | key_revoke(root_cred->thread_keyring); | ||
401 | unregister_key_type(&cifs_idmap_key_type); | ||
402 | put_cred(root_cred); | ||
403 | unregister_shrinker(&cifs_shrinker); | ||
404 | cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name); | ||
405 | } | ||
406 | |||
407 | void | ||
408 | cifs_destroy_idmaptrees(void) | ||
409 | { | ||
410 | struct rb_root *root; | ||
411 | struct rb_node *node; | ||
412 | |||
413 | root = &uidtree; | ||
414 | spin_lock(&siduidlock); | ||
415 | while ((node = rb_first(root))) | ||
416 | rb_erase(node, root); | ||
417 | spin_unlock(&siduidlock); | ||
418 | |||
419 | root = &gidtree; | ||
420 | spin_lock(&sidgidlock); | ||
421 | while ((node = rb_first(root))) | ||
422 | rb_erase(node, root); | ||
423 | spin_unlock(&sidgidlock); | ||
97 | } | 424 | } |
98 | 425 | ||
99 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are | 426 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are |
@@ -104,16 +431,24 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
104 | int num_subauth, num_sat, num_saw; | 431 | int num_subauth, num_sat, num_saw; |
105 | 432 | ||
106 | if ((!ctsid) || (!cwsid)) | 433 | if ((!ctsid) || (!cwsid)) |
107 | return 0; | 434 | return 1; |
108 | 435 | ||
109 | /* compare the revision */ | 436 | /* compare the revision */ |
110 | if (ctsid->revision != cwsid->revision) | 437 | if (ctsid->revision != cwsid->revision) { |
111 | return 0; | 438 | if (ctsid->revision > cwsid->revision) |
439 | return 1; | ||
440 | else | ||
441 | return -1; | ||
442 | } | ||
112 | 443 | ||
113 | /* compare all of the six auth values */ | 444 | /* compare all of the six auth values */ |
114 | for (i = 0; i < 6; ++i) { | 445 | for (i = 0; i < 6; ++i) { |
115 | if (ctsid->authority[i] != cwsid->authority[i]) | 446 | if (ctsid->authority[i] != cwsid->authority[i]) { |
116 | return 0; | 447 | if (ctsid->authority[i] > cwsid->authority[i]) |
448 | return 1; | ||
449 | else | ||
450 | return -1; | ||
451 | } | ||
117 | } | 452 | } |
118 | 453 | ||
119 | /* compare all of the subauth values if any */ | 454 | /* compare all of the subauth values if any */ |
@@ -122,12 +457,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
122 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 457 | num_subauth = num_sat < num_saw ? num_sat : num_saw; |
123 | if (num_subauth) { | 458 | if (num_subauth) { |
124 | for (i = 0; i < num_subauth; ++i) { | 459 | for (i = 0; i < num_subauth; ++i) { |
125 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) | 460 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) { |
126 | return 0; | 461 | if (ctsid->sub_auth[i] > cwsid->sub_auth[i]) |
462 | return 1; | ||
463 | else | ||
464 | return -1; | ||
465 | } | ||
127 | } | 466 | } |
128 | } | 467 | } |
129 | 468 | ||
130 | return 1; /* sids compare/match */ | 469 | return 0; /* sids compare/match */ |
131 | } | 470 | } |
132 | 471 | ||
133 | 472 | ||
@@ -382,22 +721,22 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
382 | #ifdef CONFIG_CIFS_DEBUG2 | 721 | #ifdef CONFIG_CIFS_DEBUG2 |
383 | dump_ace(ppace[i], end_of_acl); | 722 | dump_ace(ppace[i], end_of_acl); |
384 | #endif | 723 | #endif |
385 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 724 | if (compare_sids(&(ppace[i]->sid), pownersid) == 0) |
386 | access_flags_to_mode(ppace[i]->access_req, | 725 | access_flags_to_mode(ppace[i]->access_req, |
387 | ppace[i]->type, | 726 | ppace[i]->type, |
388 | &fattr->cf_mode, | 727 | &fattr->cf_mode, |
389 | &user_mask); | 728 | &user_mask); |
390 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 729 | if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) |
391 | access_flags_to_mode(ppace[i]->access_req, | 730 | access_flags_to_mode(ppace[i]->access_req, |
392 | ppace[i]->type, | 731 | ppace[i]->type, |
393 | &fattr->cf_mode, | 732 | &fattr->cf_mode, |
394 | &group_mask); | 733 | &group_mask); |
395 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 734 | if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) |
396 | access_flags_to_mode(ppace[i]->access_req, | 735 | access_flags_to_mode(ppace[i]->access_req, |
397 | ppace[i]->type, | 736 | ppace[i]->type, |
398 | &fattr->cf_mode, | 737 | &fattr->cf_mode, |
399 | &other_mask); | 738 | &other_mask); |
400 | if (compare_sids(&(ppace[i]->sid), &sid_authusers)) | 739 | if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) |
401 | access_flags_to_mode(ppace[i]->access_req, | 740 | access_flags_to_mode(ppace[i]->access_req, |
402 | ppace[i]->type, | 741 | ppace[i]->type, |
403 | &fattr->cf_mode, | 742 | &fattr->cf_mode, |
@@ -475,10 +814,10 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
475 | 814 | ||
476 | 815 | ||
477 | /* Convert CIFS ACL to POSIX form */ | 816 | /* Convert CIFS ACL to POSIX form */ |
478 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | 817 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, |
479 | struct cifs_fattr *fattr) | 818 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) |
480 | { | 819 | { |
481 | int rc; | 820 | int rc = 0; |
482 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 821 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
483 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 822 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
484 | char *end_of_acl = ((char *)pntsd) + acl_len; | 823 | char *end_of_acl = ((char *)pntsd) + acl_len; |
@@ -500,12 +839,26 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
500 | le32_to_cpu(pntsd->sacloffset), dacloffset); | 839 | le32_to_cpu(pntsd->sacloffset), dacloffset); |
501 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ | 840 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ |
502 | rc = parse_sid(owner_sid_ptr, end_of_acl); | 841 | rc = parse_sid(owner_sid_ptr, end_of_acl); |
503 | if (rc) | 842 | if (rc) { |
843 | cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc); | ||
844 | return rc; | ||
845 | } | ||
846 | rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER); | ||
847 | if (rc) { | ||
848 | cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc); | ||
504 | return rc; | 849 | return rc; |
850 | } | ||
505 | 851 | ||
506 | rc = parse_sid(group_sid_ptr, end_of_acl); | 852 | rc = parse_sid(group_sid_ptr, end_of_acl); |
507 | if (rc) | 853 | if (rc) { |
854 | cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc); | ||
508 | return rc; | 855 | return rc; |
856 | } | ||
857 | rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP); | ||
858 | if (rc) { | ||
859 | cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc); | ||
860 | return rc; | ||
861 | } | ||
509 | 862 | ||
510 | if (dacloffset) | 863 | if (dacloffset) |
511 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 864 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
@@ -520,7 +873,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
520 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 873 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
521 | sizeof(struct cifs_sid)); */ | 874 | sizeof(struct cifs_sid)); */ |
522 | 875 | ||
523 | return 0; | 876 | return rc; |
524 | } | 877 | } |
525 | 878 | ||
526 | 879 | ||
@@ -688,7 +1041,7 @@ out: | |||
688 | } | 1041 | } |
689 | 1042 | ||
690 | /* Set an ACL on the server */ | 1043 | /* Set an ACL on the server */ |
691 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | 1044 | int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, |
692 | struct inode *inode, const char *path) | 1045 | struct inode *inode, const char *path) |
693 | { | 1046 | { |
694 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1047 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -727,7 +1080,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
727 | rc = PTR_ERR(pntsd); | 1080 | rc = PTR_ERR(pntsd); |
728 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | 1081 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); |
729 | } else { | 1082 | } else { |
730 | rc = parse_sec_desc(pntsd, acllen, fattr); | 1083 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); |
731 | kfree(pntsd); | 1084 | kfree(pntsd); |
732 | if (rc) | 1085 | if (rc) |
733 | cERROR(1, "parse sec desc failed rc = %d", rc); | 1086 | cERROR(1, "parse sec desc failed rc = %d", rc); |
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index c4ae7d036563..5c902c7ce524 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -39,6 +39,15 @@ | |||
39 | #define ACCESS_ALLOWED 0 | 39 | #define ACCESS_ALLOWED 0 |
40 | #define ACCESS_DENIED 1 | 40 | #define ACCESS_DENIED 1 |
41 | 41 | ||
42 | #define SIDOWNER 1 | ||
43 | #define SIDGROUP 2 | ||
44 | #define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */ | ||
45 | |||
46 | #define SID_ID_MAPPED 0 | ||
47 | #define SID_ID_PENDING 1 | ||
48 | #define SID_MAP_EXPIRE (3600 * HZ) /* map entry expires after one hour */ | ||
49 | #define SID_MAP_RETRY (300 * HZ) /* wait 5 minutes for next attempt to map */ | ||
50 | |||
42 | struct cifs_ntsd { | 51 | struct cifs_ntsd { |
43 | __le16 revision; /* revision level */ | 52 | __le16 revision; /* revision level */ |
44 | __le16 type; | 53 | __le16 type; |
@@ -74,7 +83,21 @@ struct cifs_wksid { | |||
74 | char sidname[SIDNAMELENGTH]; | 83 | char sidname[SIDNAMELENGTH]; |
75 | } __attribute__((packed)); | 84 | } __attribute__((packed)); |
76 | 85 | ||
77 | extern int match_sid(struct cifs_sid *); | 86 | struct cifs_sid_id { |
87 | unsigned int refcount; /* increment with spinlock, decrement without */ | ||
88 | unsigned long id; | ||
89 | unsigned long time; | ||
90 | unsigned long state; | ||
91 | char *sidstr; | ||
92 | struct rb_node rbnode; | ||
93 | struct cifs_sid sid; | ||
94 | }; | ||
95 | |||
96 | #ifdef __KERNEL__ | ||
97 | extern struct key_type cifs_idmap_key_type; | ||
98 | extern const struct cred *root_cred; | ||
99 | #endif /* KERNEL */ | ||
100 | |||
78 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); | 101 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); |
79 | 102 | ||
80 | #endif /* _CIFSACL_H */ | 103 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index d1a016be73ba..45c3f78c8f81 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -60,7 +60,7 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | |||
60 | server->session_key.response, server->session_key.len); | 60 | server->session_key.response, server->session_key.len); |
61 | 61 | ||
62 | crypto_shash_update(&server->secmech.sdescmd5->shash, | 62 | crypto_shash_update(&server->secmech.sdescmd5->shash, |
63 | cifs_pdu->Protocol, cifs_pdu->smb_buf_length); | 63 | cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length)); |
64 | 64 | ||
65 | rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); | 65 | rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); |
66 | 66 | ||
@@ -268,10 +268,11 @@ int setup_ntlm_response(struct cifsSesInfo *ses) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 270 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
271 | void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | 271 | int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, |
272 | char *lnm_session_key) | 272 | char *lnm_session_key) |
273 | { | 273 | { |
274 | int i; | 274 | int i; |
275 | int rc; | ||
275 | char password_with_pad[CIFS_ENCPWD_SIZE]; | 276 | char password_with_pad[CIFS_ENCPWD_SIZE]; |
276 | 277 | ||
277 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | 278 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); |
@@ -282,7 +283,7 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
282 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); | 283 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); |
283 | memcpy(lnm_session_key, password_with_pad, | 284 | memcpy(lnm_session_key, password_with_pad, |
284 | CIFS_ENCPWD_SIZE); | 285 | CIFS_ENCPWD_SIZE); |
285 | return; | 286 | return 0; |
286 | } | 287 | } |
287 | 288 | ||
288 | /* calculate old style session key */ | 289 | /* calculate old style session key */ |
@@ -299,10 +300,9 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
299 | for (i = 0; i < CIFS_ENCPWD_SIZE; i++) | 300 | for (i = 0; i < CIFS_ENCPWD_SIZE; i++) |
300 | password_with_pad[i] = toupper(password_with_pad[i]); | 301 | password_with_pad[i] = toupper(password_with_pad[i]); |
301 | 302 | ||
302 | SMBencrypt(password_with_pad, cryptkey, lnm_session_key); | 303 | rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key); |
303 | 304 | ||
304 | /* clear password before we return/free memory */ | 305 | return rc; |
305 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | ||
306 | } | 306 | } |
307 | #endif /* CIFS_WEAK_PW_HASH */ | 307 | #endif /* CIFS_WEAK_PW_HASH */ |
308 | 308 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5c412b33cd7c..493b74ca5648 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -128,29 +128,22 @@ cifs_read_super(struct super_block *sb, void *data, | |||
128 | } | 128 | } |
129 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | 129 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; |
130 | 130 | ||
131 | #ifdef CONFIG_CIFS_DFS_UPCALL | 131 | /* |
132 | /* copy mount params to sb for use in submounts */ | 132 | * Copy mount params to sb for use in submounts. Better to do |
133 | /* BB: should we move this after the mount so we | 133 | * the copy here and deal with the error before cleanup gets |
134 | * do not have to do the copy on failed mounts? | 134 | * complicated post-mount. |
135 | * BB: May be it is better to do simple copy before | 135 | */ |
136 | * complex operation (mount), and in case of fail | ||
137 | * just exit instead of doing mount and attempting | ||
138 | * undo it if this copy fails?*/ | ||
139 | if (data) { | 136 | if (data) { |
140 | int len = strlen(data); | 137 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); |
141 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | ||
142 | if (cifs_sb->mountdata == NULL) { | 138 | if (cifs_sb->mountdata == NULL) { |
143 | bdi_destroy(&cifs_sb->bdi); | 139 | bdi_destroy(&cifs_sb->bdi); |
144 | kfree(sb->s_fs_info); | 140 | kfree(sb->s_fs_info); |
145 | sb->s_fs_info = NULL; | 141 | sb->s_fs_info = NULL; |
146 | return -ENOMEM; | 142 | return -ENOMEM; |
147 | } | 143 | } |
148 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
149 | cifs_sb->mountdata[len] = '\0'; | ||
150 | } | 144 | } |
151 | #endif | ||
152 | 145 | ||
153 | rc = cifs_mount(sb, cifs_sb, data, devname); | 146 | rc = cifs_mount(sb, cifs_sb, devname); |
154 | 147 | ||
155 | if (rc) { | 148 | if (rc) { |
156 | if (!silent) | 149 | if (!silent) |
@@ -163,7 +156,7 @@ cifs_read_super(struct super_block *sb, void *data, | |||
163 | sb->s_bdi = &cifs_sb->bdi; | 156 | sb->s_bdi = &cifs_sb->bdi; |
164 | sb->s_blocksize = CIFS_MAX_MSGSIZE; | 157 | sb->s_blocksize = CIFS_MAX_MSGSIZE; |
165 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ | 158 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ |
166 | inode = cifs_root_iget(sb, ROOT_I); | 159 | inode = cifs_root_iget(sb); |
167 | 160 | ||
168 | if (IS_ERR(inode)) { | 161 | if (IS_ERR(inode)) { |
169 | rc = PTR_ERR(inode); | 162 | rc = PTR_ERR(inode); |
@@ -184,12 +177,12 @@ cifs_read_super(struct super_block *sb, void *data, | |||
184 | else | 177 | else |
185 | sb->s_d_op = &cifs_dentry_ops; | 178 | sb->s_d_op = &cifs_dentry_ops; |
186 | 179 | ||
187 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 180 | #ifdef CIFS_NFSD_EXPORT |
188 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 181 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
189 | cFYI(1, "export ops supported"); | 182 | cFYI(1, "export ops supported"); |
190 | sb->s_export_op = &cifs_export_ops; | 183 | sb->s_export_op = &cifs_export_ops; |
191 | } | 184 | } |
192 | #endif /* EXPERIMENTAL */ | 185 | #endif /* CIFS_NFSD_EXPORT */ |
193 | 186 | ||
194 | return 0; | 187 | return 0; |
195 | 188 | ||
@@ -202,12 +195,10 @@ out_no_root: | |||
202 | 195 | ||
203 | out_mount_failed: | 196 | out_mount_failed: |
204 | if (cifs_sb) { | 197 | if (cifs_sb) { |
205 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
206 | if (cifs_sb->mountdata) { | 198 | if (cifs_sb->mountdata) { |
207 | kfree(cifs_sb->mountdata); | 199 | kfree(cifs_sb->mountdata); |
208 | cifs_sb->mountdata = NULL; | 200 | cifs_sb->mountdata = NULL; |
209 | } | 201 | } |
210 | #endif | ||
211 | unload_nls(cifs_sb->local_nls); | 202 | unload_nls(cifs_sb->local_nls); |
212 | bdi_destroy(&cifs_sb->bdi); | 203 | bdi_destroy(&cifs_sb->bdi); |
213 | kfree(cifs_sb); | 204 | kfree(cifs_sb); |
@@ -231,12 +222,10 @@ cifs_put_super(struct super_block *sb) | |||
231 | rc = cifs_umount(sb, cifs_sb); | 222 | rc = cifs_umount(sb, cifs_sb); |
232 | if (rc) | 223 | if (rc) |
233 | cERROR(1, "cifs_umount failed with return code %d", rc); | 224 | cERROR(1, "cifs_umount failed with return code %d", rc); |
234 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
235 | if (cifs_sb->mountdata) { | 225 | if (cifs_sb->mountdata) { |
236 | kfree(cifs_sb->mountdata); | 226 | kfree(cifs_sb->mountdata); |
237 | cifs_sb->mountdata = NULL; | 227 | cifs_sb->mountdata = NULL; |
238 | } | 228 | } |
239 | #endif | ||
240 | 229 | ||
241 | unload_nls(cifs_sb->local_nls); | 230 | unload_nls(cifs_sb->local_nls); |
242 | bdi_destroy(&cifs_sb->bdi); | 231 | bdi_destroy(&cifs_sb->bdi); |
@@ -618,16 +607,31 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | |||
618 | { | 607 | { |
619 | /* origin == SEEK_END => we must revalidate the cached file length */ | 608 | /* origin == SEEK_END => we must revalidate the cached file length */ |
620 | if (origin == SEEK_END) { | 609 | if (origin == SEEK_END) { |
621 | int retval; | 610 | int rc; |
622 | 611 | struct inode *inode = file->f_path.dentry->d_inode; | |
623 | /* some applications poll for the file length in this strange | 612 | |
624 | way so we must seek to end on non-oplocked files by | 613 | /* |
625 | setting the revalidate time to zero */ | 614 | * We need to be sure that all dirty pages are written and the |
626 | CIFS_I(file->f_path.dentry->d_inode)->time = 0; | 615 | * server has the newest file length. |
627 | 616 | */ | |
628 | retval = cifs_revalidate_file(file); | 617 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
629 | if (retval < 0) | 618 | inode->i_mapping->nrpages != 0) { |
630 | return (loff_t)retval; | 619 | rc = filemap_fdatawait(inode->i_mapping); |
620 | if (rc) { | ||
621 | mapping_set_error(inode->i_mapping, rc); | ||
622 | return rc; | ||
623 | } | ||
624 | } | ||
625 | /* | ||
626 | * Some applications poll for the file length in this strange | ||
627 | * way so we must seek to end on non-oplocked files by | ||
628 | * setting the revalidate time to zero. | ||
629 | */ | ||
630 | CIFS_I(inode)->time = 0; | ||
631 | |||
632 | rc = cifs_revalidate_file_attr(file); | ||
633 | if (rc < 0) | ||
634 | return (loff_t)rc; | ||
631 | } | 635 | } |
632 | return generic_file_llseek_unlocked(file, offset, origin); | 636 | return generic_file_llseek_unlocked(file, offset, origin); |
633 | } | 637 | } |
@@ -760,10 +764,11 @@ const struct file_operations cifs_file_strict_ops = { | |||
760 | }; | 764 | }; |
761 | 765 | ||
762 | const struct file_operations cifs_file_direct_ops = { | 766 | const struct file_operations cifs_file_direct_ops = { |
763 | /* no aio, no readv - | 767 | /* BB reevaluate whether they can be done with directio, no cache */ |
764 | BB reevaluate whether they can be done with directio, no cache */ | 768 | .read = do_sync_read, |
765 | .read = cifs_user_read, | 769 | .write = do_sync_write, |
766 | .write = cifs_user_write, | 770 | .aio_read = cifs_user_readv, |
771 | .aio_write = cifs_user_writev, | ||
767 | .open = cifs_open, | 772 | .open = cifs_open, |
768 | .release = cifs_close, | 773 | .release = cifs_close, |
769 | .lock = cifs_lock, | 774 | .lock = cifs_lock, |
@@ -815,10 +820,11 @@ const struct file_operations cifs_file_strict_nobrl_ops = { | |||
815 | }; | 820 | }; |
816 | 821 | ||
817 | const struct file_operations cifs_file_direct_nobrl_ops = { | 822 | const struct file_operations cifs_file_direct_nobrl_ops = { |
818 | /* no mmap, no aio, no readv - | 823 | /* BB reevaluate whether they can be done with directio, no cache */ |
819 | BB reevaluate whether they can be done with directio, no cache */ | 824 | .read = do_sync_read, |
820 | .read = cifs_user_read, | 825 | .write = do_sync_write, |
821 | .write = cifs_user_write, | 826 | .aio_read = cifs_user_readv, |
827 | .aio_write = cifs_user_writev, | ||
822 | .open = cifs_open, | 828 | .open = cifs_open, |
823 | .release = cifs_close, | 829 | .release = cifs_close, |
824 | .fsync = cifs_fsync, | 830 | .fsync = cifs_fsync, |
@@ -981,10 +987,10 @@ init_cifs(void) | |||
981 | int rc = 0; | 987 | int rc = 0; |
982 | cifs_proc_init(); | 988 | cifs_proc_init(); |
983 | INIT_LIST_HEAD(&cifs_tcp_ses_list); | 989 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
984 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 990 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ |
985 | INIT_LIST_HEAD(&GlobalDnotifyReqList); | 991 | INIT_LIST_HEAD(&GlobalDnotifyReqList); |
986 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); | 992 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); |
987 | #endif | 993 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ |
988 | /* | 994 | /* |
989 | * Initialize Global counters | 995 | * Initialize Global counters |
990 | */ | 996 | */ |
@@ -1033,22 +1039,33 @@ init_cifs(void) | |||
1033 | if (rc) | 1039 | if (rc) |
1034 | goto out_destroy_mids; | 1040 | goto out_destroy_mids; |
1035 | 1041 | ||
1036 | rc = register_filesystem(&cifs_fs_type); | ||
1037 | if (rc) | ||
1038 | goto out_destroy_request_bufs; | ||
1039 | #ifdef CONFIG_CIFS_UPCALL | 1042 | #ifdef CONFIG_CIFS_UPCALL |
1040 | rc = register_key_type(&cifs_spnego_key_type); | 1043 | rc = register_key_type(&cifs_spnego_key_type); |
1041 | if (rc) | 1044 | if (rc) |
1042 | goto out_unregister_filesystem; | 1045 | goto out_destroy_request_bufs; |
1043 | #endif | 1046 | #endif /* CONFIG_CIFS_UPCALL */ |
1047 | |||
1048 | #ifdef CONFIG_CIFS_ACL | ||
1049 | rc = init_cifs_idmap(); | ||
1050 | if (rc) | ||
1051 | goto out_register_key_type; | ||
1052 | #endif /* CONFIG_CIFS_ACL */ | ||
1053 | |||
1054 | rc = register_filesystem(&cifs_fs_type); | ||
1055 | if (rc) | ||
1056 | goto out_init_cifs_idmap; | ||
1044 | 1057 | ||
1045 | return 0; | 1058 | return 0; |
1046 | 1059 | ||
1047 | #ifdef CONFIG_CIFS_UPCALL | 1060 | out_init_cifs_idmap: |
1048 | out_unregister_filesystem: | 1061 | #ifdef CONFIG_CIFS_ACL |
1049 | unregister_filesystem(&cifs_fs_type); | 1062 | exit_cifs_idmap(); |
1063 | out_register_key_type: | ||
1050 | #endif | 1064 | #endif |
1065 | #ifdef CONFIG_CIFS_UPCALL | ||
1066 | unregister_key_type(&cifs_spnego_key_type); | ||
1051 | out_destroy_request_bufs: | 1067 | out_destroy_request_bufs: |
1068 | #endif | ||
1052 | cifs_destroy_request_bufs(); | 1069 | cifs_destroy_request_bufs(); |
1053 | out_destroy_mids: | 1070 | out_destroy_mids: |
1054 | cifs_destroy_mids(); | 1071 | cifs_destroy_mids(); |
@@ -1070,6 +1087,10 @@ exit_cifs(void) | |||
1070 | #ifdef CONFIG_CIFS_DFS_UPCALL | 1087 | #ifdef CONFIG_CIFS_DFS_UPCALL |
1071 | cifs_dfs_release_automount_timer(); | 1088 | cifs_dfs_release_automount_timer(); |
1072 | #endif | 1089 | #endif |
1090 | #ifdef CONFIG_CIFS_ACL | ||
1091 | cifs_destroy_idmaptrees(); | ||
1092 | exit_cifs_idmap(); | ||
1093 | #endif | ||
1073 | #ifdef CONFIG_CIFS_UPCALL | 1094 | #ifdef CONFIG_CIFS_UPCALL |
1074 | unregister_key_type(&cifs_spnego_key_type); | 1095 | unregister_key_type(&cifs_spnego_key_type); |
1075 | #endif | 1096 | #endif |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a9371b6578c0..64313f778ebf 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -47,7 +47,7 @@ extern void cifs_sb_deactive(struct super_block *sb); | |||
47 | 47 | ||
48 | /* Functions related to inodes */ | 48 | /* Functions related to inodes */ |
49 | extern const struct inode_operations cifs_dir_inode_ops; | 49 | extern const struct inode_operations cifs_dir_inode_ops; |
50 | extern struct inode *cifs_root_iget(struct super_block *, unsigned long); | 50 | extern struct inode *cifs_root_iget(struct super_block *); |
51 | extern int cifs_create(struct inode *, struct dentry *, int, | 51 | extern int cifs_create(struct inode *, struct dentry *, int, |
52 | struct nameidata *); | 52 | struct nameidata *); |
53 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, | 53 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, |
@@ -59,9 +59,11 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int); | |||
59 | extern int cifs_rmdir(struct inode *, struct dentry *); | 59 | extern int cifs_rmdir(struct inode *, struct dentry *); |
60 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | 60 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, |
61 | struct dentry *); | 61 | struct dentry *); |
62 | extern int cifs_revalidate_file_attr(struct file *filp); | ||
63 | extern int cifs_revalidate_dentry_attr(struct dentry *); | ||
62 | extern int cifs_revalidate_file(struct file *filp); | 64 | extern int cifs_revalidate_file(struct file *filp); |
63 | extern int cifs_revalidate_dentry(struct dentry *); | 65 | extern int cifs_revalidate_dentry(struct dentry *); |
64 | extern void cifs_invalidate_mapping(struct inode *inode); | 66 | extern int cifs_invalidate_mapping(struct inode *inode); |
65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 67 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
66 | extern int cifs_setattr(struct dentry *, struct iattr *); | 68 | extern int cifs_setattr(struct dentry *, struct iattr *); |
67 | 69 | ||
@@ -80,12 +82,12 @@ extern const struct file_operations cifs_file_strict_nobrl_ops; | |||
80 | extern int cifs_open(struct inode *inode, struct file *file); | 82 | extern int cifs_open(struct inode *inode, struct file *file); |
81 | extern int cifs_close(struct inode *inode, struct file *file); | 83 | extern int cifs_close(struct inode *inode, struct file *file); |
82 | extern int cifs_closedir(struct inode *inode, struct file *file); | 84 | extern int cifs_closedir(struct inode *inode, struct file *file); |
83 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, | 85 | extern ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
84 | size_t read_size, loff_t *poffset); | 86 | unsigned long nr_segs, loff_t pos); |
85 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | 87 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, |
86 | unsigned long nr_segs, loff_t pos); | 88 | unsigned long nr_segs, loff_t pos); |
87 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | 89 | extern ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
88 | size_t write_size, loff_t *poffset); | 90 | unsigned long nr_segs, loff_t pos); |
89 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | 91 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, |
90 | unsigned long nr_segs, loff_t pos); | 92 | unsigned long nr_segs, loff_t pos); |
91 | extern int cifs_lock(struct file *, int, struct file_lock *); | 93 | extern int cifs_lock(struct file *, int, struct file_lock *); |
@@ -123,9 +125,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
123 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 125 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
124 | extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | 126 | extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); |
125 | 127 | ||
126 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 128 | #ifdef CIFS_NFSD_EXPORT |
127 | extern const struct export_operations cifs_export_ops; | 129 | extern const struct export_operations cifs_export_ops; |
128 | #endif /* EXPERIMENTAL */ | 130 | #endif /* CIFS_NFSD_EXPORT */ |
129 | 131 | ||
130 | #define CIFS_VERSION "1.71" | 132 | #define CIFS_VERSION "1.72" |
131 | #endif /* _CIFSFS_H */ | 133 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a5d1106fcbde..76b4517e74b0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -274,7 +274,8 @@ struct cifsSesInfo { | |||
274 | int capabilities; | 274 | int capabilities; |
275 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for | 275 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for |
276 | TCP names - will ipv6 and sctp addresses fit? */ | 276 | TCP names - will ipv6 and sctp addresses fit? */ |
277 | char *user_name; | 277 | char *user_name; /* must not be null except during init of sess |
278 | and after mount option parsing we fill it */ | ||
278 | char *domainName; | 279 | char *domainName; |
279 | char *password; | 280 | char *password; |
280 | struct session_key auth_key; | 281 | struct session_key auth_key; |
@@ -780,10 +781,12 @@ GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock; | |||
780 | */ | 781 | */ |
781 | GLOBAL_EXTERN spinlock_t cifs_file_list_lock; | 782 | GLOBAL_EXTERN spinlock_t cifs_file_list_lock; |
782 | 783 | ||
784 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ | ||
783 | /* Outstanding dir notify requests */ | 785 | /* Outstanding dir notify requests */ |
784 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; | 786 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; |
785 | /* DirNotify response queue */ | 787 | /* DirNotify response queue */ |
786 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; | 788 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; |
789 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
787 | 790 | ||
788 | /* | 791 | /* |
789 | * Global transaction id (XID) information | 792 | * Global transaction id (XID) information |
@@ -830,6 +833,11 @@ GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | |||
830 | /* reconnect after this many failed echo attempts */ | 833 | /* reconnect after this many failed echo attempts */ |
831 | GLOBAL_EXTERN unsigned short echo_retries; | 834 | GLOBAL_EXTERN unsigned short echo_retries; |
832 | 835 | ||
836 | GLOBAL_EXTERN struct rb_root uidtree; | ||
837 | GLOBAL_EXTERN struct rb_root gidtree; | ||
838 | GLOBAL_EXTERN spinlock_t siduidlock; | ||
839 | GLOBAL_EXTERN spinlock_t sidgidlock; | ||
840 | |||
833 | void cifs_oplock_break(struct work_struct *work); | 841 | void cifs_oplock_break(struct work_struct *work); |
834 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); | 842 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); |
835 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); | 843 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index b5c8cc5d7a7f..de3aa285de03 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -397,9 +397,9 @@ | |||
397 | #define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ | 397 | #define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ |
398 | 398 | ||
399 | struct smb_hdr { | 399 | struct smb_hdr { |
400 | __u32 smb_buf_length; /* big endian on wire *//* BB length is only two | 400 | __be32 smb_buf_length; /* BB length is only two (rarely three) bytes, |
401 | or three bytes - with one or two byte type preceding it that are | 401 | with one or two byte "type" preceding it that will be |
402 | zero - we could mask the type byte off just in case BB */ | 402 | zero - we could mask the type byte off */ |
403 | __u8 Protocol[4]; | 403 | __u8 Protocol[4]; |
404 | __u8 Command; | 404 | __u8 Command; |
405 | union { | 405 | union { |
@@ -428,43 +428,28 @@ struct smb_hdr { | |||
428 | __u8 WordCount; | 428 | __u8 WordCount; |
429 | } __attribute__((packed)); | 429 | } __attribute__((packed)); |
430 | 430 | ||
431 | /* given a pointer to an smb_hdr retrieve a char pointer to the byte count */ | 431 | /* given a pointer to an smb_hdr, retrieve a void pointer to the ByteCount */ |
432 | #define BCC(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + \ | 432 | static inline void * |
433 | (2 * (smb_var)->WordCount)) | 433 | BCC(struct smb_hdr *smb) |
434 | { | ||
435 | return (void *)smb + sizeof(*smb) + 2 * smb->WordCount; | ||
436 | } | ||
434 | 437 | ||
435 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 438 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
436 | #define pByteArea(smb_var) (BCC(smb_var) + 2) | 439 | #define pByteArea(smb_var) (BCC(smb_var) + 2) |
437 | 440 | ||
438 | /* get the converted ByteCount for a SMB packet and return it */ | ||
439 | static inline __u16 | ||
440 | get_bcc(struct smb_hdr *hdr) | ||
441 | { | ||
442 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
443 | |||
444 | return get_unaligned(bc_ptr); | ||
445 | } | ||
446 | |||
447 | /* get the unconverted ByteCount for a SMB packet and return it */ | 441 | /* get the unconverted ByteCount for a SMB packet and return it */ |
448 | static inline __u16 | 442 | static inline __u16 |
449 | get_bcc_le(struct smb_hdr *hdr) | 443 | get_bcc(struct smb_hdr *hdr) |
450 | { | 444 | { |
451 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | 445 | __le16 *bc_ptr = (__le16 *)BCC(hdr); |
452 | 446 | ||
453 | return get_unaligned_le16(bc_ptr); | 447 | return get_unaligned_le16(bc_ptr); |
454 | } | 448 | } |
455 | 449 | ||
456 | /* set the ByteCount for a SMB packet in host-byte order */ | ||
457 | static inline void | ||
458 | put_bcc(__u16 count, struct smb_hdr *hdr) | ||
459 | { | ||
460 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
461 | |||
462 | put_unaligned(count, bc_ptr); | ||
463 | } | ||
464 | |||
465 | /* set the ByteCount for a SMB packet in little-endian */ | 450 | /* set the ByteCount for a SMB packet in little-endian */ |
466 | static inline void | 451 | static inline void |
467 | put_bcc_le(__u16 count, struct smb_hdr *hdr) | 452 | put_bcc(__u16 count, struct smb_hdr *hdr) |
468 | { | 453 | { |
469 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | 454 | __le16 *bc_ptr = (__le16 *)BCC(hdr); |
470 | 455 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8096f27ad9a8..6e69e06a30b3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -53,6 +53,9 @@ do { \ | |||
53 | cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ | 53 | cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ |
54 | __func__, curr_xid, (int)rc); \ | 54 | __func__, curr_xid, (int)rc); \ |
55 | } while (0) | 55 | } while (0) |
56 | extern int init_cifs_idmap(void); | ||
57 | extern void exit_cifs_idmap(void); | ||
58 | extern void cifs_destroy_idmaptrees(void); | ||
56 | extern char *build_path_from_dentry(struct dentry *); | 59 | extern char *build_path_from_dentry(struct dentry *); |
57 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | 60 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, |
58 | struct cifsTconInfo *tcon); | 61 | struct cifsTconInfo *tcon); |
@@ -90,7 +93,6 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
90 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | 93 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
91 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 94 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
92 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 95 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
93 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | ||
94 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 96 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
95 | struct TCP_Server_Info *server); | 97 | struct TCP_Server_Info *server); |
96 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 98 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
@@ -143,8 +145,10 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | |||
143 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); | 145 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); |
144 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | 146 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, |
145 | const char *, u32 *); | 147 | const char *, u32 *); |
148 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | ||
149 | const char *); | ||
146 | 150 | ||
147 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 151 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, |
148 | const char *); | 152 | const char *); |
149 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 153 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
150 | extern void cifs_dfs_release_automount_timer(void); | 154 | extern void cifs_dfs_release_automount_timer(void); |
@@ -304,12 +308,13 @@ extern int CIFSSMBUnixQuerySymLink(const int xid, | |||
304 | struct cifsTconInfo *tcon, | 308 | struct cifsTconInfo *tcon, |
305 | const unsigned char *searchName, char **syminfo, | 309 | const unsigned char *searchName, char **syminfo, |
306 | const struct nls_table *nls_codepage); | 310 | const struct nls_table *nls_codepage); |
311 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL | ||
307 | extern int CIFSSMBQueryReparseLinkInfo(const int xid, | 312 | extern int CIFSSMBQueryReparseLinkInfo(const int xid, |
308 | struct cifsTconInfo *tcon, | 313 | struct cifsTconInfo *tcon, |
309 | const unsigned char *searchName, | 314 | const unsigned char *searchName, |
310 | char *symlinkinfo, const int buflen, __u16 fid, | 315 | char *symlinkinfo, const int buflen, __u16 fid, |
311 | const struct nls_table *nls_codepage); | 316 | const struct nls_table *nls_codepage); |
312 | 317 | #endif /* temporarily unused until cifs_symlink fixed */ | |
313 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 318 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
314 | const char *fileName, const int disposition, | 319 | const char *fileName, const int disposition, |
315 | const int access_flags, const int omode, | 320 | const int access_flags, const int omode, |
@@ -348,8 +353,6 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | |||
348 | const unsigned char *searchName, __u64 *inode_number, | 353 | const unsigned char *searchName, __u64 *inode_number, |
349 | const struct nls_table *nls_codepage, | 354 | const struct nls_table *nls_codepage, |
350 | int remap_special_chars); | 355 | int remap_special_chars); |
351 | extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
352 | const struct nls_table *cp, int mapChars); | ||
353 | 356 | ||
354 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 357 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, |
355 | const __u16 netfid, const __u64 len, | 358 | const __u16 netfid, const __u64 len, |
@@ -383,9 +386,15 @@ extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | |||
383 | extern int calc_seckey(struct cifsSesInfo *); | 386 | extern int calc_seckey(struct cifsSesInfo *); |
384 | 387 | ||
385 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 388 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
386 | extern void calc_lanman_hash(const char *password, const char *cryptkey, | 389 | extern int calc_lanman_hash(const char *password, const char *cryptkey, |
387 | bool encrypt, char *lnm_session_key); | 390 | bool encrypt, char *lnm_session_key); |
388 | #endif /* CIFS_WEAK_PW_HASH */ | 391 | #endif /* CIFS_WEAK_PW_HASH */ |
392 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ | ||
393 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
394 | const int notify_subdirs, const __u16 netfid, | ||
395 | __u32 filter, struct file *file, int multishot, | ||
396 | const struct nls_table *nls_codepage); | ||
397 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
389 | extern int CIFSSMBCopy(int xid, | 398 | extern int CIFSSMBCopy(int xid, |
390 | struct cifsTconInfo *source_tcon, | 399 | struct cifsTconInfo *source_tcon, |
391 | const char *fromName, | 400 | const char *fromName, |
@@ -393,10 +402,6 @@ extern int CIFSSMBCopy(int xid, | |||
393 | const char *toName, const int flags, | 402 | const char *toName, const int flags, |
394 | const struct nls_table *nls_codepage, | 403 | const struct nls_table *nls_codepage, |
395 | int remap_special_chars); | 404 | int remap_special_chars); |
396 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
397 | const int notify_subdirs, const __u16 netfid, | ||
398 | __u32 filter, struct file *file, int multishot, | ||
399 | const struct nls_table *nls_codepage); | ||
400 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 405 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, |
401 | const unsigned char *searchName, | 406 | const unsigned char *searchName, |
402 | const unsigned char *ea_name, char *EAData, | 407 | const unsigned char *ea_name, char *EAData, |
@@ -427,9 +432,6 @@ extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, | |||
427 | struct cifs_sb_info *cifs_sb, int xid); | 432 | struct cifs_sb_info *cifs_sb, int xid); |
428 | extern int mdfour(unsigned char *, unsigned char *, int); | 433 | extern int mdfour(unsigned char *, unsigned char *, int); |
429 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); | 434 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); |
430 | extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | 435 | extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, |
431 | unsigned char *p24); | ||
432 | extern void E_P16(unsigned char *p14, unsigned char *p16); | ||
433 | extern void E_P24(unsigned char *p21, const unsigned char *c8, | ||
434 | unsigned char *p24); | 436 | unsigned char *p24); |
435 | #endif /* _CIFSPROTO_H */ | 437 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df959bae6728..83df937b814e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -339,12 +339,13 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) | 339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
340 | goto vt2_err; | 340 | goto vt2_err; |
341 | 341 | ||
342 | /* check that bcc is at least as big as parms + data */ | ||
343 | /* check that bcc is less than negotiated smb buffer */ | ||
344 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); | 342 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
345 | if (total_size >= 512) | 343 | if (total_size >= 512) |
346 | goto vt2_err; | 344 | goto vt2_err; |
347 | 345 | ||
346 | /* check that bcc is at least as big as parms + data, and that it is | ||
347 | * less than negotiated smb buffer | ||
348 | */ | ||
348 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); | 349 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
349 | if (total_size > get_bcc(&pSMB->hdr) || | 350 | if (total_size > get_bcc(&pSMB->hdr) || |
350 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) | 351 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
@@ -357,6 +358,13 @@ vt2_err: | |||
357 | return -EINVAL; | 358 | return -EINVAL; |
358 | } | 359 | } |
359 | 360 | ||
361 | static inline void inc_rfc1001_len(void *pSMB, int count) | ||
362 | { | ||
363 | struct smb_hdr *hdr = (struct smb_hdr *)pSMB; | ||
364 | |||
365 | be32_add_cpu(&hdr->smb_buf_length, count); | ||
366 | } | ||
367 | |||
360 | int | 368 | int |
361 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 369 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
362 | { | 370 | { |
@@ -409,7 +417,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
409 | count += strlen(protocols[i].name) + 1; | 417 | count += strlen(protocols[i].name) + 1; |
410 | /* null at end of source and target buffers anyway */ | 418 | /* null at end of source and target buffers anyway */ |
411 | } | 419 | } |
412 | pSMB->hdr.smb_buf_length += count; | 420 | inc_rfc1001_len(pSMB, count); |
413 | pSMB->ByteCount = cpu_to_le16(count); | 421 | pSMB->ByteCount = cpu_to_le16(count); |
414 | 422 | ||
415 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 423 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -541,10 +549,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
541 | server->secType = RawNTLMSSP; | 549 | server->secType = RawNTLMSSP; |
542 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 550 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
543 | server->secType = LANMAN; | 551 | server->secType = LANMAN; |
544 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
545 | else if (secFlags & CIFSSEC_MAY_PLNTXT) | ||
546 | server->secType = ?? | ||
547 | #endif */ | ||
548 | else { | 552 | else { |
549 | rc = -EOPNOTSUPP; | 553 | rc = -EOPNOTSUPP; |
550 | cERROR(1, "Invalid security type"); | 554 | cERROR(1, "Invalid security type"); |
@@ -578,7 +582,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
578 | 582 | ||
579 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | 583 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && |
580 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | 584 | (server->capabilities & CAP_EXTENDED_SECURITY)) { |
581 | count = pSMBr->ByteCount; | 585 | count = get_bcc(&pSMBr->hdr); |
582 | if (count < 16) { | 586 | if (count < 16) { |
583 | rc = -EIO; | 587 | rc = -EIO; |
584 | goto neg_err_exit; | 588 | goto neg_err_exit; |
@@ -732,9 +736,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
732 | smb->hdr.Tid = 0xffff; | 736 | smb->hdr.Tid = 0xffff; |
733 | smb->hdr.WordCount = 1; | 737 | smb->hdr.WordCount = 1; |
734 | put_unaligned_le16(1, &smb->EchoCount); | 738 | put_unaligned_le16(1, &smb->EchoCount); |
735 | put_bcc_le(1, &smb->hdr); | 739 | put_bcc(1, &smb->hdr); |
736 | smb->Data[0] = 'a'; | 740 | smb->Data[0] = 'a'; |
737 | smb->hdr.smb_buf_length += 3; | 741 | inc_rfc1001_len(smb, 3); |
738 | 742 | ||
739 | rc = cifs_call_async(server, (struct smb_hdr *)smb, | 743 | rc = cifs_call_async(server, (struct smb_hdr *)smb, |
740 | cifs_echo_callback, server); | 744 | cifs_echo_callback, server); |
@@ -852,7 +856,7 @@ PsxDelete: | |||
852 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 856 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
853 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); | 857 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); |
854 | pSMB->Reserved4 = 0; | 858 | pSMB->Reserved4 = 0; |
855 | pSMB->hdr.smb_buf_length += byte_count; | 859 | inc_rfc1001_len(pSMB, byte_count); |
856 | pSMB->ByteCount = cpu_to_le16(byte_count); | 860 | pSMB->ByteCount = cpu_to_le16(byte_count); |
857 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 861 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
858 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 862 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -898,7 +902,7 @@ DelFileRetry: | |||
898 | pSMB->SearchAttributes = | 902 | pSMB->SearchAttributes = |
899 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); | 903 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); |
900 | pSMB->BufferFormat = 0x04; | 904 | pSMB->BufferFormat = 0x04; |
901 | pSMB->hdr.smb_buf_length += name_len + 1; | 905 | inc_rfc1001_len(pSMB, name_len + 1); |
902 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 906 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
903 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 907 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
904 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 908 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -942,7 +946,7 @@ RmDirRetry: | |||
942 | } | 946 | } |
943 | 947 | ||
944 | pSMB->BufferFormat = 0x04; | 948 | pSMB->BufferFormat = 0x04; |
945 | pSMB->hdr.smb_buf_length += name_len + 1; | 949 | inc_rfc1001_len(pSMB, name_len + 1); |
946 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 950 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
947 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 951 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
948 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 952 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -985,7 +989,7 @@ MkDirRetry: | |||
985 | } | 989 | } |
986 | 990 | ||
987 | pSMB->BufferFormat = 0x04; | 991 | pSMB->BufferFormat = 0x04; |
988 | pSMB->hdr.smb_buf_length += name_len + 1; | 992 | inc_rfc1001_len(pSMB, name_len + 1); |
989 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 993 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
990 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 994 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
991 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 995 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -1063,7 +1067,7 @@ PsxCreat: | |||
1063 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 1067 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
1064 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); | 1068 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); |
1065 | pSMB->Reserved4 = 0; | 1069 | pSMB->Reserved4 = 0; |
1066 | pSMB->hdr.smb_buf_length += byte_count; | 1070 | inc_rfc1001_len(pSMB, byte_count); |
1067 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1071 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1068 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1072 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1069 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1073 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -1075,7 +1079,7 @@ PsxCreat: | |||
1075 | cFYI(1, "copying inode info"); | 1079 | cFYI(1, "copying inode info"); |
1076 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1080 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1077 | 1081 | ||
1078 | if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) { | 1082 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) { |
1079 | rc = -EIO; /* bad smb */ | 1083 | rc = -EIO; /* bad smb */ |
1080 | goto psx_create_err; | 1084 | goto psx_create_err; |
1081 | } | 1085 | } |
@@ -1096,7 +1100,7 @@ PsxCreat: | |||
1096 | pRetData->Type = cpu_to_le32(-1); /* unknown */ | 1100 | pRetData->Type = cpu_to_le32(-1); /* unknown */ |
1097 | cFYI(DBG2, "unknown type"); | 1101 | cFYI(DBG2, "unknown type"); |
1098 | } else { | 1102 | } else { |
1099 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) | 1103 | if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP) |
1100 | + sizeof(FILE_UNIX_BASIC_INFO)) { | 1104 | + sizeof(FILE_UNIX_BASIC_INFO)) { |
1101 | cERROR(1, "Open response data too small"); | 1105 | cERROR(1, "Open response data too small"); |
1102 | pRetData->Type = cpu_to_le32(-1); | 1106 | pRetData->Type = cpu_to_le32(-1); |
@@ -1228,7 +1232,7 @@ OldOpenRetry: | |||
1228 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | 1232 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); |
1229 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); | 1233 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); |
1230 | count += name_len; | 1234 | count += name_len; |
1231 | pSMB->hdr.smb_buf_length += count; | 1235 | inc_rfc1001_len(pSMB, count); |
1232 | 1236 | ||
1233 | pSMB->ByteCount = cpu_to_le16(count); | 1237 | pSMB->ByteCount = cpu_to_le16(count); |
1234 | /* long_op set to 1 to allow for oplock break timeouts */ | 1238 | /* long_op set to 1 to allow for oplock break timeouts */ |
@@ -1341,7 +1345,7 @@ openRetry: | |||
1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | 1345 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; |
1342 | 1346 | ||
1343 | count += name_len; | 1347 | count += name_len; |
1344 | pSMB->hdr.smb_buf_length += count; | 1348 | inc_rfc1001_len(pSMB, count); |
1345 | 1349 | ||
1346 | pSMB->ByteCount = cpu_to_le16(count); | 1350 | pSMB->ByteCount = cpu_to_le16(count); |
1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1351 | /* long_op set to 1 to allow for oplock break timeouts */ |
@@ -1426,7 +1430,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1426 | } | 1430 | } |
1427 | 1431 | ||
1428 | iov[0].iov_base = (char *)pSMB; | 1432 | iov[0].iov_base = (char *)pSMB; |
1429 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1433 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1430 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1434 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1431 | &resp_buf_type, CIFS_LOG_ERROR); | 1435 | &resp_buf_type, CIFS_LOG_ERROR); |
1432 | cifs_stats_inc(&tcon->num_reads); | 1436 | cifs_stats_inc(&tcon->num_reads); |
@@ -1560,7 +1564,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1560 | 1564 | ||
1561 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1565 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
1562 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1566 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
1563 | pSMB->hdr.smb_buf_length += byte_count; | 1567 | inc_rfc1001_len(pSMB, byte_count); |
1564 | 1568 | ||
1565 | if (wct == 14) | 1569 | if (wct == 14) |
1566 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1570 | pSMB->ByteCount = cpu_to_le16(byte_count); |
@@ -1644,11 +1648,12 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1644 | 1648 | ||
1645 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); | 1649 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); |
1646 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); | 1650 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); |
1647 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ | 1651 | /* header + 1 byte pad */ |
1652 | smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1; | ||
1648 | if (wct == 14) | 1653 | if (wct == 14) |
1649 | pSMB->hdr.smb_buf_length += count+1; | 1654 | inc_rfc1001_len(pSMB, count + 1); |
1650 | else /* wct == 12 */ | 1655 | else /* wct == 12 */ |
1651 | pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ | 1656 | inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */ |
1652 | if (wct == 14) | 1657 | if (wct == 14) |
1653 | pSMB->ByteCount = cpu_to_le16(count + 1); | 1658 | pSMB->ByteCount = cpu_to_le16(count + 1); |
1654 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { | 1659 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { |
@@ -1748,7 +1753,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1748 | /* oplock break */ | 1753 | /* oplock break */ |
1749 | count = 0; | 1754 | count = 0; |
1750 | } | 1755 | } |
1751 | pSMB->hdr.smb_buf_length += count; | 1756 | inc_rfc1001_len(pSMB, count); |
1752 | pSMB->ByteCount = cpu_to_le16(count); | 1757 | pSMB->ByteCount = cpu_to_le16(count); |
1753 | 1758 | ||
1754 | if (waitFlag) { | 1759 | if (waitFlag) { |
@@ -1839,14 +1844,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1839 | pSMB->Fid = smb_file_id; | 1844 | pSMB->Fid = smb_file_id; |
1840 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); | 1845 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); |
1841 | pSMB->Reserved4 = 0; | 1846 | pSMB->Reserved4 = 0; |
1842 | pSMB->hdr.smb_buf_length += byte_count; | 1847 | inc_rfc1001_len(pSMB, byte_count); |
1843 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1848 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1844 | if (waitFlag) { | 1849 | if (waitFlag) { |
1845 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1850 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1846 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1851 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1847 | } else { | 1852 | } else { |
1848 | iov[0].iov_base = (char *)pSMB; | 1853 | iov[0].iov_base = (char *)pSMB; |
1849 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1854 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1850 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1855 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1851 | &resp_buf_type, timeout); | 1856 | &resp_buf_type, timeout); |
1852 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | 1857 | pSMB = NULL; /* request buf already freed by SendReceive2. Do |
@@ -1862,7 +1867,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1862 | __u16 data_count; | 1867 | __u16 data_count; |
1863 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1868 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1864 | 1869 | ||
1865 | if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) { | 1870 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) { |
1866 | rc = -EIO; /* bad smb */ | 1871 | rc = -EIO; /* bad smb */ |
1867 | goto plk_err_exit; | 1872 | goto plk_err_exit; |
1868 | } | 1873 | } |
@@ -2012,7 +2017,7 @@ renameRetry: | |||
2012 | } | 2017 | } |
2013 | 2018 | ||
2014 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2019 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
2015 | pSMB->hdr.smb_buf_length += count; | 2020 | inc_rfc1001_len(pSMB, count); |
2016 | pSMB->ByteCount = cpu_to_le16(count); | 2021 | pSMB->ByteCount = cpu_to_le16(count); |
2017 | 2022 | ||
2018 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2023 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2092,7 +2097,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | |||
2092 | pSMB->InformationLevel = | 2097 | pSMB->InformationLevel = |
2093 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); | 2098 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); |
2094 | pSMB->Reserved4 = 0; | 2099 | pSMB->Reserved4 = 0; |
2095 | pSMB->hdr.smb_buf_length += byte_count; | 2100 | inc_rfc1001_len(pSMB, byte_count); |
2096 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2101 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2097 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 2102 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
2098 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2103 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2159,7 +2164,7 @@ copyRetry: | |||
2159 | } | 2164 | } |
2160 | 2165 | ||
2161 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2166 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
2162 | pSMB->hdr.smb_buf_length += count; | 2167 | inc_rfc1001_len(pSMB, count); |
2163 | pSMB->ByteCount = cpu_to_le16(count); | 2168 | pSMB->ByteCount = cpu_to_le16(count); |
2164 | 2169 | ||
2165 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2170 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2249,7 +2254,7 @@ createSymLinkRetry: | |||
2249 | pSMB->DataOffset = cpu_to_le16(offset); | 2254 | pSMB->DataOffset = cpu_to_le16(offset); |
2250 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); | 2255 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); |
2251 | pSMB->Reserved4 = 0; | 2256 | pSMB->Reserved4 = 0; |
2252 | pSMB->hdr.smb_buf_length += byte_count; | 2257 | inc_rfc1001_len(pSMB, byte_count); |
2253 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2258 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2254 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2259 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2255 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2260 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2335,7 +2340,7 @@ createHardLinkRetry: | |||
2335 | pSMB->DataOffset = cpu_to_le16(offset); | 2340 | pSMB->DataOffset = cpu_to_le16(offset); |
2336 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); | 2341 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); |
2337 | pSMB->Reserved4 = 0; | 2342 | pSMB->Reserved4 = 0; |
2338 | pSMB->hdr.smb_buf_length += byte_count; | 2343 | inc_rfc1001_len(pSMB, byte_count); |
2339 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2344 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2340 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2345 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2341 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2346 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2406,7 +2411,7 @@ winCreateHardLinkRetry: | |||
2406 | } | 2411 | } |
2407 | 2412 | ||
2408 | count = 1 /* string type byte */ + name_len + name_len2; | 2413 | count = 1 /* string type byte */ + name_len + name_len2; |
2409 | pSMB->hdr.smb_buf_length += count; | 2414 | inc_rfc1001_len(pSMB, count); |
2410 | pSMB->ByteCount = cpu_to_le16(count); | 2415 | pSMB->ByteCount = cpu_to_le16(count); |
2411 | 2416 | ||
2412 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2417 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2477,7 +2482,7 @@ querySymLinkRetry: | |||
2477 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2482 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2478 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); | 2483 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); |
2479 | pSMB->Reserved4 = 0; | 2484 | pSMB->Reserved4 = 0; |
2480 | pSMB->hdr.smb_buf_length += byte_count; | 2485 | inc_rfc1001_len(pSMB, byte_count); |
2481 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2486 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2482 | 2487 | ||
2483 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2488 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2489,7 +2494,7 @@ querySymLinkRetry: | |||
2489 | 2494 | ||
2490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2495 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2491 | /* BB also check enough total bytes returned */ | 2496 | /* BB also check enough total bytes returned */ |
2492 | if (rc || (pSMBr->ByteCount < 2)) | 2497 | if (rc || get_bcc(&pSMBr->hdr) < 2) |
2493 | rc = -EIO; | 2498 | rc = -EIO; |
2494 | else { | 2499 | else { |
2495 | bool is_unicode; | 2500 | bool is_unicode; |
@@ -2516,7 +2521,17 @@ querySymLinkRetry: | |||
2516 | return rc; | 2521 | return rc; |
2517 | } | 2522 | } |
2518 | 2523 | ||
2519 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2524 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL |
2525 | /* | ||
2526 | * Recent Windows versions now create symlinks more frequently | ||
2527 | * and they use the "reparse point" mechanism below. We can of course | ||
2528 | * do symlinks nicely to Samba and other servers which support the | ||
2529 | * CIFS Unix Extensions and we can also do SFU symlinks and "client only" | ||
2530 | * "MF" symlinks optionally, but for recent Windows we really need to | ||
2531 | * reenable the code below and fix the cifs_symlink callers to handle this. | ||
2532 | * In the interim this code has been moved to its own config option so | ||
2533 | * it is not compiled in by default until callers fixed up and more tested. | ||
2534 | */ | ||
2520 | int | 2535 | int |
2521 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2536 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
2522 | const unsigned char *searchName, | 2537 | const unsigned char *searchName, |
@@ -2561,14 +2576,14 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
2561 | } else { /* decode response */ | 2576 | } else { /* decode response */ |
2562 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); | 2577 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); |
2563 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); | 2578 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); |
2564 | if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { | 2579 | if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { |
2565 | /* BB also check enough total bytes returned */ | 2580 | /* BB also check enough total bytes returned */ |
2566 | rc = -EIO; /* bad smb */ | 2581 | rc = -EIO; /* bad smb */ |
2567 | goto qreparse_out; | 2582 | goto qreparse_out; |
2568 | } | 2583 | } |
2569 | if (data_count && (data_count < 2048)) { | 2584 | if (data_count && (data_count < 2048)) { |
2570 | char *end_of_smb = 2 /* sizeof byte count */ + | 2585 | char *end_of_smb = 2 /* sizeof byte count */ + |
2571 | pSMBr->ByteCount + (char *)&pSMBr->ByteCount; | 2586 | get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; |
2572 | 2587 | ||
2573 | struct reparse_data *reparse_buf = | 2588 | struct reparse_data *reparse_buf = |
2574 | (struct reparse_data *) | 2589 | (struct reparse_data *) |
@@ -2618,7 +2633,7 @@ qreparse_out: | |||
2618 | 2633 | ||
2619 | return rc; | 2634 | return rc; |
2620 | } | 2635 | } |
2621 | #endif /* CIFS_EXPERIMENTAL */ | 2636 | #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */ |
2622 | 2637 | ||
2623 | #ifdef CONFIG_CIFS_POSIX | 2638 | #ifdef CONFIG_CIFS_POSIX |
2624 | 2639 | ||
@@ -2814,7 +2829,7 @@ queryAclRetry: | |||
2814 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2829 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2815 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); | 2830 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); |
2816 | pSMB->Reserved4 = 0; | 2831 | pSMB->Reserved4 = 0; |
2817 | pSMB->hdr.smb_buf_length += byte_count; | 2832 | inc_rfc1001_len(pSMB, byte_count); |
2818 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2833 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2819 | 2834 | ||
2820 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2835 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2826,8 +2841,8 @@ queryAclRetry: | |||
2826 | /* decode response */ | 2841 | /* decode response */ |
2827 | 2842 | ||
2828 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2843 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2829 | if (rc || (pSMBr->ByteCount < 2)) | ||
2830 | /* BB also check enough total bytes returned */ | 2844 | /* BB also check enough total bytes returned */ |
2845 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
2831 | rc = -EIO; /* bad smb */ | 2846 | rc = -EIO; /* bad smb */ |
2832 | else { | 2847 | else { |
2833 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 2848 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -2908,7 +2923,7 @@ setAclRetry: | |||
2908 | pSMB->ParameterCount = cpu_to_le16(params); | 2923 | pSMB->ParameterCount = cpu_to_le16(params); |
2909 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 2924 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
2910 | pSMB->Reserved4 = 0; | 2925 | pSMB->Reserved4 = 0; |
2911 | pSMB->hdr.smb_buf_length += byte_count; | 2926 | inc_rfc1001_len(pSMB, byte_count); |
2912 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2927 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2913 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2928 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2914 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2929 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2966,7 +2981,7 @@ GetExtAttrRetry: | |||
2966 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); | 2981 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); |
2967 | pSMB->Pad = 0; | 2982 | pSMB->Pad = 0; |
2968 | pSMB->Fid = netfid; | 2983 | pSMB->Fid = netfid; |
2969 | pSMB->hdr.smb_buf_length += byte_count; | 2984 | inc_rfc1001_len(pSMB, byte_count); |
2970 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | 2985 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); |
2971 | 2986 | ||
2972 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2987 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2976,8 +2991,8 @@ GetExtAttrRetry: | |||
2976 | } else { | 2991 | } else { |
2977 | /* decode response */ | 2992 | /* decode response */ |
2978 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2993 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2979 | if (rc || (pSMBr->ByteCount < 2)) | ||
2980 | /* BB also check enough total bytes returned */ | 2994 | /* BB also check enough total bytes returned */ |
2995 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
2981 | /* If rc should we check for EOPNOSUPP and | 2996 | /* If rc should we check for EOPNOSUPP and |
2982 | disable the srvino flag? or in caller? */ | 2997 | disable the srvino flag? or in caller? */ |
2983 | rc = -EIO; /* bad smb */ | 2998 | rc = -EIO; /* bad smb */ |
@@ -3052,6 +3067,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3052 | char *end_of_smb; | 3067 | char *end_of_smb; |
3053 | __u32 data_count, data_offset, parm_count, parm_offset; | 3068 | __u32 data_count, data_offset, parm_count, parm_offset; |
3054 | struct smb_com_ntransact_rsp *pSMBr; | 3069 | struct smb_com_ntransact_rsp *pSMBr; |
3070 | u16 bcc; | ||
3055 | 3071 | ||
3056 | *pdatalen = 0; | 3072 | *pdatalen = 0; |
3057 | *pparmlen = 0; | 3073 | *pparmlen = 0; |
@@ -3061,8 +3077,8 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3061 | 3077 | ||
3062 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | 3078 | pSMBr = (struct smb_com_ntransact_rsp *)buf; |
3063 | 3079 | ||
3064 | /* ByteCount was converted from little endian in SendReceive */ | 3080 | bcc = get_bcc(&pSMBr->hdr); |
3065 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | 3081 | end_of_smb = 2 /* sizeof byte count */ + bcc + |
3066 | (char *)&pSMBr->ByteCount; | 3082 | (char *)&pSMBr->ByteCount; |
3067 | 3083 | ||
3068 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 3084 | data_offset = le32_to_cpu(pSMBr->DataOffset); |
@@ -3088,7 +3104,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3088 | *ppdata, data_count, (data_count + *ppdata), | 3104 | *ppdata, data_count, (data_count + *ppdata), |
3089 | end_of_smb, pSMBr); | 3105 | end_of_smb, pSMBr); |
3090 | return -EINVAL; | 3106 | return -EINVAL; |
3091 | } else if (parm_count + data_count > pSMBr->ByteCount) { | 3107 | } else if (parm_count + data_count > bcc) { |
3092 | cFYI(1, "parm count and data count larger than SMB"); | 3108 | cFYI(1, "parm count and data count larger than SMB"); |
3093 | return -EINVAL; | 3109 | return -EINVAL; |
3094 | } | 3110 | } |
@@ -3124,9 +3140,9 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3124 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | | 3140 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | |
3125 | CIFS_ACL_DACL); | 3141 | CIFS_ACL_DACL); |
3126 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ | 3142 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ |
3127 | pSMB->hdr.smb_buf_length += 11; | 3143 | inc_rfc1001_len(pSMB, 11); |
3128 | iov[0].iov_base = (char *)pSMB; | 3144 | iov[0].iov_base = (char *)pSMB; |
3129 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3145 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
3130 | 3146 | ||
3131 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3147 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3132 | 0); | 3148 | 0); |
@@ -3235,10 +3251,9 @@ setCifsAclRetry: | |||
3235 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | 3251 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, |
3236 | (char *) pntsd, | 3252 | (char *) pntsd, |
3237 | acllen); | 3253 | acllen); |
3238 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | 3254 | inc_rfc1001_len(pSMB, byte_count + data_count); |
3239 | |||
3240 | } else | 3255 | } else |
3241 | pSMB->hdr.smb_buf_length += byte_count; | 3256 | inc_rfc1001_len(pSMB, byte_count); |
3242 | 3257 | ||
3243 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3258 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3244 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3259 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3289,7 +3304,7 @@ QInfRetry: | |||
3289 | } | 3304 | } |
3290 | pSMB->BufferFormat = 0x04; | 3305 | pSMB->BufferFormat = 0x04; |
3291 | name_len++; /* account for buffer type byte */ | 3306 | name_len++; /* account for buffer type byte */ |
3292 | pSMB->hdr.smb_buf_length += (__u16) name_len; | 3307 | inc_rfc1001_len(pSMB, (__u16)name_len); |
3293 | pSMB->ByteCount = cpu_to_le16(name_len); | 3308 | pSMB->ByteCount = cpu_to_le16(name_len); |
3294 | 3309 | ||
3295 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3310 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3364,7 +3379,7 @@ QFileInfoRetry: | |||
3364 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3379 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3365 | pSMB->Pad = 0; | 3380 | pSMB->Pad = 0; |
3366 | pSMB->Fid = netfid; | 3381 | pSMB->Fid = netfid; |
3367 | pSMB->hdr.smb_buf_length += byte_count; | 3382 | inc_rfc1001_len(pSMB, byte_count); |
3368 | 3383 | ||
3369 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3384 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3370 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3385 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3375,7 +3390,7 @@ QFileInfoRetry: | |||
3375 | 3390 | ||
3376 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3391 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3377 | rc = -EIO; | 3392 | rc = -EIO; |
3378 | else if (pSMBr->ByteCount < 40) | 3393 | else if (get_bcc(&pSMBr->hdr) < 40) |
3379 | rc = -EIO; /* bad smb */ | 3394 | rc = -EIO; /* bad smb */ |
3380 | else if (pFindData) { | 3395 | else if (pFindData) { |
3381 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3396 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -3451,7 +3466,7 @@ QPathInfoRetry: | |||
3451 | else | 3466 | else |
3452 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3467 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3453 | pSMB->Reserved4 = 0; | 3468 | pSMB->Reserved4 = 0; |
3454 | pSMB->hdr.smb_buf_length += byte_count; | 3469 | inc_rfc1001_len(pSMB, byte_count); |
3455 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3470 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3456 | 3471 | ||
3457 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3472 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3463,9 +3478,9 @@ QPathInfoRetry: | |||
3463 | 3478 | ||
3464 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3479 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3465 | rc = -EIO; | 3480 | rc = -EIO; |
3466 | else if (!legacy && (pSMBr->ByteCount < 40)) | 3481 | else if (!legacy && get_bcc(&pSMBr->hdr) < 40) |
3467 | rc = -EIO; /* bad smb */ | 3482 | rc = -EIO; /* bad smb */ |
3468 | else if (legacy && (pSMBr->ByteCount < 24)) | 3483 | else if (legacy && get_bcc(&pSMBr->hdr) < 24) |
3469 | rc = -EIO; /* 24 or 26 expected but we do not read | 3484 | rc = -EIO; /* 24 or 26 expected but we do not read |
3470 | last field */ | 3485 | last field */ |
3471 | else if (pFindData) { | 3486 | else if (pFindData) { |
@@ -3532,7 +3547,7 @@ UnixQFileInfoRetry: | |||
3532 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3547 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3533 | pSMB->Pad = 0; | 3548 | pSMB->Pad = 0; |
3534 | pSMB->Fid = netfid; | 3549 | pSMB->Fid = netfid; |
3535 | pSMB->hdr.smb_buf_length += byte_count; | 3550 | inc_rfc1001_len(pSMB, byte_count); |
3536 | 3551 | ||
3537 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3552 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3538 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3553 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3541,7 +3556,7 @@ UnixQFileInfoRetry: | |||
3541 | } else { /* decode response */ | 3556 | } else { /* decode response */ |
3542 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3557 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3543 | 3558 | ||
3544 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3559 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3545 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3560 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3546 | "Unix Extensions can be disabled on mount " | 3561 | "Unix Extensions can be disabled on mount " |
3547 | "by specifying the nosfu mount option."); | 3562 | "by specifying the nosfu mount option."); |
@@ -3617,7 +3632,7 @@ UnixQPathInfoRetry: | |||
3617 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3632 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3618 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3633 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3619 | pSMB->Reserved4 = 0; | 3634 | pSMB->Reserved4 = 0; |
3620 | pSMB->hdr.smb_buf_length += byte_count; | 3635 | inc_rfc1001_len(pSMB, byte_count); |
3621 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3636 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3622 | 3637 | ||
3623 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3638 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3627,7 +3642,7 @@ UnixQPathInfoRetry: | |||
3627 | } else { /* decode response */ | 3642 | } else { /* decode response */ |
3628 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3643 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3629 | 3644 | ||
3630 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3645 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3631 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3646 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3632 | "Unix Extensions can be disabled on mount " | 3647 | "Unix Extensions can be disabled on mount " |
3633 | "by specifying the nosfu mount option."); | 3648 | "by specifying the nosfu mount option."); |
@@ -3731,7 +3746,7 @@ findFirstRetry: | |||
3731 | 3746 | ||
3732 | /* BB what should we set StorageType to? Does it matter? BB */ | 3747 | /* BB what should we set StorageType to? Does it matter? BB */ |
3733 | pSMB->SearchStorageType = 0; | 3748 | pSMB->SearchStorageType = 0; |
3734 | pSMB->hdr.smb_buf_length += byte_count; | 3749 | inc_rfc1001_len(pSMB, byte_count); |
3735 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3750 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3736 | 3751 | ||
3737 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3752 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3860,7 +3875,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3860 | byte_count = params + 1 /* pad */ ; | 3875 | byte_count = params + 1 /* pad */ ; |
3861 | pSMB->TotalParameterCount = cpu_to_le16(params); | 3876 | pSMB->TotalParameterCount = cpu_to_le16(params); |
3862 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3877 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3863 | pSMB->hdr.smb_buf_length += byte_count; | 3878 | inc_rfc1001_len(pSMB, byte_count); |
3864 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3879 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3865 | 3880 | ||
3866 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3881 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4022,7 +4037,7 @@ GetInodeNumberRetry: | |||
4022 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 4037 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
4023 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); | 4038 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); |
4024 | pSMB->Reserved4 = 0; | 4039 | pSMB->Reserved4 = 0; |
4025 | pSMB->hdr.smb_buf_length += byte_count; | 4040 | inc_rfc1001_len(pSMB, byte_count); |
4026 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4041 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4027 | 4042 | ||
4028 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4043 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4032,8 +4047,8 @@ GetInodeNumberRetry: | |||
4032 | } else { | 4047 | } else { |
4033 | /* decode response */ | 4048 | /* decode response */ |
4034 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4049 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4035 | if (rc || (pSMBr->ByteCount < 2)) | ||
4036 | /* BB also check enough total bytes returned */ | 4050 | /* BB also check enough total bytes returned */ |
4051 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
4037 | /* If rc should we check for EOPNOSUPP and | 4052 | /* If rc should we check for EOPNOSUPP and |
4038 | disable the srvino flag? or in caller? */ | 4053 | disable the srvino flag? or in caller? */ |
4039 | rc = -EIO; /* bad smb */ | 4054 | rc = -EIO; /* bad smb */ |
@@ -4246,7 +4261,7 @@ getDFSRetry: | |||
4246 | pSMB->ParameterCount = cpu_to_le16(params); | 4261 | pSMB->ParameterCount = cpu_to_le16(params); |
4247 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4262 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4248 | pSMB->MaxReferralLevel = cpu_to_le16(3); | 4263 | pSMB->MaxReferralLevel = cpu_to_le16(3); |
4249 | pSMB->hdr.smb_buf_length += byte_count; | 4264 | inc_rfc1001_len(pSMB, byte_count); |
4250 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4265 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4251 | 4266 | ||
4252 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 4267 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -4258,13 +4273,13 @@ getDFSRetry: | |||
4258 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4273 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4259 | 4274 | ||
4260 | /* BB Also check if enough total bytes returned? */ | 4275 | /* BB Also check if enough total bytes returned? */ |
4261 | if (rc || (pSMBr->ByteCount < 17)) { | 4276 | if (rc || get_bcc(&pSMBr->hdr) < 17) { |
4262 | rc = -EIO; /* bad smb */ | 4277 | rc = -EIO; /* bad smb */ |
4263 | goto GetDFSRefExit; | 4278 | goto GetDFSRefExit; |
4264 | } | 4279 | } |
4265 | 4280 | ||
4266 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", | 4281 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", |
4267 | pSMBr->ByteCount, | 4282 | get_bcc(&pSMBr->hdr), |
4268 | le16_to_cpu(pSMBr->t2.DataOffset)); | 4283 | le16_to_cpu(pSMBr->t2.DataOffset)); |
4269 | 4284 | ||
4270 | /* parse returned result into more usable form */ | 4285 | /* parse returned result into more usable form */ |
@@ -4320,7 +4335,7 @@ oldQFSInfoRetry: | |||
4320 | pSMB->Reserved3 = 0; | 4335 | pSMB->Reserved3 = 0; |
4321 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4336 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4322 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | 4337 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); |
4323 | pSMB->hdr.smb_buf_length += byte_count; | 4338 | inc_rfc1001_len(pSMB, byte_count); |
4324 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4339 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4325 | 4340 | ||
4326 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4341 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4330,12 +4345,12 @@ oldQFSInfoRetry: | |||
4330 | } else { /* decode response */ | 4345 | } else { /* decode response */ |
4331 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4346 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4332 | 4347 | ||
4333 | if (rc || (pSMBr->ByteCount < 18)) | 4348 | if (rc || get_bcc(&pSMBr->hdr) < 18) |
4334 | rc = -EIO; /* bad smb */ | 4349 | rc = -EIO; /* bad smb */ |
4335 | else { | 4350 | else { |
4336 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4351 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
4337 | cFYI(1, "qfsinf resp BCC: %d Offset %d", | 4352 | cFYI(1, "qfsinf resp BCC: %d Offset %d", |
4338 | pSMBr->ByteCount, data_offset); | 4353 | get_bcc(&pSMBr->hdr), data_offset); |
4339 | 4354 | ||
4340 | response_data = (FILE_SYSTEM_ALLOC_INFO *) | 4355 | response_data = (FILE_SYSTEM_ALLOC_INFO *) |
4341 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | 4356 | (((char *) &pSMBr->hdr.Protocol) + data_offset); |
@@ -4399,7 +4414,7 @@ QFSInfoRetry: | |||
4399 | pSMB->Reserved3 = 0; | 4414 | pSMB->Reserved3 = 0; |
4400 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4415 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4401 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); | 4416 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); |
4402 | pSMB->hdr.smb_buf_length += byte_count; | 4417 | inc_rfc1001_len(pSMB, byte_count); |
4403 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4418 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4404 | 4419 | ||
4405 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4420 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4409,7 +4424,7 @@ QFSInfoRetry: | |||
4409 | } else { /* decode response */ | 4424 | } else { /* decode response */ |
4410 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4425 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4411 | 4426 | ||
4412 | if (rc || (pSMBr->ByteCount < 24)) | 4427 | if (rc || get_bcc(&pSMBr->hdr) < 24) |
4413 | rc = -EIO; /* bad smb */ | 4428 | rc = -EIO; /* bad smb */ |
4414 | else { | 4429 | else { |
4415 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4430 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4479,7 +4494,7 @@ QFSAttributeRetry: | |||
4479 | pSMB->Reserved3 = 0; | 4494 | pSMB->Reserved3 = 0; |
4480 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4495 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4481 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); | 4496 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); |
4482 | pSMB->hdr.smb_buf_length += byte_count; | 4497 | inc_rfc1001_len(pSMB, byte_count); |
4483 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4498 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4484 | 4499 | ||
4485 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4500 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4489,7 +4504,7 @@ QFSAttributeRetry: | |||
4489 | } else { /* decode response */ | 4504 | } else { /* decode response */ |
4490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4505 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4491 | 4506 | ||
4492 | if (rc || (pSMBr->ByteCount < 13)) { | 4507 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4493 | /* BB also check if enough bytes returned */ | 4508 | /* BB also check if enough bytes returned */ |
4494 | rc = -EIO; /* bad smb */ | 4509 | rc = -EIO; /* bad smb */ |
4495 | } else { | 4510 | } else { |
@@ -4550,7 +4565,7 @@ QFSDeviceRetry: | |||
4550 | pSMB->Reserved3 = 0; | 4565 | pSMB->Reserved3 = 0; |
4551 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4566 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4552 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); | 4567 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); |
4553 | pSMB->hdr.smb_buf_length += byte_count; | 4568 | inc_rfc1001_len(pSMB, byte_count); |
4554 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4569 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4555 | 4570 | ||
4556 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4571 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4560,7 +4575,8 @@ QFSDeviceRetry: | |||
4560 | } else { /* decode response */ | 4575 | } else { /* decode response */ |
4561 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4576 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4562 | 4577 | ||
4563 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) | 4578 | if (rc || get_bcc(&pSMBr->hdr) < |
4579 | sizeof(FILE_SYSTEM_DEVICE_INFO)) | ||
4564 | rc = -EIO; /* bad smb */ | 4580 | rc = -EIO; /* bad smb */ |
4565 | else { | 4581 | else { |
4566 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4582 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4619,7 +4635,7 @@ QFSUnixRetry: | |||
4619 | pSMB->Reserved3 = 0; | 4635 | pSMB->Reserved3 = 0; |
4620 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4636 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4621 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); | 4637 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); |
4622 | pSMB->hdr.smb_buf_length += byte_count; | 4638 | inc_rfc1001_len(pSMB, byte_count); |
4623 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4639 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4624 | 4640 | ||
4625 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4641 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4629,7 +4645,7 @@ QFSUnixRetry: | |||
4629 | } else { /* decode response */ | 4645 | } else { /* decode response */ |
4630 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4646 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4631 | 4647 | ||
4632 | if (rc || (pSMBr->ByteCount < 13)) { | 4648 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4633 | rc = -EIO; /* bad smb */ | 4649 | rc = -EIO; /* bad smb */ |
4634 | } else { | 4650 | } else { |
4635 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4651 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4702,7 +4718,7 @@ SETFSUnixRetry: | |||
4702 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | 4718 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); |
4703 | pSMB->ClientUnixCap = cpu_to_le64(cap); | 4719 | pSMB->ClientUnixCap = cpu_to_le64(cap); |
4704 | 4720 | ||
4705 | pSMB->hdr.smb_buf_length += byte_count; | 4721 | inc_rfc1001_len(pSMB, byte_count); |
4706 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4722 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4707 | 4723 | ||
4708 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4724 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4764,7 +4780,7 @@ QFSPosixRetry: | |||
4764 | pSMB->Reserved3 = 0; | 4780 | pSMB->Reserved3 = 0; |
4765 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4781 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4766 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); | 4782 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); |
4767 | pSMB->hdr.smb_buf_length += byte_count; | 4783 | inc_rfc1001_len(pSMB, byte_count); |
4768 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4784 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4769 | 4785 | ||
4770 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4786 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4774,7 +4790,7 @@ QFSPosixRetry: | |||
4774 | } else { /* decode response */ | 4790 | } else { /* decode response */ |
4775 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4791 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4776 | 4792 | ||
4777 | if (rc || (pSMBr->ByteCount < 13)) { | 4793 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4778 | rc = -EIO; /* bad smb */ | 4794 | rc = -EIO; /* bad smb */ |
4779 | } else { | 4795 | } else { |
4780 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4796 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4890,7 +4906,7 @@ SetEOFRetry: | |||
4890 | pSMB->ParameterCount = cpu_to_le16(params); | 4906 | pSMB->ParameterCount = cpu_to_le16(params); |
4891 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4907 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4892 | pSMB->Reserved4 = 0; | 4908 | pSMB->Reserved4 = 0; |
4893 | pSMB->hdr.smb_buf_length += byte_count; | 4909 | inc_rfc1001_len(pSMB, byte_count); |
4894 | parm_data->FileSize = cpu_to_le64(size); | 4910 | parm_data->FileSize = cpu_to_le64(size); |
4895 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4911 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4896 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4912 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4969,7 +4985,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4969 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); | 4985 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); |
4970 | } | 4986 | } |
4971 | pSMB->Reserved4 = 0; | 4987 | pSMB->Reserved4 = 0; |
4972 | pSMB->hdr.smb_buf_length += byte_count; | 4988 | inc_rfc1001_len(pSMB, byte_count); |
4973 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4989 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4974 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 4990 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4975 | if (rc) { | 4991 | if (rc) { |
@@ -5037,7 +5053,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5037 | else | 5053 | else |
5038 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5054 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5039 | pSMB->Reserved4 = 0; | 5055 | pSMB->Reserved4 = 0; |
5040 | pSMB->hdr.smb_buf_length += byte_count; | 5056 | inc_rfc1001_len(pSMB, byte_count); |
5041 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5057 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5042 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5058 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5043 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5059 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5096,7 +5112,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | |||
5096 | pSMB->Fid = fid; | 5112 | pSMB->Fid = fid; |
5097 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); | 5113 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); |
5098 | pSMB->Reserved4 = 0; | 5114 | pSMB->Reserved4 = 0; |
5099 | pSMB->hdr.smb_buf_length += byte_count; | 5115 | inc_rfc1001_len(pSMB, byte_count); |
5100 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5116 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5101 | *data_offset = delete_file ? 1 : 0; | 5117 | *data_offset = delete_file ? 1 : 0; |
5102 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5118 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5169,7 +5185,7 @@ SetTimesRetry: | |||
5169 | else | 5185 | else |
5170 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5186 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5171 | pSMB->Reserved4 = 0; | 5187 | pSMB->Reserved4 = 0; |
5172 | pSMB->hdr.smb_buf_length += byte_count; | 5188 | inc_rfc1001_len(pSMB, byte_count); |
5173 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5189 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5174 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5190 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5175 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5191 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5221,7 +5237,7 @@ SetAttrLgcyRetry: | |||
5221 | } | 5237 | } |
5222 | pSMB->attr = cpu_to_le16(dos_attrs); | 5238 | pSMB->attr = cpu_to_le16(dos_attrs); |
5223 | pSMB->BufferFormat = 0x04; | 5239 | pSMB->BufferFormat = 0x04; |
5224 | pSMB->hdr.smb_buf_length += name_len + 1; | 5240 | inc_rfc1001_len(pSMB, name_len + 1); |
5225 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 5241 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
5226 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5242 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5227 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5243 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5326,7 +5342,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5326 | pSMB->Fid = fid; | 5342 | pSMB->Fid = fid; |
5327 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5343 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5328 | pSMB->Reserved4 = 0; | 5344 | pSMB->Reserved4 = 0; |
5329 | pSMB->hdr.smb_buf_length += byte_count; | 5345 | inc_rfc1001_len(pSMB, byte_count); |
5330 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5346 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5331 | 5347 | ||
5332 | cifs_fill_unix_set_info(data_offset, args); | 5348 | cifs_fill_unix_set_info(data_offset, args); |
@@ -5402,7 +5418,7 @@ setPermsRetry: | |||
5402 | pSMB->TotalDataCount = pSMB->DataCount; | 5418 | pSMB->TotalDataCount = pSMB->DataCount; |
5403 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5419 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5404 | pSMB->Reserved4 = 0; | 5420 | pSMB->Reserved4 = 0; |
5405 | pSMB->hdr.smb_buf_length += byte_count; | 5421 | inc_rfc1001_len(pSMB, byte_count); |
5406 | 5422 | ||
5407 | cifs_fill_unix_set_info(data_offset, args); | 5423 | cifs_fill_unix_set_info(data_offset, args); |
5408 | 5424 | ||
@@ -5418,79 +5434,6 @@ setPermsRetry: | |||
5418 | return rc; | 5434 | return rc; |
5419 | } | 5435 | } |
5420 | 5436 | ||
5421 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
5422 | const int notify_subdirs, const __u16 netfid, | ||
5423 | __u32 filter, struct file *pfile, int multishot, | ||
5424 | const struct nls_table *nls_codepage) | ||
5425 | { | ||
5426 | int rc = 0; | ||
5427 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
5428 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
5429 | struct dir_notify_req *dnotify_req; | ||
5430 | int bytes_returned; | ||
5431 | |||
5432 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
5433 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
5434 | (void **) &pSMBr); | ||
5435 | if (rc) | ||
5436 | return rc; | ||
5437 | |||
5438 | pSMB->TotalParameterCount = 0 ; | ||
5439 | pSMB->TotalDataCount = 0; | ||
5440 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
5441 | /* BB find exact data count max from sess structure BB */ | ||
5442 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
5443 | /* BB VERIFY verify which is correct for above BB */ | ||
5444 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
5445 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
5446 | |||
5447 | pSMB->MaxSetupCount = 4; | ||
5448 | pSMB->Reserved = 0; | ||
5449 | pSMB->ParameterOffset = 0; | ||
5450 | pSMB->DataCount = 0; | ||
5451 | pSMB->DataOffset = 0; | ||
5452 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
5453 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
5454 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5455 | if (notify_subdirs) | ||
5456 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
5457 | pSMB->Reserved2 = 0; | ||
5458 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
5459 | pSMB->Fid = netfid; /* file handle always le */ | ||
5460 | pSMB->ByteCount = 0; | ||
5461 | |||
5462 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
5463 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
5464 | CIFS_ASYNC_OP); | ||
5465 | if (rc) { | ||
5466 | cFYI(1, "Error in Notify = %d", rc); | ||
5467 | } else { | ||
5468 | /* Add file to outstanding requests */ | ||
5469 | /* BB change to kmem cache alloc */ | ||
5470 | dnotify_req = kmalloc( | ||
5471 | sizeof(struct dir_notify_req), | ||
5472 | GFP_KERNEL); | ||
5473 | if (dnotify_req) { | ||
5474 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
5475 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
5476 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
5477 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
5478 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
5479 | dnotify_req->netfid = netfid; | ||
5480 | dnotify_req->pfile = pfile; | ||
5481 | dnotify_req->filter = filter; | ||
5482 | dnotify_req->multishot = multishot; | ||
5483 | spin_lock(&GlobalMid_Lock); | ||
5484 | list_add_tail(&dnotify_req->lhead, | ||
5485 | &GlobalDnotifyReqList); | ||
5486 | spin_unlock(&GlobalMid_Lock); | ||
5487 | } else | ||
5488 | rc = -ENOMEM; | ||
5489 | } | ||
5490 | cifs_buf_release(pSMB); | ||
5491 | return rc; | ||
5492 | } | ||
5493 | |||
5494 | #ifdef CONFIG_CIFS_XATTR | 5437 | #ifdef CONFIG_CIFS_XATTR |
5495 | /* | 5438 | /* |
5496 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common | 5439 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common |
@@ -5560,7 +5503,7 @@ QAllEAsRetry: | |||
5560 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 5503 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
5561 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); | 5504 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); |
5562 | pSMB->Reserved4 = 0; | 5505 | pSMB->Reserved4 = 0; |
5563 | pSMB->hdr.smb_buf_length += byte_count; | 5506 | inc_rfc1001_len(pSMB, byte_count); |
5564 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5507 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5565 | 5508 | ||
5566 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5509 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5576,7 +5519,7 @@ QAllEAsRetry: | |||
5576 | of these trans2 responses */ | 5519 | of these trans2 responses */ |
5577 | 5520 | ||
5578 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5521 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
5579 | if (rc || (pSMBr->ByteCount < 4)) { | 5522 | if (rc || get_bcc(&pSMBr->hdr) < 4) { |
5580 | rc = -EIO; /* bad smb */ | 5523 | rc = -EIO; /* bad smb */ |
5581 | goto QAllEAsOut; | 5524 | goto QAllEAsOut; |
5582 | } | 5525 | } |
@@ -5773,7 +5716,7 @@ SetEARetry: | |||
5773 | pSMB->ParameterCount = cpu_to_le16(params); | 5716 | pSMB->ParameterCount = cpu_to_le16(params); |
5774 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 5717 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
5775 | pSMB->Reserved4 = 0; | 5718 | pSMB->Reserved4 = 0; |
5776 | pSMB->hdr.smb_buf_length += byte_count; | 5719 | inc_rfc1001_len(pSMB, byte_count); |
5777 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5720 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5778 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5721 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5779 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5722 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5787,5 +5730,99 @@ SetEARetry: | |||
5787 | 5730 | ||
5788 | return rc; | 5731 | return rc; |
5789 | } | 5732 | } |
5790 | |||
5791 | #endif | 5733 | #endif |
5734 | |||
5735 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ | ||
5736 | /* | ||
5737 | * Years ago the kernel added a "dnotify" function for Samba server, | ||
5738 | * to allow network clients (such as Windows) to display updated | ||
5739 | * lists of files in directory listings automatically when | ||
5740 | * files are added by one user when another user has the | ||
5741 | * same directory open on their desktop. The Linux cifs kernel | ||
5742 | * client hooked into the kernel side of this interface for | ||
5743 | * the same reason, but ironically when the VFS moved from | ||
5744 | * "dnotify" to "inotify" it became harder to plug in Linux | ||
5745 | * network file system clients (the most obvious use case | ||
5746 | * for notify interfaces is when multiple users can update | ||
5747 | * the contents of the same directory - exactly what network | ||
5748 | * file systems can do) although the server (Samba) could | ||
5749 | * still use it. For the short term we leave the worker | ||
5750 | * function ifdeffed out (below) until inotify is fixed | ||
5751 | * in the VFS to make it easier to plug in network file | ||
5752 | * system clients. If inotify turns out to be permanently | ||
5753 | * incompatible for network fs clients, we could instead simply | ||
5754 | * expose this config flag by adding a future cifs (and smb2) notify ioctl. | ||
5755 | */ | ||
5756 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
5757 | const int notify_subdirs, const __u16 netfid, | ||
5758 | __u32 filter, struct file *pfile, int multishot, | ||
5759 | const struct nls_table *nls_codepage) | ||
5760 | { | ||
5761 | int rc = 0; | ||
5762 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
5763 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
5764 | struct dir_notify_req *dnotify_req; | ||
5765 | int bytes_returned; | ||
5766 | |||
5767 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
5768 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
5769 | (void **) &pSMBr); | ||
5770 | if (rc) | ||
5771 | return rc; | ||
5772 | |||
5773 | pSMB->TotalParameterCount = 0 ; | ||
5774 | pSMB->TotalDataCount = 0; | ||
5775 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
5776 | /* BB find exact data count max from sess structure BB */ | ||
5777 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
5778 | /* BB VERIFY verify which is correct for above BB */ | ||
5779 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
5780 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
5781 | |||
5782 | pSMB->MaxSetupCount = 4; | ||
5783 | pSMB->Reserved = 0; | ||
5784 | pSMB->ParameterOffset = 0; | ||
5785 | pSMB->DataCount = 0; | ||
5786 | pSMB->DataOffset = 0; | ||
5787 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
5788 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
5789 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5790 | if (notify_subdirs) | ||
5791 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
5792 | pSMB->Reserved2 = 0; | ||
5793 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
5794 | pSMB->Fid = netfid; /* file handle always le */ | ||
5795 | pSMB->ByteCount = 0; | ||
5796 | |||
5797 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
5798 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
5799 | CIFS_ASYNC_OP); | ||
5800 | if (rc) { | ||
5801 | cFYI(1, "Error in Notify = %d", rc); | ||
5802 | } else { | ||
5803 | /* Add file to outstanding requests */ | ||
5804 | /* BB change to kmem cache alloc */ | ||
5805 | dnotify_req = kmalloc( | ||
5806 | sizeof(struct dir_notify_req), | ||
5807 | GFP_KERNEL); | ||
5808 | if (dnotify_req) { | ||
5809 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
5810 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
5811 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
5812 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
5813 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
5814 | dnotify_req->netfid = netfid; | ||
5815 | dnotify_req->pfile = pfile; | ||
5816 | dnotify_req->filter = filter; | ||
5817 | dnotify_req->multishot = multishot; | ||
5818 | spin_lock(&GlobalMid_Lock); | ||
5819 | list_add_tail(&dnotify_req->lhead, | ||
5820 | &GlobalDnotifyReqList); | ||
5821 | spin_unlock(&GlobalMid_Lock); | ||
5822 | } else | ||
5823 | rc = -ENOMEM; | ||
5824 | } | ||
5825 | cifs_buf_release(pSMB); | ||
5826 | return rc; | ||
5827 | } | ||
5828 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index db9d55b507d0..da284e3cb653 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -102,6 +102,7 @@ struct smb_vol { | |||
102 | bool fsc:1; /* enable fscache */ | 102 | bool fsc:1; /* enable fscache */ |
103 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ | 103 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ |
104 | bool multiuser:1; | 104 | bool multiuser:1; |
105 | bool use_smb2:1; /* force smb2 use on mount instead of cifs */ | ||
105 | unsigned int rsize; | 106 | unsigned int rsize; |
106 | unsigned int wsize; | 107 | unsigned int wsize; |
107 | bool sockopt_tcp_nodelay:1; | 108 | bool sockopt_tcp_nodelay:1; |
@@ -274,7 +275,8 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
274 | char *data_area_of_target; | 275 | char *data_area_of_target; |
275 | char *data_area_of_buf2; | 276 | char *data_area_of_buf2; |
276 | int remaining; | 277 | int remaining; |
277 | __u16 byte_count, total_data_size, total_in_buf, total_in_buf2; | 278 | unsigned int byte_count, total_in_buf; |
279 | __u16 total_data_size, total_in_buf2; | ||
278 | 280 | ||
279 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | 281 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
280 | 282 | ||
@@ -287,7 +289,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
287 | remaining = total_data_size - total_in_buf; | 289 | remaining = total_data_size - total_in_buf; |
288 | 290 | ||
289 | if (remaining < 0) | 291 | if (remaining < 0) |
290 | return -EINVAL; | 292 | return -EPROTO; |
291 | 293 | ||
292 | if (remaining == 0) /* nothing to do, ignore */ | 294 | if (remaining == 0) /* nothing to do, ignore */ |
293 | return 0; | 295 | return 0; |
@@ -308,19 +310,28 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
308 | data_area_of_target += total_in_buf; | 310 | data_area_of_target += total_in_buf; |
309 | 311 | ||
310 | /* copy second buffer into end of first buffer */ | 312 | /* 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; | 313 | total_in_buf += total_in_buf2; |
314 | /* is the result too big for the field? */ | ||
315 | if (total_in_buf > USHRT_MAX) | ||
316 | return -EPROTO; | ||
313 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); | 317 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); |
314 | byte_count = get_bcc_le(pTargetSMB); | ||
315 | byte_count += total_in_buf2; | ||
316 | put_bcc_le(byte_count, pTargetSMB); | ||
317 | 318 | ||
318 | byte_count = pTargetSMB->smb_buf_length; | 319 | /* fix up the BCC */ |
320 | byte_count = get_bcc(pTargetSMB); | ||
319 | byte_count += total_in_buf2; | 321 | byte_count += total_in_buf2; |
322 | /* is the result too big for the field? */ | ||
323 | if (byte_count > USHRT_MAX) | ||
324 | return -EPROTO; | ||
325 | put_bcc(byte_count, pTargetSMB); | ||
320 | 326 | ||
321 | /* BB also add check that we are not beyond maximum buffer size */ | 327 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); |
328 | byte_count += total_in_buf2; | ||
329 | /* don't allow buffer to overflow */ | ||
330 | if (byte_count > CIFSMaxBufSize) | ||
331 | return -ENOBUFS; | ||
332 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | ||
322 | 333 | ||
323 | pTargetSMB->smb_buf_length = byte_count; | 334 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); |
324 | 335 | ||
325 | if (remaining == total_in_buf2) { | 336 | if (remaining == total_in_buf2) { |
326 | cFYI(1, "found the last secondary response"); | 337 | cFYI(1, "found the last secondary response"); |
@@ -485,8 +496,7 @@ incomplete_rcv: | |||
485 | /* Note that FC 1001 length is big endian on the wire, | 496 | /* Note that FC 1001 length is big endian on the wire, |
486 | but we convert it here so it is always manipulated | 497 | but we convert it here so it is always manipulated |
487 | as host byte order */ | 498 | as host byte order */ |
488 | pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length); | 499 | pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); |
489 | smb_buffer->smb_buf_length = pdu_length; | ||
490 | 500 | ||
491 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); | 501 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); |
492 | 502 | ||
@@ -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 | ||
@@ -721,7 +735,7 @@ multi_t2_fnd: | |||
721 | sock_release(csocket); | 735 | sock_release(csocket); |
722 | server->ssocket = NULL; | 736 | server->ssocket = NULL; |
723 | } | 737 | } |
724 | /* buffer usuallly freed in free_mid - need to free it here on exit */ | 738 | /* buffer usually freed in free_mid - need to free it here on exit */ |
725 | cifs_buf_release(bigbuf); | 739 | cifs_buf_release(bigbuf); |
726 | if (smallbuf) /* no sense logging a debug message if NULL */ | 740 | if (smallbuf) /* no sense logging a debug message if NULL */ |
727 | cifs_small_buf_release(smallbuf); | 741 | cifs_small_buf_release(smallbuf); |
@@ -804,11 +818,11 @@ extract_hostname(const char *unc) | |||
804 | } | 818 | } |
805 | 819 | ||
806 | static int | 820 | static int |
807 | cifs_parse_mount_options(char *options, const char *devname, | 821 | cifs_parse_mount_options(const char *mountdata, 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; | 825 | char *mountdata_copy, *options; |
812 | unsigned int temp_len, i, j; | 826 | unsigned int temp_len, i, j; |
813 | char separator[2]; | 827 | char separator[2]; |
814 | short int override_uid = -1; | 828 | short int override_uid = -1; |
@@ -848,9 +862,15 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
848 | 862 | ||
849 | vol->actimeo = CIFS_DEF_ACTIMEO; | 863 | vol->actimeo = CIFS_DEF_ACTIMEO; |
850 | 864 | ||
851 | if (!options) | 865 | if (!mountdata) |
852 | return 1; | 866 | goto cifs_parse_mount_err; |
853 | 867 | ||
868 | mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL); | ||
869 | if (!mountdata_copy) | ||
870 | goto cifs_parse_mount_err; | ||
871 | |||
872 | options = mountdata_copy; | ||
873 | end = options + strlen(options); | ||
854 | if (strncmp(options, "sep=", 4) == 0) { | 874 | if (strncmp(options, "sep=", 4) == 0) { |
855 | if (options[4] != 0) { | 875 | if (options[4] != 0) { |
856 | separator[0] = options[4]; | 876 | separator[0] = options[4]; |
@@ -875,17 +895,22 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
875 | if (!value) { | 895 | if (!value) { |
876 | printk(KERN_WARNING | 896 | printk(KERN_WARNING |
877 | "CIFS: invalid or missing username\n"); | 897 | "CIFS: invalid or missing username\n"); |
878 | return 1; /* needs_arg; */ | 898 | goto cifs_parse_mount_err; |
879 | } else if (!*value) { | 899 | } else if (!*value) { |
880 | /* null user, ie anonymous, authentication */ | 900 | /* null user, ie anonymous, authentication */ |
881 | vol->nullauth = 1; | 901 | vol->nullauth = 1; |
882 | } | 902 | } |
883 | if (strnlen(value, MAX_USERNAME_SIZE) < | 903 | if (strnlen(value, MAX_USERNAME_SIZE) < |
884 | MAX_USERNAME_SIZE) { | 904 | MAX_USERNAME_SIZE) { |
885 | vol->username = value; | 905 | vol->username = kstrdup(value, GFP_KERNEL); |
906 | if (!vol->username) { | ||
907 | printk(KERN_WARNING "CIFS: no memory " | ||
908 | "for username\n"); | ||
909 | goto cifs_parse_mount_err; | ||
910 | } | ||
886 | } else { | 911 | } else { |
887 | printk(KERN_WARNING "CIFS: username too long\n"); | 912 | printk(KERN_WARNING "CIFS: username too long\n"); |
888 | return 1; | 913 | goto cifs_parse_mount_err; |
889 | } | 914 | } |
890 | } else if (strnicmp(data, "pass", 4) == 0) { | 915 | } else if (strnicmp(data, "pass", 4) == 0) { |
891 | if (!value) { | 916 | if (!value) { |
@@ -916,6 +941,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
916 | the only illegal character in a password is null */ | 941 | the only illegal character in a password is null */ |
917 | 942 | ||
918 | if ((value[temp_len] == 0) && | 943 | if ((value[temp_len] == 0) && |
944 | (value + temp_len < end) && | ||
919 | (value[temp_len+1] == separator[0])) { | 945 | (value[temp_len+1] == separator[0])) { |
920 | /* reinsert comma */ | 946 | /* reinsert comma */ |
921 | value[temp_len] = separator[0]; | 947 | value[temp_len] = separator[0]; |
@@ -948,7 +974,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
948 | if (vol->password == NULL) { | 974 | if (vol->password == NULL) { |
949 | printk(KERN_WARNING "CIFS: no memory " | 975 | printk(KERN_WARNING "CIFS: no memory " |
950 | "for password\n"); | 976 | "for password\n"); |
951 | return 1; | 977 | goto cifs_parse_mount_err; |
952 | } | 978 | } |
953 | for (i = 0, j = 0; i < temp_len; i++, j++) { | 979 | for (i = 0, j = 0; i < temp_len; i++, j++) { |
954 | vol->password[j] = value[i]; | 980 | vol->password[j] = value[i]; |
@@ -964,7 +990,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
964 | if (vol->password == NULL) { | 990 | if (vol->password == NULL) { |
965 | printk(KERN_WARNING "CIFS: no memory " | 991 | printk(KERN_WARNING "CIFS: no memory " |
966 | "for password\n"); | 992 | "for password\n"); |
967 | return 1; | 993 | goto cifs_parse_mount_err; |
968 | } | 994 | } |
969 | strcpy(vol->password, value); | 995 | strcpy(vol->password, value); |
970 | } | 996 | } |
@@ -974,11 +1000,16 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
974 | vol->UNCip = NULL; | 1000 | vol->UNCip = NULL; |
975 | } else if (strnlen(value, INET6_ADDRSTRLEN) < | 1001 | } else if (strnlen(value, INET6_ADDRSTRLEN) < |
976 | INET6_ADDRSTRLEN) { | 1002 | INET6_ADDRSTRLEN) { |
977 | vol->UNCip = value; | 1003 | vol->UNCip = kstrdup(value, GFP_KERNEL); |
1004 | if (!vol->UNCip) { | ||
1005 | printk(KERN_WARNING "CIFS: no memory " | ||
1006 | "for UNC IP\n"); | ||
1007 | goto cifs_parse_mount_err; | ||
1008 | } | ||
978 | } else { | 1009 | } else { |
979 | printk(KERN_WARNING "CIFS: ip address " | 1010 | printk(KERN_WARNING "CIFS: ip address " |
980 | "too long\n"); | 1011 | "too long\n"); |
981 | return 1; | 1012 | goto cifs_parse_mount_err; |
982 | } | 1013 | } |
983 | } else if (strnicmp(data, "sec", 3) == 0) { | 1014 | } else if (strnicmp(data, "sec", 3) == 0) { |
984 | if (!value || !*value) { | 1015 | if (!value || !*value) { |
@@ -991,7 +1022,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
991 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | | 1022 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | |
992 | CIFSSEC_MAY_KRB5; */ | 1023 | CIFSSEC_MAY_KRB5; */ |
993 | cERROR(1, "Krb5 cifs privacy not supported"); | 1024 | cERROR(1, "Krb5 cifs privacy not supported"); |
994 | return 1; | 1025 | goto cifs_parse_mount_err; |
995 | } else if (strnicmp(value, "krb5", 4) == 0) { | 1026 | } else if (strnicmp(value, "krb5", 4) == 0) { |
996 | vol->secFlg |= CIFSSEC_MAY_KRB5; | 1027 | vol->secFlg |= CIFSSEC_MAY_KRB5; |
997 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { | 1028 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { |
@@ -1021,7 +1052,23 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1021 | vol->nullauth = 1; | 1052 | vol->nullauth = 1; |
1022 | } else { | 1053 | } else { |
1023 | cERROR(1, "bad security option: %s", value); | 1054 | cERROR(1, "bad security option: %s", value); |
1024 | return 1; | 1055 | goto cifs_parse_mount_err; |
1056 | } | ||
1057 | } else if (strnicmp(data, "vers", 3) == 0) { | ||
1058 | if (!value || !*value) { | ||
1059 | cERROR(1, "no protocol version specified" | ||
1060 | " after vers= mount option"); | ||
1061 | } else if ((strnicmp(value, "cifs", 4) == 0) || | ||
1062 | (strnicmp(value, "1", 1) == 0)) { | ||
1063 | /* this is the default */ | ||
1064 | continue; | ||
1065 | } else if ((strnicmp(value, "smb2", 4) == 0) || | ||
1066 | (strnicmp(value, "2", 1) == 0)) { | ||
1067 | #ifdef CONFIG_CIFS_SMB2 | ||
1068 | vol->use_smb2 = true; | ||
1069 | #else | ||
1070 | cERROR(1, "smb2 support not enabled"); | ||
1071 | #endif /* CONFIG_CIFS_SMB2 */ | ||
1025 | } | 1072 | } |
1026 | } else if ((strnicmp(data, "unc", 3) == 0) | 1073 | } else if ((strnicmp(data, "unc", 3) == 0) |
1027 | || (strnicmp(data, "target", 6) == 0) | 1074 | || (strnicmp(data, "target", 6) == 0) |
@@ -1029,12 +1076,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1029 | if (!value || !*value) { | 1076 | if (!value || !*value) { |
1030 | printk(KERN_WARNING "CIFS: invalid path to " | 1077 | printk(KERN_WARNING "CIFS: invalid path to " |
1031 | "network resource\n"); | 1078 | "network resource\n"); |
1032 | return 1; /* needs_arg; */ | 1079 | goto cifs_parse_mount_err; |
1033 | } | 1080 | } |
1034 | if ((temp_len = strnlen(value, 300)) < 300) { | 1081 | if ((temp_len = strnlen(value, 300)) < 300) { |
1035 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | 1082 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); |
1036 | if (vol->UNC == NULL) | 1083 | if (vol->UNC == NULL) |
1037 | return 1; | 1084 | goto cifs_parse_mount_err; |
1038 | strcpy(vol->UNC, value); | 1085 | strcpy(vol->UNC, value); |
1039 | if (strncmp(vol->UNC, "//", 2) == 0) { | 1086 | if (strncmp(vol->UNC, "//", 2) == 0) { |
1040 | vol->UNC[0] = '\\'; | 1087 | vol->UNC[0] = '\\'; |
@@ -1043,27 +1090,32 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1043 | printk(KERN_WARNING | 1090 | printk(KERN_WARNING |
1044 | "CIFS: UNC Path does not begin " | 1091 | "CIFS: UNC Path does not begin " |
1045 | "with // or \\\\ \n"); | 1092 | "with // or \\\\ \n"); |
1046 | return 1; | 1093 | goto cifs_parse_mount_err; |
1047 | } | 1094 | } |
1048 | } else { | 1095 | } else { |
1049 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | 1096 | printk(KERN_WARNING "CIFS: UNC name too long\n"); |
1050 | return 1; | 1097 | goto cifs_parse_mount_err; |
1051 | } | 1098 | } |
1052 | } else if ((strnicmp(data, "domain", 3) == 0) | 1099 | } else if ((strnicmp(data, "domain", 3) == 0) |
1053 | || (strnicmp(data, "workgroup", 5) == 0)) { | 1100 | || (strnicmp(data, "workgroup", 5) == 0)) { |
1054 | if (!value || !*value) { | 1101 | if (!value || !*value) { |
1055 | printk(KERN_WARNING "CIFS: invalid domain name\n"); | 1102 | printk(KERN_WARNING "CIFS: invalid domain name\n"); |
1056 | return 1; /* needs_arg; */ | 1103 | goto cifs_parse_mount_err; |
1057 | } | 1104 | } |
1058 | /* BB are there cases in which a comma can be valid in | 1105 | /* BB are there cases in which a comma can be valid in |
1059 | a domain name and need special handling? */ | 1106 | a domain name and need special handling? */ |
1060 | if (strnlen(value, 256) < 256) { | 1107 | if (strnlen(value, 256) < 256) { |
1061 | vol->domainname = value; | 1108 | vol->domainname = kstrdup(value, GFP_KERNEL); |
1109 | if (!vol->domainname) { | ||
1110 | printk(KERN_WARNING "CIFS: no memory " | ||
1111 | "for domainname\n"); | ||
1112 | goto cifs_parse_mount_err; | ||
1113 | } | ||
1062 | cFYI(1, "Domain name set"); | 1114 | cFYI(1, "Domain name set"); |
1063 | } else { | 1115 | } else { |
1064 | printk(KERN_WARNING "CIFS: domain name too " | 1116 | printk(KERN_WARNING "CIFS: domain name too " |
1065 | "long\n"); | 1117 | "long\n"); |
1066 | return 1; | 1118 | goto cifs_parse_mount_err; |
1067 | } | 1119 | } |
1068 | } else if (strnicmp(data, "srcaddr", 7) == 0) { | 1120 | } else if (strnicmp(data, "srcaddr", 7) == 0) { |
1069 | vol->srcaddr.ss_family = AF_UNSPEC; | 1121 | vol->srcaddr.ss_family = AF_UNSPEC; |
@@ -1071,7 +1123,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1071 | if (!value || !*value) { | 1123 | if (!value || !*value) { |
1072 | printk(KERN_WARNING "CIFS: srcaddr value" | 1124 | printk(KERN_WARNING "CIFS: srcaddr value" |
1073 | " not specified.\n"); | 1125 | " not specified.\n"); |
1074 | return 1; /* needs_arg; */ | 1126 | goto cifs_parse_mount_err; |
1075 | } | 1127 | } |
1076 | i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, | 1128 | i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, |
1077 | value, strlen(value)); | 1129 | value, strlen(value)); |
@@ -1079,20 +1131,20 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1079 | printk(KERN_WARNING "CIFS: Could not parse" | 1131 | printk(KERN_WARNING "CIFS: Could not parse" |
1080 | " srcaddr: %s\n", | 1132 | " srcaddr: %s\n", |
1081 | value); | 1133 | value); |
1082 | return 1; | 1134 | goto cifs_parse_mount_err; |
1083 | } | 1135 | } |
1084 | } else if (strnicmp(data, "prefixpath", 10) == 0) { | 1136 | } else if (strnicmp(data, "prefixpath", 10) == 0) { |
1085 | if (!value || !*value) { | 1137 | if (!value || !*value) { |
1086 | printk(KERN_WARNING | 1138 | printk(KERN_WARNING |
1087 | "CIFS: invalid path prefix\n"); | 1139 | "CIFS: invalid path prefix\n"); |
1088 | return 1; /* needs_argument */ | 1140 | goto cifs_parse_mount_err; |
1089 | } | 1141 | } |
1090 | if ((temp_len = strnlen(value, 1024)) < 1024) { | 1142 | if ((temp_len = strnlen(value, 1024)) < 1024) { |
1091 | if (value[0] != '/') | 1143 | if (value[0] != '/') |
1092 | temp_len++; /* missing leading slash */ | 1144 | temp_len++; /* missing leading slash */ |
1093 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); | 1145 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); |
1094 | if (vol->prepath == NULL) | 1146 | if (vol->prepath == NULL) |
1095 | return 1; | 1147 | goto cifs_parse_mount_err; |
1096 | if (value[0] != '/') { | 1148 | if (value[0] != '/') { |
1097 | vol->prepath[0] = '/'; | 1149 | vol->prepath[0] = '/'; |
1098 | strcpy(vol->prepath+1, value); | 1150 | strcpy(vol->prepath+1, value); |
@@ -1101,24 +1153,33 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1101 | cFYI(1, "prefix path %s", vol->prepath); | 1153 | cFYI(1, "prefix path %s", vol->prepath); |
1102 | } else { | 1154 | } else { |
1103 | printk(KERN_WARNING "CIFS: prefix too long\n"); | 1155 | printk(KERN_WARNING "CIFS: prefix too long\n"); |
1104 | return 1; | 1156 | goto cifs_parse_mount_err; |
1105 | } | 1157 | } |
1106 | } else if (strnicmp(data, "iocharset", 9) == 0) { | 1158 | } else if (strnicmp(data, "iocharset", 9) == 0) { |
1107 | if (!value || !*value) { | 1159 | if (!value || !*value) { |
1108 | printk(KERN_WARNING "CIFS: invalid iocharset " | 1160 | printk(KERN_WARNING "CIFS: invalid iocharset " |
1109 | "specified\n"); | 1161 | "specified\n"); |
1110 | return 1; /* needs_arg; */ | 1162 | goto cifs_parse_mount_err; |
1111 | } | 1163 | } |
1112 | if (strnlen(value, 65) < 65) { | 1164 | if (strnlen(value, 65) < 65) { |
1113 | if (strnicmp(value, "default", 7)) | 1165 | if (strnicmp(value, "default", 7)) { |
1114 | vol->iocharset = value; | 1166 | vol->iocharset = kstrdup(value, |
1167 | GFP_KERNEL); | ||
1168 | |||
1169 | if (!vol->iocharset) { | ||
1170 | printk(KERN_WARNING "CIFS: no " | ||
1171 | "memory for" | ||
1172 | "charset\n"); | ||
1173 | goto cifs_parse_mount_err; | ||
1174 | } | ||
1175 | } | ||
1115 | /* if iocharset not set then load_nls_default | 1176 | /* if iocharset not set then load_nls_default |
1116 | is used by caller */ | 1177 | is used by caller */ |
1117 | cFYI(1, "iocharset set to %s", value); | 1178 | cFYI(1, "iocharset set to %s", value); |
1118 | } else { | 1179 | } else { |
1119 | printk(KERN_WARNING "CIFS: iocharset name " | 1180 | printk(KERN_WARNING "CIFS: iocharset name " |
1120 | "too long.\n"); | 1181 | "too long.\n"); |
1121 | return 1; | 1182 | goto cifs_parse_mount_err; |
1122 | } | 1183 | } |
1123 | } else if (!strnicmp(data, "uid", 3) && value && *value) { | 1184 | } else if (!strnicmp(data, "uid", 3) && value && *value) { |
1124 | vol->linux_uid = simple_strtoul(value, &value, 0); | 1185 | vol->linux_uid = simple_strtoul(value, &value, 0); |
@@ -1231,7 +1292,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1231 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { | 1292 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { |
1232 | cERROR(1, "CIFS: attribute cache" | 1293 | cERROR(1, "CIFS: attribute cache" |
1233 | "timeout too large"); | 1294 | "timeout too large"); |
1234 | return 1; | 1295 | goto cifs_parse_mount_err; |
1235 | } | 1296 | } |
1236 | } | 1297 | } |
1237 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1298 | } else if (strnicmp(data, "credentials", 4) == 0) { |
@@ -1375,7 +1436,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1375 | #ifndef CONFIG_CIFS_FSCACHE | 1436 | #ifndef CONFIG_CIFS_FSCACHE |
1376 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" | 1437 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" |
1377 | "kernel config option set"); | 1438 | "kernel config option set"); |
1378 | return 1; | 1439 | goto cifs_parse_mount_err; |
1379 | #endif | 1440 | #endif |
1380 | vol->fsc = true; | 1441 | vol->fsc = true; |
1381 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1442 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { |
@@ -1390,12 +1451,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1390 | if (devname == NULL) { | 1451 | if (devname == NULL) { |
1391 | printk(KERN_WARNING "CIFS: Missing UNC name for mount " | 1452 | printk(KERN_WARNING "CIFS: Missing UNC name for mount " |
1392 | "target\n"); | 1453 | "target\n"); |
1393 | return 1; | 1454 | goto cifs_parse_mount_err; |
1394 | } | 1455 | } |
1395 | if ((temp_len = strnlen(devname, 300)) < 300) { | 1456 | if ((temp_len = strnlen(devname, 300)) < 300) { |
1396 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | 1457 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); |
1397 | if (vol->UNC == NULL) | 1458 | if (vol->UNC == NULL) |
1398 | return 1; | 1459 | goto cifs_parse_mount_err; |
1399 | strcpy(vol->UNC, devname); | 1460 | strcpy(vol->UNC, devname); |
1400 | if (strncmp(vol->UNC, "//", 2) == 0) { | 1461 | if (strncmp(vol->UNC, "//", 2) == 0) { |
1401 | vol->UNC[0] = '\\'; | 1462 | vol->UNC[0] = '\\'; |
@@ -1403,21 +1464,21 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1403 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { | 1464 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { |
1404 | printk(KERN_WARNING "CIFS: UNC Path does not " | 1465 | printk(KERN_WARNING "CIFS: UNC Path does not " |
1405 | "begin with // or \\\\ \n"); | 1466 | "begin with // or \\\\ \n"); |
1406 | return 1; | 1467 | goto cifs_parse_mount_err; |
1407 | } | 1468 | } |
1408 | value = strpbrk(vol->UNC+2, "/\\"); | 1469 | value = strpbrk(vol->UNC+2, "/\\"); |
1409 | if (value) | 1470 | if (value) |
1410 | *value = '\\'; | 1471 | *value = '\\'; |
1411 | } else { | 1472 | } else { |
1412 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | 1473 | printk(KERN_WARNING "CIFS: UNC name too long\n"); |
1413 | return 1; | 1474 | goto cifs_parse_mount_err; |
1414 | } | 1475 | } |
1415 | } | 1476 | } |
1416 | 1477 | ||
1417 | if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { | 1478 | if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { |
1418 | cERROR(1, "Multiuser mounts currently require krb5 " | 1479 | cERROR(1, "Multiuser mounts currently require krb5 " |
1419 | "authentication!"); | 1480 | "authentication!"); |
1420 | return 1; | 1481 | goto cifs_parse_mount_err; |
1421 | } | 1482 | } |
1422 | 1483 | ||
1423 | if (vol->UNCip == NULL) | 1484 | if (vol->UNCip == NULL) |
@@ -1435,7 +1496,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1435 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " | 1496 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " |
1436 | "specified with no gid= option.\n"); | 1497 | "specified with no gid= option.\n"); |
1437 | 1498 | ||
1499 | kfree(mountdata_copy); | ||
1438 | return 0; | 1500 | return 0; |
1501 | |||
1502 | cifs_parse_mount_err: | ||
1503 | kfree(mountdata_copy); | ||
1504 | return 1; | ||
1439 | } | 1505 | } |
1440 | 1506 | ||
1441 | /** Returns true if srcaddr isn't specified and rhs isn't | 1507 | /** Returns true if srcaddr isn't specified and rhs isn't |
@@ -2265,7 +2331,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) | |||
2265 | smb_buf = (struct smb_hdr *)ses_init_buf; | 2331 | smb_buf = (struct smb_hdr *)ses_init_buf; |
2266 | 2332 | ||
2267 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 2333 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
2268 | smb_buf->smb_buf_length = 0x81000044; | 2334 | smb_buf->smb_buf_length = cpu_to_be32(0x81000044); |
2269 | rc = smb_send(server, smb_buf, 0x44); | 2335 | rc = smb_send(server, smb_buf, 0x44); |
2270 | kfree(ses_init_buf); | 2336 | kfree(ses_init_buf); |
2271 | /* | 2337 | /* |
@@ -2658,6 +2724,11 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, | |||
2658 | 0 /* not legacy */, cifs_sb->local_nls, | 2724 | 0 /* not legacy */, cifs_sb->local_nls, |
2659 | cifs_sb->mnt_cifs_flags & | 2725 | cifs_sb->mnt_cifs_flags & |
2660 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2726 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2727 | |||
2728 | if (rc == -EOPNOTSUPP || rc == -EINVAL) | ||
2729 | rc = SMBQueryInformation(xid, tcon, full_path, pfile_info, | ||
2730 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | ||
2731 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2661 | kfree(pfile_info); | 2732 | kfree(pfile_info); |
2662 | return rc; | 2733 | return rc; |
2663 | } | 2734 | } |
@@ -2671,8 +2742,12 @@ cleanup_volume_info(struct smb_vol **pvolume_info) | |||
2671 | return; | 2742 | return; |
2672 | 2743 | ||
2673 | volume_info = *pvolume_info; | 2744 | volume_info = *pvolume_info; |
2745 | kfree(volume_info->username); | ||
2674 | kzfree(volume_info->password); | 2746 | kzfree(volume_info->password); |
2675 | kfree(volume_info->UNC); | 2747 | kfree(volume_info->UNC); |
2748 | kfree(volume_info->UNCip); | ||
2749 | kfree(volume_info->domainname); | ||
2750 | kfree(volume_info->iocharset); | ||
2676 | kfree(volume_info->prepath); | 2751 | kfree(volume_info->prepath); |
2677 | kfree(volume_info); | 2752 | kfree(volume_info); |
2678 | *pvolume_info = NULL; | 2753 | *pvolume_info = NULL; |
@@ -2709,11 +2784,65 @@ build_unc_path_to_root(const struct smb_vol *volume_info, | |||
2709 | full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */ | 2784 | full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */ |
2710 | return full_path; | 2785 | return full_path; |
2711 | } | 2786 | } |
2787 | |||
2788 | /* | ||
2789 | * Perform a dfs referral query for a share and (optionally) prefix | ||
2790 | * | ||
2791 | * If a referral is found, cifs_sb->mountdata will be (re-)allocated | ||
2792 | * to a string containing updated options for the submount. Otherwise it | ||
2793 | * will be left untouched. | ||
2794 | * | ||
2795 | * Returns the rc from get_dfs_path to the caller, which can be used to | ||
2796 | * determine whether there were referrals. | ||
2797 | */ | ||
2798 | static int | ||
2799 | expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, | ||
2800 | struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, | ||
2801 | int check_prefix) | ||
2802 | { | ||
2803 | int rc; | ||
2804 | unsigned int num_referrals = 0; | ||
2805 | struct dfs_info3_param *referrals = NULL; | ||
2806 | char *full_path = NULL, *ref_path = NULL, *mdata = NULL; | ||
2807 | |||
2808 | full_path = build_unc_path_to_root(volume_info, cifs_sb); | ||
2809 | if (IS_ERR(full_path)) | ||
2810 | return PTR_ERR(full_path); | ||
2811 | |||
2812 | /* For DFS paths, skip the first '\' of the UNC */ | ||
2813 | ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; | ||
2814 | |||
2815 | rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls, | ||
2816 | &num_referrals, &referrals, | ||
2817 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2818 | |||
2819 | if (!rc && num_referrals > 0) { | ||
2820 | char *fake_devname = NULL; | ||
2821 | |||
2822 | mdata = cifs_compose_mount_options(cifs_sb->mountdata, | ||
2823 | full_path + 1, referrals, | ||
2824 | &fake_devname); | ||
2825 | |||
2826 | free_dfs_info_array(referrals, num_referrals); | ||
2827 | kfree(fake_devname); | ||
2828 | |||
2829 | if (cifs_sb->mountdata != NULL) | ||
2830 | kfree(cifs_sb->mountdata); | ||
2831 | |||
2832 | if (IS_ERR(mdata)) { | ||
2833 | rc = PTR_ERR(mdata); | ||
2834 | mdata = NULL; | ||
2835 | } | ||
2836 | cifs_sb->mountdata = mdata; | ||
2837 | } | ||
2838 | kfree(full_path); | ||
2839 | return rc; | ||
2840 | } | ||
2712 | #endif | 2841 | #endif |
2713 | 2842 | ||
2714 | int | 2843 | int |
2715 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2844 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
2716 | char *mount_data_global, const char *devname) | 2845 | const char *devname) |
2717 | { | 2846 | { |
2718 | int rc; | 2847 | int rc; |
2719 | int xid; | 2848 | int xid; |
@@ -2722,13 +2851,20 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2722 | struct cifsTconInfo *tcon; | 2851 | struct cifsTconInfo *tcon; |
2723 | struct TCP_Server_Info *srvTcp; | 2852 | struct TCP_Server_Info *srvTcp; |
2724 | char *full_path; | 2853 | char *full_path; |
2725 | char *mount_data = mount_data_global; | ||
2726 | struct tcon_link *tlink; | 2854 | struct tcon_link *tlink; |
2727 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2855 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2728 | struct dfs_info3_param *referrals = NULL; | ||
2729 | unsigned int num_referrals = 0; | ||
2730 | int referral_walks_count = 0; | 2856 | int referral_walks_count = 0; |
2731 | try_mount_again: | 2857 | try_mount_again: |
2858 | /* cleanup activities if we're chasing a referral */ | ||
2859 | if (referral_walks_count) { | ||
2860 | if (tcon) | ||
2861 | cifs_put_tcon(tcon); | ||
2862 | else if (pSesInfo) | ||
2863 | cifs_put_smb_ses(pSesInfo); | ||
2864 | |||
2865 | cleanup_volume_info(&volume_info); | ||
2866 | FreeXid(xid); | ||
2867 | } | ||
2732 | #endif | 2868 | #endif |
2733 | rc = 0; | 2869 | rc = 0; |
2734 | tcon = NULL; | 2870 | tcon = NULL; |
@@ -2745,7 +2881,8 @@ try_mount_again: | |||
2745 | goto out; | 2881 | goto out; |
2746 | } | 2882 | } |
2747 | 2883 | ||
2748 | if (cifs_parse_mount_options(mount_data, devname, volume_info)) { | 2884 | if (cifs_parse_mount_options(cifs_sb->mountdata, devname, |
2885 | volume_info)) { | ||
2749 | rc = -EINVAL; | 2886 | rc = -EINVAL; |
2750 | goto out; | 2887 | goto out; |
2751 | } | 2888 | } |
@@ -2841,6 +2978,24 @@ try_mount_again: | |||
2841 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); | 2978 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); |
2842 | 2979 | ||
2843 | remote_path_check: | 2980 | remote_path_check: |
2981 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
2982 | /* | ||
2983 | * Perform an unconditional check for whether there are DFS | ||
2984 | * referrals for this path without prefix, to provide support | ||
2985 | * for DFS referrals from w2k8 servers which don't seem to respond | ||
2986 | * with PATH_NOT_COVERED to requests that include the prefix. | ||
2987 | * Chase the referral if found, otherwise continue normally. | ||
2988 | */ | ||
2989 | if (referral_walks_count == 0) { | ||
2990 | int refrc = expand_dfs_referral(xid, pSesInfo, volume_info, | ||
2991 | cifs_sb, false); | ||
2992 | if (!refrc) { | ||
2993 | referral_walks_count++; | ||
2994 | goto try_mount_again; | ||
2995 | } | ||
2996 | } | ||
2997 | #endif | ||
2998 | |||
2844 | /* check if a whole path (including prepath) is not remote */ | 2999 | /* check if a whole path (including prepath) is not remote */ |
2845 | if (!rc && tcon) { | 3000 | if (!rc && tcon) { |
2846 | /* build_path_to_root works only when we have a valid tcon */ | 3001 | /* build_path_to_root works only when we have a valid tcon */ |
@@ -2874,46 +3029,15 @@ remote_path_check: | |||
2874 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) | 3029 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) |
2875 | convert_delimiter(cifs_sb->prepath, | 3030 | convert_delimiter(cifs_sb->prepath, |
2876 | CIFS_DIR_SEP(cifs_sb)); | 3031 | CIFS_DIR_SEP(cifs_sb)); |
2877 | full_path = build_unc_path_to_root(volume_info, cifs_sb); | ||
2878 | if (IS_ERR(full_path)) { | ||
2879 | rc = PTR_ERR(full_path); | ||
2880 | goto mount_fail_check; | ||
2881 | } | ||
2882 | |||
2883 | cFYI(1, "Getting referral for: %s", full_path); | ||
2884 | rc = get_dfs_path(xid, pSesInfo , full_path + 1, | ||
2885 | cifs_sb->local_nls, &num_referrals, &referrals, | ||
2886 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2887 | if (!rc && num_referrals > 0) { | ||
2888 | char *fake_devname = NULL; | ||
2889 | |||
2890 | if (mount_data != mount_data_global) | ||
2891 | kfree(mount_data); | ||
2892 | 3032 | ||
2893 | mount_data = cifs_compose_mount_options( | 3033 | rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, |
2894 | cifs_sb->mountdata, full_path + 1, | 3034 | true); |
2895 | referrals, &fake_devname); | ||
2896 | 3035 | ||
2897 | free_dfs_info_array(referrals, num_referrals); | 3036 | if (!rc) { |
2898 | kfree(fake_devname); | ||
2899 | kfree(full_path); | ||
2900 | |||
2901 | if (IS_ERR(mount_data)) { | ||
2902 | rc = PTR_ERR(mount_data); | ||
2903 | mount_data = NULL; | ||
2904 | goto mount_fail_check; | ||
2905 | } | ||
2906 | |||
2907 | if (tcon) | ||
2908 | cifs_put_tcon(tcon); | ||
2909 | else if (pSesInfo) | ||
2910 | cifs_put_smb_ses(pSesInfo); | ||
2911 | |||
2912 | cleanup_volume_info(&volume_info); | ||
2913 | referral_walks_count++; | 3037 | referral_walks_count++; |
2914 | FreeXid(xid); | ||
2915 | goto try_mount_again; | 3038 | goto try_mount_again; |
2916 | } | 3039 | } |
3040 | goto mount_fail_check; | ||
2917 | #else /* No DFS support, return error on mount */ | 3041 | #else /* No DFS support, return error on mount */ |
2918 | rc = -EOPNOTSUPP; | 3042 | rc = -EOPNOTSUPP; |
2919 | #endif | 3043 | #endif |
@@ -2946,8 +3070,6 @@ remote_path_check: | |||
2946 | mount_fail_check: | 3070 | mount_fail_check: |
2947 | /* on error free sesinfo and tcon struct if needed */ | 3071 | /* on error free sesinfo and tcon struct if needed */ |
2948 | if (rc) { | 3072 | if (rc) { |
2949 | if (mount_data != mount_data_global) | ||
2950 | kfree(mount_data); | ||
2951 | /* If find_unc succeeded then rc == 0 so we can not end */ | 3073 | /* If find_unc succeeded then rc == 0 so we can not end */ |
2952 | /* up accidentally freeing someone elses tcon struct */ | 3074 | /* up accidentally freeing someone elses tcon struct */ |
2953 | if (tcon) | 3075 | if (tcon) |
@@ -3063,7 +3185,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3063 | bcc_ptr += strlen("?????"); | 3185 | bcc_ptr += strlen("?????"); |
3064 | bcc_ptr += 1; | 3186 | bcc_ptr += 1; |
3065 | count = bcc_ptr - &pSMB->Password[0]; | 3187 | count = bcc_ptr - &pSMB->Password[0]; |
3066 | pSMB->hdr.smb_buf_length += count; | 3188 | pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu( |
3189 | pSMB->hdr.smb_buf_length) + count); | ||
3067 | pSMB->ByteCount = cpu_to_le16(count); | 3190 | pSMB->ByteCount = cpu_to_le16(count); |
3068 | 3191 | ||
3069 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, | 3192 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
@@ -3238,7 +3361,9 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3238 | struct cifsSesInfo *ses; | 3361 | struct cifsSesInfo *ses; |
3239 | struct cifsTconInfo *tcon = NULL; | 3362 | struct cifsTconInfo *tcon = NULL; |
3240 | struct smb_vol *vol_info; | 3363 | struct smb_vol *vol_info; |
3241 | char username[MAX_USERNAME_SIZE + 1]; | 3364 | char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */ |
3365 | /* We used to have this as MAX_USERNAME which is */ | ||
3366 | /* way too big now (256 instead of 32) */ | ||
3242 | 3367 | ||
3243 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); | 3368 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); |
3244 | if (vol_info == NULL) { | 3369 | if (vol_info == NULL) { |
diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 993f82045bf6..55d87ac52000 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include "cifs_debug.h" | 45 | #include "cifs_debug.h" |
46 | #include "cifsfs.h" | 46 | #include "cifsfs.h" |
47 | 47 | ||
48 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 48 | #ifdef CIFS_NFSD_EXPORT |
49 | static struct dentry *cifs_get_parent(struct dentry *dentry) | 49 | static struct dentry *cifs_get_parent(struct dentry *dentry) |
50 | { | 50 | { |
51 | /* BB need to add code here eventually to enable export via NFSD */ | 51 | /* BB need to add code here eventually to enable export via NFSD */ |
@@ -63,5 +63,5 @@ const struct export_operations cifs_export_ops = { | |||
63 | .encode_fs = */ | 63 | .encode_fs = */ |
64 | }; | 64 | }; |
65 | 65 | ||
66 | #endif /* EXPERIMENTAL */ | 66 | #endif /* CIFS_NFSD_EXPORT */ |
67 | 67 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index faf59529e847..c672afef0c09 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -857,95 +857,6 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
857 | cifsi->server_eof = end_of_write; | 857 | cifsi->server_eof = end_of_write; |
858 | } | 858 | } |
859 | 859 | ||
860 | ssize_t cifs_user_write(struct file *file, const char __user *write_data, | ||
861 | size_t write_size, loff_t *poffset) | ||
862 | { | ||
863 | struct inode *inode = file->f_path.dentry->d_inode; | ||
864 | int rc = 0; | ||
865 | unsigned int bytes_written = 0; | ||
866 | unsigned int total_written; | ||
867 | struct cifs_sb_info *cifs_sb; | ||
868 | struct cifsTconInfo *pTcon; | ||
869 | int xid; | ||
870 | struct cifsFileInfo *open_file; | ||
871 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
872 | |||
873 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
874 | |||
875 | /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, | ||
876 | *poffset, file->f_path.dentry->d_name.name); */ | ||
877 | |||
878 | if (file->private_data == NULL) | ||
879 | return -EBADF; | ||
880 | |||
881 | open_file = file->private_data; | ||
882 | pTcon = tlink_tcon(open_file->tlink); | ||
883 | |||
884 | rc = generic_write_checks(file, poffset, &write_size, 0); | ||
885 | if (rc) | ||
886 | return rc; | ||
887 | |||
888 | xid = GetXid(); | ||
889 | |||
890 | for (total_written = 0; write_size > total_written; | ||
891 | total_written += bytes_written) { | ||
892 | rc = -EAGAIN; | ||
893 | while (rc == -EAGAIN) { | ||
894 | if (file->private_data == NULL) { | ||
895 | /* file has been closed on us */ | ||
896 | FreeXid(xid); | ||
897 | /* if we have gotten here we have written some data | ||
898 | and blocked, and the file has been freed on us while | ||
899 | we blocked so return what we managed to write */ | ||
900 | return total_written; | ||
901 | } | ||
902 | if (open_file->invalidHandle) { | ||
903 | /* we could deadlock if we called | ||
904 | filemap_fdatawait from here so tell | ||
905 | reopen_file not to flush data to server | ||
906 | now */ | ||
907 | rc = cifs_reopen_file(open_file, false); | ||
908 | if (rc != 0) | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | rc = CIFSSMBWrite(xid, pTcon, | ||
913 | open_file->netfid, | ||
914 | min_t(const int, cifs_sb->wsize, | ||
915 | write_size - total_written), | ||
916 | *poffset, &bytes_written, | ||
917 | NULL, write_data + total_written, 0); | ||
918 | } | ||
919 | if (rc || (bytes_written == 0)) { | ||
920 | if (total_written) | ||
921 | break; | ||
922 | else { | ||
923 | FreeXid(xid); | ||
924 | return rc; | ||
925 | } | ||
926 | } else { | ||
927 | cifs_update_eof(cifsi, *poffset, bytes_written); | ||
928 | *poffset += bytes_written; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | cifs_stats_bytes_written(pTcon, total_written); | ||
933 | |||
934 | /* Do not update local mtime - server will set its actual value on write | ||
935 | * inode->i_ctime = inode->i_mtime = | ||
936 | * current_fs_time(inode->i_sb);*/ | ||
937 | if (total_written > 0) { | ||
938 | spin_lock(&inode->i_lock); | ||
939 | if (*poffset > inode->i_size) | ||
940 | i_size_write(inode, *poffset); | ||
941 | spin_unlock(&inode->i_lock); | ||
942 | } | ||
943 | mark_inode_dirty_sync(inode); | ||
944 | |||
945 | FreeXid(xid); | ||
946 | return total_written; | ||
947 | } | ||
948 | |||
949 | static ssize_t cifs_write(struct cifsFileInfo *open_file, | 860 | static ssize_t cifs_write(struct cifsFileInfo *open_file, |
950 | const char *write_data, size_t write_size, | 861 | const char *write_data, size_t write_size, |
951 | loff_t *poffset) | 862 | loff_t *poffset) |
@@ -1420,9 +1331,10 @@ retry_write: | |||
1420 | return rc; | 1331 | return rc; |
1421 | } | 1332 | } |
1422 | 1333 | ||
1423 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | 1334 | static int |
1335 | cifs_writepage_locked(struct page *page, struct writeback_control *wbc) | ||
1424 | { | 1336 | { |
1425 | int rc = -EFAULT; | 1337 | int rc; |
1426 | int xid; | 1338 | int xid; |
1427 | 1339 | ||
1428 | xid = GetXid(); | 1340 | xid = GetXid(); |
@@ -1442,15 +1354,29 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc) | |||
1442 | * to fail to update with the state of the page correctly. | 1354 | * to fail to update with the state of the page correctly. |
1443 | */ | 1355 | */ |
1444 | set_page_writeback(page); | 1356 | set_page_writeback(page); |
1357 | retry_write: | ||
1445 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); | 1358 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); |
1446 | SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ | 1359 | if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL) |
1447 | unlock_page(page); | 1360 | goto retry_write; |
1361 | else if (rc == -EAGAIN) | ||
1362 | redirty_page_for_writepage(wbc, page); | ||
1363 | else if (rc != 0) | ||
1364 | SetPageError(page); | ||
1365 | else | ||
1366 | SetPageUptodate(page); | ||
1448 | end_page_writeback(page); | 1367 | end_page_writeback(page); |
1449 | page_cache_release(page); | 1368 | page_cache_release(page); |
1450 | FreeXid(xid); | 1369 | FreeXid(xid); |
1451 | return rc; | 1370 | return rc; |
1452 | } | 1371 | } |
1453 | 1372 | ||
1373 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | ||
1374 | { | ||
1375 | int rc = cifs_writepage_locked(page, wbc); | ||
1376 | unlock_page(page); | ||
1377 | return rc; | ||
1378 | } | ||
1379 | |||
1454 | static int cifs_write_end(struct file *file, struct address_space *mapping, | 1380 | static int cifs_write_end(struct file *file, struct address_space *mapping, |
1455 | loff_t pos, unsigned len, unsigned copied, | 1381 | loff_t pos, unsigned len, unsigned copied, |
1456 | struct page *page, void *fsdata) | 1382 | struct page *page, void *fsdata) |
@@ -1519,8 +1445,13 @@ int cifs_strict_fsync(struct file *file, int datasync) | |||
1519 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1445 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1520 | file->f_path.dentry->d_name.name, datasync); | 1446 | file->f_path.dentry->d_name.name, datasync); |
1521 | 1447 | ||
1522 | if (!CIFS_I(inode)->clientCanCacheRead) | 1448 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1523 | cifs_invalidate_mapping(inode); | 1449 | rc = cifs_invalidate_mapping(inode); |
1450 | if (rc) { | ||
1451 | cFYI(1, "rc: %d during invalidate phase", rc); | ||
1452 | rc = 0; /* don't care about it in fsync */ | ||
1453 | } | ||
1454 | } | ||
1524 | 1455 | ||
1525 | tcon = tlink_tcon(smbfile->tlink); | 1456 | tcon = tlink_tcon(smbfile->tlink); |
1526 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1457 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
@@ -1726,7 +1657,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
1726 | return total_written; | 1657 | return total_written; |
1727 | } | 1658 | } |
1728 | 1659 | ||
1729 | static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | 1660 | ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
1730 | unsigned long nr_segs, loff_t pos) | 1661 | unsigned long nr_segs, loff_t pos) |
1731 | { | 1662 | { |
1732 | ssize_t written; | 1663 | ssize_t written; |
@@ -1849,17 +1780,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
1849 | return total_read; | 1780 | return total_read; |
1850 | } | 1781 | } |
1851 | 1782 | ||
1852 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1783 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
1853 | size_t read_size, loff_t *poffset) | ||
1854 | { | ||
1855 | struct iovec iov; | ||
1856 | iov.iov_base = read_data; | ||
1857 | iov.iov_len = read_size; | ||
1858 | |||
1859 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
1860 | } | ||
1861 | |||
1862 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1863 | unsigned long nr_segs, loff_t pos) | 1784 | unsigned long nr_segs, loff_t pos) |
1864 | { | 1785 | { |
1865 | ssize_t read; | 1786 | ssize_t read; |
@@ -1987,8 +1908,11 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | |||
1987 | 1908 | ||
1988 | xid = GetXid(); | 1909 | xid = GetXid(); |
1989 | 1910 | ||
1990 | if (!CIFS_I(inode)->clientCanCacheRead) | 1911 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1991 | cifs_invalidate_mapping(inode); | 1912 | rc = cifs_invalidate_mapping(inode); |
1913 | if (rc) | ||
1914 | return rc; | ||
1915 | } | ||
1992 | 1916 | ||
1993 | rc = generic_file_mmap(file, vma); | 1917 | rc = generic_file_mmap(file, vma); |
1994 | if (rc == 0) | 1918 | if (rc == 0) |
@@ -2415,6 +2339,27 @@ static void cifs_invalidate_page(struct page *page, unsigned long offset) | |||
2415 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | 2339 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); |
2416 | } | 2340 | } |
2417 | 2341 | ||
2342 | static int cifs_launder_page(struct page *page) | ||
2343 | { | ||
2344 | int rc = 0; | ||
2345 | loff_t range_start = page_offset(page); | ||
2346 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | ||
2347 | struct writeback_control wbc = { | ||
2348 | .sync_mode = WB_SYNC_ALL, | ||
2349 | .nr_to_write = 0, | ||
2350 | .range_start = range_start, | ||
2351 | .range_end = range_end, | ||
2352 | }; | ||
2353 | |||
2354 | cFYI(1, "Launder page: %p", page); | ||
2355 | |||
2356 | if (clear_page_dirty_for_io(page)) | ||
2357 | rc = cifs_writepage_locked(page, &wbc); | ||
2358 | |||
2359 | cifs_fscache_invalidate_page(page, page->mapping->host); | ||
2360 | return rc; | ||
2361 | } | ||
2362 | |||
2418 | void cifs_oplock_break(struct work_struct *work) | 2363 | void cifs_oplock_break(struct work_struct *work) |
2419 | { | 2364 | { |
2420 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2365 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
@@ -2486,7 +2431,7 @@ const struct address_space_operations cifs_addr_ops = { | |||
2486 | .set_page_dirty = __set_page_dirty_nobuffers, | 2431 | .set_page_dirty = __set_page_dirty_nobuffers, |
2487 | .releasepage = cifs_release_page, | 2432 | .releasepage = cifs_release_page, |
2488 | .invalidatepage = cifs_invalidate_page, | 2433 | .invalidatepage = cifs_invalidate_page, |
2489 | /* .direct_IO = */ | 2434 | .launder_page = cifs_launder_page, |
2490 | }; | 2435 | }; |
2491 | 2436 | ||
2492 | /* | 2437 | /* |
@@ -2503,5 +2448,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2503 | .set_page_dirty = __set_page_dirty_nobuffers, | 2448 | .set_page_dirty = __set_page_dirty_nobuffers, |
2504 | .releasepage = cifs_release_page, | 2449 | .releasepage = cifs_release_page, |
2505 | .invalidatepage = cifs_invalidate_page, | 2450 | .invalidatepage = cifs_invalidate_page, |
2506 | /* .direct_IO = */ | 2451 | .launder_page = cifs_launder_page, |
2507 | }; | 2452 | }; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8852470b4fbb..de02ed5e25c2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -878,7 +878,7 @@ retry_iget5_locked: | |||
878 | } | 878 | } |
879 | 879 | ||
880 | /* gets root inode */ | 880 | /* gets root inode */ |
881 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 881 | struct inode *cifs_root_iget(struct super_block *sb) |
882 | { | 882 | { |
883 | int xid; | 883 | int xid; |
884 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 884 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
@@ -1683,71 +1683,70 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1683 | /* | 1683 | /* |
1684 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
1685 | */ | 1685 | */ |
1686 | void | 1686 | int |
1687 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
1688 | { | 1688 | { |
1689 | int rc; | 1689 | int rc = 0; |
1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1691 | 1691 | ||
1692 | cifs_i->invalid_mapping = false; | 1692 | cifs_i->invalid_mapping = false; |
1693 | 1693 | ||
1694 | /* write back any cached data */ | ||
1695 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1694 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1696 | rc = filemap_write_and_wait(inode->i_mapping); | 1695 | rc = invalidate_inode_pages2(inode->i_mapping); |
1697 | mapping_set_error(inode->i_mapping, rc); | 1696 | if (rc) { |
1697 | cERROR(1, "%s: could not invalidate inode %p", __func__, | ||
1698 | inode); | ||
1699 | cifs_i->invalid_mapping = true; | ||
1700 | } | ||
1698 | } | 1701 | } |
1699 | invalidate_remote_inode(inode); | 1702 | |
1700 | cifs_fscache_reset_inode_cookie(inode); | 1703 | cifs_fscache_reset_inode_cookie(inode); |
1704 | return rc; | ||
1701 | } | 1705 | } |
1702 | 1706 | ||
1703 | int cifs_revalidate_file(struct file *filp) | 1707 | int cifs_revalidate_file_attr(struct file *filp) |
1704 | { | 1708 | { |
1705 | int rc = 0; | 1709 | int rc = 0; |
1706 | struct inode *inode = filp->f_path.dentry->d_inode; | 1710 | struct inode *inode = filp->f_path.dentry->d_inode; |
1707 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 1711 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; |
1708 | 1712 | ||
1709 | if (!cifs_inode_needs_reval(inode)) | 1713 | if (!cifs_inode_needs_reval(inode)) |
1710 | goto check_inval; | 1714 | return rc; |
1711 | 1715 | ||
1712 | if (tlink_tcon(cfile->tlink)->unix_ext) | 1716 | if (tlink_tcon(cfile->tlink)->unix_ext) |
1713 | rc = cifs_get_file_info_unix(filp); | 1717 | rc = cifs_get_file_info_unix(filp); |
1714 | else | 1718 | else |
1715 | rc = cifs_get_file_info(filp); | 1719 | rc = cifs_get_file_info(filp); |
1716 | 1720 | ||
1717 | check_inval: | ||
1718 | if (CIFS_I(inode)->invalid_mapping) | ||
1719 | cifs_invalidate_mapping(inode); | ||
1720 | |||
1721 | return rc; | 1721 | return rc; |
1722 | } | 1722 | } |
1723 | 1723 | ||
1724 | /* revalidate a dentry's inode attributes */ | 1724 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1725 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1726 | { | 1725 | { |
1727 | int xid; | 1726 | int xid; |
1728 | int rc = 0; | 1727 | int rc = 0; |
1729 | char *full_path = NULL; | ||
1730 | struct inode *inode = dentry->d_inode; | 1728 | struct inode *inode = dentry->d_inode; |
1731 | struct super_block *sb = dentry->d_sb; | 1729 | struct super_block *sb = dentry->d_sb; |
1730 | char *full_path = NULL; | ||
1732 | 1731 | ||
1733 | if (inode == NULL) | 1732 | if (inode == NULL) |
1734 | return -ENOENT; | 1733 | return -ENOENT; |
1735 | 1734 | ||
1736 | xid = GetXid(); | ||
1737 | |||
1738 | if (!cifs_inode_needs_reval(inode)) | 1735 | if (!cifs_inode_needs_reval(inode)) |
1739 | goto check_inval; | 1736 | return rc; |
1737 | |||
1738 | xid = GetXid(); | ||
1740 | 1739 | ||
1741 | /* can not safely grab the rename sem here if rename calls revalidate | 1740 | /* can not safely grab the rename sem here if rename calls revalidate |
1742 | since that would deadlock */ | 1741 | since that would deadlock */ |
1743 | full_path = build_path_from_dentry(dentry); | 1742 | full_path = build_path_from_dentry(dentry); |
1744 | if (full_path == NULL) { | 1743 | if (full_path == NULL) { |
1745 | rc = -ENOMEM; | 1744 | rc = -ENOMEM; |
1746 | goto check_inval; | 1745 | goto out; |
1747 | } | 1746 | } |
1748 | 1747 | ||
1749 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1748 | cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " |
1750 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1749 | "%ld jiffies %ld", full_path, inode, inode->i_count.counter, |
1751 | dentry, dentry->d_time, jiffies); | 1750 | dentry, dentry->d_time, jiffies); |
1752 | 1751 | ||
1753 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) | 1752 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
@@ -1756,41 +1755,83 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
1756 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1755 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
1757 | xid, NULL); | 1756 | xid, NULL); |
1758 | 1757 | ||
1759 | check_inval: | 1758 | out: |
1760 | if (CIFS_I(inode)->invalid_mapping) | ||
1761 | cifs_invalidate_mapping(inode); | ||
1762 | |||
1763 | kfree(full_path); | 1759 | kfree(full_path); |
1764 | FreeXid(xid); | 1760 | FreeXid(xid); |
1765 | return rc; | 1761 | return rc; |
1766 | } | 1762 | } |
1767 | 1763 | ||
1764 | int cifs_revalidate_file(struct file *filp) | ||
1765 | { | ||
1766 | int rc; | ||
1767 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1768 | |||
1769 | rc = cifs_revalidate_file_attr(filp); | ||
1770 | if (rc) | ||
1771 | return rc; | ||
1772 | |||
1773 | if (CIFS_I(inode)->invalid_mapping) | ||
1774 | rc = cifs_invalidate_mapping(inode); | ||
1775 | return rc; | ||
1776 | } | ||
1777 | |||
1778 | /* revalidate a dentry's inode attributes */ | ||
1779 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1780 | { | ||
1781 | int rc; | ||
1782 | struct inode *inode = dentry->d_inode; | ||
1783 | |||
1784 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1785 | if (rc) | ||
1786 | return rc; | ||
1787 | |||
1788 | if (CIFS_I(inode)->invalid_mapping) | ||
1789 | rc = cifs_invalidate_mapping(inode); | ||
1790 | return rc; | ||
1791 | } | ||
1792 | |||
1768 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1793 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1769 | struct kstat *stat) | 1794 | struct kstat *stat) |
1770 | { | 1795 | { |
1771 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); | 1796 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); |
1772 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 1797 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); |
1773 | int err = cifs_revalidate_dentry(dentry); | 1798 | struct inode *inode = dentry->d_inode; |
1774 | 1799 | int rc; | |
1775 | if (!err) { | ||
1776 | generic_fillattr(dentry->d_inode, stat); | ||
1777 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1778 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1779 | 1800 | ||
1780 | /* | 1801 | /* |
1781 | * If on a multiuser mount without unix extensions, and the | 1802 | * We need to be sure that all dirty pages are written and the server |
1782 | * admin hasn't overridden them, set the ownership to the | 1803 | * has actual ctime, mtime and file length. |
1783 | * fsuid/fsgid of the current process. | 1804 | */ |
1784 | */ | 1805 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
1785 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | 1806 | inode->i_mapping->nrpages != 0) { |
1786 | !tcon->unix_ext) { | 1807 | rc = filemap_fdatawait(inode->i_mapping); |
1787 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | 1808 | if (rc) { |
1788 | stat->uid = current_fsuid(); | 1809 | mapping_set_error(inode->i_mapping, rc); |
1789 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | 1810 | return rc; |
1790 | stat->gid = current_fsgid(); | ||
1791 | } | 1811 | } |
1792 | } | 1812 | } |
1793 | return err; | 1813 | |
1814 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1815 | if (rc) | ||
1816 | return rc; | ||
1817 | |||
1818 | generic_fillattr(inode, stat); | ||
1819 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1820 | stat->ino = CIFS_I(inode)->uniqueid; | ||
1821 | |||
1822 | /* | ||
1823 | * If on a multiuser mount without unix extensions, and the admin hasn't | ||
1824 | * overridden them, set the ownership to the fsuid/fsgid of the current | ||
1825 | * process. | ||
1826 | */ | ||
1827 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
1828 | !tcon->unix_ext) { | ||
1829 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
1830 | stat->uid = current_fsuid(); | ||
1831 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
1832 | stat->gid = current_fsgid(); | ||
1833 | } | ||
1834 | return rc; | ||
1794 | } | 1835 | } |
1795 | 1836 | ||
1796 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) | 1837 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 0c684ae4c071..907531ac5888 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -304,12 +304,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
304 | 304 | ||
305 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ | 305 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ |
306 | 306 | ||
307 | buffer->smb_buf_length = | 307 | buffer->smb_buf_length = cpu_to_be32( |
308 | (2 * word_count) + sizeof(struct smb_hdr) - | 308 | (2 * word_count) + sizeof(struct smb_hdr) - |
309 | 4 /* RFC 1001 length field does not count */ + | 309 | 4 /* RFC 1001 length field does not count */ + |
310 | 2 /* for bcc field itself */ ; | 310 | 2 /* for bcc field itself */) ; |
311 | /* Note that this is the only network field that has to be converted | ||
312 | to big endian and it is done just before we send it */ | ||
313 | 311 | ||
314 | buffer->Protocol[0] = 0xFF; | 312 | buffer->Protocol[0] = 0xFF; |
315 | buffer->Protocol[1] = 'S'; | 313 | buffer->Protocol[1] = 'S'; |
@@ -424,7 +422,7 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid) | |||
424 | int | 422 | int |
425 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | 423 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) |
426 | { | 424 | { |
427 | __u32 len = smb->smb_buf_length; | 425 | __u32 len = be32_to_cpu(smb->smb_buf_length); |
428 | __u32 clc_len; /* calculated length */ | 426 | __u32 clc_len; /* calculated length */ |
429 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); | 427 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); |
430 | 428 | ||
@@ -464,7 +462,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | |||
464 | 462 | ||
465 | if (check_smb_hdr(smb, mid)) | 463 | if (check_smb_hdr(smb, mid)) |
466 | return 1; | 464 | return 1; |
467 | clc_len = smbCalcSize_LE(smb); | 465 | clc_len = smbCalcSize(smb); |
468 | 466 | ||
469 | if (4 + len != length) { | 467 | if (4 + len != length) { |
470 | cERROR(1, "Length read does not match RFC1001 length %d", | 468 | cERROR(1, "Length read does not match RFC1001 length %d", |
@@ -521,7 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
521 | (struct smb_com_transaction_change_notify_rsp *)buf; | 519 | (struct smb_com_transaction_change_notify_rsp *)buf; |
522 | struct file_notify_information *pnotify; | 520 | struct file_notify_information *pnotify; |
523 | __u32 data_offset = 0; | 521 | __u32 data_offset = 0; |
524 | if (get_bcc_le(buf) > sizeof(struct file_notify_information)) { | 522 | if (get_bcc(buf) > sizeof(struct file_notify_information)) { |
525 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 523 | data_offset = le32_to_cpu(pSMBr->DataOffset); |
526 | 524 | ||
527 | pnotify = (struct file_notify_information *) | 525 | pnotify = (struct file_notify_information *) |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 79f641eeda30..79b71c2c7c9d 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -919,13 +919,6 @@ smbCalcSize(struct smb_hdr *ptr) | |||
919 | 2 /* size of the bcc field */ + get_bcc(ptr)); | 919 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
920 | } | 920 | } |
921 | 921 | ||
922 | unsigned int | ||
923 | smbCalcSize_LE(struct smb_hdr *ptr) | ||
924 | { | ||
925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | ||
926 | 2 /* size of the bcc field */ + get_bcc_le(ptr)); | ||
927 | } | ||
928 | |||
929 | /* The following are taken from fs/ntfs/util.c */ | 922 | /* The following are taken from fs/ntfs/util.c */ |
930 | 923 | ||
931 | #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) | 924 | #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index f6728eb6f4b9..7dd462100378 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); |
@@ -634,7 +621,7 @@ ssetup_ntlmssp_authenticate: | |||
634 | and rest of bcc area. This allows us to avoid | 621 | and rest of bcc area. This allows us to avoid |
635 | a large buffer 17K allocation */ | 622 | a large buffer 17K allocation */ |
636 | iov[0].iov_base = (char *)pSMB; | 623 | iov[0].iov_base = (char *)pSMB; |
637 | iov[0].iov_len = smb_buf->smb_buf_length + 4; | 624 | iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4; |
638 | 625 | ||
639 | /* setting this here allows the code at the end of the function | 626 | /* setting this here allows the code at the end of the function |
640 | to free the request buffer if there's an error */ | 627 | to free the request buffer if there's an error */ |
@@ -669,7 +656,7 @@ ssetup_ntlmssp_authenticate: | |||
669 | * to use challenge/response method (i.e. Password bit is 1). | 656 | * to use challenge/response method (i.e. Password bit is 1). |
670 | */ | 657 | */ |
671 | 658 | ||
672 | calc_lanman_hash(ses->password, ses->server->cryptkey, | 659 | rc = calc_lanman_hash(ses->password, ses->server->cryptkey, |
673 | ses->server->secMode & SECMODE_PW_ENCRYPT ? | 660 | ses->server->secMode & SECMODE_PW_ENCRYPT ? |
674 | true : false, lnm_session_key); | 661 | true : false, lnm_session_key); |
675 | 662 | ||
@@ -872,9 +859,10 @@ ssetup_ntlmssp_authenticate: | |||
872 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; | 859 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; |
873 | 860 | ||
874 | count = iov[1].iov_len + iov[2].iov_len; | 861 | count = iov[1].iov_len + iov[2].iov_len; |
875 | smb_buf->smb_buf_length += count; | 862 | smb_buf->smb_buf_length = |
863 | cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count); | ||
876 | 864 | ||
877 | put_bcc_le(count, smb_buf); | 865 | put_bcc(count, smb_buf); |
878 | 866 | ||
879 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, | 867 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
880 | CIFS_LOG_ERROR); | 868 | CIFS_LOG_ERROR); |
@@ -929,7 +917,9 @@ ssetup_ntlmssp_authenticate: | |||
929 | } | 917 | } |
930 | 918 | ||
931 | /* BB check if Unicode and decode strings */ | 919 | /* BB check if Unicode and decode strings */ |
932 | if (smb_buf->Flags2 & SMBFLG2_UNICODE) { | 920 | if (bytes_remaining == 0) { |
921 | /* no string area to decode, do nothing */ | ||
922 | } else if (smb_buf->Flags2 & SMBFLG2_UNICODE) { | ||
933 | /* unicode string area must be word-aligned */ | 923 | /* unicode string area must be word-aligned */ |
934 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { | 924 | if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) { |
935 | ++bcc_ptr; | 925 | ++bcc_ptr; |
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c deleted file mode 100644 index 04721485925d..000000000000 --- a/fs/cifs/smbdes.c +++ /dev/null | |||
@@ -1,418 +0,0 @@ | |||
1 | /* | ||
2 | Unix SMB/Netbios implementation. | ||
3 | Version 1.9. | ||
4 | |||
5 | a partial implementation of DES designed for use in the | ||
6 | SMB authentication protocol | ||
7 | |||
8 | Copyright (C) Andrew Tridgell 1998 | ||
9 | Modified by Steve French (sfrench@us.ibm.com) 2002,2004 | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* NOTES: | ||
27 | |||
28 | This code makes no attempt to be fast! In fact, it is a very | ||
29 | slow implementation | ||
30 | |||
31 | This code is NOT a complete DES implementation. It implements only | ||
32 | the minimum necessary for SMB authentication, as used by all SMB | ||
33 | products (including every copy of Microsoft Windows95 ever sold) | ||
34 | |||
35 | In particular, it can only do a unchained forward DES pass. This | ||
36 | means it is not possible to use this code for encryption/decryption | ||
37 | of data, instead it is only useful as a "hash" algorithm. | ||
38 | |||
39 | There is no entry point into this code that allows normal DES operation. | ||
40 | |||
41 | I believe this means that this code does not come under ITAR | ||
42 | regulations but this is NOT a legal opinion. If you are concerned | ||
43 | about the applicability of ITAR regulations to this code then you | ||
44 | should confirm it for yourself (and maybe let me know if you come | ||
45 | up with a different answer to the one above) | ||
46 | */ | ||
47 | #include <linux/slab.h> | ||
48 | #define uchar unsigned char | ||
49 | |||
50 | static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, | ||
51 | 1, 58, 50, 42, 34, 26, 18, | ||
52 | 10, 2, 59, 51, 43, 35, 27, | ||
53 | 19, 11, 3, 60, 52, 44, 36, | ||
54 | 63, 55, 47, 39, 31, 23, 15, | ||
55 | 7, 62, 54, 46, 38, 30, 22, | ||
56 | 14, 6, 61, 53, 45, 37, 29, | ||
57 | 21, 13, 5, 28, 20, 12, 4 | ||
58 | }; | ||
59 | |||
60 | static uchar perm2[48] = { 14, 17, 11, 24, 1, 5, | ||
61 | 3, 28, 15, 6, 21, 10, | ||
62 | 23, 19, 12, 4, 26, 8, | ||
63 | 16, 7, 27, 20, 13, 2, | ||
64 | 41, 52, 31, 37, 47, 55, | ||
65 | 30, 40, 51, 45, 33, 48, | ||
66 | 44, 49, 39, 56, 34, 53, | ||
67 | 46, 42, 50, 36, 29, 32 | ||
68 | }; | ||
69 | |||
70 | static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2, | ||
71 | 60, 52, 44, 36, 28, 20, 12, 4, | ||
72 | 62, 54, 46, 38, 30, 22, 14, 6, | ||
73 | 64, 56, 48, 40, 32, 24, 16, 8, | ||
74 | 57, 49, 41, 33, 25, 17, 9, 1, | ||
75 | 59, 51, 43, 35, 27, 19, 11, 3, | ||
76 | 61, 53, 45, 37, 29, 21, 13, 5, | ||
77 | 63, 55, 47, 39, 31, 23, 15, 7 | ||
78 | }; | ||
79 | |||
80 | static uchar perm4[48] = { 32, 1, 2, 3, 4, 5, | ||
81 | 4, 5, 6, 7, 8, 9, | ||
82 | 8, 9, 10, 11, 12, 13, | ||
83 | 12, 13, 14, 15, 16, 17, | ||
84 | 16, 17, 18, 19, 20, 21, | ||
85 | 20, 21, 22, 23, 24, 25, | ||
86 | 24, 25, 26, 27, 28, 29, | ||
87 | 28, 29, 30, 31, 32, 1 | ||
88 | }; | ||
89 | |||
90 | static uchar perm5[32] = { 16, 7, 20, 21, | ||
91 | 29, 12, 28, 17, | ||
92 | 1, 15, 23, 26, | ||
93 | 5, 18, 31, 10, | ||
94 | 2, 8, 24, 14, | ||
95 | 32, 27, 3, 9, | ||
96 | 19, 13, 30, 6, | ||
97 | 22, 11, 4, 25 | ||
98 | }; | ||
99 | |||
100 | static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32, | ||
101 | 39, 7, 47, 15, 55, 23, 63, 31, | ||
102 | 38, 6, 46, 14, 54, 22, 62, 30, | ||
103 | 37, 5, 45, 13, 53, 21, 61, 29, | ||
104 | 36, 4, 44, 12, 52, 20, 60, 28, | ||
105 | 35, 3, 43, 11, 51, 19, 59, 27, | ||
106 | 34, 2, 42, 10, 50, 18, 58, 26, | ||
107 | 33, 1, 41, 9, 49, 17, 57, 25 | ||
108 | }; | ||
109 | |||
110 | static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; | ||
111 | |||
112 | static uchar sbox[8][4][16] = { | ||
113 | {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, | ||
114 | {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, | ||
115 | {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, | ||
116 | {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} }, | ||
117 | |||
118 | {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, | ||
119 | {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, | ||
120 | {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, | ||
121 | {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} }, | ||
122 | |||
123 | {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, | ||
124 | {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, | ||
125 | {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, | ||
126 | {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} }, | ||
127 | |||
128 | {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, | ||
129 | {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, | ||
130 | {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, | ||
131 | {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} }, | ||
132 | |||
133 | {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, | ||
134 | {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, | ||
135 | {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, | ||
136 | {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} }, | ||
137 | |||
138 | {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, | ||
139 | {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, | ||
140 | {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, | ||
141 | {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} }, | ||
142 | |||
143 | {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, | ||
144 | {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, | ||
145 | {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, | ||
146 | {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} }, | ||
147 | |||
148 | {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, | ||
149 | {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, | ||
150 | {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, | ||
151 | {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} } | ||
152 | }; | ||
153 | |||
154 | static void | ||
155 | permute(char *out, char *in, uchar *p, int n) | ||
156 | { | ||
157 | int i; | ||
158 | for (i = 0; i < n; i++) | ||
159 | out[i] = in[p[i] - 1]; | ||
160 | } | ||
161 | |||
162 | static void | ||
163 | lshift(char *d, int count, int n) | ||
164 | { | ||
165 | char out[64]; | ||
166 | int i; | ||
167 | for (i = 0; i < n; i++) | ||
168 | out[i] = d[(i + count) % n]; | ||
169 | for (i = 0; i < n; i++) | ||
170 | d[i] = out[i]; | ||
171 | } | ||
172 | |||
173 | static void | ||
174 | concat(char *out, char *in1, char *in2, int l1, int l2) | ||
175 | { | ||
176 | while (l1--) | ||
177 | *out++ = *in1++; | ||
178 | while (l2--) | ||
179 | *out++ = *in2++; | ||
180 | } | ||
181 | |||
182 | static void | ||
183 | xor(char *out, char *in1, char *in2, int n) | ||
184 | { | ||
185 | int i; | ||
186 | for (i = 0; i < n; i++) | ||
187 | out[i] = in1[i] ^ in2[i]; | ||
188 | } | ||
189 | |||
190 | static void | ||
191 | dohash(char *out, char *in, char *key, int forw) | ||
192 | { | ||
193 | int i, j, k; | ||
194 | char *pk1; | ||
195 | char c[28]; | ||
196 | char d[28]; | ||
197 | char *cd; | ||
198 | char (*ki)[48]; | ||
199 | char *pd1; | ||
200 | char l[32], r[32]; | ||
201 | char *rl; | ||
202 | |||
203 | /* Have to reduce stack usage */ | ||
204 | pk1 = kmalloc(56+56+64+64, GFP_KERNEL); | ||
205 | if (pk1 == NULL) | ||
206 | return; | ||
207 | |||
208 | ki = kmalloc(16*48, GFP_KERNEL); | ||
209 | if (ki == NULL) { | ||
210 | kfree(pk1); | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | cd = pk1 + 56; | ||
215 | pd1 = cd + 56; | ||
216 | rl = pd1 + 64; | ||
217 | |||
218 | permute(pk1, key, perm1, 56); | ||
219 | |||
220 | for (i = 0; i < 28; i++) | ||
221 | c[i] = pk1[i]; | ||
222 | for (i = 0; i < 28; i++) | ||
223 | d[i] = pk1[i + 28]; | ||
224 | |||
225 | for (i = 0; i < 16; i++) { | ||
226 | lshift(c, sc[i], 28); | ||
227 | lshift(d, sc[i], 28); | ||
228 | |||
229 | concat(cd, c, d, 28, 28); | ||
230 | permute(ki[i], cd, perm2, 48); | ||
231 | } | ||
232 | |||
233 | permute(pd1, in, perm3, 64); | ||
234 | |||
235 | for (j = 0; j < 32; j++) { | ||
236 | l[j] = pd1[j]; | ||
237 | r[j] = pd1[j + 32]; | ||
238 | } | ||
239 | |||
240 | for (i = 0; i < 16; i++) { | ||
241 | char *er; /* er[48] */ | ||
242 | char *erk; /* erk[48] */ | ||
243 | char b[8][6]; | ||
244 | char *cb; /* cb[32] */ | ||
245 | char *pcb; /* pcb[32] */ | ||
246 | char *r2; /* r2[32] */ | ||
247 | |||
248 | er = kmalloc(48+48+32+32+32, GFP_KERNEL); | ||
249 | if (er == NULL) { | ||
250 | kfree(pk1); | ||
251 | kfree(ki); | ||
252 | return; | ||
253 | } | ||
254 | erk = er+48; | ||
255 | cb = erk+48; | ||
256 | pcb = cb+32; | ||
257 | r2 = pcb+32; | ||
258 | |||
259 | permute(er, r, perm4, 48); | ||
260 | |||
261 | xor(erk, er, ki[forw ? i : 15 - i], 48); | ||
262 | |||
263 | for (j = 0; j < 8; j++) | ||
264 | for (k = 0; k < 6; k++) | ||
265 | b[j][k] = erk[j * 6 + k]; | ||
266 | |||
267 | for (j = 0; j < 8; j++) { | ||
268 | int m, n; | ||
269 | m = (b[j][0] << 1) | b[j][5]; | ||
270 | |||
271 | n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << | ||
272 | 1) | b[j][4]; | ||
273 | |||
274 | for (k = 0; k < 4; k++) | ||
275 | b[j][k] = | ||
276 | (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0; | ||
277 | } | ||
278 | |||
279 | for (j = 0; j < 8; j++) | ||
280 | for (k = 0; k < 4; k++) | ||
281 | cb[j * 4 + k] = b[j][k]; | ||
282 | permute(pcb, cb, perm5, 32); | ||
283 | |||
284 | xor(r2, l, pcb, 32); | ||
285 | |||
286 | for (j = 0; j < 32; j++) | ||
287 | l[j] = r[j]; | ||
288 | |||
289 | for (j = 0; j < 32; j++) | ||
290 | r[j] = r2[j]; | ||
291 | |||
292 | kfree(er); | ||
293 | } | ||
294 | |||
295 | concat(rl, r, l, 32, 32); | ||
296 | |||
297 | permute(out, rl, perm6, 64); | ||
298 | kfree(pk1); | ||
299 | kfree(ki); | ||
300 | } | ||
301 | |||
302 | static void | ||
303 | str_to_key(unsigned char *str, unsigned char *key) | ||
304 | { | ||
305 | int i; | ||
306 | |||
307 | key[0] = str[0] >> 1; | ||
308 | key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); | ||
309 | key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); | ||
310 | key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); | ||
311 | key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); | ||
312 | key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); | ||
313 | key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); | ||
314 | key[7] = str[6] & 0x7F; | ||
315 | for (i = 0; i < 8; i++) | ||
316 | key[i] = (key[i] << 1); | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | smbhash(unsigned char *out, const unsigned char *in, unsigned char *key, | ||
321 | int forw) | ||
322 | { | ||
323 | int i; | ||
324 | char *outb; /* outb[64] */ | ||
325 | char *inb; /* inb[64] */ | ||
326 | char *keyb; /* keyb[64] */ | ||
327 | unsigned char key2[8]; | ||
328 | |||
329 | outb = kmalloc(64 * 3, GFP_KERNEL); | ||
330 | if (outb == NULL) | ||
331 | return; | ||
332 | |||
333 | inb = outb + 64; | ||
334 | keyb = inb + 64; | ||
335 | |||
336 | str_to_key(key, key2); | ||
337 | |||
338 | for (i = 0; i < 64; i++) { | ||
339 | inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; | ||
340 | keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; | ||
341 | outb[i] = 0; | ||
342 | } | ||
343 | |||
344 | dohash(outb, inb, keyb, forw); | ||
345 | |||
346 | for (i = 0; i < 8; i++) | ||
347 | out[i] = 0; | ||
348 | |||
349 | for (i = 0; i < 64; i++) { | ||
350 | if (outb[i]) | ||
351 | out[i / 8] |= (1 << (7 - (i % 8))); | ||
352 | } | ||
353 | kfree(outb); | ||
354 | } | ||
355 | |||
356 | void | ||
357 | E_P16(unsigned char *p14, unsigned char *p16) | ||
358 | { | ||
359 | unsigned char sp8[8] = | ||
360 | { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; | ||
361 | smbhash(p16, sp8, p14, 1); | ||
362 | smbhash(p16 + 8, sp8, p14 + 7, 1); | ||
363 | } | ||
364 | |||
365 | void | ||
366 | E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) | ||
367 | { | ||
368 | smbhash(p24, c8, p21, 1); | ||
369 | smbhash(p24 + 8, c8, p21 + 7, 1); | ||
370 | smbhash(p24 + 16, c8, p21 + 14, 1); | ||
371 | } | ||
372 | |||
373 | #if 0 /* currently unused */ | ||
374 | static void | ||
375 | D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) | ||
376 | { | ||
377 | smbhash(out, in, p14, 0); | ||
378 | smbhash(out + 8, in + 8, p14 + 7, 0); | ||
379 | } | ||
380 | |||
381 | static void | ||
382 | E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out) | ||
383 | { | ||
384 | smbhash(out, in, p14, 1); | ||
385 | smbhash(out + 8, in + 8, p14 + 7, 1); | ||
386 | } | ||
387 | /* these routines are currently unneeded, but may be | ||
388 | needed later */ | ||
389 | void | ||
390 | cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key) | ||
391 | { | ||
392 | unsigned char buf[8]; | ||
393 | |||
394 | smbhash(buf, in, key, 1); | ||
395 | smbhash(out, buf, key + 9, 1); | ||
396 | } | ||
397 | |||
398 | void | ||
399 | cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key) | ||
400 | { | ||
401 | unsigned char buf[8]; | ||
402 | static unsigned char key2[8]; | ||
403 | |||
404 | smbhash(buf, in, key, 1); | ||
405 | key2[0] = key[7]; | ||
406 | smbhash(out, buf, key2, 1); | ||
407 | } | ||
408 | |||
409 | void | ||
410 | cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw) | ||
411 | { | ||
412 | static unsigned char key2[8]; | ||
413 | |||
414 | smbhash(out, in, key, forw); | ||
415 | key2[0] = key[7]; | ||
416 | smbhash(out + 8, in + 8, key2, forw); | ||
417 | } | ||
418 | #endif /* unneeded routines */ | ||
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index b5041c849981..1525d5e662b6 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
@@ -47,6 +47,88 @@ | |||
47 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) | 47 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) |
48 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) | 48 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) |
49 | 49 | ||
50 | static void | ||
51 | str_to_key(unsigned char *str, unsigned char *key) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | key[0] = str[0] >> 1; | ||
56 | key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); | ||
57 | key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); | ||
58 | key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); | ||
59 | key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); | ||
60 | key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); | ||
61 | key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); | ||
62 | key[7] = str[6] & 0x7F; | ||
63 | for (i = 0; i < 8; i++) | ||
64 | key[i] = (key[i] << 1); | ||
65 | } | ||
66 | |||
67 | static int | ||
68 | smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) | ||
69 | { | ||
70 | int rc; | ||
71 | unsigned char key2[8]; | ||
72 | struct crypto_blkcipher *tfm_des; | ||
73 | struct scatterlist sgin, sgout; | ||
74 | struct blkcipher_desc desc; | ||
75 | |||
76 | str_to_key(key, key2); | ||
77 | |||
78 | tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); | ||
79 | if (IS_ERR(tfm_des)) { | ||
80 | rc = PTR_ERR(tfm_des); | ||
81 | cERROR(1, "could not allocate des crypto API\n"); | ||
82 | goto smbhash_err; | ||
83 | } | ||
84 | |||
85 | desc.tfm = tfm_des; | ||
86 | |||
87 | crypto_blkcipher_setkey(tfm_des, key2, 8); | ||
88 | |||
89 | sg_init_one(&sgin, in, 8); | ||
90 | sg_init_one(&sgout, out, 8); | ||
91 | |||
92 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); | ||
93 | if (rc) { | ||
94 | cERROR(1, "could not encrypt crypt key rc: %d\n", rc); | ||
95 | crypto_free_blkcipher(tfm_des); | ||
96 | goto smbhash_err; | ||
97 | } | ||
98 | |||
99 | smbhash_err: | ||
100 | return rc; | ||
101 | } | ||
102 | |||
103 | static int | ||
104 | E_P16(unsigned char *p14, unsigned char *p16) | ||
105 | { | ||
106 | int rc; | ||
107 | unsigned char sp8[8] = | ||
108 | { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; | ||
109 | |||
110 | rc = smbhash(p16, sp8, p14); | ||
111 | if (rc) | ||
112 | return rc; | ||
113 | rc = smbhash(p16 + 8, sp8, p14 + 7); | ||
114 | return rc; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) | ||
119 | { | ||
120 | int rc; | ||
121 | |||
122 | rc = smbhash(p24, c8, p21); | ||
123 | if (rc) | ||
124 | return rc; | ||
125 | rc = smbhash(p24 + 8, c8, p21 + 7); | ||
126 | if (rc) | ||
127 | return rc; | ||
128 | rc = smbhash(p24 + 16, c8, p21 + 14); | ||
129 | return rc; | ||
130 | } | ||
131 | |||
50 | /* produce a md4 message digest from data of length n bytes */ | 132 | /* produce a md4 message digest from data of length n bytes */ |
51 | int | 133 | int |
52 | mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) | 134 | mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) |
@@ -87,40 +169,30 @@ mdfour_err: | |||
87 | return rc; | 169 | return rc; |
88 | } | 170 | } |
89 | 171 | ||
90 | /* Does the des encryption from the NT or LM MD4 hash. */ | ||
91 | static void | ||
92 | SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, | ||
93 | unsigned char p24[24]) | ||
94 | { | ||
95 | unsigned char p21[21]; | ||
96 | |||
97 | memset(p21, '\0', 21); | ||
98 | |||
99 | memcpy(p21, passwd, 16); | ||
100 | E_P24(p21, c8, p24); | ||
101 | } | ||
102 | |||
103 | /* | 172 | /* |
104 | This implements the X/Open SMB password encryption | 173 | This implements the X/Open SMB password encryption |
105 | It takes a password, a 8 byte "crypt key" and puts 24 bytes of | 174 | It takes a password, a 8 byte "crypt key" and puts 24 bytes of |
106 | encrypted password into p24 */ | 175 | encrypted password into p24 */ |
107 | /* Note that password must be uppercased and null terminated */ | 176 | /* Note that password must be uppercased and null terminated */ |
108 | void | 177 | int |
109 | SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) | 178 | SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) |
110 | { | 179 | { |
111 | unsigned char p14[15], p21[21]; | 180 | int rc; |
181 | unsigned char p14[14], p16[16], p21[21]; | ||
112 | 182 | ||
113 | memset(p21, '\0', 21); | ||
114 | memset(p14, '\0', 14); | 183 | memset(p14, '\0', 14); |
115 | strncpy((char *) p14, (char *) passwd, 14); | 184 | memset(p16, '\0', 16); |
185 | memset(p21, '\0', 21); | ||
116 | 186 | ||
117 | /* strupper((char *)p14); *//* BB at least uppercase the easy range */ | 187 | memcpy(p14, passwd, 14); |
118 | E_P16(p14, p21); | 188 | rc = E_P16(p14, p16); |
189 | if (rc) | ||
190 | return rc; | ||
119 | 191 | ||
120 | SMBOWFencrypt(p21, c8, p24); | 192 | memcpy(p21, p16, 16); |
193 | rc = E_P24(p21, c8, p24); | ||
121 | 194 | ||
122 | memset(p14, 0, 15); | 195 | return rc; |
123 | memset(p21, 0, 21); | ||
124 | } | 196 | } |
125 | 197 | ||
126 | /* Routines for Windows NT MD4 Hash functions. */ | 198 | /* Routines for Windows NT MD4 Hash functions. */ |
@@ -279,16 +351,18 @@ int | |||
279 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) | 351 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) |
280 | { | 352 | { |
281 | int rc; | 353 | int rc; |
282 | unsigned char p21[21]; | 354 | unsigned char p16[16], p21[21]; |
283 | 355 | ||
356 | memset(p16, '\0', 16); | ||
284 | memset(p21, '\0', 21); | 357 | memset(p21, '\0', 21); |
285 | 358 | ||
286 | rc = E_md4hash(passwd, p21); | 359 | rc = E_md4hash(passwd, p16); |
287 | if (rc) { | 360 | if (rc) { |
288 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); | 361 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); |
289 | return rc; | 362 | return rc; |
290 | } | 363 | } |
291 | SMBOWFencrypt(p21, c8, p24); | 364 | memcpy(p21, p16, 16); |
365 | rc = E_P24(p21, c8, p24); | ||
292 | return rc; | 366 | return rc; |
293 | } | 367 | } |
294 | 368 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 46d8756f2b24..f2513fb8c391 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -129,7 +129,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
129 | unsigned int len = iov[0].iov_len; | 129 | unsigned int len = iov[0].iov_len; |
130 | unsigned int total_len; | 130 | unsigned int total_len; |
131 | int first_vec = 0; | 131 | int first_vec = 0; |
132 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; | 132 | unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); |
133 | struct socket *ssocket = server->ssocket; | 133 | struct socket *ssocket = server->ssocket; |
134 | 134 | ||
135 | if (ssocket == NULL) | 135 | if (ssocket == NULL) |
@@ -144,17 +144,10 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
144 | else | 144 | else |
145 | smb_msg.msg_flags = MSG_NOSIGNAL; | 145 | smb_msg.msg_flags = MSG_NOSIGNAL; |
146 | 146 | ||
147 | /* smb header is converted in header_assemble. bcc and rest of SMB word | ||
148 | area, and byte area if necessary, is converted to littleendian in | ||
149 | cifssmb.c and RFC1001 len is converted to bigendian in smb_send | ||
150 | Flags2 is converted in SendReceive */ | ||
151 | |||
152 | |||
153 | total_len = 0; | 147 | total_len = 0; |
154 | for (i = 0; i < n_vec; i++) | 148 | for (i = 0; i < n_vec; i++) |
155 | total_len += iov[i].iov_len; | 149 | total_len += iov[i].iov_len; |
156 | 150 | ||
157 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); | ||
158 | cFYI(1, "Sending smb: total_len %d", total_len); | 151 | cFYI(1, "Sending smb: total_len %d", total_len); |
159 | dump_smb(smb_buffer, len); | 152 | dump_smb(smb_buffer, len); |
160 | 153 | ||
@@ -243,7 +236,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
243 | 236 | ||
244 | /* Don't want to modify the buffer as a | 237 | /* Don't want to modify the buffer as a |
245 | side effect of this call. */ | 238 | side effect of this call. */ |
246 | smb_buffer->smb_buf_length = smb_buf_length; | 239 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length); |
247 | 240 | ||
248 | return rc; | 241 | return rc; |
249 | } | 242 | } |
@@ -387,7 +380,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
387 | #ifdef CONFIG_CIFS_STATS2 | 380 | #ifdef CONFIG_CIFS_STATS2 |
388 | atomic_inc(&server->inSend); | 381 | atomic_inc(&server->inSend); |
389 | #endif | 382 | #endif |
390 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | 383 | rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
391 | #ifdef CONFIG_CIFS_STATS2 | 384 | #ifdef CONFIG_CIFS_STATS2 |
392 | atomic_dec(&server->inSend); | 385 | atomic_dec(&server->inSend); |
393 | mid->when_sent = jiffies; | 386 | mid->when_sent = jiffies; |
@@ -422,7 +415,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | |||
422 | int resp_buf_type; | 415 | int resp_buf_type; |
423 | 416 | ||
424 | iov[0].iov_base = (char *)in_buf; | 417 | iov[0].iov_base = (char *)in_buf; |
425 | iov[0].iov_len = in_buf->smb_buf_length + 4; | 418 | iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; |
426 | flags |= CIFS_NO_RESP; | 419 | flags |= CIFS_NO_RESP; |
427 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | 420 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); |
428 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); | 421 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); |
@@ -488,10 +481,10 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
488 | int rc = 0; | 481 | int rc = 0; |
489 | 482 | ||
490 | /* -4 for RFC1001 length and +2 for BCC field */ | 483 | /* -4 for RFC1001 length and +2 for BCC field */ |
491 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; | 484 | in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); |
492 | in_buf->Command = SMB_COM_NT_CANCEL; | 485 | in_buf->Command = SMB_COM_NT_CANCEL; |
493 | in_buf->WordCount = 0; | 486 | in_buf->WordCount = 0; |
494 | put_bcc_le(0, in_buf); | 487 | put_bcc(0, in_buf); |
495 | 488 | ||
496 | mutex_lock(&server->srv_mutex); | 489 | mutex_lock(&server->srv_mutex); |
497 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | 490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); |
@@ -499,7 +492,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
499 | mutex_unlock(&server->srv_mutex); | 492 | mutex_unlock(&server->srv_mutex); |
500 | return rc; | 493 | return rc; |
501 | } | 494 | } |
502 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | 495 | rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
503 | mutex_unlock(&server->srv_mutex); | 496 | mutex_unlock(&server->srv_mutex); |
504 | 497 | ||
505 | cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", | 498 | cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", |
@@ -612,7 +605,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
612 | return rc; | 605 | return rc; |
613 | } | 606 | } |
614 | 607 | ||
615 | receive_len = midQ->resp_buf->smb_buf_length; | 608 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
616 | 609 | ||
617 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 610 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
618 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 611 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
@@ -651,11 +644,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
651 | rc = map_smb_to_linux_error(midQ->resp_buf, | 644 | rc = map_smb_to_linux_error(midQ->resp_buf, |
652 | flags & CIFS_LOG_ERROR); | 645 | flags & CIFS_LOG_ERROR); |
653 | 646 | ||
654 | /* convert ByteCount if necessary */ | ||
655 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
656 | /* do not count RFC1001 header */ + | ||
657 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | ||
658 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); | ||
659 | if ((flags & CIFS_NO_RESP) == 0) | 647 | if ((flags & CIFS_NO_RESP) == 0) |
660 | midQ->resp_buf = NULL; /* mark it so buf will | 648 | midQ->resp_buf = NULL; /* mark it so buf will |
661 | not be freed by | 649 | not be freed by |
@@ -698,9 +686,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
698 | to the same server. We may make this configurable later or | 686 | to the same server. We may make this configurable later or |
699 | use ses->maxReq */ | 687 | use ses->maxReq */ |
700 | 688 | ||
701 | if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 689 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + |
690 | MAX_CIFS_HDR_SIZE - 4) { | ||
702 | cERROR(1, "Illegal length, greater than maximum frame, %d", | 691 | cERROR(1, "Illegal length, greater than maximum frame, %d", |
703 | in_buf->smb_buf_length); | 692 | be32_to_cpu(in_buf->smb_buf_length)); |
704 | return -EIO; | 693 | return -EIO; |
705 | } | 694 | } |
706 | 695 | ||
@@ -733,7 +722,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
733 | #ifdef CONFIG_CIFS_STATS2 | 722 | #ifdef CONFIG_CIFS_STATS2 |
734 | atomic_inc(&ses->server->inSend); | 723 | atomic_inc(&ses->server->inSend); |
735 | #endif | 724 | #endif |
736 | rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length); | 725 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
737 | #ifdef CONFIG_CIFS_STATS2 | 726 | #ifdef CONFIG_CIFS_STATS2 |
738 | atomic_dec(&ses->server->inSend); | 727 | atomic_dec(&ses->server->inSend); |
739 | midQ->when_sent = jiffies; | 728 | midQ->when_sent = jiffies; |
@@ -768,7 +757,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
768 | return rc; | 757 | return rc; |
769 | } | 758 | } |
770 | 759 | ||
771 | receive_len = midQ->resp_buf->smb_buf_length; | 760 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
772 | 761 | ||
773 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 762 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
774 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 763 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
@@ -781,7 +770,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
781 | 770 | ||
782 | if (midQ->resp_buf && out_buf | 771 | if (midQ->resp_buf && out_buf |
783 | && (midQ->midState == MID_RESPONSE_RECEIVED)) { | 772 | && (midQ->midState == MID_RESPONSE_RECEIVED)) { |
784 | out_buf->smb_buf_length = receive_len; | 773 | out_buf->smb_buf_length = cpu_to_be32(receive_len); |
785 | memcpy((char *)out_buf + 4, | 774 | memcpy((char *)out_buf + 4, |
786 | (char *)midQ->resp_buf + 4, | 775 | (char *)midQ->resp_buf + 4, |
787 | receive_len); | 776 | receive_len); |
@@ -800,16 +789,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
800 | } | 789 | } |
801 | } | 790 | } |
802 | 791 | ||
803 | *pbytes_returned = out_buf->smb_buf_length; | 792 | *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length); |
804 | 793 | ||
805 | /* BB special case reconnect tid and uid here? */ | 794 | /* BB special case reconnect tid and uid here? */ |
806 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); | 795 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
807 | |||
808 | /* convert ByteCount if necessary */ | ||
809 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
810 | /* do not count RFC1001 header */ + | ||
811 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | ||
812 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); | ||
813 | } else { | 796 | } else { |
814 | rc = -EIO; | 797 | rc = -EIO; |
815 | cERROR(1, "Bad MID state?"); | 798 | cERROR(1, "Bad MID state?"); |
@@ -877,9 +860,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
877 | to the same server. We may make this configurable later or | 860 | to the same server. We may make this configurable later or |
878 | use ses->maxReq */ | 861 | use ses->maxReq */ |
879 | 862 | ||
880 | if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 863 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + |
864 | MAX_CIFS_HDR_SIZE - 4) { | ||
881 | cERROR(1, "Illegal length, greater than maximum frame, %d", | 865 | cERROR(1, "Illegal length, greater than maximum frame, %d", |
882 | in_buf->smb_buf_length); | 866 | be32_to_cpu(in_buf->smb_buf_length)); |
883 | return -EIO; | 867 | return -EIO; |
884 | } | 868 | } |
885 | 869 | ||
@@ -910,7 +894,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
910 | #ifdef CONFIG_CIFS_STATS2 | 894 | #ifdef CONFIG_CIFS_STATS2 |
911 | atomic_inc(&ses->server->inSend); | 895 | atomic_inc(&ses->server->inSend); |
912 | #endif | 896 | #endif |
913 | rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length); | 897 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
914 | #ifdef CONFIG_CIFS_STATS2 | 898 | #ifdef CONFIG_CIFS_STATS2 |
915 | atomic_dec(&ses->server->inSend); | 899 | atomic_dec(&ses->server->inSend); |
916 | midQ->when_sent = jiffies; | 900 | midQ->when_sent = jiffies; |
@@ -977,7 +961,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
977 | if (rc != 0) | 961 | if (rc != 0) |
978 | return rc; | 962 | return rc; |
979 | 963 | ||
980 | receive_len = midQ->resp_buf->smb_buf_length; | 964 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
981 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 965 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
982 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 966 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
983 | receive_len, xid); | 967 | receive_len, xid); |
@@ -993,7 +977,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
993 | goto out; | 977 | goto out; |
994 | } | 978 | } |
995 | 979 | ||
996 | out_buf->smb_buf_length = receive_len; | 980 | out_buf->smb_buf_length = cpu_to_be32(receive_len); |
997 | memcpy((char *)out_buf + 4, | 981 | memcpy((char *)out_buf + 4, |
998 | (char *)midQ->resp_buf + 4, | 982 | (char *)midQ->resp_buf + 4, |
999 | receive_len); | 983 | receive_len); |
@@ -1012,17 +996,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
1012 | } | 996 | } |
1013 | } | 997 | } |
1014 | 998 | ||
1015 | *pbytes_returned = out_buf->smb_buf_length; | 999 | *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length); |
1016 | 1000 | ||
1017 | /* BB special case reconnect tid and uid here? */ | 1001 | /* BB special case reconnect tid and uid here? */ |
1018 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); | 1002 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
1019 | 1003 | ||
1020 | /* convert ByteCount if necessary */ | ||
1021 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
1022 | /* do not count RFC1001 header */ + | ||
1023 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | ||
1024 | put_bcc(get_bcc_le(out_buf), out_buf); | ||
1025 | |||
1026 | out: | 1004 | out: |
1027 | delete_mid(midQ); | 1005 | delete_mid(midQ); |
1028 | if (rstart && rc == -EACCES) | 1006 | if (rstart && rc == -EACCES) |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index eae2a1491608..912995e013ec 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -112,6 +112,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
112 | struct cifsTconInfo *pTcon; | 112 | struct cifsTconInfo *pTcon; |
113 | struct super_block *sb; | 113 | struct super_block *sb; |
114 | char *full_path; | 114 | char *full_path; |
115 | struct cifs_ntsd *pacl; | ||
115 | 116 | ||
116 | if (direntry == NULL) | 117 | if (direntry == NULL) |
117 | return -EIO; | 118 | return -EIO; |
@@ -166,6 +167,25 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
166 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 167 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, |
167 | (__u16)value_size, cifs_sb->local_nls, | 168 | (__u16)value_size, cifs_sb->local_nls, |
168 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 169 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
172 | pacl = kmalloc(value_size, GFP_KERNEL); | ||
173 | if (!pacl) { | ||
174 | cFYI(1, "%s: Can't allocate memory for ACL", | ||
175 | __func__); | ||
176 | rc = -ENOMEM; | ||
177 | } else { | ||
178 | #ifdef CONFIG_CIFS_ACL | ||
179 | memcpy(pacl, ea_value, value_size); | ||
180 | rc = set_cifs_acl(pacl, value_size, | ||
181 | direntry->d_inode, full_path); | ||
182 | if (rc == 0) /* force revalidate of the inode */ | ||
183 | CIFS_I(direntry->d_inode)->time = 0; | ||
184 | kfree(pacl); | ||
185 | #else | ||
186 | cFYI(1, "Set CIFS ACL not supported yet"); | ||
187 | #endif /* CONFIG_CIFS_ACL */ | ||
188 | } | ||
169 | } else { | 189 | } else { |
170 | int temp; | 190 | int temp; |
171 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 191 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
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..18b2a1f10ed8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/hardirq.h> | 35 | #include <linux/hardirq.h> |
36 | #include <linux/bit_spinlock.h> | 36 | #include <linux/bit_spinlock.h> |
37 | #include <linux/rculist_bl.h> | 37 | #include <linux/rculist_bl.h> |
38 | #include <linux/prefetch.h> | ||
38 | #include "internal.h" | 39 | #include "internal.h" |
39 | 40 | ||
40 | /* | 41 | /* |
@@ -99,12 +100,9 @@ static struct kmem_cache *dentry_cache __read_mostly; | |||
99 | static unsigned int d_hash_mask __read_mostly; | 100 | static unsigned int d_hash_mask __read_mostly; |
100 | static unsigned int d_hash_shift __read_mostly; | 101 | static unsigned int d_hash_shift __read_mostly; |
101 | 102 | ||
102 | struct dcache_hash_bucket { | 103 | 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 | 104 | ||
107 | static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, | 105 | static inline struct hlist_bl_head *d_hash(struct dentry *parent, |
108 | unsigned long hash) | 106 | unsigned long hash) |
109 | { | 107 | { |
110 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; | 108 | hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES; |
@@ -112,16 +110,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent, | |||
112 | return dentry_hashtable + (hash & D_HASHMASK); | 110 | return dentry_hashtable + (hash & D_HASHMASK); |
113 | } | 111 | } |
114 | 112 | ||
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. */ | 113 | /* Statistics gathering. */ |
126 | struct dentry_stat_t dentry_stat = { | 114 | struct dentry_stat_t dentry_stat = { |
127 | .age_limit = 45, | 115 | .age_limit = 45, |
@@ -167,8 +155,8 @@ static void d_free(struct dentry *dentry) | |||
167 | if (dentry->d_op && dentry->d_op->d_release) | 155 | if (dentry->d_op && dentry->d_op->d_release) |
168 | dentry->d_op->d_release(dentry); | 156 | dentry->d_op->d_release(dentry); |
169 | 157 | ||
170 | /* if dentry was never inserted into hash, immediate free is OK */ | 158 | /* if dentry was never visible to RCU, immediate free is OK */ |
171 | if (hlist_bl_unhashed(&dentry->d_hash)) | 159 | if (!(dentry->d_flags & DCACHE_RCUACCESS)) |
172 | __d_free(&dentry->d_u.d_rcu); | 160 | __d_free(&dentry->d_u.d_rcu); |
173 | else | 161 | else |
174 | call_rcu(&dentry->d_u.d_rcu, __d_free); | 162 | call_rcu(&dentry->d_u.d_rcu, __d_free); |
@@ -330,28 +318,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
330 | */ | 318 | */ |
331 | void __d_drop(struct dentry *dentry) | 319 | void __d_drop(struct dentry *dentry) |
332 | { | 320 | { |
333 | if (!(dentry->d_flags & DCACHE_UNHASHED)) { | 321 | if (!d_unhashed(dentry)) { |
334 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) { | 322 | struct hlist_bl_head *b; |
335 | bit_spin_lock(0, | 323 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) |
336 | (unsigned long *)&dentry->d_sb->s_anon.first); | 324 | b = &dentry->d_sb->s_anon; |
337 | dentry->d_flags |= DCACHE_UNHASHED; | 325 | 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); | 326 | b = d_hash(dentry->d_parent, dentry->d_name.hash); |
344 | spin_lock_bucket(b); | 327 | |
345 | /* | 328 | hlist_bl_lock(b); |
346 | * We may not actually need to put DCACHE_UNHASHED | 329 | __hlist_bl_del(&dentry->d_hash); |
347 | * manipulations under the hash lock, but follow | 330 | dentry->d_hash.pprev = NULL; |
348 | * the principle of least surprise. | 331 | hlist_bl_unlock(b); |
349 | */ | 332 | |
350 | dentry->d_flags |= DCACHE_UNHASHED; | 333 | dentry_rcuwalk_barrier(dentry); |
351 | hlist_bl_del_rcu(&dentry->d_hash); | ||
352 | spin_unlock_bucket(b); | ||
353 | dentry_rcuwalk_barrier(dentry); | ||
354 | } | ||
355 | } | 334 | } |
356 | } | 335 | } |
357 | EXPORT_SYMBOL(__d_drop); | 336 | EXPORT_SYMBOL(__d_drop); |
@@ -1304,7 +1283,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1304 | dname[name->len] = 0; | 1283 | dname[name->len] = 0; |
1305 | 1284 | ||
1306 | dentry->d_count = 1; | 1285 | dentry->d_count = 1; |
1307 | dentry->d_flags = DCACHE_UNHASHED; | 1286 | dentry->d_flags = 0; |
1308 | spin_lock_init(&dentry->d_lock); | 1287 | spin_lock_init(&dentry->d_lock); |
1309 | seqcount_init(&dentry->d_seq); | 1288 | seqcount_init(&dentry->d_seq); |
1310 | dentry->d_inode = NULL; | 1289 | dentry->d_inode = NULL; |
@@ -1606,10 +1585,9 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1606 | tmp->d_inode = inode; | 1585 | tmp->d_inode = inode; |
1607 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1586 | tmp->d_flags |= DCACHE_DISCONNECTED; |
1608 | list_add(&tmp->d_alias, &inode->i_dentry); | 1587 | list_add(&tmp->d_alias, &inode->i_dentry); |
1609 | bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first); | 1588 | 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); | 1589 | 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); | 1590 | hlist_bl_unlock(&tmp->d_sb->s_anon); |
1613 | spin_unlock(&tmp->d_lock); | 1591 | spin_unlock(&tmp->d_lock); |
1614 | spin_unlock(&inode->i_lock); | 1592 | spin_unlock(&inode->i_lock); |
1615 | security_d_instantiate(tmp, inode); | 1593 | security_d_instantiate(tmp, inode); |
@@ -1789,7 +1767,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1789 | unsigned int len = name->len; | 1767 | unsigned int len = name->len; |
1790 | unsigned int hash = name->hash; | 1768 | unsigned int hash = name->hash; |
1791 | const unsigned char *str = name->name; | 1769 | const unsigned char *str = name->name; |
1792 | struct dcache_hash_bucket *b = d_hash(parent, hash); | 1770 | struct hlist_bl_head *b = d_hash(parent, hash); |
1793 | struct hlist_bl_node *node; | 1771 | struct hlist_bl_node *node; |
1794 | struct dentry *dentry; | 1772 | struct dentry *dentry; |
1795 | 1773 | ||
@@ -1813,7 +1791,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name, | |||
1813 | * | 1791 | * |
1814 | * See Documentation/filesystems/path-lookup.txt for more details. | 1792 | * See Documentation/filesystems/path-lookup.txt for more details. |
1815 | */ | 1793 | */ |
1816 | hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { | 1794 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { |
1817 | struct inode *i; | 1795 | struct inode *i; |
1818 | const char *tname; | 1796 | const char *tname; |
1819 | int tlen; | 1797 | int tlen; |
@@ -1908,7 +1886,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) | |||
1908 | unsigned int len = name->len; | 1886 | unsigned int len = name->len; |
1909 | unsigned int hash = name->hash; | 1887 | unsigned int hash = name->hash; |
1910 | const unsigned char *str = name->name; | 1888 | const unsigned char *str = name->name; |
1911 | struct dcache_hash_bucket *b = d_hash(parent, hash); | 1889 | struct hlist_bl_head *b = d_hash(parent, hash); |
1912 | struct hlist_bl_node *node; | 1890 | struct hlist_bl_node *node; |
1913 | struct dentry *found = NULL; | 1891 | struct dentry *found = NULL; |
1914 | struct dentry *dentry; | 1892 | struct dentry *dentry; |
@@ -1935,7 +1913,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name) | |||
1935 | */ | 1913 | */ |
1936 | rcu_read_lock(); | 1914 | rcu_read_lock(); |
1937 | 1915 | ||
1938 | hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) { | 1916 | hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) { |
1939 | const char *tname; | 1917 | const char *tname; |
1940 | int tlen; | 1918 | int tlen; |
1941 | 1919 | ||
@@ -2086,13 +2064,13 @@ again: | |||
2086 | } | 2064 | } |
2087 | EXPORT_SYMBOL(d_delete); | 2065 | EXPORT_SYMBOL(d_delete); |
2088 | 2066 | ||
2089 | static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b) | 2067 | static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b) |
2090 | { | 2068 | { |
2091 | BUG_ON(!d_unhashed(entry)); | 2069 | BUG_ON(!d_unhashed(entry)); |
2092 | spin_lock_bucket(b); | 2070 | hlist_bl_lock(b); |
2093 | entry->d_flags &= ~DCACHE_UNHASHED; | 2071 | entry->d_flags |= DCACHE_RCUACCESS; |
2094 | hlist_bl_add_head_rcu(&entry->d_hash, &b->head); | 2072 | hlist_bl_add_head_rcu(&entry->d_hash, b); |
2095 | spin_unlock_bucket(b); | 2073 | hlist_bl_unlock(b); |
2096 | } | 2074 | } |
2097 | 2075 | ||
2098 | static void _d_rehash(struct dentry * entry) | 2076 | static void _d_rehash(struct dentry * entry) |
@@ -3025,7 +3003,7 @@ static void __init dcache_init_early(void) | |||
3025 | 3003 | ||
3026 | dentry_hashtable = | 3004 | dentry_hashtable = |
3027 | alloc_large_system_hash("Dentry cache", | 3005 | alloc_large_system_hash("Dentry cache", |
3028 | sizeof(struct dcache_hash_bucket), | 3006 | sizeof(struct hlist_bl_head), |
3029 | dhash_entries, | 3007 | dhash_entries, |
3030 | 13, | 3008 | 13, |
3031 | HASH_EARLY, | 3009 | HASH_EARLY, |
@@ -3034,7 +3012,7 @@ static void __init dcache_init_early(void) | |||
3034 | 0); | 3012 | 0); |
3035 | 3013 | ||
3036 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 3014 | for (loop = 0; loop < (1 << d_hash_shift); loop++) |
3037 | INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); | 3015 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
3038 | } | 3016 | } |
3039 | 3017 | ||
3040 | static void __init dcache_init(void) | 3018 | static void __init dcache_init(void) |
@@ -3057,7 +3035,7 @@ static void __init dcache_init(void) | |||
3057 | 3035 | ||
3058 | dentry_hashtable = | 3036 | dentry_hashtable = |
3059 | alloc_large_system_hash("Dentry cache", | 3037 | alloc_large_system_hash("Dentry cache", |
3060 | sizeof(struct dcache_hash_bucket), | 3038 | sizeof(struct hlist_bl_head), |
3061 | dhash_entries, | 3039 | dhash_entries, |
3062 | 13, | 3040 | 13, |
3063 | 0, | 3041 | 0, |
@@ -3066,7 +3044,7 @@ static void __init dcache_init(void) | |||
3066 | 0); | 3044 | 0); |
3067 | 3045 | ||
3068 | for (loop = 0; loop < (1 << d_hash_shift); loop++) | 3046 | for (loop = 0; loop < (1 << d_hash_shift); loop++) |
3069 | INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head); | 3047 | INIT_HLIST_BL_HEAD(dentry_hashtable + loop); |
3070 | } | 3048 | } |
3071 | 3049 | ||
3072 | /* SLAB cache for __getname() consumers */ | 3050 | /* SLAB cache for __getname() consumers */ |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 89d394d8fe24..90f76575c056 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -428,26 +428,17 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf, | |||
428 | size_t count, loff_t *ppos) | 428 | size_t count, loff_t *ppos) |
429 | { | 429 | { |
430 | char buf[32]; | 430 | char buf[32]; |
431 | int buf_size; | 431 | size_t buf_size; |
432 | bool bv; | ||
432 | u32 *val = file->private_data; | 433 | u32 *val = file->private_data; |
433 | 434 | ||
434 | buf_size = min(count, (sizeof(buf)-1)); | 435 | buf_size = min(count, (sizeof(buf)-1)); |
435 | if (copy_from_user(buf, user_buf, buf_size)) | 436 | if (copy_from_user(buf, user_buf, buf_size)) |
436 | return -EFAULT; | 437 | return -EFAULT; |
437 | 438 | ||
438 | switch (buf[0]) { | 439 | if (strtobool(buf, &bv) == 0) |
439 | case 'y': | 440 | *val = bv; |
440 | case 'Y': | 441 | |
441 | case '1': | ||
442 | *val = 1; | ||
443 | break; | ||
444 | case 'n': | ||
445 | case 'N': | ||
446 | case '0': | ||
447 | *val = 0; | ||
448 | break; | ||
449 | } | ||
450 | |||
451 | return count; | 442 | return count; |
452 | } | 443 | } |
453 | 444 | ||
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 | } |
@@ -1659,6 +1659,7 @@ static int zap_process(struct task_struct *start, int exit_code) | |||
1659 | 1659 | ||
1660 | t = start; | 1660 | t = start; |
1661 | do { | 1661 | do { |
1662 | task_clear_group_stop_pending(t); | ||
1662 | if (t != current && t->mm) { | 1663 | if (t != current && t->mm) { |
1663 | sigaddset(&t->pending.signal, SIGKILL); | 1664 | sigaddset(&t->pending.signal, SIGKILL); |
1664 | signal_wake_up(t, 1); | 1665 | signal_wake_up(t, 1); |
@@ -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/Makefile b/fs/gfs2/Makefile index f3d23ef4e876..86128202384f 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | ccflags-y := -I$(src) | 1 | ccflags-y := -I$(src) |
2 | obj-$(CONFIG_GFS2_FS) += gfs2.o | 2 | obj-$(CONFIG_GFS2_FS) += gfs2.o |
3 | gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \ | 3 | gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \ |
4 | glops.o inode.o log.o lops.o main.o meta_io.o \ | 4 | glops.o log.o lops.o main.o meta_io.o \ |
5 | aops.o dentry.o export.o file.o \ | 5 | aops.o dentry.o export.o file.o \ |
6 | ops_fstype.o ops_inode.o quota.o \ | 6 | ops_fstype.o inode.o quota.o \ |
7 | recovery.o rgrp.o super.o sys.o trans.o util.o | 7 | recovery.o rgrp.o super.o sys.o trans.o util.o |
8 | 8 | ||
9 | gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o | 9 | gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index c71995b111bf..802ac5eeba28 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); |
@@ -1076,8 +1076,8 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
1076 | bd = bh->b_private; | 1076 | bd = bh->b_private; |
1077 | if (bd && bd->bd_ail) | 1077 | if (bd && bd->bd_ail) |
1078 | goto cannot_release; | 1078 | goto cannot_release; |
1079 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); | 1079 | if (buffer_pinned(bh) || buffer_dirty(bh)) |
1080 | gfs2_assert_warn(sdp, !buffer_dirty(bh)); | 1080 | goto not_possible; |
1081 | bh = bh->b_this_page; | 1081 | bh = bh->b_this_page; |
1082 | } while(bh != head); | 1082 | } while(bh != head); |
1083 | gfs2_log_unlock(sdp); | 1083 | gfs2_log_unlock(sdp); |
@@ -1107,6 +1107,10 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
1107 | } while (bh != head); | 1107 | } while (bh != head); |
1108 | 1108 | ||
1109 | return try_to_free_buffers(page); | 1109 | return try_to_free_buffers(page); |
1110 | |||
1111 | not_possible: /* Should never happen */ | ||
1112 | WARN_ON(buffer_dirty(bh)); | ||
1113 | WARN_ON(buffer_pinned(bh)); | ||
1110 | cannot_release: | 1114 | cannot_release: |
1111 | gfs2_log_unlock(sdp); | 1115 | gfs2_log_unlock(sdp); |
1112 | return 0; | 1116 | return 0; |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 5c356d09c321..091ee4779538 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -82,12 +82,9 @@ | |||
82 | struct qstr gfs2_qdot __read_mostly; | 82 | struct qstr gfs2_qdot __read_mostly; |
83 | struct qstr gfs2_qdotdot __read_mostly; | 83 | struct qstr gfs2_qdotdot __read_mostly; |
84 | 84 | ||
85 | typedef int (*leaf_call_t) (struct gfs2_inode *dip, u32 index, u32 len, | ||
86 | u64 leaf_no, void *data); | ||
87 | typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, | 85 | typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, |
88 | const struct qstr *name, void *opaque); | 86 | const struct qstr *name, void *opaque); |
89 | 87 | ||
90 | |||
91 | int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, | 88 | int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, |
92 | struct buffer_head **bhp) | 89 | struct buffer_head **bhp) |
93 | { | 90 | { |
@@ -1506,7 +1503,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) | |||
1506 | inode = gfs2_inode_lookup(dir->i_sb, | 1503 | inode = gfs2_inode_lookup(dir->i_sb, |
1507 | be16_to_cpu(dent->de_type), | 1504 | be16_to_cpu(dent->de_type), |
1508 | be64_to_cpu(dent->de_inum.no_addr), | 1505 | be64_to_cpu(dent->de_inum.no_addr), |
1509 | be64_to_cpu(dent->de_inum.no_formal_ino)); | 1506 | be64_to_cpu(dent->de_inum.no_formal_ino), 0); |
1510 | brelse(bh); | 1507 | brelse(bh); |
1511 | return inode; | 1508 | return inode; |
1512 | } | 1509 | } |
@@ -1600,7 +1597,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) | |||
1600 | */ | 1597 | */ |
1601 | 1598 | ||
1602 | int gfs2_dir_add(struct inode *inode, const struct qstr *name, | 1599 | int gfs2_dir_add(struct inode *inode, const struct qstr *name, |
1603 | const struct gfs2_inode *nip, unsigned type) | 1600 | const struct gfs2_inode *nip) |
1604 | { | 1601 | { |
1605 | struct gfs2_inode *ip = GFS2_I(inode); | 1602 | struct gfs2_inode *ip = GFS2_I(inode); |
1606 | struct buffer_head *bh; | 1603 | struct buffer_head *bh; |
@@ -1616,7 +1613,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1616 | return PTR_ERR(dent); | 1613 | return PTR_ERR(dent); |
1617 | dent = gfs2_init_dirent(inode, dent, name, bh); | 1614 | dent = gfs2_init_dirent(inode, dent, name, bh); |
1618 | gfs2_inum_out(nip, dent); | 1615 | gfs2_inum_out(nip, dent); |
1619 | dent->de_type = cpu_to_be16(type); | 1616 | dent->de_type = cpu_to_be16(IF2DT(nip->i_inode.i_mode)); |
1620 | if (ip->i_diskflags & GFS2_DIF_EXHASH) { | 1617 | if (ip->i_diskflags & GFS2_DIF_EXHASH) { |
1621 | leaf = (struct gfs2_leaf *)bh->b_data; | 1618 | leaf = (struct gfs2_leaf *)bh->b_data; |
1622 | be16_add_cpu(&leaf->lf_entries, 1); | 1619 | be16_add_cpu(&leaf->lf_entries, 1); |
@@ -1628,6 +1625,8 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1628 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 1625 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
1629 | ip->i_entries++; | 1626 | ip->i_entries++; |
1630 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1627 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
1628 | if (S_ISDIR(nip->i_inode.i_mode)) | ||
1629 | inc_nlink(&ip->i_inode); | ||
1631 | gfs2_dinode_out(ip, bh->b_data); | 1630 | gfs2_dinode_out(ip, bh->b_data); |
1632 | brelse(bh); | 1631 | brelse(bh); |
1633 | error = 0; | 1632 | error = 0; |
@@ -1672,8 +1671,9 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name, | |||
1672 | * Returns: 0 on success, error code on failure | 1671 | * Returns: 0 on success, error code on failure |
1673 | */ | 1672 | */ |
1674 | 1673 | ||
1675 | int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) | 1674 | int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry) |
1676 | { | 1675 | { |
1676 | const struct qstr *name = &dentry->d_name; | ||
1677 | struct gfs2_dirent *dent, *prev = NULL; | 1677 | struct gfs2_dirent *dent, *prev = NULL; |
1678 | struct buffer_head *bh; | 1678 | struct buffer_head *bh; |
1679 | int error; | 1679 | int error; |
@@ -1714,6 +1714,8 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) | |||
1714 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | 1714 | gfs2_trans_add_bh(dip->i_gl, bh, 1); |
1715 | dip->i_entries--; | 1715 | dip->i_entries--; |
1716 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; | 1716 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; |
1717 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
1718 | drop_nlink(&dip->i_inode); | ||
1717 | gfs2_dinode_out(dip, bh->b_data); | 1719 | gfs2_dinode_out(dip, bh->b_data); |
1718 | brelse(bh); | 1720 | brelse(bh); |
1719 | mark_inode_dirty(&dip->i_inode); | 1721 | mark_inode_dirty(&dip->i_inode); |
@@ -1768,94 +1770,20 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | |||
1768 | } | 1770 | } |
1769 | 1771 | ||
1770 | /** | 1772 | /** |
1771 | * foreach_leaf - call a function for each leaf in a directory | ||
1772 | * @dip: the directory | ||
1773 | * @lc: the function to call for each each | ||
1774 | * @data: private data to pass to it | ||
1775 | * | ||
1776 | * Returns: errno | ||
1777 | */ | ||
1778 | |||
1779 | static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data) | ||
1780 | { | ||
1781 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | ||
1782 | struct buffer_head *bh; | ||
1783 | struct gfs2_leaf *leaf; | ||
1784 | u32 hsize, len; | ||
1785 | u32 ht_offset, lp_offset, ht_offset_cur = -1; | ||
1786 | u32 index = 0; | ||
1787 | __be64 *lp; | ||
1788 | u64 leaf_no; | ||
1789 | int error = 0; | ||
1790 | |||
1791 | hsize = 1 << dip->i_depth; | ||
1792 | if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) { | ||
1793 | gfs2_consist_inode(dip); | ||
1794 | return -EIO; | ||
1795 | } | ||
1796 | |||
1797 | lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS); | ||
1798 | if (!lp) | ||
1799 | return -ENOMEM; | ||
1800 | |||
1801 | while (index < hsize) { | ||
1802 | lp_offset = index & (sdp->sd_hash_ptrs - 1); | ||
1803 | ht_offset = index - lp_offset; | ||
1804 | |||
1805 | if (ht_offset_cur != ht_offset) { | ||
1806 | error = gfs2_dir_read_data(dip, (char *)lp, | ||
1807 | ht_offset * sizeof(__be64), | ||
1808 | sdp->sd_hash_bsize, 1); | ||
1809 | if (error != sdp->sd_hash_bsize) { | ||
1810 | if (error >= 0) | ||
1811 | error = -EIO; | ||
1812 | goto out; | ||
1813 | } | ||
1814 | ht_offset_cur = ht_offset; | ||
1815 | } | ||
1816 | |||
1817 | leaf_no = be64_to_cpu(lp[lp_offset]); | ||
1818 | if (leaf_no) { | ||
1819 | error = get_leaf(dip, leaf_no, &bh); | ||
1820 | if (error) | ||
1821 | goto out; | ||
1822 | leaf = (struct gfs2_leaf *)bh->b_data; | ||
1823 | len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth)); | ||
1824 | brelse(bh); | ||
1825 | |||
1826 | error = lc(dip, index, len, leaf_no, data); | ||
1827 | if (error) | ||
1828 | goto out; | ||
1829 | |||
1830 | index = (index & ~(len - 1)) + len; | ||
1831 | } else | ||
1832 | index++; | ||
1833 | } | ||
1834 | |||
1835 | if (index != hsize) { | ||
1836 | gfs2_consist_inode(dip); | ||
1837 | error = -EIO; | ||
1838 | } | ||
1839 | |||
1840 | out: | ||
1841 | kfree(lp); | ||
1842 | |||
1843 | return error; | ||
1844 | } | ||
1845 | |||
1846 | /** | ||
1847 | * leaf_dealloc - Deallocate a directory leaf | 1773 | * leaf_dealloc - Deallocate a directory leaf |
1848 | * @dip: the directory | 1774 | * @dip: the directory |
1849 | * @index: the hash table offset in the directory | 1775 | * @index: the hash table offset in the directory |
1850 | * @len: the number of pointers to this leaf | 1776 | * @len: the number of pointers to this leaf |
1851 | * @leaf_no: the leaf number | 1777 | * @leaf_no: the leaf number |
1852 | * @data: not used | 1778 | * @leaf_bh: buffer_head for the starting leaf |
1779 | * last_dealloc: 1 if this is the final dealloc for the leaf, else 0 | ||
1853 | * | 1780 | * |
1854 | * Returns: errno | 1781 | * Returns: errno |
1855 | */ | 1782 | */ |
1856 | 1783 | ||
1857 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | 1784 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, |
1858 | u64 leaf_no, void *data) | 1785 | u64 leaf_no, struct buffer_head *leaf_bh, |
1786 | int last_dealloc) | ||
1859 | { | 1787 | { |
1860 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 1788 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
1861 | struct gfs2_leaf *tmp_leaf; | 1789 | struct gfs2_leaf *tmp_leaf; |
@@ -1887,14 +1815,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1887 | goto out_qs; | 1815 | goto out_qs; |
1888 | 1816 | ||
1889 | /* Count the number of leaves */ | 1817 | /* Count the number of leaves */ |
1818 | bh = leaf_bh; | ||
1890 | 1819 | ||
1891 | for (blk = leaf_no; blk; blk = nblk) { | 1820 | for (blk = leaf_no; blk; blk = nblk) { |
1892 | error = get_leaf(dip, blk, &bh); | 1821 | if (blk != leaf_no) { |
1893 | if (error) | 1822 | error = get_leaf(dip, blk, &bh); |
1894 | goto out_rlist; | 1823 | if (error) |
1824 | goto out_rlist; | ||
1825 | } | ||
1895 | tmp_leaf = (struct gfs2_leaf *)bh->b_data; | 1826 | tmp_leaf = (struct gfs2_leaf *)bh->b_data; |
1896 | nblk = be64_to_cpu(tmp_leaf->lf_next); | 1827 | nblk = be64_to_cpu(tmp_leaf->lf_next); |
1897 | brelse(bh); | 1828 | if (blk != leaf_no) |
1829 | brelse(bh); | ||
1898 | 1830 | ||
1899 | gfs2_rlist_add(sdp, &rlist, blk); | 1831 | gfs2_rlist_add(sdp, &rlist, blk); |
1900 | l_blocks++; | 1832 | l_blocks++; |
@@ -1918,13 +1850,18 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1918 | if (error) | 1850 | if (error) |
1919 | goto out_rg_gunlock; | 1851 | goto out_rg_gunlock; |
1920 | 1852 | ||
1853 | bh = leaf_bh; | ||
1854 | |||
1921 | for (blk = leaf_no; blk; blk = nblk) { | 1855 | for (blk = leaf_no; blk; blk = nblk) { |
1922 | error = get_leaf(dip, blk, &bh); | 1856 | if (blk != leaf_no) { |
1923 | if (error) | 1857 | error = get_leaf(dip, blk, &bh); |
1924 | goto out_end_trans; | 1858 | if (error) |
1859 | goto out_end_trans; | ||
1860 | } | ||
1925 | tmp_leaf = (struct gfs2_leaf *)bh->b_data; | 1861 | tmp_leaf = (struct gfs2_leaf *)bh->b_data; |
1926 | nblk = be64_to_cpu(tmp_leaf->lf_next); | 1862 | nblk = be64_to_cpu(tmp_leaf->lf_next); |
1927 | brelse(bh); | 1863 | if (blk != leaf_no) |
1864 | brelse(bh); | ||
1928 | 1865 | ||
1929 | gfs2_free_meta(dip, blk, 1); | 1866 | gfs2_free_meta(dip, blk, 1); |
1930 | gfs2_add_inode_blocks(&dip->i_inode, -1); | 1867 | gfs2_add_inode_blocks(&dip->i_inode, -1); |
@@ -1942,6 +1879,10 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1942 | goto out_end_trans; | 1879 | goto out_end_trans; |
1943 | 1880 | ||
1944 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); | 1881 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); |
1882 | /* On the last dealloc, make this a regular file in case we crash. | ||
1883 | (We don't want to free these blocks a second time.) */ | ||
1884 | if (last_dealloc) | ||
1885 | dip->i_inode.i_mode = S_IFREG; | ||
1945 | gfs2_dinode_out(dip, dibh->b_data); | 1886 | gfs2_dinode_out(dip, dibh->b_data); |
1946 | brelse(dibh); | 1887 | brelse(dibh); |
1947 | 1888 | ||
@@ -1975,29 +1916,67 @@ int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) | |||
1975 | { | 1916 | { |
1976 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 1917 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
1977 | struct buffer_head *bh; | 1918 | struct buffer_head *bh; |
1978 | int error; | 1919 | struct gfs2_leaf *leaf; |
1920 | u32 hsize, len; | ||
1921 | u32 ht_offset, lp_offset, ht_offset_cur = -1; | ||
1922 | u32 index = 0, next_index; | ||
1923 | __be64 *lp; | ||
1924 | u64 leaf_no; | ||
1925 | int error = 0, last; | ||
1979 | 1926 | ||
1980 | /* Dealloc on-disk leaves to FREEMETA state */ | 1927 | hsize = 1 << dip->i_depth; |
1981 | error = foreach_leaf(dip, leaf_dealloc, NULL); | 1928 | if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) { |
1982 | if (error) | 1929 | gfs2_consist_inode(dip); |
1983 | return error; | 1930 | return -EIO; |
1931 | } | ||
1984 | 1932 | ||
1985 | /* Make this a regular file in case we crash. | 1933 | lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS); |
1986 | (We don't want to free these blocks a second time.) */ | 1934 | if (!lp) |
1935 | return -ENOMEM; | ||
1987 | 1936 | ||
1988 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | 1937 | while (index < hsize) { |
1989 | if (error) | 1938 | lp_offset = index & (sdp->sd_hash_ptrs - 1); |
1990 | return error; | 1939 | ht_offset = index - lp_offset; |
1991 | 1940 | ||
1992 | error = gfs2_meta_inode_buffer(dip, &bh); | 1941 | if (ht_offset_cur != ht_offset) { |
1993 | if (!error) { | 1942 | error = gfs2_dir_read_data(dip, (char *)lp, |
1994 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | 1943 | ht_offset * sizeof(__be64), |
1995 | ((struct gfs2_dinode *)bh->b_data)->di_mode = | 1944 | sdp->sd_hash_bsize, 1); |
1996 | cpu_to_be32(S_IFREG); | 1945 | if (error != sdp->sd_hash_bsize) { |
1997 | brelse(bh); | 1946 | if (error >= 0) |
1947 | error = -EIO; | ||
1948 | goto out; | ||
1949 | } | ||
1950 | ht_offset_cur = ht_offset; | ||
1951 | } | ||
1952 | |||
1953 | leaf_no = be64_to_cpu(lp[lp_offset]); | ||
1954 | if (leaf_no) { | ||
1955 | error = get_leaf(dip, leaf_no, &bh); | ||
1956 | if (error) | ||
1957 | goto out; | ||
1958 | leaf = (struct gfs2_leaf *)bh->b_data; | ||
1959 | len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth)); | ||
1960 | |||
1961 | next_index = (index & ~(len - 1)) + len; | ||
1962 | last = ((next_index >= hsize) ? 1 : 0); | ||
1963 | error = leaf_dealloc(dip, index, len, leaf_no, bh, | ||
1964 | last); | ||
1965 | brelse(bh); | ||
1966 | if (error) | ||
1967 | goto out; | ||
1968 | index = next_index; | ||
1969 | } else | ||
1970 | index++; | ||
1998 | } | 1971 | } |
1999 | 1972 | ||
2000 | gfs2_trans_end(sdp); | 1973 | if (index != hsize) { |
1974 | gfs2_consist_inode(dip); | ||
1975 | error = -EIO; | ||
1976 | } | ||
1977 | |||
1978 | out: | ||
1979 | kfree(lp); | ||
2001 | 1980 | ||
2002 | return error; | 1981 | return error; |
2003 | } | 1982 | } |
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h index a98f644bd3df..e686af11becd 100644 --- a/fs/gfs2/dir.h +++ b/fs/gfs2/dir.h | |||
@@ -22,8 +22,8 @@ extern struct inode *gfs2_dir_search(struct inode *dir, | |||
22 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, | 22 | extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, |
23 | const struct gfs2_inode *ip); | 23 | const struct gfs2_inode *ip); |
24 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, | 24 | extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, |
25 | const struct gfs2_inode *ip, unsigned int type); | 25 | const struct gfs2_inode *ip); |
26 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); | 26 | extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); |
27 | extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | 27 | extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, |
28 | filldir_t filldir); | 28 | filldir_t filldir); |
29 | extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, | 29 | extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, |
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index b5a5e60df0d5..fe9945f2ff72 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
@@ -139,7 +139,7 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, | |||
139 | struct gfs2_sbd *sdp = sb->s_fs_info; | 139 | struct gfs2_sbd *sdp = sb->s_fs_info; |
140 | struct inode *inode; | 140 | struct inode *inode; |
141 | 141 | ||
142 | inode = gfs2_ilookup(sb, inum->no_addr); | 142 | inode = gfs2_ilookup(sb, inum->no_addr, 0); |
143 | if (inode) { | 143 | if (inode) { |
144 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { | 144 | if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { |
145 | iput(inode); | 145 | iput(inode); |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b2682e073eee..a9f5cbe45cd9 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -545,18 +545,10 @@ static int gfs2_close(struct inode *inode, struct file *file) | |||
545 | /** | 545 | /** |
546 | * gfs2_fsync - sync the dirty data for a file (across the cluster) | 546 | * gfs2_fsync - sync the dirty data for a file (across the cluster) |
547 | * @file: the file that points to the dentry (we ignore this) | 547 | * @file: the file that points to the dentry (we ignore this) |
548 | * @dentry: the dentry that points to the inode to sync | 548 | * @datasync: set if we can ignore timestamp changes |
549 | * | 549 | * |
550 | * The VFS will flush "normal" data for us. We only need to worry | 550 | * The VFS will flush data for us. We only need to worry |
551 | * about metadata here. For journaled data, we just do a log flush | 551 | * about metadata here. |
552 | * as we can't avoid it. Otherwise we can just bale out if datasync | ||
553 | * is set. For stuffed inodes we must flush the log in order to | ||
554 | * ensure that all data is on disk. | ||
555 | * | ||
556 | * The call to write_inode_now() is there to write back metadata and | ||
557 | * the inode itself. It does also try and write the data, but thats | ||
558 | * (hopefully) a no-op due to the VFS having already called filemap_fdatawrite() | ||
559 | * for us. | ||
560 | * | 552 | * |
561 | * Returns: errno | 553 | * Returns: errno |
562 | */ | 554 | */ |
@@ -565,22 +557,20 @@ static int gfs2_fsync(struct file *file, int datasync) | |||
565 | { | 557 | { |
566 | struct inode *inode = file->f_mapping->host; | 558 | struct inode *inode = file->f_mapping->host; |
567 | int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); | 559 | int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); |
568 | int ret = 0; | 560 | struct gfs2_inode *ip = GFS2_I(inode); |
569 | 561 | int ret; | |
570 | if (gfs2_is_jdata(GFS2_I(inode))) { | ||
571 | gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); | ||
572 | return 0; | ||
573 | } | ||
574 | 562 | ||
575 | if (sync_state != 0) { | 563 | if (datasync) |
576 | if (!datasync) | 564 | sync_state &= ~I_DIRTY_SYNC; |
577 | ret = write_inode_now(inode, 0); | ||
578 | 565 | ||
579 | if (gfs2_is_stuffed(GFS2_I(inode))) | 566 | if (sync_state) { |
580 | gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); | 567 | ret = sync_inode_metadata(inode, 1); |
568 | if (ret) | ||
569 | return ret; | ||
570 | gfs2_ail_flush(ip->i_gl); | ||
581 | } | 571 | } |
582 | 572 | ||
583 | return ret; | 573 | return 0; |
584 | } | 574 | } |
585 | 575 | ||
586 | /** | 576 | /** |
@@ -617,18 +607,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); | 607 | return generic_file_aio_write(iocb, iov, nr_segs, pos); |
618 | } | 608 | } |
619 | 609 | ||
620 | static void empty_write_end(struct page *page, unsigned from, | 610 | static int empty_write_end(struct page *page, unsigned from, |
621 | unsigned to) | 611 | unsigned to, int mode) |
622 | { | 612 | { |
623 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 613 | struct inode *inode = page->mapping->host; |
614 | struct gfs2_inode *ip = GFS2_I(inode); | ||
615 | struct buffer_head *bh; | ||
616 | unsigned offset, blksize = 1 << inode->i_blkbits; | ||
617 | pgoff_t end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; | ||
624 | 618 | ||
625 | zero_user(page, from, to-from); | 619 | zero_user(page, from, to-from); |
626 | mark_page_accessed(page); | 620 | mark_page_accessed(page); |
627 | 621 | ||
628 | if (!gfs2_is_writeback(ip)) | 622 | if (page->index < end_index || !(mode & FALLOC_FL_KEEP_SIZE)) { |
629 | gfs2_page_add_databufs(ip, page, from, to); | 623 | if (!gfs2_is_writeback(ip)) |
624 | gfs2_page_add_databufs(ip, page, from, to); | ||
630 | 625 | ||
631 | block_commit_write(page, from, to); | 626 | block_commit_write(page, from, to); |
627 | return 0; | ||
628 | } | ||
629 | |||
630 | offset = 0; | ||
631 | bh = page_buffers(page); | ||
632 | while (offset < to) { | ||
633 | if (offset >= from) { | ||
634 | set_buffer_uptodate(bh); | ||
635 | mark_buffer_dirty(bh); | ||
636 | clear_buffer_new(bh); | ||
637 | write_dirty_buffer(bh, WRITE); | ||
638 | } | ||
639 | offset += blksize; | ||
640 | bh = bh->b_this_page; | ||
641 | } | ||
642 | |||
643 | offset = 0; | ||
644 | bh = page_buffers(page); | ||
645 | while (offset < to) { | ||
646 | if (offset >= from) { | ||
647 | wait_on_buffer(bh); | ||
648 | if (!buffer_uptodate(bh)) | ||
649 | return -EIO; | ||
650 | } | ||
651 | offset += blksize; | ||
652 | bh = bh->b_this_page; | ||
653 | } | ||
654 | return 0; | ||
632 | } | 655 | } |
633 | 656 | ||
634 | static int needs_empty_write(sector_t block, struct inode *inode) | 657 | static int needs_empty_write(sector_t block, struct inode *inode) |
@@ -643,7 +666,8 @@ static int needs_empty_write(sector_t block, struct inode *inode) | |||
643 | return !buffer_mapped(&bh_map); | 666 | return !buffer_mapped(&bh_map); |
644 | } | 667 | } |
645 | 668 | ||
646 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | 669 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to, |
670 | int mode) | ||
647 | { | 671 | { |
648 | struct inode *inode = page->mapping->host; | 672 | struct inode *inode = page->mapping->host; |
649 | unsigned start, end, next, blksize; | 673 | unsigned start, end, next, blksize; |
@@ -668,7 +692,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
668 | gfs2_block_map); | 692 | gfs2_block_map); |
669 | if (unlikely(ret)) | 693 | if (unlikely(ret)) |
670 | return ret; | 694 | return ret; |
671 | empty_write_end(page, start, end); | 695 | ret = empty_write_end(page, start, end, mode); |
696 | if (unlikely(ret)) | ||
697 | return ret; | ||
672 | end = 0; | 698 | end = 0; |
673 | } | 699 | } |
674 | start = next; | 700 | start = next; |
@@ -682,7 +708,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); | 708 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); |
683 | if (unlikely(ret)) | 709 | if (unlikely(ret)) |
684 | return ret; | 710 | return ret; |
685 | empty_write_end(page, start, end); | 711 | ret = empty_write_end(page, start, end, mode); |
712 | if (unlikely(ret)) | ||
713 | return ret; | ||
686 | } | 714 | } |
687 | 715 | ||
688 | return 0; | 716 | return 0; |
@@ -731,7 +759,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, | |||
731 | 759 | ||
732 | if (curr == end) | 760 | if (curr == end) |
733 | to = end_offset; | 761 | to = end_offset; |
734 | error = write_empty_blocks(page, from, to); | 762 | error = write_empty_blocks(page, from, to, mode); |
735 | if (!error && offset + to > inode->i_size && | 763 | if (!error && offset + to > inode->i_size && |
736 | !(mode & FALLOC_FL_KEEP_SIZE)) { | 764 | !(mode & FALLOC_FL_KEEP_SIZE)) { |
737 | i_size_write(inode, offset + to); | 765 | i_size_write(inode, offset + to); |
@@ -788,6 +816,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
788 | loff_t bytes, max_bytes; | 816 | loff_t bytes, max_bytes; |
789 | struct gfs2_alloc *al; | 817 | struct gfs2_alloc *al; |
790 | int error; | 818 | int error; |
819 | loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1); | ||
791 | loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; | 820 | loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; |
792 | next = (next + 1) << sdp->sd_sb.sb_bsize_shift; | 821 | next = (next + 1) << sdp->sd_sb.sb_bsize_shift; |
793 | 822 | ||
@@ -795,13 +824,15 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, | |||
795 | if (mode & ~FALLOC_FL_KEEP_SIZE) | 824 | if (mode & ~FALLOC_FL_KEEP_SIZE) |
796 | return -EOPNOTSUPP; | 825 | return -EOPNOTSUPP; |
797 | 826 | ||
798 | offset = (offset >> sdp->sd_sb.sb_bsize_shift) << | 827 | offset &= bsize_mask; |
799 | sdp->sd_sb.sb_bsize_shift; | ||
800 | 828 | ||
801 | len = next - offset; | 829 | len = next - offset; |
802 | bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2; | 830 | bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2; |
803 | if (!bytes) | 831 | if (!bytes) |
804 | bytes = UINT_MAX; | 832 | bytes = UINT_MAX; |
833 | bytes &= bsize_mask; | ||
834 | if (bytes == 0) | ||
835 | bytes = sdp->sd_sb.sb_bsize; | ||
805 | 836 | ||
806 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); | 837 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); |
807 | error = gfs2_glock_nq(&ip->i_gh); | 838 | error = gfs2_glock_nq(&ip->i_gh); |
@@ -832,6 +863,9 @@ retry: | |||
832 | if (error) { | 863 | if (error) { |
833 | if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) { | 864 | if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) { |
834 | bytes >>= 1; | 865 | bytes >>= 1; |
866 | bytes &= bsize_mask; | ||
867 | if (bytes == 0) | ||
868 | bytes = sdp->sd_sb.sb_bsize; | ||
835 | goto retry; | 869 | goto retry; |
836 | } | 870 | } |
837 | goto out_qunlock; | 871 | goto out_qunlock; |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f07643e21bfa..a2a6abbccc07 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) |
@@ -145,14 +143,9 @@ static int demote_ok(const struct gfs2_glock *gl) | |||
145 | { | 143 | { |
146 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 144 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
147 | 145 | ||
148 | /* assert_spin_locked(&gl->gl_spin); */ | ||
149 | |||
150 | if (gl->gl_state == LM_ST_UNLOCKED) | 146 | if (gl->gl_state == LM_ST_UNLOCKED) |
151 | return 0; | 147 | return 0; |
152 | if (test_bit(GLF_LFLUSH, &gl->gl_flags)) | 148 | if (!list_empty(&gl->gl_holders)) |
153 | return 0; | ||
154 | if ((gl->gl_name.ln_type != LM_TYPE_INODE) && | ||
155 | !list_empty(&gl->gl_holders)) | ||
156 | return 0; | 149 | return 0; |
157 | if (glops->go_demote_ok) | 150 | if (glops->go_demote_ok) |
158 | return glops->go_demote_ok(gl); | 151 | return glops->go_demote_ok(gl); |
@@ -160,6 +153,31 @@ static int demote_ok(const struct gfs2_glock *gl) | |||
160 | } | 153 | } |
161 | 154 | ||
162 | 155 | ||
156 | void gfs2_glock_add_to_lru(struct gfs2_glock *gl) | ||
157 | { | ||
158 | spin_lock(&lru_lock); | ||
159 | |||
160 | if (!list_empty(&gl->gl_lru)) | ||
161 | list_del_init(&gl->gl_lru); | ||
162 | else | ||
163 | atomic_inc(&lru_count); | ||
164 | |||
165 | list_add_tail(&gl->gl_lru, &lru_list); | ||
166 | set_bit(GLF_LRU, &gl->gl_flags); | ||
167 | spin_unlock(&lru_lock); | ||
168 | } | ||
169 | |||
170 | static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl) | ||
171 | { | ||
172 | spin_lock(&lru_lock); | ||
173 | if (!list_empty(&gl->gl_lru)) { | ||
174 | list_del_init(&gl->gl_lru); | ||
175 | atomic_dec(&lru_count); | ||
176 | clear_bit(GLF_LRU, &gl->gl_flags); | ||
177 | } | ||
178 | spin_unlock(&lru_lock); | ||
179 | } | ||
180 | |||
163 | /** | 181 | /** |
164 | * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list | 182 | * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list |
165 | * @gl: the glock | 183 | * @gl: the glock |
@@ -170,24 +188,8 @@ static int demote_ok(const struct gfs2_glock *gl) | |||
170 | 188 | ||
171 | static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | 189 | static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) |
172 | { | 190 | { |
173 | if (demote_ok(gl)) { | 191 | if (demote_ok(gl)) |
174 | spin_lock(&lru_lock); | 192 | gfs2_glock_add_to_lru(gl); |
175 | |||
176 | if (!list_empty(&gl->gl_lru)) | ||
177 | list_del_init(&gl->gl_lru); | ||
178 | else | ||
179 | atomic_inc(&lru_count); | ||
180 | |||
181 | list_add_tail(&gl->gl_lru, &lru_list); | ||
182 | spin_unlock(&lru_lock); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl) | ||
187 | { | ||
188 | spin_lock(&gl->gl_spin); | ||
189 | __gfs2_glock_schedule_for_reclaim(gl); | ||
190 | spin_unlock(&gl->gl_spin); | ||
191 | } | 193 | } |
192 | 194 | ||
193 | /** | 195 | /** |
@@ -219,12 +221,7 @@ void gfs2_glock_put(struct gfs2_glock *gl) | |||
219 | spin_lock_bucket(gl->gl_hash); | 221 | spin_lock_bucket(gl->gl_hash); |
220 | hlist_bl_del_rcu(&gl->gl_list); | 222 | hlist_bl_del_rcu(&gl->gl_list); |
221 | spin_unlock_bucket(gl->gl_hash); | 223 | spin_unlock_bucket(gl->gl_hash); |
222 | spin_lock(&lru_lock); | 224 | gfs2_glock_remove_from_lru(gl); |
223 | if (!list_empty(&gl->gl_lru)) { | ||
224 | list_del_init(&gl->gl_lru); | ||
225 | atomic_dec(&lru_count); | ||
226 | } | ||
227 | spin_unlock(&lru_lock); | ||
228 | GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); | 225 | GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); |
229 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); | 226 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); |
230 | trace_gfs2_glock_put(gl); | 227 | trace_gfs2_glock_put(gl); |
@@ -544,11 +541,6 @@ __acquires(&gl->gl_spin) | |||
544 | clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); | 541 | clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); |
545 | 542 | ||
546 | gfs2_glock_hold(gl); | 543 | gfs2_glock_hold(gl); |
547 | if (target != LM_ST_UNLOCKED && (gl->gl_state == LM_ST_SHARED || | ||
548 | gl->gl_state == LM_ST_DEFERRED) && | ||
549 | !(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) | ||
550 | lck_flags |= LM_FLAG_TRY_1CB; | ||
551 | |||
552 | if (sdp->sd_lockstruct.ls_ops->lm_lock) { | 544 | if (sdp->sd_lockstruct.ls_ops->lm_lock) { |
553 | /* lock_dlm */ | 545 | /* lock_dlm */ |
554 | ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); | 546 | ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags); |
@@ -650,7 +642,7 @@ static void delete_work_func(struct work_struct *work) | |||
650 | /* Note: Unsafe to dereference ip as we don't hold right refs/locks */ | 642 | /* Note: Unsafe to dereference ip as we don't hold right refs/locks */ |
651 | 643 | ||
652 | if (ip) | 644 | if (ip) |
653 | inode = gfs2_ilookup(sdp->sd_vfs, no_addr); | 645 | inode = gfs2_ilookup(sdp->sd_vfs, no_addr, 1); |
654 | else | 646 | else |
655 | inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED); | 647 | inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED); |
656 | if (inode && !IS_ERR(inode)) { | 648 | if (inode && !IS_ERR(inode)) { |
@@ -1027,6 +1019,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh) | |||
1027 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | 1019 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
1028 | return -EIO; | 1020 | return -EIO; |
1029 | 1021 | ||
1022 | if (test_bit(GLF_LRU, &gl->gl_flags)) | ||
1023 | gfs2_glock_remove_from_lru(gl); | ||
1024 | |||
1030 | spin_lock(&gl->gl_spin); | 1025 | spin_lock(&gl->gl_spin); |
1031 | add_to_queue(gh); | 1026 | add_to_queue(gh); |
1032 | if ((LM_FLAG_NOEXP & gh->gh_flags) && | 1027 | if ((LM_FLAG_NOEXP & gh->gh_flags) && |
@@ -1084,7 +1079,8 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1084 | !test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1079 | !test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1085 | fast_path = 1; | 1080 | fast_path = 1; |
1086 | } | 1081 | } |
1087 | __gfs2_glock_schedule_for_reclaim(gl); | 1082 | if (!test_bit(GLF_LFLUSH, &gl->gl_flags)) |
1083 | __gfs2_glock_schedule_for_reclaim(gl); | ||
1088 | trace_gfs2_glock_queue(gh, 0); | 1084 | trace_gfs2_glock_queue(gh, 0); |
1089 | spin_unlock(&gl->gl_spin); | 1085 | spin_unlock(&gl->gl_spin); |
1090 | if (likely(fast_path)) | 1086 | if (likely(fast_path)) |
@@ -1367,6 +1363,7 @@ static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_m | |||
1367 | while(nr && !list_empty(&lru_list)) { | 1363 | while(nr && !list_empty(&lru_list)) { |
1368 | gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru); | 1364 | gl = list_entry(lru_list.next, struct gfs2_glock, gl_lru); |
1369 | list_del_init(&gl->gl_lru); | 1365 | list_del_init(&gl->gl_lru); |
1366 | clear_bit(GLF_LRU, &gl->gl_flags); | ||
1370 | atomic_dec(&lru_count); | 1367 | atomic_dec(&lru_count); |
1371 | 1368 | ||
1372 | /* Test for being demotable */ | 1369 | /* Test for being demotable */ |
@@ -1389,6 +1386,7 @@ static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_m | |||
1389 | } | 1386 | } |
1390 | nr_skipped++; | 1387 | nr_skipped++; |
1391 | list_add(&gl->gl_lru, &skipped); | 1388 | list_add(&gl->gl_lru, &skipped); |
1389 | set_bit(GLF_LRU, &gl->gl_flags); | ||
1392 | } | 1390 | } |
1393 | list_splice(&skipped, &lru_list); | 1391 | list_splice(&skipped, &lru_list); |
1394 | atomic_add(nr_skipped, &lru_count); | 1392 | atomic_add(nr_skipped, &lru_count); |
@@ -1461,12 +1459,7 @@ static void thaw_glock(struct gfs2_glock *gl) | |||
1461 | 1459 | ||
1462 | static void clear_glock(struct gfs2_glock *gl) | 1460 | static void clear_glock(struct gfs2_glock *gl) |
1463 | { | 1461 | { |
1464 | spin_lock(&lru_lock); | 1462 | gfs2_glock_remove_from_lru(gl); |
1465 | if (!list_empty(&gl->gl_lru)) { | ||
1466 | list_del_init(&gl->gl_lru); | ||
1467 | atomic_dec(&lru_count); | ||
1468 | } | ||
1469 | spin_unlock(&lru_lock); | ||
1470 | 1463 | ||
1471 | spin_lock(&gl->gl_spin); | 1464 | spin_lock(&gl->gl_spin); |
1472 | if (gl->gl_state != LM_ST_UNLOCKED) | 1465 | if (gl->gl_state != LM_ST_UNLOCKED) |
@@ -1601,9 +1594,11 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) | |||
1601 | return 0; | 1594 | return 0; |
1602 | } | 1595 | } |
1603 | 1596 | ||
1604 | static const char *gflags2str(char *buf, const unsigned long *gflags) | 1597 | static const char *gflags2str(char *buf, const struct gfs2_glock *gl) |
1605 | { | 1598 | { |
1599 | const unsigned long *gflags = &gl->gl_flags; | ||
1606 | char *p = buf; | 1600 | char *p = buf; |
1601 | |||
1607 | if (test_bit(GLF_LOCK, gflags)) | 1602 | if (test_bit(GLF_LOCK, gflags)) |
1608 | *p++ = 'l'; | 1603 | *p++ = 'l'; |
1609 | if (test_bit(GLF_DEMOTE, gflags)) | 1604 | if (test_bit(GLF_DEMOTE, gflags)) |
@@ -1626,6 +1621,10 @@ static const char *gflags2str(char *buf, const unsigned long *gflags) | |||
1626 | *p++ = 'F'; | 1621 | *p++ = 'F'; |
1627 | if (test_bit(GLF_QUEUED, gflags)) | 1622 | if (test_bit(GLF_QUEUED, gflags)) |
1628 | *p++ = 'q'; | 1623 | *p++ = 'q'; |
1624 | if (test_bit(GLF_LRU, gflags)) | ||
1625 | *p++ = 'L'; | ||
1626 | if (gl->gl_object) | ||
1627 | *p++ = 'o'; | ||
1629 | *p = 0; | 1628 | *p = 0; |
1630 | return buf; | 1629 | return buf; |
1631 | } | 1630 | } |
@@ -1660,14 +1659,15 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) | |||
1660 | dtime *= 1000000/HZ; /* demote time in uSec */ | 1659 | dtime *= 1000000/HZ; /* demote time in uSec */ |
1661 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1660 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1662 | dtime = 0; | 1661 | dtime = 0; |
1663 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d r:%d\n", | 1662 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d v:%d r:%d\n", |
1664 | state2str(gl->gl_state), | 1663 | state2str(gl->gl_state), |
1665 | gl->gl_name.ln_type, | 1664 | gl->gl_name.ln_type, |
1666 | (unsigned long long)gl->gl_name.ln_number, | 1665 | (unsigned long long)gl->gl_name.ln_number, |
1667 | gflags2str(gflags_buf, &gl->gl_flags), | 1666 | gflags2str(gflags_buf, gl), |
1668 | state2str(gl->gl_target), | 1667 | state2str(gl->gl_target), |
1669 | state2str(gl->gl_demote_state), dtime, | 1668 | state2str(gl->gl_demote_state), dtime, |
1670 | atomic_read(&gl->gl_ail_count), | 1669 | atomic_read(&gl->gl_ail_count), |
1670 | atomic_read(&gl->gl_revokes), | ||
1671 | atomic_read(&gl->gl_ref)); | 1671 | atomic_read(&gl->gl_ref)); |
1672 | 1672 | ||
1673 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | 1673 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index aea160690e94..6b2f757b9281 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -225,11 +225,10 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl, | |||
225 | 225 | ||
226 | extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state); | 226 | extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state); |
227 | extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret); | 227 | extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret); |
228 | extern void gfs2_reclaim_glock(struct gfs2_sbd *sdp); | ||
229 | extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); | 228 | extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp); |
230 | extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip); | 229 | extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip); |
231 | extern void gfs2_glock_thaw(struct gfs2_sbd *sdp); | 230 | extern void gfs2_glock_thaw(struct gfs2_sbd *sdp); |
232 | extern void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl); | 231 | extern void gfs2_glock_add_to_lru(struct gfs2_glock *gl); |
233 | extern void gfs2_glock_free(struct gfs2_glock *gl); | 232 | extern void gfs2_glock_free(struct gfs2_glock *gl); |
234 | 233 | ||
235 | extern int __init gfs2_glock_init(void); | 234 | extern int __init gfs2_glock_init(void); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 3754e3cbf02b..8ef70f464731 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -28,33 +28,18 @@ | |||
28 | #include "trans.h" | 28 | #include "trans.h" |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * ail_empty_gl - remove all buffers for a given lock from the AIL | 31 | * __gfs2_ail_flush - remove all buffers for a given lock from the AIL |
32 | * @gl: the glock | 32 | * @gl: the glock |
33 | * | 33 | * |
34 | * None of the buffers should be dirty, locked, or pinned. | 34 | * None of the buffers should be dirty, locked, or pinned. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | 37 | static void __gfs2_ail_flush(struct gfs2_glock *gl) |
38 | { | 38 | { |
39 | struct gfs2_sbd *sdp = gl->gl_sbd; | 39 | struct gfs2_sbd *sdp = gl->gl_sbd; |
40 | struct list_head *head = &gl->gl_ail_list; | 40 | struct list_head *head = &gl->gl_ail_list; |
41 | struct gfs2_bufdata *bd; | 41 | struct gfs2_bufdata *bd; |
42 | struct buffer_head *bh; | 42 | struct buffer_head *bh; |
43 | struct gfs2_trans tr; | ||
44 | |||
45 | memset(&tr, 0, sizeof(tr)); | ||
46 | tr.tr_revokes = atomic_read(&gl->gl_ail_count); | ||
47 | |||
48 | if (!tr.tr_revokes) | ||
49 | return; | ||
50 | |||
51 | /* A shortened, inline version of gfs2_trans_begin() */ | ||
52 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); | ||
53 | tr.tr_ip = (unsigned long)__builtin_return_address(0); | ||
54 | INIT_LIST_HEAD(&tr.tr_list_buf); | ||
55 | gfs2_log_reserve(sdp, tr.tr_reserved); | ||
56 | BUG_ON(current->journal_info); | ||
57 | current->journal_info = &tr; | ||
58 | 43 | ||
59 | spin_lock(&sdp->sd_ail_lock); | 44 | spin_lock(&sdp->sd_ail_lock); |
60 | while (!list_empty(head)) { | 45 | while (!list_empty(head)) { |
@@ -76,11 +61,51 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
76 | } | 61 | } |
77 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); | 62 | gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); |
78 | spin_unlock(&sdp->sd_ail_lock); | 63 | spin_unlock(&sdp->sd_ail_lock); |
64 | } | ||
65 | |||
66 | |||
67 | static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | ||
68 | { | ||
69 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
70 | struct gfs2_trans tr; | ||
71 | |||
72 | memset(&tr, 0, sizeof(tr)); | ||
73 | tr.tr_revokes = atomic_read(&gl->gl_ail_count); | ||
74 | |||
75 | if (!tr.tr_revokes) | ||
76 | return; | ||
77 | |||
78 | /* A shortened, inline version of gfs2_trans_begin() */ | ||
79 | tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64)); | ||
80 | tr.tr_ip = (unsigned long)__builtin_return_address(0); | ||
81 | INIT_LIST_HEAD(&tr.tr_list_buf); | ||
82 | gfs2_log_reserve(sdp, tr.tr_reserved); | ||
83 | BUG_ON(current->journal_info); | ||
84 | current->journal_info = &tr; | ||
85 | |||
86 | __gfs2_ail_flush(gl); | ||
79 | 87 | ||
80 | gfs2_trans_end(sdp); | 88 | gfs2_trans_end(sdp); |
81 | gfs2_log_flush(sdp, NULL); | 89 | gfs2_log_flush(sdp, NULL); |
82 | } | 90 | } |
83 | 91 | ||
92 | void gfs2_ail_flush(struct gfs2_glock *gl) | ||
93 | { | ||
94 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
95 | unsigned int revokes = atomic_read(&gl->gl_ail_count); | ||
96 | int ret; | ||
97 | |||
98 | if (!revokes) | ||
99 | return; | ||
100 | |||
101 | ret = gfs2_trans_begin(sdp, 0, revokes); | ||
102 | if (ret) | ||
103 | return; | ||
104 | __gfs2_ail_flush(gl); | ||
105 | gfs2_trans_end(sdp); | ||
106 | gfs2_log_flush(sdp, NULL); | ||
107 | } | ||
108 | |||
84 | /** | 109 | /** |
85 | * rgrp_go_sync - sync out the metadata for this glock | 110 | * rgrp_go_sync - sync out the metadata for this glock |
86 | * @gl: the glock | 111 | * @gl: the glock |
@@ -227,6 +252,119 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl) | |||
227 | } | 252 | } |
228 | 253 | ||
229 | /** | 254 | /** |
255 | * gfs2_set_nlink - Set the inode's link count based on on-disk info | ||
256 | * @inode: The inode in question | ||
257 | * @nlink: The link count | ||
258 | * | ||
259 | * If the link count has hit zero, it must never be raised, whatever the | ||
260 | * on-disk inode might say. When new struct inodes are created the link | ||
261 | * count is set to 1, so that we can safely use this test even when reading | ||
262 | * in on disk information for the first time. | ||
263 | */ | ||
264 | |||
265 | static void gfs2_set_nlink(struct inode *inode, u32 nlink) | ||
266 | { | ||
267 | /* | ||
268 | * We will need to review setting the nlink count here in the | ||
269 | * light of the forthcoming ro bind mount work. This is a reminder | ||
270 | * to do that. | ||
271 | */ | ||
272 | if ((inode->i_nlink != nlink) && (inode->i_nlink != 0)) { | ||
273 | if (nlink == 0) | ||
274 | clear_nlink(inode); | ||
275 | else | ||
276 | inode->i_nlink = nlink; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | ||
281 | { | ||
282 | const struct gfs2_dinode *str = buf; | ||
283 | struct timespec atime; | ||
284 | u16 height, depth; | ||
285 | |||
286 | if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) | ||
287 | goto corrupt; | ||
288 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); | ||
289 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); | ||
290 | ip->i_inode.i_rdev = 0; | ||
291 | switch (ip->i_inode.i_mode & S_IFMT) { | ||
292 | case S_IFBLK: | ||
293 | case S_IFCHR: | ||
294 | ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), | ||
295 | be32_to_cpu(str->di_minor)); | ||
296 | break; | ||
297 | }; | ||
298 | |||
299 | ip->i_inode.i_uid = be32_to_cpu(str->di_uid); | ||
300 | ip->i_inode.i_gid = be32_to_cpu(str->di_gid); | ||
301 | gfs2_set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink)); | ||
302 | i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); | ||
303 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); | ||
304 | atime.tv_sec = be64_to_cpu(str->di_atime); | ||
305 | atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); | ||
306 | if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0) | ||
307 | ip->i_inode.i_atime = atime; | ||
308 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); | ||
309 | ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); | ||
310 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); | ||
311 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); | ||
312 | |||
313 | ip->i_goal = be64_to_cpu(str->di_goal_meta); | ||
314 | ip->i_generation = be64_to_cpu(str->di_generation); | ||
315 | |||
316 | ip->i_diskflags = be32_to_cpu(str->di_flags); | ||
317 | gfs2_set_inode_flags(&ip->i_inode); | ||
318 | height = be16_to_cpu(str->di_height); | ||
319 | if (unlikely(height > GFS2_MAX_META_HEIGHT)) | ||
320 | goto corrupt; | ||
321 | ip->i_height = (u8)height; | ||
322 | |||
323 | depth = be16_to_cpu(str->di_depth); | ||
324 | if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) | ||
325 | goto corrupt; | ||
326 | ip->i_depth = (u8)depth; | ||
327 | ip->i_entries = be32_to_cpu(str->di_entries); | ||
328 | |||
329 | ip->i_eattr = be64_to_cpu(str->di_eattr); | ||
330 | if (S_ISREG(ip->i_inode.i_mode)) | ||
331 | gfs2_set_aops(&ip->i_inode); | ||
332 | |||
333 | return 0; | ||
334 | corrupt: | ||
335 | gfs2_consist_inode(ip); | ||
336 | return -EIO; | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * gfs2_inode_refresh - Refresh the incore copy of the dinode | ||
341 | * @ip: The GFS2 inode | ||
342 | * | ||
343 | * Returns: errno | ||
344 | */ | ||
345 | |||
346 | int gfs2_inode_refresh(struct gfs2_inode *ip) | ||
347 | { | ||
348 | struct buffer_head *dibh; | ||
349 | int error; | ||
350 | |||
351 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
352 | if (error) | ||
353 | return error; | ||
354 | |||
355 | if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), dibh, GFS2_METATYPE_DI)) { | ||
356 | brelse(dibh); | ||
357 | return -EIO; | ||
358 | } | ||
359 | |||
360 | error = gfs2_dinode_in(ip, dibh->b_data); | ||
361 | brelse(dibh); | ||
362 | clear_bit(GIF_INVALID, &ip->i_flags); | ||
363 | |||
364 | return error; | ||
365 | } | ||
366 | |||
367 | /** | ||
230 | * inode_go_lock - operation done after an inode lock is locked by a process | 368 | * inode_go_lock - operation done after an inode lock is locked by a process |
231 | * @gl: the glock | 369 | * @gl: the glock |
232 | * @flags: | 370 | * @flags: |
@@ -385,6 +523,10 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl) | |||
385 | static void iopen_go_callback(struct gfs2_glock *gl) | 523 | static void iopen_go_callback(struct gfs2_glock *gl) |
386 | { | 524 | { |
387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 525 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
526 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
527 | |||
528 | if (sdp->sd_vfs->s_flags & MS_RDONLY) | ||
529 | return; | ||
388 | 530 | ||
389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 531 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
390 | gl->gl_state == LM_ST_SHARED && ip) { | 532 | gl->gl_state == LM_ST_SHARED && ip) { |
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h index b3aa2e3210fd..6fce409b5a50 100644 --- a/fs/gfs2/glops.h +++ b/fs/gfs2/glops.h | |||
@@ -23,4 +23,6 @@ extern const struct gfs2_glock_operations gfs2_quota_glops; | |||
23 | extern const struct gfs2_glock_operations gfs2_journal_glops; | 23 | extern const struct gfs2_glock_operations gfs2_journal_glops; |
24 | extern const struct gfs2_glock_operations *gfs2_glops_list[]; | 24 | extern const struct gfs2_glock_operations *gfs2_glops_list[]; |
25 | 25 | ||
26 | extern void gfs2_ail_flush(struct gfs2_glock *gl); | ||
27 | |||
26 | #endif /* __GLOPS_DOT_H__ */ | 28 | #endif /* __GLOPS_DOT_H__ */ |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 870a89d6d4dc..0a064e91ac70 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -20,7 +20,6 @@ | |||
20 | 20 | ||
21 | #define DIO_WAIT 0x00000010 | 21 | #define DIO_WAIT 0x00000010 |
22 | #define DIO_METADATA 0x00000020 | 22 | #define DIO_METADATA 0x00000020 |
23 | #define DIO_ALL 0x00000100 | ||
24 | 23 | ||
25 | struct gfs2_log_operations; | 24 | struct gfs2_log_operations; |
26 | struct gfs2_log_element; | 25 | struct gfs2_log_element; |
@@ -200,6 +199,8 @@ enum { | |||
200 | GLF_INITIAL = 10, | 199 | GLF_INITIAL = 10, |
201 | GLF_FROZEN = 11, | 200 | GLF_FROZEN = 11, |
202 | GLF_QUEUED = 12, | 201 | GLF_QUEUED = 12, |
202 | GLF_LRU = 13, | ||
203 | GLF_OBJECT = 14, /* Used only for tracing */ | ||
203 | }; | 204 | }; |
204 | 205 | ||
205 | struct gfs2_glock { | 206 | struct gfs2_glock { |
@@ -234,6 +235,7 @@ struct gfs2_glock { | |||
234 | 235 | ||
235 | struct list_head gl_ail_list; | 236 | struct list_head gl_ail_list; |
236 | atomic_t gl_ail_count; | 237 | atomic_t gl_ail_count; |
238 | atomic_t gl_revokes; | ||
237 | struct delayed_work gl_work; | 239 | struct delayed_work gl_work; |
238 | struct work_struct gl_delete; | 240 | struct work_struct gl_delete; |
239 | struct rcu_head gl_rcu; | 241 | struct rcu_head gl_rcu; |
@@ -374,8 +376,6 @@ struct gfs2_ail { | |||
374 | unsigned int ai_first; | 376 | unsigned int ai_first; |
375 | struct list_head ai_ail1_list; | 377 | struct list_head ai_ail1_list; |
376 | struct list_head ai_ail2_list; | 378 | struct list_head ai_ail2_list; |
377 | |||
378 | u64 ai_sync_gen; | ||
379 | }; | 379 | }; |
380 | 380 | ||
381 | struct gfs2_journal_extent { | 381 | struct gfs2_journal_extent { |
@@ -488,7 +488,6 @@ struct gfs2_sb_host { | |||
488 | 488 | ||
489 | char sb_lockproto[GFS2_LOCKNAME_LEN]; | 489 | char sb_lockproto[GFS2_LOCKNAME_LEN]; |
490 | char sb_locktable[GFS2_LOCKNAME_LEN]; | 490 | char sb_locktable[GFS2_LOCKNAME_LEN]; |
491 | u8 sb_uuid[16]; | ||
492 | }; | 491 | }; |
493 | 492 | ||
494 | /* | 493 | /* |
@@ -654,7 +653,6 @@ struct gfs2_sbd { | |||
654 | spinlock_t sd_ail_lock; | 653 | spinlock_t sd_ail_lock; |
655 | struct list_head sd_ail1_list; | 654 | struct list_head sd_ail1_list; |
656 | struct list_head sd_ail2_list; | 655 | struct list_head sd_ail2_list; |
657 | u64 sd_ail_sync_gen; | ||
658 | 656 | ||
659 | /* Replay stuff */ | 657 | /* Replay stuff */ |
660 | 658 | ||
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 97d54a28776a..03e0c529063e 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1,23 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
7 | * of the GNU General Public License version 2. | 7 | * of the GNU General Public License version 2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
12 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
13 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
14 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
14 | #include <linux/namei.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/xattr.h> | ||
15 | #include <linux/posix_acl.h> | 17 | #include <linux/posix_acl.h> |
16 | #include <linux/sort.h> | ||
17 | #include <linux/gfs2_ondisk.h> | 18 | #include <linux/gfs2_ondisk.h> |
18 | #include <linux/crc32.h> | 19 | #include <linux/crc32.h> |
20 | #include <linux/fiemap.h> | ||
19 | #include <linux/security.h> | 21 | #include <linux/security.h> |
20 | #include <linux/time.h> | 22 | #include <asm/uaccess.h> |
21 | 23 | ||
22 | #include "gfs2.h" | 24 | #include "gfs2.h" |
23 | #include "incore.h" | 25 | #include "incore.h" |
@@ -26,51 +28,70 @@ | |||
26 | #include "dir.h" | 28 | #include "dir.h" |
27 | #include "xattr.h" | 29 | #include "xattr.h" |
28 | #include "glock.h" | 30 | #include "glock.h" |
29 | #include "glops.h" | ||
30 | #include "inode.h" | 31 | #include "inode.h" |
31 | #include "log.h" | ||
32 | #include "meta_io.h" | 32 | #include "meta_io.h" |
33 | #include "quota.h" | 33 | #include "quota.h" |
34 | #include "rgrp.h" | 34 | #include "rgrp.h" |
35 | #include "trans.h" | 35 | #include "trans.h" |
36 | #include "util.h" | 36 | #include "util.h" |
37 | #include "super.h" | ||
38 | #include "glops.h" | ||
37 | 39 | ||
38 | struct gfs2_inum_range_host { | 40 | struct gfs2_skip_data { |
39 | u64 ir_start; | 41 | u64 no_addr; |
40 | u64 ir_length; | 42 | int skipped; |
43 | int non_block; | ||
41 | }; | 44 | }; |
42 | 45 | ||
43 | static int iget_test(struct inode *inode, void *opaque) | 46 | static int iget_test(struct inode *inode, void *opaque) |
44 | { | 47 | { |
45 | struct gfs2_inode *ip = GFS2_I(inode); | 48 | struct gfs2_inode *ip = GFS2_I(inode); |
46 | u64 *no_addr = opaque; | 49 | struct gfs2_skip_data *data = opaque; |
47 | 50 | ||
48 | if (ip->i_no_addr == *no_addr) | 51 | if (ip->i_no_addr == data->no_addr) { |
52 | if (data->non_block && | ||
53 | inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) { | ||
54 | data->skipped = 1; | ||
55 | return 0; | ||
56 | } | ||
49 | return 1; | 57 | return 1; |
50 | 58 | } | |
51 | return 0; | 59 | return 0; |
52 | } | 60 | } |
53 | 61 | ||
54 | static int iget_set(struct inode *inode, void *opaque) | 62 | static int iget_set(struct inode *inode, void *opaque) |
55 | { | 63 | { |
56 | struct gfs2_inode *ip = GFS2_I(inode); | 64 | struct gfs2_inode *ip = GFS2_I(inode); |
57 | u64 *no_addr = opaque; | 65 | struct gfs2_skip_data *data = opaque; |
58 | 66 | ||
59 | inode->i_ino = (unsigned long)*no_addr; | 67 | if (data->skipped) |
60 | ip->i_no_addr = *no_addr; | 68 | return -ENOENT; |
69 | inode->i_ino = (unsigned long)(data->no_addr); | ||
70 | ip->i_no_addr = data->no_addr; | ||
61 | return 0; | 71 | return 0; |
62 | } | 72 | } |
63 | 73 | ||
64 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr) | 74 | struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int non_block) |
65 | { | 75 | { |
66 | unsigned long hash = (unsigned long)no_addr; | 76 | unsigned long hash = (unsigned long)no_addr; |
67 | return ilookup5(sb, hash, iget_test, &no_addr); | 77 | struct gfs2_skip_data data; |
78 | |||
79 | data.no_addr = no_addr; | ||
80 | data.skipped = 0; | ||
81 | data.non_block = non_block; | ||
82 | return ilookup5(sb, hash, iget_test, &data); | ||
68 | } | 83 | } |
69 | 84 | ||
70 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | 85 | static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr, |
86 | int non_block) | ||
71 | { | 87 | { |
88 | struct gfs2_skip_data data; | ||
72 | unsigned long hash = (unsigned long)no_addr; | 89 | unsigned long hash = (unsigned long)no_addr; |
73 | return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); | 90 | |
91 | data.no_addr = no_addr; | ||
92 | data.skipped = 0; | ||
93 | data.non_block = non_block; | ||
94 | return iget5_locked(sb, hash, iget_test, iget_set, &data); | ||
74 | } | 95 | } |
75 | 96 | ||
76 | /** | 97 | /** |
@@ -111,19 +132,20 @@ static void gfs2_set_iop(struct inode *inode) | |||
111 | * @sb: The super block | 132 | * @sb: The super block |
112 | * @no_addr: The inode number | 133 | * @no_addr: The inode number |
113 | * @type: The type of the inode | 134 | * @type: The type of the inode |
135 | * non_block: Can we block on inodes that are being freed? | ||
114 | * | 136 | * |
115 | * Returns: A VFS inode, or an error | 137 | * Returns: A VFS inode, or an error |
116 | */ | 138 | */ |
117 | 139 | ||
118 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, | 140 | struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, |
119 | u64 no_addr, u64 no_formal_ino) | 141 | u64 no_addr, u64 no_formal_ino, int non_block) |
120 | { | 142 | { |
121 | struct inode *inode; | 143 | struct inode *inode; |
122 | struct gfs2_inode *ip; | 144 | struct gfs2_inode *ip; |
123 | struct gfs2_glock *io_gl = NULL; | 145 | struct gfs2_glock *io_gl = NULL; |
124 | int error; | 146 | int error; |
125 | 147 | ||
126 | inode = gfs2_iget(sb, no_addr); | 148 | inode = gfs2_iget(sb, no_addr, non_block); |
127 | ip = GFS2_I(inode); | 149 | ip = GFS2_I(inode); |
128 | 150 | ||
129 | if (!inode) | 151 | if (!inode) |
@@ -185,11 +207,12 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
185 | { | 207 | { |
186 | struct super_block *sb = sdp->sd_vfs; | 208 | struct super_block *sb = sdp->sd_vfs; |
187 | struct gfs2_holder i_gh; | 209 | struct gfs2_holder i_gh; |
188 | struct inode *inode; | 210 | struct inode *inode = NULL; |
189 | int error; | 211 | int error; |
190 | 212 | ||
213 | /* Must not read in block until block type is verified */ | ||
191 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, | 214 | error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops, |
192 | LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 215 | LM_ST_EXCLUSIVE, GL_SKIP, &i_gh); |
193 | if (error) | 216 | if (error) |
194 | return ERR_PTR(error); | 217 | return ERR_PTR(error); |
195 | 218 | ||
@@ -197,7 +220,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, | |||
197 | if (error) | 220 | if (error) |
198 | goto fail; | 221 | goto fail; |
199 | 222 | ||
200 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0); | 223 | inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1); |
201 | if (IS_ERR(inode)) | 224 | if (IS_ERR(inode)) |
202 | goto fail; | 225 | goto fail; |
203 | 226 | ||
@@ -222,203 +245,6 @@ fail_iput: | |||
222 | goto fail; | 245 | goto fail; |
223 | } | 246 | } |
224 | 247 | ||
225 | static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) | ||
226 | { | ||
227 | const struct gfs2_dinode *str = buf; | ||
228 | struct timespec atime; | ||
229 | u16 height, depth; | ||
230 | |||
231 | if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) | ||
232 | goto corrupt; | ||
233 | ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); | ||
234 | ip->i_inode.i_mode = be32_to_cpu(str->di_mode); | ||
235 | ip->i_inode.i_rdev = 0; | ||
236 | switch (ip->i_inode.i_mode & S_IFMT) { | ||
237 | case S_IFBLK: | ||
238 | case S_IFCHR: | ||
239 | ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), | ||
240 | be32_to_cpu(str->di_minor)); | ||
241 | break; | ||
242 | }; | ||
243 | |||
244 | ip->i_inode.i_uid = be32_to_cpu(str->di_uid); | ||
245 | ip->i_inode.i_gid = be32_to_cpu(str->di_gid); | ||
246 | /* | ||
247 | * We will need to review setting the nlink count here in the | ||
248 | * light of the forthcoming ro bind mount work. This is a reminder | ||
249 | * to do that. | ||
250 | */ | ||
251 | ip->i_inode.i_nlink = be32_to_cpu(str->di_nlink); | ||
252 | i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); | ||
253 | gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); | ||
254 | atime.tv_sec = be64_to_cpu(str->di_atime); | ||
255 | atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); | ||
256 | if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0) | ||
257 | ip->i_inode.i_atime = atime; | ||
258 | ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); | ||
259 | ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); | ||
260 | ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); | ||
261 | ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); | ||
262 | |||
263 | ip->i_goal = be64_to_cpu(str->di_goal_meta); | ||
264 | ip->i_generation = be64_to_cpu(str->di_generation); | ||
265 | |||
266 | ip->i_diskflags = be32_to_cpu(str->di_flags); | ||
267 | gfs2_set_inode_flags(&ip->i_inode); | ||
268 | height = be16_to_cpu(str->di_height); | ||
269 | if (unlikely(height > GFS2_MAX_META_HEIGHT)) | ||
270 | goto corrupt; | ||
271 | ip->i_height = (u8)height; | ||
272 | |||
273 | depth = be16_to_cpu(str->di_depth); | ||
274 | if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) | ||
275 | goto corrupt; | ||
276 | ip->i_depth = (u8)depth; | ||
277 | ip->i_entries = be32_to_cpu(str->di_entries); | ||
278 | |||
279 | ip->i_eattr = be64_to_cpu(str->di_eattr); | ||
280 | if (S_ISREG(ip->i_inode.i_mode)) | ||
281 | gfs2_set_aops(&ip->i_inode); | ||
282 | |||
283 | return 0; | ||
284 | corrupt: | ||
285 | if (gfs2_consist_inode(ip)) | ||
286 | gfs2_dinode_print(ip); | ||
287 | return -EIO; | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * gfs2_inode_refresh - Refresh the incore copy of the dinode | ||
292 | * @ip: The GFS2 inode | ||
293 | * | ||
294 | * Returns: errno | ||
295 | */ | ||
296 | |||
297 | int gfs2_inode_refresh(struct gfs2_inode *ip) | ||
298 | { | ||
299 | struct buffer_head *dibh; | ||
300 | int error; | ||
301 | |||
302 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
303 | if (error) | ||
304 | return error; | ||
305 | |||
306 | if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), dibh, GFS2_METATYPE_DI)) { | ||
307 | brelse(dibh); | ||
308 | return -EIO; | ||
309 | } | ||
310 | |||
311 | error = gfs2_dinode_in(ip, dibh->b_data); | ||
312 | brelse(dibh); | ||
313 | clear_bit(GIF_INVALID, &ip->i_flags); | ||
314 | |||
315 | return error; | ||
316 | } | ||
317 | |||
318 | int gfs2_dinode_dealloc(struct gfs2_inode *ip) | ||
319 | { | ||
320 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
321 | struct gfs2_alloc *al; | ||
322 | struct gfs2_rgrpd *rgd; | ||
323 | int error; | ||
324 | |||
325 | if (gfs2_get_inode_blocks(&ip->i_inode) != 1) { | ||
326 | if (gfs2_consist_inode(ip)) | ||
327 | gfs2_dinode_print(ip); | ||
328 | return -EIO; | ||
329 | } | ||
330 | |||
331 | al = gfs2_alloc_get(ip); | ||
332 | if (!al) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | ||
336 | if (error) | ||
337 | goto out; | ||
338 | |||
339 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
340 | if (error) | ||
341 | goto out_qs; | ||
342 | |||
343 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
344 | if (!rgd) { | ||
345 | gfs2_consist_inode(ip); | ||
346 | error = -EIO; | ||
347 | goto out_rindex_relse; | ||
348 | } | ||
349 | |||
350 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, | ||
351 | &al->al_rgd_gh); | ||
352 | if (error) | ||
353 | goto out_rindex_relse; | ||
354 | |||
355 | error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, 1); | ||
356 | if (error) | ||
357 | goto out_rg_gunlock; | ||
358 | |||
359 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); | ||
360 | set_bit(GLF_LFLUSH, &ip->i_gl->gl_flags); | ||
361 | |||
362 | gfs2_free_di(rgd, ip); | ||
363 | |||
364 | gfs2_trans_end(sdp); | ||
365 | |||
366 | out_rg_gunlock: | ||
367 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | ||
368 | out_rindex_relse: | ||
369 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
370 | out_qs: | ||
371 | gfs2_quota_unhold(ip); | ||
372 | out: | ||
373 | gfs2_alloc_put(ip); | ||
374 | return error; | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * gfs2_change_nlink - Change nlink count on inode | ||
379 | * @ip: The GFS2 inode | ||
380 | * @diff: The change in the nlink count required | ||
381 | * | ||
382 | * Returns: errno | ||
383 | */ | ||
384 | int gfs2_change_nlink(struct gfs2_inode *ip, int diff) | ||
385 | { | ||
386 | struct buffer_head *dibh; | ||
387 | u32 nlink; | ||
388 | int error; | ||
389 | |||
390 | BUG_ON(diff != 1 && diff != -1); | ||
391 | nlink = ip->i_inode.i_nlink + diff; | ||
392 | |||
393 | /* If we are reducing the nlink count, but the new value ends up being | ||
394 | bigger than the old one, we must have underflowed. */ | ||
395 | if (diff < 0 && nlink > ip->i_inode.i_nlink) { | ||
396 | if (gfs2_consist_inode(ip)) | ||
397 | gfs2_dinode_print(ip); | ||
398 | return -EIO; | ||
399 | } | ||
400 | |||
401 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
402 | if (error) | ||
403 | return error; | ||
404 | |||
405 | if (diff > 0) | ||
406 | inc_nlink(&ip->i_inode); | ||
407 | else | ||
408 | drop_nlink(&ip->i_inode); | ||
409 | |||
410 | ip->i_inode.i_ctime = CURRENT_TIME; | ||
411 | |||
412 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
413 | gfs2_dinode_out(ip, dibh->b_data); | ||
414 | brelse(dibh); | ||
415 | mark_inode_dirty(&ip->i_inode); | ||
416 | |||
417 | if (ip->i_inode.i_nlink == 0) | ||
418 | gfs2_unlink_di(&ip->i_inode); /* mark inode unlinked */ | ||
419 | |||
420 | return error; | ||
421 | } | ||
422 | 248 | ||
423 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) | 249 | struct inode *gfs2_lookup_simple(struct inode *dip, const char *name) |
424 | { | 250 | { |
@@ -517,7 +343,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
517 | 343 | ||
518 | /* Don't create entries in an unlinked directory */ | 344 | /* Don't create entries in an unlinked directory */ |
519 | if (!dip->i_inode.i_nlink) | 345 | if (!dip->i_inode.i_nlink) |
520 | return -EPERM; | 346 | return -ENOENT; |
521 | 347 | ||
522 | error = gfs2_dir_check(&dip->i_inode, name, NULL); | 348 | error = gfs2_dir_check(&dip->i_inode, name, NULL); |
523 | switch (error) { | 349 | switch (error) { |
@@ -587,21 +413,44 @@ out: | |||
587 | return error; | 413 | return error; |
588 | } | 414 | } |
589 | 415 | ||
416 | static void gfs2_init_dir(struct buffer_head *dibh, | ||
417 | const struct gfs2_inode *parent) | ||
418 | { | ||
419 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | ||
420 | struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1); | ||
421 | |||
422 | gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent); | ||
423 | dent->de_inum = di->di_num; /* already GFS2 endian */ | ||
424 | dent->de_type = cpu_to_be16(DT_DIR); | ||
425 | |||
426 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); | ||
427 | gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); | ||
428 | gfs2_inum_out(parent, dent); | ||
429 | dent->de_type = cpu_to_be16(DT_DIR); | ||
430 | |||
431 | } | ||
432 | |||
590 | /** | 433 | /** |
591 | * init_dinode - Fill in a new dinode structure | 434 | * init_dinode - Fill in a new dinode structure |
592 | * @dip: the directory this inode is being created in | 435 | * @dip: The directory this inode is being created in |
593 | * @gl: The glock covering the new inode | 436 | * @gl: The glock covering the new inode |
594 | * @inum: the inode number | 437 | * @inum: The inode number |
595 | * @mode: the file permissions | 438 | * @mode: The file permissions |
596 | * @uid: | 439 | * @uid: The uid of the new inode |
597 | * @gid: | 440 | * @gid: The gid of the new inode |
441 | * @generation: The generation number of the new inode | ||
442 | * @dev: The device number (if a device node) | ||
443 | * @symname: The symlink destination (if a symlink) | ||
444 | * @size: The inode size (ignored for directories) | ||
445 | * @bhp: The buffer head (returned to caller) | ||
598 | * | 446 | * |
599 | */ | 447 | */ |
600 | 448 | ||
601 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 449 | static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, |
602 | const struct gfs2_inum_host *inum, unsigned int mode, | 450 | const struct gfs2_inum_host *inum, unsigned int mode, |
603 | unsigned int uid, unsigned int gid, | 451 | unsigned int uid, unsigned int gid, |
604 | const u64 *generation, dev_t dev, struct buffer_head **bhp) | 452 | const u64 *generation, dev_t dev, const char *symname, |
453 | unsigned size, struct buffer_head **bhp) | ||
605 | { | 454 | { |
606 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 455 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
607 | struct gfs2_dinode *di; | 456 | struct gfs2_dinode *di; |
@@ -620,7 +469,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
620 | di->di_uid = cpu_to_be32(uid); | 469 | di->di_uid = cpu_to_be32(uid); |
621 | di->di_gid = cpu_to_be32(gid); | 470 | di->di_gid = cpu_to_be32(gid); |
622 | di->di_nlink = 0; | 471 | di->di_nlink = 0; |
623 | di->di_size = 0; | 472 | di->di_size = cpu_to_be64(size); |
624 | di->di_blocks = cpu_to_be64(1); | 473 | di->di_blocks = cpu_to_be64(1); |
625 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); | 474 | di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec); |
626 | di->di_major = cpu_to_be32(MAJOR(dev)); | 475 | di->di_major = cpu_to_be32(MAJOR(dev)); |
@@ -628,16 +477,6 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
628 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); | 477 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr); |
629 | di->di_generation = cpu_to_be64(*generation); | 478 | di->di_generation = cpu_to_be64(*generation); |
630 | di->di_flags = 0; | 479 | di->di_flags = 0; |
631 | |||
632 | if (S_ISREG(mode)) { | ||
633 | if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) || | ||
634 | gfs2_tune_get(sdp, gt_new_files_jdata)) | ||
635 | di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA); | ||
636 | } else if (S_ISDIR(mode)) { | ||
637 | di->di_flags |= cpu_to_be32(dip->i_diskflags & | ||
638 | GFS2_DIF_INHERIT_JDATA); | ||
639 | } | ||
640 | |||
641 | di->__pad1 = 0; | 480 | di->__pad1 = 0; |
642 | di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); | 481 | di->di_payload_format = cpu_to_be32(S_ISDIR(mode) ? GFS2_FORMAT_DE : 0); |
643 | di->di_height = 0; | 482 | di->di_height = 0; |
@@ -651,7 +490,26 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
651 | di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); | 490 | di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec); |
652 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); | 491 | di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec); |
653 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); | 492 | memset(&di->di_reserved, 0, sizeof(di->di_reserved)); |
654 | 493 | ||
494 | switch(mode & S_IFMT) { | ||
495 | case S_IFREG: | ||
496 | if ((dip->i_diskflags & GFS2_DIF_INHERIT_JDATA) || | ||
497 | gfs2_tune_get(sdp, gt_new_files_jdata)) | ||
498 | di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA); | ||
499 | break; | ||
500 | case S_IFDIR: | ||
501 | di->di_flags |= cpu_to_be32(dip->i_diskflags & | ||
502 | GFS2_DIF_INHERIT_JDATA); | ||
503 | di->di_flags |= cpu_to_be32(GFS2_DIF_JDATA); | ||
504 | di->di_size = cpu_to_be64(sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)); | ||
505 | di->di_entries = cpu_to_be32(2); | ||
506 | gfs2_init_dir(dibh, dip); | ||
507 | break; | ||
508 | case S_IFLNK: | ||
509 | memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, size); | ||
510 | break; | ||
511 | } | ||
512 | |||
655 | set_buffer_uptodate(dibh); | 513 | set_buffer_uptodate(dibh); |
656 | 514 | ||
657 | *bhp = dibh; | 515 | *bhp = dibh; |
@@ -659,7 +517,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
659 | 517 | ||
660 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | 518 | static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, |
661 | unsigned int mode, const struct gfs2_inum_host *inum, | 519 | unsigned int mode, const struct gfs2_inum_host *inum, |
662 | const u64 *generation, dev_t dev, struct buffer_head **bhp) | 520 | const u64 *generation, dev_t dev, const char *symname, |
521 | unsigned int size, struct buffer_head **bhp) | ||
663 | { | 522 | { |
664 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 523 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
665 | unsigned int uid, gid; | 524 | unsigned int uid, gid; |
@@ -681,7 +540,7 @@ static int make_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl, | |||
681 | if (error) | 540 | if (error) |
682 | goto out_quota; | 541 | goto out_quota; |
683 | 542 | ||
684 | init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, bhp); | 543 | init_dinode(dip, gl, inum, mode, uid, gid, generation, dev, symname, size, bhp); |
685 | gfs2_quota_change(dip, +1, uid, gid); | 544 | gfs2_quota_change(dip, +1, uid, gid); |
686 | gfs2_trans_end(sdp); | 545 | gfs2_trans_end(sdp); |
687 | 546 | ||
@@ -735,14 +594,16 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, | |||
735 | goto fail_quota_locks; | 594 | goto fail_quota_locks; |
736 | } | 595 | } |
737 | 596 | ||
738 | error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode)); | 597 | error = gfs2_dir_add(&dip->i_inode, name, ip); |
739 | if (error) | 598 | if (error) |
740 | goto fail_end_trans; | 599 | goto fail_end_trans; |
741 | 600 | ||
742 | error = gfs2_meta_inode_buffer(ip, &dibh); | 601 | error = gfs2_meta_inode_buffer(ip, &dibh); |
743 | if (error) | 602 | if (error) |
744 | goto fail_end_trans; | 603 | goto fail_end_trans; |
745 | ip->i_inode.i_nlink = 1; | 604 | inc_nlink(&ip->i_inode); |
605 | if (S_ISDIR(ip->i_inode.i_mode)) | ||
606 | inc_nlink(&ip->i_inode); | ||
746 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 607 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
747 | gfs2_dinode_out(ip, dibh->b_data); | 608 | gfs2_dinode_out(ip, dibh->b_data); |
748 | brelse(dibh); | 609 | brelse(dibh); |
@@ -789,27 +650,25 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, | |||
789 | } | 650 | } |
790 | 651 | ||
791 | /** | 652 | /** |
792 | * gfs2_createi - Create a new inode | 653 | * gfs2_create_inode - Create a new inode |
793 | * @ghs: An array of two holders | 654 | * @dir: The parent directory |
794 | * @name: The name of the new file | 655 | * @dentry: The new dentry |
795 | * @mode: the permissions on the new inode | 656 | * @mode: The permissions on the new inode |
657 | * @dev: For device nodes, this is the device number | ||
658 | * @symname: For symlinks, this is the link destination | ||
659 | * @size: The initial size of the inode (ignored for directories) | ||
796 | * | 660 | * |
797 | * @ghs[0] is an initialized holder for the directory | 661 | * Returns: 0 on success, or error code |
798 | * @ghs[1] is the holder for the inode lock | ||
799 | * | ||
800 | * If the return value is not NULL, the glocks on both the directory and the new | ||
801 | * file are held. A transaction has been started and an inplace reservation | ||
802 | * is held, as well. | ||
803 | * | ||
804 | * Returns: An inode | ||
805 | */ | 662 | */ |
806 | 663 | ||
807 | struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | 664 | static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, |
808 | unsigned int mode, dev_t dev) | 665 | unsigned int mode, dev_t dev, const char *symname, |
666 | unsigned int size) | ||
809 | { | 667 | { |
668 | const struct qstr *name = &dentry->d_name; | ||
669 | struct gfs2_holder ghs[2]; | ||
810 | struct inode *inode = NULL; | 670 | struct inode *inode = NULL; |
811 | struct gfs2_inode *dip = ghs->gh_gl->gl_object; | 671 | struct gfs2_inode *dip = GFS2_I(dir); |
812 | struct inode *dir = &dip->i_inode; | ||
813 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 672 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
814 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; | 673 | struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 }; |
815 | int error; | 674 | int error; |
@@ -817,10 +676,9 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
817 | struct buffer_head *bh = NULL; | 676 | struct buffer_head *bh = NULL; |
818 | 677 | ||
819 | if (!name->len || name->len > GFS2_FNAMESIZE) | 678 | if (!name->len || name->len > GFS2_FNAMESIZE) |
820 | return ERR_PTR(-ENAMETOOLONG); | 679 | return -ENAMETOOLONG; |
821 | 680 | ||
822 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, 0, ghs); | 681 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
823 | error = gfs2_glock_nq(ghs); | ||
824 | if (error) | 682 | if (error) |
825 | goto fail; | 683 | goto fail; |
826 | 684 | ||
@@ -838,12 +696,12 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
838 | if (error) | 696 | if (error) |
839 | goto fail_gunlock; | 697 | goto fail_gunlock; |
840 | 698 | ||
841 | error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, &bh); | 699 | error = make_dinode(dip, ghs[1].gh_gl, mode, &inum, &generation, dev, symname, size, &bh); |
842 | if (error) | 700 | if (error) |
843 | goto fail_gunlock2; | 701 | goto fail_gunlock2; |
844 | 702 | ||
845 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, | 703 | inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr, |
846 | inum.no_formal_ino); | 704 | inum.no_formal_ino, 0); |
847 | if (IS_ERR(inode)) | 705 | if (IS_ERR(inode)) |
848 | goto fail_gunlock2; | 706 | goto fail_gunlock2; |
849 | 707 | ||
@@ -865,18 +723,852 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
865 | 723 | ||
866 | if (bh) | 724 | if (bh) |
867 | brelse(bh); | 725 | brelse(bh); |
868 | return inode; | 726 | |
727 | gfs2_trans_end(sdp); | ||
728 | if (dip->i_alloc->al_rgd) | ||
729 | gfs2_inplace_release(dip); | ||
730 | gfs2_quota_unlock(dip); | ||
731 | gfs2_alloc_put(dip); | ||
732 | gfs2_glock_dq_uninit_m(2, ghs); | ||
733 | mark_inode_dirty(inode); | ||
734 | d_instantiate(dentry, inode); | ||
735 | return 0; | ||
869 | 736 | ||
870 | fail_gunlock2: | 737 | fail_gunlock2: |
871 | gfs2_glock_dq_uninit(ghs + 1); | 738 | gfs2_glock_dq_uninit(ghs + 1); |
872 | if (inode && !IS_ERR(inode)) | 739 | if (inode && !IS_ERR(inode)) |
873 | iput(inode); | 740 | iput(inode); |
874 | fail_gunlock: | 741 | fail_gunlock: |
875 | gfs2_glock_dq(ghs); | 742 | gfs2_glock_dq_uninit(ghs); |
876 | fail: | 743 | fail: |
877 | if (bh) | 744 | if (bh) |
878 | brelse(bh); | 745 | brelse(bh); |
879 | return ERR_PTR(error); | 746 | return error; |
747 | } | ||
748 | |||
749 | /** | ||
750 | * gfs2_create - Create a file | ||
751 | * @dir: The directory in which to create the file | ||
752 | * @dentry: The dentry of the new file | ||
753 | * @mode: The mode of the new file | ||
754 | * | ||
755 | * Returns: errno | ||
756 | */ | ||
757 | |||
758 | static int gfs2_create(struct inode *dir, struct dentry *dentry, | ||
759 | int mode, struct nameidata *nd) | ||
760 | { | ||
761 | struct inode *inode; | ||
762 | int ret; | ||
763 | |||
764 | for (;;) { | ||
765 | ret = gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0); | ||
766 | if (ret != -EEXIST || (nd && (nd->flags & LOOKUP_EXCL))) | ||
767 | return ret; | ||
768 | |||
769 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | ||
770 | if (inode) { | ||
771 | if (!IS_ERR(inode)) | ||
772 | break; | ||
773 | return PTR_ERR(inode); | ||
774 | } | ||
775 | } | ||
776 | |||
777 | d_instantiate(dentry, inode); | ||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | /** | ||
782 | * gfs2_lookup - Look up a filename in a directory and return its inode | ||
783 | * @dir: The directory inode | ||
784 | * @dentry: The dentry of the new inode | ||
785 | * @nd: passed from Linux VFS, ignored by us | ||
786 | * | ||
787 | * Called by the VFS layer. Lock dir and call gfs2_lookupi() | ||
788 | * | ||
789 | * Returns: errno | ||
790 | */ | ||
791 | |||
792 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, | ||
793 | struct nameidata *nd) | ||
794 | { | ||
795 | struct inode *inode = NULL; | ||
796 | |||
797 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | ||
798 | if (inode && IS_ERR(inode)) | ||
799 | return ERR_CAST(inode); | ||
800 | |||
801 | if (inode) { | ||
802 | struct gfs2_glock *gl = GFS2_I(inode)->i_gl; | ||
803 | struct gfs2_holder gh; | ||
804 | int error; | ||
805 | error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
806 | if (error) { | ||
807 | iput(inode); | ||
808 | return ERR_PTR(error); | ||
809 | } | ||
810 | gfs2_glock_dq_uninit(&gh); | ||
811 | return d_splice_alias(inode, dentry); | ||
812 | } | ||
813 | d_add(dentry, inode); | ||
814 | |||
815 | return NULL; | ||
816 | } | ||
817 | |||
818 | /** | ||
819 | * gfs2_link - Link to a file | ||
820 | * @old_dentry: The inode to link | ||
821 | * @dir: Add link to this directory | ||
822 | * @dentry: The name of the link | ||
823 | * | ||
824 | * Link the inode in "old_dentry" into the directory "dir" with the | ||
825 | * name in "dentry". | ||
826 | * | ||
827 | * Returns: errno | ||
828 | */ | ||
829 | |||
830 | static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | ||
831 | struct dentry *dentry) | ||
832 | { | ||
833 | struct gfs2_inode *dip = GFS2_I(dir); | ||
834 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
835 | struct inode *inode = old_dentry->d_inode; | ||
836 | struct gfs2_inode *ip = GFS2_I(inode); | ||
837 | struct gfs2_holder ghs[2]; | ||
838 | struct buffer_head *dibh; | ||
839 | int alloc_required; | ||
840 | int error; | ||
841 | |||
842 | if (S_ISDIR(inode->i_mode)) | ||
843 | return -EPERM; | ||
844 | |||
845 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
846 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | ||
847 | |||
848 | error = gfs2_glock_nq(ghs); /* parent */ | ||
849 | if (error) | ||
850 | goto out_parent; | ||
851 | |||
852 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
853 | if (error) | ||
854 | goto out_child; | ||
855 | |||
856 | error = -ENOENT; | ||
857 | if (inode->i_nlink == 0) | ||
858 | goto out_gunlock; | ||
859 | |||
860 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0); | ||
861 | if (error) | ||
862 | goto out_gunlock; | ||
863 | |||
864 | error = gfs2_dir_check(dir, &dentry->d_name, NULL); | ||
865 | switch (error) { | ||
866 | case -ENOENT: | ||
867 | break; | ||
868 | case 0: | ||
869 | error = -EEXIST; | ||
870 | default: | ||
871 | goto out_gunlock; | ||
872 | } | ||
873 | |||
874 | error = -EINVAL; | ||
875 | if (!dip->i_inode.i_nlink) | ||
876 | goto out_gunlock; | ||
877 | error = -EFBIG; | ||
878 | if (dip->i_entries == (u32)-1) | ||
879 | goto out_gunlock; | ||
880 | error = -EPERM; | ||
881 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
882 | goto out_gunlock; | ||
883 | error = -EINVAL; | ||
884 | if (!ip->i_inode.i_nlink) | ||
885 | goto out_gunlock; | ||
886 | error = -EMLINK; | ||
887 | if (ip->i_inode.i_nlink == (u32)-1) | ||
888 | goto out_gunlock; | ||
889 | |||
890 | alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name); | ||
891 | if (error < 0) | ||
892 | goto out_gunlock; | ||
893 | error = 0; | ||
894 | |||
895 | if (alloc_required) { | ||
896 | struct gfs2_alloc *al = gfs2_alloc_get(dip); | ||
897 | if (!al) { | ||
898 | error = -ENOMEM; | ||
899 | goto out_gunlock; | ||
900 | } | ||
901 | |||
902 | error = gfs2_quota_lock_check(dip); | ||
903 | if (error) | ||
904 | goto out_alloc; | ||
905 | |||
906 | al->al_requested = sdp->sd_max_dirres; | ||
907 | |||
908 | error = gfs2_inplace_reserve(dip); | ||
909 | if (error) | ||
910 | goto out_gunlock_q; | ||
911 | |||
912 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | ||
913 | gfs2_rg_blocks(al) + | ||
914 | 2 * RES_DINODE + RES_STATFS + | ||
915 | RES_QUOTA, 0); | ||
916 | if (error) | ||
917 | goto out_ipres; | ||
918 | } else { | ||
919 | error = gfs2_trans_begin(sdp, 2 * RES_DINODE + RES_LEAF, 0); | ||
920 | if (error) | ||
921 | goto out_ipres; | ||
922 | } | ||
923 | |||
924 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
925 | if (error) | ||
926 | goto out_end_trans; | ||
927 | |||
928 | error = gfs2_dir_add(dir, &dentry->d_name, ip); | ||
929 | if (error) | ||
930 | goto out_brelse; | ||
931 | |||
932 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
933 | inc_nlink(&ip->i_inode); | ||
934 | ip->i_inode.i_ctime = CURRENT_TIME; | ||
935 | gfs2_dinode_out(ip, dibh->b_data); | ||
936 | mark_inode_dirty(&ip->i_inode); | ||
937 | |||
938 | out_brelse: | ||
939 | brelse(dibh); | ||
940 | out_end_trans: | ||
941 | gfs2_trans_end(sdp); | ||
942 | out_ipres: | ||
943 | if (alloc_required) | ||
944 | gfs2_inplace_release(dip); | ||
945 | out_gunlock_q: | ||
946 | if (alloc_required) | ||
947 | gfs2_quota_unlock(dip); | ||
948 | out_alloc: | ||
949 | if (alloc_required) | ||
950 | gfs2_alloc_put(dip); | ||
951 | out_gunlock: | ||
952 | gfs2_glock_dq(ghs + 1); | ||
953 | out_child: | ||
954 | gfs2_glock_dq(ghs); | ||
955 | out_parent: | ||
956 | gfs2_holder_uninit(ghs); | ||
957 | gfs2_holder_uninit(ghs + 1); | ||
958 | if (!error) { | ||
959 | ihold(inode); | ||
960 | d_instantiate(dentry, inode); | ||
961 | mark_inode_dirty(inode); | ||
962 | } | ||
963 | return error; | ||
964 | } | ||
965 | |||
966 | /* | ||
967 | * gfs2_unlink_ok - check to see that a inode is still in a directory | ||
968 | * @dip: the directory | ||
969 | * @name: the name of the file | ||
970 | * @ip: the inode | ||
971 | * | ||
972 | * Assumes that the lock on (at least) @dip is held. | ||
973 | * | ||
974 | * Returns: 0 if the parent/child relationship is correct, errno if it isn't | ||
975 | */ | ||
976 | |||
977 | static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | ||
978 | const struct gfs2_inode *ip) | ||
979 | { | ||
980 | int error; | ||
981 | |||
982 | if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode)) | ||
983 | return -EPERM; | ||
984 | |||
985 | if ((dip->i_inode.i_mode & S_ISVTX) && | ||
986 | dip->i_inode.i_uid != current_fsuid() && | ||
987 | ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER)) | ||
988 | return -EPERM; | ||
989 | |||
990 | if (IS_APPEND(&dip->i_inode)) | ||
991 | return -EPERM; | ||
992 | |||
993 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0); | ||
994 | if (error) | ||
995 | return error; | ||
996 | |||
997 | error = gfs2_dir_check(&dip->i_inode, name, ip); | ||
998 | if (error) | ||
999 | return error; | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /** | ||
1005 | * gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it | ||
1006 | * @dip: The parent directory | ||
1007 | * @name: The name of the entry in the parent directory | ||
1008 | * @bh: The inode buffer for the inode to be removed | ||
1009 | * @inode: The inode to be removed | ||
1010 | * | ||
1011 | * Called with all the locks and in a transaction. This will only be | ||
1012 | * called for a directory after it has been checked to ensure it is empty. | ||
1013 | * | ||
1014 | * Returns: 0 on success, or an error | ||
1015 | */ | ||
1016 | |||
1017 | static int gfs2_unlink_inode(struct gfs2_inode *dip, | ||
1018 | const struct dentry *dentry, | ||
1019 | struct buffer_head *bh) | ||
1020 | { | ||
1021 | struct inode *inode = dentry->d_inode; | ||
1022 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1023 | int error; | ||
1024 | |||
1025 | error = gfs2_dir_del(dip, dentry); | ||
1026 | if (error) | ||
1027 | return error; | ||
1028 | |||
1029 | ip->i_entries = 0; | ||
1030 | inode->i_ctime = CURRENT_TIME; | ||
1031 | if (S_ISDIR(inode->i_mode)) | ||
1032 | clear_nlink(inode); | ||
1033 | else | ||
1034 | drop_nlink(inode); | ||
1035 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | ||
1036 | gfs2_dinode_out(ip, bh->b_data); | ||
1037 | mark_inode_dirty(inode); | ||
1038 | if (inode->i_nlink == 0) | ||
1039 | gfs2_unlink_di(inode); | ||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | /** | ||
1045 | * gfs2_unlink - Unlink an inode (this does rmdir as well) | ||
1046 | * @dir: The inode of the directory containing the inode to unlink | ||
1047 | * @dentry: The file itself | ||
1048 | * | ||
1049 | * This routine uses the type of the inode as a flag to figure out | ||
1050 | * whether this is an unlink or an rmdir. | ||
1051 | * | ||
1052 | * Returns: errno | ||
1053 | */ | ||
1054 | |||
1055 | static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | ||
1056 | { | ||
1057 | struct gfs2_inode *dip = GFS2_I(dir); | ||
1058 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
1059 | struct inode *inode = dentry->d_inode; | ||
1060 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1061 | struct buffer_head *bh; | ||
1062 | struct gfs2_holder ghs[3]; | ||
1063 | struct gfs2_rgrpd *rgd; | ||
1064 | struct gfs2_holder ri_gh; | ||
1065 | int error; | ||
1066 | |||
1067 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1068 | if (error) | ||
1069 | return error; | ||
1070 | |||
1071 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
1072 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | ||
1073 | |||
1074 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
1075 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
1076 | |||
1077 | |||
1078 | error = gfs2_glock_nq(ghs); /* parent */ | ||
1079 | if (error) | ||
1080 | goto out_parent; | ||
1081 | |||
1082 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
1083 | if (error) | ||
1084 | goto out_child; | ||
1085 | |||
1086 | error = -ENOENT; | ||
1087 | if (inode->i_nlink == 0) | ||
1088 | goto out_rgrp; | ||
1089 | |||
1090 | if (S_ISDIR(inode->i_mode)) { | ||
1091 | error = -ENOTEMPTY; | ||
1092 | if (ip->i_entries > 2 || inode->i_nlink > 2) | ||
1093 | goto out_rgrp; | ||
1094 | } | ||
1095 | |||
1096 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | ||
1097 | if (error) | ||
1098 | goto out_rgrp; | ||
1099 | |||
1100 | error = gfs2_unlink_ok(dip, &dentry->d_name, ip); | ||
1101 | if (error) | ||
1102 | goto out_gunlock; | ||
1103 | |||
1104 | error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0); | ||
1105 | if (error) | ||
1106 | goto out_gunlock; | ||
1107 | |||
1108 | error = gfs2_meta_inode_buffer(ip, &bh); | ||
1109 | if (error) | ||
1110 | goto out_end_trans; | ||
1111 | |||
1112 | error = gfs2_unlink_inode(dip, dentry, bh); | ||
1113 | brelse(bh); | ||
1114 | |||
1115 | out_end_trans: | ||
1116 | gfs2_trans_end(sdp); | ||
1117 | out_gunlock: | ||
1118 | gfs2_glock_dq(ghs + 2); | ||
1119 | out_rgrp: | ||
1120 | gfs2_holder_uninit(ghs + 2); | ||
1121 | gfs2_glock_dq(ghs + 1); | ||
1122 | out_child: | ||
1123 | gfs2_holder_uninit(ghs + 1); | ||
1124 | gfs2_glock_dq(ghs); | ||
1125 | out_parent: | ||
1126 | gfs2_holder_uninit(ghs); | ||
1127 | gfs2_glock_dq_uninit(&ri_gh); | ||
1128 | return error; | ||
1129 | } | ||
1130 | |||
1131 | /** | ||
1132 | * gfs2_symlink - Create a symlink | ||
1133 | * @dir: The directory to create the symlink in | ||
1134 | * @dentry: The dentry to put the symlink in | ||
1135 | * @symname: The thing which the link points to | ||
1136 | * | ||
1137 | * Returns: errno | ||
1138 | */ | ||
1139 | |||
1140 | static int gfs2_symlink(struct inode *dir, struct dentry *dentry, | ||
1141 | const char *symname) | ||
1142 | { | ||
1143 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
1144 | unsigned int size; | ||
1145 | |||
1146 | size = strlen(symname); | ||
1147 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1) | ||
1148 | return -ENAMETOOLONG; | ||
1149 | |||
1150 | return gfs2_create_inode(dir, dentry, S_IFLNK | S_IRWXUGO, 0, symname, size); | ||
1151 | } | ||
1152 | |||
1153 | /** | ||
1154 | * gfs2_mkdir - Make a directory | ||
1155 | * @dir: The parent directory of the new one | ||
1156 | * @dentry: The dentry of the new directory | ||
1157 | * @mode: The mode of the new directory | ||
1158 | * | ||
1159 | * Returns: errno | ||
1160 | */ | ||
1161 | |||
1162 | static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
1163 | { | ||
1164 | return gfs2_create_inode(dir, dentry, S_IFDIR | mode, 0, NULL, 0); | ||
1165 | } | ||
1166 | |||
1167 | /** | ||
1168 | * gfs2_mknod - Make a special file | ||
1169 | * @dir: The directory in which the special file will reside | ||
1170 | * @dentry: The dentry of the special file | ||
1171 | * @mode: The mode of the special file | ||
1172 | * @dev: The device specification of the special file | ||
1173 | * | ||
1174 | */ | ||
1175 | |||
1176 | static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, | ||
1177 | dev_t dev) | ||
1178 | { | ||
1179 | return gfs2_create_inode(dir, dentry, mode, dev, NULL, 0); | ||
1180 | } | ||
1181 | |||
1182 | /* | ||
1183 | * gfs2_ok_to_move - check if it's ok to move a directory to another directory | ||
1184 | * @this: move this | ||
1185 | * @to: to here | ||
1186 | * | ||
1187 | * Follow @to back to the root and make sure we don't encounter @this | ||
1188 | * Assumes we already hold the rename lock. | ||
1189 | * | ||
1190 | * Returns: errno | ||
1191 | */ | ||
1192 | |||
1193 | static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) | ||
1194 | { | ||
1195 | struct inode *dir = &to->i_inode; | ||
1196 | struct super_block *sb = dir->i_sb; | ||
1197 | struct inode *tmp; | ||
1198 | int error = 0; | ||
1199 | |||
1200 | igrab(dir); | ||
1201 | |||
1202 | for (;;) { | ||
1203 | if (dir == &this->i_inode) { | ||
1204 | error = -EINVAL; | ||
1205 | break; | ||
1206 | } | ||
1207 | if (dir == sb->s_root->d_inode) { | ||
1208 | error = 0; | ||
1209 | break; | ||
1210 | } | ||
1211 | |||
1212 | tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1); | ||
1213 | if (IS_ERR(tmp)) { | ||
1214 | error = PTR_ERR(tmp); | ||
1215 | break; | ||
1216 | } | ||
1217 | |||
1218 | iput(dir); | ||
1219 | dir = tmp; | ||
1220 | } | ||
1221 | |||
1222 | iput(dir); | ||
1223 | |||
1224 | return error; | ||
1225 | } | ||
1226 | |||
1227 | /** | ||
1228 | * gfs2_rename - Rename a file | ||
1229 | * @odir: Parent directory of old file name | ||
1230 | * @odentry: The old dentry of the file | ||
1231 | * @ndir: Parent directory of new file name | ||
1232 | * @ndentry: The new dentry of the file | ||
1233 | * | ||
1234 | * Returns: errno | ||
1235 | */ | ||
1236 | |||
1237 | static int gfs2_rename(struct inode *odir, struct dentry *odentry, | ||
1238 | struct inode *ndir, struct dentry *ndentry) | ||
1239 | { | ||
1240 | struct gfs2_inode *odip = GFS2_I(odir); | ||
1241 | struct gfs2_inode *ndip = GFS2_I(ndir); | ||
1242 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | ||
1243 | struct gfs2_inode *nip = NULL; | ||
1244 | struct gfs2_sbd *sdp = GFS2_SB(odir); | ||
1245 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh; | ||
1246 | struct gfs2_rgrpd *nrgd; | ||
1247 | unsigned int num_gh; | ||
1248 | int dir_rename = 0; | ||
1249 | int alloc_required = 0; | ||
1250 | unsigned int x; | ||
1251 | int error; | ||
1252 | |||
1253 | if (ndentry->d_inode) { | ||
1254 | nip = GFS2_I(ndentry->d_inode); | ||
1255 | if (ip == nip) | ||
1256 | return 0; | ||
1257 | } | ||
1258 | |||
1259 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1260 | if (error) | ||
1261 | return error; | ||
1262 | |||
1263 | if (odip != ndip) { | ||
1264 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, | ||
1265 | 0, &r_gh); | ||
1266 | if (error) | ||
1267 | goto out; | ||
1268 | |||
1269 | if (S_ISDIR(ip->i_inode.i_mode)) { | ||
1270 | dir_rename = 1; | ||
1271 | /* don't move a dirctory into it's subdir */ | ||
1272 | error = gfs2_ok_to_move(ip, ndip); | ||
1273 | if (error) | ||
1274 | goto out_gunlock_r; | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | num_gh = 1; | ||
1279 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
1280 | if (odip != ndip) { | ||
1281 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
1282 | num_gh++; | ||
1283 | } | ||
1284 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
1285 | num_gh++; | ||
1286 | |||
1287 | if (nip) { | ||
1288 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
1289 | num_gh++; | ||
1290 | /* grab the resource lock for unlink flag twiddling | ||
1291 | * this is the case of the target file already existing | ||
1292 | * so we unlink before doing the rename | ||
1293 | */ | ||
1294 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr); | ||
1295 | if (nrgd) | ||
1296 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); | ||
1297 | } | ||
1298 | |||
1299 | for (x = 0; x < num_gh; x++) { | ||
1300 | error = gfs2_glock_nq(ghs + x); | ||
1301 | if (error) | ||
1302 | goto out_gunlock; | ||
1303 | } | ||
1304 | |||
1305 | error = -ENOENT; | ||
1306 | if (ip->i_inode.i_nlink == 0) | ||
1307 | goto out_gunlock; | ||
1308 | |||
1309 | /* Check out the old directory */ | ||
1310 | |||
1311 | error = gfs2_unlink_ok(odip, &odentry->d_name, ip); | ||
1312 | if (error) | ||
1313 | goto out_gunlock; | ||
1314 | |||
1315 | /* Check out the new directory */ | ||
1316 | |||
1317 | if (nip) { | ||
1318 | error = gfs2_unlink_ok(ndip, &ndentry->d_name, nip); | ||
1319 | if (error) | ||
1320 | goto out_gunlock; | ||
1321 | |||
1322 | if (nip->i_inode.i_nlink == 0) { | ||
1323 | error = -EAGAIN; | ||
1324 | goto out_gunlock; | ||
1325 | } | ||
1326 | |||
1327 | if (S_ISDIR(nip->i_inode.i_mode)) { | ||
1328 | if (nip->i_entries < 2) { | ||
1329 | gfs2_consist_inode(nip); | ||
1330 | error = -EIO; | ||
1331 | goto out_gunlock; | ||
1332 | } | ||
1333 | if (nip->i_entries > 2) { | ||
1334 | error = -ENOTEMPTY; | ||
1335 | goto out_gunlock; | ||
1336 | } | ||
1337 | } | ||
1338 | } else { | ||
1339 | error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0); | ||
1340 | if (error) | ||
1341 | goto out_gunlock; | ||
1342 | |||
1343 | error = gfs2_dir_check(ndir, &ndentry->d_name, NULL); | ||
1344 | switch (error) { | ||
1345 | case -ENOENT: | ||
1346 | error = 0; | ||
1347 | break; | ||
1348 | case 0: | ||
1349 | error = -EEXIST; | ||
1350 | default: | ||
1351 | goto out_gunlock; | ||
1352 | }; | ||
1353 | |||
1354 | if (odip != ndip) { | ||
1355 | if (!ndip->i_inode.i_nlink) { | ||
1356 | error = -ENOENT; | ||
1357 | goto out_gunlock; | ||
1358 | } | ||
1359 | if (ndip->i_entries == (u32)-1) { | ||
1360 | error = -EFBIG; | ||
1361 | goto out_gunlock; | ||
1362 | } | ||
1363 | if (S_ISDIR(ip->i_inode.i_mode) && | ||
1364 | ndip->i_inode.i_nlink == (u32)-1) { | ||
1365 | error = -EMLINK; | ||
1366 | goto out_gunlock; | ||
1367 | } | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1371 | /* Check out the dir to be renamed */ | ||
1372 | |||
1373 | if (dir_rename) { | ||
1374 | error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0); | ||
1375 | if (error) | ||
1376 | goto out_gunlock; | ||
1377 | } | ||
1378 | |||
1379 | if (nip == NULL) | ||
1380 | alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | ||
1381 | error = alloc_required; | ||
1382 | if (error < 0) | ||
1383 | goto out_gunlock; | ||
1384 | error = 0; | ||
1385 | |||
1386 | if (alloc_required) { | ||
1387 | struct gfs2_alloc *al = gfs2_alloc_get(ndip); | ||
1388 | if (!al) { | ||
1389 | error = -ENOMEM; | ||
1390 | goto out_gunlock; | ||
1391 | } | ||
1392 | |||
1393 | error = gfs2_quota_lock_check(ndip); | ||
1394 | if (error) | ||
1395 | goto out_alloc; | ||
1396 | |||
1397 | al->al_requested = sdp->sd_max_dirres; | ||
1398 | |||
1399 | error = gfs2_inplace_reserve_ri(ndip); | ||
1400 | if (error) | ||
1401 | goto out_gunlock_q; | ||
1402 | |||
1403 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | ||
1404 | gfs2_rg_blocks(al) + | ||
1405 | 4 * RES_DINODE + 4 * RES_LEAF + | ||
1406 | RES_STATFS + RES_QUOTA + 4, 0); | ||
1407 | if (error) | ||
1408 | goto out_ipreserv; | ||
1409 | } else { | ||
1410 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + | ||
1411 | 5 * RES_LEAF + 4, 0); | ||
1412 | if (error) | ||
1413 | goto out_gunlock; | ||
1414 | } | ||
1415 | |||
1416 | /* Remove the target file, if it exists */ | ||
1417 | |||
1418 | if (nip) { | ||
1419 | struct buffer_head *bh; | ||
1420 | error = gfs2_meta_inode_buffer(nip, &bh); | ||
1421 | if (error) | ||
1422 | goto out_end_trans; | ||
1423 | error = gfs2_unlink_inode(ndip, ndentry, bh); | ||
1424 | brelse(bh); | ||
1425 | } | ||
1426 | |||
1427 | if (dir_rename) { | ||
1428 | error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR); | ||
1429 | if (error) | ||
1430 | goto out_end_trans; | ||
1431 | } else { | ||
1432 | struct buffer_head *dibh; | ||
1433 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
1434 | if (error) | ||
1435 | goto out_end_trans; | ||
1436 | ip->i_inode.i_ctime = CURRENT_TIME; | ||
1437 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
1438 | gfs2_dinode_out(ip, dibh->b_data); | ||
1439 | brelse(dibh); | ||
1440 | } | ||
1441 | |||
1442 | error = gfs2_dir_del(odip, odentry); | ||
1443 | if (error) | ||
1444 | goto out_end_trans; | ||
1445 | |||
1446 | error = gfs2_dir_add(ndir, &ndentry->d_name, ip); | ||
1447 | if (error) | ||
1448 | goto out_end_trans; | ||
1449 | |||
1450 | out_end_trans: | ||
1451 | gfs2_trans_end(sdp); | ||
1452 | out_ipreserv: | ||
1453 | if (alloc_required) | ||
1454 | gfs2_inplace_release(ndip); | ||
1455 | out_gunlock_q: | ||
1456 | if (alloc_required) | ||
1457 | gfs2_quota_unlock(ndip); | ||
1458 | out_alloc: | ||
1459 | if (alloc_required) | ||
1460 | gfs2_alloc_put(ndip); | ||
1461 | out_gunlock: | ||
1462 | while (x--) { | ||
1463 | gfs2_glock_dq(ghs + x); | ||
1464 | gfs2_holder_uninit(ghs + x); | ||
1465 | } | ||
1466 | out_gunlock_r: | ||
1467 | if (r_gh.gh_gl) | ||
1468 | gfs2_glock_dq_uninit(&r_gh); | ||
1469 | out: | ||
1470 | gfs2_glock_dq_uninit(&ri_gh); | ||
1471 | return error; | ||
1472 | } | ||
1473 | |||
1474 | /** | ||
1475 | * gfs2_follow_link - Follow a symbolic link | ||
1476 | * @dentry: The dentry of the link | ||
1477 | * @nd: Data that we pass to vfs_follow_link() | ||
1478 | * | ||
1479 | * This can handle symlinks of any size. | ||
1480 | * | ||
1481 | * Returns: 0 on success or error code | ||
1482 | */ | ||
1483 | |||
1484 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
1485 | { | ||
1486 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
1487 | struct gfs2_holder i_gh; | ||
1488 | struct buffer_head *dibh; | ||
1489 | unsigned int size; | ||
1490 | char *buf; | ||
1491 | int error; | ||
1492 | |||
1493 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); | ||
1494 | error = gfs2_glock_nq(&i_gh); | ||
1495 | if (error) { | ||
1496 | gfs2_holder_uninit(&i_gh); | ||
1497 | nd_set_link(nd, ERR_PTR(error)); | ||
1498 | return NULL; | ||
1499 | } | ||
1500 | |||
1501 | size = (unsigned int)i_size_read(&ip->i_inode); | ||
1502 | if (size == 0) { | ||
1503 | gfs2_consist_inode(ip); | ||
1504 | buf = ERR_PTR(-EIO); | ||
1505 | goto out; | ||
1506 | } | ||
1507 | |||
1508 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
1509 | if (error) { | ||
1510 | buf = ERR_PTR(error); | ||
1511 | goto out; | ||
1512 | } | ||
1513 | |||
1514 | buf = kzalloc(size + 1, GFP_NOFS); | ||
1515 | if (!buf) | ||
1516 | buf = ERR_PTR(-ENOMEM); | ||
1517 | else | ||
1518 | memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), size); | ||
1519 | brelse(dibh); | ||
1520 | out: | ||
1521 | gfs2_glock_dq_uninit(&i_gh); | ||
1522 | nd_set_link(nd, buf); | ||
1523 | return NULL; | ||
1524 | } | ||
1525 | |||
1526 | static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | ||
1527 | { | ||
1528 | char *s = nd_get_link(nd); | ||
1529 | if (!IS_ERR(s)) | ||
1530 | kfree(s); | ||
1531 | } | ||
1532 | |||
1533 | /** | ||
1534 | * gfs2_permission - | ||
1535 | * @inode: The inode | ||
1536 | * @mask: The mask to be tested | ||
1537 | * @flags: Indicates whether this is an RCU path walk or not | ||
1538 | * | ||
1539 | * This may be called from the VFS directly, or from within GFS2 with the | ||
1540 | * inode locked, so we look to see if the glock is already locked and only | ||
1541 | * lock the glock if its not already been done. | ||
1542 | * | ||
1543 | * Returns: errno | ||
1544 | */ | ||
1545 | |||
1546 | int gfs2_permission(struct inode *inode, int mask, unsigned int flags) | ||
1547 | { | ||
1548 | struct gfs2_inode *ip; | ||
1549 | struct gfs2_holder i_gh; | ||
1550 | int error; | ||
1551 | int unlock = 0; | ||
1552 | |||
1553 | |||
1554 | ip = GFS2_I(inode); | ||
1555 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | ||
1556 | if (flags & IPERM_FLAG_RCU) | ||
1557 | return -ECHILD; | ||
1558 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | ||
1559 | if (error) | ||
1560 | return error; | ||
1561 | unlock = 1; | ||
1562 | } | ||
1563 | |||
1564 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | ||
1565 | error = -EACCES; | ||
1566 | else | ||
1567 | error = generic_permission(inode, mask, flags, gfs2_check_acl); | ||
1568 | if (unlock) | ||
1569 | gfs2_glock_dq_uninit(&i_gh); | ||
1570 | |||
1571 | return error; | ||
880 | } | 1572 | } |
881 | 1573 | ||
882 | static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | 1574 | static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) |
@@ -902,8 +1594,6 @@ static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | |||
902 | * @ip: | 1594 | * @ip: |
903 | * @attr: | 1595 | * @attr: |
904 | * | 1596 | * |
905 | * Called with a reference on the vnode. | ||
906 | * | ||
907 | * Returns: errno | 1597 | * Returns: errno |
908 | */ | 1598 | */ |
909 | 1599 | ||
@@ -923,60 +1613,280 @@ int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | |||
923 | return error; | 1613 | return error; |
924 | } | 1614 | } |
925 | 1615 | ||
926 | void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | 1616 | static int setattr_chown(struct inode *inode, struct iattr *attr) |
927 | { | 1617 | { |
928 | struct gfs2_dinode *str = buf; | 1618 | struct gfs2_inode *ip = GFS2_I(inode); |
929 | 1619 | struct gfs2_sbd *sdp = GFS2_SB(inode); | |
930 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 1620 | u32 ouid, ogid, nuid, ngid; |
931 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); | 1621 | int error; |
932 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); | 1622 | |
933 | str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); | 1623 | ouid = inode->i_uid; |
934 | str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); | 1624 | ogid = inode->i_gid; |
935 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); | 1625 | nuid = attr->ia_uid; |
936 | str->di_uid = cpu_to_be32(ip->i_inode.i_uid); | 1626 | ngid = attr->ia_gid; |
937 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); | 1627 | |
938 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); | 1628 | if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) |
939 | str->di_size = cpu_to_be64(i_size_read(&ip->i_inode)); | 1629 | ouid = nuid = NO_QUOTA_CHANGE; |
940 | str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); | 1630 | if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) |
941 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | 1631 | ogid = ngid = NO_QUOTA_CHANGE; |
942 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); | 1632 | |
943 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); | 1633 | if (!gfs2_alloc_get(ip)) |
944 | 1634 | return -ENOMEM; | |
945 | str->di_goal_meta = cpu_to_be64(ip->i_goal); | 1635 | |
946 | str->di_goal_data = cpu_to_be64(ip->i_goal); | 1636 | error = gfs2_quota_lock(ip, nuid, ngid); |
947 | str->di_generation = cpu_to_be64(ip->i_generation); | 1637 | if (error) |
948 | 1638 | goto out_alloc; | |
949 | str->di_flags = cpu_to_be32(ip->i_diskflags); | 1639 | |
950 | str->di_height = cpu_to_be16(ip->i_height); | 1640 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { |
951 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && | 1641 | error = gfs2_quota_check(ip, nuid, ngid); |
952 | !(ip->i_diskflags & GFS2_DIF_EXHASH) ? | 1642 | if (error) |
953 | GFS2_FORMAT_DE : 0); | 1643 | goto out_gunlock_q; |
954 | str->di_depth = cpu_to_be16(ip->i_depth); | 1644 | } |
955 | str->di_entries = cpu_to_be32(ip->i_entries); | 1645 | |
956 | 1646 | error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_QUOTA, 0); | |
957 | str->di_eattr = cpu_to_be64(ip->i_eattr); | 1647 | if (error) |
958 | str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); | 1648 | goto out_gunlock_q; |
959 | str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec); | 1649 | |
960 | str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec); | 1650 | error = gfs2_setattr_simple(ip, attr); |
961 | } | 1651 | if (error) |
962 | 1652 | goto out_end_trans; | |
963 | void gfs2_dinode_print(const struct gfs2_inode *ip) | 1653 | |
964 | { | 1654 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { |
965 | printk(KERN_INFO " no_formal_ino = %llu\n", | 1655 | u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); |
966 | (unsigned long long)ip->i_no_formal_ino); | 1656 | gfs2_quota_change(ip, -blocks, ouid, ogid); |
967 | printk(KERN_INFO " no_addr = %llu\n", | 1657 | gfs2_quota_change(ip, blocks, nuid, ngid); |
968 | (unsigned long long)ip->i_no_addr); | 1658 | } |
969 | printk(KERN_INFO " i_size = %llu\n", | 1659 | |
970 | (unsigned long long)i_size_read(&ip->i_inode)); | 1660 | out_end_trans: |
971 | printk(KERN_INFO " blocks = %llu\n", | 1661 | gfs2_trans_end(sdp); |
972 | (unsigned long long)gfs2_get_inode_blocks(&ip->i_inode)); | 1662 | out_gunlock_q: |
973 | printk(KERN_INFO " i_goal = %llu\n", | 1663 | gfs2_quota_unlock(ip); |
974 | (unsigned long long)ip->i_goal); | 1664 | out_alloc: |
975 | printk(KERN_INFO " i_diskflags = 0x%.8X\n", ip->i_diskflags); | 1665 | gfs2_alloc_put(ip); |
976 | printk(KERN_INFO " i_height = %u\n", ip->i_height); | 1666 | return error; |
977 | printk(KERN_INFO " i_depth = %u\n", ip->i_depth); | ||
978 | printk(KERN_INFO " i_entries = %u\n", ip->i_entries); | ||
979 | printk(KERN_INFO " i_eattr = %llu\n", | ||
980 | (unsigned long long)ip->i_eattr); | ||
981 | } | 1667 | } |
982 | 1668 | ||
1669 | /** | ||
1670 | * gfs2_setattr - Change attributes on an inode | ||
1671 | * @dentry: The dentry which is changing | ||
1672 | * @attr: The structure describing the change | ||
1673 | * | ||
1674 | * The VFS layer wants to change one or more of an inodes attributes. Write | ||
1675 | * that change out to disk. | ||
1676 | * | ||
1677 | * Returns: errno | ||
1678 | */ | ||
1679 | |||
1680 | static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | ||
1681 | { | ||
1682 | struct inode *inode = dentry->d_inode; | ||
1683 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1684 | struct gfs2_holder i_gh; | ||
1685 | int error; | ||
1686 | |||
1687 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); | ||
1688 | if (error) | ||
1689 | return error; | ||
1690 | |||
1691 | error = -EPERM; | ||
1692 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
1693 | goto out; | ||
1694 | |||
1695 | error = inode_change_ok(inode, attr); | ||
1696 | if (error) | ||
1697 | goto out; | ||
1698 | |||
1699 | if (attr->ia_valid & ATTR_SIZE) | ||
1700 | error = gfs2_setattr_size(inode, attr->ia_size); | ||
1701 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) | ||
1702 | error = setattr_chown(inode, attr); | ||
1703 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) | ||
1704 | error = gfs2_acl_chmod(ip, attr); | ||
1705 | else | ||
1706 | error = gfs2_setattr_simple(ip, attr); | ||
1707 | |||
1708 | out: | ||
1709 | gfs2_glock_dq_uninit(&i_gh); | ||
1710 | if (!error) | ||
1711 | mark_inode_dirty(inode); | ||
1712 | return error; | ||
1713 | } | ||
1714 | |||
1715 | /** | ||
1716 | * gfs2_getattr - Read out an inode's attributes | ||
1717 | * @mnt: The vfsmount the inode is being accessed from | ||
1718 | * @dentry: The dentry to stat | ||
1719 | * @stat: The inode's stats | ||
1720 | * | ||
1721 | * This may be called from the VFS directly, or from within GFS2 with the | ||
1722 | * inode locked, so we look to see if the glock is already locked and only | ||
1723 | * lock the glock if its not already been done. Note that its the NFS | ||
1724 | * readdirplus operation which causes this to be called (from filldir) | ||
1725 | * with the glock already held. | ||
1726 | * | ||
1727 | * Returns: errno | ||
1728 | */ | ||
1729 | |||
1730 | static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
1731 | struct kstat *stat) | ||
1732 | { | ||
1733 | struct inode *inode = dentry->d_inode; | ||
1734 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1735 | struct gfs2_holder gh; | ||
1736 | int error; | ||
1737 | int unlock = 0; | ||
1738 | |||
1739 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | ||
1740 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1741 | if (error) | ||
1742 | return error; | ||
1743 | unlock = 1; | ||
1744 | } | ||
1745 | |||
1746 | generic_fillattr(inode, stat); | ||
1747 | if (unlock) | ||
1748 | gfs2_glock_dq_uninit(&gh); | ||
1749 | |||
1750 | return 0; | ||
1751 | } | ||
1752 | |||
1753 | static int gfs2_setxattr(struct dentry *dentry, const char *name, | ||
1754 | const void *data, size_t size, int flags) | ||
1755 | { | ||
1756 | struct inode *inode = dentry->d_inode; | ||
1757 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1758 | struct gfs2_holder gh; | ||
1759 | int ret; | ||
1760 | |||
1761 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
1762 | ret = gfs2_glock_nq(&gh); | ||
1763 | if (ret == 0) { | ||
1764 | ret = generic_setxattr(dentry, name, data, size, flags); | ||
1765 | gfs2_glock_dq(&gh); | ||
1766 | } | ||
1767 | gfs2_holder_uninit(&gh); | ||
1768 | return ret; | ||
1769 | } | ||
1770 | |||
1771 | static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name, | ||
1772 | void *data, size_t size) | ||
1773 | { | ||
1774 | struct inode *inode = dentry->d_inode; | ||
1775 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1776 | struct gfs2_holder gh; | ||
1777 | int ret; | ||
1778 | |||
1779 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1780 | ret = gfs2_glock_nq(&gh); | ||
1781 | if (ret == 0) { | ||
1782 | ret = generic_getxattr(dentry, name, data, size); | ||
1783 | gfs2_glock_dq(&gh); | ||
1784 | } | ||
1785 | gfs2_holder_uninit(&gh); | ||
1786 | return ret; | ||
1787 | } | ||
1788 | |||
1789 | static int gfs2_removexattr(struct dentry *dentry, const char *name) | ||
1790 | { | ||
1791 | struct inode *inode = dentry->d_inode; | ||
1792 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1793 | struct gfs2_holder gh; | ||
1794 | int ret; | ||
1795 | |||
1796 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
1797 | ret = gfs2_glock_nq(&gh); | ||
1798 | if (ret == 0) { | ||
1799 | ret = generic_removexattr(dentry, name); | ||
1800 | gfs2_glock_dq(&gh); | ||
1801 | } | ||
1802 | gfs2_holder_uninit(&gh); | ||
1803 | return ret; | ||
1804 | } | ||
1805 | |||
1806 | static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
1807 | u64 start, u64 len) | ||
1808 | { | ||
1809 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1810 | struct gfs2_holder gh; | ||
1811 | int ret; | ||
1812 | |||
1813 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | ||
1814 | if (ret) | ||
1815 | return ret; | ||
1816 | |||
1817 | mutex_lock(&inode->i_mutex); | ||
1818 | |||
1819 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
1820 | if (ret) | ||
1821 | goto out; | ||
1822 | |||
1823 | if (gfs2_is_stuffed(ip)) { | ||
1824 | u64 phys = ip->i_no_addr << inode->i_blkbits; | ||
1825 | u64 size = i_size_read(inode); | ||
1826 | u32 flags = FIEMAP_EXTENT_LAST|FIEMAP_EXTENT_NOT_ALIGNED| | ||
1827 | FIEMAP_EXTENT_DATA_INLINE; | ||
1828 | phys += sizeof(struct gfs2_dinode); | ||
1829 | phys += start; | ||
1830 | if (start + len > size) | ||
1831 | len = size - start; | ||
1832 | if (start < size) | ||
1833 | ret = fiemap_fill_next_extent(fieinfo, start, phys, | ||
1834 | len, flags); | ||
1835 | if (ret == 1) | ||
1836 | ret = 0; | ||
1837 | } else { | ||
1838 | ret = __generic_block_fiemap(inode, fieinfo, start, len, | ||
1839 | gfs2_block_map); | ||
1840 | } | ||
1841 | |||
1842 | gfs2_glock_dq_uninit(&gh); | ||
1843 | out: | ||
1844 | mutex_unlock(&inode->i_mutex); | ||
1845 | return ret; | ||
1846 | } | ||
1847 | |||
1848 | const struct inode_operations gfs2_file_iops = { | ||
1849 | .permission = gfs2_permission, | ||
1850 | .setattr = gfs2_setattr, | ||
1851 | .getattr = gfs2_getattr, | ||
1852 | .setxattr = gfs2_setxattr, | ||
1853 | .getxattr = gfs2_getxattr, | ||
1854 | .listxattr = gfs2_listxattr, | ||
1855 | .removexattr = gfs2_removexattr, | ||
1856 | .fiemap = gfs2_fiemap, | ||
1857 | }; | ||
1858 | |||
1859 | const struct inode_operations gfs2_dir_iops = { | ||
1860 | .create = gfs2_create, | ||
1861 | .lookup = gfs2_lookup, | ||
1862 | .link = gfs2_link, | ||
1863 | .unlink = gfs2_unlink, | ||
1864 | .symlink = gfs2_symlink, | ||
1865 | .mkdir = gfs2_mkdir, | ||
1866 | .rmdir = gfs2_unlink, | ||
1867 | .mknod = gfs2_mknod, | ||
1868 | .rename = gfs2_rename, | ||
1869 | .permission = gfs2_permission, | ||
1870 | .setattr = gfs2_setattr, | ||
1871 | .getattr = gfs2_getattr, | ||
1872 | .setxattr = gfs2_setxattr, | ||
1873 | .getxattr = gfs2_getxattr, | ||
1874 | .listxattr = gfs2_listxattr, | ||
1875 | .removexattr = gfs2_removexattr, | ||
1876 | .fiemap = gfs2_fiemap, | ||
1877 | }; | ||
1878 | |||
1879 | const struct inode_operations gfs2_symlink_iops = { | ||
1880 | .readlink = generic_readlink, | ||
1881 | .follow_link = gfs2_follow_link, | ||
1882 | .put_link = gfs2_put_link, | ||
1883 | .permission = gfs2_permission, | ||
1884 | .setattr = gfs2_setattr, | ||
1885 | .getattr = gfs2_getattr, | ||
1886 | .setxattr = gfs2_setxattr, | ||
1887 | .getxattr = gfs2_getxattr, | ||
1888 | .listxattr = gfs2_listxattr, | ||
1889 | .removexattr = gfs2_removexattr, | ||
1890 | .fiemap = gfs2_fiemap, | ||
1891 | }; | ||
1892 | |||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 3e00a66e7cbd..31606076f701 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
@@ -97,26 +97,21 @@ 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); |
104 | extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); | 105 | extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int nonblock); |
105 | 106 | ||
106 | extern int gfs2_inode_refresh(struct gfs2_inode *ip); | 107 | extern int gfs2_inode_refresh(struct gfs2_inode *ip); |
107 | 108 | ||
108 | extern int gfs2_dinode_dealloc(struct gfs2_inode *inode); | ||
109 | extern int gfs2_change_nlink(struct gfs2_inode *ip, int diff); | ||
110 | extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | 109 | extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, |
111 | int is_root); | 110 | int is_root); |
112 | extern struct inode *gfs2_createi(struct gfs2_holder *ghs, | ||
113 | const struct qstr *name, | ||
114 | unsigned int mode, dev_t dev); | ||
115 | extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); | 111 | extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); |
116 | extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); | 112 | extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); |
117 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); | 113 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); |
118 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | 114 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); |
119 | extern void gfs2_dinode_print(const struct gfs2_inode *ip); | ||
120 | 115 | ||
121 | extern const struct inode_operations gfs2_file_iops; | 116 | extern const struct inode_operations gfs2_file_iops; |
122 | extern const struct inode_operations gfs2_dir_iops; | 117 | extern const struct inode_operations gfs2_dir_iops; |
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 5b102c1887fd..cec26c00b50d 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kthread.h> | 18 | #include <linux/kthread.h> |
19 | #include <linux/freezer.h> | 19 | #include <linux/freezer.h> |
20 | #include <linux/bio.h> | 20 | #include <linux/bio.h> |
21 | #include <linux/writeback.h> | ||
21 | 22 | ||
22 | #include "gfs2.h" | 23 | #include "gfs2.h" |
23 | #include "incore.h" | 24 | #include "incore.h" |
@@ -83,55 +84,97 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd) | |||
83 | /** | 84 | /** |
84 | * gfs2_ail1_start_one - Start I/O on a part of the AIL | 85 | * gfs2_ail1_start_one - Start I/O on a part of the AIL |
85 | * @sdp: the filesystem | 86 | * @sdp: the filesystem |
86 | * @tr: the part of the AIL | 87 | * @wbc: The writeback control structure |
88 | * @ai: The ail structure | ||
87 | * | 89 | * |
88 | */ | 90 | */ |
89 | 91 | ||
90 | static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 92 | static int gfs2_ail1_start_one(struct gfs2_sbd *sdp, |
93 | struct writeback_control *wbc, | ||
94 | struct gfs2_ail *ai) | ||
91 | __releases(&sdp->sd_ail_lock) | 95 | __releases(&sdp->sd_ail_lock) |
92 | __acquires(&sdp->sd_ail_lock) | 96 | __acquires(&sdp->sd_ail_lock) |
93 | { | 97 | { |
98 | struct gfs2_glock *gl = NULL; | ||
99 | struct address_space *mapping; | ||
94 | struct gfs2_bufdata *bd, *s; | 100 | struct gfs2_bufdata *bd, *s; |
95 | struct buffer_head *bh; | 101 | struct buffer_head *bh; |
96 | int retry; | ||
97 | 102 | ||
98 | do { | 103 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, bd_ail_st_list) { |
99 | retry = 0; | 104 | bh = bd->bd_bh; |
100 | 105 | ||
101 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, | 106 | gfs2_assert(sdp, bd->bd_ail == ai); |
102 | bd_ail_st_list) { | ||
103 | bh = bd->bd_bh; | ||
104 | 107 | ||
105 | gfs2_assert(sdp, bd->bd_ail == ai); | 108 | if (!buffer_busy(bh)) { |
109 | if (!buffer_uptodate(bh)) | ||
110 | gfs2_io_error_bh(sdp, bh); | ||
111 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | ||
112 | continue; | ||
113 | } | ||
106 | 114 | ||
107 | if (!buffer_busy(bh)) { | 115 | if (!buffer_dirty(bh)) |
108 | if (!buffer_uptodate(bh)) | 116 | continue; |
109 | gfs2_io_error_bh(sdp, bh); | 117 | if (gl == bd->bd_gl) |
110 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | 118 | continue; |
111 | continue; | 119 | gl = bd->bd_gl; |
112 | } | 120 | list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); |
121 | mapping = bh->b_page->mapping; | ||
122 | if (!mapping) | ||
123 | continue; | ||
124 | spin_unlock(&sdp->sd_ail_lock); | ||
125 | generic_writepages(mapping, wbc); | ||
126 | spin_lock(&sdp->sd_ail_lock); | ||
127 | if (wbc->nr_to_write <= 0) | ||
128 | break; | ||
129 | return 1; | ||
130 | } | ||
113 | 131 | ||
114 | if (!buffer_dirty(bh)) | 132 | return 0; |
115 | continue; | 133 | } |
116 | 134 | ||
117 | list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list); | ||
118 | 135 | ||
119 | get_bh(bh); | 136 | /** |
120 | spin_unlock(&sdp->sd_ail_lock); | 137 | * gfs2_ail1_flush - start writeback of some ail1 entries |
121 | lock_buffer(bh); | 138 | * @sdp: The super block |
122 | if (test_clear_buffer_dirty(bh)) { | 139 | * @wbc: The writeback control structure |
123 | bh->b_end_io = end_buffer_write_sync; | 140 | * |
124 | submit_bh(WRITE_SYNC, bh); | 141 | * Writes back some ail1 entries, according to the limits in the |
125 | } else { | 142 | * writeback control structure |
126 | unlock_buffer(bh); | 143 | */ |
127 | brelse(bh); | 144 | |
128 | } | 145 | void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc) |
129 | spin_lock(&sdp->sd_ail_lock); | 146 | { |
130 | 147 | struct list_head *head = &sdp->sd_ail1_list; | |
131 | retry = 1; | 148 | struct gfs2_ail *ai; |
149 | |||
150 | trace_gfs2_ail_flush(sdp, wbc, 1); | ||
151 | spin_lock(&sdp->sd_ail_lock); | ||
152 | restart: | ||
153 | list_for_each_entry_reverse(ai, head, ai_list) { | ||
154 | if (wbc->nr_to_write <= 0) | ||
132 | break; | 155 | break; |
133 | } | 156 | if (gfs2_ail1_start_one(sdp, wbc, ai)) |
134 | } while (retry); | 157 | goto restart; |
158 | } | ||
159 | spin_unlock(&sdp->sd_ail_lock); | ||
160 | trace_gfs2_ail_flush(sdp, wbc, 0); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * gfs2_ail1_start - start writeback of all ail1 entries | ||
165 | * @sdp: The superblock | ||
166 | */ | ||
167 | |||
168 | static void gfs2_ail1_start(struct gfs2_sbd *sdp) | ||
169 | { | ||
170 | struct writeback_control wbc = { | ||
171 | .sync_mode = WB_SYNC_NONE, | ||
172 | .nr_to_write = LONG_MAX, | ||
173 | .range_start = 0, | ||
174 | .range_end = LLONG_MAX, | ||
175 | }; | ||
176 | |||
177 | return gfs2_ail1_flush(sdp, &wbc); | ||
135 | } | 178 | } |
136 | 179 | ||
137 | /** | 180 | /** |
@@ -141,7 +184,7 @@ __acquires(&sdp->sd_ail_lock) | |||
141 | * | 184 | * |
142 | */ | 185 | */ |
143 | 186 | ||
144 | static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int flags) | 187 | static void gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai) |
145 | { | 188 | { |
146 | struct gfs2_bufdata *bd, *s; | 189 | struct gfs2_bufdata *bd, *s; |
147 | struct buffer_head *bh; | 190 | struct buffer_head *bh; |
@@ -149,71 +192,37 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl | |||
149 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, | 192 | list_for_each_entry_safe_reverse(bd, s, &ai->ai_ail1_list, |
150 | bd_ail_st_list) { | 193 | bd_ail_st_list) { |
151 | bh = bd->bd_bh; | 194 | bh = bd->bd_bh; |
152 | |||
153 | gfs2_assert(sdp, bd->bd_ail == ai); | 195 | gfs2_assert(sdp, bd->bd_ail == ai); |
154 | 196 | if (buffer_busy(bh)) | |
155 | if (buffer_busy(bh)) { | 197 | continue; |
156 | if (flags & DIO_ALL) | ||
157 | continue; | ||
158 | else | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | if (!buffer_uptodate(bh)) | 198 | if (!buffer_uptodate(bh)) |
163 | gfs2_io_error_bh(sdp, bh); | 199 | gfs2_io_error_bh(sdp, bh); |
164 | |||
165 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); | 200 | list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list); |
166 | } | 201 | } |
167 | 202 | ||
168 | return list_empty(&ai->ai_ail1_list); | ||
169 | } | 203 | } |
170 | 204 | ||
171 | static void gfs2_ail1_start(struct gfs2_sbd *sdp) | 205 | /** |
172 | { | 206 | * gfs2_ail1_empty - Try to empty the ail1 lists |
173 | struct list_head *head; | 207 | * @sdp: The superblock |
174 | u64 sync_gen; | 208 | * |
175 | struct gfs2_ail *ai; | 209 | * Tries to empty the ail1 lists, starting with the oldest first |
176 | int done = 0; | 210 | */ |
177 | |||
178 | spin_lock(&sdp->sd_ail_lock); | ||
179 | head = &sdp->sd_ail1_list; | ||
180 | if (list_empty(head)) { | ||
181 | spin_unlock(&sdp->sd_ail_lock); | ||
182 | return; | ||
183 | } | ||
184 | sync_gen = sdp->sd_ail_sync_gen++; | ||
185 | |||
186 | while(!done) { | ||
187 | done = 1; | ||
188 | list_for_each_entry_reverse(ai, head, ai_list) { | ||
189 | if (ai->ai_sync_gen >= sync_gen) | ||
190 | continue; | ||
191 | ai->ai_sync_gen = sync_gen; | ||
192 | gfs2_ail1_start_one(sdp, ai); /* This may drop ail lock */ | ||
193 | done = 0; | ||
194 | break; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | spin_unlock(&sdp->sd_ail_lock); | ||
199 | } | ||
200 | 211 | ||
201 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags) | 212 | static int gfs2_ail1_empty(struct gfs2_sbd *sdp) |
202 | { | 213 | { |
203 | struct gfs2_ail *ai, *s; | 214 | struct gfs2_ail *ai, *s; |
204 | int ret; | 215 | int ret; |
205 | 216 | ||
206 | spin_lock(&sdp->sd_ail_lock); | 217 | spin_lock(&sdp->sd_ail_lock); |
207 | |||
208 | list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { | 218 | list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) { |
209 | if (gfs2_ail1_empty_one(sdp, ai, flags)) | 219 | gfs2_ail1_empty_one(sdp, ai); |
220 | if (list_empty(&ai->ai_ail1_list)) | ||
210 | list_move(&ai->ai_list, &sdp->sd_ail2_list); | 221 | list_move(&ai->ai_list, &sdp->sd_ail2_list); |
211 | else if (!(flags & DIO_ALL)) | 222 | else |
212 | break; | 223 | break; |
213 | } | 224 | } |
214 | |||
215 | ret = list_empty(&sdp->sd_ail1_list); | 225 | ret = list_empty(&sdp->sd_ail1_list); |
216 | |||
217 | spin_unlock(&sdp->sd_ail_lock); | 226 | spin_unlock(&sdp->sd_ail_lock); |
218 | 227 | ||
219 | return ret; | 228 | return ret; |
@@ -574,7 +583,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull) | |||
574 | set_buffer_uptodate(bh); | 583 | set_buffer_uptodate(bh); |
575 | clear_buffer_dirty(bh); | 584 | clear_buffer_dirty(bh); |
576 | 585 | ||
577 | gfs2_ail1_empty(sdp, 0); | 586 | gfs2_ail1_empty(sdp); |
578 | tail = current_tail(sdp); | 587 | tail = current_tail(sdp); |
579 | 588 | ||
580 | lh = (struct gfs2_log_header *)bh->b_data; | 589 | lh = (struct gfs2_log_header *)bh->b_data; |
@@ -869,7 +878,7 @@ void gfs2_meta_syncfs(struct gfs2_sbd *sdp) | |||
869 | gfs2_log_flush(sdp, NULL); | 878 | gfs2_log_flush(sdp, NULL); |
870 | for (;;) { | 879 | for (;;) { |
871 | gfs2_ail1_start(sdp); | 880 | gfs2_ail1_start(sdp); |
872 | if (gfs2_ail1_empty(sdp, DIO_ALL)) | 881 | if (gfs2_ail1_empty(sdp)) |
873 | break; | 882 | break; |
874 | msleep(10); | 883 | msleep(10); |
875 | } | 884 | } |
@@ -905,17 +914,15 @@ int gfs2_logd(void *data) | |||
905 | 914 | ||
906 | preflush = atomic_read(&sdp->sd_log_pinned); | 915 | preflush = atomic_read(&sdp->sd_log_pinned); |
907 | if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { | 916 | if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { |
908 | gfs2_ail1_empty(sdp, DIO_ALL); | 917 | gfs2_ail1_empty(sdp); |
909 | gfs2_log_flush(sdp, NULL); | 918 | gfs2_log_flush(sdp, NULL); |
910 | gfs2_ail1_empty(sdp, DIO_ALL); | ||
911 | } | 919 | } |
912 | 920 | ||
913 | if (gfs2_ail_flush_reqd(sdp)) { | 921 | if (gfs2_ail_flush_reqd(sdp)) { |
914 | gfs2_ail1_start(sdp); | 922 | gfs2_ail1_start(sdp); |
915 | io_schedule(); | 923 | io_schedule(); |
916 | gfs2_ail1_empty(sdp, 0); | 924 | gfs2_ail1_empty(sdp); |
917 | gfs2_log_flush(sdp, NULL); | 925 | gfs2_log_flush(sdp, NULL); |
918 | gfs2_ail1_empty(sdp, DIO_ALL); | ||
919 | } | 926 | } |
920 | 927 | ||
921 | wake_up(&sdp->sd_log_waitq); | 928 | wake_up(&sdp->sd_log_waitq); |
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h index 0d007f920234..ab0621698b73 100644 --- a/fs/gfs2/log.h +++ b/fs/gfs2/log.h | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/list.h> | 13 | #include <linux/list.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/writeback.h> | ||
15 | #include "incore.h" | 16 | #include "incore.h" |
16 | 17 | ||
17 | /** | 18 | /** |
@@ -59,6 +60,7 @@ extern struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp, | |||
59 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); | 60 | extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl); |
60 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); | 61 | extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans); |
61 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); | 62 | extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd); |
63 | extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc); | ||
62 | 64 | ||
63 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); | 65 | extern void gfs2_log_shutdown(struct gfs2_sbd *sdp); |
64 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); | 66 | extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 51d27f00ebb4..05bbb124699f 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -40,7 +40,7 @@ static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | |||
40 | { | 40 | { |
41 | struct gfs2_bufdata *bd; | 41 | struct gfs2_bufdata *bd; |
42 | 42 | ||
43 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | 43 | BUG_ON(!current->journal_info); |
44 | 44 | ||
45 | clear_buffer_dirty(bh); | 45 | clear_buffer_dirty(bh); |
46 | if (test_set_buffer_pinned(bh)) | 46 | if (test_set_buffer_pinned(bh)) |
@@ -65,6 +65,7 @@ static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | |||
65 | * @sdp: the filesystem the buffer belongs to | 65 | * @sdp: the filesystem the buffer belongs to |
66 | * @bh: The buffer to unpin | 66 | * @bh: The buffer to unpin |
67 | * @ai: | 67 | * @ai: |
68 | * @flags: The inode dirty flags | ||
68 | * | 69 | * |
69 | */ | 70 | */ |
70 | 71 | ||
@@ -73,10 +74,8 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | |||
73 | { | 74 | { |
74 | struct gfs2_bufdata *bd = bh->b_private; | 75 | struct gfs2_bufdata *bd = bh->b_private; |
75 | 76 | ||
76 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | 77 | BUG_ON(!buffer_uptodate(bh)); |
77 | 78 | BUG_ON(!buffer_pinned(bh)); | |
78 | if (!buffer_pinned(bh)) | ||
79 | gfs2_assert_withdraw(sdp, 0); | ||
80 | 79 | ||
81 | lock_buffer(bh); | 80 | lock_buffer(bh); |
82 | mark_buffer_dirty(bh); | 81 | mark_buffer_dirty(bh); |
@@ -95,8 +94,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | |||
95 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | 94 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); |
96 | spin_unlock(&sdp->sd_ail_lock); | 95 | spin_unlock(&sdp->sd_ail_lock); |
97 | 96 | ||
98 | if (test_and_clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags)) | 97 | clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); |
99 | gfs2_glock_schedule_for_reclaim(bd->bd_gl); | ||
100 | trace_gfs2_pin(bd, 0); | 98 | trace_gfs2_pin(bd, 0); |
101 | unlock_buffer(bh); | 99 | unlock_buffer(bh); |
102 | atomic_dec(&sdp->sd_log_pinned); | 100 | atomic_dec(&sdp->sd_log_pinned); |
@@ -322,12 +320,16 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) | |||
322 | 320 | ||
323 | static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | 321 | static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) |
324 | { | 322 | { |
323 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); | ||
324 | struct gfs2_glock *gl = bd->bd_gl; | ||
325 | struct gfs2_trans *tr; | 325 | struct gfs2_trans *tr; |
326 | 326 | ||
327 | tr = current->journal_info; | 327 | tr = current->journal_info; |
328 | tr->tr_touched = 1; | 328 | tr->tr_touched = 1; |
329 | tr->tr_num_revoke++; | 329 | tr->tr_num_revoke++; |
330 | sdp->sd_log_num_revoke++; | 330 | sdp->sd_log_num_revoke++; |
331 | atomic_inc(&gl->gl_revokes); | ||
332 | set_bit(GLF_LFLUSH, &gl->gl_flags); | ||
331 | list_add(&le->le_list, &sdp->sd_log_le_revoke); | 333 | list_add(&le->le_list, &sdp->sd_log_le_revoke); |
332 | } | 334 | } |
333 | 335 | ||
@@ -350,9 +352,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
350 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); | 352 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); |
351 | offset = sizeof(struct gfs2_log_descriptor); | 353 | offset = sizeof(struct gfs2_log_descriptor); |
352 | 354 | ||
353 | while (!list_empty(head)) { | 355 | list_for_each_entry(bd, head, bd_le.le_list) { |
354 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); | ||
355 | list_del_init(&bd->bd_le.le_list); | ||
356 | sdp->sd_log_num_revoke--; | 356 | sdp->sd_log_num_revoke--; |
357 | 357 | ||
358 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { | 358 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { |
@@ -367,8 +367,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
367 | } | 367 | } |
368 | 368 | ||
369 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno); | 369 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno); |
370 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
371 | |||
372 | offset += sizeof(u64); | 370 | offset += sizeof(u64); |
373 | } | 371 | } |
374 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 372 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
@@ -376,6 +374,22 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
376 | submit_bh(WRITE_SYNC, bh); | 374 | submit_bh(WRITE_SYNC, bh); |
377 | } | 375 | } |
378 | 376 | ||
377 | static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | ||
378 | { | ||
379 | struct list_head *head = &sdp->sd_log_le_revoke; | ||
380 | struct gfs2_bufdata *bd; | ||
381 | struct gfs2_glock *gl; | ||
382 | |||
383 | while (!list_empty(head)) { | ||
384 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); | ||
385 | list_del_init(&bd->bd_le.le_list); | ||
386 | gl = bd->bd_gl; | ||
387 | atomic_dec(&gl->gl_revokes); | ||
388 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
389 | kmem_cache_free(gfs2_bufdata_cachep, bd); | ||
390 | } | ||
391 | } | ||
392 | |||
379 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, | 393 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |
380 | struct gfs2_log_header_host *head, int pass) | 394 | struct gfs2_log_header_host *head, int pass) |
381 | { | 395 | { |
@@ -749,6 +763,7 @@ const struct gfs2_log_operations gfs2_buf_lops = { | |||
749 | const struct gfs2_log_operations gfs2_revoke_lops = { | 763 | const struct gfs2_log_operations gfs2_revoke_lops = { |
750 | .lo_add = revoke_lo_add, | 764 | .lo_add = revoke_lo_add, |
751 | .lo_before_commit = revoke_lo_before_commit, | 765 | .lo_before_commit = revoke_lo_before_commit, |
766 | .lo_after_commit = revoke_lo_after_commit, | ||
752 | .lo_before_scan = revoke_lo_before_scan, | 767 | .lo_before_scan = revoke_lo_before_scan, |
753 | .lo_scan_elements = revoke_lo_scan_elements, | 768 | .lo_scan_elements = revoke_lo_scan_elements, |
754 | .lo_after_scan = revoke_lo_after_scan, | 769 | .lo_after_scan = revoke_lo_after_scan, |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 888a5f5a1a58..cfa327d33194 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -53,6 +53,7 @@ static void gfs2_init_glock_once(void *foo) | |||
53 | INIT_LIST_HEAD(&gl->gl_lru); | 53 | INIT_LIST_HEAD(&gl->gl_lru); |
54 | INIT_LIST_HEAD(&gl->gl_ail_list); | 54 | INIT_LIST_HEAD(&gl->gl_ail_list); |
55 | atomic_set(&gl->gl_ail_count, 0); | 55 | atomic_set(&gl->gl_ail_count, 0); |
56 | atomic_set(&gl->gl_revokes, 0); | ||
56 | } | 57 | } |
57 | 58 | ||
58 | static void gfs2_init_gl_aspace_once(void *foo) | 59 | static void gfs2_init_gl_aspace_once(void *foo) |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 675349b5a133..747238cd9f96 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "rgrp.h" | 31 | #include "rgrp.h" |
32 | #include "trans.h" | 32 | #include "trans.h" |
33 | #include "util.h" | 33 | #include "util.h" |
34 | #include "trace_gfs2.h" | ||
34 | 35 | ||
35 | static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc) | 36 | static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc) |
36 | { | 37 | { |
@@ -310,6 +311,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int | |||
310 | struct gfs2_bufdata *bd = bh->b_private; | 311 | struct gfs2_bufdata *bd = bh->b_private; |
311 | 312 | ||
312 | if (test_clear_buffer_pinned(bh)) { | 313 | if (test_clear_buffer_pinned(bh)) { |
314 | trace_gfs2_pin(bd, 0); | ||
313 | atomic_dec(&sdp->sd_log_pinned); | 315 | atomic_dec(&sdp->sd_log_pinned); |
314 | list_del_init(&bd->bd_le.le_list); | 316 | list_del_init(&bd->bd_le.le_list); |
315 | if (meta) { | 317 | if (meta) { |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index 6a1d9ba16411..22c526593131 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -77,8 +77,6 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); | |||
77 | 77 | ||
78 | #define buffer_busy(bh) \ | 78 | #define buffer_busy(bh) \ |
79 | ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned))) | 79 | ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock) | (1ul << BH_Pinned))) |
80 | #define buffer_in_io(bh) \ | ||
81 | ((bh)->b_state & ((1ul << BH_Dirty) | (1ul << BH_Lock))) | ||
82 | 80 | ||
83 | #endif /* __DIO_DOT_H__ */ | 81 | #endif /* __DIO_DOT_H__ */ |
84 | 82 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 42ef24355afb..8ac9ae189b53 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -126,8 +126,10 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
126 | * changed. | 126 | * changed. |
127 | */ | 127 | */ |
128 | 128 | ||
129 | static int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent) | 129 | static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) |
130 | { | 130 | { |
131 | struct gfs2_sb_host *sb = &sdp->sd_sb; | ||
132 | |||
131 | if (sb->sb_magic != GFS2_MAGIC || | 133 | if (sb->sb_magic != GFS2_MAGIC || |
132 | sb->sb_type != GFS2_METATYPE_SB) { | 134 | sb->sb_type != GFS2_METATYPE_SB) { |
133 | if (!silent) | 135 | if (!silent) |
@@ -157,8 +159,10 @@ static void end_bio_io_page(struct bio *bio, int error) | |||
157 | unlock_page(page); | 159 | unlock_page(page); |
158 | } | 160 | } |
159 | 161 | ||
160 | static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) | 162 | static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf) |
161 | { | 163 | { |
164 | struct gfs2_sb_host *sb = &sdp->sd_sb; | ||
165 | struct super_block *s = sdp->sd_vfs; | ||
162 | const struct gfs2_sb *str = buf; | 166 | const struct gfs2_sb *str = buf; |
163 | 167 | ||
164 | sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); | 168 | sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); |
@@ -175,7 +179,7 @@ static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) | |||
175 | 179 | ||
176 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); | 180 | memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN); |
177 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); | 181 | memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN); |
178 | memcpy(sb->sb_uuid, str->sb_uuid, 16); | 182 | memcpy(s->s_uuid, str->sb_uuid, 16); |
179 | } | 183 | } |
180 | 184 | ||
181 | /** | 185 | /** |
@@ -197,7 +201,7 @@ static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) | |||
197 | * Returns: 0 on success or error | 201 | * Returns: 0 on success or error |
198 | */ | 202 | */ |
199 | 203 | ||
200 | static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) | 204 | static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) |
201 | { | 205 | { |
202 | struct super_block *sb = sdp->sd_vfs; | 206 | struct super_block *sb = sdp->sd_vfs; |
203 | struct gfs2_sb *p; | 207 | struct gfs2_sb *p; |
@@ -227,10 +231,10 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) | |||
227 | return -EIO; | 231 | return -EIO; |
228 | } | 232 | } |
229 | p = kmap(page); | 233 | p = kmap(page); |
230 | gfs2_sb_in(&sdp->sd_sb, p); | 234 | gfs2_sb_in(sdp, p); |
231 | kunmap(page); | 235 | kunmap(page); |
232 | __free_page(page); | 236 | __free_page(page); |
233 | return 0; | 237 | return gfs2_check_sb(sdp, silent); |
234 | } | 238 | } |
235 | 239 | ||
236 | /** | 240 | /** |
@@ -247,17 +251,13 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent) | |||
247 | unsigned int x; | 251 | unsigned int x; |
248 | int error; | 252 | int error; |
249 | 253 | ||
250 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); | 254 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift, silent); |
251 | if (error) { | 255 | if (error) { |
252 | if (!silent) | 256 | if (!silent) |
253 | fs_err(sdp, "can't read superblock\n"); | 257 | fs_err(sdp, "can't read superblock\n"); |
254 | return error; | 258 | return error; |
255 | } | 259 | } |
256 | 260 | ||
257 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); | ||
258 | if (error) | ||
259 | return error; | ||
260 | |||
261 | sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - | 261 | sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - |
262 | GFS2_BASIC_BLOCK_SHIFT; | 262 | GFS2_BASIC_BLOCK_SHIFT; |
263 | sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; | 263 | sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; |
@@ -340,14 +340,10 @@ static int init_names(struct gfs2_sbd *sdp, int silent) | |||
340 | /* Try to autodetect */ | 340 | /* Try to autodetect */ |
341 | 341 | ||
342 | if (!proto[0] || !table[0]) { | 342 | if (!proto[0] || !table[0]) { |
343 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); | 343 | error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift, silent); |
344 | if (error) | 344 | if (error) |
345 | return error; | 345 | return error; |
346 | 346 | ||
347 | error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); | ||
348 | if (error) | ||
349 | goto out; | ||
350 | |||
351 | if (!proto[0]) | 347 | if (!proto[0]) |
352 | proto = sdp->sd_sb.sb_lockproto; | 348 | proto = sdp->sd_sb.sb_lockproto; |
353 | if (!table[0]) | 349 | if (!table[0]) |
@@ -364,7 +360,6 @@ static int init_names(struct gfs2_sbd *sdp, int silent) | |||
364 | while ((table = strchr(table, '/'))) | 360 | while ((table = strchr(table, '/'))) |
365 | *table = '_'; | 361 | *table = '_'; |
366 | 362 | ||
367 | out: | ||
368 | return error; | 363 | return error; |
369 | } | 364 | } |
370 | 365 | ||
@@ -430,7 +425,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr, | |||
430 | struct dentry *dentry; | 425 | struct dentry *dentry; |
431 | struct inode *inode; | 426 | struct inode *inode; |
432 | 427 | ||
433 | inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); | 428 | inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0); |
434 | if (IS_ERR(inode)) { | 429 | if (IS_ERR(inode)) { |
435 | fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); | 430 | fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode)); |
436 | return PTR_ERR(inode); | 431 | return PTR_ERR(inode); |
@@ -1119,8 +1114,7 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent | |||
1119 | if (sdp->sd_args.ar_statfs_quantum) { | 1114 | if (sdp->sd_args.ar_statfs_quantum) { |
1120 | sdp->sd_tune.gt_statfs_slow = 0; | 1115 | sdp->sd_tune.gt_statfs_slow = 0; |
1121 | sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum; | 1116 | sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum; |
1122 | } | 1117 | } else { |
1123 | else { | ||
1124 | sdp->sd_tune.gt_statfs_slow = 1; | 1118 | sdp->sd_tune.gt_statfs_slow = 1; |
1125 | sdp->sd_tune.gt_statfs_quantum = 30; | 1119 | sdp->sd_tune.gt_statfs_quantum = 30; |
1126 | } | 1120 | } |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c deleted file mode 100644 index 09e436a50723..000000000000 --- a/fs/gfs2/ops_inode.c +++ /dev/null | |||
@@ -1,1344 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | ||
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * This copyrighted material is made available to anyone wishing to use, | ||
6 | * modify, copy, or redistribute it subject to the terms and conditions | ||
7 | * of the GNU General Public License version 2. | ||
8 | */ | ||
9 | |||
10 | #include <linux/slab.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/completion.h> | ||
13 | #include <linux/buffer_head.h> | ||
14 | #include <linux/namei.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/xattr.h> | ||
17 | #include <linux/posix_acl.h> | ||
18 | #include <linux/gfs2_ondisk.h> | ||
19 | #include <linux/crc32.h> | ||
20 | #include <linux/fiemap.h> | ||
21 | #include <asm/uaccess.h> | ||
22 | |||
23 | #include "gfs2.h" | ||
24 | #include "incore.h" | ||
25 | #include "acl.h" | ||
26 | #include "bmap.h" | ||
27 | #include "dir.h" | ||
28 | #include "xattr.h" | ||
29 | #include "glock.h" | ||
30 | #include "inode.h" | ||
31 | #include "meta_io.h" | ||
32 | #include "quota.h" | ||
33 | #include "rgrp.h" | ||
34 | #include "trans.h" | ||
35 | #include "util.h" | ||
36 | #include "super.h" | ||
37 | |||
38 | /** | ||
39 | * gfs2_create - Create a file | ||
40 | * @dir: The directory in which to create the file | ||
41 | * @dentry: The dentry of the new file | ||
42 | * @mode: The mode of the new file | ||
43 | * | ||
44 | * Returns: errno | ||
45 | */ | ||
46 | |||
47 | static int gfs2_create(struct inode *dir, struct dentry *dentry, | ||
48 | int mode, struct nameidata *nd) | ||
49 | { | ||
50 | struct gfs2_inode *dip = GFS2_I(dir); | ||
51 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
52 | struct gfs2_holder ghs[2]; | ||
53 | struct inode *inode; | ||
54 | |||
55 | gfs2_holder_init(dip->i_gl, 0, 0, ghs); | ||
56 | |||
57 | for (;;) { | ||
58 | inode = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode, 0); | ||
59 | if (!IS_ERR(inode)) { | ||
60 | gfs2_trans_end(sdp); | ||
61 | if (dip->i_alloc->al_rgd) | ||
62 | gfs2_inplace_release(dip); | ||
63 | gfs2_quota_unlock(dip); | ||
64 | gfs2_alloc_put(dip); | ||
65 | gfs2_glock_dq_uninit_m(2, ghs); | ||
66 | mark_inode_dirty(inode); | ||
67 | break; | ||
68 | } else if (PTR_ERR(inode) != -EEXIST || | ||
69 | (nd && nd->flags & LOOKUP_EXCL)) { | ||
70 | gfs2_holder_uninit(ghs); | ||
71 | return PTR_ERR(inode); | ||
72 | } | ||
73 | |||
74 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | ||
75 | if (inode) { | ||
76 | if (!IS_ERR(inode)) { | ||
77 | gfs2_holder_uninit(ghs); | ||
78 | break; | ||
79 | } else { | ||
80 | gfs2_holder_uninit(ghs); | ||
81 | return PTR_ERR(inode); | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | d_instantiate(dentry, inode); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * gfs2_lookup - Look up a filename in a directory and return its inode | ||
93 | * @dir: The directory inode | ||
94 | * @dentry: The dentry of the new inode | ||
95 | * @nd: passed from Linux VFS, ignored by us | ||
96 | * | ||
97 | * Called by the VFS layer. Lock dir and call gfs2_lookupi() | ||
98 | * | ||
99 | * Returns: errno | ||
100 | */ | ||
101 | |||
102 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, | ||
103 | struct nameidata *nd) | ||
104 | { | ||
105 | struct inode *inode = NULL; | ||
106 | |||
107 | inode = gfs2_lookupi(dir, &dentry->d_name, 0); | ||
108 | if (inode && IS_ERR(inode)) | ||
109 | return ERR_CAST(inode); | ||
110 | |||
111 | if (inode) { | ||
112 | struct gfs2_glock *gl = GFS2_I(inode)->i_gl; | ||
113 | struct gfs2_holder gh; | ||
114 | int error; | ||
115 | error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
116 | if (error) { | ||
117 | iput(inode); | ||
118 | return ERR_PTR(error); | ||
119 | } | ||
120 | gfs2_glock_dq_uninit(&gh); | ||
121 | return d_splice_alias(inode, dentry); | ||
122 | } | ||
123 | d_add(dentry, inode); | ||
124 | |||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * gfs2_link - Link to a file | ||
130 | * @old_dentry: The inode to link | ||
131 | * @dir: Add link to this directory | ||
132 | * @dentry: The name of the link | ||
133 | * | ||
134 | * Link the inode in "old_dentry" into the directory "dir" with the | ||
135 | * name in "dentry". | ||
136 | * | ||
137 | * Returns: errno | ||
138 | */ | ||
139 | |||
140 | static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | ||
141 | struct dentry *dentry) | ||
142 | { | ||
143 | struct gfs2_inode *dip = GFS2_I(dir); | ||
144 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
145 | struct inode *inode = old_dentry->d_inode; | ||
146 | struct gfs2_inode *ip = GFS2_I(inode); | ||
147 | struct gfs2_holder ghs[2]; | ||
148 | int alloc_required; | ||
149 | int error; | ||
150 | |||
151 | if (S_ISDIR(inode->i_mode)) | ||
152 | return -EPERM; | ||
153 | |||
154 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
155 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | ||
156 | |||
157 | error = gfs2_glock_nq(ghs); /* parent */ | ||
158 | if (error) | ||
159 | goto out_parent; | ||
160 | |||
161 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
162 | if (error) | ||
163 | goto out_child; | ||
164 | |||
165 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0); | ||
166 | if (error) | ||
167 | goto out_gunlock; | ||
168 | |||
169 | error = gfs2_dir_check(dir, &dentry->d_name, NULL); | ||
170 | switch (error) { | ||
171 | case -ENOENT: | ||
172 | break; | ||
173 | case 0: | ||
174 | error = -EEXIST; | ||
175 | default: | ||
176 | goto out_gunlock; | ||
177 | } | ||
178 | |||
179 | error = -EINVAL; | ||
180 | if (!dip->i_inode.i_nlink) | ||
181 | goto out_gunlock; | ||
182 | error = -EFBIG; | ||
183 | if (dip->i_entries == (u32)-1) | ||
184 | goto out_gunlock; | ||
185 | error = -EPERM; | ||
186 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
187 | goto out_gunlock; | ||
188 | error = -EINVAL; | ||
189 | if (!ip->i_inode.i_nlink) | ||
190 | goto out_gunlock; | ||
191 | error = -EMLINK; | ||
192 | if (ip->i_inode.i_nlink == (u32)-1) | ||
193 | goto out_gunlock; | ||
194 | |||
195 | alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name); | ||
196 | if (error < 0) | ||
197 | goto out_gunlock; | ||
198 | error = 0; | ||
199 | |||
200 | if (alloc_required) { | ||
201 | struct gfs2_alloc *al = gfs2_alloc_get(dip); | ||
202 | if (!al) { | ||
203 | error = -ENOMEM; | ||
204 | goto out_gunlock; | ||
205 | } | ||
206 | |||
207 | error = gfs2_quota_lock_check(dip); | ||
208 | if (error) | ||
209 | goto out_alloc; | ||
210 | |||
211 | al->al_requested = sdp->sd_max_dirres; | ||
212 | |||
213 | error = gfs2_inplace_reserve(dip); | ||
214 | if (error) | ||
215 | goto out_gunlock_q; | ||
216 | |||
217 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | ||
218 | gfs2_rg_blocks(al) + | ||
219 | 2 * RES_DINODE + RES_STATFS + | ||
220 | RES_QUOTA, 0); | ||
221 | if (error) | ||
222 | goto out_ipres; | ||
223 | } else { | ||
224 | error = gfs2_trans_begin(sdp, 2 * RES_DINODE + RES_LEAF, 0); | ||
225 | if (error) | ||
226 | goto out_ipres; | ||
227 | } | ||
228 | |||
229 | error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode)); | ||
230 | if (error) | ||
231 | goto out_end_trans; | ||
232 | |||
233 | error = gfs2_change_nlink(ip, +1); | ||
234 | |||
235 | out_end_trans: | ||
236 | gfs2_trans_end(sdp); | ||
237 | out_ipres: | ||
238 | if (alloc_required) | ||
239 | gfs2_inplace_release(dip); | ||
240 | out_gunlock_q: | ||
241 | if (alloc_required) | ||
242 | gfs2_quota_unlock(dip); | ||
243 | out_alloc: | ||
244 | if (alloc_required) | ||
245 | gfs2_alloc_put(dip); | ||
246 | out_gunlock: | ||
247 | gfs2_glock_dq(ghs + 1); | ||
248 | out_child: | ||
249 | gfs2_glock_dq(ghs); | ||
250 | out_parent: | ||
251 | gfs2_holder_uninit(ghs); | ||
252 | gfs2_holder_uninit(ghs + 1); | ||
253 | if (!error) { | ||
254 | ihold(inode); | ||
255 | d_instantiate(dentry, inode); | ||
256 | mark_inode_dirty(inode); | ||
257 | } | ||
258 | return error; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * gfs2_unlink_ok - check to see that a inode is still in a directory | ||
263 | * @dip: the directory | ||
264 | * @name: the name of the file | ||
265 | * @ip: the inode | ||
266 | * | ||
267 | * Assumes that the lock on (at least) @dip is held. | ||
268 | * | ||
269 | * Returns: 0 if the parent/child relationship is correct, errno if it isn't | ||
270 | */ | ||
271 | |||
272 | static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | ||
273 | const struct gfs2_inode *ip) | ||
274 | { | ||
275 | int error; | ||
276 | |||
277 | if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode)) | ||
278 | return -EPERM; | ||
279 | |||
280 | if ((dip->i_inode.i_mode & S_ISVTX) && | ||
281 | dip->i_inode.i_uid != current_fsuid() && | ||
282 | ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER)) | ||
283 | return -EPERM; | ||
284 | |||
285 | if (IS_APPEND(&dip->i_inode)) | ||
286 | return -EPERM; | ||
287 | |||
288 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0); | ||
289 | if (error) | ||
290 | return error; | ||
291 | |||
292 | error = gfs2_dir_check(&dip->i_inode, name, ip); | ||
293 | if (error) | ||
294 | return error; | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * gfs2_unlink - Unlink a file | ||
301 | * @dir: The inode of the directory containing the file to unlink | ||
302 | * @dentry: The file itself | ||
303 | * | ||
304 | * Unlink a file. Call gfs2_unlinki() | ||
305 | * | ||
306 | * Returns: errno | ||
307 | */ | ||
308 | |||
309 | static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | ||
310 | { | ||
311 | struct gfs2_inode *dip = GFS2_I(dir); | ||
312 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
313 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
314 | struct gfs2_holder ghs[3]; | ||
315 | struct gfs2_rgrpd *rgd; | ||
316 | struct gfs2_holder ri_gh; | ||
317 | int error; | ||
318 | |||
319 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
320 | if (error) | ||
321 | return error; | ||
322 | |||
323 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
324 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | ||
325 | |||
326 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
327 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
328 | |||
329 | |||
330 | error = gfs2_glock_nq(ghs); /* parent */ | ||
331 | if (error) | ||
332 | goto out_parent; | ||
333 | |||
334 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
335 | if (error) | ||
336 | goto out_child; | ||
337 | |||
338 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | ||
339 | if (error) | ||
340 | goto out_rgrp; | ||
341 | |||
342 | error = gfs2_unlink_ok(dip, &dentry->d_name, ip); | ||
343 | if (error) | ||
344 | goto out_gunlock; | ||
345 | |||
346 | error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); | ||
347 | if (error) | ||
348 | goto out_gunlock; | ||
349 | |||
350 | error = gfs2_dir_del(dip, &dentry->d_name); | ||
351 | if (error) | ||
352 | goto out_end_trans; | ||
353 | |||
354 | error = gfs2_change_nlink(ip, -1); | ||
355 | |||
356 | out_end_trans: | ||
357 | gfs2_trans_end(sdp); | ||
358 | out_gunlock: | ||
359 | gfs2_glock_dq(ghs + 2); | ||
360 | out_rgrp: | ||
361 | gfs2_holder_uninit(ghs + 2); | ||
362 | gfs2_glock_dq(ghs + 1); | ||
363 | out_child: | ||
364 | gfs2_holder_uninit(ghs + 1); | ||
365 | gfs2_glock_dq(ghs); | ||
366 | out_parent: | ||
367 | gfs2_holder_uninit(ghs); | ||
368 | gfs2_glock_dq_uninit(&ri_gh); | ||
369 | return error; | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * gfs2_symlink - Create a symlink | ||
374 | * @dir: The directory to create the symlink in | ||
375 | * @dentry: The dentry to put the symlink in | ||
376 | * @symname: The thing which the link points to | ||
377 | * | ||
378 | * Returns: errno | ||
379 | */ | ||
380 | |||
381 | static int gfs2_symlink(struct inode *dir, struct dentry *dentry, | ||
382 | const char *symname) | ||
383 | { | ||
384 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | ||
385 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
386 | struct gfs2_holder ghs[2]; | ||
387 | struct inode *inode; | ||
388 | struct buffer_head *dibh; | ||
389 | int size; | ||
390 | int error; | ||
391 | |||
392 | /* Must be stuffed with a null terminator for gfs2_follow_link() */ | ||
393 | size = strlen(symname); | ||
394 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode) - 1) | ||
395 | return -ENAMETOOLONG; | ||
396 | |||
397 | gfs2_holder_init(dip->i_gl, 0, 0, ghs); | ||
398 | |||
399 | inode = gfs2_createi(ghs, &dentry->d_name, S_IFLNK | S_IRWXUGO, 0); | ||
400 | if (IS_ERR(inode)) { | ||
401 | gfs2_holder_uninit(ghs); | ||
402 | return PTR_ERR(inode); | ||
403 | } | ||
404 | |||
405 | ip = ghs[1].gh_gl->gl_object; | ||
406 | |||
407 | i_size_write(inode, size); | ||
408 | |||
409 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
410 | |||
411 | if (!gfs2_assert_withdraw(sdp, !error)) { | ||
412 | gfs2_dinode_out(ip, dibh->b_data); | ||
413 | memcpy(dibh->b_data + sizeof(struct gfs2_dinode), symname, | ||
414 | size); | ||
415 | brelse(dibh); | ||
416 | } | ||
417 | |||
418 | gfs2_trans_end(sdp); | ||
419 | if (dip->i_alloc->al_rgd) | ||
420 | gfs2_inplace_release(dip); | ||
421 | gfs2_quota_unlock(dip); | ||
422 | gfs2_alloc_put(dip); | ||
423 | |||
424 | gfs2_glock_dq_uninit_m(2, ghs); | ||
425 | |||
426 | d_instantiate(dentry, inode); | ||
427 | mark_inode_dirty(inode); | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * gfs2_mkdir - Make a directory | ||
434 | * @dir: The parent directory of the new one | ||
435 | * @dentry: The dentry of the new directory | ||
436 | * @mode: The mode of the new directory | ||
437 | * | ||
438 | * Returns: errno | ||
439 | */ | ||
440 | |||
441 | static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
442 | { | ||
443 | struct gfs2_inode *dip = GFS2_I(dir), *ip; | ||
444 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
445 | struct gfs2_holder ghs[2]; | ||
446 | struct inode *inode; | ||
447 | struct buffer_head *dibh; | ||
448 | int error; | ||
449 | |||
450 | gfs2_holder_init(dip->i_gl, 0, 0, ghs); | ||
451 | |||
452 | inode = gfs2_createi(ghs, &dentry->d_name, S_IFDIR | mode, 0); | ||
453 | if (IS_ERR(inode)) { | ||
454 | gfs2_holder_uninit(ghs); | ||
455 | return PTR_ERR(inode); | ||
456 | } | ||
457 | |||
458 | ip = ghs[1].gh_gl->gl_object; | ||
459 | |||
460 | ip->i_inode.i_nlink = 2; | ||
461 | i_size_write(inode, sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)); | ||
462 | ip->i_diskflags |= GFS2_DIF_JDATA; | ||
463 | ip->i_entries = 2; | ||
464 | |||
465 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
466 | |||
467 | if (!gfs2_assert_withdraw(sdp, !error)) { | ||
468 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | ||
469 | struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1); | ||
470 | |||
471 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
472 | gfs2_qstr2dirent(&gfs2_qdot, GFS2_DIRENT_SIZE(gfs2_qdot.len), dent); | ||
473 | dent->de_inum = di->di_num; /* already GFS2 endian */ | ||
474 | dent->de_type = cpu_to_be16(DT_DIR); | ||
475 | di->di_entries = cpu_to_be32(1); | ||
476 | |||
477 | dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1)); | ||
478 | gfs2_qstr2dirent(&gfs2_qdotdot, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent); | ||
479 | |||
480 | gfs2_inum_out(dip, dent); | ||
481 | dent->de_type = cpu_to_be16(DT_DIR); | ||
482 | |||
483 | gfs2_dinode_out(ip, di); | ||
484 | |||
485 | brelse(dibh); | ||
486 | } | ||
487 | |||
488 | error = gfs2_change_nlink(dip, +1); | ||
489 | gfs2_assert_withdraw(sdp, !error); /* dip already pinned */ | ||
490 | |||
491 | gfs2_trans_end(sdp); | ||
492 | if (dip->i_alloc->al_rgd) | ||
493 | gfs2_inplace_release(dip); | ||
494 | gfs2_quota_unlock(dip); | ||
495 | gfs2_alloc_put(dip); | ||
496 | |||
497 | gfs2_glock_dq_uninit_m(2, ghs); | ||
498 | |||
499 | d_instantiate(dentry, inode); | ||
500 | mark_inode_dirty(inode); | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /** | ||
506 | * gfs2_rmdiri - Remove a directory | ||
507 | * @dip: The parent directory of the directory to be removed | ||
508 | * @name: The name of the directory to be removed | ||
509 | * @ip: The GFS2 inode of the directory to be removed | ||
510 | * | ||
511 | * Assumes Glocks on dip and ip are held | ||
512 | * | ||
513 | * Returns: errno | ||
514 | */ | ||
515 | |||
516 | static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, | ||
517 | struct gfs2_inode *ip) | ||
518 | { | ||
519 | int error; | ||
520 | |||
521 | if (ip->i_entries != 2) { | ||
522 | if (gfs2_consist_inode(ip)) | ||
523 | gfs2_dinode_print(ip); | ||
524 | return -EIO; | ||
525 | } | ||
526 | |||
527 | error = gfs2_dir_del(dip, name); | ||
528 | if (error) | ||
529 | return error; | ||
530 | |||
531 | error = gfs2_change_nlink(dip, -1); | ||
532 | if (error) | ||
533 | return error; | ||
534 | |||
535 | error = gfs2_dir_del(ip, &gfs2_qdot); | ||
536 | if (error) | ||
537 | return error; | ||
538 | |||
539 | error = gfs2_dir_del(ip, &gfs2_qdotdot); | ||
540 | if (error) | ||
541 | return error; | ||
542 | |||
543 | /* It looks odd, but it really should be done twice */ | ||
544 | error = gfs2_change_nlink(ip, -1); | ||
545 | if (error) | ||
546 | return error; | ||
547 | |||
548 | error = gfs2_change_nlink(ip, -1); | ||
549 | if (error) | ||
550 | return error; | ||
551 | |||
552 | return error; | ||
553 | } | ||
554 | |||
555 | /** | ||
556 | * gfs2_rmdir - Remove a directory | ||
557 | * @dir: The parent directory of the directory to be removed | ||
558 | * @dentry: The dentry of the directory to remove | ||
559 | * | ||
560 | * Remove a directory. Call gfs2_rmdiri() | ||
561 | * | ||
562 | * Returns: errno | ||
563 | */ | ||
564 | |||
565 | static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | ||
566 | { | ||
567 | struct gfs2_inode *dip = GFS2_I(dir); | ||
568 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
569 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
570 | struct gfs2_holder ghs[3]; | ||
571 | struct gfs2_rgrpd *rgd; | ||
572 | struct gfs2_holder ri_gh; | ||
573 | int error; | ||
574 | |||
575 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
576 | if (error) | ||
577 | return error; | ||
578 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
579 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | ||
580 | |||
581 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
582 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
583 | |||
584 | error = gfs2_glock_nq(ghs); /* parent */ | ||
585 | if (error) | ||
586 | goto out_parent; | ||
587 | |||
588 | error = gfs2_glock_nq(ghs + 1); /* child */ | ||
589 | if (error) | ||
590 | goto out_child; | ||
591 | |||
592 | error = gfs2_glock_nq(ghs + 2); /* rgrp */ | ||
593 | if (error) | ||
594 | goto out_rgrp; | ||
595 | |||
596 | error = gfs2_unlink_ok(dip, &dentry->d_name, ip); | ||
597 | if (error) | ||
598 | goto out_gunlock; | ||
599 | |||
600 | if (ip->i_entries < 2) { | ||
601 | if (gfs2_consist_inode(ip)) | ||
602 | gfs2_dinode_print(ip); | ||
603 | error = -EIO; | ||
604 | goto out_gunlock; | ||
605 | } | ||
606 | if (ip->i_entries > 2) { | ||
607 | error = -ENOTEMPTY; | ||
608 | goto out_gunlock; | ||
609 | } | ||
610 | |||
611 | error = gfs2_trans_begin(sdp, 2 * RES_DINODE + 3 * RES_LEAF + RES_RG_BIT, 0); | ||
612 | if (error) | ||
613 | goto out_gunlock; | ||
614 | |||
615 | error = gfs2_rmdiri(dip, &dentry->d_name, ip); | ||
616 | |||
617 | gfs2_trans_end(sdp); | ||
618 | |||
619 | out_gunlock: | ||
620 | gfs2_glock_dq(ghs + 2); | ||
621 | out_rgrp: | ||
622 | gfs2_holder_uninit(ghs + 2); | ||
623 | gfs2_glock_dq(ghs + 1); | ||
624 | out_child: | ||
625 | gfs2_holder_uninit(ghs + 1); | ||
626 | gfs2_glock_dq(ghs); | ||
627 | out_parent: | ||
628 | gfs2_holder_uninit(ghs); | ||
629 | gfs2_glock_dq_uninit(&ri_gh); | ||
630 | return error; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * gfs2_mknod - Make a special file | ||
635 | * @dir: The directory in which the special file will reside | ||
636 | * @dentry: The dentry of the special file | ||
637 | * @mode: The mode of the special file | ||
638 | * @rdev: The device specification of the special file | ||
639 | * | ||
640 | */ | ||
641 | |||
642 | static int gfs2_mknod(struct inode *dir, struct dentry *dentry, int mode, | ||
643 | dev_t dev) | ||
644 | { | ||
645 | struct gfs2_inode *dip = GFS2_I(dir); | ||
646 | struct gfs2_sbd *sdp = GFS2_SB(dir); | ||
647 | struct gfs2_holder ghs[2]; | ||
648 | struct inode *inode; | ||
649 | |||
650 | gfs2_holder_init(dip->i_gl, 0, 0, ghs); | ||
651 | |||
652 | inode = gfs2_createi(ghs, &dentry->d_name, mode, dev); | ||
653 | if (IS_ERR(inode)) { | ||
654 | gfs2_holder_uninit(ghs); | ||
655 | return PTR_ERR(inode); | ||
656 | } | ||
657 | |||
658 | gfs2_trans_end(sdp); | ||
659 | if (dip->i_alloc->al_rgd) | ||
660 | gfs2_inplace_release(dip); | ||
661 | gfs2_quota_unlock(dip); | ||
662 | gfs2_alloc_put(dip); | ||
663 | |||
664 | gfs2_glock_dq_uninit_m(2, ghs); | ||
665 | |||
666 | d_instantiate(dentry, inode); | ||
667 | mark_inode_dirty(inode); | ||
668 | |||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * gfs2_ok_to_move - check if it's ok to move a directory to another directory | ||
674 | * @this: move this | ||
675 | * @to: to here | ||
676 | * | ||
677 | * Follow @to back to the root and make sure we don't encounter @this | ||
678 | * Assumes we already hold the rename lock. | ||
679 | * | ||
680 | * Returns: errno | ||
681 | */ | ||
682 | |||
683 | static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) | ||
684 | { | ||
685 | struct inode *dir = &to->i_inode; | ||
686 | struct super_block *sb = dir->i_sb; | ||
687 | struct inode *tmp; | ||
688 | int error = 0; | ||
689 | |||
690 | igrab(dir); | ||
691 | |||
692 | for (;;) { | ||
693 | if (dir == &this->i_inode) { | ||
694 | error = -EINVAL; | ||
695 | break; | ||
696 | } | ||
697 | if (dir == sb->s_root->d_inode) { | ||
698 | error = 0; | ||
699 | break; | ||
700 | } | ||
701 | |||
702 | tmp = gfs2_lookupi(dir, &gfs2_qdotdot, 1); | ||
703 | if (IS_ERR(tmp)) { | ||
704 | error = PTR_ERR(tmp); | ||
705 | break; | ||
706 | } | ||
707 | |||
708 | iput(dir); | ||
709 | dir = tmp; | ||
710 | } | ||
711 | |||
712 | iput(dir); | ||
713 | |||
714 | return error; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * gfs2_rename - Rename a file | ||
719 | * @odir: Parent directory of old file name | ||
720 | * @odentry: The old dentry of the file | ||
721 | * @ndir: Parent directory of new file name | ||
722 | * @ndentry: The new dentry of the file | ||
723 | * | ||
724 | * Returns: errno | ||
725 | */ | ||
726 | |||
727 | static int gfs2_rename(struct inode *odir, struct dentry *odentry, | ||
728 | struct inode *ndir, struct dentry *ndentry) | ||
729 | { | ||
730 | struct gfs2_inode *odip = GFS2_I(odir); | ||
731 | struct gfs2_inode *ndip = GFS2_I(ndir); | ||
732 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | ||
733 | struct gfs2_inode *nip = NULL; | ||
734 | struct gfs2_sbd *sdp = GFS2_SB(odir); | ||
735 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh; | ||
736 | struct gfs2_rgrpd *nrgd; | ||
737 | unsigned int num_gh; | ||
738 | int dir_rename = 0; | ||
739 | int alloc_required = 0; | ||
740 | unsigned int x; | ||
741 | int error; | ||
742 | |||
743 | if (ndentry->d_inode) { | ||
744 | nip = GFS2_I(ndentry->d_inode); | ||
745 | if (ip == nip) | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
750 | if (error) | ||
751 | return error; | ||
752 | |||
753 | if (odip != ndip) { | ||
754 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, | ||
755 | 0, &r_gh); | ||
756 | if (error) | ||
757 | goto out; | ||
758 | |||
759 | if (S_ISDIR(ip->i_inode.i_mode)) { | ||
760 | dir_rename = 1; | ||
761 | /* don't move a dirctory into it's subdir */ | ||
762 | error = gfs2_ok_to_move(ip, ndip); | ||
763 | if (error) | ||
764 | goto out_gunlock_r; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | num_gh = 1; | ||
769 | gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | ||
770 | if (odip != ndip) { | ||
771 | gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
772 | num_gh++; | ||
773 | } | ||
774 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
775 | num_gh++; | ||
776 | |||
777 | if (nip) { | ||
778 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | ||
779 | num_gh++; | ||
780 | /* grab the resource lock for unlink flag twiddling | ||
781 | * this is the case of the target file already existing | ||
782 | * so we unlink before doing the rename | ||
783 | */ | ||
784 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr); | ||
785 | if (nrgd) | ||
786 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); | ||
787 | } | ||
788 | |||
789 | for (x = 0; x < num_gh; x++) { | ||
790 | error = gfs2_glock_nq(ghs + x); | ||
791 | if (error) | ||
792 | goto out_gunlock; | ||
793 | } | ||
794 | |||
795 | /* Check out the old directory */ | ||
796 | |||
797 | error = gfs2_unlink_ok(odip, &odentry->d_name, ip); | ||
798 | if (error) | ||
799 | goto out_gunlock; | ||
800 | |||
801 | /* Check out the new directory */ | ||
802 | |||
803 | if (nip) { | ||
804 | error = gfs2_unlink_ok(ndip, &ndentry->d_name, nip); | ||
805 | if (error) | ||
806 | goto out_gunlock; | ||
807 | |||
808 | if (S_ISDIR(nip->i_inode.i_mode)) { | ||
809 | if (nip->i_entries < 2) { | ||
810 | if (gfs2_consist_inode(nip)) | ||
811 | gfs2_dinode_print(nip); | ||
812 | error = -EIO; | ||
813 | goto out_gunlock; | ||
814 | } | ||
815 | if (nip->i_entries > 2) { | ||
816 | error = -ENOTEMPTY; | ||
817 | goto out_gunlock; | ||
818 | } | ||
819 | } | ||
820 | } else { | ||
821 | error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0); | ||
822 | if (error) | ||
823 | goto out_gunlock; | ||
824 | |||
825 | error = gfs2_dir_check(ndir, &ndentry->d_name, NULL); | ||
826 | switch (error) { | ||
827 | case -ENOENT: | ||
828 | error = 0; | ||
829 | break; | ||
830 | case 0: | ||
831 | error = -EEXIST; | ||
832 | default: | ||
833 | goto out_gunlock; | ||
834 | }; | ||
835 | |||
836 | if (odip != ndip) { | ||
837 | if (!ndip->i_inode.i_nlink) { | ||
838 | error = -EINVAL; | ||
839 | goto out_gunlock; | ||
840 | } | ||
841 | if (ndip->i_entries == (u32)-1) { | ||
842 | error = -EFBIG; | ||
843 | goto out_gunlock; | ||
844 | } | ||
845 | if (S_ISDIR(ip->i_inode.i_mode) && | ||
846 | ndip->i_inode.i_nlink == (u32)-1) { | ||
847 | error = -EMLINK; | ||
848 | goto out_gunlock; | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | |||
853 | /* Check out the dir to be renamed */ | ||
854 | |||
855 | if (dir_rename) { | ||
856 | error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0); | ||
857 | if (error) | ||
858 | goto out_gunlock; | ||
859 | } | ||
860 | |||
861 | if (nip == NULL) | ||
862 | alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name); | ||
863 | error = alloc_required; | ||
864 | if (error < 0) | ||
865 | goto out_gunlock; | ||
866 | error = 0; | ||
867 | |||
868 | if (alloc_required) { | ||
869 | struct gfs2_alloc *al = gfs2_alloc_get(ndip); | ||
870 | if (!al) { | ||
871 | error = -ENOMEM; | ||
872 | goto out_gunlock; | ||
873 | } | ||
874 | |||
875 | error = gfs2_quota_lock_check(ndip); | ||
876 | if (error) | ||
877 | goto out_alloc; | ||
878 | |||
879 | al->al_requested = sdp->sd_max_dirres; | ||
880 | |||
881 | error = gfs2_inplace_reserve_ri(ndip); | ||
882 | if (error) | ||
883 | goto out_gunlock_q; | ||
884 | |||
885 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | ||
886 | gfs2_rg_blocks(al) + | ||
887 | 4 * RES_DINODE + 4 * RES_LEAF + | ||
888 | RES_STATFS + RES_QUOTA + 4, 0); | ||
889 | if (error) | ||
890 | goto out_ipreserv; | ||
891 | } else { | ||
892 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + | ||
893 | 5 * RES_LEAF + 4, 0); | ||
894 | if (error) | ||
895 | goto out_gunlock; | ||
896 | } | ||
897 | |||
898 | /* Remove the target file, if it exists */ | ||
899 | |||
900 | if (nip) { | ||
901 | if (S_ISDIR(nip->i_inode.i_mode)) | ||
902 | error = gfs2_rmdiri(ndip, &ndentry->d_name, nip); | ||
903 | else { | ||
904 | error = gfs2_dir_del(ndip, &ndentry->d_name); | ||
905 | if (error) | ||
906 | goto out_end_trans; | ||
907 | error = gfs2_change_nlink(nip, -1); | ||
908 | } | ||
909 | if (error) | ||
910 | goto out_end_trans; | ||
911 | } | ||
912 | |||
913 | if (dir_rename) { | ||
914 | error = gfs2_change_nlink(ndip, +1); | ||
915 | if (error) | ||
916 | goto out_end_trans; | ||
917 | error = gfs2_change_nlink(odip, -1); | ||
918 | if (error) | ||
919 | goto out_end_trans; | ||
920 | |||
921 | error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR); | ||
922 | if (error) | ||
923 | goto out_end_trans; | ||
924 | } else { | ||
925 | struct buffer_head *dibh; | ||
926 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
927 | if (error) | ||
928 | goto out_end_trans; | ||
929 | ip->i_inode.i_ctime = CURRENT_TIME; | ||
930 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
931 | gfs2_dinode_out(ip, dibh->b_data); | ||
932 | brelse(dibh); | ||
933 | } | ||
934 | |||
935 | error = gfs2_dir_del(odip, &odentry->d_name); | ||
936 | if (error) | ||
937 | goto out_end_trans; | ||
938 | |||
939 | error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode)); | ||
940 | if (error) | ||
941 | goto out_end_trans; | ||
942 | |||
943 | out_end_trans: | ||
944 | gfs2_trans_end(sdp); | ||
945 | out_ipreserv: | ||
946 | if (alloc_required) | ||
947 | gfs2_inplace_release(ndip); | ||
948 | out_gunlock_q: | ||
949 | if (alloc_required) | ||
950 | gfs2_quota_unlock(ndip); | ||
951 | out_alloc: | ||
952 | if (alloc_required) | ||
953 | gfs2_alloc_put(ndip); | ||
954 | out_gunlock: | ||
955 | while (x--) { | ||
956 | gfs2_glock_dq(ghs + x); | ||
957 | gfs2_holder_uninit(ghs + x); | ||
958 | } | ||
959 | out_gunlock_r: | ||
960 | if (r_gh.gh_gl) | ||
961 | gfs2_glock_dq_uninit(&r_gh); | ||
962 | out: | ||
963 | gfs2_glock_dq_uninit(&ri_gh); | ||
964 | return error; | ||
965 | } | ||
966 | |||
967 | /** | ||
968 | * gfs2_follow_link - Follow a symbolic link | ||
969 | * @dentry: The dentry of the link | ||
970 | * @nd: Data that we pass to vfs_follow_link() | ||
971 | * | ||
972 | * This can handle symlinks of any size. | ||
973 | * | ||
974 | * Returns: 0 on success or error code | ||
975 | */ | ||
976 | |||
977 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
978 | { | ||
979 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
980 | struct gfs2_holder i_gh; | ||
981 | struct buffer_head *dibh; | ||
982 | unsigned int x, size; | ||
983 | char *buf; | ||
984 | int error; | ||
985 | |||
986 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); | ||
987 | error = gfs2_glock_nq(&i_gh); | ||
988 | if (error) { | ||
989 | gfs2_holder_uninit(&i_gh); | ||
990 | nd_set_link(nd, ERR_PTR(error)); | ||
991 | return NULL; | ||
992 | } | ||
993 | |||
994 | size = (unsigned int)i_size_read(&ip->i_inode); | ||
995 | if (size == 0) { | ||
996 | gfs2_consist_inode(ip); | ||
997 | buf = ERR_PTR(-EIO); | ||
998 | goto out; | ||
999 | } | ||
1000 | |||
1001 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
1002 | if (error) { | ||
1003 | buf = ERR_PTR(error); | ||
1004 | goto out; | ||
1005 | } | ||
1006 | |||
1007 | x = size + 1; | ||
1008 | buf = kmalloc(x, GFP_NOFS); | ||
1009 | if (!buf) | ||
1010 | buf = ERR_PTR(-ENOMEM); | ||
1011 | else | ||
1012 | memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x); | ||
1013 | brelse(dibh); | ||
1014 | out: | ||
1015 | gfs2_glock_dq_uninit(&i_gh); | ||
1016 | nd_set_link(nd, buf); | ||
1017 | return NULL; | ||
1018 | } | ||
1019 | |||
1020 | static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | ||
1021 | { | ||
1022 | char *s = nd_get_link(nd); | ||
1023 | if (!IS_ERR(s)) | ||
1024 | kfree(s); | ||
1025 | } | ||
1026 | |||
1027 | /** | ||
1028 | * gfs2_permission - | ||
1029 | * @inode: The inode | ||
1030 | * @mask: The mask to be tested | ||
1031 | * @flags: Indicates whether this is an RCU path walk or not | ||
1032 | * | ||
1033 | * This may be called from the VFS directly, or from within GFS2 with the | ||
1034 | * inode locked, so we look to see if the glock is already locked and only | ||
1035 | * lock the glock if its not already been done. | ||
1036 | * | ||
1037 | * Returns: errno | ||
1038 | */ | ||
1039 | |||
1040 | int gfs2_permission(struct inode *inode, int mask, unsigned int flags) | ||
1041 | { | ||
1042 | struct gfs2_inode *ip; | ||
1043 | struct gfs2_holder i_gh; | ||
1044 | int error; | ||
1045 | int unlock = 0; | ||
1046 | |||
1047 | |||
1048 | ip = GFS2_I(inode); | ||
1049 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | ||
1050 | if (flags & IPERM_FLAG_RCU) | ||
1051 | return -ECHILD; | ||
1052 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | ||
1053 | if (error) | ||
1054 | return error; | ||
1055 | unlock = 1; | ||
1056 | } | ||
1057 | |||
1058 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | ||
1059 | error = -EACCES; | ||
1060 | else | ||
1061 | error = generic_permission(inode, mask, flags, gfs2_check_acl); | ||
1062 | if (unlock) | ||
1063 | gfs2_glock_dq_uninit(&i_gh); | ||
1064 | |||
1065 | return error; | ||
1066 | } | ||
1067 | |||
1068 | static int setattr_chown(struct inode *inode, struct iattr *attr) | ||
1069 | { | ||
1070 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1071 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1072 | u32 ouid, ogid, nuid, ngid; | ||
1073 | int error; | ||
1074 | |||
1075 | ouid = inode->i_uid; | ||
1076 | ogid = inode->i_gid; | ||
1077 | nuid = attr->ia_uid; | ||
1078 | ngid = attr->ia_gid; | ||
1079 | |||
1080 | if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) | ||
1081 | ouid = nuid = NO_QUOTA_CHANGE; | ||
1082 | if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) | ||
1083 | ogid = ngid = NO_QUOTA_CHANGE; | ||
1084 | |||
1085 | if (!gfs2_alloc_get(ip)) | ||
1086 | return -ENOMEM; | ||
1087 | |||
1088 | error = gfs2_quota_lock(ip, nuid, ngid); | ||
1089 | if (error) | ||
1090 | goto out_alloc; | ||
1091 | |||
1092 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { | ||
1093 | error = gfs2_quota_check(ip, nuid, ngid); | ||
1094 | if (error) | ||
1095 | goto out_gunlock_q; | ||
1096 | } | ||
1097 | |||
1098 | error = gfs2_trans_begin(sdp, RES_DINODE + 2 * RES_QUOTA, 0); | ||
1099 | if (error) | ||
1100 | goto out_gunlock_q; | ||
1101 | |||
1102 | error = gfs2_setattr_simple(ip, attr); | ||
1103 | if (error) | ||
1104 | goto out_end_trans; | ||
1105 | |||
1106 | if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { | ||
1107 | u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); | ||
1108 | gfs2_quota_change(ip, -blocks, ouid, ogid); | ||
1109 | gfs2_quota_change(ip, blocks, nuid, ngid); | ||
1110 | } | ||
1111 | |||
1112 | out_end_trans: | ||
1113 | gfs2_trans_end(sdp); | ||
1114 | out_gunlock_q: | ||
1115 | gfs2_quota_unlock(ip); | ||
1116 | out_alloc: | ||
1117 | gfs2_alloc_put(ip); | ||
1118 | return error; | ||
1119 | } | ||
1120 | |||
1121 | /** | ||
1122 | * gfs2_setattr - Change attributes on an inode | ||
1123 | * @dentry: The dentry which is changing | ||
1124 | * @attr: The structure describing the change | ||
1125 | * | ||
1126 | * The VFS layer wants to change one or more of an inodes attributes. Write | ||
1127 | * that change out to disk. | ||
1128 | * | ||
1129 | * Returns: errno | ||
1130 | */ | ||
1131 | |||
1132 | static int gfs2_setattr(struct dentry *dentry, struct iattr *attr) | ||
1133 | { | ||
1134 | struct inode *inode = dentry->d_inode; | ||
1135 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1136 | struct gfs2_holder i_gh; | ||
1137 | int error; | ||
1138 | |||
1139 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); | ||
1140 | if (error) | ||
1141 | return error; | ||
1142 | |||
1143 | error = -EPERM; | ||
1144 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
1145 | goto out; | ||
1146 | |||
1147 | error = inode_change_ok(inode, attr); | ||
1148 | if (error) | ||
1149 | goto out; | ||
1150 | |||
1151 | if (attr->ia_valid & ATTR_SIZE) | ||
1152 | error = gfs2_setattr_size(inode, attr->ia_size); | ||
1153 | else if (attr->ia_valid & (ATTR_UID | ATTR_GID)) | ||
1154 | error = setattr_chown(inode, attr); | ||
1155 | else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode)) | ||
1156 | error = gfs2_acl_chmod(ip, attr); | ||
1157 | else | ||
1158 | error = gfs2_setattr_simple(ip, attr); | ||
1159 | |||
1160 | out: | ||
1161 | gfs2_glock_dq_uninit(&i_gh); | ||
1162 | if (!error) | ||
1163 | mark_inode_dirty(inode); | ||
1164 | return error; | ||
1165 | } | ||
1166 | |||
1167 | /** | ||
1168 | * gfs2_getattr - Read out an inode's attributes | ||
1169 | * @mnt: The vfsmount the inode is being accessed from | ||
1170 | * @dentry: The dentry to stat | ||
1171 | * @stat: The inode's stats | ||
1172 | * | ||
1173 | * This may be called from the VFS directly, or from within GFS2 with the | ||
1174 | * inode locked, so we look to see if the glock is already locked and only | ||
1175 | * lock the glock if its not already been done. Note that its the NFS | ||
1176 | * readdirplus operation which causes this to be called (from filldir) | ||
1177 | * with the glock already held. | ||
1178 | * | ||
1179 | * Returns: errno | ||
1180 | */ | ||
1181 | |||
1182 | static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
1183 | struct kstat *stat) | ||
1184 | { | ||
1185 | struct inode *inode = dentry->d_inode; | ||
1186 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1187 | struct gfs2_holder gh; | ||
1188 | int error; | ||
1189 | int unlock = 0; | ||
1190 | |||
1191 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | ||
1192 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1193 | if (error) | ||
1194 | return error; | ||
1195 | unlock = 1; | ||
1196 | } | ||
1197 | |||
1198 | generic_fillattr(inode, stat); | ||
1199 | if (unlock) | ||
1200 | gfs2_glock_dq_uninit(&gh); | ||
1201 | |||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | static int gfs2_setxattr(struct dentry *dentry, const char *name, | ||
1206 | const void *data, size_t size, int flags) | ||
1207 | { | ||
1208 | struct inode *inode = dentry->d_inode; | ||
1209 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1210 | struct gfs2_holder gh; | ||
1211 | int ret; | ||
1212 | |||
1213 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
1214 | ret = gfs2_glock_nq(&gh); | ||
1215 | if (ret == 0) { | ||
1216 | ret = generic_setxattr(dentry, name, data, size, flags); | ||
1217 | gfs2_glock_dq(&gh); | ||
1218 | } | ||
1219 | gfs2_holder_uninit(&gh); | ||
1220 | return ret; | ||
1221 | } | ||
1222 | |||
1223 | static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name, | ||
1224 | void *data, size_t size) | ||
1225 | { | ||
1226 | struct inode *inode = dentry->d_inode; | ||
1227 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1228 | struct gfs2_holder gh; | ||
1229 | int ret; | ||
1230 | |||
1231 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); | ||
1232 | ret = gfs2_glock_nq(&gh); | ||
1233 | if (ret == 0) { | ||
1234 | ret = generic_getxattr(dentry, name, data, size); | ||
1235 | gfs2_glock_dq(&gh); | ||
1236 | } | ||
1237 | gfs2_holder_uninit(&gh); | ||
1238 | return ret; | ||
1239 | } | ||
1240 | |||
1241 | static int gfs2_removexattr(struct dentry *dentry, const char *name) | ||
1242 | { | ||
1243 | struct inode *inode = dentry->d_inode; | ||
1244 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1245 | struct gfs2_holder gh; | ||
1246 | int ret; | ||
1247 | |||
1248 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | ||
1249 | ret = gfs2_glock_nq(&gh); | ||
1250 | if (ret == 0) { | ||
1251 | ret = generic_removexattr(dentry, name); | ||
1252 | gfs2_glock_dq(&gh); | ||
1253 | } | ||
1254 | gfs2_holder_uninit(&gh); | ||
1255 | return ret; | ||
1256 | } | ||
1257 | |||
1258 | static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
1259 | u64 start, u64 len) | ||
1260 | { | ||
1261 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1262 | struct gfs2_holder gh; | ||
1263 | int ret; | ||
1264 | |||
1265 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | ||
1266 | if (ret) | ||
1267 | return ret; | ||
1268 | |||
1269 | mutex_lock(&inode->i_mutex); | ||
1270 | |||
1271 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
1272 | if (ret) | ||
1273 | goto out; | ||
1274 | |||
1275 | if (gfs2_is_stuffed(ip)) { | ||
1276 | u64 phys = ip->i_no_addr << inode->i_blkbits; | ||
1277 | u64 size = i_size_read(inode); | ||
1278 | u32 flags = FIEMAP_EXTENT_LAST|FIEMAP_EXTENT_NOT_ALIGNED| | ||
1279 | FIEMAP_EXTENT_DATA_INLINE; | ||
1280 | phys += sizeof(struct gfs2_dinode); | ||
1281 | phys += start; | ||
1282 | if (start + len > size) | ||
1283 | len = size - start; | ||
1284 | if (start < size) | ||
1285 | ret = fiemap_fill_next_extent(fieinfo, start, phys, | ||
1286 | len, flags); | ||
1287 | if (ret == 1) | ||
1288 | ret = 0; | ||
1289 | } else { | ||
1290 | ret = __generic_block_fiemap(inode, fieinfo, start, len, | ||
1291 | gfs2_block_map); | ||
1292 | } | ||
1293 | |||
1294 | gfs2_glock_dq_uninit(&gh); | ||
1295 | out: | ||
1296 | mutex_unlock(&inode->i_mutex); | ||
1297 | return ret; | ||
1298 | } | ||
1299 | |||
1300 | const struct inode_operations gfs2_file_iops = { | ||
1301 | .permission = gfs2_permission, | ||
1302 | .setattr = gfs2_setattr, | ||
1303 | .getattr = gfs2_getattr, | ||
1304 | .setxattr = gfs2_setxattr, | ||
1305 | .getxattr = gfs2_getxattr, | ||
1306 | .listxattr = gfs2_listxattr, | ||
1307 | .removexattr = gfs2_removexattr, | ||
1308 | .fiemap = gfs2_fiemap, | ||
1309 | }; | ||
1310 | |||
1311 | const struct inode_operations gfs2_dir_iops = { | ||
1312 | .create = gfs2_create, | ||
1313 | .lookup = gfs2_lookup, | ||
1314 | .link = gfs2_link, | ||
1315 | .unlink = gfs2_unlink, | ||
1316 | .symlink = gfs2_symlink, | ||
1317 | .mkdir = gfs2_mkdir, | ||
1318 | .rmdir = gfs2_rmdir, | ||
1319 | .mknod = gfs2_mknod, | ||
1320 | .rename = gfs2_rename, | ||
1321 | .permission = gfs2_permission, | ||
1322 | .setattr = gfs2_setattr, | ||
1323 | .getattr = gfs2_getattr, | ||
1324 | .setxattr = gfs2_setxattr, | ||
1325 | .getxattr = gfs2_getxattr, | ||
1326 | .listxattr = gfs2_listxattr, | ||
1327 | .removexattr = gfs2_removexattr, | ||
1328 | .fiemap = gfs2_fiemap, | ||
1329 | }; | ||
1330 | |||
1331 | const struct inode_operations gfs2_symlink_iops = { | ||
1332 | .readlink = generic_readlink, | ||
1333 | .follow_link = gfs2_follow_link, | ||
1334 | .put_link = gfs2_put_link, | ||
1335 | .permission = gfs2_permission, | ||
1336 | .setattr = gfs2_setattr, | ||
1337 | .getattr = gfs2_getattr, | ||
1338 | .setxattr = gfs2_setxattr, | ||
1339 | .getxattr = gfs2_getxattr, | ||
1340 | .listxattr = gfs2_listxattr, | ||
1341 | .removexattr = gfs2_removexattr, | ||
1342 | .fiemap = gfs2_fiemap, | ||
1343 | }; | ||
1344 | |||
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index cf930cd9664a..7273ad3c85ba 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -78,10 +78,11 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
78 | 78 | ||
79 | static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1, | 79 | static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1, |
80 | unsigned char *buf2, unsigned int offset, | 80 | unsigned char *buf2, unsigned int offset, |
81 | unsigned int buflen, u32 block, | 81 | struct gfs2_bitmap *bi, u32 block, |
82 | unsigned char new_state) | 82 | unsigned char new_state) |
83 | { | 83 | { |
84 | unsigned char *byte1, *byte2, *end, cur_state; | 84 | unsigned char *byte1, *byte2, *end, cur_state; |
85 | unsigned int buflen = bi->bi_len; | ||
85 | const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; | 86 | const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; |
86 | 87 | ||
87 | byte1 = buf1 + offset + (block / GFS2_NBBY); | 88 | byte1 = buf1 + offset + (block / GFS2_NBBY); |
@@ -92,6 +93,16 @@ static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1, | |||
92 | cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; | 93 | cur_state = (*byte1 >> bit) & GFS2_BIT_MASK; |
93 | 94 | ||
94 | if (unlikely(!valid_change[new_state * 4 + cur_state])) { | 95 | if (unlikely(!valid_change[new_state * 4 + cur_state])) { |
96 | printk(KERN_WARNING "GFS2: buf_blk = 0x%llx old_state=%d, " | ||
97 | "new_state=%d\n", | ||
98 | (unsigned long long)block, cur_state, new_state); | ||
99 | printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%lx\n", | ||
100 | (unsigned long long)rgd->rd_addr, | ||
101 | (unsigned long)bi->bi_start); | ||
102 | printk(KERN_WARNING "GFS2: bi_offset=0x%lx bi_len=0x%lx\n", | ||
103 | (unsigned long)bi->bi_offset, | ||
104 | (unsigned long)bi->bi_len); | ||
105 | dump_stack(); | ||
95 | gfs2_consist_rgrpd(rgd); | 106 | gfs2_consist_rgrpd(rgd); |
96 | return; | 107 | return; |
97 | } | 108 | } |
@@ -381,6 +392,7 @@ static void clear_rgrpdi(struct gfs2_sbd *sdp) | |||
381 | 392 | ||
382 | if (gl) { | 393 | if (gl) { |
383 | gl->gl_object = NULL; | 394 | gl->gl_object = NULL; |
395 | gfs2_glock_add_to_lru(gl); | ||
384 | gfs2_glock_put(gl); | 396 | gfs2_glock_put(gl); |
385 | } | 397 | } |
386 | 398 | ||
@@ -945,7 +957,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 | 957 | /* rgblk_search can return a block < goal, so we need to |
946 | keep it marching forward. */ | 958 | keep it marching forward. */ |
947 | no_addr = block + rgd->rd_data0; | 959 | no_addr = block + rgd->rd_data0; |
948 | goal++; | 960 | goal = max(block + 1, goal + 1); |
949 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) | 961 | if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked) |
950 | continue; | 962 | continue; |
951 | if (no_addr == skip) | 963 | if (no_addr == skip) |
@@ -971,7 +983,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip | |||
971 | found++; | 983 | found++; |
972 | 984 | ||
973 | /* Limit reclaim to sensible number of tasks */ | 985 | /* Limit reclaim to sensible number of tasks */ |
974 | if (found > 2*NR_CPUS) | 986 | if (found > NR_CPUS) |
975 | return; | 987 | return; |
976 | } | 988 | } |
977 | 989 | ||
@@ -1365,7 +1377,7 @@ skip: | |||
1365 | 1377 | ||
1366 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1378 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1367 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1379 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1368 | bi->bi_len, blk, new_state); | 1380 | bi, blk, new_state); |
1369 | goal = blk; | 1381 | goal = blk; |
1370 | while (*n < elen) { | 1382 | while (*n < elen) { |
1371 | goal++; | 1383 | goal++; |
@@ -1375,7 +1387,7 @@ skip: | |||
1375 | GFS2_BLKST_FREE) | 1387 | GFS2_BLKST_FREE) |
1376 | break; | 1388 | break; |
1377 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1389 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1378 | bi->bi_len, goal, new_state); | 1390 | bi, goal, new_state); |
1379 | (*n)++; | 1391 | (*n)++; |
1380 | } | 1392 | } |
1381 | out: | 1393 | out: |
@@ -1432,7 +1444,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
1432 | } | 1444 | } |
1433 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1445 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1434 | gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset, | 1446 | gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset, |
1435 | bi->bi_len, buf_blk, new_state); | 1447 | bi, buf_blk, new_state); |
1436 | } | 1448 | } |
1437 | 1449 | ||
1438 | return rgd; | 1450 | return rgd; |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a4e23d68a398..ed540e7018be 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/time.h> | 23 | #include <linux/time.h> |
24 | #include <linux/wait.h> | 24 | #include <linux/wait.h> |
25 | #include <linux/writeback.h> | 25 | #include <linux/writeback.h> |
26 | #include <linux/backing-dev.h> | ||
26 | 27 | ||
27 | #include "gfs2.h" | 28 | #include "gfs2.h" |
28 | #include "incore.h" | 29 | #include "incore.h" |
@@ -700,11 +701,47 @@ void gfs2_unfreeze_fs(struct gfs2_sbd *sdp) | |||
700 | mutex_unlock(&sdp->sd_freeze_lock); | 701 | mutex_unlock(&sdp->sd_freeze_lock); |
701 | } | 702 | } |
702 | 703 | ||
704 | void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) | ||
705 | { | ||
706 | struct gfs2_dinode *str = buf; | ||
707 | |||
708 | str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
709 | str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); | ||
710 | str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); | ||
711 | str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); | ||
712 | str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); | ||
713 | str->di_mode = cpu_to_be32(ip->i_inode.i_mode); | ||
714 | str->di_uid = cpu_to_be32(ip->i_inode.i_uid); | ||
715 | str->di_gid = cpu_to_be32(ip->i_inode.i_gid); | ||
716 | str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); | ||
717 | str->di_size = cpu_to_be64(i_size_read(&ip->i_inode)); | ||
718 | str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); | ||
719 | str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | ||
720 | str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); | ||
721 | str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); | ||
722 | |||
723 | str->di_goal_meta = cpu_to_be64(ip->i_goal); | ||
724 | str->di_goal_data = cpu_to_be64(ip->i_goal); | ||
725 | str->di_generation = cpu_to_be64(ip->i_generation); | ||
726 | |||
727 | str->di_flags = cpu_to_be32(ip->i_diskflags); | ||
728 | str->di_height = cpu_to_be16(ip->i_height); | ||
729 | str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && | ||
730 | !(ip->i_diskflags & GFS2_DIF_EXHASH) ? | ||
731 | GFS2_FORMAT_DE : 0); | ||
732 | str->di_depth = cpu_to_be16(ip->i_depth); | ||
733 | str->di_entries = cpu_to_be32(ip->i_entries); | ||
734 | |||
735 | str->di_eattr = cpu_to_be64(ip->i_eattr); | ||
736 | str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); | ||
737 | str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec); | ||
738 | str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec); | ||
739 | } | ||
703 | 740 | ||
704 | /** | 741 | /** |
705 | * gfs2_write_inode - Make sure the inode is stable on the disk | 742 | * gfs2_write_inode - Make sure the inode is stable on the disk |
706 | * @inode: The inode | 743 | * @inode: The inode |
707 | * @sync: synchronous write flag | 744 | * @wbc: The writeback control structure |
708 | * | 745 | * |
709 | * Returns: errno | 746 | * Returns: errno |
710 | */ | 747 | */ |
@@ -713,15 +750,17 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
713 | { | 750 | { |
714 | struct gfs2_inode *ip = GFS2_I(inode); | 751 | struct gfs2_inode *ip = GFS2_I(inode); |
715 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 752 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
753 | struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); | ||
754 | struct backing_dev_info *bdi = metamapping->backing_dev_info; | ||
716 | struct gfs2_holder gh; | 755 | struct gfs2_holder gh; |
717 | struct buffer_head *bh; | 756 | struct buffer_head *bh; |
718 | struct timespec atime; | 757 | struct timespec atime; |
719 | struct gfs2_dinode *di; | 758 | struct gfs2_dinode *di; |
720 | int ret = 0; | 759 | int ret = -EAGAIN; |
721 | 760 | ||
722 | /* Check this is a "normal" inode, etc */ | 761 | /* Skip timestamp update, if this is from a memalloc */ |
723 | if (current->flags & PF_MEMALLOC) | 762 | if (current->flags & PF_MEMALLOC) |
724 | return 0; | 763 | goto do_flush; |
725 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 764 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
726 | if (ret) | 765 | if (ret) |
727 | goto do_flush; | 766 | goto do_flush; |
@@ -745,6 +784,13 @@ do_unlock: | |||
745 | do_flush: | 784 | do_flush: |
746 | if (wbc->sync_mode == WB_SYNC_ALL) | 785 | if (wbc->sync_mode == WB_SYNC_ALL) |
747 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); | 786 | gfs2_log_flush(GFS2_SB(inode), ip->i_gl); |
787 | filemap_fdatawrite(metamapping); | ||
788 | if (bdi->dirty_exceeded) | ||
789 | gfs2_ail1_flush(sdp, wbc); | ||
790 | if (!ret && (wbc->sync_mode == WB_SYNC_ALL)) | ||
791 | ret = filemap_fdatawait(metamapping); | ||
792 | if (ret) | ||
793 | mark_inode_dirty_sync(inode); | ||
748 | return ret; | 794 | return ret; |
749 | } | 795 | } |
750 | 796 | ||
@@ -874,8 +920,9 @@ restart: | |||
874 | 920 | ||
875 | static int gfs2_sync_fs(struct super_block *sb, int wait) | 921 | static int gfs2_sync_fs(struct super_block *sb, int wait) |
876 | { | 922 | { |
877 | if (wait && sb->s_fs_info) | 923 | struct gfs2_sbd *sdp = sb->s_fs_info; |
878 | gfs2_log_flush(sb->s_fs_info, NULL); | 924 | if (wait && sdp) |
925 | gfs2_log_flush(sdp, NULL); | ||
879 | return 0; | 926 | return 0; |
880 | } | 927 | } |
881 | 928 | ||
@@ -1308,6 +1355,78 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1308 | return 0; | 1355 | return 0; |
1309 | } | 1356 | } |
1310 | 1357 | ||
1358 | static void gfs2_final_release_pages(struct gfs2_inode *ip) | ||
1359 | { | ||
1360 | struct inode *inode = &ip->i_inode; | ||
1361 | struct gfs2_glock *gl = ip->i_gl; | ||
1362 | |||
1363 | truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0); | ||
1364 | truncate_inode_pages(&inode->i_data, 0); | ||
1365 | |||
1366 | if (atomic_read(&gl->gl_revokes) == 0) { | ||
1367 | clear_bit(GLF_LFLUSH, &gl->gl_flags); | ||
1368 | clear_bit(GLF_DIRTY, &gl->gl_flags); | ||
1369 | } | ||
1370 | } | ||
1371 | |||
1372 | static int gfs2_dinode_dealloc(struct gfs2_inode *ip) | ||
1373 | { | ||
1374 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1375 | struct gfs2_alloc *al; | ||
1376 | struct gfs2_rgrpd *rgd; | ||
1377 | int error; | ||
1378 | |||
1379 | if (gfs2_get_inode_blocks(&ip->i_inode) != 1) { | ||
1380 | gfs2_consist_inode(ip); | ||
1381 | return -EIO; | ||
1382 | } | ||
1383 | |||
1384 | al = gfs2_alloc_get(ip); | ||
1385 | if (!al) | ||
1386 | return -ENOMEM; | ||
1387 | |||
1388 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | ||
1389 | if (error) | ||
1390 | goto out; | ||
1391 | |||
1392 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1393 | if (error) | ||
1394 | goto out_qs; | ||
1395 | |||
1396 | rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); | ||
1397 | if (!rgd) { | ||
1398 | gfs2_consist_inode(ip); | ||
1399 | error = -EIO; | ||
1400 | goto out_rindex_relse; | ||
1401 | } | ||
1402 | |||
1403 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, | ||
1404 | &al->al_rgd_gh); | ||
1405 | if (error) | ||
1406 | goto out_rindex_relse; | ||
1407 | |||
1408 | error = gfs2_trans_begin(sdp, RES_RG_BIT + RES_STATFS + RES_QUOTA, | ||
1409 | sdp->sd_jdesc->jd_blocks); | ||
1410 | if (error) | ||
1411 | goto out_rg_gunlock; | ||
1412 | |||
1413 | gfs2_free_di(rgd, ip); | ||
1414 | |||
1415 | gfs2_final_release_pages(ip); | ||
1416 | |||
1417 | gfs2_trans_end(sdp); | ||
1418 | |||
1419 | out_rg_gunlock: | ||
1420 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | ||
1421 | out_rindex_relse: | ||
1422 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1423 | out_qs: | ||
1424 | gfs2_quota_unhold(ip); | ||
1425 | out: | ||
1426 | gfs2_alloc_put(ip); | ||
1427 | return error; | ||
1428 | } | ||
1429 | |||
1311 | /* | 1430 | /* |
1312 | * We have to (at the moment) hold the inodes main lock to cover | 1431 | * We have to (at the moment) hold the inodes main lock to cover |
1313 | * the gap between unlocking the shared lock on the iopen lock and | 1432 | * the gap between unlocking the shared lock on the iopen lock and |
@@ -1318,15 +1437,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1318 | 1437 | ||
1319 | static void gfs2_evict_inode(struct inode *inode) | 1438 | static void gfs2_evict_inode(struct inode *inode) |
1320 | { | 1439 | { |
1321 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 1440 | struct super_block *sb = inode->i_sb; |
1441 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
1322 | struct gfs2_inode *ip = GFS2_I(inode); | 1442 | struct gfs2_inode *ip = GFS2_I(inode); |
1323 | struct gfs2_holder gh; | 1443 | struct gfs2_holder gh; |
1324 | int error; | 1444 | int error; |
1325 | 1445 | ||
1326 | if (inode->i_nlink) | 1446 | if (inode->i_nlink || (sb->s_flags & MS_RDONLY)) |
1327 | goto out; | 1447 | goto out; |
1328 | 1448 | ||
1329 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1449 | /* Must not read inode block until block type has been verified */ |
1450 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); | ||
1330 | if (unlikely(error)) { | 1451 | if (unlikely(error)) { |
1331 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1452 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1332 | goto out; | 1453 | goto out; |
@@ -1336,6 +1457,12 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1336 | if (error) | 1457 | if (error) |
1337 | goto out_truncate; | 1458 | goto out_truncate; |
1338 | 1459 | ||
1460 | if (test_bit(GIF_INVALID, &ip->i_flags)) { | ||
1461 | error = gfs2_inode_refresh(ip); | ||
1462 | if (error) | ||
1463 | goto out_truncate; | ||
1464 | } | ||
1465 | |||
1339 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; | 1466 | ip->i_iopen_gh.gh_flags |= GL_NOCACHE; |
1340 | gfs2_glock_dq_wait(&ip->i_iopen_gh); | 1467 | 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); | 1468 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); |
@@ -1363,15 +1490,13 @@ static void gfs2_evict_inode(struct inode *inode) | |||
1363 | } | 1490 | } |
1364 | 1491 | ||
1365 | error = gfs2_dinode_dealloc(ip); | 1492 | error = gfs2_dinode_dealloc(ip); |
1366 | if (error) | 1493 | goto out_unlock; |
1367 | goto out_unlock; | ||
1368 | 1494 | ||
1369 | out_truncate: | 1495 | out_truncate: |
1370 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); | 1496 | error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); |
1371 | if (error) | 1497 | if (error) |
1372 | goto out_unlock; | 1498 | goto out_unlock; |
1373 | /* Needs to be done before glock release & also in a transaction */ | 1499 | gfs2_final_release_pages(ip); |
1374 | truncate_inode_pages(&inode->i_data, 0); | ||
1375 | gfs2_trans_end(sdp); | 1500 | gfs2_trans_end(sdp); |
1376 | 1501 | ||
1377 | out_unlock: | 1502 | out_unlock: |
@@ -1386,6 +1511,7 @@ out: | |||
1386 | end_writeback(inode); | 1511 | end_writeback(inode); |
1387 | 1512 | ||
1388 | ip->i_gl->gl_object = NULL; | 1513 | ip->i_gl->gl_object = NULL; |
1514 | gfs2_glock_add_to_lru(ip->i_gl); | ||
1389 | gfs2_glock_put(ip->i_gl); | 1515 | gfs2_glock_put(ip->i_gl); |
1390 | ip->i_gl = NULL; | 1516 | ip->i_gl = NULL; |
1391 | if (ip->i_iopen_gh.gh_gl) { | 1517 | if (ip->i_iopen_gh.gh_gl) { |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 748ccb557c18..e20eab37bc80 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -81,7 +81,8 @@ static int gfs2_uuid_valid(const u8 *uuid) | |||
81 | 81 | ||
82 | static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf) | 82 | static ssize_t uuid_show(struct gfs2_sbd *sdp, char *buf) |
83 | { | 83 | { |
84 | const u8 *uuid = sdp->sd_sb.sb_uuid; | 84 | struct super_block *s = sdp->sd_vfs; |
85 | const u8 *uuid = s->s_uuid; | ||
85 | buf[0] = '\0'; | 86 | buf[0] = '\0'; |
86 | if (!gfs2_uuid_valid(uuid)) | 87 | if (!gfs2_uuid_valid(uuid)) |
87 | return 0; | 88 | return 0; |
@@ -616,7 +617,8 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
616 | struct kobj_uevent_env *env) | 617 | struct kobj_uevent_env *env) |
617 | { | 618 | { |
618 | struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); | 619 | struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); |
619 | const u8 *uuid = sdp->sd_sb.sb_uuid; | 620 | struct super_block *s = sdp->sd_vfs; |
621 | const u8 *uuid = s->s_uuid; | ||
620 | 622 | ||
621 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); | 623 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); |
622 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); | 624 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); |
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h index cedb0bb96d96..5d07609ec57d 100644 --- a/fs/gfs2/trace_gfs2.h +++ b/fs/gfs2/trace_gfs2.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
11 | #include <linux/dlmconstants.h> | 11 | #include <linux/dlmconstants.h> |
12 | #include <linux/gfs2_ondisk.h> | 12 | #include <linux/gfs2_ondisk.h> |
13 | #include <linux/writeback.h> | ||
13 | #include "incore.h" | 14 | #include "incore.h" |
14 | #include "glock.h" | 15 | #include "glock.h" |
15 | 16 | ||
@@ -40,7 +41,9 @@ | |||
40 | {(1UL << GLF_REPLY_PENDING), "r" }, \ | 41 | {(1UL << GLF_REPLY_PENDING), "r" }, \ |
41 | {(1UL << GLF_INITIAL), "I" }, \ | 42 | {(1UL << GLF_INITIAL), "I" }, \ |
42 | {(1UL << GLF_FROZEN), "F" }, \ | 43 | {(1UL << GLF_FROZEN), "F" }, \ |
43 | {(1UL << GLF_QUEUED), "q" }) | 44 | {(1UL << GLF_QUEUED), "q" }, \ |
45 | {(1UL << GLF_LRU), "L" }, \ | ||
46 | {(1UL << GLF_OBJECT), "o" }) | ||
44 | 47 | ||
45 | #ifndef NUMPTY | 48 | #ifndef NUMPTY |
46 | #define NUMPTY | 49 | #define NUMPTY |
@@ -94,7 +97,7 @@ TRACE_EVENT(gfs2_glock_state_change, | |||
94 | __entry->new_state = glock_trace_state(new_state); | 97 | __entry->new_state = glock_trace_state(new_state); |
95 | __entry->tgt_state = glock_trace_state(gl->gl_target); | 98 | __entry->tgt_state = glock_trace_state(gl->gl_target); |
96 | __entry->dmt_state = glock_trace_state(gl->gl_demote_state); | 99 | __entry->dmt_state = glock_trace_state(gl->gl_demote_state); |
97 | __entry->flags = gl->gl_flags; | 100 | __entry->flags = gl->gl_flags | (gl->gl_object ? (1UL<<GLF_OBJECT) : 0); |
98 | ), | 101 | ), |
99 | 102 | ||
100 | TP_printk("%u,%u glock %d:%lld state %s to %s tgt:%s dmt:%s flags:%s", | 103 | TP_printk("%u,%u glock %d:%lld state %s to %s tgt:%s dmt:%s flags:%s", |
@@ -127,7 +130,7 @@ TRACE_EVENT(gfs2_glock_put, | |||
127 | __entry->gltype = gl->gl_name.ln_type; | 130 | __entry->gltype = gl->gl_name.ln_type; |
128 | __entry->glnum = gl->gl_name.ln_number; | 131 | __entry->glnum = gl->gl_name.ln_number; |
129 | __entry->cur_state = glock_trace_state(gl->gl_state); | 132 | __entry->cur_state = glock_trace_state(gl->gl_state); |
130 | __entry->flags = gl->gl_flags; | 133 | __entry->flags = gl->gl_flags | (gl->gl_object ? (1UL<<GLF_OBJECT) : 0); |
131 | ), | 134 | ), |
132 | 135 | ||
133 | TP_printk("%u,%u glock %d:%lld state %s => %s flags:%s", | 136 | TP_printk("%u,%u glock %d:%lld state %s => %s flags:%s", |
@@ -161,7 +164,7 @@ TRACE_EVENT(gfs2_demote_rq, | |||
161 | __entry->glnum = gl->gl_name.ln_number; | 164 | __entry->glnum = gl->gl_name.ln_number; |
162 | __entry->cur_state = glock_trace_state(gl->gl_state); | 165 | __entry->cur_state = glock_trace_state(gl->gl_state); |
163 | __entry->dmt_state = glock_trace_state(gl->gl_demote_state); | 166 | __entry->dmt_state = glock_trace_state(gl->gl_demote_state); |
164 | __entry->flags = gl->gl_flags; | 167 | __entry->flags = gl->gl_flags | (gl->gl_object ? (1UL<<GLF_OBJECT) : 0); |
165 | ), | 168 | ), |
166 | 169 | ||
167 | TP_printk("%u,%u glock %d:%lld demote %s to %s flags:%s", | 170 | TP_printk("%u,%u glock %d:%lld demote %s to %s flags:%s", |
@@ -318,6 +321,33 @@ TRACE_EVENT(gfs2_log_blocks, | |||
318 | MINOR(__entry->dev), __entry->blocks) | 321 | MINOR(__entry->dev), __entry->blocks) |
319 | ); | 322 | ); |
320 | 323 | ||
324 | /* Writing back the AIL */ | ||
325 | TRACE_EVENT(gfs2_ail_flush, | ||
326 | |||
327 | TP_PROTO(const struct gfs2_sbd *sdp, const struct writeback_control *wbc, int start), | ||
328 | |||
329 | TP_ARGS(sdp, wbc, start), | ||
330 | |||
331 | TP_STRUCT__entry( | ||
332 | __field( dev_t, dev ) | ||
333 | __field( int, start ) | ||
334 | __field( int, sync_mode ) | ||
335 | __field( long, nr_to_write ) | ||
336 | ), | ||
337 | |||
338 | TP_fast_assign( | ||
339 | __entry->dev = sdp->sd_vfs->s_dev; | ||
340 | __entry->start = start; | ||
341 | __entry->sync_mode = wbc->sync_mode; | ||
342 | __entry->nr_to_write = wbc->nr_to_write; | ||
343 | ), | ||
344 | |||
345 | TP_printk("%u,%u ail flush %s %s %ld", MAJOR(__entry->dev), | ||
346 | MINOR(__entry->dev), __entry->start ? "start" : "end", | ||
347 | __entry->sync_mode == WB_SYNC_ALL ? "all" : "none", | ||
348 | __entry->nr_to_write) | ||
349 | ); | ||
350 | |||
321 | /* Section 3 - bmap | 351 | /* Section 3 - bmap |
322 | * | 352 | * |
323 | * Objectives: | 353 | * Objectives: |
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/inode.c b/fs/inode.c index 33c963d08ab4..05f4fa521325 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mount.h> | 24 | #include <linux/mount.h> |
25 | #include <linux/async.h> | 25 | #include <linux/async.h> |
26 | #include <linux/posix_acl.h> | 26 | #include <linux/posix_acl.h> |
27 | #include <linux/prefetch.h> | ||
27 | #include <linux/ima.h> | 28 | #include <linux/ima.h> |
28 | #include <linux/cred.h> | 29 | #include <linux/cred.h> |
29 | #include "internal.h" | 30 | #include "internal.h" |
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 1adc8d455f0e..df0de27c2733 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
12 | #include <linux/gfp.h> | 12 | #include <linux/gfp.h> |
13 | #include <linux/prefetch.h> | ||
13 | 14 | ||
14 | #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) | 15 | #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) |
15 | 16 | ||
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..6ff858c049c0 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 | ||
@@ -1378,12 +1378,12 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) | |||
1378 | { | 1378 | { |
1379 | int res; | 1379 | int res; |
1380 | 1380 | ||
1381 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); | ||
1382 | if (unlikely(current->link_count >= MAX_NESTED_LINKS)) { | 1381 | if (unlikely(current->link_count >= MAX_NESTED_LINKS)) { |
1383 | path_put_conditional(path, nd); | 1382 | path_put_conditional(path, nd); |
1384 | path_put(&nd->path); | 1383 | path_put(&nd->path); |
1385 | return -ELOOP; | 1384 | return -ELOOP; |
1386 | } | 1385 | } |
1386 | BUG_ON(nd->depth >= MAX_NESTED_LINKS); | ||
1387 | 1387 | ||
1388 | nd->depth++; | 1388 | nd->depth++; |
1389 | current->link_count++; | 1389 | current->link_count++; |
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/partitions/ldm.c b/fs/partitions/ldm.c index ce4f62440425..a29d5ccf3d54 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c | |||
@@ -1335,6 +1335,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags) | |||
1335 | 1335 | ||
1336 | list_add_tail (&f->list, frags); | 1336 | list_add_tail (&f->list, frags); |
1337 | found: | 1337 | found: |
1338 | if (rec >= f->num) { | ||
1339 | ldm_error("REC value (%d) exceeds NUM value (%d)", rec, f->num); | ||
1340 | return false; | ||
1341 | } | ||
1342 | |||
1338 | if (f->map & (1 << rec)) { | 1343 | if (f->map & (1 << rec)) { |
1339 | ldm_error ("Duplicate VBLK, part %d.", rec); | 1344 | ldm_error ("Duplicate VBLK, part %d.", rec); |
1340 | f->map &= 0x7F; /* Mark the group as broken */ | 1345 | f->map &= 0x7F; /* Mark the group as broken */ |
diff --git a/fs/proc/base.c b/fs/proc/base.c index dd6628d3ba42..dfa532730e55 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -3124,11 +3124,16 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi | |||
3124 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 3124 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
3125 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 3125 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) |
3126 | { | 3126 | { |
3127 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 3127 | unsigned int nr; |
3128 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 3128 | struct task_struct *reaper; |
3129 | struct tgid_iter iter; | 3129 | struct tgid_iter iter; |
3130 | struct pid_namespace *ns; | 3130 | struct pid_namespace *ns; |
3131 | 3131 | ||
3132 | if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) | ||
3133 | goto out_no_task; | ||
3134 | nr = filp->f_pos - FIRST_PROCESS_ENTRY; | ||
3135 | |||
3136 | reaper = get_proc_task(filp->f_path.dentry->d_inode); | ||
3132 | if (!reaper) | 3137 | if (!reaper) |
3133 | goto out_no_task; | 3138 | goto out_no_task; |
3134 | 3139 | ||
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/pstore/platform.c b/fs/pstore/platform.c index f835a25625ff..f2c3ff20ea68 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
@@ -152,21 +152,27 @@ EXPORT_SYMBOL_GPL(pstore_register); | |||
152 | void pstore_get_records(void) | 152 | void pstore_get_records(void) |
153 | { | 153 | { |
154 | struct pstore_info *psi = psinfo; | 154 | struct pstore_info *psi = psinfo; |
155 | size_t size; | 155 | ssize_t size; |
156 | u64 id; | 156 | u64 id; |
157 | enum pstore_type_id type; | 157 | enum pstore_type_id type; |
158 | struct timespec time; | 158 | struct timespec time; |
159 | int failed = 0; | 159 | int failed = 0, rc; |
160 | 160 | ||
161 | if (!psi) | 161 | if (!psi) |
162 | return; | 162 | return; |
163 | 163 | ||
164 | mutex_lock(&psinfo->buf_mutex); | 164 | mutex_lock(&psinfo->buf_mutex); |
165 | rc = psi->open(psi); | ||
166 | if (rc) | ||
167 | goto out; | ||
168 | |||
165 | while ((size = psi->read(&id, &type, &time)) > 0) { | 169 | while ((size = psi->read(&id, &type, &time)) > 0) { |
166 | if (pstore_mkfile(type, psi->name, id, psi->buf, size, | 170 | if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, |
167 | time, psi->erase)) | 171 | time, psi->erase)) |
168 | failed++; | 172 | failed++; |
169 | } | 173 | } |
174 | psi->close(psi); | ||
175 | out: | ||
170 | mutex_unlock(&psinfo->buf_mutex); | 176 | mutex_unlock(&psinfo->buf_mutex); |
171 | 177 | ||
172 | if (failed) | 178 | if (failed) |
diff --git a/fs/super.c b/fs/super.c index 8a06881b1920..c04f7e0b7ed2 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -948,8 +948,7 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) | |||
948 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | 948 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE |
949 | * but s_maxbytes was an unsigned long long for many releases. Throw | 949 | * but s_maxbytes was an unsigned long long for many releases. Throw |
950 | * this warning for a little while to try and catch filesystems that | 950 | * this warning for a little while to try and catch filesystems that |
951 | * violate this rule. This warning should be either removed or | 951 | * violate this rule. |
952 | * converted to a BUG() in 2.6.34. | ||
953 | */ | 952 | */ |
954 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " | 953 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " |
955 | "negative value (%lld)\n", type->name, sb->s_maxbytes); | 954 | "negative value (%lld)\n", type->name, sb->s_maxbytes); |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index da3fefe91a8f..1ad8c93c1b85 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -24,13 +24,6 @@ | |||
24 | 24 | ||
25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
26 | 26 | ||
27 | /* used in crash dumps to help with debugging */ | ||
28 | static char last_sysfs_file[PATH_MAX]; | ||
29 | void sysfs_printk_last_file(void) | ||
30 | { | ||
31 | printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file); | ||
32 | } | ||
33 | |||
34 | /* | 27 | /* |
35 | * There's one sysfs_buffer for each open file and one | 28 | * There's one sysfs_buffer for each open file and one |
36 | * sysfs_open_dirent for each sysfs_dirent with one or more open | 29 | * sysfs_open_dirent for each sysfs_dirent with one or more open |
@@ -337,11 +330,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
337 | struct sysfs_buffer *buffer; | 330 | struct sysfs_buffer *buffer; |
338 | const struct sysfs_ops *ops; | 331 | const struct sysfs_ops *ops; |
339 | int error = -EACCES; | 332 | int error = -EACCES; |
340 | char *p; | ||
341 | |||
342 | p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file)); | ||
343 | if (!IS_ERR(p)) | ||
344 | memmove(last_sysfs_file, p, strlen(p) + 1); | ||
345 | 333 | ||
346 | /* need attr_sd for attr and ops, its parent for kobj */ | 334 | /* need attr_sd for attr and ops, its parent for kobj */ |
347 | if (!sysfs_get_active(attr_sd)) | 335 | if (!sysfs_get_active(attr_sd)) |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index c8769dc222d8..194414f8298c 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -101,9 +101,9 @@ int sysfs_create_group(struct kobject *kobj, | |||
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * sysfs_update_group - given a directory kobject, create an attribute group | 104 | * sysfs_update_group - given a directory kobject, update an attribute group |
105 | * @kobj: The kobject to create the group on | 105 | * @kobj: The kobject to update the group on |
106 | * @grp: The attribute group to create | 106 | * @grp: The attribute group to update |
107 | * | 107 | * |
108 | * This function updates an attribute group. Unlike | 108 | * This function updates an attribute group. Unlike |
109 | * sysfs_create_group(), it will explicitly not warn or error if any | 109 | * sysfs_create_group(), it will explicitly not warn or error if any |
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 | } |