0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/fs.h>
0035 #include <linux/vfs.h>
0036 #include <linux/slab.h>
0037 #include <linux/vmalloc.h>
0038 #include <linux/sched.h>
0039 #include <linux/spinlock.h>
0040 #include <linux/wait.h>
0041 #include <linux/pagemap.h>
0042
0043 #include "squashfs_fs.h"
0044 #include "squashfs_fs_sb.h"
0045 #include "squashfs.h"
0046 #include "page_actor.h"
0047
0048
0049
0050
0051
0052 struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
0053 struct squashfs_cache *cache, u64 block, int length)
0054 {
0055 int i, n;
0056 struct squashfs_cache_entry *entry;
0057
0058 spin_lock(&cache->lock);
0059
0060 while (1) {
0061 for (i = cache->curr_blk, n = 0; n < cache->entries; n++) {
0062 if (cache->entry[i].block == block) {
0063 cache->curr_blk = i;
0064 break;
0065 }
0066 i = (i + 1) % cache->entries;
0067 }
0068
0069 if (n == cache->entries) {
0070
0071
0072
0073
0074 if (cache->unused == 0) {
0075 cache->num_waiters++;
0076 spin_unlock(&cache->lock);
0077 wait_event(cache->wait_queue, cache->unused);
0078 spin_lock(&cache->lock);
0079 cache->num_waiters--;
0080 continue;
0081 }
0082
0083
0084
0085
0086
0087
0088 i = cache->next_blk;
0089 for (n = 0; n < cache->entries; n++) {
0090 if (cache->entry[i].refcount == 0)
0091 break;
0092 i = (i + 1) % cache->entries;
0093 }
0094
0095 cache->next_blk = (i + 1) % cache->entries;
0096 entry = &cache->entry[i];
0097
0098
0099
0100
0101
0102 cache->unused--;
0103 entry->block = block;
0104 entry->refcount = 1;
0105 entry->pending = 1;
0106 entry->num_waiters = 0;
0107 entry->error = 0;
0108 spin_unlock(&cache->lock);
0109
0110 entry->length = squashfs_read_data(sb, block, length,
0111 &entry->next_index, entry->actor);
0112
0113 spin_lock(&cache->lock);
0114
0115 if (entry->length < 0)
0116 entry->error = entry->length;
0117
0118 entry->pending = 0;
0119
0120
0121
0122
0123
0124
0125 if (entry->num_waiters) {
0126 spin_unlock(&cache->lock);
0127 wake_up_all(&entry->wait_queue);
0128 } else
0129 spin_unlock(&cache->lock);
0130
0131 goto out;
0132 }
0133
0134
0135
0136
0137
0138
0139
0140 entry = &cache->entry[i];
0141 if (entry->refcount == 0)
0142 cache->unused--;
0143 entry->refcount++;
0144
0145
0146
0147
0148
0149 if (entry->pending) {
0150 entry->num_waiters++;
0151 spin_unlock(&cache->lock);
0152 wait_event(entry->wait_queue, !entry->pending);
0153 } else
0154 spin_unlock(&cache->lock);
0155
0156 goto out;
0157 }
0158
0159 out:
0160 TRACE("Got %s %d, start block %lld, refcount %d, error %d\n",
0161 cache->name, i, entry->block, entry->refcount, entry->error);
0162
0163 if (entry->error)
0164 ERROR("Unable to read %s cache entry [%llx]\n", cache->name,
0165 block);
0166 return entry;
0167 }
0168
0169
0170
0171
0172
0173 void squashfs_cache_put(struct squashfs_cache_entry *entry)
0174 {
0175 struct squashfs_cache *cache = entry->cache;
0176
0177 spin_lock(&cache->lock);
0178 entry->refcount--;
0179 if (entry->refcount == 0) {
0180 cache->unused++;
0181
0182
0183
0184
0185 if (cache->num_waiters) {
0186 spin_unlock(&cache->lock);
0187 wake_up(&cache->wait_queue);
0188 return;
0189 }
0190 }
0191 spin_unlock(&cache->lock);
0192 }
0193
0194
0195
0196
0197 void squashfs_cache_delete(struct squashfs_cache *cache)
0198 {
0199 int i, j;
0200
0201 if (cache == NULL)
0202 return;
0203
0204 for (i = 0; i < cache->entries; i++) {
0205 if (cache->entry[i].data) {
0206 for (j = 0; j < cache->pages; j++)
0207 kfree(cache->entry[i].data[j]);
0208 kfree(cache->entry[i].data);
0209 }
0210 kfree(cache->entry[i].actor);
0211 }
0212
0213 kfree(cache->entry);
0214 kfree(cache);
0215 }
0216
0217
0218
0219
0220
0221
0222
0223 struct squashfs_cache *squashfs_cache_init(char *name, int entries,
0224 int block_size)
0225 {
0226 int i, j;
0227 struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
0228
0229 if (cache == NULL) {
0230 ERROR("Failed to allocate %s cache\n", name);
0231 return NULL;
0232 }
0233
0234 cache->entry = kcalloc(entries, sizeof(*(cache->entry)), GFP_KERNEL);
0235 if (cache->entry == NULL) {
0236 ERROR("Failed to allocate %s cache\n", name);
0237 goto cleanup;
0238 }
0239
0240 cache->curr_blk = 0;
0241 cache->next_blk = 0;
0242 cache->unused = entries;
0243 cache->entries = entries;
0244 cache->block_size = block_size;
0245 cache->pages = block_size >> PAGE_SHIFT;
0246 cache->pages = cache->pages ? cache->pages : 1;
0247 cache->name = name;
0248 cache->num_waiters = 0;
0249 spin_lock_init(&cache->lock);
0250 init_waitqueue_head(&cache->wait_queue);
0251
0252 for (i = 0; i < entries; i++) {
0253 struct squashfs_cache_entry *entry = &cache->entry[i];
0254
0255 init_waitqueue_head(&cache->entry[i].wait_queue);
0256 entry->cache = cache;
0257 entry->block = SQUASHFS_INVALID_BLK;
0258 entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
0259 if (entry->data == NULL) {
0260 ERROR("Failed to allocate %s cache entry\n", name);
0261 goto cleanup;
0262 }
0263
0264 for (j = 0; j < cache->pages; j++) {
0265 entry->data[j] = kmalloc(PAGE_SIZE, GFP_KERNEL);
0266 if (entry->data[j] == NULL) {
0267 ERROR("Failed to allocate %s buffer\n", name);
0268 goto cleanup;
0269 }
0270 }
0271
0272 entry->actor = squashfs_page_actor_init(entry->data,
0273 cache->pages, 0);
0274 if (entry->actor == NULL) {
0275 ERROR("Failed to allocate %s cache entry\n", name);
0276 goto cleanup;
0277 }
0278 }
0279
0280 return cache;
0281
0282 cleanup:
0283 squashfs_cache_delete(cache);
0284 return NULL;
0285 }
0286
0287
0288
0289
0290
0291
0292
0293 int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry,
0294 int offset, int length)
0295 {
0296 int remaining = length;
0297
0298 if (length == 0)
0299 return 0;
0300 else if (buffer == NULL)
0301 return min(length, entry->length - offset);
0302
0303 while (offset < entry->length) {
0304 void *buff = entry->data[offset / PAGE_SIZE]
0305 + (offset % PAGE_SIZE);
0306 int bytes = min_t(int, entry->length - offset,
0307 PAGE_SIZE - (offset % PAGE_SIZE));
0308
0309 if (bytes >= remaining) {
0310 memcpy(buffer, buff, remaining);
0311 remaining = 0;
0312 break;
0313 }
0314
0315 memcpy(buffer, buff, bytes);
0316 buffer += bytes;
0317 remaining -= bytes;
0318 offset += bytes;
0319 }
0320
0321 return length - remaining;
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331 int squashfs_read_metadata(struct super_block *sb, void *buffer,
0332 u64 *block, int *offset, int length)
0333 {
0334 struct squashfs_sb_info *msblk = sb->s_fs_info;
0335 int bytes, res = length;
0336 struct squashfs_cache_entry *entry;
0337
0338 TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
0339
0340 if (unlikely(length < 0))
0341 return -EIO;
0342
0343 while (length) {
0344 entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
0345 if (entry->error) {
0346 res = entry->error;
0347 goto error;
0348 } else if (*offset >= entry->length) {
0349 res = -EIO;
0350 goto error;
0351 }
0352
0353 bytes = squashfs_copy_data(buffer, entry, *offset, length);
0354 if (buffer)
0355 buffer += bytes;
0356 length -= bytes;
0357 *offset += bytes;
0358
0359 if (*offset == entry->length) {
0360 *block = entry->next_index;
0361 *offset = 0;
0362 }
0363
0364 squashfs_cache_put(entry);
0365 }
0366
0367 return res;
0368
0369 error:
0370 squashfs_cache_put(entry);
0371 return res;
0372 }
0373
0374
0375
0376
0377
0378
0379 struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *sb,
0380 u64 start_block, int length)
0381 {
0382 struct squashfs_sb_info *msblk = sb->s_fs_info;
0383
0384 return squashfs_cache_get(sb, msblk->fragment_cache, start_block,
0385 length);
0386 }
0387
0388
0389
0390
0391
0392
0393
0394 struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
0395 u64 start_block, int length)
0396 {
0397 struct squashfs_sb_info *msblk = sb->s_fs_info;
0398
0399 return squashfs_cache_get(sb, msblk->read_page, start_block, length);
0400 }
0401
0402
0403
0404
0405
0406 void *squashfs_read_table(struct super_block *sb, u64 block, int length)
0407 {
0408 int pages = (length + PAGE_SIZE - 1) >> PAGE_SHIFT;
0409 int i, res;
0410 void *table, *buffer, **data;
0411 struct squashfs_page_actor *actor;
0412
0413 table = buffer = kmalloc(length, GFP_KERNEL);
0414 if (table == NULL)
0415 return ERR_PTR(-ENOMEM);
0416
0417 data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
0418 if (data == NULL) {
0419 res = -ENOMEM;
0420 goto failed;
0421 }
0422
0423 actor = squashfs_page_actor_init(data, pages, length);
0424 if (actor == NULL) {
0425 res = -ENOMEM;
0426 goto failed2;
0427 }
0428
0429 for (i = 0; i < pages; i++, buffer += PAGE_SIZE)
0430 data[i] = buffer;
0431
0432 res = squashfs_read_data(sb, block, length |
0433 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, actor);
0434
0435 kfree(data);
0436 kfree(actor);
0437
0438 if (res < 0)
0439 goto failed;
0440
0441 return table;
0442
0443 failed2:
0444 kfree(data);
0445 failed:
0446 kfree(table);
0447 return ERR_PTR(res);
0448 }