diff options
Diffstat (limited to 'fs/ntfs/inode.c')
| -rw-r--r-- | fs/ntfs/inode.c | 514 |
1 files changed, 473 insertions, 41 deletions
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 7ec045131808..b24f4c4b2c5c 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "debug.h" | 30 | #include "debug.h" |
| 31 | #include "inode.h" | 31 | #include "inode.h" |
| 32 | #include "attrib.h" | 32 | #include "attrib.h" |
| 33 | #include "lcnalloc.h" | ||
| 33 | #include "malloc.h" | 34 | #include "malloc.h" |
| 34 | #include "mft.h" | 35 | #include "mft.h" |
| 35 | #include "time.h" | 36 | #include "time.h" |
| @@ -2291,11 +2292,16 @@ int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt) | |||
| 2291 | 2292 | ||
| 2292 | #ifdef NTFS_RW | 2293 | #ifdef NTFS_RW |
| 2293 | 2294 | ||
| 2295 | static const char *es = " Leaving inconsistent metadata. Unmount and run " | ||
| 2296 | "chkdsk."; | ||
| 2297 | |||
| 2294 | /** | 2298 | /** |
| 2295 | * ntfs_truncate - called when the i_size of an ntfs inode is changed | 2299 | * ntfs_truncate - called when the i_size of an ntfs inode is changed |
| 2296 | * @vi: inode for which the i_size was changed | 2300 | * @vi: inode for which the i_size was changed |
| 2297 | * | 2301 | * |
| 2298 | * We do not support i_size changes yet. | 2302 | * We only support i_size changes for normal files at present, i.e. not |
| 2303 | * compressed and not encrypted. This is enforced in ntfs_setattr(), see | ||
| 2304 | * below. | ||
| 2299 | * | 2305 | * |
| 2300 | * The kernel guarantees that @vi is a regular file (S_ISREG() is true) and | 2306 | * The kernel guarantees that @vi is a regular file (S_ISREG() is true) and |
| 2301 | * that the change is allowed. | 2307 | * that the change is allowed. |
| @@ -2306,80 +2312,499 @@ int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt) | |||
| 2306 | * Returns 0 on success or -errno on error. | 2312 | * Returns 0 on success or -errno on error. |
| 2307 | * | 2313 | * |
| 2308 | * Called with ->i_sem held. In all but one case ->i_alloc_sem is held for | 2314 | * Called with ->i_sem held. In all but one case ->i_alloc_sem is held for |
| 2309 | * writing. The only case where ->i_alloc_sem is not held is | 2315 | * writing. The only case in the kernel where ->i_alloc_sem is not held is |
| 2310 | * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called | 2316 | * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called |
| 2311 | * with the current i_size as the offset which means that it is a noop as far | 2317 | * with the current i_size as the offset. The analogous place in NTFS is in |
| 2312 | * as ntfs_truncate() is concerned. | 2318 | * fs/ntfs/file.c::ntfs_file_buffered_write() where we call vmtruncate() again |
| 2319 | * without holding ->i_alloc_sem. | ||
| 2313 | */ | 2320 | */ |
| 2314 | int ntfs_truncate(struct inode *vi) | 2321 | int ntfs_truncate(struct inode *vi) |
| 2315 | { | 2322 | { |
| 2316 | ntfs_inode *ni = NTFS_I(vi); | 2323 | s64 new_size, old_size, nr_freed, new_alloc_size, old_alloc_size; |
| 2324 | VCN highest_vcn; | ||
| 2325 | unsigned long flags; | ||
| 2326 | ntfs_inode *base_ni, *ni = NTFS_I(vi); | ||
| 2317 | ntfs_volume *vol = ni->vol; | 2327 | ntfs_volume *vol = ni->vol; |
| 2318 | ntfs_attr_search_ctx *ctx; | 2328 | ntfs_attr_search_ctx *ctx; |
| 2319 | MFT_RECORD *m; | 2329 | MFT_RECORD *m; |
| 2320 | ATTR_RECORD *a; | 2330 | ATTR_RECORD *a; |
| 2321 | const char *te = " Leaving file length out of sync with i_size."; | 2331 | const char *te = " Leaving file length out of sync with i_size."; |
| 2322 | int err; | 2332 | int err, mp_size, size_change, alloc_change; |
| 2333 | u32 attr_len; | ||
| 2323 | 2334 | ||
| 2324 | ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); | 2335 | ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); |
| 2325 | BUG_ON(NInoAttr(ni)); | 2336 | BUG_ON(NInoAttr(ni)); |
| 2337 | BUG_ON(S_ISDIR(vi->i_mode)); | ||
| 2338 | BUG_ON(NInoMstProtected(ni)); | ||
| 2326 | BUG_ON(ni->nr_extents < 0); | 2339 | BUG_ON(ni->nr_extents < 0); |
| 2327 | m = map_mft_record(ni); | 2340 | retry_truncate: |
| 2341 | /* | ||
| 2342 | * Lock the runlist for writing and map the mft record to ensure it is | ||
| 2343 | * safe to mess with the attribute runlist and sizes. | ||
| 2344 | */ | ||
| 2345 | down_write(&ni->runlist.lock); | ||
| 2346 | if (!NInoAttr(ni)) | ||
| 2347 | base_ni = ni; | ||
| 2348 | else | ||
| 2349 | base_ni = ni->ext.base_ntfs_ino; | ||
| 2350 | m = map_mft_record(base_ni); | ||
| 2328 | if (IS_ERR(m)) { | 2351 | if (IS_ERR(m)) { |
| 2329 | err = PTR_ERR(m); | 2352 | err = PTR_ERR(m); |
| 2330 | ntfs_error(vi->i_sb, "Failed to map mft record for inode 0x%lx " | 2353 | ntfs_error(vi->i_sb, "Failed to map mft record for inode 0x%lx " |
| 2331 | "(error code %d).%s", vi->i_ino, err, te); | 2354 | "(error code %d).%s", vi->i_ino, err, te); |
| 2332 | ctx = NULL; | 2355 | ctx = NULL; |
| 2333 | m = NULL; | 2356 | m = NULL; |
| 2334 | goto err_out; | 2357 | goto old_bad_out; |
| 2335 | } | 2358 | } |
| 2336 | ctx = ntfs_attr_get_search_ctx(ni, m); | 2359 | ctx = ntfs_attr_get_search_ctx(base_ni, m); |
| 2337 | if (unlikely(!ctx)) { | 2360 | if (unlikely(!ctx)) { |
| 2338 | ntfs_error(vi->i_sb, "Failed to allocate a search context for " | 2361 | ntfs_error(vi->i_sb, "Failed to allocate a search context for " |
| 2339 | "inode 0x%lx (not enough memory).%s", | 2362 | "inode 0x%lx (not enough memory).%s", |
| 2340 | vi->i_ino, te); | 2363 | vi->i_ino, te); |
| 2341 | err = -ENOMEM; | 2364 | err = -ENOMEM; |
| 2342 | goto err_out; | 2365 | goto old_bad_out; |
| 2343 | } | 2366 | } |
| 2344 | err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, | 2367 | err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, |
| 2345 | CASE_SENSITIVE, 0, NULL, 0, ctx); | 2368 | CASE_SENSITIVE, 0, NULL, 0, ctx); |
| 2346 | if (unlikely(err)) { | 2369 | if (unlikely(err)) { |
| 2347 | if (err == -ENOENT) | 2370 | if (err == -ENOENT) { |
| 2348 | ntfs_error(vi->i_sb, "Open attribute is missing from " | 2371 | ntfs_error(vi->i_sb, "Open attribute is missing from " |
| 2349 | "mft record. Inode 0x%lx is corrupt. " | 2372 | "mft record. Inode 0x%lx is corrupt. " |
| 2350 | "Run chkdsk.", vi->i_ino); | 2373 | "Run chkdsk.%s", vi->i_ino, te); |
| 2351 | else | 2374 | err = -EIO; |
| 2375 | } else | ||
| 2352 | ntfs_error(vi->i_sb, "Failed to lookup attribute in " | 2376 | ntfs_error(vi->i_sb, "Failed to lookup attribute in " |
| 2353 | "inode 0x%lx (error code %d).", | 2377 | "inode 0x%lx (error code %d).%s", |
| 2354 | vi->i_ino, err); | 2378 | vi->i_ino, err, te); |
| 2355 | goto err_out; | 2379 | goto old_bad_out; |
| 2356 | } | 2380 | } |
| 2381 | m = ctx->mrec; | ||
| 2357 | a = ctx->attr; | 2382 | a = ctx->attr; |
| 2358 | /* If the size has not changed there is nothing to do. */ | 2383 | /* |
| 2359 | if (ntfs_attr_size(a) == i_size_read(vi)) | 2384 | * The i_size of the vfs inode is the new size for the attribute value. |
| 2360 | goto done; | 2385 | */ |
| 2361 | // TODO: Implement the truncate... | 2386 | new_size = i_size_read(vi); |
| 2362 | ntfs_error(vi->i_sb, "Inode size has changed but this is not " | 2387 | /* The current size of the attribute value is the old size. */ |
| 2363 | "implemented yet. Resetting inode size to old value. " | 2388 | old_size = ntfs_attr_size(a); |
| 2364 | " This is most likely a bug in the ntfs driver!"); | 2389 | /* Calculate the new allocated size. */ |
| 2365 | i_size_write(vi, ntfs_attr_size(a)); | 2390 | if (NInoNonResident(ni)) |
| 2366 | done: | 2391 | new_alloc_size = (new_size + vol->cluster_size - 1) & |
| 2392 | ~(s64)vol->cluster_size_mask; | ||
| 2393 | else | ||
| 2394 | new_alloc_size = (new_size + 7) & ~7; | ||
| 2395 | /* The current allocated size is the old allocated size. */ | ||
| 2396 | read_lock_irqsave(&ni->size_lock, flags); | ||
| 2397 | old_alloc_size = ni->allocated_size; | ||
| 2398 | read_unlock_irqrestore(&ni->size_lock, flags); | ||
| 2399 | /* | ||
| 2400 | * The change in the file size. This will be 0 if no change, >0 if the | ||
| 2401 | * size is growing, and <0 if the size is shrinking. | ||
| 2402 | */ | ||
| 2403 | size_change = -1; | ||
| 2404 | if (new_size - old_size >= 0) { | ||
| 2405 | size_change = 1; | ||
| 2406 | if (new_size == old_size) | ||
| 2407 | size_change = 0; | ||
| 2408 | } | ||
| 2409 | /* As above for the allocated size. */ | ||
| 2410 | alloc_change = -1; | ||
| 2411 | if (new_alloc_size - old_alloc_size >= 0) { | ||
| 2412 | alloc_change = 1; | ||
| 2413 | if (new_alloc_size == old_alloc_size) | ||
| 2414 | alloc_change = 0; | ||
| 2415 | } | ||
| 2416 | /* | ||
| 2417 | * If neither the size nor the allocation are being changed there is | ||
| 2418 | * nothing to do. | ||
| 2419 | */ | ||
| 2420 | if (!size_change && !alloc_change) | ||
| 2421 | goto unm_done; | ||
| 2422 | /* If the size is changing, check if new size is allowed in $AttrDef. */ | ||
| 2423 | if (size_change) { | ||
| 2424 | err = ntfs_attr_size_bounds_check(vol, ni->type, new_size); | ||
| 2425 | if (unlikely(err)) { | ||
| 2426 | if (err == -ERANGE) { | ||
| 2427 | ntfs_error(vol->sb, "Truncate would cause the " | ||
| 2428 | "inode 0x%lx to %simum size " | ||
| 2429 | "for its attribute type " | ||
| 2430 | "(0x%x). Aborting truncate.", | ||
| 2431 | vi->i_ino, | ||
| 2432 | new_size > old_size ? "exceed " | ||
| 2433 | "the max" : "go under the min", | ||
| 2434 | le32_to_cpu(ni->type)); | ||
| 2435 | err = -EFBIG; | ||
| 2436 | } else { | ||
| 2437 | ntfs_error(vol->sb, "Inode 0x%lx has unknown " | ||
| 2438 | "attribute type 0x%x. " | ||
| 2439 | "Aborting truncate.", | ||
| 2440 | vi->i_ino, | ||
| 2441 | le32_to_cpu(ni->type)); | ||
| 2442 | err = -EIO; | ||
| 2443 | } | ||
| 2444 | /* Reset the vfs inode size to the old size. */ | ||
| 2445 | i_size_write(vi, old_size); | ||
| 2446 | goto err_out; | ||
| 2447 | } | ||
| 2448 | } | ||
| 2449 | if (NInoCompressed(ni) || NInoEncrypted(ni)) { | ||
| 2450 | ntfs_warning(vi->i_sb, "Changes in inode size are not " | ||
| 2451 | "supported yet for %s files, ignoring.", | ||
| 2452 | NInoCompressed(ni) ? "compressed" : | ||
| 2453 | "encrypted"); | ||
| 2454 | err = -EOPNOTSUPP; | ||
| 2455 | goto bad_out; | ||
| 2456 | } | ||
| 2457 | if (a->non_resident) | ||
| 2458 | goto do_non_resident_truncate; | ||
| 2459 | BUG_ON(NInoNonResident(ni)); | ||
| 2460 | /* Resize the attribute record to best fit the new attribute size. */ | ||
| 2461 | if (new_size < vol->mft_record_size && | ||
| 2462 | !ntfs_resident_attr_value_resize(m, a, new_size)) { | ||
| 2463 | unsigned long flags; | ||
| 2464 | |||
| 2465 | /* The resize succeeded! */ | ||
| 2466 | flush_dcache_mft_record_page(ctx->ntfs_ino); | ||
| 2467 | mark_mft_record_dirty(ctx->ntfs_ino); | ||
| 2468 | write_lock_irqsave(&ni->size_lock, flags); | ||
| 2469 | /* Update the sizes in the ntfs inode and all is done. */ | ||
| 2470 | ni->allocated_size = le32_to_cpu(a->length) - | ||
| 2471 | le16_to_cpu(a->data.resident.value_offset); | ||
| 2472 | /* | ||
| 2473 | * Note ntfs_resident_attr_value_resize() has already done any | ||
| 2474 | * necessary data clearing in the attribute record. When the | ||
| 2475 | * file is being shrunk vmtruncate() will already have cleared | ||
| 2476 | * the top part of the last partial page, i.e. since this is | ||
| 2477 | * the resident case this is the page with index 0. However, | ||
| 2478 | * when the file is being expanded, the page cache page data | ||
| 2479 | * between the old data_size, i.e. old_size, and the new_size | ||
| 2480 | * has not been zeroed. Fortunately, we do not need to zero it | ||
| 2481 | * either since on one hand it will either already be zero due | ||
| 2482 | * to both readpage and writepage clearing partial page data | ||
| 2483 | * beyond i_size in which case there is nothing to do or in the | ||
| 2484 | * case of the file being mmap()ped at the same time, POSIX | ||
| 2485 | * specifies that the behaviour is unspecified thus we do not | ||
| 2486 | * have to do anything. This means that in our implementation | ||
| 2487 | * in the rare case that the file is mmap()ped and a write | ||
| 2488 | * occured into the mmap()ped region just beyond the file size | ||
| 2489 | * and writepage has not yet been called to write out the page | ||
| 2490 | * (which would clear the area beyond the file size) and we now | ||
| 2491 | * extend the file size to incorporate this dirty region | ||
| 2492 | * outside the file size, a write of the page would result in | ||
| 2493 | * this data being written to disk instead of being cleared. | ||
| 2494 | * Given both POSIX and the Linux mmap(2) man page specify that | ||
| 2495 | * this corner case is undefined, we choose to leave it like | ||
| 2496 | * that as this is much simpler for us as we cannot lock the | ||
| 2497 | * relevant page now since we are holding too many ntfs locks | ||
| 2498 | * which would result in a lock reversal deadlock. | ||
| 2499 | */ | ||
| 2500 | ni->initialized_size = new_size; | ||
| 2501 | write_unlock_irqrestore(&ni->size_lock, flags); | ||
| 2502 | goto unm_done; | ||
| 2503 | } | ||
| 2504 | /* If the above resize failed, this must be an attribute extension. */ | ||
| 2505 | BUG_ON(size_change < 0); | ||
| 2506 | /* | ||
| 2507 | * We have to drop all the locks so we can call | ||
| 2508 | * ntfs_attr_make_non_resident(). This could be optimised by try- | ||
| 2509 | * locking the first page cache page and only if that fails dropping | ||
| 2510 | * the locks, locking the page, and redoing all the locking and | ||
| 2511 | * lookups. While this would be a huge optimisation, it is not worth | ||
| 2512 | * it as this is definitely a slow code path as it only ever can happen | ||
| 2513 | * once for any given file. | ||
| 2514 | */ | ||
| 2367 | ntfs_attr_put_search_ctx(ctx); | 2515 | ntfs_attr_put_search_ctx(ctx); |
| 2368 | unmap_mft_record(ni); | 2516 | unmap_mft_record(base_ni); |
| 2369 | NInoClearTruncateFailed(ni); | 2517 | up_write(&ni->runlist.lock); |
| 2370 | ntfs_debug("Done."); | 2518 | /* |
| 2371 | return 0; | 2519 | * Not enough space in the mft record, try to make the attribute |
| 2372 | err_out: | 2520 | * non-resident and if successful restart the truncation process. |
| 2373 | if (err != -ENOMEM) { | 2521 | */ |
| 2522 | err = ntfs_attr_make_non_resident(ni, old_size); | ||
| 2523 | if (likely(!err)) | ||
| 2524 | goto retry_truncate; | ||
| 2525 | /* | ||
| 2526 | * Could not make non-resident. If this is due to this not being | ||
| 2527 | * permitted for this attribute type or there not being enough space, | ||
| 2528 | * try to make other attributes non-resident. Otherwise fail. | ||
| 2529 | */ | ||
| 2530 | if (unlikely(err != -EPERM && err != -ENOSPC)) { | ||
| 2531 | ntfs_error(vol->sb, "Cannot truncate inode 0x%lx, attribute " | ||
| 2532 | "type 0x%x, because the conversion from " | ||
| 2533 | "resident to non-resident attribute failed " | ||
| 2534 | "with error code %i.", vi->i_ino, | ||
| 2535 | (unsigned)le32_to_cpu(ni->type), err); | ||
| 2536 | if (err != -ENOMEM) | ||
| 2537 | err = -EIO; | ||
| 2538 | goto conv_err_out; | ||
| 2539 | } | ||
| 2540 | /* TODO: Not implemented from here, abort. */ | ||
| 2541 | if (err == -ENOSPC) | ||
| 2542 | ntfs_error(vol->sb, "Not enough space in the mft record/on " | ||
| 2543 | "disk for the non-resident attribute value. " | ||
| 2544 | "This case is not implemented yet."); | ||
| 2545 | else /* if (err == -EPERM) */ | ||
| 2546 | ntfs_error(vol->sb, "This attribute type may not be " | ||
| 2547 | "non-resident. This case is not implemented " | ||
| 2548 | "yet."); | ||
| 2549 | err = -EOPNOTSUPP; | ||
| 2550 | goto conv_err_out; | ||
| 2551 | #if 0 | ||
| 2552 | // TODO: Attempt to make other attributes non-resident. | ||
| 2553 | if (!err) | ||
| 2554 | goto do_resident_extend; | ||
| 2555 | /* | ||
| 2556 | * Both the attribute list attribute and the standard information | ||
| 2557 | * attribute must remain in the base inode. Thus, if this is one of | ||
| 2558 | * these attributes, we have to try to move other attributes out into | ||
| 2559 | * extent mft records instead. | ||
| 2560 | */ | ||
| 2561 | if (ni->type == AT_ATTRIBUTE_LIST || | ||
| 2562 | ni->type == AT_STANDARD_INFORMATION) { | ||
| 2563 | // TODO: Attempt to move other attributes into extent mft | ||
| 2564 | // records. | ||
| 2565 | err = -EOPNOTSUPP; | ||
| 2566 | if (!err) | ||
| 2567 | goto do_resident_extend; | ||
| 2568 | goto err_out; | ||
| 2569 | } | ||
| 2570 | // TODO: Attempt to move this attribute to an extent mft record, but | ||
| 2571 | // only if it is not already the only attribute in an mft record in | ||
| 2572 | // which case there would be nothing to gain. | ||
| 2573 | err = -EOPNOTSUPP; | ||
| 2574 | if (!err) | ||
| 2575 | goto do_resident_extend; | ||
| 2576 | /* There is nothing we can do to make enough space. )-: */ | ||
| 2577 | goto err_out; | ||
| 2578 | #endif | ||
| 2579 | do_non_resident_truncate: | ||
| 2580 | BUG_ON(!NInoNonResident(ni)); | ||
| 2581 | if (alloc_change < 0) { | ||
| 2582 | highest_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn); | ||
| 2583 | if (highest_vcn > 0 && | ||
| 2584 | old_alloc_size >> vol->cluster_size_bits > | ||
| 2585 | highest_vcn + 1) { | ||
| 2586 | /* | ||
| 2587 | * This attribute has multiple extents. Not yet | ||
| 2588 | * supported. | ||
| 2589 | */ | ||
| 2590 | ntfs_error(vol->sb, "Cannot truncate inode 0x%lx, " | ||
| 2591 | "attribute type 0x%x, because the " | ||
| 2592 | "attribute is highly fragmented (it " | ||
| 2593 | "consists of multiple extents) and " | ||
| 2594 | "this case is not implemented yet.", | ||
| 2595 | vi->i_ino, | ||
| 2596 | (unsigned)le32_to_cpu(ni->type)); | ||
| 2597 | err = -EOPNOTSUPP; | ||
| 2598 | goto bad_out; | ||
| 2599 | } | ||
| 2600 | } | ||
| 2601 | /* | ||
| 2602 | * If the size is shrinking, need to reduce the initialized_size and | ||
| 2603 | * the data_size before reducing the allocation. | ||
| 2604 | */ | ||
| 2605 | if (size_change < 0) { | ||
| 2606 | /* | ||
| 2607 | * Make the valid size smaller (i_size is already up-to-date). | ||
| 2608 | */ | ||
| 2609 | write_lock_irqsave(&ni->size_lock, flags); | ||
| 2610 | if (new_size < ni->initialized_size) { | ||
| 2611 | ni->initialized_size = new_size; | ||
| 2612 | a->data.non_resident.initialized_size = | ||
| 2613 | cpu_to_sle64(new_size); | ||
| 2614 | } | ||
| 2615 | a->data.non_resident.data_size = cpu_to_sle64(new_size); | ||
| 2616 | write_unlock_irqrestore(&ni->size_lock, flags); | ||
| 2617 | flush_dcache_mft_record_page(ctx->ntfs_ino); | ||
| 2618 | mark_mft_record_dirty(ctx->ntfs_ino); | ||
| 2619 | /* If the allocated size is not changing, we are done. */ | ||
| 2620 | if (!alloc_change) | ||
| 2621 | goto unm_done; | ||
| 2622 | /* | ||
| 2623 | * If the size is shrinking it makes no sense for the | ||
| 2624 | * allocation to be growing. | ||
| 2625 | */ | ||
| 2626 | BUG_ON(alloc_change > 0); | ||
| 2627 | } else /* if (size_change >= 0) */ { | ||
| 2628 | /* | ||
| 2629 | * The file size is growing or staying the same but the | ||
| 2630 | * allocation can be shrinking, growing or staying the same. | ||
| 2631 | */ | ||
| 2632 | if (alloc_change > 0) { | ||
| 2633 | /* | ||
| 2634 | * We need to extend the allocation and possibly update | ||
| 2635 | * the data size. If we are updating the data size, | ||
| 2636 | * since we are not touching the initialized_size we do | ||
| 2637 | * not need to worry about the actual data on disk. | ||
| 2638 | * And as far as the page cache is concerned, there | ||
| 2639 | * will be no pages beyond the old data size and any | ||
| 2640 | * partial region in the last page between the old and | ||
| 2641 | * new data size (or the end of the page if the new | ||
| 2642 | * data size is outside the page) does not need to be | ||
| 2643 | * modified as explained above for the resident | ||
| 2644 | * attribute truncate case. To do this, we simply drop | ||
| 2645 | * the locks we hold and leave all the work to our | ||
| 2646 | * friendly helper ntfs_attr_extend_allocation(). | ||
| 2647 | */ | ||
| 2648 | ntfs_attr_put_search_ctx(ctx); | ||
| 2649 | unmap_mft_record(base_ni); | ||
| 2650 | up_write(&ni->runlist.lock); | ||
| 2651 | err = ntfs_attr_extend_allocation(ni, new_size, | ||
| 2652 | size_change > 0 ? new_size : -1, -1); | ||
| 2653 | /* | ||
| 2654 | * ntfs_attr_extend_allocation() will have done error | ||
| 2655 | * output already. | ||
| 2656 | */ | ||
| 2657 | goto done; | ||
| 2658 | } | ||
| 2659 | if (!alloc_change) | ||
| 2660 | goto alloc_done; | ||
| 2661 | } | ||
| 2662 | /* alloc_change < 0 */ | ||
| 2663 | /* Free the clusters. */ | ||
| 2664 | nr_freed = ntfs_cluster_free(ni, new_alloc_size >> | ||
| 2665 | vol->cluster_size_bits, -1, ctx); | ||
| 2666 | m = ctx->mrec; | ||
| 2667 | a = ctx->attr; | ||
| 2668 | if (unlikely(nr_freed < 0)) { | ||
| 2669 | ntfs_error(vol->sb, "Failed to release cluster(s) (error code " | ||
| 2670 | "%lli). Unmount and run chkdsk to recover " | ||
| 2671 | "the lost cluster(s).", (long long)nr_freed); | ||
| 2374 | NVolSetErrors(vol); | 2672 | NVolSetErrors(vol); |
| 2673 | nr_freed = 0; | ||
| 2674 | } | ||
| 2675 | /* Truncate the runlist. */ | ||
| 2676 | err = ntfs_rl_truncate_nolock(vol, &ni->runlist, | ||
| 2677 | new_alloc_size >> vol->cluster_size_bits); | ||
| 2678 | /* | ||
| 2679 | * If the runlist truncation failed and/or the search context is no | ||
| 2680 | * longer valid, we cannot resize the attribute record or build the | ||
| 2681 | * mapping pairs array thus we mark the inode bad so that no access to | ||
| 2682 | * the freed clusters can happen. | ||
| 2683 | */ | ||
| 2684 | if (unlikely(err || IS_ERR(m))) { | ||
| 2685 | ntfs_error(vol->sb, "Failed to %s (error code %li).%s", | ||
| 2686 | IS_ERR(m) ? | ||
| 2687 | "restore attribute search context" : | ||
| 2688 | "truncate attribute runlist", | ||
| 2689 | IS_ERR(m) ? PTR_ERR(m) : err, es); | ||
| 2690 | err = -EIO; | ||
| 2691 | goto bad_out; | ||
| 2692 | } | ||
| 2693 | /* Get the size for the shrunk mapping pairs array for the runlist. */ | ||
| 2694 | mp_size = ntfs_get_size_for_mapping_pairs(vol, ni->runlist.rl, 0, -1); | ||
| 2695 | if (unlikely(mp_size <= 0)) { | ||
| 2696 | ntfs_error(vol->sb, "Cannot shrink allocation of inode 0x%lx, " | ||
| 2697 | "attribute type 0x%x, because determining the " | ||
| 2698 | "size for the mapping pairs failed with error " | ||
| 2699 | "code %i.%s", vi->i_ino, | ||
| 2700 | (unsigned)le32_to_cpu(ni->type), mp_size, es); | ||
| 2701 | err = -EIO; | ||
| 2702 | goto bad_out; | ||
| 2703 | } | ||
| 2704 | /* | ||
| 2705 | * Shrink the attribute record for the new mapping pairs array. Note, | ||
| 2706 | * this cannot fail since we are making the attribute smaller thus by | ||
| 2707 | * definition there is enough space to do so. | ||
| 2708 | */ | ||
| 2709 | attr_len = le32_to_cpu(a->length); | ||
| 2710 | err = ntfs_attr_record_resize(m, a, mp_size + | ||
| 2711 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset)); | ||
| 2712 | BUG_ON(err); | ||
| 2713 | /* | ||
| 2714 | * Generate the mapping pairs array directly into the attribute record. | ||
| 2715 | */ | ||
| 2716 | err = ntfs_mapping_pairs_build(vol, (u8*)a + | ||
| 2717 | le16_to_cpu(a->data.non_resident.mapping_pairs_offset), | ||
| 2718 | mp_size, ni->runlist.rl, 0, -1, NULL); | ||
| 2719 | if (unlikely(err)) { | ||
| 2720 | ntfs_error(vol->sb, "Cannot shrink allocation of inode 0x%lx, " | ||
| 2721 | "attribute type 0x%x, because building the " | ||
| 2722 | "mapping pairs failed with error code %i.%s", | ||
| 2723 | vi->i_ino, (unsigned)le32_to_cpu(ni->type), | ||
| 2724 | err, es); | ||
| 2725 | err = -EIO; | ||
| 2726 | goto bad_out; | ||
| 2727 | } | ||
| 2728 | /* Update the allocated/compressed size as well as the highest vcn. */ | ||
| 2729 | a->data.non_resident.highest_vcn = cpu_to_sle64((new_alloc_size >> | ||
| 2730 | vol->cluster_size_bits) - 1); | ||
| 2731 | write_lock_irqsave(&ni->size_lock, flags); | ||
| 2732 | ni->allocated_size = new_alloc_size; | ||
| 2733 | a->data.non_resident.allocated_size = cpu_to_sle64(new_alloc_size); | ||
| 2734 | if (NInoSparse(ni) || NInoCompressed(ni)) { | ||
| 2735 | if (nr_freed) { | ||
| 2736 | ni->itype.compressed.size -= nr_freed << | ||
| 2737 | vol->cluster_size_bits; | ||
| 2738 | BUG_ON(ni->itype.compressed.size < 0); | ||
| 2739 | a->data.non_resident.compressed_size = cpu_to_sle64( | ||
| 2740 | ni->itype.compressed.size); | ||
| 2741 | vi->i_blocks = ni->itype.compressed.size >> 9; | ||
| 2742 | } | ||
| 2743 | } else | ||
| 2744 | vi->i_blocks = new_alloc_size >> 9; | ||
| 2745 | write_unlock_irqrestore(&ni->size_lock, flags); | ||
| 2746 | /* | ||
| 2747 | * We have shrunk the allocation. If this is a shrinking truncate we | ||
| 2748 | * have already dealt with the initialized_size and the data_size above | ||
| 2749 | * and we are done. If the truncate is only changing the allocation | ||
| 2750 | * and not the data_size, we are also done. If this is an extending | ||
| 2751 | * truncate, need to extend the data_size now which is ensured by the | ||
| 2752 | * fact that @size_change is positive. | ||
| 2753 | */ | ||
| 2754 | alloc_done: | ||
| 2755 | /* | ||
| 2756 | * If the size is growing, need to update it now. If it is shrinking, | ||
| 2757 | * we have already updated it above (before the allocation change). | ||
| 2758 | */ | ||
| 2759 | if (size_change > 0) | ||
| 2760 | a->data.non_resident.data_size = cpu_to_sle64(new_size); | ||
| 2761 | /* Ensure the modified mft record is written out. */ | ||
| 2762 | flush_dcache_mft_record_page(ctx->ntfs_ino); | ||
| 2763 | mark_mft_record_dirty(ctx->ntfs_ino); | ||
| 2764 | unm_done: | ||
| 2765 | ntfs_attr_put_search_ctx(ctx); | ||
| 2766 | unmap_mft_record(base_ni); | ||
| 2767 | up_write(&ni->runlist.lock); | ||
| 2768 | done: | ||
| 2769 | /* Update the mtime and ctime on the base inode. */ | ||
| 2770 | inode_update_time(VFS_I(base_ni), 1); | ||
| 2771 | if (likely(!err)) { | ||
| 2772 | NInoClearTruncateFailed(ni); | ||
| 2773 | ntfs_debug("Done."); | ||
| 2774 | } | ||
| 2775 | return err; | ||
| 2776 | old_bad_out: | ||
| 2777 | old_size = -1; | ||
| 2778 | bad_out: | ||
| 2779 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | ||
| 2375 | make_bad_inode(vi); | 2780 | make_bad_inode(vi); |
| 2781 | make_bad_inode(VFS_I(base_ni)); | ||
| 2782 | NVolSetErrors(vol); | ||
| 2376 | } | 2783 | } |
| 2784 | if (err != -EOPNOTSUPP) | ||
| 2785 | NInoSetTruncateFailed(ni); | ||
| 2786 | else if (old_size >= 0) | ||
| 2787 | i_size_write(vi, old_size); | ||
| 2788 | err_out: | ||
| 2377 | if (ctx) | 2789 | if (ctx) |
| 2378 | ntfs_attr_put_search_ctx(ctx); | 2790 | ntfs_attr_put_search_ctx(ctx); |
| 2379 | if (m) | 2791 | if (m) |
| 2380 | unmap_mft_record(ni); | 2792 | unmap_mft_record(base_ni); |
| 2381 | NInoSetTruncateFailed(ni); | 2793 | up_write(&ni->runlist.lock); |
| 2794 | out: | ||
| 2795 | ntfs_debug("Failed. Returning error code %i.", err); | ||
| 2382 | return err; | 2796 | return err; |
| 2797 | conv_err_out: | ||
| 2798 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | ||
| 2799 | make_bad_inode(vi); | ||
| 2800 | make_bad_inode(VFS_I(base_ni)); | ||
| 2801 | NVolSetErrors(vol); | ||
| 2802 | } | ||
| 2803 | if (err != -EOPNOTSUPP) | ||
| 2804 | NInoSetTruncateFailed(ni); | ||
| 2805 | else | ||
| 2806 | i_size_write(vi, old_size); | ||
| 2807 | goto out; | ||
| 2383 | } | 2808 | } |
| 2384 | 2809 | ||
| 2385 | /** | 2810 | /** |
| @@ -2420,8 +2845,7 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 2420 | 2845 | ||
| 2421 | err = inode_change_ok(vi, attr); | 2846 | err = inode_change_ok(vi, attr); |
| 2422 | if (err) | 2847 | if (err) |
| 2423 | return err; | 2848 | goto out; |
| 2424 | |||
| 2425 | /* We do not support NTFS ACLs yet. */ | 2849 | /* We do not support NTFS ACLs yet. */ |
| 2426 | if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) { | 2850 | if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) { |
| 2427 | ntfs_warning(vi->i_sb, "Changes in user/group/mode are not " | 2851 | ntfs_warning(vi->i_sb, "Changes in user/group/mode are not " |
| @@ -2429,14 +2853,22 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 2429 | err = -EOPNOTSUPP; | 2853 | err = -EOPNOTSUPP; |
| 2430 | goto out; | 2854 | goto out; |
| 2431 | } | 2855 | } |
| 2432 | |||
| 2433 | if (ia_valid & ATTR_SIZE) { | 2856 | if (ia_valid & ATTR_SIZE) { |
| 2434 | if (attr->ia_size != i_size_read(vi)) { | 2857 | if (attr->ia_size != i_size_read(vi)) { |
| 2435 | ntfs_warning(vi->i_sb, "Changes in inode size are not " | 2858 | ntfs_inode *ni = NTFS_I(vi); |
| 2436 | "supported yet, ignoring."); | 2859 | /* |
| 2437 | err = -EOPNOTSUPP; | 2860 | * FIXME: For now we do not support resizing of |
| 2438 | // TODO: Implement... | 2861 | * compressed or encrypted files yet. |
| 2439 | // err = vmtruncate(vi, attr->ia_size); | 2862 | */ |
| 2863 | if (NInoCompressed(ni) || NInoEncrypted(ni)) { | ||
| 2864 | ntfs_warning(vi->i_sb, "Changes in inode size " | ||
| 2865 | "are not supported yet for " | ||
| 2866 | "%s files, ignoring.", | ||
| 2867 | NInoCompressed(ni) ? | ||
| 2868 | "compressed" : "encrypted"); | ||
| 2869 | err = -EOPNOTSUPP; | ||
| 2870 | } else | ||
| 2871 | err = vmtruncate(vi, attr->ia_size); | ||
| 2440 | if (err || ia_valid == ATTR_SIZE) | 2872 | if (err || ia_valid == ATTR_SIZE) |
| 2441 | goto out; | 2873 | goto out; |
| 2442 | } else { | 2874 | } else { |
