diff options
Diffstat (limited to 'fs')
68 files changed, 2474 insertions, 1773 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index dfebdbe7440e..3031e3233dd6 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/idr.h> | 28 | #include <linux/idr.h> |
29 | #include <asm/semaphore.h> | ||
30 | #include <net/9p/9p.h> | 29 | #include <net/9p/9p.h> |
31 | #include <net/9p/client.h> | 30 | #include <net/9p/client.h> |
32 | 31 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index 028ae38ecc52..8b18a8758677 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -689,6 +689,7 @@ config ZISOFS | |||
689 | 689 | ||
690 | config UDF_FS | 690 | config UDF_FS |
691 | tristate "UDF file system support" | 691 | tristate "UDF file system support" |
692 | select CRC_ITU_T | ||
692 | help | 693 | help |
693 | This is the new file system used on some CD-ROMs and DVDs. Say Y if | 694 | This is the new file system used on some CD-ROMs and DVDs. Say Y if |
694 | you intend to mount DVD discs or CDRW's written in packet mode, or | 695 | you intend to mount DVD discs or CDRW's written in packet mode, or |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index b5c3b6114add..853845abcca6 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -62,7 +62,7 @@ config BINFMT_SHARED_FLAT | |||
62 | config BINFMT_AOUT | 62 | config BINFMT_AOUT |
63 | tristate "Kernel support for a.out and ECOFF binaries" | 63 | tristate "Kernel support for a.out and ECOFF binaries" |
64 | depends on ARCH_SUPPORTS_AOUT && \ | 64 | depends on ARCH_SUPPORTS_AOUT && \ |
65 | (X86_32 || ALPHA || ARM || M68K || SPARC32) | 65 | (X86_32 || ALPHA || ARM || M68K) |
66 | ---help--- | 66 | ---help--- |
67 | A.out (Assembler.OUTput) is a set of formats for libraries and | 67 | A.out (Assembler.OUTput) is a set of formats for libraries and |
68 | executables used in the earliest versions of UNIX. Linux used | 68 | executables used in the earliest versions of UNIX. Linux used |
@@ -444,22 +444,27 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, | |||
444 | 444 | ||
445 | struct bio_map_data { | 445 | struct bio_map_data { |
446 | struct bio_vec *iovecs; | 446 | struct bio_vec *iovecs; |
447 | void __user *userptr; | 447 | int nr_sgvecs; |
448 | struct sg_iovec *sgvecs; | ||
448 | }; | 449 | }; |
449 | 450 | ||
450 | static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio) | 451 | static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, |
452 | struct sg_iovec *iov, int iov_count) | ||
451 | { | 453 | { |
452 | memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt); | 454 | memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt); |
455 | memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count); | ||
456 | bmd->nr_sgvecs = iov_count; | ||
453 | bio->bi_private = bmd; | 457 | bio->bi_private = bmd; |
454 | } | 458 | } |
455 | 459 | ||
456 | static void bio_free_map_data(struct bio_map_data *bmd) | 460 | static void bio_free_map_data(struct bio_map_data *bmd) |
457 | { | 461 | { |
458 | kfree(bmd->iovecs); | 462 | kfree(bmd->iovecs); |
463 | kfree(bmd->sgvecs); | ||
459 | kfree(bmd); | 464 | kfree(bmd); |
460 | } | 465 | } |
461 | 466 | ||
462 | static struct bio_map_data *bio_alloc_map_data(int nr_segs) | 467 | static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count) |
463 | { | 468 | { |
464 | struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL); | 469 | struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL); |
465 | 470 | ||
@@ -467,13 +472,71 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs) | |||
467 | return NULL; | 472 | return NULL; |
468 | 473 | ||
469 | bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL); | 474 | bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL); |
470 | if (bmd->iovecs) | 475 | if (!bmd->iovecs) { |
476 | kfree(bmd); | ||
477 | return NULL; | ||
478 | } | ||
479 | |||
480 | bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, GFP_KERNEL); | ||
481 | if (bmd->sgvecs) | ||
471 | return bmd; | 482 | return bmd; |
472 | 483 | ||
484 | kfree(bmd->iovecs); | ||
473 | kfree(bmd); | 485 | kfree(bmd); |
474 | return NULL; | 486 | return NULL; |
475 | } | 487 | } |
476 | 488 | ||
489 | static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count, | ||
490 | int uncopy) | ||
491 | { | ||
492 | int ret = 0, i; | ||
493 | struct bio_vec *bvec; | ||
494 | int iov_idx = 0; | ||
495 | unsigned int iov_off = 0; | ||
496 | int read = bio_data_dir(bio) == READ; | ||
497 | |||
498 | __bio_for_each_segment(bvec, bio, i, 0) { | ||
499 | char *bv_addr = page_address(bvec->bv_page); | ||
500 | unsigned int bv_len = bvec->bv_len; | ||
501 | |||
502 | while (bv_len && iov_idx < iov_count) { | ||
503 | unsigned int bytes; | ||
504 | char *iov_addr; | ||
505 | |||
506 | bytes = min_t(unsigned int, | ||
507 | iov[iov_idx].iov_len - iov_off, bv_len); | ||
508 | iov_addr = iov[iov_idx].iov_base + iov_off; | ||
509 | |||
510 | if (!ret) { | ||
511 | if (!read && !uncopy) | ||
512 | ret = copy_from_user(bv_addr, iov_addr, | ||
513 | bytes); | ||
514 | if (read && uncopy) | ||
515 | ret = copy_to_user(iov_addr, bv_addr, | ||
516 | bytes); | ||
517 | |||
518 | if (ret) | ||
519 | ret = -EFAULT; | ||
520 | } | ||
521 | |||
522 | bv_len -= bytes; | ||
523 | bv_addr += bytes; | ||
524 | iov_addr += bytes; | ||
525 | iov_off += bytes; | ||
526 | |||
527 | if (iov[iov_idx].iov_len == iov_off) { | ||
528 | iov_idx++; | ||
529 | iov_off = 0; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | if (uncopy) | ||
534 | __free_page(bvec->bv_page); | ||
535 | } | ||
536 | |||
537 | return ret; | ||
538 | } | ||
539 | |||
477 | /** | 540 | /** |
478 | * bio_uncopy_user - finish previously mapped bio | 541 | * bio_uncopy_user - finish previously mapped bio |
479 | * @bio: bio being terminated | 542 | * @bio: bio being terminated |
@@ -484,55 +547,56 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs) | |||
484 | int bio_uncopy_user(struct bio *bio) | 547 | int bio_uncopy_user(struct bio *bio) |
485 | { | 548 | { |
486 | struct bio_map_data *bmd = bio->bi_private; | 549 | struct bio_map_data *bmd = bio->bi_private; |
487 | const int read = bio_data_dir(bio) == READ; | 550 | int ret; |
488 | struct bio_vec *bvec; | ||
489 | int i, ret = 0; | ||
490 | 551 | ||
491 | __bio_for_each_segment(bvec, bio, i, 0) { | 552 | ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, 1); |
492 | char *addr = page_address(bvec->bv_page); | ||
493 | unsigned int len = bmd->iovecs[i].bv_len; | ||
494 | 553 | ||
495 | if (read && !ret && copy_to_user(bmd->userptr, addr, len)) | ||
496 | ret = -EFAULT; | ||
497 | |||
498 | __free_page(bvec->bv_page); | ||
499 | bmd->userptr += len; | ||
500 | } | ||
501 | bio_free_map_data(bmd); | 554 | bio_free_map_data(bmd); |
502 | bio_put(bio); | 555 | bio_put(bio); |
503 | return ret; | 556 | return ret; |
504 | } | 557 | } |
505 | 558 | ||
506 | /** | 559 | /** |
507 | * bio_copy_user - copy user data to bio | 560 | * bio_copy_user_iov - copy user data to bio |
508 | * @q: destination block queue | 561 | * @q: destination block queue |
509 | * @uaddr: start of user address | 562 | * @iov: the iovec. |
510 | * @len: length in bytes | 563 | * @iov_count: number of elements in the iovec |
511 | * @write_to_vm: bool indicating writing to pages or not | 564 | * @write_to_vm: bool indicating writing to pages or not |
512 | * | 565 | * |
513 | * Prepares and returns a bio for indirect user io, bouncing data | 566 | * Prepares and returns a bio for indirect user io, bouncing data |
514 | * to/from kernel pages as necessary. Must be paired with | 567 | * to/from kernel pages as necessary. Must be paired with |
515 | * call bio_uncopy_user() on io completion. | 568 | * call bio_uncopy_user() on io completion. |
516 | */ | 569 | */ |
517 | struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, | 570 | struct bio *bio_copy_user_iov(struct request_queue *q, struct sg_iovec *iov, |
518 | unsigned int len, int write_to_vm) | 571 | int iov_count, int write_to_vm) |
519 | { | 572 | { |
520 | unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
521 | unsigned long start = uaddr >> PAGE_SHIFT; | ||
522 | struct bio_map_data *bmd; | 573 | struct bio_map_data *bmd; |
523 | struct bio_vec *bvec; | 574 | struct bio_vec *bvec; |
524 | struct page *page; | 575 | struct page *page; |
525 | struct bio *bio; | 576 | struct bio *bio; |
526 | int i, ret; | 577 | int i, ret; |
578 | int nr_pages = 0; | ||
579 | unsigned int len = 0; | ||
527 | 580 | ||
528 | bmd = bio_alloc_map_data(end - start); | 581 | for (i = 0; i < iov_count; i++) { |
582 | unsigned long uaddr; | ||
583 | unsigned long end; | ||
584 | unsigned long start; | ||
585 | |||
586 | uaddr = (unsigned long)iov[i].iov_base; | ||
587 | end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
588 | start = uaddr >> PAGE_SHIFT; | ||
589 | |||
590 | nr_pages += end - start; | ||
591 | len += iov[i].iov_len; | ||
592 | } | ||
593 | |||
594 | bmd = bio_alloc_map_data(nr_pages, iov_count); | ||
529 | if (!bmd) | 595 | if (!bmd) |
530 | return ERR_PTR(-ENOMEM); | 596 | return ERR_PTR(-ENOMEM); |
531 | 597 | ||
532 | bmd->userptr = (void __user *) uaddr; | ||
533 | |||
534 | ret = -ENOMEM; | 598 | ret = -ENOMEM; |
535 | bio = bio_alloc(GFP_KERNEL, end - start); | 599 | bio = bio_alloc(GFP_KERNEL, nr_pages); |
536 | if (!bio) | 600 | if (!bio) |
537 | goto out_bmd; | 601 | goto out_bmd; |
538 | 602 | ||
@@ -564,22 +628,12 @@ struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, | |||
564 | * success | 628 | * success |
565 | */ | 629 | */ |
566 | if (!write_to_vm) { | 630 | if (!write_to_vm) { |
567 | char __user *p = (char __user *) uaddr; | 631 | ret = __bio_copy_iov(bio, iov, iov_count, 0); |
568 | 632 | if (ret) | |
569 | /* | 633 | goto cleanup; |
570 | * for a write, copy in data to kernel pages | ||
571 | */ | ||
572 | ret = -EFAULT; | ||
573 | bio_for_each_segment(bvec, bio, i) { | ||
574 | char *addr = page_address(bvec->bv_page); | ||
575 | |||
576 | if (copy_from_user(addr, p, bvec->bv_len)) | ||
577 | goto cleanup; | ||
578 | p += bvec->bv_len; | ||
579 | } | ||
580 | } | 634 | } |
581 | 635 | ||
582 | bio_set_map_data(bmd, bio); | 636 | bio_set_map_data(bmd, bio, iov, iov_count); |
583 | return bio; | 637 | return bio; |
584 | cleanup: | 638 | cleanup: |
585 | bio_for_each_segment(bvec, bio, i) | 639 | bio_for_each_segment(bvec, bio, i) |
@@ -591,6 +645,28 @@ out_bmd: | |||
591 | return ERR_PTR(ret); | 645 | return ERR_PTR(ret); |
592 | } | 646 | } |
593 | 647 | ||
648 | /** | ||
649 | * bio_copy_user - copy user data to bio | ||
650 | * @q: destination block queue | ||
651 | * @uaddr: start of user address | ||
652 | * @len: length in bytes | ||
653 | * @write_to_vm: bool indicating writing to pages or not | ||
654 | * | ||
655 | * Prepares and returns a bio for indirect user io, bouncing data | ||
656 | * to/from kernel pages as necessary. Must be paired with | ||
657 | * call bio_uncopy_user() on io completion. | ||
658 | */ | ||
659 | struct bio *bio_copy_user(struct request_queue *q, unsigned long uaddr, | ||
660 | unsigned int len, int write_to_vm) | ||
661 | { | ||
662 | struct sg_iovec iov; | ||
663 | |||
664 | iov.iov_base = (void __user *)uaddr; | ||
665 | iov.iov_len = len; | ||
666 | |||
667 | return bio_copy_user_iov(q, &iov, 1, write_to_vm); | ||
668 | } | ||
669 | |||
594 | static struct bio *__bio_map_user_iov(struct request_queue *q, | 670 | static struct bio *__bio_map_user_iov(struct request_queue *q, |
595 | struct block_device *bdev, | 671 | struct block_device *bdev, |
596 | struct sg_iovec *iov, int iov_count, | 672 | struct sg_iovec *iov, int iov_count, |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 350680fd7da7..0c3b618c15b3 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/buffer_head.h> | 23 | #include <linux/buffer_head.h> |
24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <asm/semaphore.h> | ||
27 | 26 | ||
28 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
29 | 28 | ||
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 73c36f501707..5a7ac33b629c 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/jhash.h> | 37 | #include <linux/jhash.h> |
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <asm/semaphore.h> | ||
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | 41 | ||
43 | #include <linux/dlm.h> | 42 | #include <linux/dlm.h> |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 5deb8b74e649..08f647d8188d 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
@@ -253,7 +253,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) | |||
253 | * it has too few free inodes left (min_inodes) or | 253 | * it has too few free inodes left (min_inodes) or |
254 | * it has too few free blocks left (min_blocks) or | 254 | * it has too few free blocks left (min_blocks) or |
255 | * it's already running too large debt (max_debt). | 255 | * it's already running too large debt (max_debt). |
256 | * Parent's group is prefered, if it doesn't satisfy these | 256 | * Parent's group is preferred, if it doesn't satisfy these |
257 | * conditions we search cyclically through the rest. If none | 257 | * conditions we search cyclically through the rest. If none |
258 | * of the groups look good we just look for a group with more | 258 | * of the groups look good we just look for a group with more |
259 | * free inodes than average (starting at parent's group). | 259 | * free inodes than average (starting at parent's group). |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index c62006805427..b8a2990bab83 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -239,7 +239,7 @@ no_block: | |||
239 | * @inode: owner | 239 | * @inode: owner |
240 | * @ind: descriptor of indirect block. | 240 | * @ind: descriptor of indirect block. |
241 | * | 241 | * |
242 | * This function returns the prefered place for block allocation. | 242 | * This function returns the preferred place for block allocation. |
243 | * It is used when heuristic for sequential allocation fails. | 243 | * It is used when heuristic for sequential allocation fails. |
244 | * Rules are: | 244 | * Rules are: |
245 | * + if there is a block to the left of our position - allocate near it. | 245 | * + if there is a block to the left of our position - allocate near it. |
@@ -283,7 +283,7 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind) | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /** | 285 | /** |
286 | * ext2_find_goal - find a prefered place for allocation. | 286 | * ext2_find_goal - find a preferred place for allocation. |
287 | * @inode: owner | 287 | * @inode: owner |
288 | * @block: block we want | 288 | * @block: block we want |
289 | * @partial: pointer to the last triple within a chain | 289 | * @partial: pointer to the last triple within a chain |
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index b8ea11fee5c6..de876fa793e1 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/compat.h> | 14 | #include <linux/compat.h> |
15 | #include <linux/mount.h> | ||
15 | #include <linux/smp_lock.h> | 16 | #include <linux/smp_lock.h> |
16 | #include <asm/current.h> | 17 | #include <asm/current.h> |
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
@@ -23,6 +24,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
23 | struct ext2_inode_info *ei = EXT2_I(inode); | 24 | struct ext2_inode_info *ei = EXT2_I(inode); |
24 | unsigned int flags; | 25 | unsigned int flags; |
25 | unsigned short rsv_window_size; | 26 | unsigned short rsv_window_size; |
27 | int ret; | ||
26 | 28 | ||
27 | ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); | 29 | ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); |
28 | 30 | ||
@@ -34,14 +36,19 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
34 | case EXT2_IOC_SETFLAGS: { | 36 | case EXT2_IOC_SETFLAGS: { |
35 | unsigned int oldflags; | 37 | unsigned int oldflags; |
36 | 38 | ||
37 | if (IS_RDONLY(inode)) | 39 | ret = mnt_want_write(filp->f_path.mnt); |
38 | return -EROFS; | 40 | if (ret) |
41 | return ret; | ||
39 | 42 | ||
40 | if (!is_owner_or_cap(inode)) | 43 | if (!is_owner_or_cap(inode)) { |
41 | return -EACCES; | 44 | ret = -EACCES; |
45 | goto setflags_out; | ||
46 | } | ||
42 | 47 | ||
43 | if (get_user(flags, (int __user *) arg)) | 48 | if (get_user(flags, (int __user *) arg)) { |
44 | return -EFAULT; | 49 | ret = -EFAULT; |
50 | goto setflags_out; | ||
51 | } | ||
45 | 52 | ||
46 | if (!S_ISDIR(inode->i_mode)) | 53 | if (!S_ISDIR(inode->i_mode)) |
47 | flags &= ~EXT2_DIRSYNC_FL; | 54 | flags &= ~EXT2_DIRSYNC_FL; |
@@ -50,7 +57,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
50 | /* Is it quota file? Do not allow user to mess with it */ | 57 | /* Is it quota file? Do not allow user to mess with it */ |
51 | if (IS_NOQUOTA(inode)) { | 58 | if (IS_NOQUOTA(inode)) { |
52 | mutex_unlock(&inode->i_mutex); | 59 | mutex_unlock(&inode->i_mutex); |
53 | return -EPERM; | 60 | ret = -EPERM; |
61 | goto setflags_out; | ||
54 | } | 62 | } |
55 | oldflags = ei->i_flags; | 63 | oldflags = ei->i_flags; |
56 | 64 | ||
@@ -63,7 +71,8 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
63 | if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { | 71 | if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { |
64 | if (!capable(CAP_LINUX_IMMUTABLE)) { | 72 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
65 | mutex_unlock(&inode->i_mutex); | 73 | mutex_unlock(&inode->i_mutex); |
66 | return -EPERM; | 74 | ret = -EPERM; |
75 | goto setflags_out; | ||
67 | } | 76 | } |
68 | } | 77 | } |
69 | 78 | ||
@@ -75,20 +84,26 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
75 | ext2_set_inode_flags(inode); | 84 | ext2_set_inode_flags(inode); |
76 | inode->i_ctime = CURRENT_TIME_SEC; | 85 | inode->i_ctime = CURRENT_TIME_SEC; |
77 | mark_inode_dirty(inode); | 86 | mark_inode_dirty(inode); |
78 | return 0; | 87 | setflags_out: |
88 | mnt_drop_write(filp->f_path.mnt); | ||
89 | return ret; | ||
79 | } | 90 | } |
80 | case EXT2_IOC_GETVERSION: | 91 | case EXT2_IOC_GETVERSION: |
81 | return put_user(inode->i_generation, (int __user *) arg); | 92 | return put_user(inode->i_generation, (int __user *) arg); |
82 | case EXT2_IOC_SETVERSION: | 93 | case EXT2_IOC_SETVERSION: |
83 | if (!is_owner_or_cap(inode)) | 94 | if (!is_owner_or_cap(inode)) |
84 | return -EPERM; | 95 | return -EPERM; |
85 | if (IS_RDONLY(inode)) | 96 | ret = mnt_want_write(filp->f_path.mnt); |
86 | return -EROFS; | 97 | if (ret) |
87 | if (get_user(inode->i_generation, (int __user *) arg)) | 98 | return ret; |
88 | return -EFAULT; | 99 | if (get_user(inode->i_generation, (int __user *) arg)) { |
89 | inode->i_ctime = CURRENT_TIME_SEC; | 100 | ret = -EFAULT; |
90 | mark_inode_dirty(inode); | 101 | } else { |
91 | return 0; | 102 | inode->i_ctime = CURRENT_TIME_SEC; |
103 | mark_inode_dirty(inode); | ||
104 | } | ||
105 | mnt_drop_write(filp->f_path.mnt); | ||
106 | return ret; | ||
92 | case EXT2_IOC_GETRSVSZ: | 107 | case EXT2_IOC_GETRSVSZ: |
93 | if (test_opt(inode->i_sb, RESERVATION) | 108 | if (test_opt(inode->i_sb, RESERVATION) |
94 | && S_ISREG(inode->i_mode) | 109 | && S_ISREG(inode->i_mode) |
@@ -102,15 +117,16 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
102 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) | 117 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) |
103 | return -ENOTTY; | 118 | return -ENOTTY; |
104 | 119 | ||
105 | if (IS_RDONLY(inode)) | 120 | if (!is_owner_or_cap(inode)) |
106 | return -EROFS; | ||
107 | |||
108 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
109 | return -EACCES; | 121 | return -EACCES; |
110 | 122 | ||
111 | if (get_user(rsv_window_size, (int __user *)arg)) | 123 | if (get_user(rsv_window_size, (int __user *)arg)) |
112 | return -EFAULT; | 124 | return -EFAULT; |
113 | 125 | ||
126 | ret = mnt_want_write(filp->f_path.mnt); | ||
127 | if (ret) | ||
128 | return ret; | ||
129 | |||
114 | if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS) | 130 | if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS) |
115 | rsv_window_size = EXT2_MAX_RESERVE_BLOCKS; | 131 | rsv_window_size = EXT2_MAX_RESERVE_BLOCKS; |
116 | 132 | ||
@@ -131,6 +147,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
131 | rsv->rsv_goal_size = rsv_window_size; | 147 | rsv->rsv_goal_size = rsv_window_size; |
132 | } | 148 | } |
133 | mutex_unlock(&ei->truncate_mutex); | 149 | mutex_unlock(&ei->truncate_mutex); |
150 | mnt_drop_write(filp->f_path.mnt); | ||
134 | return 0; | 151 | return 0; |
135 | } | 152 | } |
136 | default: | 153 | default: |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 4f4020c54683..96dd5573e49b 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
@@ -239,7 +239,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) | |||
239 | * it has too few free inodes left (min_inodes) or | 239 | * it has too few free inodes left (min_inodes) or |
240 | * it has too few free blocks left (min_blocks) or | 240 | * it has too few free blocks left (min_blocks) or |
241 | * it's already running too large debt (max_debt). | 241 | * it's already running too large debt (max_debt). |
242 | * Parent's group is prefered, if it doesn't satisfy these | 242 | * Parent's group is preferred, if it doesn't satisfy these |
243 | * conditions we search cyclically through the rest. If none | 243 | * conditions we search cyclically through the rest. If none |
244 | * of the groups look good we just look for a group with more | 244 | * of the groups look good we just look for a group with more |
245 | * free inodes than average (starting at parent's group). | 245 | * free inodes than average (starting at parent's group). |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index eb95670a27eb..c683609b0e3a 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -392,7 +392,7 @@ no_block: | |||
392 | * @inode: owner | 392 | * @inode: owner |
393 | * @ind: descriptor of indirect block. | 393 | * @ind: descriptor of indirect block. |
394 | * | 394 | * |
395 | * This function returns the prefered place for block allocation. | 395 | * This function returns the preferred place for block allocation. |
396 | * It is used when heuristic for sequential allocation fails. | 396 | * It is used when heuristic for sequential allocation fails. |
397 | * Rules are: | 397 | * Rules are: |
398 | * + if there is a block to the left of our position - allocate near it. | 398 | * + if there is a block to the left of our position - allocate near it. |
@@ -436,12 +436,12 @@ static ext3_fsblk_t ext3_find_near(struct inode *inode, Indirect *ind) | |||
436 | } | 436 | } |
437 | 437 | ||
438 | /** | 438 | /** |
439 | * ext3_find_goal - find a prefered place for allocation. | 439 | * ext3_find_goal - find a preferred place for allocation. |
440 | * @inode: owner | 440 | * @inode: owner |
441 | * @block: block we want | 441 | * @block: block we want |
442 | * @partial: pointer to the last triple within a chain | 442 | * @partial: pointer to the last triple within a chain |
443 | * | 443 | * |
444 | * Normally this function find the prefered place for block allocation, | 444 | * Normally this function find the preferred place for block allocation, |
445 | * returns it. | 445 | * returns it. |
446 | */ | 446 | */ |
447 | 447 | ||
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 023a070f55f1..0d0c70151642 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/capability.h> | 12 | #include <linux/capability.h> |
13 | #include <linux/ext3_fs.h> | 13 | #include <linux/ext3_fs.h> |
14 | #include <linux/ext3_jbd.h> | 14 | #include <linux/ext3_jbd.h> |
15 | #include <linux/mount.h> | ||
15 | #include <linux/time.h> | 16 | #include <linux/time.h> |
16 | #include <linux/compat.h> | 17 | #include <linux/compat.h> |
17 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
@@ -38,14 +39,19 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
38 | unsigned int oldflags; | 39 | unsigned int oldflags; |
39 | unsigned int jflag; | 40 | unsigned int jflag; |
40 | 41 | ||
41 | if (IS_RDONLY(inode)) | 42 | err = mnt_want_write(filp->f_path.mnt); |
42 | return -EROFS; | 43 | if (err) |
44 | return err; | ||
43 | 45 | ||
44 | if (!is_owner_or_cap(inode)) | 46 | if (!is_owner_or_cap(inode)) { |
45 | return -EACCES; | 47 | err = -EACCES; |
48 | goto flags_out; | ||
49 | } | ||
46 | 50 | ||
47 | if (get_user(flags, (int __user *) arg)) | 51 | if (get_user(flags, (int __user *) arg)) { |
48 | return -EFAULT; | 52 | err = -EFAULT; |
53 | goto flags_out; | ||
54 | } | ||
49 | 55 | ||
50 | if (!S_ISDIR(inode->i_mode)) | 56 | if (!S_ISDIR(inode->i_mode)) |
51 | flags &= ~EXT3_DIRSYNC_FL; | 57 | flags &= ~EXT3_DIRSYNC_FL; |
@@ -54,7 +60,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
54 | /* Is it quota file? Do not allow user to mess with it */ | 60 | /* Is it quota file? Do not allow user to mess with it */ |
55 | if (IS_NOQUOTA(inode)) { | 61 | if (IS_NOQUOTA(inode)) { |
56 | mutex_unlock(&inode->i_mutex); | 62 | mutex_unlock(&inode->i_mutex); |
57 | return -EPERM; | 63 | err = -EPERM; |
64 | goto flags_out; | ||
58 | } | 65 | } |
59 | oldflags = ei->i_flags; | 66 | oldflags = ei->i_flags; |
60 | 67 | ||
@@ -70,7 +77,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
70 | if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { | 77 | if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { |
71 | if (!capable(CAP_LINUX_IMMUTABLE)) { | 78 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
72 | mutex_unlock(&inode->i_mutex); | 79 | mutex_unlock(&inode->i_mutex); |
73 | return -EPERM; | 80 | err = -EPERM; |
81 | goto flags_out; | ||
74 | } | 82 | } |
75 | } | 83 | } |
76 | 84 | ||
@@ -81,7 +89,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
81 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { | 89 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { |
82 | if (!capable(CAP_SYS_RESOURCE)) { | 90 | if (!capable(CAP_SYS_RESOURCE)) { |
83 | mutex_unlock(&inode->i_mutex); | 91 | mutex_unlock(&inode->i_mutex); |
84 | return -EPERM; | 92 | err = -EPERM; |
93 | goto flags_out; | ||
85 | } | 94 | } |
86 | } | 95 | } |
87 | 96 | ||
@@ -89,7 +98,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
89 | handle = ext3_journal_start(inode, 1); | 98 | handle = ext3_journal_start(inode, 1); |
90 | if (IS_ERR(handle)) { | 99 | if (IS_ERR(handle)) { |
91 | mutex_unlock(&inode->i_mutex); | 100 | mutex_unlock(&inode->i_mutex); |
92 | return PTR_ERR(handle); | 101 | err = PTR_ERR(handle); |
102 | goto flags_out; | ||
93 | } | 103 | } |
94 | if (IS_SYNC(inode)) | 104 | if (IS_SYNC(inode)) |
95 | handle->h_sync = 1; | 105 | handle->h_sync = 1; |
@@ -115,6 +125,8 @@ flags_err: | |||
115 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) | 125 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) |
116 | err = ext3_change_inode_journal_flag(inode, jflag); | 126 | err = ext3_change_inode_journal_flag(inode, jflag); |
117 | mutex_unlock(&inode->i_mutex); | 127 | mutex_unlock(&inode->i_mutex); |
128 | flags_out: | ||
129 | mnt_drop_write(filp->f_path.mnt); | ||
118 | return err; | 130 | return err; |
119 | } | 131 | } |
120 | case EXT3_IOC_GETVERSION: | 132 | case EXT3_IOC_GETVERSION: |
@@ -129,14 +141,18 @@ flags_err: | |||
129 | 141 | ||
130 | if (!is_owner_or_cap(inode)) | 142 | if (!is_owner_or_cap(inode)) |
131 | return -EPERM; | 143 | return -EPERM; |
132 | if (IS_RDONLY(inode)) | 144 | err = mnt_want_write(filp->f_path.mnt); |
133 | return -EROFS; | 145 | if (err) |
134 | if (get_user(generation, (int __user *) arg)) | 146 | return err; |
135 | return -EFAULT; | 147 | if (get_user(generation, (int __user *) arg)) { |
136 | 148 | err = -EFAULT; | |
149 | goto setversion_out; | ||
150 | } | ||
137 | handle = ext3_journal_start(inode, 1); | 151 | handle = ext3_journal_start(inode, 1); |
138 | if (IS_ERR(handle)) | 152 | if (IS_ERR(handle)) { |
139 | return PTR_ERR(handle); | 153 | err = PTR_ERR(handle); |
154 | goto setversion_out; | ||
155 | } | ||
140 | err = ext3_reserve_inode_write(handle, inode, &iloc); | 156 | err = ext3_reserve_inode_write(handle, inode, &iloc); |
141 | if (err == 0) { | 157 | if (err == 0) { |
142 | inode->i_ctime = CURRENT_TIME_SEC; | 158 | inode->i_ctime = CURRENT_TIME_SEC; |
@@ -144,6 +160,8 @@ flags_err: | |||
144 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); | 160 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); |
145 | } | 161 | } |
146 | ext3_journal_stop(handle); | 162 | ext3_journal_stop(handle); |
163 | setversion_out: | ||
164 | mnt_drop_write(filp->f_path.mnt); | ||
147 | return err; | 165 | return err; |
148 | } | 166 | } |
149 | #ifdef CONFIG_JBD_DEBUG | 167 | #ifdef CONFIG_JBD_DEBUG |
@@ -179,18 +197,24 @@ flags_err: | |||
179 | } | 197 | } |
180 | return -ENOTTY; | 198 | return -ENOTTY; |
181 | case EXT3_IOC_SETRSVSZ: { | 199 | case EXT3_IOC_SETRSVSZ: { |
200 | int err; | ||
182 | 201 | ||
183 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) | 202 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) |
184 | return -ENOTTY; | 203 | return -ENOTTY; |
185 | 204 | ||
186 | if (IS_RDONLY(inode)) | 205 | err = mnt_want_write(filp->f_path.mnt); |
187 | return -EROFS; | 206 | if (err) |
207 | return err; | ||
188 | 208 | ||
189 | if (!is_owner_or_cap(inode)) | 209 | if (!is_owner_or_cap(inode)) { |
190 | return -EACCES; | 210 | err = -EACCES; |
211 | goto setrsvsz_out; | ||
212 | } | ||
191 | 213 | ||
192 | if (get_user(rsv_window_size, (int __user *)arg)) | 214 | if (get_user(rsv_window_size, (int __user *)arg)) { |
193 | return -EFAULT; | 215 | err = -EFAULT; |
216 | goto setrsvsz_out; | ||
217 | } | ||
194 | 218 | ||
195 | if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS) | 219 | if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS) |
196 | rsv_window_size = EXT3_MAX_RESERVE_BLOCKS; | 220 | rsv_window_size = EXT3_MAX_RESERVE_BLOCKS; |
@@ -208,7 +232,9 @@ flags_err: | |||
208 | rsv->rsv_goal_size = rsv_window_size; | 232 | rsv->rsv_goal_size = rsv_window_size; |
209 | } | 233 | } |
210 | mutex_unlock(&ei->truncate_mutex); | 234 | mutex_unlock(&ei->truncate_mutex); |
211 | return 0; | 235 | setrsvsz_out: |
236 | mnt_drop_write(filp->f_path.mnt); | ||
237 | return err; | ||
212 | } | 238 | } |
213 | case EXT3_IOC_GROUP_EXTEND: { | 239 | case EXT3_IOC_GROUP_EXTEND: { |
214 | ext3_fsblk_t n_blocks_count; | 240 | ext3_fsblk_t n_blocks_count; |
@@ -218,17 +244,20 @@ flags_err: | |||
218 | if (!capable(CAP_SYS_RESOURCE)) | 244 | if (!capable(CAP_SYS_RESOURCE)) |
219 | return -EPERM; | 245 | return -EPERM; |
220 | 246 | ||
221 | if (IS_RDONLY(inode)) | 247 | err = mnt_want_write(filp->f_path.mnt); |
222 | return -EROFS; | 248 | if (err) |
223 | 249 | return err; | |
224 | if (get_user(n_blocks_count, (__u32 __user *)arg)) | ||
225 | return -EFAULT; | ||
226 | 250 | ||
251 | if (get_user(n_blocks_count, (__u32 __user *)arg)) { | ||
252 | err = -EFAULT; | ||
253 | goto group_extend_out; | ||
254 | } | ||
227 | err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count); | 255 | err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count); |
228 | journal_lock_updates(EXT3_SB(sb)->s_journal); | 256 | journal_lock_updates(EXT3_SB(sb)->s_journal); |
229 | journal_flush(EXT3_SB(sb)->s_journal); | 257 | journal_flush(EXT3_SB(sb)->s_journal); |
230 | journal_unlock_updates(EXT3_SB(sb)->s_journal); | 258 | journal_unlock_updates(EXT3_SB(sb)->s_journal); |
231 | 259 | group_extend_out: | |
260 | mnt_drop_write(filp->f_path.mnt); | ||
232 | return err; | 261 | return err; |
233 | } | 262 | } |
234 | case EXT3_IOC_GROUP_ADD: { | 263 | case EXT3_IOC_GROUP_ADD: { |
@@ -239,18 +268,22 @@ flags_err: | |||
239 | if (!capable(CAP_SYS_RESOURCE)) | 268 | if (!capable(CAP_SYS_RESOURCE)) |
240 | return -EPERM; | 269 | return -EPERM; |
241 | 270 | ||
242 | if (IS_RDONLY(inode)) | 271 | err = mnt_want_write(filp->f_path.mnt); |
243 | return -EROFS; | 272 | if (err) |
273 | return err; | ||
244 | 274 | ||
245 | if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg, | 275 | if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg, |
246 | sizeof(input))) | 276 | sizeof(input))) { |
247 | return -EFAULT; | 277 | err = -EFAULT; |
278 | goto group_add_out; | ||
279 | } | ||
248 | 280 | ||
249 | err = ext3_group_add(sb, &input); | 281 | err = ext3_group_add(sb, &input); |
250 | journal_lock_updates(EXT3_SB(sb)->s_journal); | 282 | journal_lock_updates(EXT3_SB(sb)->s_journal); |
251 | journal_flush(EXT3_SB(sb)->s_journal); | 283 | journal_flush(EXT3_SB(sb)->s_journal); |
252 | journal_unlock_updates(EXT3_SB(sb)->s_journal); | 284 | journal_unlock_updates(EXT3_SB(sb)->s_journal); |
253 | 285 | group_add_out: | |
286 | mnt_drop_write(filp->f_path.mnt); | ||
254 | return err; | 287 | return err; |
255 | } | 288 | } |
256 | 289 | ||
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 8036b9b5376b..486e46a3918d 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -305,7 +305,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent, | |||
305 | * it has too few free inodes left (min_inodes) or | 305 | * it has too few free inodes left (min_inodes) or |
306 | * it has too few free blocks left (min_blocks) or | 306 | * it has too few free blocks left (min_blocks) or |
307 | * it's already running too large debt (max_debt). | 307 | * it's already running too large debt (max_debt). |
308 | * Parent's group is prefered, if it doesn't satisfy these | 308 | * Parent's group is preferred, if it doesn't satisfy these |
309 | * conditions we search cyclically through the rest. If none | 309 | * conditions we search cyclically through the rest. If none |
310 | * of the groups look good we just look for a group with more | 310 | * of the groups look good we just look for a group with more |
311 | * free inodes than average (starting at parent's group). | 311 | * free inodes than average (starting at parent's group). |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 945cbf6cb1fc..8fab233cb05f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -382,7 +382,7 @@ no_block: | |||
382 | * @inode: owner | 382 | * @inode: owner |
383 | * @ind: descriptor of indirect block. | 383 | * @ind: descriptor of indirect block. |
384 | * | 384 | * |
385 | * This function returns the prefered place for block allocation. | 385 | * This function returns the preferred place for block allocation. |
386 | * It is used when heuristic for sequential allocation fails. | 386 | * It is used when heuristic for sequential allocation fails. |
387 | * Rules are: | 387 | * Rules are: |
388 | * + if there is a block to the left of our position - allocate near it. | 388 | * + if there is a block to the left of our position - allocate near it. |
@@ -432,12 +432,12 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | /** | 434 | /** |
435 | * ext4_find_goal - find a prefered place for allocation. | 435 | * ext4_find_goal - find a preferred place for allocation. |
436 | * @inode: owner | 436 | * @inode: owner |
437 | * @block: block we want | 437 | * @block: block we want |
438 | * @partial: pointer to the last triple within a chain | 438 | * @partial: pointer to the last triple within a chain |
439 | * | 439 | * |
440 | * Normally this function find the prefered place for block allocation, | 440 | * Normally this function find the preferred place for block allocation, |
441 | * returns it. | 441 | * returns it. |
442 | */ | 442 | */ |
443 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block, | 443 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block, |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 2ed7c37f897e..25b13ede8086 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
16 | #include <linux/compat.h> | 16 | #include <linux/compat.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/mount.h> | ||
18 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
19 | 20 | ||
20 | int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | 21 | int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, |
@@ -38,24 +39,25 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
38 | unsigned int oldflags; | 39 | unsigned int oldflags; |
39 | unsigned int jflag; | 40 | unsigned int jflag; |
40 | 41 | ||
41 | if (IS_RDONLY(inode)) | ||
42 | return -EROFS; | ||
43 | |||
44 | if (!is_owner_or_cap(inode)) | 42 | if (!is_owner_or_cap(inode)) |
45 | return -EACCES; | 43 | return -EACCES; |
46 | 44 | ||
47 | if (get_user(flags, (int __user *) arg)) | 45 | if (get_user(flags, (int __user *) arg)) |
48 | return -EFAULT; | 46 | return -EFAULT; |
49 | 47 | ||
48 | err = mnt_want_write(filp->f_path.mnt); | ||
49 | if (err) | ||
50 | return err; | ||
51 | |||
50 | if (!S_ISDIR(inode->i_mode)) | 52 | if (!S_ISDIR(inode->i_mode)) |
51 | flags &= ~EXT4_DIRSYNC_FL; | 53 | flags &= ~EXT4_DIRSYNC_FL; |
52 | 54 | ||
55 | err = -EPERM; | ||
53 | mutex_lock(&inode->i_mutex); | 56 | mutex_lock(&inode->i_mutex); |
54 | /* Is it quota file? Do not allow user to mess with it */ | 57 | /* Is it quota file? Do not allow user to mess with it */ |
55 | if (IS_NOQUOTA(inode)) { | 58 | if (IS_NOQUOTA(inode)) |
56 | mutex_unlock(&inode->i_mutex); | 59 | goto flags_out; |
57 | return -EPERM; | 60 | |
58 | } | ||
59 | oldflags = ei->i_flags; | 61 | oldflags = ei->i_flags; |
60 | 62 | ||
61 | /* The JOURNAL_DATA flag is modifiable only by root */ | 63 | /* The JOURNAL_DATA flag is modifiable only by root */ |
@@ -68,10 +70,8 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
68 | * This test looks nicer. Thanks to Pauline Middelink | 70 | * This test looks nicer. Thanks to Pauline Middelink |
69 | */ | 71 | */ |
70 | if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { | 72 | if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) { |
71 | if (!capable(CAP_LINUX_IMMUTABLE)) { | 73 | if (!capable(CAP_LINUX_IMMUTABLE)) |
72 | mutex_unlock(&inode->i_mutex); | 74 | goto flags_out; |
73 | return -EPERM; | ||
74 | } | ||
75 | } | 75 | } |
76 | 76 | ||
77 | /* | 77 | /* |
@@ -79,17 +79,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
79 | * the relevant capability. | 79 | * the relevant capability. |
80 | */ | 80 | */ |
81 | if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { | 81 | if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) { |
82 | if (!capable(CAP_SYS_RESOURCE)) { | 82 | if (!capable(CAP_SYS_RESOURCE)) |
83 | mutex_unlock(&inode->i_mutex); | 83 | goto flags_out; |
84 | return -EPERM; | ||
85 | } | ||
86 | } | 84 | } |
87 | 85 | ||
88 | |||
89 | handle = ext4_journal_start(inode, 1); | 86 | handle = ext4_journal_start(inode, 1); |
90 | if (IS_ERR(handle)) { | 87 | if (IS_ERR(handle)) { |
91 | mutex_unlock(&inode->i_mutex); | 88 | err = PTR_ERR(handle); |
92 | return PTR_ERR(handle); | 89 | goto flags_out; |
93 | } | 90 | } |
94 | if (IS_SYNC(inode)) | 91 | if (IS_SYNC(inode)) |
95 | handle->h_sync = 1; | 92 | handle->h_sync = 1; |
@@ -107,14 +104,14 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
107 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); | 104 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
108 | flags_err: | 105 | flags_err: |
109 | ext4_journal_stop(handle); | 106 | ext4_journal_stop(handle); |
110 | if (err) { | 107 | if (err) |
111 | mutex_unlock(&inode->i_mutex); | 108 | goto flags_out; |
112 | return err; | ||
113 | } | ||
114 | 109 | ||
115 | if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) | 110 | if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) |
116 | err = ext4_change_inode_journal_flag(inode, jflag); | 111 | err = ext4_change_inode_journal_flag(inode, jflag); |
112 | flags_out: | ||
117 | mutex_unlock(&inode->i_mutex); | 113 | mutex_unlock(&inode->i_mutex); |
114 | mnt_drop_write(filp->f_path.mnt); | ||
118 | return err; | 115 | return err; |
119 | } | 116 | } |
120 | case EXT4_IOC_GETVERSION: | 117 | case EXT4_IOC_GETVERSION: |
@@ -129,14 +126,20 @@ flags_err: | |||
129 | 126 | ||
130 | if (!is_owner_or_cap(inode)) | 127 | if (!is_owner_or_cap(inode)) |
131 | return -EPERM; | 128 | return -EPERM; |
132 | if (IS_RDONLY(inode)) | 129 | |
133 | return -EROFS; | 130 | err = mnt_want_write(filp->f_path.mnt); |
134 | if (get_user(generation, (int __user *) arg)) | 131 | if (err) |
135 | return -EFAULT; | 132 | return err; |
133 | if (get_user(generation, (int __user *) arg)) { | ||
134 | err = -EFAULT; | ||
135 | goto setversion_out; | ||
136 | } | ||
136 | 137 | ||
137 | handle = ext4_journal_start(inode, 1); | 138 | handle = ext4_journal_start(inode, 1); |
138 | if (IS_ERR(handle)) | 139 | if (IS_ERR(handle)) { |
139 | return PTR_ERR(handle); | 140 | err = PTR_ERR(handle); |
141 | goto setversion_out; | ||
142 | } | ||
140 | err = ext4_reserve_inode_write(handle, inode, &iloc); | 143 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
141 | if (err == 0) { | 144 | if (err == 0) { |
142 | inode->i_ctime = ext4_current_time(inode); | 145 | inode->i_ctime = ext4_current_time(inode); |
@@ -144,6 +147,8 @@ flags_err: | |||
144 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); | 147 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
145 | } | 148 | } |
146 | ext4_journal_stop(handle); | 149 | ext4_journal_stop(handle); |
150 | setversion_out: | ||
151 | mnt_drop_write(filp->f_path.mnt); | ||
147 | return err; | 152 | return err; |
148 | } | 153 | } |
149 | #ifdef CONFIG_JBD2_DEBUG | 154 | #ifdef CONFIG_JBD2_DEBUG |
@@ -179,19 +184,21 @@ flags_err: | |||
179 | } | 184 | } |
180 | return -ENOTTY; | 185 | return -ENOTTY; |
181 | case EXT4_IOC_SETRSVSZ: { | 186 | case EXT4_IOC_SETRSVSZ: { |
187 | int err; | ||
182 | 188 | ||
183 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) | 189 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) |
184 | return -ENOTTY; | 190 | return -ENOTTY; |
185 | 191 | ||
186 | if (IS_RDONLY(inode)) | ||
187 | return -EROFS; | ||
188 | |||
189 | if (!is_owner_or_cap(inode)) | 192 | if (!is_owner_or_cap(inode)) |
190 | return -EACCES; | 193 | return -EACCES; |
191 | 194 | ||
192 | if (get_user(rsv_window_size, (int __user *)arg)) | 195 | if (get_user(rsv_window_size, (int __user *)arg)) |
193 | return -EFAULT; | 196 | return -EFAULT; |
194 | 197 | ||
198 | err = mnt_want_write(filp->f_path.mnt); | ||
199 | if (err) | ||
200 | return err; | ||
201 | |||
195 | if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS) | 202 | if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS) |
196 | rsv_window_size = EXT4_MAX_RESERVE_BLOCKS; | 203 | rsv_window_size = EXT4_MAX_RESERVE_BLOCKS; |
197 | 204 | ||
@@ -208,6 +215,7 @@ flags_err: | |||
208 | rsv->rsv_goal_size = rsv_window_size; | 215 | rsv->rsv_goal_size = rsv_window_size; |
209 | } | 216 | } |
210 | up_write(&ei->i_data_sem); | 217 | up_write(&ei->i_data_sem); |
218 | mnt_drop_write(filp->f_path.mnt); | ||
211 | return 0; | 219 | return 0; |
212 | } | 220 | } |
213 | case EXT4_IOC_GROUP_EXTEND: { | 221 | case EXT4_IOC_GROUP_EXTEND: { |
@@ -218,16 +226,18 @@ flags_err: | |||
218 | if (!capable(CAP_SYS_RESOURCE)) | 226 | if (!capable(CAP_SYS_RESOURCE)) |
219 | return -EPERM; | 227 | return -EPERM; |
220 | 228 | ||
221 | if (IS_RDONLY(inode)) | ||
222 | return -EROFS; | ||
223 | |||
224 | if (get_user(n_blocks_count, (__u32 __user *)arg)) | 229 | if (get_user(n_blocks_count, (__u32 __user *)arg)) |
225 | return -EFAULT; | 230 | return -EFAULT; |
226 | 231 | ||
232 | err = mnt_want_write(filp->f_path.mnt); | ||
233 | if (err) | ||
234 | return err; | ||
235 | |||
227 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); | 236 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); |
228 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 237 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
229 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 238 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
230 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 239 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
240 | mnt_drop_write(filp->f_path.mnt); | ||
231 | 241 | ||
232 | return err; | 242 | return err; |
233 | } | 243 | } |
@@ -239,17 +249,19 @@ flags_err: | |||
239 | if (!capable(CAP_SYS_RESOURCE)) | 249 | if (!capable(CAP_SYS_RESOURCE)) |
240 | return -EPERM; | 250 | return -EPERM; |
241 | 251 | ||
242 | if (IS_RDONLY(inode)) | ||
243 | return -EROFS; | ||
244 | |||
245 | if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, | 252 | if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, |
246 | sizeof(input))) | 253 | sizeof(input))) |
247 | return -EFAULT; | 254 | return -EFAULT; |
248 | 255 | ||
256 | err = mnt_want_write(filp->f_path.mnt); | ||
257 | if (err) | ||
258 | return err; | ||
259 | |||
249 | err = ext4_group_add(sb, &input); | 260 | err = ext4_group_add(sb, &input); |
250 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 261 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
251 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 262 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
252 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 263 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
264 | mnt_drop_write(filp->f_path.mnt); | ||
253 | 265 | ||
254 | return err; | 266 | return err; |
255 | } | 267 | } |
diff --git a/fs/fat/file.c b/fs/fat/file.c index c614175876e0..2a3bed967041 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/capability.h> | 9 | #include <linux/capability.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/mount.h> | ||
11 | #include <linux/time.h> | 12 | #include <linux/time.h> |
12 | #include <linux/msdos_fs.h> | 13 | #include <linux/msdos_fs.h> |
13 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
@@ -46,10 +47,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
46 | 47 | ||
47 | mutex_lock(&inode->i_mutex); | 48 | mutex_lock(&inode->i_mutex); |
48 | 49 | ||
49 | if (IS_RDONLY(inode)) { | 50 | err = mnt_want_write(filp->f_path.mnt); |
50 | err = -EROFS; | 51 | if (err) |
51 | goto up; | 52 | goto up_no_drop_write; |
52 | } | ||
53 | 53 | ||
54 | /* | 54 | /* |
55 | * ATTR_VOLUME and ATTR_DIR cannot be changed; this also | 55 | * ATTR_VOLUME and ATTR_DIR cannot be changed; this also |
@@ -105,7 +105,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
105 | 105 | ||
106 | MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; | 106 | MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; |
107 | mark_inode_dirty(inode); | 107 | mark_inode_dirty(inode); |
108 | up: | 108 | up: |
109 | mnt_drop_write(filp->f_path.mnt); | ||
110 | up_no_drop_write: | ||
109 | mutex_unlock(&inode->i_mutex); | 111 | mutex_unlock(&inode->i_mutex); |
110 | return err; | 112 | return err; |
111 | } | 113 | } |
diff --git a/fs/file_table.c b/fs/file_table.c index 986ff4ed0a7c..7a0a9b872251 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -42,6 +42,7 @@ static inline void file_free_rcu(struct rcu_head *head) | |||
42 | static inline void file_free(struct file *f) | 42 | static inline void file_free(struct file *f) |
43 | { | 43 | { |
44 | percpu_counter_dec(&nr_files); | 44 | percpu_counter_dec(&nr_files); |
45 | file_check_state(f); | ||
45 | call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); | 46 | call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); |
46 | } | 47 | } |
47 | 48 | ||
@@ -199,6 +200,18 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry, | |||
199 | file->f_mapping = dentry->d_inode->i_mapping; | 200 | file->f_mapping = dentry->d_inode->i_mapping; |
200 | file->f_mode = mode; | 201 | file->f_mode = mode; |
201 | file->f_op = fop; | 202 | file->f_op = fop; |
203 | |||
204 | /* | ||
205 | * These mounts don't really matter in practice | ||
206 | * for r/o bind mounts. They aren't userspace- | ||
207 | * visible. We do this for consistency, and so | ||
208 | * that we can do debugging checks at __fput() | ||
209 | */ | ||
210 | if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) { | ||
211 | file_take_write(file); | ||
212 | error = mnt_want_write(mnt); | ||
213 | WARN_ON(error); | ||
214 | } | ||
202 | return error; | 215 | return error; |
203 | } | 216 | } |
204 | EXPORT_SYMBOL(init_file); | 217 | EXPORT_SYMBOL(init_file); |
@@ -211,6 +224,31 @@ void fput(struct file *file) | |||
211 | 224 | ||
212 | EXPORT_SYMBOL(fput); | 225 | EXPORT_SYMBOL(fput); |
213 | 226 | ||
227 | /** | ||
228 | * drop_file_write_access - give up ability to write to a file | ||
229 | * @file: the file to which we will stop writing | ||
230 | * | ||
231 | * This is a central place which will give up the ability | ||
232 | * to write to @file, along with access to write through | ||
233 | * its vfsmount. | ||
234 | */ | ||
235 | void drop_file_write_access(struct file *file) | ||
236 | { | ||
237 | struct vfsmount *mnt = file->f_path.mnt; | ||
238 | struct dentry *dentry = file->f_path.dentry; | ||
239 | struct inode *inode = dentry->d_inode; | ||
240 | |||
241 | put_write_access(inode); | ||
242 | |||
243 | if (special_file(inode->i_mode)) | ||
244 | return; | ||
245 | if (file_check_writeable(file) != 0) | ||
246 | return; | ||
247 | mnt_drop_write(mnt); | ||
248 | file_release_write(file); | ||
249 | } | ||
250 | EXPORT_SYMBOL_GPL(drop_file_write_access); | ||
251 | |||
214 | /* __fput is called from task context when aio completion releases the last | 252 | /* __fput is called from task context when aio completion releases the last |
215 | * last use of a struct file *. Do not use otherwise. | 253 | * last use of a struct file *. Do not use otherwise. |
216 | */ | 254 | */ |
@@ -236,10 +274,10 @@ void __fput(struct file *file) | |||
236 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) | 274 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) |
237 | cdev_put(inode->i_cdev); | 275 | cdev_put(inode->i_cdev); |
238 | fops_put(file->f_op); | 276 | fops_put(file->f_op); |
239 | if (file->f_mode & FMODE_WRITE) | ||
240 | put_write_access(inode); | ||
241 | put_pid(file->f_owner.pid); | 277 | put_pid(file->f_owner.pid); |
242 | file_kill(file); | 278 | file_kill(file); |
279 | if (file->f_mode & FMODE_WRITE) | ||
280 | drop_file_write_access(file); | ||
243 | file->f_path.dentry = NULL; | 281 | file->f_path.dentry = NULL; |
244 | file->f_path.mnt = NULL; | 282 | file->f_path.mnt = NULL; |
245 | file_free(file); | 283 | file_free(file); |
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index b60c0affbec5..f457d2ca51ab 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/capability.h> | 15 | #include <linux/capability.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/mount.h> | ||
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/xattr.h> | 19 | #include <linux/xattr.h> |
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
@@ -35,25 +36,32 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
35 | flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ | 36 | flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ |
36 | return put_user(flags, (int __user *)arg); | 37 | return put_user(flags, (int __user *)arg); |
37 | case HFSPLUS_IOC_EXT2_SETFLAGS: { | 38 | case HFSPLUS_IOC_EXT2_SETFLAGS: { |
38 | if (IS_RDONLY(inode)) | 39 | int err = 0; |
39 | return -EROFS; | 40 | err = mnt_want_write(filp->f_path.mnt); |
40 | 41 | if (err) | |
41 | if (!is_owner_or_cap(inode)) | 42 | return err; |
42 | return -EACCES; | 43 | |
43 | 44 | if (!is_owner_or_cap(inode)) { | |
44 | if (get_user(flags, (int __user *)arg)) | 45 | err = -EACCES; |
45 | return -EFAULT; | 46 | goto setflags_out; |
46 | 47 | } | |
48 | if (get_user(flags, (int __user *)arg)) { | ||
49 | err = -EFAULT; | ||
50 | goto setflags_out; | ||
51 | } | ||
47 | if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || | 52 | if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || |
48 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { | 53 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { |
49 | if (!capable(CAP_LINUX_IMMUTABLE)) | 54 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
50 | return -EPERM; | 55 | err = -EPERM; |
56 | goto setflags_out; | ||
57 | } | ||
51 | } | 58 | } |
52 | 59 | ||
53 | /* don't silently ignore unsupported ext2 flags */ | 60 | /* don't silently ignore unsupported ext2 flags */ |
54 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) | 61 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { |
55 | return -EOPNOTSUPP; | 62 | err = -EOPNOTSUPP; |
56 | 63 | goto setflags_out; | |
64 | } | ||
57 | if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ | 65 | if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ |
58 | inode->i_flags |= S_IMMUTABLE; | 66 | inode->i_flags |= S_IMMUTABLE; |
59 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; | 67 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; |
@@ -75,7 +83,9 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
75 | 83 | ||
76 | inode->i_ctime = CURRENT_TIME_SEC; | 84 | inode->i_ctime = CURRENT_TIME_SEC; |
77 | mark_inode_dirty(inode); | 85 | mark_inode_dirty(inode); |
78 | return 0; | 86 | setflags_out: |
87 | mnt_drop_write(filp->f_path.mnt); | ||
88 | return err; | ||
79 | } | 89 | } |
80 | default: | 90 | default: |
81 | return -ENOTTY; | 91 | return -ENOTTY; |
diff --git a/fs/inode.c b/fs/inode.c index 53245ffcf93d..27ee1af50d02 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1199,42 +1199,37 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) | |||
1199 | struct inode *inode = dentry->d_inode; | 1199 | struct inode *inode = dentry->d_inode; |
1200 | struct timespec now; | 1200 | struct timespec now; |
1201 | 1201 | ||
1202 | if (inode->i_flags & S_NOATIME) | 1202 | if (mnt_want_write(mnt)) |
1203 | return; | 1203 | return; |
1204 | if (inode->i_flags & S_NOATIME) | ||
1205 | goto out; | ||
1204 | if (IS_NOATIME(inode)) | 1206 | if (IS_NOATIME(inode)) |
1205 | return; | 1207 | goto out; |
1206 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1208 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) |
1207 | return; | 1209 | goto out; |
1208 | 1210 | ||
1209 | /* | 1211 | if (mnt->mnt_flags & MNT_NOATIME) |
1210 | * We may have a NULL vfsmount when coming from NFSD | 1212 | goto out; |
1211 | */ | 1213 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) |
1212 | if (mnt) { | 1214 | goto out; |
1213 | if (mnt->mnt_flags & MNT_NOATIME) | 1215 | if (mnt->mnt_flags & MNT_RELATIME) { |
1214 | return; | 1216 | /* |
1215 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1217 | * With relative atime, only update atime if the previous |
1216 | return; | 1218 | * atime is earlier than either the ctime or mtime. |
1217 | 1219 | */ | |
1218 | if (mnt->mnt_flags & MNT_RELATIME) { | 1220 | if (timespec_compare(&inode->i_mtime, &inode->i_atime) < 0 && |
1219 | /* | 1221 | timespec_compare(&inode->i_ctime, &inode->i_atime) < 0) |
1220 | * With relative atime, only update atime if the | 1222 | goto out; |
1221 | * previous atime is earlier than either the ctime or | ||
1222 | * mtime. | ||
1223 | */ | ||
1224 | if (timespec_compare(&inode->i_mtime, | ||
1225 | &inode->i_atime) < 0 && | ||
1226 | timespec_compare(&inode->i_ctime, | ||
1227 | &inode->i_atime) < 0) | ||
1228 | return; | ||
1229 | } | ||
1230 | } | 1223 | } |
1231 | 1224 | ||
1232 | now = current_fs_time(inode->i_sb); | 1225 | now = current_fs_time(inode->i_sb); |
1233 | if (timespec_equal(&inode->i_atime, &now)) | 1226 | if (timespec_equal(&inode->i_atime, &now)) |
1234 | return; | 1227 | goto out; |
1235 | 1228 | ||
1236 | inode->i_atime = now; | 1229 | inode->i_atime = now; |
1237 | mark_inode_dirty_sync(inode); | 1230 | mark_inode_dirty_sync(inode); |
1231 | out: | ||
1232 | mnt_drop_write(mnt); | ||
1238 | } | 1233 | } |
1239 | EXPORT_SYMBOL(touch_atime); | 1234 | EXPORT_SYMBOL(touch_atime); |
1240 | 1235 | ||
@@ -1255,10 +1250,13 @@ void file_update_time(struct file *file) | |||
1255 | struct inode *inode = file->f_path.dentry->d_inode; | 1250 | struct inode *inode = file->f_path.dentry->d_inode; |
1256 | struct timespec now; | 1251 | struct timespec now; |
1257 | int sync_it = 0; | 1252 | int sync_it = 0; |
1253 | int err; | ||
1258 | 1254 | ||
1259 | if (IS_NOCMTIME(inode)) | 1255 | if (IS_NOCMTIME(inode)) |
1260 | return; | 1256 | return; |
1261 | if (IS_RDONLY(inode)) | 1257 | |
1258 | err = mnt_want_write(file->f_path.mnt); | ||
1259 | if (err) | ||
1262 | return; | 1260 | return; |
1263 | 1261 | ||
1264 | now = current_fs_time(inode->i_sb); | 1262 | now = current_fs_time(inode->i_sb); |
@@ -1279,6 +1277,7 @@ void file_update_time(struct file *file) | |||
1279 | 1277 | ||
1280 | if (sync_it) | 1278 | if (sync_it) |
1281 | mark_inode_dirty_sync(inode); | 1279 | mark_inode_dirty_sync(inode); |
1280 | mnt_drop_write(file->f_path.mnt); | ||
1282 | } | 1281 | } |
1283 | 1282 | ||
1284 | EXPORT_SYMBOL(file_update_time); | 1283 | EXPORT_SYMBOL(file_update_time); |
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 0b78fdc9773b..a841f4973a74 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/version.h> | 15 | #include <linux/version.h> |
16 | #include <linux/rbtree.h> | 16 | #include <linux/rbtree.h> |
17 | #include <linux/posix_acl.h> | 17 | #include <linux/posix_acl.h> |
18 | #include <asm/semaphore.h> | 18 | #include <linux/semaphore.h> |
19 | 19 | ||
20 | struct jffs2_inode_info { | 20 | struct jffs2_inode_info { |
21 | /* We need an internal mutex similar to inode->i_mutex. | 21 | /* We need an internal mutex similar to inode->i_mutex. |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 3a2197f3c812..18fca2b9e531 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
18 | #include <linux/completion.h> | 18 | #include <linux/completion.h> |
19 | #include <asm/semaphore.h> | 19 | #include <linux/semaphore.h> |
20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
21 | #include <linux/wait.h> | 21 | #include <linux/wait.h> |
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index a1f8e375ad21..afe222bf300f 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include <linux/ctype.h> | 9 | #include <linux/ctype.h> |
10 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
11 | #include <linux/mount.h> | ||
11 | #include <linux/time.h> | 12 | #include <linux/time.h> |
12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
13 | #include <asm/current.h> | 14 | #include <asm/current.h> |
@@ -65,23 +66,30 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
65 | return put_user(flags, (int __user *) arg); | 66 | return put_user(flags, (int __user *) arg); |
66 | case JFS_IOC_SETFLAGS: { | 67 | case JFS_IOC_SETFLAGS: { |
67 | unsigned int oldflags; | 68 | unsigned int oldflags; |
69 | int err; | ||
68 | 70 | ||
69 | if (IS_RDONLY(inode)) | 71 | err = mnt_want_write(filp->f_path.mnt); |
70 | return -EROFS; | 72 | if (err) |
73 | return err; | ||
71 | 74 | ||
72 | if (!is_owner_or_cap(inode)) | 75 | if (!is_owner_or_cap(inode)) { |
73 | return -EACCES; | 76 | err = -EACCES; |
74 | 77 | goto setflags_out; | |
75 | if (get_user(flags, (int __user *) arg)) | 78 | } |
76 | return -EFAULT; | 79 | if (get_user(flags, (int __user *) arg)) { |
80 | err = -EFAULT; | ||
81 | goto setflags_out; | ||
82 | } | ||
77 | 83 | ||
78 | flags = jfs_map_ext2(flags, 1); | 84 | flags = jfs_map_ext2(flags, 1); |
79 | if (!S_ISDIR(inode->i_mode)) | 85 | if (!S_ISDIR(inode->i_mode)) |
80 | flags &= ~JFS_DIRSYNC_FL; | 86 | flags &= ~JFS_DIRSYNC_FL; |
81 | 87 | ||
82 | /* Is it quota file? Do not allow user to mess with it */ | 88 | /* Is it quota file? Do not allow user to mess with it */ |
83 | if (IS_NOQUOTA(inode)) | 89 | if (IS_NOQUOTA(inode)) { |
84 | return -EPERM; | 90 | err = -EPERM; |
91 | goto setflags_out; | ||
92 | } | ||
85 | 93 | ||
86 | /* Lock against other parallel changes of flags */ | 94 | /* Lock against other parallel changes of flags */ |
87 | mutex_lock(&inode->i_mutex); | 95 | mutex_lock(&inode->i_mutex); |
@@ -98,7 +106,8 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
98 | (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) { | 106 | (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) { |
99 | if (!capable(CAP_LINUX_IMMUTABLE)) { | 107 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
100 | mutex_unlock(&inode->i_mutex); | 108 | mutex_unlock(&inode->i_mutex); |
101 | return -EPERM; | 109 | err = -EPERM; |
110 | goto setflags_out; | ||
102 | } | 111 | } |
103 | } | 112 | } |
104 | 113 | ||
@@ -110,7 +119,9 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
110 | mutex_unlock(&inode->i_mutex); | 119 | mutex_unlock(&inode->i_mutex); |
111 | inode->i_ctime = CURRENT_TIME_SEC; | 120 | inode->i_ctime = CURRENT_TIME_SEC; |
112 | mark_inode_dirty(inode); | 121 | mark_inode_dirty(inode); |
113 | return 0; | 122 | setflags_out: |
123 | mnt_drop_write(filp->f_path.mnt); | ||
124 | return err; | ||
114 | } | 125 | } |
115 | default: | 126 | default: |
116 | return -ENOTTY; | 127 | return -ENOTTY; |
diff --git a/fs/locks.c b/fs/locks.c index 43c0af21a0c5..592faadbcec1 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -127,7 +127,6 @@ | |||
127 | #include <linux/rcupdate.h> | 127 | #include <linux/rcupdate.h> |
128 | #include <linux/pid_namespace.h> | 128 | #include <linux/pid_namespace.h> |
129 | 129 | ||
130 | #include <asm/semaphore.h> | ||
131 | #include <asm/uaccess.h> | 130 | #include <asm/uaccess.h> |
132 | 131 | ||
133 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) | 132 | #define IS_POSIX(fl) (fl->fl_flags & FL_POSIX) |
diff --git a/fs/namei.c b/fs/namei.c index 8cf9bb9c2fc0..e179f71bfcb0 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1623,8 +1623,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1623 | return -EACCES; | 1623 | return -EACCES; |
1624 | 1624 | ||
1625 | flag &= ~O_TRUNC; | 1625 | flag &= ~O_TRUNC; |
1626 | } else if (IS_RDONLY(inode) && (acc_mode & MAY_WRITE)) | 1626 | } |
1627 | return -EROFS; | ||
1628 | 1627 | ||
1629 | error = vfs_permission(nd, acc_mode); | 1628 | error = vfs_permission(nd, acc_mode); |
1630 | if (error) | 1629 | if (error) |
@@ -1677,7 +1676,12 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1677 | return 0; | 1676 | return 0; |
1678 | } | 1677 | } |
1679 | 1678 | ||
1680 | static int open_namei_create(struct nameidata *nd, struct path *path, | 1679 | /* |
1680 | * Be careful about ever adding any more callers of this | ||
1681 | * function. Its flags must be in the namei format, not | ||
1682 | * what get passed to sys_open(). | ||
1683 | */ | ||
1684 | static int __open_namei_create(struct nameidata *nd, struct path *path, | ||
1681 | int flag, int mode) | 1685 | int flag, int mode) |
1682 | { | 1686 | { |
1683 | int error; | 1687 | int error; |
@@ -1696,26 +1700,56 @@ static int open_namei_create(struct nameidata *nd, struct path *path, | |||
1696 | } | 1700 | } |
1697 | 1701 | ||
1698 | /* | 1702 | /* |
1699 | * open_namei() | 1703 | * Note that while the flag value (low two bits) for sys_open means: |
1704 | * 00 - read-only | ||
1705 | * 01 - write-only | ||
1706 | * 10 - read-write | ||
1707 | * 11 - special | ||
1708 | * it is changed into | ||
1709 | * 00 - no permissions needed | ||
1710 | * 01 - read-permission | ||
1711 | * 10 - write-permission | ||
1712 | * 11 - read-write | ||
1713 | * for the internal routines (ie open_namei()/follow_link() etc) | ||
1714 | * This is more logical, and also allows the 00 "no perm needed" | ||
1715 | * to be used for symlinks (where the permissions are checked | ||
1716 | * later). | ||
1700 | * | 1717 | * |
1701 | * namei for open - this is in fact almost the whole open-routine. | 1718 | */ |
1702 | * | 1719 | static inline int open_to_namei_flags(int flag) |
1703 | * Note that the low bits of "flag" aren't the same as in the open | 1720 | { |
1704 | * system call - they are 00 - no permissions needed | 1721 | if ((flag+1) & O_ACCMODE) |
1705 | * 01 - read permission needed | 1722 | flag++; |
1706 | * 10 - write permission needed | 1723 | return flag; |
1707 | * 11 - read/write permissions needed | 1724 | } |
1708 | * which is a lot more logical, and also allows the "no perm" needed | 1725 | |
1709 | * for symlinks (where the permissions are checked later). | 1726 | static int open_will_write_to_fs(int flag, struct inode *inode) |
1710 | * SMP-safe | 1727 | { |
1728 | /* | ||
1729 | * We'll never write to the fs underlying | ||
1730 | * a device file. | ||
1731 | */ | ||
1732 | if (special_file(inode->i_mode)) | ||
1733 | return 0; | ||
1734 | return (flag & O_TRUNC); | ||
1735 | } | ||
1736 | |||
1737 | /* | ||
1738 | * Note that the low bits of the passed in "open_flag" | ||
1739 | * are not the same as in the local variable "flag". See | ||
1740 | * open_to_namei_flags() for more details. | ||
1711 | */ | 1741 | */ |
1712 | int open_namei(int dfd, const char *pathname, int flag, | 1742 | struct file *do_filp_open(int dfd, const char *pathname, |
1713 | int mode, struct nameidata *nd) | 1743 | int open_flag, int mode) |
1714 | { | 1744 | { |
1745 | struct file *filp; | ||
1746 | struct nameidata nd; | ||
1715 | int acc_mode, error; | 1747 | int acc_mode, error; |
1716 | struct path path; | 1748 | struct path path; |
1717 | struct dentry *dir; | 1749 | struct dentry *dir; |
1718 | int count = 0; | 1750 | int count = 0; |
1751 | int will_write; | ||
1752 | int flag = open_to_namei_flags(open_flag); | ||
1719 | 1753 | ||
1720 | acc_mode = ACC_MODE(flag); | 1754 | acc_mode = ACC_MODE(flag); |
1721 | 1755 | ||
@@ -1733,18 +1767,19 @@ int open_namei(int dfd, const char *pathname, int flag, | |||
1733 | */ | 1767 | */ |
1734 | if (!(flag & O_CREAT)) { | 1768 | if (!(flag & O_CREAT)) { |
1735 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), | 1769 | error = path_lookup_open(dfd, pathname, lookup_flags(flag), |
1736 | nd, flag); | 1770 | &nd, flag); |
1737 | if (error) | 1771 | if (error) |
1738 | return error; | 1772 | return ERR_PTR(error); |
1739 | goto ok; | 1773 | goto ok; |
1740 | } | 1774 | } |
1741 | 1775 | ||
1742 | /* | 1776 | /* |
1743 | * Create - we need to know the parent. | 1777 | * Create - we need to know the parent. |
1744 | */ | 1778 | */ |
1745 | error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); | 1779 | error = path_lookup_create(dfd, pathname, LOOKUP_PARENT, |
1780 | &nd, flag, mode); | ||
1746 | if (error) | 1781 | if (error) |
1747 | return error; | 1782 | return ERR_PTR(error); |
1748 | 1783 | ||
1749 | /* | 1784 | /* |
1750 | * We have the parent and last component. First of all, check | 1785 | * We have the parent and last component. First of all, check |
@@ -1752,14 +1787,14 @@ int open_namei(int dfd, const char *pathname, int flag, | |||
1752 | * will not do. | 1787 | * will not do. |
1753 | */ | 1788 | */ |
1754 | error = -EISDIR; | 1789 | error = -EISDIR; |
1755 | if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) | 1790 | if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len]) |
1756 | goto exit; | 1791 | goto exit; |
1757 | 1792 | ||
1758 | dir = nd->path.dentry; | 1793 | dir = nd.path.dentry; |
1759 | nd->flags &= ~LOOKUP_PARENT; | 1794 | nd.flags &= ~LOOKUP_PARENT; |
1760 | mutex_lock(&dir->d_inode->i_mutex); | 1795 | mutex_lock(&dir->d_inode->i_mutex); |
1761 | path.dentry = lookup_hash(nd); | 1796 | path.dentry = lookup_hash(&nd); |
1762 | path.mnt = nd->path.mnt; | 1797 | path.mnt = nd.path.mnt; |
1763 | 1798 | ||
1764 | do_last: | 1799 | do_last: |
1765 | error = PTR_ERR(path.dentry); | 1800 | error = PTR_ERR(path.dentry); |
@@ -1768,18 +1803,31 @@ do_last: | |||
1768 | goto exit; | 1803 | goto exit; |
1769 | } | 1804 | } |
1770 | 1805 | ||
1771 | if (IS_ERR(nd->intent.open.file)) { | 1806 | if (IS_ERR(nd.intent.open.file)) { |
1772 | mutex_unlock(&dir->d_inode->i_mutex); | 1807 | error = PTR_ERR(nd.intent.open.file); |
1773 | error = PTR_ERR(nd->intent.open.file); | 1808 | goto exit_mutex_unlock; |
1774 | goto exit_dput; | ||
1775 | } | 1809 | } |
1776 | 1810 | ||
1777 | /* Negative dentry, just create the file */ | 1811 | /* Negative dentry, just create the file */ |
1778 | if (!path.dentry->d_inode) { | 1812 | if (!path.dentry->d_inode) { |
1779 | error = open_namei_create(nd, &path, flag, mode); | 1813 | /* |
1814 | * This write is needed to ensure that a | ||
1815 | * ro->rw transition does not occur between | ||
1816 | * the time when the file is created and when | ||
1817 | * a permanent write count is taken through | ||
1818 | * the 'struct file' in nameidata_to_filp(). | ||
1819 | */ | ||
1820 | error = mnt_want_write(nd.path.mnt); | ||
1780 | if (error) | 1821 | if (error) |
1822 | goto exit_mutex_unlock; | ||
1823 | error = __open_namei_create(&nd, &path, flag, mode); | ||
1824 | if (error) { | ||
1825 | mnt_drop_write(nd.path.mnt); | ||
1781 | goto exit; | 1826 | goto exit; |
1782 | return 0; | 1827 | } |
1828 | filp = nameidata_to_filp(&nd, open_flag); | ||
1829 | mnt_drop_write(nd.path.mnt); | ||
1830 | return filp; | ||
1783 | } | 1831 | } |
1784 | 1832 | ||
1785 | /* | 1833 | /* |
@@ -1804,23 +1852,52 @@ do_last: | |||
1804 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) | 1852 | if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) |
1805 | goto do_link; | 1853 | goto do_link; |
1806 | 1854 | ||
1807 | path_to_nameidata(&path, nd); | 1855 | path_to_nameidata(&path, &nd); |
1808 | error = -EISDIR; | 1856 | error = -EISDIR; |
1809 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) | 1857 | if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) |
1810 | goto exit; | 1858 | goto exit; |
1811 | ok: | 1859 | ok: |
1812 | error = may_open(nd, acc_mode, flag); | 1860 | /* |
1813 | if (error) | 1861 | * Consider: |
1862 | * 1. may_open() truncates a file | ||
1863 | * 2. a rw->ro mount transition occurs | ||
1864 | * 3. nameidata_to_filp() fails due to | ||
1865 | * the ro mount. | ||
1866 | * That would be inconsistent, and should | ||
1867 | * be avoided. Taking this mnt write here | ||
1868 | * ensures that (2) can not occur. | ||
1869 | */ | ||
1870 | will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode); | ||
1871 | if (will_write) { | ||
1872 | error = mnt_want_write(nd.path.mnt); | ||
1873 | if (error) | ||
1874 | goto exit; | ||
1875 | } | ||
1876 | error = may_open(&nd, acc_mode, flag); | ||
1877 | if (error) { | ||
1878 | if (will_write) | ||
1879 | mnt_drop_write(nd.path.mnt); | ||
1814 | goto exit; | 1880 | goto exit; |
1815 | return 0; | 1881 | } |
1882 | filp = nameidata_to_filp(&nd, open_flag); | ||
1883 | /* | ||
1884 | * It is now safe to drop the mnt write | ||
1885 | * because the filp has had a write taken | ||
1886 | * on its behalf. | ||
1887 | */ | ||
1888 | if (will_write) | ||
1889 | mnt_drop_write(nd.path.mnt); | ||
1890 | return filp; | ||
1816 | 1891 | ||
1892 | exit_mutex_unlock: | ||
1893 | mutex_unlock(&dir->d_inode->i_mutex); | ||
1817 | exit_dput: | 1894 | exit_dput: |
1818 | path_put_conditional(&path, nd); | 1895 | path_put_conditional(&path, &nd); |
1819 | exit: | 1896 | exit: |
1820 | if (!IS_ERR(nd->intent.open.file)) | 1897 | if (!IS_ERR(nd.intent.open.file)) |
1821 | release_open_intent(nd); | 1898 | release_open_intent(&nd); |
1822 | path_put(&nd->path); | 1899 | path_put(&nd.path); |
1823 | return error; | 1900 | return ERR_PTR(error); |
1824 | 1901 | ||
1825 | do_link: | 1902 | do_link: |
1826 | error = -ELOOP; | 1903 | error = -ELOOP; |
@@ -1836,43 +1913,60 @@ do_link: | |||
1836 | * stored in nd->last.name and we will have to putname() it when we | 1913 | * stored in nd->last.name and we will have to putname() it when we |
1837 | * are done. Procfs-like symlinks just set LAST_BIND. | 1914 | * are done. Procfs-like symlinks just set LAST_BIND. |
1838 | */ | 1915 | */ |
1839 | nd->flags |= LOOKUP_PARENT; | 1916 | nd.flags |= LOOKUP_PARENT; |
1840 | error = security_inode_follow_link(path.dentry, nd); | 1917 | error = security_inode_follow_link(path.dentry, &nd); |
1841 | if (error) | 1918 | if (error) |
1842 | goto exit_dput; | 1919 | goto exit_dput; |
1843 | error = __do_follow_link(&path, nd); | 1920 | error = __do_follow_link(&path, &nd); |
1844 | if (error) { | 1921 | if (error) { |
1845 | /* Does someone understand code flow here? Or it is only | 1922 | /* Does someone understand code flow here? Or it is only |
1846 | * me so stupid? Anathema to whoever designed this non-sense | 1923 | * me so stupid? Anathema to whoever designed this non-sense |
1847 | * with "intent.open". | 1924 | * with "intent.open". |
1848 | */ | 1925 | */ |
1849 | release_open_intent(nd); | 1926 | release_open_intent(&nd); |
1850 | return error; | 1927 | return ERR_PTR(error); |
1851 | } | 1928 | } |
1852 | nd->flags &= ~LOOKUP_PARENT; | 1929 | nd.flags &= ~LOOKUP_PARENT; |
1853 | if (nd->last_type == LAST_BIND) | 1930 | if (nd.last_type == LAST_BIND) |
1854 | goto ok; | 1931 | goto ok; |
1855 | error = -EISDIR; | 1932 | error = -EISDIR; |
1856 | if (nd->last_type != LAST_NORM) | 1933 | if (nd.last_type != LAST_NORM) |
1857 | goto exit; | 1934 | goto exit; |
1858 | if (nd->last.name[nd->last.len]) { | 1935 | if (nd.last.name[nd.last.len]) { |
1859 | __putname(nd->last.name); | 1936 | __putname(nd.last.name); |
1860 | goto exit; | 1937 | goto exit; |
1861 | } | 1938 | } |
1862 | error = -ELOOP; | 1939 | error = -ELOOP; |
1863 | if (count++==32) { | 1940 | if (count++==32) { |
1864 | __putname(nd->last.name); | 1941 | __putname(nd.last.name); |
1865 | goto exit; | 1942 | goto exit; |
1866 | } | 1943 | } |
1867 | dir = nd->path.dentry; | 1944 | dir = nd.path.dentry; |
1868 | mutex_lock(&dir->d_inode->i_mutex); | 1945 | mutex_lock(&dir->d_inode->i_mutex); |
1869 | path.dentry = lookup_hash(nd); | 1946 | path.dentry = lookup_hash(&nd); |
1870 | path.mnt = nd->path.mnt; | 1947 | path.mnt = nd.path.mnt; |
1871 | __putname(nd->last.name); | 1948 | __putname(nd.last.name); |
1872 | goto do_last; | 1949 | goto do_last; |
1873 | } | 1950 | } |
1874 | 1951 | ||
1875 | /** | 1952 | /** |
1953 | * filp_open - open file and return file pointer | ||
1954 | * | ||
1955 | * @filename: path to open | ||
1956 | * @flags: open flags as per the open(2) second argument | ||
1957 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
1958 | * | ||
1959 | * This is the helper to open a file from kernelspace if you really | ||
1960 | * have to. But in generally you should not do this, so please move | ||
1961 | * along, nothing to see here.. | ||
1962 | */ | ||
1963 | struct file *filp_open(const char *filename, int flags, int mode) | ||
1964 | { | ||
1965 | return do_filp_open(AT_FDCWD, filename, flags, mode); | ||
1966 | } | ||
1967 | EXPORT_SYMBOL(filp_open); | ||
1968 | |||
1969 | /** | ||
1876 | * lookup_create - lookup a dentry, creating it if it doesn't exist | 1970 | * lookup_create - lookup a dentry, creating it if it doesn't exist |
1877 | * @nd: nameidata info | 1971 | * @nd: nameidata info |
1878 | * @is_dir: directory flag | 1972 | * @is_dir: directory flag |
@@ -1945,6 +2039,23 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1945 | return error; | 2039 | return error; |
1946 | } | 2040 | } |
1947 | 2041 | ||
2042 | static int may_mknod(mode_t mode) | ||
2043 | { | ||
2044 | switch (mode & S_IFMT) { | ||
2045 | case S_IFREG: | ||
2046 | case S_IFCHR: | ||
2047 | case S_IFBLK: | ||
2048 | case S_IFIFO: | ||
2049 | case S_IFSOCK: | ||
2050 | case 0: /* zero mode translates to S_IFREG */ | ||
2051 | return 0; | ||
2052 | case S_IFDIR: | ||
2053 | return -EPERM; | ||
2054 | default: | ||
2055 | return -EINVAL; | ||
2056 | } | ||
2057 | } | ||
2058 | |||
1948 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | 2059 | asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, |
1949 | unsigned dev) | 2060 | unsigned dev) |
1950 | { | 2061 | { |
@@ -1963,12 +2074,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1963 | if (error) | 2074 | if (error) |
1964 | goto out; | 2075 | goto out; |
1965 | dentry = lookup_create(&nd, 0); | 2076 | dentry = lookup_create(&nd, 0); |
1966 | error = PTR_ERR(dentry); | 2077 | if (IS_ERR(dentry)) { |
1967 | 2078 | error = PTR_ERR(dentry); | |
2079 | goto out_unlock; | ||
2080 | } | ||
1968 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) | 2081 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
1969 | mode &= ~current->fs->umask; | 2082 | mode &= ~current->fs->umask; |
1970 | if (!IS_ERR(dentry)) { | 2083 | error = may_mknod(mode); |
1971 | switch (mode & S_IFMT) { | 2084 | if (error) |
2085 | goto out_dput; | ||
2086 | error = mnt_want_write(nd.path.mnt); | ||
2087 | if (error) | ||
2088 | goto out_dput; | ||
2089 | switch (mode & S_IFMT) { | ||
1972 | case 0: case S_IFREG: | 2090 | case 0: case S_IFREG: |
1973 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); | 2091 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
1974 | break; | 2092 | break; |
@@ -1979,14 +2097,11 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1979 | case S_IFIFO: case S_IFSOCK: | 2097 | case S_IFIFO: case S_IFSOCK: |
1980 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); | 2098 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
1981 | break; | 2099 | break; |
1982 | case S_IFDIR: | ||
1983 | error = -EPERM; | ||
1984 | break; | ||
1985 | default: | ||
1986 | error = -EINVAL; | ||
1987 | } | ||
1988 | dput(dentry); | ||
1989 | } | 2100 | } |
2101 | mnt_drop_write(nd.path.mnt); | ||
2102 | out_dput: | ||
2103 | dput(dentry); | ||
2104 | out_unlock: | ||
1990 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2105 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
1991 | path_put(&nd.path); | 2106 | path_put(&nd.path); |
1992 | out: | 2107 | out: |
@@ -2044,7 +2159,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2044 | 2159 | ||
2045 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) | 2160 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
2046 | mode &= ~current->fs->umask; | 2161 | mode &= ~current->fs->umask; |
2162 | error = mnt_want_write(nd.path.mnt); | ||
2163 | if (error) | ||
2164 | goto out_dput; | ||
2047 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); | 2165 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2166 | mnt_drop_write(nd.path.mnt); | ||
2167 | out_dput: | ||
2048 | dput(dentry); | 2168 | dput(dentry); |
2049 | out_unlock: | 2169 | out_unlock: |
2050 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2170 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2151,7 +2271,12 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2151 | error = PTR_ERR(dentry); | 2271 | error = PTR_ERR(dentry); |
2152 | if (IS_ERR(dentry)) | 2272 | if (IS_ERR(dentry)) |
2153 | goto exit2; | 2273 | goto exit2; |
2274 | error = mnt_want_write(nd.path.mnt); | ||
2275 | if (error) | ||
2276 | goto exit3; | ||
2154 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); | 2277 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2278 | mnt_drop_write(nd.path.mnt); | ||
2279 | exit3: | ||
2155 | dput(dentry); | 2280 | dput(dentry); |
2156 | exit2: | 2281 | exit2: |
2157 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2282 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2232,7 +2357,11 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2232 | inode = dentry->d_inode; | 2357 | inode = dentry->d_inode; |
2233 | if (inode) | 2358 | if (inode) |
2234 | atomic_inc(&inode->i_count); | 2359 | atomic_inc(&inode->i_count); |
2360 | error = mnt_want_write(nd.path.mnt); | ||
2361 | if (error) | ||
2362 | goto exit2; | ||
2235 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); | 2363 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2364 | mnt_drop_write(nd.path.mnt); | ||
2236 | exit2: | 2365 | exit2: |
2237 | dput(dentry); | 2366 | dput(dentry); |
2238 | } | 2367 | } |
@@ -2313,7 +2442,12 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2313 | if (IS_ERR(dentry)) | 2442 | if (IS_ERR(dentry)) |
2314 | goto out_unlock; | 2443 | goto out_unlock; |
2315 | 2444 | ||
2445 | error = mnt_want_write(nd.path.mnt); | ||
2446 | if (error) | ||
2447 | goto out_dput; | ||
2316 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); | 2448 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); |
2449 | mnt_drop_write(nd.path.mnt); | ||
2450 | out_dput: | ||
2317 | dput(dentry); | 2451 | dput(dentry); |
2318 | out_unlock: | 2452 | out_unlock: |
2319 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2453 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2408,7 +2542,12 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2408 | error = PTR_ERR(new_dentry); | 2542 | error = PTR_ERR(new_dentry); |
2409 | if (IS_ERR(new_dentry)) | 2543 | if (IS_ERR(new_dentry)) |
2410 | goto out_unlock; | 2544 | goto out_unlock; |
2545 | error = mnt_want_write(nd.path.mnt); | ||
2546 | if (error) | ||
2547 | goto out_dput; | ||
2411 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); | 2548 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); |
2549 | mnt_drop_write(nd.path.mnt); | ||
2550 | out_dput: | ||
2412 | dput(new_dentry); | 2551 | dput(new_dentry); |
2413 | out_unlock: | 2552 | out_unlock: |
2414 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2553 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
@@ -2634,8 +2773,12 @@ static int do_rename(int olddfd, const char *oldname, | |||
2634 | if (new_dentry == trap) | 2773 | if (new_dentry == trap) |
2635 | goto exit5; | 2774 | goto exit5; |
2636 | 2775 | ||
2776 | error = mnt_want_write(oldnd.path.mnt); | ||
2777 | if (error) | ||
2778 | goto exit5; | ||
2637 | error = vfs_rename(old_dir->d_inode, old_dentry, | 2779 | error = vfs_rename(old_dir->d_inode, old_dentry, |
2638 | new_dir->d_inode, new_dentry); | 2780 | new_dir->d_inode, new_dentry); |
2781 | mnt_drop_write(oldnd.path.mnt); | ||
2639 | exit5: | 2782 | exit5: |
2640 | dput(new_dentry); | 2783 | dput(new_dentry); |
2641 | exit4: | 2784 | exit4: |
diff --git a/fs/namespace.c b/fs/namespace.c index 94f026ec990a..678f7ce060f2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/quotaops.h> | 17 | #include <linux/quotaops.h> |
18 | #include <linux/acct.h> | 18 | #include <linux/acct.h> |
19 | #include <linux/capability.h> | 19 | #include <linux/capability.h> |
20 | #include <linux/cpumask.h> | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/sysfs.h> | 22 | #include <linux/sysfs.h> |
22 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
@@ -55,6 +56,8 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) | |||
55 | return tmp & (HASH_SIZE - 1); | 56 | return tmp & (HASH_SIZE - 1); |
56 | } | 57 | } |
57 | 58 | ||
59 | #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16) | ||
60 | |||
58 | struct vfsmount *alloc_vfsmnt(const char *name) | 61 | struct vfsmount *alloc_vfsmnt(const char *name) |
59 | { | 62 | { |
60 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 63 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
@@ -68,6 +71,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
68 | INIT_LIST_HEAD(&mnt->mnt_share); | 71 | INIT_LIST_HEAD(&mnt->mnt_share); |
69 | INIT_LIST_HEAD(&mnt->mnt_slave_list); | 72 | INIT_LIST_HEAD(&mnt->mnt_slave_list); |
70 | INIT_LIST_HEAD(&mnt->mnt_slave); | 73 | INIT_LIST_HEAD(&mnt->mnt_slave); |
74 | atomic_set(&mnt->__mnt_writers, 0); | ||
71 | if (name) { | 75 | if (name) { |
72 | int size = strlen(name) + 1; | 76 | int size = strlen(name) + 1; |
73 | char *newname = kmalloc(size, GFP_KERNEL); | 77 | char *newname = kmalloc(size, GFP_KERNEL); |
@@ -80,6 +84,263 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
80 | return mnt; | 84 | return mnt; |
81 | } | 85 | } |
82 | 86 | ||
87 | /* | ||
88 | * Most r/o checks on a fs are for operations that take | ||
89 | * discrete amounts of time, like a write() or unlink(). | ||
90 | * We must keep track of when those operations start | ||
91 | * (for permission checks) and when they end, so that | ||
92 | * we can determine when writes are able to occur to | ||
93 | * a filesystem. | ||
94 | */ | ||
95 | /* | ||
96 | * __mnt_is_readonly: check whether a mount is read-only | ||
97 | * @mnt: the mount to check for its write status | ||
98 | * | ||
99 | * This shouldn't be used directly ouside of the VFS. | ||
100 | * It does not guarantee that the filesystem will stay | ||
101 | * r/w, just that it is right *now*. This can not and | ||
102 | * should not be used in place of IS_RDONLY(inode). | ||
103 | * mnt_want/drop_write() will _keep_ the filesystem | ||
104 | * r/w. | ||
105 | */ | ||
106 | int __mnt_is_readonly(struct vfsmount *mnt) | ||
107 | { | ||
108 | if (mnt->mnt_flags & MNT_READONLY) | ||
109 | return 1; | ||
110 | if (mnt->mnt_sb->s_flags & MS_RDONLY) | ||
111 | return 1; | ||
112 | return 0; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(__mnt_is_readonly); | ||
115 | |||
116 | struct mnt_writer { | ||
117 | /* | ||
118 | * If holding multiple instances of this lock, they | ||
119 | * must be ordered by cpu number. | ||
120 | */ | ||
121 | spinlock_t lock; | ||
122 | struct lock_class_key lock_class; /* compiles out with !lockdep */ | ||
123 | unsigned long count; | ||
124 | struct vfsmount *mnt; | ||
125 | } ____cacheline_aligned_in_smp; | ||
126 | static DEFINE_PER_CPU(struct mnt_writer, mnt_writers); | ||
127 | |||
128 | static int __init init_mnt_writers(void) | ||
129 | { | ||
130 | int cpu; | ||
131 | for_each_possible_cpu(cpu) { | ||
132 | struct mnt_writer *writer = &per_cpu(mnt_writers, cpu); | ||
133 | spin_lock_init(&writer->lock); | ||
134 | lockdep_set_class(&writer->lock, &writer->lock_class); | ||
135 | writer->count = 0; | ||
136 | } | ||
137 | return 0; | ||
138 | } | ||
139 | fs_initcall(init_mnt_writers); | ||
140 | |||
141 | static void unlock_mnt_writers(void) | ||
142 | { | ||
143 | int cpu; | ||
144 | struct mnt_writer *cpu_writer; | ||
145 | |||
146 | for_each_possible_cpu(cpu) { | ||
147 | cpu_writer = &per_cpu(mnt_writers, cpu); | ||
148 | spin_unlock(&cpu_writer->lock); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static inline void __clear_mnt_count(struct mnt_writer *cpu_writer) | ||
153 | { | ||
154 | if (!cpu_writer->mnt) | ||
155 | return; | ||
156 | /* | ||
157 | * This is in case anyone ever leaves an invalid, | ||
158 | * old ->mnt and a count of 0. | ||
159 | */ | ||
160 | if (!cpu_writer->count) | ||
161 | return; | ||
162 | atomic_add(cpu_writer->count, &cpu_writer->mnt->__mnt_writers); | ||
163 | cpu_writer->count = 0; | ||
164 | } | ||
165 | /* | ||
166 | * must hold cpu_writer->lock | ||
167 | */ | ||
168 | static inline void use_cpu_writer_for_mount(struct mnt_writer *cpu_writer, | ||
169 | struct vfsmount *mnt) | ||
170 | { | ||
171 | if (cpu_writer->mnt == mnt) | ||
172 | return; | ||
173 | __clear_mnt_count(cpu_writer); | ||
174 | cpu_writer->mnt = mnt; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Most r/o checks on a fs are for operations that take | ||
179 | * discrete amounts of time, like a write() or unlink(). | ||
180 | * We must keep track of when those operations start | ||
181 | * (for permission checks) and when they end, so that | ||
182 | * we can determine when writes are able to occur to | ||
183 | * a filesystem. | ||
184 | */ | ||
185 | /** | ||
186 | * mnt_want_write - get write access to a mount | ||
187 | * @mnt: the mount on which to take a write | ||
188 | * | ||
189 | * This tells the low-level filesystem that a write is | ||
190 | * about to be performed to it, and makes sure that | ||
191 | * writes are allowed before returning success. When | ||
192 | * the write operation is finished, mnt_drop_write() | ||
193 | * must be called. This is effectively a refcount. | ||
194 | */ | ||
195 | int mnt_want_write(struct vfsmount *mnt) | ||
196 | { | ||
197 | int ret = 0; | ||
198 | struct mnt_writer *cpu_writer; | ||
199 | |||
200 | cpu_writer = &get_cpu_var(mnt_writers); | ||
201 | spin_lock(&cpu_writer->lock); | ||
202 | if (__mnt_is_readonly(mnt)) { | ||
203 | ret = -EROFS; | ||
204 | goto out; | ||
205 | } | ||
206 | use_cpu_writer_for_mount(cpu_writer, mnt); | ||
207 | cpu_writer->count++; | ||
208 | out: | ||
209 | spin_unlock(&cpu_writer->lock); | ||
210 | put_cpu_var(mnt_writers); | ||
211 | return ret; | ||
212 | } | ||
213 | EXPORT_SYMBOL_GPL(mnt_want_write); | ||
214 | |||
215 | static void lock_mnt_writers(void) | ||
216 | { | ||
217 | int cpu; | ||
218 | struct mnt_writer *cpu_writer; | ||
219 | |||
220 | for_each_possible_cpu(cpu) { | ||
221 | cpu_writer = &per_cpu(mnt_writers, cpu); | ||
222 | spin_lock(&cpu_writer->lock); | ||
223 | __clear_mnt_count(cpu_writer); | ||
224 | cpu_writer->mnt = NULL; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * These per-cpu write counts are not guaranteed to have | ||
230 | * matched increments and decrements on any given cpu. | ||
231 | * A file open()ed for write on one cpu and close()d on | ||
232 | * another cpu will imbalance this count. Make sure it | ||
233 | * does not get too far out of whack. | ||
234 | */ | ||
235 | static void handle_write_count_underflow(struct vfsmount *mnt) | ||
236 | { | ||
237 | if (atomic_read(&mnt->__mnt_writers) >= | ||
238 | MNT_WRITER_UNDERFLOW_LIMIT) | ||
239 | return; | ||
240 | /* | ||
241 | * It isn't necessary to hold all of the locks | ||
242 | * at the same time, but doing it this way makes | ||
243 | * us share a lot more code. | ||
244 | */ | ||
245 | lock_mnt_writers(); | ||
246 | /* | ||
247 | * vfsmount_lock is for mnt_flags. | ||
248 | */ | ||
249 | spin_lock(&vfsmount_lock); | ||
250 | /* | ||
251 | * If coalescing the per-cpu writer counts did not | ||
252 | * get us back to a positive writer count, we have | ||
253 | * a bug. | ||
254 | */ | ||
255 | if ((atomic_read(&mnt->__mnt_writers) < 0) && | ||
256 | !(mnt->mnt_flags & MNT_IMBALANCED_WRITE_COUNT)) { | ||
257 | printk(KERN_DEBUG "leak detected on mount(%p) writers " | ||
258 | "count: %d\n", | ||
259 | mnt, atomic_read(&mnt->__mnt_writers)); | ||
260 | WARN_ON(1); | ||
261 | /* use the flag to keep the dmesg spam down */ | ||
262 | mnt->mnt_flags |= MNT_IMBALANCED_WRITE_COUNT; | ||
263 | } | ||
264 | spin_unlock(&vfsmount_lock); | ||
265 | unlock_mnt_writers(); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * mnt_drop_write - give up write access to a mount | ||
270 | * @mnt: the mount on which to give up write access | ||
271 | * | ||
272 | * Tells the low-level filesystem that we are done | ||
273 | * performing writes to it. Must be matched with | ||
274 | * mnt_want_write() call above. | ||
275 | */ | ||
276 | void mnt_drop_write(struct vfsmount *mnt) | ||
277 | { | ||
278 | int must_check_underflow = 0; | ||
279 | struct mnt_writer *cpu_writer; | ||
280 | |||
281 | cpu_writer = &get_cpu_var(mnt_writers); | ||
282 | spin_lock(&cpu_writer->lock); | ||
283 | |||
284 | use_cpu_writer_for_mount(cpu_writer, mnt); | ||
285 | if (cpu_writer->count > 0) { | ||
286 | cpu_writer->count--; | ||
287 | } else { | ||
288 | must_check_underflow = 1; | ||
289 | atomic_dec(&mnt->__mnt_writers); | ||
290 | } | ||
291 | |||
292 | spin_unlock(&cpu_writer->lock); | ||
293 | /* | ||
294 | * Logically, we could call this each time, | ||
295 | * but the __mnt_writers cacheline tends to | ||
296 | * be cold, and makes this expensive. | ||
297 | */ | ||
298 | if (must_check_underflow) | ||
299 | handle_write_count_underflow(mnt); | ||
300 | /* | ||
301 | * This could be done right after the spinlock | ||
302 | * is taken because the spinlock keeps us on | ||
303 | * the cpu, and disables preemption. However, | ||
304 | * putting it here bounds the amount that | ||
305 | * __mnt_writers can underflow. Without it, | ||
306 | * we could theoretically wrap __mnt_writers. | ||
307 | */ | ||
308 | put_cpu_var(mnt_writers); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(mnt_drop_write); | ||
311 | |||
312 | static int mnt_make_readonly(struct vfsmount *mnt) | ||
313 | { | ||
314 | int ret = 0; | ||
315 | |||
316 | lock_mnt_writers(); | ||
317 | /* | ||
318 | * With all the locks held, this value is stable | ||
319 | */ | ||
320 | if (atomic_read(&mnt->__mnt_writers) > 0) { | ||
321 | ret = -EBUSY; | ||
322 | goto out; | ||
323 | } | ||
324 | /* | ||
325 | * nobody can do a successful mnt_want_write() with all | ||
326 | * of the counts in MNT_DENIED_WRITE and the locks held. | ||
327 | */ | ||
328 | spin_lock(&vfsmount_lock); | ||
329 | if (!ret) | ||
330 | mnt->mnt_flags |= MNT_READONLY; | ||
331 | spin_unlock(&vfsmount_lock); | ||
332 | out: | ||
333 | unlock_mnt_writers(); | ||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | static void __mnt_unmake_readonly(struct vfsmount *mnt) | ||
338 | { | ||
339 | spin_lock(&vfsmount_lock); | ||
340 | mnt->mnt_flags &= ~MNT_READONLY; | ||
341 | spin_unlock(&vfsmount_lock); | ||
342 | } | ||
343 | |||
83 | int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) | 344 | int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) |
84 | { | 345 | { |
85 | mnt->mnt_sb = sb; | 346 | mnt->mnt_sb = sb; |
@@ -271,7 +532,36 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
271 | 532 | ||
272 | static inline void __mntput(struct vfsmount *mnt) | 533 | static inline void __mntput(struct vfsmount *mnt) |
273 | { | 534 | { |
535 | int cpu; | ||
274 | struct super_block *sb = mnt->mnt_sb; | 536 | struct super_block *sb = mnt->mnt_sb; |
537 | /* | ||
538 | * We don't have to hold all of the locks at the | ||
539 | * same time here because we know that we're the | ||
540 | * last reference to mnt and that no new writers | ||
541 | * can come in. | ||
542 | */ | ||
543 | for_each_possible_cpu(cpu) { | ||
544 | struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu); | ||
545 | if (cpu_writer->mnt != mnt) | ||
546 | continue; | ||
547 | spin_lock(&cpu_writer->lock); | ||
548 | atomic_add(cpu_writer->count, &mnt->__mnt_writers); | ||
549 | cpu_writer->count = 0; | ||
550 | /* | ||
551 | * Might as well do this so that no one | ||
552 | * ever sees the pointer and expects | ||
553 | * it to be valid. | ||
554 | */ | ||
555 | cpu_writer->mnt = NULL; | ||
556 | spin_unlock(&cpu_writer->lock); | ||
557 | } | ||
558 | /* | ||
559 | * This probably indicates that somebody messed | ||
560 | * up a mnt_want/drop_write() pair. If this | ||
561 | * happens, the filesystem was probably unable | ||
562 | * to make r/w->r/o transitions. | ||
563 | */ | ||
564 | WARN_ON(atomic_read(&mnt->__mnt_writers)); | ||
275 | dput(mnt->mnt_root); | 565 | dput(mnt->mnt_root); |
276 | free_vfsmnt(mnt); | 566 | free_vfsmnt(mnt); |
277 | deactivate_super(sb); | 567 | deactivate_super(sb); |
@@ -417,7 +707,7 @@ static int show_vfsmnt(struct seq_file *m, void *v) | |||
417 | seq_putc(m, '.'); | 707 | seq_putc(m, '.'); |
418 | mangle(m, mnt->mnt_sb->s_subtype); | 708 | mangle(m, mnt->mnt_sb->s_subtype); |
419 | } | 709 | } |
420 | seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw"); | 710 | seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); |
421 | for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { | 711 | for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { |
422 | if (mnt->mnt_sb->s_flags & fs_infop->flag) | 712 | if (mnt->mnt_sb->s_flags & fs_infop->flag) |
423 | seq_puts(m, fs_infop->str); | 713 | seq_puts(m, fs_infop->str); |
@@ -1019,6 +1309,23 @@ out: | |||
1019 | return err; | 1309 | return err; |
1020 | } | 1310 | } |
1021 | 1311 | ||
1312 | static int change_mount_flags(struct vfsmount *mnt, int ms_flags) | ||
1313 | { | ||
1314 | int error = 0; | ||
1315 | int readonly_request = 0; | ||
1316 | |||
1317 | if (ms_flags & MS_RDONLY) | ||
1318 | readonly_request = 1; | ||
1319 | if (readonly_request == __mnt_is_readonly(mnt)) | ||
1320 | return 0; | ||
1321 | |||
1322 | if (readonly_request) | ||
1323 | error = mnt_make_readonly(mnt); | ||
1324 | else | ||
1325 | __mnt_unmake_readonly(mnt); | ||
1326 | return error; | ||
1327 | } | ||
1328 | |||
1022 | /* | 1329 | /* |
1023 | * change filesystem flags. dir should be a physical root of filesystem. | 1330 | * change filesystem flags. dir should be a physical root of filesystem. |
1024 | * If you've mounted a non-root directory somewhere and want to do remount | 1331 | * If you've mounted a non-root directory somewhere and want to do remount |
@@ -1041,7 +1348,10 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags, | |||
1041 | return -EINVAL; | 1348 | return -EINVAL; |
1042 | 1349 | ||
1043 | down_write(&sb->s_umount); | 1350 | down_write(&sb->s_umount); |
1044 | err = do_remount_sb(sb, flags, data, 0); | 1351 | if (flags & MS_BIND) |
1352 | err = change_mount_flags(nd->path.mnt, flags); | ||
1353 | else | ||
1354 | err = do_remount_sb(sb, flags, data, 0); | ||
1045 | if (!err) | 1355 | if (!err) |
1046 | nd->path.mnt->mnt_flags = mnt_flags; | 1356 | nd->path.mnt->mnt_flags = mnt_flags; |
1047 | up_write(&sb->s_umount); | 1357 | up_write(&sb->s_umount); |
@@ -1425,6 +1735,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1425 | mnt_flags |= MNT_NODIRATIME; | 1735 | mnt_flags |= MNT_NODIRATIME; |
1426 | if (flags & MS_RELATIME) | 1736 | if (flags & MS_RELATIME) |
1427 | mnt_flags |= MNT_RELATIME; | 1737 | mnt_flags |= MNT_RELATIME; |
1738 | if (flags & MS_RDONLY) | ||
1739 | mnt_flags |= MNT_READONLY; | ||
1428 | 1740 | ||
1429 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | | 1741 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | |
1430 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); | 1742 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT); |
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index c67b4bdcf719..ad8f167e54bc 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/ioctl.h> | 14 | #include <linux/ioctl.h> |
15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/mount.h> | ||
17 | #include <linux/highuid.h> | 18 | #include <linux/highuid.h> |
18 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
19 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
@@ -261,7 +262,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg) | |||
261 | } | 262 | } |
262 | #endif /* CONFIG_NCPFS_NLS */ | 263 | #endif /* CONFIG_NCPFS_NLS */ |
263 | 264 | ||
264 | int ncp_ioctl(struct inode *inode, struct file *filp, | 265 | static int __ncp_ioctl(struct inode *inode, struct file *filp, |
265 | unsigned int cmd, unsigned long arg) | 266 | unsigned int cmd, unsigned long arg) |
266 | { | 267 | { |
267 | struct ncp_server *server = NCP_SERVER(inode); | 268 | struct ncp_server *server = NCP_SERVER(inode); |
@@ -822,6 +823,57 @@ outrel: | |||
822 | return -EINVAL; | 823 | return -EINVAL; |
823 | } | 824 | } |
824 | 825 | ||
826 | static int ncp_ioctl_need_write(unsigned int cmd) | ||
827 | { | ||
828 | switch (cmd) { | ||
829 | case NCP_IOC_GET_FS_INFO: | ||
830 | case NCP_IOC_GET_FS_INFO_V2: | ||
831 | case NCP_IOC_NCPREQUEST: | ||
832 | case NCP_IOC_SETDENTRYTTL: | ||
833 | case NCP_IOC_SIGN_INIT: | ||
834 | case NCP_IOC_LOCKUNLOCK: | ||
835 | case NCP_IOC_SET_SIGN_WANTED: | ||
836 | return 1; | ||
837 | case NCP_IOC_GETOBJECTNAME: | ||
838 | case NCP_IOC_SETOBJECTNAME: | ||
839 | case NCP_IOC_GETPRIVATEDATA: | ||
840 | case NCP_IOC_SETPRIVATEDATA: | ||
841 | case NCP_IOC_SETCHARSETS: | ||
842 | case NCP_IOC_GETCHARSETS: | ||
843 | case NCP_IOC_CONN_LOGGED_IN: | ||
844 | case NCP_IOC_GETDENTRYTTL: | ||
845 | case NCP_IOC_GETMOUNTUID2: | ||
846 | case NCP_IOC_SIGN_WANTED: | ||
847 | case NCP_IOC_GETROOT: | ||
848 | case NCP_IOC_SETROOT: | ||
849 | return 0; | ||
850 | default: | ||
851 | /* unkown IOCTL command, assume write */ | ||
852 | return 1; | ||
853 | } | ||
854 | } | ||
855 | |||
856 | int ncp_ioctl(struct inode *inode, struct file *filp, | ||
857 | unsigned int cmd, unsigned long arg) | ||
858 | { | ||
859 | int ret; | ||
860 | |||
861 | if (ncp_ioctl_need_write(cmd)) { | ||
862 | /* | ||
863 | * inside the ioctl(), any failures which | ||
864 | * are because of file_permission() are | ||
865 | * -EACCESS, so it seems consistent to keep | ||
866 | * that here. | ||
867 | */ | ||
868 | if (mnt_want_write(filp->f_path.mnt)) | ||
869 | return -EACCES; | ||
870 | } | ||
871 | ret = __ncp_ioctl(inode, filp, cmd, arg); | ||
872 | if (ncp_ioctl_need_write(cmd)) | ||
873 | mnt_drop_write(filp->f_path.mnt); | ||
874 | return ret; | ||
875 | } | ||
876 | |||
825 | #ifdef CONFIG_COMPAT | 877 | #ifdef CONFIG_COMPAT |
826 | long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 878 | long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
827 | { | 879 | { |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 6cea7479c5b4..d9e30ac2798d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -967,7 +967,8 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd) | |||
967 | if (nd->flags & LOOKUP_DIRECTORY) | 967 | if (nd->flags & LOOKUP_DIRECTORY) |
968 | return 0; | 968 | return 0; |
969 | /* Are we trying to write to a read only partition? */ | 969 | /* Are we trying to write to a read only partition? */ |
970 | if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) | 970 | if (__mnt_is_readonly(nd->path.mnt) && |
971 | (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) | ||
971 | return 0; | 972 | return 0; |
972 | return 1; | 973 | return 1; |
973 | } | 974 | } |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index c593db047d8b..c309c881bd4e 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -658,14 +658,19 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
658 | return status; | 658 | return status; |
659 | } | 659 | } |
660 | } | 660 | } |
661 | status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt); | ||
662 | if (status) | ||
663 | return status; | ||
661 | status = nfs_ok; | 664 | status = nfs_ok; |
662 | if (setattr->sa_acl != NULL) | 665 | if (setattr->sa_acl != NULL) |
663 | status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh, | 666 | status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh, |
664 | setattr->sa_acl); | 667 | setattr->sa_acl); |
665 | if (status) | 668 | if (status) |
666 | return status; | 669 | goto out; |
667 | status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, | 670 | status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, |
668 | 0, (time_t)0); | 671 | 0, (time_t)0); |
672 | out: | ||
673 | mnt_drop_write(cstate->current_fh.fh_export->ex_path.mnt); | ||
669 | return status; | 674 | return status; |
670 | } | 675 | } |
671 | 676 | ||
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 1ff90625860f..145b3c877a27 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/scatterlist.h> | 46 | #include <linux/scatterlist.h> |
47 | #include <linux/crypto.h> | 47 | #include <linux/crypto.h> |
48 | #include <linux/sched.h> | 48 | #include <linux/sched.h> |
49 | #include <linux/mount.h> | ||
49 | 50 | ||
50 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 51 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
51 | 52 | ||
@@ -154,7 +155,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
154 | dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n"); | 155 | dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n"); |
155 | goto out_put; | 156 | goto out_put; |
156 | } | 157 | } |
158 | status = mnt_want_write(rec_dir.path.mnt); | ||
159 | if (status) | ||
160 | goto out_put; | ||
157 | status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU); | 161 | status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU); |
162 | mnt_drop_write(rec_dir.path.mnt); | ||
158 | out_put: | 163 | out_put: |
159 | dput(dentry); | 164 | dput(dentry); |
160 | out_unlock: | 165 | out_unlock: |
@@ -313,12 +318,17 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
313 | if (!rec_dir_init || !clp->cl_firststate) | 318 | if (!rec_dir_init || !clp->cl_firststate) |
314 | return; | 319 | return; |
315 | 320 | ||
321 | status = mnt_want_write(rec_dir.path.mnt); | ||
322 | if (status) | ||
323 | goto out; | ||
316 | clp->cl_firststate = 0; | 324 | clp->cl_firststate = 0; |
317 | nfs4_save_user(&uid, &gid); | 325 | nfs4_save_user(&uid, &gid); |
318 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); | 326 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); |
319 | nfs4_reset_user(uid, gid); | 327 | nfs4_reset_user(uid, gid); |
320 | if (status == 0) | 328 | if (status == 0) |
321 | nfsd4_sync_rec_dir(); | 329 | nfsd4_sync_rec_dir(); |
330 | mnt_drop_write(rec_dir.path.mnt); | ||
331 | out: | ||
322 | if (status) | 332 | if (status) |
323 | printk("NFSD: Failed to remove expired client state directory" | 333 | printk("NFSD: Failed to remove expired client state directory" |
324 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); | 334 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); |
@@ -347,13 +357,17 @@ nfsd4_recdir_purge_old(void) { | |||
347 | 357 | ||
348 | if (!rec_dir_init) | 358 | if (!rec_dir_init) |
349 | return; | 359 | return; |
360 | status = mnt_want_write(rec_dir.path.mnt); | ||
361 | if (status) | ||
362 | goto out; | ||
350 | status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old); | 363 | status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old); |
351 | if (status == 0) | 364 | if (status == 0) |
352 | nfsd4_sync_rec_dir(); | 365 | nfsd4_sync_rec_dir(); |
366 | mnt_drop_write(rec_dir.path.mnt); | ||
367 | out: | ||
353 | if (status) | 368 | if (status) |
354 | printk("nfsd4: failed to purge old clients from recovery" | 369 | printk("nfsd4: failed to purge old clients from recovery" |
355 | " directory %s\n", rec_dir.path.dentry->d_name.name); | 370 | " directory %s\n", rec_dir.path.dentry->d_name.name); |
356 | return; | ||
357 | } | 371 | } |
358 | 372 | ||
359 | static int | 373 | static int |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index bcb97d8e8b8b..81a75f3081f4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/sunrpc/svc.h> | 41 | #include <linux/sunrpc/svc.h> |
42 | #include <linux/nfsd/nfsd.h> | 42 | #include <linux/nfsd/nfsd.h> |
43 | #include <linux/nfsd/cache.h> | 43 | #include <linux/nfsd/cache.h> |
44 | #include <linux/file.h> | ||
44 | #include <linux/mount.h> | 45 | #include <linux/mount.h> |
45 | #include <linux/workqueue.h> | 46 | #include <linux/workqueue.h> |
46 | #include <linux/smp_lock.h> | 47 | #include <linux/smp_lock.h> |
@@ -1239,7 +1240,7 @@ static inline void | |||
1239 | nfs4_file_downgrade(struct file *filp, unsigned int share_access) | 1240 | nfs4_file_downgrade(struct file *filp, unsigned int share_access) |
1240 | { | 1241 | { |
1241 | if (share_access & NFS4_SHARE_ACCESS_WRITE) { | 1242 | if (share_access & NFS4_SHARE_ACCESS_WRITE) { |
1242 | put_write_access(filp->f_path.dentry->d_inode); | 1243 | drop_file_write_access(filp); |
1243 | filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; | 1244 | filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; |
1244 | } | 1245 | } |
1245 | } | 1246 | } |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 46f59d5365a0..304bf5f643c9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1255,23 +1255,35 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1255 | err = 0; | 1255 | err = 0; |
1256 | switch (type) { | 1256 | switch (type) { |
1257 | case S_IFREG: | 1257 | case S_IFREG: |
1258 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1259 | if (host_err) | ||
1260 | goto out_nfserr; | ||
1258 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1261 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1259 | break; | 1262 | break; |
1260 | case S_IFDIR: | 1263 | case S_IFDIR: |
1264 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1265 | if (host_err) | ||
1266 | goto out_nfserr; | ||
1261 | host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); | 1267 | host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); |
1262 | break; | 1268 | break; |
1263 | case S_IFCHR: | 1269 | case S_IFCHR: |
1264 | case S_IFBLK: | 1270 | case S_IFBLK: |
1265 | case S_IFIFO: | 1271 | case S_IFIFO: |
1266 | case S_IFSOCK: | 1272 | case S_IFSOCK: |
1273 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1274 | if (host_err) | ||
1275 | goto out_nfserr; | ||
1267 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1276 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
1268 | break; | 1277 | break; |
1269 | default: | 1278 | default: |
1270 | printk("nfsd: bad file type %o in nfsd_create\n", type); | 1279 | printk("nfsd: bad file type %o in nfsd_create\n", type); |
1271 | host_err = -EINVAL; | 1280 | host_err = -EINVAL; |
1281 | goto out_nfserr; | ||
1272 | } | 1282 | } |
1273 | if (host_err < 0) | 1283 | if (host_err < 0) { |
1284 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1274 | goto out_nfserr; | 1285 | goto out_nfserr; |
1286 | } | ||
1275 | 1287 | ||
1276 | if (EX_ISSYNC(fhp->fh_export)) { | 1288 | if (EX_ISSYNC(fhp->fh_export)) { |
1277 | err = nfserrno(nfsd_sync_dir(dentry)); | 1289 | err = nfserrno(nfsd_sync_dir(dentry)); |
@@ -1282,6 +1294,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1282 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); | 1294 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); |
1283 | if (err2) | 1295 | if (err2) |
1284 | err = err2; | 1296 | err = err2; |
1297 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1285 | /* | 1298 | /* |
1286 | * Update the file handle to get the new inode info. | 1299 | * Update the file handle to get the new inode info. |
1287 | */ | 1300 | */ |
@@ -1359,6 +1372,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1359 | v_atime = verifier[1]&0x7fffffff; | 1372 | v_atime = verifier[1]&0x7fffffff; |
1360 | } | 1373 | } |
1361 | 1374 | ||
1375 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1376 | if (host_err) | ||
1377 | goto out_nfserr; | ||
1362 | if (dchild->d_inode) { | 1378 | if (dchild->d_inode) { |
1363 | err = 0; | 1379 | err = 0; |
1364 | 1380 | ||
@@ -1390,12 +1406,15 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1390 | case NFS3_CREATE_GUARDED: | 1406 | case NFS3_CREATE_GUARDED: |
1391 | err = nfserr_exist; | 1407 | err = nfserr_exist; |
1392 | } | 1408 | } |
1409 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1393 | goto out; | 1410 | goto out; |
1394 | } | 1411 | } |
1395 | 1412 | ||
1396 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1413 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1397 | if (host_err < 0) | 1414 | if (host_err < 0) { |
1415 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1398 | goto out_nfserr; | 1416 | goto out_nfserr; |
1417 | } | ||
1399 | if (created) | 1418 | if (created) |
1400 | *created = 1; | 1419 | *created = 1; |
1401 | 1420 | ||
@@ -1420,6 +1439,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1420 | if (err2) | 1439 | if (err2) |
1421 | err = err2; | 1440 | err = err2; |
1422 | 1441 | ||
1442 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1423 | /* | 1443 | /* |
1424 | * Update the filehandle to get the new inode info. | 1444 | * Update the filehandle to get the new inode info. |
1425 | */ | 1445 | */ |
@@ -1522,6 +1542,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1522 | if (iap && (iap->ia_valid & ATTR_MODE)) | 1542 | if (iap && (iap->ia_valid & ATTR_MODE)) |
1523 | mode = iap->ia_mode & S_IALLUGO; | 1543 | mode = iap->ia_mode & S_IALLUGO; |
1524 | 1544 | ||
1545 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1546 | if (host_err) | ||
1547 | goto out_nfserr; | ||
1548 | |||
1525 | if (unlikely(path[plen] != 0)) { | 1549 | if (unlikely(path[plen] != 0)) { |
1526 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); | 1550 | char *path_alloced = kmalloc(plen+1, GFP_KERNEL); |
1527 | if (path_alloced == NULL) | 1551 | if (path_alloced == NULL) |
@@ -1542,6 +1566,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1542 | err = nfserrno(host_err); | 1566 | err = nfserrno(host_err); |
1543 | fh_unlock(fhp); | 1567 | fh_unlock(fhp); |
1544 | 1568 | ||
1569 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1570 | |||
1545 | cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); | 1571 | cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); |
1546 | dput(dnew); | 1572 | dput(dnew); |
1547 | if (err==0) err = cerr; | 1573 | if (err==0) err = cerr; |
@@ -1592,6 +1618,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1592 | dold = tfhp->fh_dentry; | 1618 | dold = tfhp->fh_dentry; |
1593 | dest = dold->d_inode; | 1619 | dest = dold->d_inode; |
1594 | 1620 | ||
1621 | host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); | ||
1622 | if (host_err) { | ||
1623 | err = nfserrno(host_err); | ||
1624 | goto out_dput; | ||
1625 | } | ||
1595 | host_err = vfs_link(dold, dirp, dnew); | 1626 | host_err = vfs_link(dold, dirp, dnew); |
1596 | if (!host_err) { | 1627 | if (!host_err) { |
1597 | if (EX_ISSYNC(ffhp->fh_export)) { | 1628 | if (EX_ISSYNC(ffhp->fh_export)) { |
@@ -1605,7 +1636,8 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1605 | else | 1636 | else |
1606 | err = nfserrno(host_err); | 1637 | err = nfserrno(host_err); |
1607 | } | 1638 | } |
1608 | 1639 | mnt_drop_write(tfhp->fh_export->ex_path.mnt); | |
1640 | out_dput: | ||
1609 | dput(dnew); | 1641 | dput(dnew); |
1610 | out_unlock: | 1642 | out_unlock: |
1611 | fh_unlock(ffhp); | 1643 | fh_unlock(ffhp); |
@@ -1678,13 +1710,20 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1678 | if (ndentry == trap) | 1710 | if (ndentry == trap) |
1679 | goto out_dput_new; | 1711 | goto out_dput_new; |
1680 | 1712 | ||
1681 | #ifdef MSNFS | 1713 | if (svc_msnfs(ffhp) && |
1682 | if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && | ||
1683 | ((atomic_read(&odentry->d_count) > 1) | 1714 | ((atomic_read(&odentry->d_count) > 1) |
1684 | || (atomic_read(&ndentry->d_count) > 1))) { | 1715 | || (atomic_read(&ndentry->d_count) > 1))) { |
1685 | host_err = -EPERM; | 1716 | host_err = -EPERM; |
1686 | } else | 1717 | goto out_dput_new; |
1687 | #endif | 1718 | } |
1719 | |||
1720 | host_err = -EXDEV; | ||
1721 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | ||
1722 | goto out_dput_new; | ||
1723 | host_err = mnt_want_write(ffhp->fh_export->ex_path.mnt); | ||
1724 | if (host_err) | ||
1725 | goto out_dput_new; | ||
1726 | |||
1688 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1727 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1689 | if (!host_err && EX_ISSYNC(tfhp->fh_export)) { | 1728 | if (!host_err && EX_ISSYNC(tfhp->fh_export)) { |
1690 | host_err = nfsd_sync_dir(tdentry); | 1729 | host_err = nfsd_sync_dir(tdentry); |
@@ -1692,6 +1731,8 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1692 | host_err = nfsd_sync_dir(fdentry); | 1731 | host_err = nfsd_sync_dir(fdentry); |
1693 | } | 1732 | } |
1694 | 1733 | ||
1734 | mnt_drop_write(ffhp->fh_export->ex_path.mnt); | ||
1735 | |||
1695 | out_dput_new: | 1736 | out_dput_new: |
1696 | dput(ndentry); | 1737 | dput(ndentry); |
1697 | out_dput_old: | 1738 | out_dput_old: |
@@ -1750,6 +1791,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1750 | if (!type) | 1791 | if (!type) |
1751 | type = rdentry->d_inode->i_mode & S_IFMT; | 1792 | type = rdentry->d_inode->i_mode & S_IFMT; |
1752 | 1793 | ||
1794 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1795 | if (host_err) | ||
1796 | goto out_nfserr; | ||
1797 | |||
1753 | if (type != S_IFDIR) { /* It's UNLINK */ | 1798 | if (type != S_IFDIR) { /* It's UNLINK */ |
1754 | #ifdef MSNFS | 1799 | #ifdef MSNFS |
1755 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | 1800 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && |
@@ -1765,10 +1810,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1765 | dput(rdentry); | 1810 | dput(rdentry); |
1766 | 1811 | ||
1767 | if (host_err) | 1812 | if (host_err) |
1768 | goto out_nfserr; | 1813 | goto out_drop; |
1769 | if (EX_ISSYNC(fhp->fh_export)) | 1814 | if (EX_ISSYNC(fhp->fh_export)) |
1770 | host_err = nfsd_sync_dir(dentry); | 1815 | host_err = nfsd_sync_dir(dentry); |
1771 | 1816 | ||
1817 | out_drop: | ||
1818 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1772 | out_nfserr: | 1819 | out_nfserr: |
1773 | err = nfserrno(host_err); | 1820 | err = nfserrno(host_err); |
1774 | out: | 1821 | out: |
@@ -1865,7 +1912,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
1865 | inode->i_mode, | 1912 | inode->i_mode, |
1866 | IS_IMMUTABLE(inode)? " immut" : "", | 1913 | IS_IMMUTABLE(inode)? " immut" : "", |
1867 | IS_APPEND(inode)? " append" : "", | 1914 | IS_APPEND(inode)? " append" : "", |
1868 | IS_RDONLY(inode)? " ro" : ""); | 1915 | __mnt_is_readonly(exp->ex_path.mnt)? " ro" : ""); |
1869 | dprintk(" owner %d/%d user %d/%d\n", | 1916 | dprintk(" owner %d/%d user %d/%d\n", |
1870 | inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); | 1917 | inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); |
1871 | #endif | 1918 | #endif |
@@ -1876,7 +1923,8 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
1876 | */ | 1923 | */ |
1877 | if (!(acc & MAY_LOCAL_ACCESS)) | 1924 | if (!(acc & MAY_LOCAL_ACCESS)) |
1878 | if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { | 1925 | if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { |
1879 | if (exp_rdonly(rqstp, exp) || IS_RDONLY(inode)) | 1926 | if (exp_rdonly(rqstp, exp) || |
1927 | __mnt_is_readonly(exp->ex_path.mnt)) | ||
1880 | return nfserr_rofs; | 1928 | return nfserr_rofs; |
1881 | if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) | 1929 | if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) |
1882 | return nfserr_perm; | 1930 | return nfserr_perm; |
@@ -2039,6 +2087,9 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) | |||
2039 | } else | 2087 | } else |
2040 | size = 0; | 2088 | size = 0; |
2041 | 2089 | ||
2090 | error = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
2091 | if (error) | ||
2092 | goto getout; | ||
2042 | if (size) | 2093 | if (size) |
2043 | error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0); | 2094 | error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0); |
2044 | else { | 2095 | else { |
@@ -2050,6 +2101,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) | |||
2050 | error = 0; | 2101 | error = 0; |
2051 | } | 2102 | } |
2052 | } | 2103 | } |
2104 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
2053 | 2105 | ||
2054 | getout: | 2106 | getout: |
2055 | kfree(value); | 2107 | kfree(value); |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index b413166dd163..7b142f0ce995 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
@@ -60,10 +60,6 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | |||
60 | goto bail; | 60 | goto bail; |
61 | } | 61 | } |
62 | 62 | ||
63 | status = -EROFS; | ||
64 | if (IS_RDONLY(inode)) | ||
65 | goto bail_unlock; | ||
66 | |||
67 | status = -EACCES; | 63 | status = -EACCES; |
68 | if (!is_owner_or_cap(inode)) | 64 | if (!is_owner_or_cap(inode)) |
69 | goto bail_unlock; | 65 | goto bail_unlock; |
@@ -134,8 +130,13 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
134 | if (get_user(flags, (int __user *) arg)) | 130 | if (get_user(flags, (int __user *) arg)) |
135 | return -EFAULT; | 131 | return -EFAULT; |
136 | 132 | ||
137 | return ocfs2_set_inode_attr(inode, flags, | 133 | status = mnt_want_write(filp->f_path.mnt); |
134 | if (status) | ||
135 | return status; | ||
136 | status = ocfs2_set_inode_attr(inode, flags, | ||
138 | OCFS2_FL_MODIFIABLE); | 137 | OCFS2_FL_MODIFIABLE); |
138 | mnt_drop_write(filp->f_path.mnt); | ||
139 | return status; | ||
139 | case OCFS2_IOC_RESVSP: | 140 | case OCFS2_IOC_RESVSP: |
140 | case OCFS2_IOC_RESVSP64: | 141 | case OCFS2_IOC_RESVSP64: |
141 | case OCFS2_IOC_UNRESVSP: | 142 | case OCFS2_IOC_UNRESVSP: |
@@ -244,21 +244,21 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
244 | if (!S_ISREG(inode->i_mode)) | 244 | if (!S_ISREG(inode->i_mode)) |
245 | goto dput_and_out; | 245 | goto dput_and_out; |
246 | 246 | ||
247 | error = vfs_permission(&nd, MAY_WRITE); | 247 | error = mnt_want_write(nd.path.mnt); |
248 | if (error) | 248 | if (error) |
249 | goto dput_and_out; | 249 | goto dput_and_out; |
250 | 250 | ||
251 | error = -EROFS; | 251 | error = vfs_permission(&nd, MAY_WRITE); |
252 | if (IS_RDONLY(inode)) | 252 | if (error) |
253 | goto dput_and_out; | 253 | goto mnt_drop_write_and_out; |
254 | 254 | ||
255 | error = -EPERM; | 255 | error = -EPERM; |
256 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 256 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
257 | goto dput_and_out; | 257 | goto mnt_drop_write_and_out; |
258 | 258 | ||
259 | error = get_write_access(inode); | 259 | error = get_write_access(inode); |
260 | if (error) | 260 | if (error) |
261 | goto dput_and_out; | 261 | goto mnt_drop_write_and_out; |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * Make sure that there are no leases. get_write_access() protects | 264 | * Make sure that there are no leases. get_write_access() protects |
@@ -276,6 +276,8 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
276 | 276 | ||
277 | put_write_and_out: | 277 | put_write_and_out: |
278 | put_write_access(inode); | 278 | put_write_access(inode); |
279 | mnt_drop_write_and_out: | ||
280 | mnt_drop_write(nd.path.mnt); | ||
279 | dput_and_out: | 281 | dput_and_out: |
280 | path_put(&nd.path); | 282 | path_put(&nd.path); |
281 | out: | 283 | out: |
@@ -457,8 +459,17 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
457 | if(res || !(mode & S_IWOTH) || | 459 | if(res || !(mode & S_IWOTH) || |
458 | special_file(nd.path.dentry->d_inode->i_mode)) | 460 | special_file(nd.path.dentry->d_inode->i_mode)) |
459 | goto out_path_release; | 461 | goto out_path_release; |
460 | 462 | /* | |
461 | if(IS_RDONLY(nd.path.dentry->d_inode)) | 463 | * This is a rare case where using __mnt_is_readonly() |
464 | * is OK without a mnt_want/drop_write() pair. Since | ||
465 | * no actual write to the fs is performed here, we do | ||
466 | * not need to telegraph to that to anyone. | ||
467 | * | ||
468 | * By doing this, we accept that this access is | ||
469 | * inherently racy and know that the fs may change | ||
470 | * state before we even see this result. | ||
471 | */ | ||
472 | if (__mnt_is_readonly(nd.path.mnt)) | ||
462 | res = -EROFS; | 473 | res = -EROFS; |
463 | 474 | ||
464 | out_path_release: | 475 | out_path_release: |
@@ -567,12 +578,12 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
567 | 578 | ||
568 | audit_inode(NULL, dentry); | 579 | audit_inode(NULL, dentry); |
569 | 580 | ||
570 | err = -EROFS; | 581 | err = mnt_want_write(file->f_path.mnt); |
571 | if (IS_RDONLY(inode)) | 582 | if (err) |
572 | goto out_putf; | 583 | goto out_putf; |
573 | err = -EPERM; | 584 | err = -EPERM; |
574 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 585 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
575 | goto out_putf; | 586 | goto out_drop_write; |
576 | mutex_lock(&inode->i_mutex); | 587 | mutex_lock(&inode->i_mutex); |
577 | if (mode == (mode_t) -1) | 588 | if (mode == (mode_t) -1) |
578 | mode = inode->i_mode; | 589 | mode = inode->i_mode; |
@@ -581,6 +592,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
581 | err = notify_change(dentry, &newattrs); | 592 | err = notify_change(dentry, &newattrs); |
582 | mutex_unlock(&inode->i_mutex); | 593 | mutex_unlock(&inode->i_mutex); |
583 | 594 | ||
595 | out_drop_write: | ||
596 | mnt_drop_write(file->f_path.mnt); | ||
584 | out_putf: | 597 | out_putf: |
585 | fput(file); | 598 | fput(file); |
586 | out: | 599 | out: |
@@ -600,13 +613,13 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | |||
600 | goto out; | 613 | goto out; |
601 | inode = nd.path.dentry->d_inode; | 614 | inode = nd.path.dentry->d_inode; |
602 | 615 | ||
603 | error = -EROFS; | 616 | error = mnt_want_write(nd.path.mnt); |
604 | if (IS_RDONLY(inode)) | 617 | if (error) |
605 | goto dput_and_out; | 618 | goto dput_and_out; |
606 | 619 | ||
607 | error = -EPERM; | 620 | error = -EPERM; |
608 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 621 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
609 | goto dput_and_out; | 622 | goto out_drop_write; |
610 | 623 | ||
611 | mutex_lock(&inode->i_mutex); | 624 | mutex_lock(&inode->i_mutex); |
612 | if (mode == (mode_t) -1) | 625 | if (mode == (mode_t) -1) |
@@ -616,6 +629,8 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | |||
616 | error = notify_change(nd.path.dentry, &newattrs); | 629 | error = notify_change(nd.path.dentry, &newattrs); |
617 | mutex_unlock(&inode->i_mutex); | 630 | mutex_unlock(&inode->i_mutex); |
618 | 631 | ||
632 | out_drop_write: | ||
633 | mnt_drop_write(nd.path.mnt); | ||
619 | dput_and_out: | 634 | dput_and_out: |
620 | path_put(&nd.path); | 635 | path_put(&nd.path); |
621 | out: | 636 | out: |
@@ -638,9 +653,6 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
638 | printk(KERN_ERR "chown_common: NULL inode\n"); | 653 | printk(KERN_ERR "chown_common: NULL inode\n"); |
639 | goto out; | 654 | goto out; |
640 | } | 655 | } |
641 | error = -EROFS; | ||
642 | if (IS_RDONLY(inode)) | ||
643 | goto out; | ||
644 | error = -EPERM; | 656 | error = -EPERM; |
645 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 657 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
646 | goto out; | 658 | goto out; |
@@ -671,7 +683,12 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) | |||
671 | error = user_path_walk(filename, &nd); | 683 | error = user_path_walk(filename, &nd); |
672 | if (error) | 684 | if (error) |
673 | goto out; | 685 | goto out; |
686 | error = mnt_want_write(nd.path.mnt); | ||
687 | if (error) | ||
688 | goto out_release; | ||
674 | error = chown_common(nd.path.dentry, user, group); | 689 | error = chown_common(nd.path.dentry, user, group); |
690 | mnt_drop_write(nd.path.mnt); | ||
691 | out_release: | ||
675 | path_put(&nd.path); | 692 | path_put(&nd.path); |
676 | out: | 693 | out: |
677 | return error; | 694 | return error; |
@@ -691,7 +708,12 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
691 | error = __user_walk_fd(dfd, filename, follow, &nd); | 708 | error = __user_walk_fd(dfd, filename, follow, &nd); |
692 | if (error) | 709 | if (error) |
693 | goto out; | 710 | goto out; |
711 | error = mnt_want_write(nd.path.mnt); | ||
712 | if (error) | ||
713 | goto out_release; | ||
694 | error = chown_common(nd.path.dentry, user, group); | 714 | error = chown_common(nd.path.dentry, user, group); |
715 | mnt_drop_write(nd.path.mnt); | ||
716 | out_release: | ||
695 | path_put(&nd.path); | 717 | path_put(&nd.path); |
696 | out: | 718 | out: |
697 | return error; | 719 | return error; |
@@ -705,7 +727,12 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group | |||
705 | error = user_path_walk_link(filename, &nd); | 727 | error = user_path_walk_link(filename, &nd); |
706 | if (error) | 728 | if (error) |
707 | goto out; | 729 | goto out; |
730 | error = mnt_want_write(nd.path.mnt); | ||
731 | if (error) | ||
732 | goto out_release; | ||
708 | error = chown_common(nd.path.dentry, user, group); | 733 | error = chown_common(nd.path.dentry, user, group); |
734 | mnt_drop_write(nd.path.mnt); | ||
735 | out_release: | ||
709 | path_put(&nd.path); | 736 | path_put(&nd.path); |
710 | out: | 737 | out: |
711 | return error; | 738 | return error; |
@@ -722,14 +749,48 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
722 | if (!file) | 749 | if (!file) |
723 | goto out; | 750 | goto out; |
724 | 751 | ||
752 | error = mnt_want_write(file->f_path.mnt); | ||
753 | if (error) | ||
754 | goto out_fput; | ||
725 | dentry = file->f_path.dentry; | 755 | dentry = file->f_path.dentry; |
726 | audit_inode(NULL, dentry); | 756 | audit_inode(NULL, dentry); |
727 | error = chown_common(dentry, user, group); | 757 | error = chown_common(dentry, user, group); |
758 | mnt_drop_write(file->f_path.mnt); | ||
759 | out_fput: | ||
728 | fput(file); | 760 | fput(file); |
729 | out: | 761 | out: |
730 | return error; | 762 | return error; |
731 | } | 763 | } |
732 | 764 | ||
765 | /* | ||
766 | * You have to be very careful that these write | ||
767 | * counts get cleaned up in error cases and | ||
768 | * upon __fput(). This should probably never | ||
769 | * be called outside of __dentry_open(). | ||
770 | */ | ||
771 | static inline int __get_file_write_access(struct inode *inode, | ||
772 | struct vfsmount *mnt) | ||
773 | { | ||
774 | int error; | ||
775 | error = get_write_access(inode); | ||
776 | if (error) | ||
777 | return error; | ||
778 | /* | ||
779 | * Do not take mount writer counts on | ||
780 | * special files since no writes to | ||
781 | * the mount itself will occur. | ||
782 | */ | ||
783 | if (!special_file(inode->i_mode)) { | ||
784 | /* | ||
785 | * Balanced in __fput() | ||
786 | */ | ||
787 | error = mnt_want_write(mnt); | ||
788 | if (error) | ||
789 | put_write_access(inode); | ||
790 | } | ||
791 | return error; | ||
792 | } | ||
793 | |||
733 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 794 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
734 | int flags, struct file *f, | 795 | int flags, struct file *f, |
735 | int (*open)(struct inode *, struct file *)) | 796 | int (*open)(struct inode *, struct file *)) |
@@ -742,9 +803,11 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
742 | FMODE_PREAD | FMODE_PWRITE; | 803 | FMODE_PREAD | FMODE_PWRITE; |
743 | inode = dentry->d_inode; | 804 | inode = dentry->d_inode; |
744 | if (f->f_mode & FMODE_WRITE) { | 805 | if (f->f_mode & FMODE_WRITE) { |
745 | error = get_write_access(inode); | 806 | error = __get_file_write_access(inode, mnt); |
746 | if (error) | 807 | if (error) |
747 | goto cleanup_file; | 808 | goto cleanup_file; |
809 | if (!special_file(inode->i_mode)) | ||
810 | file_take_write(f); | ||
748 | } | 811 | } |
749 | 812 | ||
750 | f->f_mapping = inode->i_mapping; | 813 | f->f_mapping = inode->i_mapping; |
@@ -784,8 +847,19 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
784 | 847 | ||
785 | cleanup_all: | 848 | cleanup_all: |
786 | fops_put(f->f_op); | 849 | fops_put(f->f_op); |
787 | if (f->f_mode & FMODE_WRITE) | 850 | if (f->f_mode & FMODE_WRITE) { |
788 | put_write_access(inode); | 851 | put_write_access(inode); |
852 | if (!special_file(inode->i_mode)) { | ||
853 | /* | ||
854 | * We don't consider this a real | ||
855 | * mnt_want/drop_write() pair | ||
856 | * because it all happenend right | ||
857 | * here, so just reset the state. | ||
858 | */ | ||
859 | file_reset_write(f); | ||
860 | mnt_drop_write(mnt); | ||
861 | } | ||
862 | } | ||
789 | file_kill(f); | 863 | file_kill(f); |
790 | f->f_path.dentry = NULL; | 864 | f->f_path.dentry = NULL; |
791 | f->f_path.mnt = NULL; | 865 | f->f_path.mnt = NULL; |
@@ -796,43 +870,6 @@ cleanup_file: | |||
796 | return ERR_PTR(error); | 870 | return ERR_PTR(error); |
797 | } | 871 | } |
798 | 872 | ||
799 | /* | ||
800 | * Note that while the flag value (low two bits) for sys_open means: | ||
801 | * 00 - read-only | ||
802 | * 01 - write-only | ||
803 | * 10 - read-write | ||
804 | * 11 - special | ||
805 | * it is changed into | ||
806 | * 00 - no permissions needed | ||
807 | * 01 - read-permission | ||
808 | * 10 - write-permission | ||
809 | * 11 - read-write | ||
810 | * for the internal routines (ie open_namei()/follow_link() etc). 00 is | ||
811 | * used by symlinks. | ||
812 | */ | ||
813 | static struct file *do_filp_open(int dfd, const char *filename, int flags, | ||
814 | int mode) | ||
815 | { | ||
816 | int namei_flags, error; | ||
817 | struct nameidata nd; | ||
818 | |||
819 | namei_flags = flags; | ||
820 | if ((namei_flags+1) & O_ACCMODE) | ||
821 | namei_flags++; | ||
822 | |||
823 | error = open_namei(dfd, filename, namei_flags, mode, &nd); | ||
824 | if (!error) | ||
825 | return nameidata_to_filp(&nd, flags); | ||
826 | |||
827 | return ERR_PTR(error); | ||
828 | } | ||
829 | |||
830 | struct file *filp_open(const char *filename, int flags, int mode) | ||
831 | { | ||
832 | return do_filp_open(AT_FDCWD, filename, flags, mode); | ||
833 | } | ||
834 | EXPORT_SYMBOL(filp_open); | ||
835 | |||
836 | /** | 873 | /** |
837 | * lookup_instantiate_filp - instantiates the open intent filp | 874 | * lookup_instantiate_filp - instantiates the open intent filp |
838 | * @nd: pointer to nameidata | 875 | * @nd: pointer to nameidata |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 03f808c5b79d..6149e4b58c88 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -473,6 +473,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
473 | return 0; | 473 | return 0; |
474 | if (IS_ERR(state)) /* I/O error reading the partition table */ | 474 | if (IS_ERR(state)) /* I/O error reading the partition table */ |
475 | return -EIO; | 475 | return -EIO; |
476 | |||
477 | /* tell userspace that the media / partition table may have changed */ | ||
478 | kobject_uevent(&disk->dev.kobj, KOBJ_CHANGE); | ||
479 | |||
476 | for (p = 1; p < state->limit; p++) { | 480 | for (p = 1; p < state->limit; p++) { |
477 | sector_t size = state->parts[p].size; | 481 | sector_t size = state->parts[p].size; |
478 | sector_t from = state->parts[p].from; | 482 | sector_t from = state->parts[p].from; |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index e0f0f098a523..74363a7aacbc 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include <linux/capability.h> | 5 | #include <linux/capability.h> |
6 | #include <linux/fs.h> | 6 | #include <linux/fs.h> |
7 | #include <linux/mount.h> | ||
7 | #include <linux/reiserfs_fs.h> | 8 | #include <linux/reiserfs_fs.h> |
8 | #include <linux/time.h> | 9 | #include <linux/time.h> |
9 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
@@ -25,6 +26,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
25 | unsigned long arg) | 26 | unsigned long arg) |
26 | { | 27 | { |
27 | unsigned int flags; | 28 | unsigned int flags; |
29 | int err = 0; | ||
28 | 30 | ||
29 | switch (cmd) { | 31 | switch (cmd) { |
30 | case REISERFS_IOC_UNPACK: | 32 | case REISERFS_IOC_UNPACK: |
@@ -48,50 +50,67 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
48 | if (!reiserfs_attrs(inode->i_sb)) | 50 | if (!reiserfs_attrs(inode->i_sb)) |
49 | return -ENOTTY; | 51 | return -ENOTTY; |
50 | 52 | ||
51 | if (IS_RDONLY(inode)) | 53 | err = mnt_want_write(filp->f_path.mnt); |
52 | return -EROFS; | 54 | if (err) |
55 | return err; | ||
53 | 56 | ||
54 | if (!is_owner_or_cap(inode)) | 57 | if (!is_owner_or_cap(inode)) { |
55 | return -EPERM; | 58 | err = -EPERM; |
56 | 59 | goto setflags_out; | |
57 | if (get_user(flags, (int __user *)arg)) | 60 | } |
58 | return -EFAULT; | 61 | if (get_user(flags, (int __user *)arg)) { |
59 | 62 | err = -EFAULT; | |
60 | /* Is it quota file? Do not allow user to mess with it. */ | 63 | goto setflags_out; |
61 | if (IS_NOQUOTA(inode)) | 64 | } |
62 | return -EPERM; | 65 | /* |
66 | * Is it quota file? Do not allow user to mess with it | ||
67 | */ | ||
68 | if (IS_NOQUOTA(inode)) { | ||
69 | err = -EPERM; | ||
70 | goto setflags_out; | ||
71 | } | ||
63 | if (((flags ^ REISERFS_I(inode)-> | 72 | if (((flags ^ REISERFS_I(inode)-> |
64 | i_attrs) & (REISERFS_IMMUTABLE_FL | | 73 | i_attrs) & (REISERFS_IMMUTABLE_FL | |
65 | REISERFS_APPEND_FL)) | 74 | REISERFS_APPEND_FL)) |
66 | && !capable(CAP_LINUX_IMMUTABLE)) | 75 | && !capable(CAP_LINUX_IMMUTABLE)) { |
67 | return -EPERM; | 76 | err = -EPERM; |
68 | 77 | goto setflags_out; | |
78 | } | ||
69 | if ((flags & REISERFS_NOTAIL_FL) && | 79 | if ((flags & REISERFS_NOTAIL_FL) && |
70 | S_ISREG(inode->i_mode)) { | 80 | S_ISREG(inode->i_mode)) { |
71 | int result; | 81 | int result; |
72 | 82 | ||
73 | result = reiserfs_unpack(inode, filp); | 83 | result = reiserfs_unpack(inode, filp); |
74 | if (result) | 84 | if (result) { |
75 | return result; | 85 | err = result; |
86 | goto setflags_out; | ||
87 | } | ||
76 | } | 88 | } |
77 | sd_attrs_to_i_attrs(flags, inode); | 89 | sd_attrs_to_i_attrs(flags, inode); |
78 | REISERFS_I(inode)->i_attrs = flags; | 90 | REISERFS_I(inode)->i_attrs = flags; |
79 | inode->i_ctime = CURRENT_TIME_SEC; | 91 | inode->i_ctime = CURRENT_TIME_SEC; |
80 | mark_inode_dirty(inode); | 92 | mark_inode_dirty(inode); |
81 | return 0; | 93 | setflags_out: |
94 | mnt_drop_write(filp->f_path.mnt); | ||
95 | return err; | ||
82 | } | 96 | } |
83 | case REISERFS_IOC_GETVERSION: | 97 | case REISERFS_IOC_GETVERSION: |
84 | return put_user(inode->i_generation, (int __user *)arg); | 98 | return put_user(inode->i_generation, (int __user *)arg); |
85 | case REISERFS_IOC_SETVERSION: | 99 | case REISERFS_IOC_SETVERSION: |
86 | if (!is_owner_or_cap(inode)) | 100 | if (!is_owner_or_cap(inode)) |
87 | return -EPERM; | 101 | return -EPERM; |
88 | if (IS_RDONLY(inode)) | 102 | err = mnt_want_write(filp->f_path.mnt); |
89 | return -EROFS; | 103 | if (err) |
90 | if (get_user(inode->i_generation, (int __user *)arg)) | 104 | return err; |
91 | return -EFAULT; | 105 | if (get_user(inode->i_generation, (int __user *)arg)) { |
106 | err = -EFAULT; | ||
107 | goto setversion_out; | ||
108 | } | ||
92 | inode->i_ctime = CURRENT_TIME_SEC; | 109 | inode->i_ctime = CURRENT_TIME_SEC; |
93 | mark_inode_dirty(inode); | 110 | mark_inode_dirty(inode); |
94 | return 0; | 111 | setversion_out: |
112 | mnt_drop_write(filp->f_path.mnt); | ||
113 | return err; | ||
95 | default: | 114 | default: |
96 | return -ENOTTY; | 115 | return -ENOTTY; |
97 | } | 116 | } |
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index bb05a3e51b93..060eb3f598e7 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | 39 | ||
40 | #include <linux/time.h> | 40 | #include <linux/time.h> |
41 | #include <asm/semaphore.h> | 41 | #include <linux/semaphore.h> |
42 | 42 | ||
43 | #include <linux/vmalloc.h> | 43 | #include <linux/vmalloc.h> |
44 | #include <linux/reiserfs_fs.h> | 44 | #include <linux/reiserfs_fs.h> |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 344b9b96cc56..d7c4935c1034 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <net/checksum.h> | 44 | #include <net/checksum.h> |
45 | #include <linux/smp_lock.h> | 45 | #include <linux/smp_lock.h> |
46 | #include <linux/stat.h> | 46 | #include <linux/stat.h> |
47 | #include <asm/semaphore.h> | ||
48 | 47 | ||
49 | #define FL_READONLY 128 | 48 | #define FL_READONLY 128 |
50 | #define FL_DIR_SEM_HELD 256 | 49 | #define FL_DIR_SEM_HELD 256 |
diff --git a/fs/select.c b/fs/select.c index 5633fe980781..00f58c5c7e05 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -260,7 +260,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
260 | wait = NULL; | 260 | wait = NULL; |
261 | if (retval || !*timeout || signal_pending(current)) | 261 | if (retval || !*timeout || signal_pending(current)) |
262 | break; | 262 | break; |
263 | if(table.error) { | 263 | if (table.error) { |
264 | retval = table.error; | 264 | retval = table.error; |
265 | break; | 265 | break; |
266 | } | 266 | } |
diff --git a/fs/super.c b/fs/super.c index 09008dbd264e..1f8f05ede437 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
38 | #include <linux/kobject.h> | 38 | #include <linux/kobject.h> |
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/file.h> | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | 42 | ||
42 | 43 | ||
@@ -567,10 +568,29 @@ static void mark_files_ro(struct super_block *sb) | |||
567 | { | 568 | { |
568 | struct file *f; | 569 | struct file *f; |
569 | 570 | ||
571 | retry: | ||
570 | file_list_lock(); | 572 | file_list_lock(); |
571 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { | 573 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { |
572 | if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f)) | 574 | struct vfsmount *mnt; |
573 | f->f_mode &= ~FMODE_WRITE; | 575 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
576 | continue; | ||
577 | if (!file_count(f)) | ||
578 | continue; | ||
579 | if (!(f->f_mode & FMODE_WRITE)) | ||
580 | continue; | ||
581 | f->f_mode &= ~FMODE_WRITE; | ||
582 | if (file_check_writeable(f) != 0) | ||
583 | continue; | ||
584 | file_release_write(f); | ||
585 | mnt = mntget(f->f_path.mnt); | ||
586 | file_list_unlock(); | ||
587 | /* | ||
588 | * This can sleep, so we can't hold | ||
589 | * the file_list_lock() spinlock. | ||
590 | */ | ||
591 | mnt_drop_write(mnt); | ||
592 | mntput(mnt); | ||
593 | goto retry; | ||
574 | } | 594 | } |
575 | file_list_unlock(); | 595 | file_list_unlock(); |
576 | } | 596 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4948d9bc405d..a1c3a1fab7f0 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
21 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/slab.h> | ||
23 | #include "sysfs.h" | 24 | #include "sysfs.h" |
24 | 25 | ||
25 | DEFINE_MUTEX(sysfs_mutex); | 26 | DEFINE_MUTEX(sysfs_mutex); |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index baa663e69388..ade9a7e6a757 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/kobject.h> | 14 | #include <linux/kobject.h> |
15 | #include <linux/kallsyms.h> | 15 | #include <linux/kallsyms.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
17 | #include <linux/poll.h> | 18 | #include <linux/poll.h> |
18 | #include <linux/list.h> | 19 | #include <linux/list.h> |
@@ -128,7 +129,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
128 | ssize_t retval = 0; | 129 | ssize_t retval = 0; |
129 | 130 | ||
130 | mutex_lock(&buffer->mutex); | 131 | mutex_lock(&buffer->mutex); |
131 | if (buffer->needs_read_fill) { | 132 | if (buffer->needs_read_fill || *ppos == 0) { |
132 | retval = fill_read_buffer(file->f_path.dentry,buffer); | 133 | retval = fill_read_buffer(file->f_path.dentry,buffer); |
133 | if (retval) | 134 | if (retval) |
134 | goto out; | 135 | goto out; |
@@ -409,8 +410,7 @@ static int sysfs_release(struct inode *inode, struct file *filp) | |||
409 | * return POLLERR|POLLPRI, and select will return the fd whether | 410 | * return POLLERR|POLLPRI, and select will return the fd whether |
410 | * it is waiting for read, write, or exceptions. | 411 | * it is waiting for read, write, or exceptions. |
411 | * Once poll/select indicates that the value has changed, you | 412 | * Once poll/select indicates that the value has changed, you |
412 | * need to close and re-open the file, as simply seeking and reading | 413 | * need to close and re-open the file, or seek to 0 and read again. |
413 | * again will not get new data, or reset the state of 'poll'. | ||
414 | * Reminder: this only works for attributes which actively support | 414 | * Reminder: this only works for attributes which actively support |
415 | * it, and it is not possible to test an attribute from userspace | 415 | * it, and it is not possible to test an attribute from userspace |
416 | * to see if it supports poll (Neither 'poll' nor 'select' return | 416 | * to see if it supports poll (Neither 'poll' nor 'select' return |
diff --git a/fs/udf/Makefile b/fs/udf/Makefile index be845e7540ef..0d4503f7446d 100644 --- a/fs/udf/Makefile +++ b/fs/udf/Makefile | |||
@@ -6,4 +6,4 @@ obj-$(CONFIG_UDF_FS) += udf.o | |||
6 | 6 | ||
7 | udf-objs := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \ | 7 | udf-objs := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \ |
8 | partition.o super.o truncate.o symlink.o fsync.o \ | 8 | partition.o super.o truncate.o symlink.o fsync.o \ |
9 | crc.o directory.o misc.o udftime.o unicode.o | 9 | directory.o misc.o udftime.o unicode.o |
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index f855dcbbdfb8..1b809bd494bd 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
@@ -149,8 +149,7 @@ static bool udf_add_free_space(struct udf_sb_info *sbi, | |||
149 | return false; | 149 | return false; |
150 | 150 | ||
151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; | 151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; |
152 | lvid->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu( | 152 | le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); |
153 | lvid->freeSpaceTable[partition]) + cnt); | ||
154 | return true; | 153 | return true; |
155 | } | 154 | } |
156 | 155 | ||
@@ -589,10 +588,8 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
589 | sptr = oepos.bh->b_data + epos.offset; | 588 | sptr = oepos.bh->b_data + epos.offset; |
590 | aed = (struct allocExtDesc *) | 589 | aed = (struct allocExtDesc *) |
591 | oepos.bh->b_data; | 590 | oepos.bh->b_data; |
592 | aed->lengthAllocDescs = | 591 | le32_add_cpu(&aed->lengthAllocDescs, |
593 | cpu_to_le32(le32_to_cpu( | 592 | adsize); |
594 | aed->lengthAllocDescs) + | ||
595 | adsize); | ||
596 | } else { | 593 | } else { |
597 | sptr = iinfo->i_ext.i_data + | 594 | sptr = iinfo->i_ext.i_data + |
598 | epos.offset; | 595 | epos.offset; |
@@ -645,9 +642,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
645 | mark_inode_dirty(table); | 642 | mark_inode_dirty(table); |
646 | } else { | 643 | } else { |
647 | aed = (struct allocExtDesc *)epos.bh->b_data; | 644 | aed = (struct allocExtDesc *)epos.bh->b_data; |
648 | aed->lengthAllocDescs = | 645 | le32_add_cpu(&aed->lengthAllocDescs, adsize); |
649 | cpu_to_le32(le32_to_cpu( | ||
650 | aed->lengthAllocDescs) + adsize); | ||
651 | udf_update_tag(epos.bh->b_data, epos.offset); | 646 | udf_update_tag(epos.bh->b_data, epos.offset); |
652 | mark_buffer_dirty(epos.bh); | 647 | mark_buffer_dirty(epos.bh); |
653 | } | 648 | } |
diff --git a/fs/udf/crc.c b/fs/udf/crc.c deleted file mode 100644 index b1661296e786..000000000000 --- a/fs/udf/crc.c +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | * crc.c | ||
3 | * | ||
4 | * PURPOSE | ||
5 | * Routines to generate, calculate, and test a 16-bit CRC. | ||
6 | * | ||
7 | * DESCRIPTION | ||
8 | * The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories | ||
9 | * and Ned W. Rhodes of Software Systems Group. It has been published in | ||
10 | * "Design and Validation of Computer Protocols", Prentice Hall, | ||
11 | * Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4. | ||
12 | * | ||
13 | * Copyright is held by AT&T. | ||
14 | * | ||
15 | * AT&T gives permission for the free use of the CRC source code. | ||
16 | * | ||
17 | * COPYRIGHT | ||
18 | * This file is distributed under the terms of the GNU General Public | ||
19 | * License (GPL). Copies of the GPL can be obtained from: | ||
20 | * ftp://prep.ai.mit.edu/pub/gnu/GPL | ||
21 | * Each contributing author retains all rights to their own work. | ||
22 | */ | ||
23 | |||
24 | #include "udfdecl.h" | ||
25 | |||
26 | static uint16_t crc_table[256] = { | ||
27 | 0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U, | ||
28 | 0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU, | ||
29 | 0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U, | ||
30 | 0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU, | ||
31 | 0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U, | ||
32 | 0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU, | ||
33 | 0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U, | ||
34 | 0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU, | ||
35 | 0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U, | ||
36 | 0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU, | ||
37 | 0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U, | ||
38 | 0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU, | ||
39 | 0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U, | ||
40 | 0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U, | ||
41 | 0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U, | ||
42 | 0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U, | ||
43 | 0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU, | ||
44 | 0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U, | ||
45 | 0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU, | ||
46 | 0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U, | ||
47 | 0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU, | ||
48 | 0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U, | ||
49 | 0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU, | ||
50 | 0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U, | ||
51 | 0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU, | ||
52 | 0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U, | ||
53 | 0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU, | ||
54 | 0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U, | ||
55 | 0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U, | ||
56 | 0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U, | ||
57 | 0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U, | ||
58 | 0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * udf_crc | ||
63 | * | ||
64 | * PURPOSE | ||
65 | * Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial. | ||
66 | * | ||
67 | * DESCRIPTION | ||
68 | * The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory. | ||
69 | * The polynomial used is: x^16 + x^12 + x^15 + 1 | ||
70 | * | ||
71 | * PRE-CONDITIONS | ||
72 | * data Pointer to the data block. | ||
73 | * size Size of the data block. | ||
74 | * | ||
75 | * POST-CONDITIONS | ||
76 | * <return> CRC of the data block. | ||
77 | * | ||
78 | * HISTORY | ||
79 | * July 21, 1997 - Andrew E. Mileski | ||
80 | * Adapted from OSTA-UDF(tm) 1.50 standard. | ||
81 | */ | ||
82 | uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc) | ||
83 | { | ||
84 | while (size--) | ||
85 | crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8); | ||
86 | |||
87 | return crc; | ||
88 | } | ||
89 | |||
90 | /****************************************************************************/ | ||
91 | #if defined(TEST) | ||
92 | |||
93 | /* | ||
94 | * PURPOSE | ||
95 | * Test udf_crc() | ||
96 | * | ||
97 | * HISTORY | ||
98 | * July 21, 1997 - Andrew E. Mileski | ||
99 | * Adapted from OSTA-UDF(tm) 1.50 standard. | ||
100 | */ | ||
101 | |||
102 | unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U }; | ||
103 | |||
104 | int main(void) | ||
105 | { | ||
106 | unsigned short x; | ||
107 | |||
108 | x = udf_crc(bytes, sizeof bytes); | ||
109 | printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | #endif /* defined(TEST) */ | ||
115 | |||
116 | /****************************************************************************/ | ||
117 | #if defined(GENERATE) | ||
118 | |||
119 | /* | ||
120 | * PURPOSE | ||
121 | * Generate a table for fast 16-bit CRC calculations (any polynomial). | ||
122 | * | ||
123 | * DESCRIPTION | ||
124 | * The ITU-T V.41 polynomial is 010041. | ||
125 | * | ||
126 | * HISTORY | ||
127 | * July 21, 1997 - Andrew E. Mileski | ||
128 | * Adapted from OSTA-UDF(tm) 1.50 standard. | ||
129 | */ | ||
130 | |||
131 | #include <stdio.h> | ||
132 | |||
133 | int main(int argc, char **argv) | ||
134 | { | ||
135 | unsigned long crc, poly; | ||
136 | int n, i; | ||
137 | |||
138 | /* Get the polynomial */ | ||
139 | sscanf(argv[1], "%lo", &poly); | ||
140 | if (poly & 0xffff0000U) { | ||
141 | fprintf(stderr, "polynomial is too large\en"); | ||
142 | exit(1); | ||
143 | } | ||
144 | |||
145 | printf("/* CRC 0%o */\n", poly); | ||
146 | |||
147 | /* Create a table */ | ||
148 | printf("static unsigned short crc_table[256] = {\n"); | ||
149 | for (n = 0; n < 256; n++) { | ||
150 | if (n % 8 == 0) | ||
151 | printf("\t"); | ||
152 | crc = n << 8; | ||
153 | for (i = 0; i < 8; i++) { | ||
154 | if (crc & 0x8000U) | ||
155 | crc = (crc << 1) ^ poly; | ||
156 | else | ||
157 | crc <<= 1; | ||
158 | crc &= 0xFFFFU; | ||
159 | } | ||
160 | if (n == 255) | ||
161 | printf("0x%04xU ", crc); | ||
162 | else | ||
163 | printf("0x%04xU, ", crc); | ||
164 | if (n % 8 == 7) | ||
165 | printf("\n"); | ||
166 | } | ||
167 | printf("};\n"); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | #endif /* defined(GENERATE) */ | ||
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 8d8643ada199..62dc270c69d1 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -39,13 +39,13 @@ | |||
39 | static int do_udf_readdir(struct inode *dir, struct file *filp, | 39 | static int do_udf_readdir(struct inode *dir, struct file *filp, |
40 | filldir_t filldir, void *dirent) | 40 | filldir_t filldir, void *dirent) |
41 | { | 41 | { |
42 | struct udf_fileident_bh fibh; | 42 | struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; |
43 | struct fileIdentDesc *fi = NULL; | 43 | struct fileIdentDesc *fi = NULL; |
44 | struct fileIdentDesc cfi; | 44 | struct fileIdentDesc cfi; |
45 | int block, iblock; | 45 | int block, iblock; |
46 | loff_t nf_pos = (filp->f_pos - 1) << 2; | 46 | loff_t nf_pos = (filp->f_pos - 1) << 2; |
47 | int flen; | 47 | int flen; |
48 | char fname[UDF_NAME_LEN]; | 48 | char *fname = NULL; |
49 | char *nameptr; | 49 | char *nameptr; |
50 | uint16_t liu; | 50 | uint16_t liu; |
51 | uint8_t lfi; | 51 | uint8_t lfi; |
@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
54 | kernel_lb_addr eloc; | 54 | kernel_lb_addr eloc; |
55 | uint32_t elen; | 55 | uint32_t elen; |
56 | sector_t offset; | 56 | sector_t offset; |
57 | int i, num; | 57 | int i, num, ret = 0; |
58 | unsigned int dt_type; | 58 | unsigned int dt_type; |
59 | struct extent_position epos = { NULL, 0, {0, 0} }; | 59 | struct extent_position epos = { NULL, 0, {0, 0} }; |
60 | struct udf_inode_info *iinfo; | 60 | struct udf_inode_info *iinfo; |
61 | 61 | ||
62 | if (nf_pos >= size) | 62 | if (nf_pos >= size) |
63 | return 0; | 63 | goto out; |
64 | |||
65 | fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); | ||
66 | if (!fname) { | ||
67 | ret = -ENOMEM; | ||
68 | goto out; | ||
69 | } | ||
64 | 70 | ||
65 | if (nf_pos == 0) | 71 | if (nf_pos == 0) |
66 | nf_pos = udf_ext0_offset(dir); | 72 | nf_pos = udf_ext0_offset(dir); |
67 | 73 | ||
68 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); | 74 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); |
69 | iinfo = UDF_I(dir); | 75 | iinfo = UDF_I(dir); |
70 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 76 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
71 | fibh.sbh = fibh.ebh = NULL; | 77 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, |
72 | } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, | 78 | &epos, &eloc, &elen, &offset) |
73 | &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) { | 79 | != (EXT_RECORDED_ALLOCATED >> 30)) { |
80 | ret = -ENOENT; | ||
81 | goto out; | ||
82 | } | ||
74 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 83 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); |
75 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 84 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
76 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
83 | } | 92 | } |
84 | 93 | ||
85 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { | 94 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { |
86 | brelse(epos.bh); | 95 | ret = -EIO; |
87 | return -EIO; | 96 | goto out; |
88 | } | 97 | } |
89 | 98 | ||
90 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { | 99 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { |
@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
105 | brelse(bha[i]); | 114 | brelse(bha[i]); |
106 | } | 115 | } |
107 | } | 116 | } |
108 | } else { | ||
109 | brelse(epos.bh); | ||
110 | return -ENOENT; | ||
111 | } | 117 | } |
112 | 118 | ||
113 | while (nf_pos < size) { | 119 | while (nf_pos < size) { |
@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
115 | 121 | ||
116 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, | 122 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, |
117 | &elen, &offset); | 123 | &elen, &offset); |
118 | if (!fi) { | 124 | if (!fi) |
119 | if (fibh.sbh != fibh.ebh) | 125 | goto out; |
120 | brelse(fibh.ebh); | ||
121 | brelse(fibh.sbh); | ||
122 | brelse(epos.bh); | ||
123 | return 0; | ||
124 | } | ||
125 | 126 | ||
126 | liu = le16_to_cpu(cfi.lengthOfImpUse); | 127 | liu = le16_to_cpu(cfi.lengthOfImpUse); |
127 | lfi = cfi.lengthFileIdent; | 128 | lfi = cfi.lengthFileIdent; |
@@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
167 | dt_type = DT_UNKNOWN; | 168 | dt_type = DT_UNKNOWN; |
168 | } | 169 | } |
169 | 170 | ||
170 | if (flen) { | 171 | if (flen && filldir(dirent, fname, flen, filp->f_pos, |
171 | if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) { | 172 | iblock, dt_type) < 0) |
172 | if (fibh.sbh != fibh.ebh) | 173 | goto out; |
173 | brelse(fibh.ebh); | ||
174 | brelse(fibh.sbh); | ||
175 | brelse(epos.bh); | ||
176 | return 0; | ||
177 | } | ||
178 | } | ||
179 | } /* end while */ | 174 | } /* end while */ |
180 | 175 | ||
181 | filp->f_pos = (nf_pos >> 2) + 1; | 176 | filp->f_pos = (nf_pos >> 2) + 1; |
182 | 177 | ||
178 | out: | ||
183 | if (fibh.sbh != fibh.ebh) | 179 | if (fibh.sbh != fibh.ebh) |
184 | brelse(fibh.ebh); | 180 | brelse(fibh.ebh); |
185 | brelse(fibh.sbh); | 181 | brelse(fibh.sbh); |
186 | brelse(epos.bh); | 182 | brelse(epos.bh); |
183 | kfree(fname); | ||
187 | 184 | ||
188 | return 0; | 185 | return ret; |
189 | } | 186 | } |
190 | 187 | ||
191 | /* | ||
192 | * udf_readdir | ||
193 | * | ||
194 | * PURPOSE | ||
195 | * Read a directory entry. | ||
196 | * | ||
197 | * DESCRIPTION | ||
198 | * Optional - sys_getdents() will return -ENOTDIR if this routine is not | ||
199 | * available. | ||
200 | * | ||
201 | * Refer to sys_getdents() in fs/readdir.c | ||
202 | * sys_getdents() -> . | ||
203 | * | ||
204 | * PRE-CONDITIONS | ||
205 | * filp Pointer to directory file. | ||
206 | * buf Pointer to directory entry buffer. | ||
207 | * filldir Pointer to filldir function. | ||
208 | * | ||
209 | * POST-CONDITIONS | ||
210 | * <return> >=0 on success. | ||
211 | * | ||
212 | * HISTORY | ||
213 | * July 1, 1997 - Andrew E. Mileski | ||
214 | * Written, tested, and released. | ||
215 | */ | ||
216 | |||
217 | static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) | 188 | static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) |
218 | { | 189 | { |
219 | struct inode *dir = filp->f_path.dentry->d_inode; | 190 | struct inode *dir = filp->f_path.dentry->d_inode; |
diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h index 56387711589b..a0974df82b31 100644 --- a/fs/udf/ecma_167.h +++ b/fs/udf/ecma_167.h | |||
@@ -70,19 +70,6 @@ typedef struct { | |||
70 | uint8_t microseconds; | 70 | uint8_t microseconds; |
71 | } __attribute__ ((packed)) timestamp; | 71 | } __attribute__ ((packed)) timestamp; |
72 | 72 | ||
73 | typedef struct { | ||
74 | uint16_t typeAndTimezone; | ||
75 | int16_t year; | ||
76 | uint8_t month; | ||
77 | uint8_t day; | ||
78 | uint8_t hour; | ||
79 | uint8_t minute; | ||
80 | uint8_t second; | ||
81 | uint8_t centiseconds; | ||
82 | uint8_t hundredsOfMicroseconds; | ||
83 | uint8_t microseconds; | ||
84 | } __attribute__ ((packed)) kernel_timestamp; | ||
85 | |||
86 | /* Type and Time Zone (ECMA 167r3 1/7.3.1) */ | 73 | /* Type and Time Zone (ECMA 167r3 1/7.3.1) */ |
87 | #define TIMESTAMP_TYPE_MASK 0xF000 | 74 | #define TIMESTAMP_TYPE_MASK 0xF000 |
88 | #define TIMESTAMP_TYPE_CUT 0x0000 | 75 | #define TIMESTAMP_TYPE_CUT 0x0000 |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 97c71ae7c689..0ed6e146a0d9 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include "udfdecl.h" | 28 | #include "udfdecl.h" |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/udf_fs.h> | ||
31 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/string.h> /* memset */ | 32 | #include <linux/string.h> /* memset */ |
@@ -144,40 +143,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
144 | return retval; | 143 | return retval; |
145 | } | 144 | } |
146 | 145 | ||
147 | /* | ||
148 | * udf_ioctl | ||
149 | * | ||
150 | * PURPOSE | ||
151 | * Issue an ioctl. | ||
152 | * | ||
153 | * DESCRIPTION | ||
154 | * Optional - sys_ioctl() will return -ENOTTY if this routine is not | ||
155 | * available, and the ioctl cannot be handled without filesystem help. | ||
156 | * | ||
157 | * sys_ioctl() handles these ioctls that apply only to regular files: | ||
158 | * FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD | ||
159 | * These ioctls are also handled by sys_ioctl(): | ||
160 | * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC | ||
161 | * All other ioctls are passed to the filesystem. | ||
162 | * | ||
163 | * Refer to sys_ioctl() in fs/ioctl.c | ||
164 | * sys_ioctl() -> . | ||
165 | * | ||
166 | * PRE-CONDITIONS | ||
167 | * inode Pointer to inode that ioctl was issued on. | ||
168 | * filp Pointer to file that ioctl was issued on. | ||
169 | * cmd The ioctl command. | ||
170 | * arg The ioctl argument [can be interpreted as a | ||
171 | * user-space pointer if desired]. | ||
172 | * | ||
173 | * POST-CONDITIONS | ||
174 | * <return> Success (>=0) or an error code (<=0) that | ||
175 | * sys_ioctl() will return. | ||
176 | * | ||
177 | * HISTORY | ||
178 | * July 1, 1997 - Andrew E. Mileski | ||
179 | * Written, tested, and released. | ||
180 | */ | ||
181 | int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 146 | int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
182 | unsigned long arg) | 147 | unsigned long arg) |
183 | { | 148 | { |
@@ -225,18 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
225 | return result; | 190 | return result; |
226 | } | 191 | } |
227 | 192 | ||
228 | /* | ||
229 | * udf_release_file | ||
230 | * | ||
231 | * PURPOSE | ||
232 | * Called when all references to the file are closed | ||
233 | * | ||
234 | * DESCRIPTION | ||
235 | * Discard prealloced blocks | ||
236 | * | ||
237 | * HISTORY | ||
238 | * | ||
239 | */ | ||
240 | static int udf_release_file(struct inode *inode, struct file *filp) | 193 | static int udf_release_file(struct inode *inode, struct file *filp) |
241 | { | 194 | { |
242 | if (filp->f_mode & FMODE_WRITE) { | 195 | if (filp->f_mode & FMODE_WRITE) { |
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 84360315aca2..eb9cfa23dc3d 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "udfdecl.h" | 21 | #include "udfdecl.h" |
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/quotaops.h> | 23 | #include <linux/quotaops.h> |
24 | #include <linux/udf_fs.h> | ||
25 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | 26 | ||
@@ -47,11 +46,9 @@ void udf_free_inode(struct inode *inode) | |||
47 | struct logicalVolIntegrityDescImpUse *lvidiu = | 46 | struct logicalVolIntegrityDescImpUse *lvidiu = |
48 | udf_sb_lvidiu(sbi); | 47 | udf_sb_lvidiu(sbi); |
49 | if (S_ISDIR(inode->i_mode)) | 48 | if (S_ISDIR(inode->i_mode)) |
50 | lvidiu->numDirs = | 49 | le32_add_cpu(&lvidiu->numDirs, -1); |
51 | cpu_to_le32(le32_to_cpu(lvidiu->numDirs) - 1); | ||
52 | else | 50 | else |
53 | lvidiu->numFiles = | 51 | le32_add_cpu(&lvidiu->numFiles, -1); |
54 | cpu_to_le32(le32_to_cpu(lvidiu->numFiles) - 1); | ||
55 | 52 | ||
56 | mark_buffer_dirty(sbi->s_lvid_bh); | 53 | mark_buffer_dirty(sbi->s_lvid_bh); |
57 | } | 54 | } |
@@ -105,11 +102,9 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) | |||
105 | lvhd = (struct logicalVolHeaderDesc *) | 102 | lvhd = (struct logicalVolHeaderDesc *) |
106 | (lvid->logicalVolContentsUse); | 103 | (lvid->logicalVolContentsUse); |
107 | if (S_ISDIR(mode)) | 104 | if (S_ISDIR(mode)) |
108 | lvidiu->numDirs = | 105 | le32_add_cpu(&lvidiu->numDirs, 1); |
109 | cpu_to_le32(le32_to_cpu(lvidiu->numDirs) + 1); | ||
110 | else | 106 | else |
111 | lvidiu->numFiles = | 107 | le32_add_cpu(&lvidiu->numFiles, 1); |
112 | cpu_to_le32(le32_to_cpu(lvidiu->numFiles) + 1); | ||
113 | iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID); | 108 | iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID); |
114 | if (!(++uniqueID & 0x00000000FFFFFFFFUL)) | 109 | if (!(++uniqueID & 0x00000000FFFFFFFFUL)) |
115 | uniqueID += 16; | 110 | uniqueID += 16; |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 24cfa55d0fdc..6e74b117aaf0 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
38 | #include <linux/writeback.h> | 38 | #include <linux/writeback.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/crc-itu-t.h> | ||
40 | 41 | ||
41 | #include "udf_i.h" | 42 | #include "udf_i.h" |
42 | #include "udf_sb.h" | 43 | #include "udf_sb.h" |
@@ -66,22 +67,7 @@ static void udf_update_extents(struct inode *, | |||
66 | struct extent_position *); | 67 | struct extent_position *); |
67 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); | 68 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); |
68 | 69 | ||
69 | /* | 70 | |
70 | * udf_delete_inode | ||
71 | * | ||
72 | * PURPOSE | ||
73 | * Clean-up before the specified inode is destroyed. | ||
74 | * | ||
75 | * DESCRIPTION | ||
76 | * This routine is called when the kernel destroys an inode structure | ||
77 | * ie. when iput() finds i_count == 0. | ||
78 | * | ||
79 | * HISTORY | ||
80 | * July 1, 1997 - Andrew E. Mileski | ||
81 | * Written, tested, and released. | ||
82 | * | ||
83 | * Called at the last iput() if i_nlink is zero. | ||
84 | */ | ||
85 | void udf_delete_inode(struct inode *inode) | 71 | void udf_delete_inode(struct inode *inode) |
86 | { | 72 | { |
87 | truncate_inode_pages(&inode->i_data, 0); | 73 | truncate_inode_pages(&inode->i_data, 0); |
@@ -323,9 +309,6 @@ static int udf_get_block(struct inode *inode, sector_t block, | |||
323 | 309 | ||
324 | lock_kernel(); | 310 | lock_kernel(); |
325 | 311 | ||
326 | if (block < 0) | ||
327 | goto abort_negative; | ||
328 | |||
329 | iinfo = UDF_I(inode); | 312 | iinfo = UDF_I(inode); |
330 | if (block == iinfo->i_next_alloc_block + 1) { | 313 | if (block == iinfo->i_next_alloc_block + 1) { |
331 | iinfo->i_next_alloc_block++; | 314 | iinfo->i_next_alloc_block++; |
@@ -347,10 +330,6 @@ static int udf_get_block(struct inode *inode, sector_t block, | |||
347 | abort: | 330 | abort: |
348 | unlock_kernel(); | 331 | unlock_kernel(); |
349 | return err; | 332 | return err; |
350 | |||
351 | abort_negative: | ||
352 | udf_warning(inode->i_sb, "udf_get_block", "block < 0"); | ||
353 | goto abort; | ||
354 | } | 333 | } |
355 | 334 | ||
356 | static struct buffer_head *udf_getblk(struct inode *inode, long block, | 335 | static struct buffer_head *udf_getblk(struct inode *inode, long block, |
@@ -1116,42 +1095,36 @@ static void __udf_read_inode(struct inode *inode) | |||
1116 | fe = (struct fileEntry *)bh->b_data; | 1095 | fe = (struct fileEntry *)bh->b_data; |
1117 | 1096 | ||
1118 | if (fe->icbTag.strategyType == cpu_to_le16(4096)) { | 1097 | if (fe->icbTag.strategyType == cpu_to_le16(4096)) { |
1119 | struct buffer_head *ibh = NULL, *nbh = NULL; | 1098 | struct buffer_head *ibh; |
1120 | struct indirectEntry *ie; | ||
1121 | 1099 | ||
1122 | ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1, | 1100 | ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1, |
1123 | &ident); | 1101 | &ident); |
1124 | if (ident == TAG_IDENT_IE) { | 1102 | if (ident == TAG_IDENT_IE && ibh) { |
1125 | if (ibh) { | 1103 | struct buffer_head *nbh = NULL; |
1126 | kernel_lb_addr loc; | 1104 | kernel_lb_addr loc; |
1127 | ie = (struct indirectEntry *)ibh->b_data; | 1105 | struct indirectEntry *ie; |
1128 | 1106 | ||
1129 | loc = lelb_to_cpu(ie->indirectICB.extLocation); | 1107 | ie = (struct indirectEntry *)ibh->b_data; |
1130 | 1108 | loc = lelb_to_cpu(ie->indirectICB.extLocation); | |
1131 | if (ie->indirectICB.extLength && | 1109 | |
1132 | (nbh = udf_read_ptagged(inode->i_sb, loc, 0, | 1110 | if (ie->indirectICB.extLength && |
1133 | &ident))) { | 1111 | (nbh = udf_read_ptagged(inode->i_sb, loc, 0, |
1134 | if (ident == TAG_IDENT_FE || | 1112 | &ident))) { |
1135 | ident == TAG_IDENT_EFE) { | 1113 | if (ident == TAG_IDENT_FE || |
1136 | memcpy(&iinfo->i_location, | 1114 | ident == TAG_IDENT_EFE) { |
1137 | &loc, | 1115 | memcpy(&iinfo->i_location, |
1138 | sizeof(kernel_lb_addr)); | 1116 | &loc, |
1139 | brelse(bh); | 1117 | sizeof(kernel_lb_addr)); |
1140 | brelse(ibh); | 1118 | brelse(bh); |
1141 | brelse(nbh); | ||
1142 | __udf_read_inode(inode); | ||
1143 | return; | ||
1144 | } else { | ||
1145 | brelse(nbh); | ||
1146 | brelse(ibh); | ||
1147 | } | ||
1148 | } else { | ||
1149 | brelse(ibh); | 1119 | brelse(ibh); |
1120 | brelse(nbh); | ||
1121 | __udf_read_inode(inode); | ||
1122 | return; | ||
1150 | } | 1123 | } |
1124 | brelse(nbh); | ||
1151 | } | 1125 | } |
1152 | } else { | ||
1153 | brelse(ibh); | ||
1154 | } | 1126 | } |
1127 | brelse(ibh); | ||
1155 | } else if (fe->icbTag.strategyType != cpu_to_le16(4)) { | 1128 | } else if (fe->icbTag.strategyType != cpu_to_le16(4)) { |
1156 | printk(KERN_ERR "udf: unsupported strategy type: %d\n", | 1129 | printk(KERN_ERR "udf: unsupported strategy type: %d\n", |
1157 | le16_to_cpu(fe->icbTag.strategyType)); | 1130 | le16_to_cpu(fe->icbTag.strategyType)); |
@@ -1168,8 +1141,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1168 | { | 1141 | { |
1169 | struct fileEntry *fe; | 1142 | struct fileEntry *fe; |
1170 | struct extendedFileEntry *efe; | 1143 | struct extendedFileEntry *efe; |
1171 | time_t convtime; | ||
1172 | long convtime_usec; | ||
1173 | int offset; | 1144 | int offset; |
1174 | struct udf_sb_info *sbi = UDF_SB(inode->i_sb); | 1145 | struct udf_sb_info *sbi = UDF_SB(inode->i_sb); |
1175 | struct udf_inode_info *iinfo = UDF_I(inode); | 1146 | struct udf_inode_info *iinfo = UDF_I(inode); |
@@ -1257,29 +1228,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1257 | inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << | 1228 | inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << |
1258 | (inode->i_sb->s_blocksize_bits - 9); | 1229 | (inode->i_sb->s_blocksize_bits - 9); |
1259 | 1230 | ||
1260 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1231 | if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime)) |
1261 | lets_to_cpu(fe->accessTime))) { | ||
1262 | inode->i_atime.tv_sec = convtime; | ||
1263 | inode->i_atime.tv_nsec = convtime_usec * 1000; | ||
1264 | } else { | ||
1265 | inode->i_atime = sbi->s_record_time; | 1232 | inode->i_atime = sbi->s_record_time; |
1266 | } | ||
1267 | 1233 | ||
1268 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1234 | if (!udf_disk_stamp_to_time(&inode->i_mtime, |
1269 | lets_to_cpu(fe->modificationTime))) { | 1235 | fe->modificationTime)) |
1270 | inode->i_mtime.tv_sec = convtime; | ||
1271 | inode->i_mtime.tv_nsec = convtime_usec * 1000; | ||
1272 | } else { | ||
1273 | inode->i_mtime = sbi->s_record_time; | 1236 | inode->i_mtime = sbi->s_record_time; |
1274 | } | ||
1275 | 1237 | ||
1276 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1238 | if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime)) |
1277 | lets_to_cpu(fe->attrTime))) { | ||
1278 | inode->i_ctime.tv_sec = convtime; | ||
1279 | inode->i_ctime.tv_nsec = convtime_usec * 1000; | ||
1280 | } else { | ||
1281 | inode->i_ctime = sbi->s_record_time; | 1239 | inode->i_ctime = sbi->s_record_time; |
1282 | } | ||
1283 | 1240 | ||
1284 | iinfo->i_unique = le64_to_cpu(fe->uniqueID); | 1241 | iinfo->i_unique = le64_to_cpu(fe->uniqueID); |
1285 | iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); | 1242 | iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); |
@@ -1289,37 +1246,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1289 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << | 1246 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << |
1290 | (inode->i_sb->s_blocksize_bits - 9); | 1247 | (inode->i_sb->s_blocksize_bits - 9); |
1291 | 1248 | ||
1292 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1249 | if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime)) |
1293 | lets_to_cpu(efe->accessTime))) { | ||
1294 | inode->i_atime.tv_sec = convtime; | ||
1295 | inode->i_atime.tv_nsec = convtime_usec * 1000; | ||
1296 | } else { | ||
1297 | inode->i_atime = sbi->s_record_time; | 1250 | inode->i_atime = sbi->s_record_time; |
1298 | } | ||
1299 | 1251 | ||
1300 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1252 | if (!udf_disk_stamp_to_time(&inode->i_mtime, |
1301 | lets_to_cpu(efe->modificationTime))) { | 1253 | efe->modificationTime)) |
1302 | inode->i_mtime.tv_sec = convtime; | ||
1303 | inode->i_mtime.tv_nsec = convtime_usec * 1000; | ||
1304 | } else { | ||
1305 | inode->i_mtime = sbi->s_record_time; | 1254 | inode->i_mtime = sbi->s_record_time; |
1306 | } | ||
1307 | 1255 | ||
1308 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1256 | if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime)) |
1309 | lets_to_cpu(efe->createTime))) { | ||
1310 | iinfo->i_crtime.tv_sec = convtime; | ||
1311 | iinfo->i_crtime.tv_nsec = convtime_usec * 1000; | ||
1312 | } else { | ||
1313 | iinfo->i_crtime = sbi->s_record_time; | 1257 | iinfo->i_crtime = sbi->s_record_time; |
1314 | } | ||
1315 | 1258 | ||
1316 | if (udf_stamp_to_time(&convtime, &convtime_usec, | 1259 | if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime)) |
1317 | lets_to_cpu(efe->attrTime))) { | ||
1318 | inode->i_ctime.tv_sec = convtime; | ||
1319 | inode->i_ctime.tv_nsec = convtime_usec * 1000; | ||
1320 | } else { | ||
1321 | inode->i_ctime = sbi->s_record_time; | 1260 | inode->i_ctime = sbi->s_record_time; |
1322 | } | ||
1323 | 1261 | ||
1324 | iinfo->i_unique = le64_to_cpu(efe->uniqueID); | 1262 | iinfo->i_unique = le64_to_cpu(efe->uniqueID); |
1325 | iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); | 1263 | iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); |
@@ -1338,6 +1276,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1338 | case ICBTAG_FILE_TYPE_REALTIME: | 1276 | case ICBTAG_FILE_TYPE_REALTIME: |
1339 | case ICBTAG_FILE_TYPE_REGULAR: | 1277 | case ICBTAG_FILE_TYPE_REGULAR: |
1340 | case ICBTAG_FILE_TYPE_UNDEF: | 1278 | case ICBTAG_FILE_TYPE_UNDEF: |
1279 | case ICBTAG_FILE_TYPE_VAT20: | ||
1341 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 1280 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
1342 | inode->i_data.a_ops = &udf_adinicb_aops; | 1281 | inode->i_data.a_ops = &udf_adinicb_aops; |
1343 | else | 1282 | else |
@@ -1363,6 +1302,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1363 | inode->i_op = &page_symlink_inode_operations; | 1302 | inode->i_op = &page_symlink_inode_operations; |
1364 | inode->i_mode = S_IFLNK | S_IRWXUGO; | 1303 | inode->i_mode = S_IFLNK | S_IRWXUGO; |
1365 | break; | 1304 | break; |
1305 | case ICBTAG_FILE_TYPE_MAIN: | ||
1306 | udf_debug("METADATA FILE-----\n"); | ||
1307 | break; | ||
1308 | case ICBTAG_FILE_TYPE_MIRROR: | ||
1309 | udf_debug("METADATA MIRROR FILE-----\n"); | ||
1310 | break; | ||
1311 | case ICBTAG_FILE_TYPE_BITMAP: | ||
1312 | udf_debug("METADATA BITMAP FILE-----\n"); | ||
1313 | break; | ||
1366 | default: | 1314 | default: |
1367 | printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown " | 1315 | printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown " |
1368 | "file type=%d\n", inode->i_ino, | 1316 | "file type=%d\n", inode->i_ino, |
@@ -1416,21 +1364,6 @@ static mode_t udf_convert_permissions(struct fileEntry *fe) | |||
1416 | return mode; | 1364 | return mode; |
1417 | } | 1365 | } |
1418 | 1366 | ||
1419 | /* | ||
1420 | * udf_write_inode | ||
1421 | * | ||
1422 | * PURPOSE | ||
1423 | * Write out the specified inode. | ||
1424 | * | ||
1425 | * DESCRIPTION | ||
1426 | * This routine is called whenever an inode is synced. | ||
1427 | * Currently this routine is just a placeholder. | ||
1428 | * | ||
1429 | * HISTORY | ||
1430 | * July 1, 1997 - Andrew E. Mileski | ||
1431 | * Written, tested, and released. | ||
1432 | */ | ||
1433 | |||
1434 | int udf_write_inode(struct inode *inode, int sync) | 1367 | int udf_write_inode(struct inode *inode, int sync) |
1435 | { | 1368 | { |
1436 | int ret; | 1369 | int ret; |
@@ -1455,7 +1388,6 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1455 | uint32_t udfperms; | 1388 | uint32_t udfperms; |
1456 | uint16_t icbflags; | 1389 | uint16_t icbflags; |
1457 | uint16_t crclen; | 1390 | uint16_t crclen; |
1458 | kernel_timestamp cpu_time; | ||
1459 | int err = 0; | 1391 | int err = 0; |
1460 | struct udf_sb_info *sbi = UDF_SB(inode->i_sb); | 1392 | struct udf_sb_info *sbi = UDF_SB(inode->i_sb); |
1461 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 1393 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
@@ -1488,9 +1420,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1488 | iinfo->i_location. | 1420 | iinfo->i_location. |
1489 | logicalBlockNum); | 1421 | logicalBlockNum); |
1490 | use->descTag.descCRCLength = cpu_to_le16(crclen); | 1422 | use->descTag.descCRCLength = cpu_to_le16(crclen); |
1491 | use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + | 1423 | use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + |
1492 | sizeof(tag), crclen, | 1424 | sizeof(tag), |
1493 | 0)); | 1425 | crclen)); |
1494 | use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); | 1426 | use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); |
1495 | 1427 | ||
1496 | mark_buffer_dirty(bh); | 1428 | mark_buffer_dirty(bh); |
@@ -1558,12 +1490,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1558 | (inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> | 1490 | (inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >> |
1559 | (blocksize_bits - 9)); | 1491 | (blocksize_bits - 9)); |
1560 | 1492 | ||
1561 | if (udf_time_to_stamp(&cpu_time, inode->i_atime)) | 1493 | udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime); |
1562 | fe->accessTime = cpu_to_lets(cpu_time); | 1494 | udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); |
1563 | if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) | 1495 | udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime); |
1564 | fe->modificationTime = cpu_to_lets(cpu_time); | ||
1565 | if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) | ||
1566 | fe->attrTime = cpu_to_lets(cpu_time); | ||
1567 | memset(&(fe->impIdent), 0, sizeof(regid)); | 1496 | memset(&(fe->impIdent), 0, sizeof(regid)); |
1568 | strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); | 1497 | strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); |
1569 | fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1498 | fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
@@ -1598,14 +1527,10 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1598 | iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec)) | 1527 | iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec)) |
1599 | iinfo->i_crtime = inode->i_ctime; | 1528 | iinfo->i_crtime = inode->i_ctime; |
1600 | 1529 | ||
1601 | if (udf_time_to_stamp(&cpu_time, inode->i_atime)) | 1530 | udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime); |
1602 | efe->accessTime = cpu_to_lets(cpu_time); | 1531 | udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime); |
1603 | if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) | 1532 | udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime); |
1604 | efe->modificationTime = cpu_to_lets(cpu_time); | 1533 | udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime); |
1605 | if (udf_time_to_stamp(&cpu_time, iinfo->i_crtime)) | ||
1606 | efe->createTime = cpu_to_lets(cpu_time); | ||
1607 | if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) | ||
1608 | efe->attrTime = cpu_to_lets(cpu_time); | ||
1609 | 1534 | ||
1610 | memset(&(efe->impIdent), 0, sizeof(regid)); | 1535 | memset(&(efe->impIdent), 0, sizeof(regid)); |
1611 | strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); | 1536 | strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); |
@@ -1660,8 +1585,8 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1660 | crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - | 1585 | crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - |
1661 | sizeof(tag); | 1586 | sizeof(tag); |
1662 | fe->descTag.descCRCLength = cpu_to_le16(crclen); | 1587 | fe->descTag.descCRCLength = cpu_to_le16(crclen); |
1663 | fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag), | 1588 | fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag), |
1664 | crclen, 0)); | 1589 | crclen)); |
1665 | fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); | 1590 | fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); |
1666 | 1591 | ||
1667 | /* write the data blocks */ | 1592 | /* write the data blocks */ |
@@ -1778,9 +1703,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1778 | 1703 | ||
1779 | if (epos->bh) { | 1704 | if (epos->bh) { |
1780 | aed = (struct allocExtDesc *)epos->bh->b_data; | 1705 | aed = (struct allocExtDesc *)epos->bh->b_data; |
1781 | aed->lengthAllocDescs = | 1706 | le32_add_cpu(&aed->lengthAllocDescs, adsize); |
1782 | cpu_to_le32(le32_to_cpu( | ||
1783 | aed->lengthAllocDescs) + adsize); | ||
1784 | } else { | 1707 | } else { |
1785 | iinfo->i_lenAlloc += adsize; | 1708 | iinfo->i_lenAlloc += adsize; |
1786 | mark_inode_dirty(inode); | 1709 | mark_inode_dirty(inode); |
@@ -1830,9 +1753,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1830 | mark_inode_dirty(inode); | 1753 | mark_inode_dirty(inode); |
1831 | } else { | 1754 | } else { |
1832 | aed = (struct allocExtDesc *)epos->bh->b_data; | 1755 | aed = (struct allocExtDesc *)epos->bh->b_data; |
1833 | aed->lengthAllocDescs = | 1756 | le32_add_cpu(&aed->lengthAllocDescs, adsize); |
1834 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + | ||
1835 | adsize); | ||
1836 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || | 1757 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || |
1837 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) | 1758 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) |
1838 | udf_update_tag(epos->bh->b_data, | 1759 | udf_update_tag(epos->bh->b_data, |
@@ -2046,9 +1967,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
2046 | mark_inode_dirty(inode); | 1967 | mark_inode_dirty(inode); |
2047 | } else { | 1968 | } else { |
2048 | aed = (struct allocExtDesc *)oepos.bh->b_data; | 1969 | aed = (struct allocExtDesc *)oepos.bh->b_data; |
2049 | aed->lengthAllocDescs = | 1970 | le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize)); |
2050 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - | ||
2051 | (2 * adsize)); | ||
2052 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || | 1971 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || |
2053 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) | 1972 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) |
2054 | udf_update_tag(oepos.bh->b_data, | 1973 | udf_update_tag(oepos.bh->b_data, |
@@ -2065,9 +1984,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
2065 | mark_inode_dirty(inode); | 1984 | mark_inode_dirty(inode); |
2066 | } else { | 1985 | } else { |
2067 | aed = (struct allocExtDesc *)oepos.bh->b_data; | 1986 | aed = (struct allocExtDesc *)oepos.bh->b_data; |
2068 | aed->lengthAllocDescs = | 1987 | le32_add_cpu(&aed->lengthAllocDescs, -adsize); |
2069 | cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - | ||
2070 | adsize); | ||
2071 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || | 1988 | if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || |
2072 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) | 1989 | UDF_SB(inode->i_sb)->s_udfrev >= 0x0201) |
2073 | udf_update_tag(oepos.bh->b_data, | 1990 | udf_update_tag(oepos.bh->b_data, |
@@ -2095,11 +2012,6 @@ int8_t inode_bmap(struct inode *inode, sector_t block, | |||
2095 | int8_t etype; | 2012 | int8_t etype; |
2096 | struct udf_inode_info *iinfo; | 2013 | struct udf_inode_info *iinfo; |
2097 | 2014 | ||
2098 | if (block < 0) { | ||
2099 | printk(KERN_ERR "udf: inode_bmap: block < 0\n"); | ||
2100 | return -1; | ||
2101 | } | ||
2102 | |||
2103 | iinfo = UDF_I(inode); | 2015 | iinfo = UDF_I(inode); |
2104 | pos->offset = 0; | 2016 | pos->offset = 0; |
2105 | pos->block = iinfo->i_location; | 2017 | pos->block = iinfo->i_location; |
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c index 579bae71e67e..703843f30ffd 100644 --- a/fs/udf/lowlevel.c +++ b/fs/udf/lowlevel.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/cdrom.h> | 23 | #include <linux/cdrom.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | 25 | ||
26 | #include <linux/udf_fs.h> | ||
27 | #include "udf_sb.h" | 26 | #include "udf_sb.h" |
28 | 27 | ||
29 | unsigned int udf_get_last_session(struct super_block *sb) | 28 | unsigned int udf_get_last_session(struct super_block *sb) |
diff --git a/fs/udf/misc.c b/fs/udf/misc.c index a1d6da0caf71..84bf0fd4a4f1 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c | |||
@@ -23,8 +23,8 @@ | |||
23 | 23 | ||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/udf_fs.h> | ||
27 | #include <linux/buffer_head.h> | 26 | #include <linux/buffer_head.h> |
27 | #include <linux/crc-itu-t.h> | ||
28 | 28 | ||
29 | #include "udf_i.h" | 29 | #include "udf_i.h" |
30 | #include "udf_sb.h" | 30 | #include "udf_sb.h" |
@@ -136,8 +136,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, | |||
136 | /* rewrite CRC + checksum of eahd */ | 136 | /* rewrite CRC + checksum of eahd */ |
137 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); | 137 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); |
138 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); | 138 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); |
139 | eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd + | 139 | eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd + |
140 | sizeof(tag), crclen, 0)); | 140 | sizeof(tag), crclen)); |
141 | eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); | 141 | eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); |
142 | iinfo->i_lenEAttr += size; | 142 | iinfo->i_lenEAttr += size; |
143 | return (struct genericFormat *)&ea[offset]; | 143 | return (struct genericFormat *)&ea[offset]; |
@@ -204,16 +204,15 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
204 | { | 204 | { |
205 | tag *tag_p; | 205 | tag *tag_p; |
206 | struct buffer_head *bh = NULL; | 206 | struct buffer_head *bh = NULL; |
207 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
208 | 207 | ||
209 | /* Read the block */ | 208 | /* Read the block */ |
210 | if (block == 0xFFFFFFFF) | 209 | if (block == 0xFFFFFFFF) |
211 | return NULL; | 210 | return NULL; |
212 | 211 | ||
213 | bh = udf_tread(sb, block + sbi->s_session); | 212 | bh = udf_tread(sb, block); |
214 | if (!bh) { | 213 | if (!bh) { |
215 | udf_debug("block=%d, location=%d: read failed\n", | 214 | udf_debug("block=%d, location=%d: read failed\n", |
216 | block + sbi->s_session, location); | 215 | block, location); |
217 | return NULL; | 216 | return NULL; |
218 | } | 217 | } |
219 | 218 | ||
@@ -223,8 +222,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
223 | 222 | ||
224 | if (location != le32_to_cpu(tag_p->tagLocation)) { | 223 | if (location != le32_to_cpu(tag_p->tagLocation)) { |
225 | udf_debug("location mismatch block %u, tag %u != %u\n", | 224 | udf_debug("location mismatch block %u, tag %u != %u\n", |
226 | block + sbi->s_session, | 225 | block, le32_to_cpu(tag_p->tagLocation), location); |
227 | le32_to_cpu(tag_p->tagLocation), location); | ||
228 | goto error_out; | 226 | goto error_out; |
229 | } | 227 | } |
230 | 228 | ||
@@ -244,13 +242,13 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
244 | 242 | ||
245 | /* Verify the descriptor CRC */ | 243 | /* Verify the descriptor CRC */ |
246 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || | 244 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || |
247 | le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag), | 245 | le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, |
248 | le16_to_cpu(tag_p->descCRCLength), 0)) | 246 | bh->b_data + sizeof(tag), |
247 | le16_to_cpu(tag_p->descCRCLength))) | ||
249 | return bh; | 248 | return bh; |
250 | 249 | ||
251 | udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", | 250 | udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block, |
252 | block + sbi->s_session, le16_to_cpu(tag_p->descCRC), | 251 | le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength)); |
253 | le16_to_cpu(tag_p->descCRCLength)); | ||
254 | 252 | ||
255 | error_out: | 253 | error_out: |
256 | brelse(bh); | 254 | brelse(bh); |
@@ -270,7 +268,7 @@ void udf_update_tag(char *data, int length) | |||
270 | length -= sizeof(tag); | 268 | length -= sizeof(tag); |
271 | 269 | ||
272 | tptr->descCRCLength = cpu_to_le16(length); | 270 | tptr->descCRCLength = cpu_to_le16(length); |
273 | tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0)); | 271 | tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length)); |
274 | tptr->tagChecksum = udf_tag_checksum(tptr); | 272 | tptr->tagChecksum = udf_tag_checksum(tptr); |
275 | } | 273 | } |
276 | 274 | ||
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 112a5fb0b27b..ba5537d4bc15 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/smp_lock.h> | 31 | #include <linux/smp_lock.h> |
32 | #include <linux/buffer_head.h> | 32 | #include <linux/buffer_head.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/crc-itu-t.h> | ||
34 | 35 | ||
35 | static inline int udf_match(int len1, const char *name1, int len2, | 36 | static inline int udf_match(int len1, const char *name1, int len2, |
36 | const char *name2) | 37 | const char *name2) |
@@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, | |||
97 | memset(fibh->ebh->b_data, 0x00, padlen + offset); | 98 | memset(fibh->ebh->b_data, 0x00, padlen + offset); |
98 | } | 99 | } |
99 | 100 | ||
100 | crc = udf_crc((uint8_t *)cfi + sizeof(tag), | 101 | crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag), |
101 | sizeof(struct fileIdentDesc) - sizeof(tag), 0); | 102 | sizeof(struct fileIdentDesc) - sizeof(tag)); |
102 | 103 | ||
103 | if (fibh->sbh == fibh->ebh) { | 104 | if (fibh->sbh == fibh->ebh) { |
104 | crc = udf_crc((uint8_t *)sfi->impUse, | 105 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, |
105 | crclen + sizeof(tag) - | 106 | crclen + sizeof(tag) - |
106 | sizeof(struct fileIdentDesc), crc); | 107 | sizeof(struct fileIdentDesc)); |
107 | } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { | 108 | } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { |
108 | crc = udf_crc(fibh->ebh->b_data + | 109 | crc = crc_itu_t(crc, fibh->ebh->b_data + |
109 | sizeof(struct fileIdentDesc) + | 110 | sizeof(struct fileIdentDesc) + |
110 | fibh->soffset, | 111 | fibh->soffset, |
111 | crclen + sizeof(tag) - | 112 | crclen + sizeof(tag) - |
112 | sizeof(struct fileIdentDesc), | 113 | sizeof(struct fileIdentDesc)); |
113 | crc); | ||
114 | } else { | 114 | } else { |
115 | crc = udf_crc((uint8_t *)sfi->impUse, | 115 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, |
116 | -fibh->soffset - sizeof(struct fileIdentDesc), | 116 | -fibh->soffset - sizeof(struct fileIdentDesc)); |
117 | crc); | 117 | crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset); |
118 | crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc); | ||
119 | } | 118 | } |
120 | 119 | ||
121 | cfi->descTag.descCRC = cpu_to_le16(crc); | 120 | cfi->descTag.descCRC = cpu_to_le16(crc); |
@@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
149 | struct fileIdentDesc *fi = NULL; | 148 | struct fileIdentDesc *fi = NULL; |
150 | loff_t f_pos; | 149 | loff_t f_pos; |
151 | int block, flen; | 150 | int block, flen; |
152 | char fname[UDF_NAME_LEN]; | 151 | char *fname = NULL; |
153 | char *nameptr; | 152 | char *nameptr; |
154 | uint8_t lfi; | 153 | uint8_t lfi; |
155 | uint16_t liu; | 154 | uint16_t liu; |
@@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
163 | size = udf_ext0_offset(dir) + dir->i_size; | 162 | size = udf_ext0_offset(dir) + dir->i_size; |
164 | f_pos = udf_ext0_offset(dir); | 163 | f_pos = udf_ext0_offset(dir); |
165 | 164 | ||
165 | fibh->sbh = fibh->ebh = NULL; | ||
166 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); | 166 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); |
167 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 167 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
168 | fibh->sbh = fibh->ebh = NULL; | 168 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, |
169 | else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, | 169 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) |
170 | &epos, &eloc, &elen, &offset) == | 170 | goto out_err; |
171 | (EXT_RECORDED_ALLOCATED >> 30)) { | ||
172 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 171 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); |
173 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 172 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
174 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 173 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
@@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
179 | offset = 0; | 178 | offset = 0; |
180 | 179 | ||
181 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); | 180 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); |
182 | if (!fibh->sbh) { | 181 | if (!fibh->sbh) |
183 | brelse(epos.bh); | 182 | goto out_err; |
184 | return NULL; | ||
185 | } | ||
186 | } else { | ||
187 | brelse(epos.bh); | ||
188 | return NULL; | ||
189 | } | 183 | } |
190 | 184 | ||
185 | fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); | ||
186 | if (!fname) | ||
187 | goto out_err; | ||
188 | |||
191 | while (f_pos < size) { | 189 | while (f_pos < size) { |
192 | fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, | 190 | fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, |
193 | &elen, &offset); | 191 | &elen, &offset); |
194 | if (!fi) { | 192 | if (!fi) |
195 | if (fibh->sbh != fibh->ebh) | 193 | goto out_err; |
196 | brelse(fibh->ebh); | ||
197 | brelse(fibh->sbh); | ||
198 | brelse(epos.bh); | ||
199 | return NULL; | ||
200 | } | ||
201 | 194 | ||
202 | liu = le16_to_cpu(cfi->lengthOfImpUse); | 195 | liu = le16_to_cpu(cfi->lengthOfImpUse); |
203 | lfi = cfi->lengthFileIdent; | 196 | lfi = cfi->lengthFileIdent; |
@@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
237 | 230 | ||
238 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 231 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); |
239 | if (flen && udf_match(flen, fname, dentry->d_name.len, | 232 | if (flen && udf_match(flen, fname, dentry->d_name.len, |
240 | dentry->d_name.name)) { | 233 | dentry->d_name.name)) |
241 | brelse(epos.bh); | 234 | goto out_ok; |
242 | return fi; | ||
243 | } | ||
244 | } | 235 | } |
245 | 236 | ||
237 | out_err: | ||
238 | fi = NULL; | ||
246 | if (fibh->sbh != fibh->ebh) | 239 | if (fibh->sbh != fibh->ebh) |
247 | brelse(fibh->ebh); | 240 | brelse(fibh->ebh); |
248 | brelse(fibh->sbh); | 241 | brelse(fibh->sbh); |
242 | out_ok: | ||
249 | brelse(epos.bh); | 243 | brelse(epos.bh); |
244 | kfree(fname); | ||
250 | 245 | ||
251 | return NULL; | 246 | return fi; |
252 | } | 247 | } |
253 | 248 | ||
254 | /* | ||
255 | * udf_lookup | ||
256 | * | ||
257 | * PURPOSE | ||
258 | * Look-up the inode for a given name. | ||
259 | * | ||
260 | * DESCRIPTION | ||
261 | * Required - lookup_dentry() will return -ENOTDIR if this routine is not | ||
262 | * available for a directory. The filesystem is useless if this routine is | ||
263 | * not available for at least the filesystem's root directory. | ||
264 | * | ||
265 | * This routine is passed an incomplete dentry - it must be completed by | ||
266 | * calling d_add(dentry, inode). If the name does not exist, then the | ||
267 | * specified inode must be set to null. An error should only be returned | ||
268 | * when the lookup fails for a reason other than the name not existing. | ||
269 | * Note that the directory inode semaphore is held during the call. | ||
270 | * | ||
271 | * Refer to lookup_dentry() in fs/namei.c | ||
272 | * lookup_dentry() -> lookup() -> real_lookup() -> . | ||
273 | * | ||
274 | * PRE-CONDITIONS | ||
275 | * dir Pointer to inode of parent directory. | ||
276 | * dentry Pointer to dentry to complete. | ||
277 | * nd Pointer to lookup nameidata | ||
278 | * | ||
279 | * POST-CONDITIONS | ||
280 | * <return> Zero on success. | ||
281 | * | ||
282 | * HISTORY | ||
283 | * July 1, 1997 - Andrew E. Mileski | ||
284 | * Written, tested, and released. | ||
285 | */ | ||
286 | |||
287 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | 249 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, |
288 | struct nameidata *nd) | 250 | struct nameidata *nd) |
289 | { | 251 | { |
@@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
336 | { | 298 | { |
337 | struct super_block *sb = dir->i_sb; | 299 | struct super_block *sb = dir->i_sb; |
338 | struct fileIdentDesc *fi = NULL; | 300 | struct fileIdentDesc *fi = NULL; |
339 | char name[UDF_NAME_LEN], fname[UDF_NAME_LEN]; | 301 | char *name = NULL; |
340 | int namelen; | 302 | int namelen; |
341 | loff_t f_pos; | 303 | loff_t f_pos; |
342 | int flen; | ||
343 | char *nameptr; | ||
344 | loff_t size = udf_ext0_offset(dir) + dir->i_size; | 304 | loff_t size = udf_ext0_offset(dir) + dir->i_size; |
345 | int nfidlen; | 305 | int nfidlen; |
346 | uint8_t lfi; | 306 | uint8_t lfi; |
@@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
352 | struct extent_position epos = {}; | 312 | struct extent_position epos = {}; |
353 | struct udf_inode_info *dinfo; | 313 | struct udf_inode_info *dinfo; |
354 | 314 | ||
315 | fibh->sbh = fibh->ebh = NULL; | ||
316 | name = kmalloc(UDF_NAME_LEN, GFP_NOFS); | ||
317 | if (!name) { | ||
318 | *err = -ENOMEM; | ||
319 | goto out_err; | ||
320 | } | ||
321 | |||
355 | if (dentry) { | 322 | if (dentry) { |
356 | if (!dentry->d_name.len) { | 323 | if (!dentry->d_name.len) { |
357 | *err = -EINVAL; | 324 | *err = -EINVAL; |
358 | return NULL; | 325 | goto out_err; |
359 | } | 326 | } |
360 | namelen = udf_put_filename(sb, dentry->d_name.name, name, | 327 | namelen = udf_put_filename(sb, dentry->d_name.name, name, |
361 | dentry->d_name.len); | 328 | dentry->d_name.len); |
362 | if (!namelen) { | 329 | if (!namelen) { |
363 | *err = -ENAMETOOLONG; | 330 | *err = -ENAMETOOLONG; |
364 | return NULL; | 331 | goto out_err; |
365 | } | 332 | } |
366 | } else { | 333 | } else { |
367 | namelen = 0; | 334 | namelen = 0; |
@@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
373 | 340 | ||
374 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); | 341 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); |
375 | dinfo = UDF_I(dir); | 342 | dinfo = UDF_I(dir); |
376 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 343 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
377 | fibh->sbh = fibh->ebh = NULL; | 344 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, |
378 | else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, | 345 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) { |
379 | &epos, &eloc, &elen, &offset) == | 346 | block = udf_get_lb_pblock(dir->i_sb, |
380 | (EXT_RECORDED_ALLOCATED >> 30)) { | 347 | dinfo->i_location, 0); |
348 | fibh->soffset = fibh->eoffset = sb->s_blocksize; | ||
349 | goto add; | ||
350 | } | ||
381 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 351 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); |
382 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 352 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
383 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 353 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
@@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
389 | 359 | ||
390 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); | 360 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); |
391 | if (!fibh->sbh) { | 361 | if (!fibh->sbh) { |
392 | brelse(epos.bh); | ||
393 | *err = -EIO; | 362 | *err = -EIO; |
394 | return NULL; | 363 | goto out_err; |
395 | } | 364 | } |
396 | 365 | ||
397 | block = dinfo->i_location.logicalBlockNum; | 366 | block = dinfo->i_location.logicalBlockNum; |
398 | } else { | ||
399 | block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0); | ||
400 | fibh->sbh = fibh->ebh = NULL; | ||
401 | fibh->soffset = fibh->eoffset = sb->s_blocksize; | ||
402 | goto add; | ||
403 | } | 367 | } |
404 | 368 | ||
405 | while (f_pos < size) { | 369 | while (f_pos < size) { |
@@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
407 | &elen, &offset); | 371 | &elen, &offset); |
408 | 372 | ||
409 | if (!fi) { | 373 | if (!fi) { |
410 | if (fibh->sbh != fibh->ebh) | ||
411 | brelse(fibh->ebh); | ||
412 | brelse(fibh->sbh); | ||
413 | brelse(epos.bh); | ||
414 | *err = -EIO; | 374 | *err = -EIO; |
415 | return NULL; | 375 | goto out_err; |
416 | } | 376 | } |
417 | 377 | ||
418 | liu = le16_to_cpu(cfi->lengthOfImpUse); | 378 | liu = le16_to_cpu(cfi->lengthOfImpUse); |
419 | lfi = cfi->lengthFileIdent; | 379 | lfi = cfi->lengthFileIdent; |
420 | 380 | ||
421 | if (fibh->sbh == fibh->ebh) | ||
422 | nameptr = fi->fileIdent + liu; | ||
423 | else { | ||
424 | int poffset; /* Unpaded ending offset */ | ||
425 | |||
426 | poffset = fibh->soffset + sizeof(struct fileIdentDesc) + | ||
427 | liu + lfi; | ||
428 | |||
429 | if (poffset >= lfi) | ||
430 | nameptr = (char *)(fibh->ebh->b_data + | ||
431 | poffset - lfi); | ||
432 | else { | ||
433 | nameptr = fname; | ||
434 | memcpy(nameptr, fi->fileIdent + liu, | ||
435 | lfi - poffset); | ||
436 | memcpy(nameptr + lfi - poffset, | ||
437 | fibh->ebh->b_data, poffset); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { | 381 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { |
442 | if (((sizeof(struct fileIdentDesc) + | 382 | if (((sizeof(struct fileIdentDesc) + |
443 | liu + lfi + 3) & ~3) == nfidlen) { | 383 | liu + lfi + 3) & ~3) == nfidlen) { |
444 | brelse(epos.bh); | ||
445 | cfi->descTag.tagSerialNum = cpu_to_le16(1); | 384 | cfi->descTag.tagSerialNum = cpu_to_le16(1); |
446 | cfi->fileVersionNum = cpu_to_le16(1); | 385 | cfi->fileVersionNum = cpu_to_le16(1); |
447 | cfi->fileCharacteristics = 0; | 386 | cfi->fileCharacteristics = 0; |
@@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
449 | cfi->lengthOfImpUse = cpu_to_le16(0); | 388 | cfi->lengthOfImpUse = cpu_to_le16(0); |
450 | if (!udf_write_fi(dir, cfi, fi, fibh, NULL, | 389 | if (!udf_write_fi(dir, cfi, fi, fibh, NULL, |
451 | name)) | 390 | name)) |
452 | return fi; | 391 | goto out_ok; |
453 | else { | 392 | else { |
454 | *err = -EIO; | 393 | *err = -EIO; |
455 | return NULL; | 394 | goto out_err; |
456 | } | 395 | } |
457 | } | 396 | } |
458 | } | 397 | } |
459 | |||
460 | if (!lfi || !dentry) | ||
461 | continue; | ||
462 | |||
463 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | ||
464 | if (flen && udf_match(flen, fname, dentry->d_name.len, | ||
465 | dentry->d_name.name)) { | ||
466 | if (fibh->sbh != fibh->ebh) | ||
467 | brelse(fibh->ebh); | ||
468 | brelse(fibh->sbh); | ||
469 | brelse(epos.bh); | ||
470 | *err = -EEXIST; | ||
471 | return NULL; | ||
472 | } | ||
473 | } | 398 | } |
474 | 399 | ||
475 | add: | 400 | add: |
@@ -496,7 +421,7 @@ add: | |||
496 | fibh->sbh = fibh->ebh = | 421 | fibh->sbh = fibh->ebh = |
497 | udf_expand_dir_adinicb(dir, &block, err); | 422 | udf_expand_dir_adinicb(dir, &block, err); |
498 | if (!fibh->sbh) | 423 | if (!fibh->sbh) |
499 | return NULL; | 424 | goto out_err; |
500 | epos.block = dinfo->i_location; | 425 | epos.block = dinfo->i_location; |
501 | epos.offset = udf_file_entry_alloc_offset(dir); | 426 | epos.offset = udf_file_entry_alloc_offset(dir); |
502 | /* Load extent udf_expand_dir_adinicb() has created */ | 427 | /* Load extent udf_expand_dir_adinicb() has created */ |
@@ -537,11 +462,8 @@ add: | |||
537 | dir->i_sb->s_blocksize_bits); | 462 | dir->i_sb->s_blocksize_bits); |
538 | fibh->ebh = udf_bread(dir, | 463 | fibh->ebh = udf_bread(dir, |
539 | f_pos >> dir->i_sb->s_blocksize_bits, 1, err); | 464 | f_pos >> dir->i_sb->s_blocksize_bits, 1, err); |
540 | if (!fibh->ebh) { | 465 | if (!fibh->ebh) |
541 | brelse(epos.bh); | 466 | goto out_err; |
542 | brelse(fibh->sbh); | ||
543 | return NULL; | ||
544 | } | ||
545 | 467 | ||
546 | if (!fibh->soffset) { | 468 | if (!fibh->soffset) { |
547 | if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == | 469 | if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == |
@@ -572,20 +494,25 @@ add: | |||
572 | cfi->lengthFileIdent = namelen; | 494 | cfi->lengthFileIdent = namelen; |
573 | cfi->lengthOfImpUse = cpu_to_le16(0); | 495 | cfi->lengthOfImpUse = cpu_to_le16(0); |
574 | if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { | 496 | if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { |
575 | brelse(epos.bh); | ||
576 | dir->i_size += nfidlen; | 497 | dir->i_size += nfidlen; |
577 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 498 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
578 | dinfo->i_lenAlloc += nfidlen; | 499 | dinfo->i_lenAlloc += nfidlen; |
579 | mark_inode_dirty(dir); | 500 | mark_inode_dirty(dir); |
580 | return fi; | 501 | goto out_ok; |
581 | } else { | 502 | } else { |
582 | brelse(epos.bh); | ||
583 | if (fibh->sbh != fibh->ebh) | ||
584 | brelse(fibh->ebh); | ||
585 | brelse(fibh->sbh); | ||
586 | *err = -EIO; | 503 | *err = -EIO; |
587 | return NULL; | 504 | goto out_err; |
588 | } | 505 | } |
506 | |||
507 | out_err: | ||
508 | fi = NULL; | ||
509 | if (fibh->sbh != fibh->ebh) | ||
510 | brelse(fibh->ebh); | ||
511 | brelse(fibh->sbh); | ||
512 | out_ok: | ||
513 | brelse(epos.bh); | ||
514 | kfree(name); | ||
515 | return fi; | ||
589 | } | 516 | } |
590 | 517 | ||
591 | static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, | 518 | static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, |
@@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
940 | char *ea; | 867 | char *ea; |
941 | int err; | 868 | int err; |
942 | int block; | 869 | int block; |
943 | char name[UDF_NAME_LEN]; | 870 | char *name = NULL; |
944 | int namelen; | 871 | int namelen; |
945 | struct buffer_head *bh; | 872 | struct buffer_head *bh; |
946 | struct udf_inode_info *iinfo; | 873 | struct udf_inode_info *iinfo; |
@@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
950 | if (!inode) | 877 | if (!inode) |
951 | goto out; | 878 | goto out; |
952 | 879 | ||
880 | name = kmalloc(UDF_NAME_LEN, GFP_NOFS); | ||
881 | if (!name) { | ||
882 | err = -ENOMEM; | ||
883 | goto out_no_entry; | ||
884 | } | ||
885 | |||
953 | iinfo = UDF_I(inode); | 886 | iinfo = UDF_I(inode); |
954 | inode->i_mode = S_IFLNK | S_IRWXUGO; | 887 | inode->i_mode = S_IFLNK | S_IRWXUGO; |
955 | inode->i_data.a_ops = &udf_symlink_aops; | 888 | inode->i_data.a_ops = &udf_symlink_aops; |
@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
1089 | err = 0; | 1022 | err = 0; |
1090 | 1023 | ||
1091 | out: | 1024 | out: |
1025 | kfree(name); | ||
1092 | unlock_kernel(); | 1026 | unlock_kernel(); |
1093 | return err; | 1027 | return err; |
1094 | 1028 | ||
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index fc533345ab89..63610f026ae1 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/udf_fs.h> | ||
28 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
29 | #include <linux/buffer_head.h> | 28 | #include <linux/buffer_head.h> |
30 | 29 | ||
@@ -55,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
55 | struct udf_sb_info *sbi = UDF_SB(sb); | 54 | struct udf_sb_info *sbi = UDF_SB(sb); |
56 | struct udf_part_map *map; | 55 | struct udf_part_map *map; |
57 | struct udf_virtual_data *vdata; | 56 | struct udf_virtual_data *vdata; |
58 | struct udf_inode_info *iinfo; | 57 | struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode); |
59 | 58 | ||
60 | map = &sbi->s_partmaps[partition]; | 59 | map = &sbi->s_partmaps[partition]; |
61 | vdata = &map->s_type_specific.s_virtual; | 60 | vdata = &map->s_type_specific.s_virtual; |
62 | index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t); | ||
63 | 61 | ||
64 | if (block > vdata->s_num_entries) { | 62 | if (block > vdata->s_num_entries) { |
65 | udf_debug("Trying to access block beyond end of VAT " | 63 | udf_debug("Trying to access block beyond end of VAT " |
@@ -67,6 +65,12 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
67 | return 0xFFFFFFFF; | 65 | return 0xFFFFFFFF; |
68 | } | 66 | } |
69 | 67 | ||
68 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | ||
69 | loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data + | ||
70 | vdata->s_start_offset))[block]); | ||
71 | goto translate; | ||
72 | } | ||
73 | index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t); | ||
70 | if (block >= index) { | 74 | if (block >= index) { |
71 | block -= index; | 75 | block -= index; |
72 | newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); | 76 | newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); |
@@ -89,7 +93,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, | |||
89 | 93 | ||
90 | brelse(bh); | 94 | brelse(bh); |
91 | 95 | ||
92 | iinfo = UDF_I(sbi->s_vat_inode); | 96 | translate: |
93 | if (iinfo->i_location.partitionReferenceNum == partition) { | 97 | if (iinfo->i_location.partitionReferenceNum == partition) { |
94 | udf_debug("recursive call to udf_get_pblock!\n"); | 98 | udf_debug("recursive call to udf_get_pblock!\n"); |
95 | return 0xFFFFFFFF; | 99 | return 0xFFFFFFFF; |
@@ -263,3 +267,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) | |||
263 | 267 | ||
264 | return 0; | 268 | return 0; |
265 | } | 269 | } |
270 | |||
271 | static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, | ||
272 | uint16_t partition, uint32_t offset) | ||
273 | { | ||
274 | struct super_block *sb = inode->i_sb; | ||
275 | struct udf_part_map *map; | ||
276 | kernel_lb_addr eloc; | ||
277 | uint32_t elen; | ||
278 | sector_t ext_offset; | ||
279 | struct extent_position epos = {}; | ||
280 | uint32_t phyblock; | ||
281 | |||
282 | if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) != | ||
283 | (EXT_RECORDED_ALLOCATED >> 30)) | ||
284 | phyblock = 0xFFFFFFFF; | ||
285 | else { | ||
286 | map = &UDF_SB(sb)->s_partmaps[partition]; | ||
287 | /* map to sparable/physical partition desc */ | ||
288 | phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, | ||
289 | map->s_partition_num, ext_offset + offset); | ||
290 | } | ||
291 | |||
292 | brelse(epos.bh); | ||
293 | return phyblock; | ||
294 | } | ||
295 | |||
296 | uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, | ||
297 | uint16_t partition, uint32_t offset) | ||
298 | { | ||
299 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
300 | struct udf_part_map *map; | ||
301 | struct udf_meta_data *mdata; | ||
302 | uint32_t retblk; | ||
303 | struct inode *inode; | ||
304 | |||
305 | udf_debug("READING from METADATA\n"); | ||
306 | |||
307 | map = &sbi->s_partmaps[partition]; | ||
308 | mdata = &map->s_type_specific.s_metadata; | ||
309 | inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe; | ||
310 | |||
311 | /* We shouldn't mount such media... */ | ||
312 | BUG_ON(!inode); | ||
313 | retblk = udf_try_read_meta(inode, block, partition, offset); | ||
314 | if (retblk == 0xFFFFFFFF) { | ||
315 | udf_warning(sb, __func__, "error reading from METADATA, " | ||
316 | "trying to read from MIRROR"); | ||
317 | inode = mdata->s_mirror_fe; | ||
318 | if (!inode) | ||
319 | return 0xFFFFFFFF; | ||
320 | retblk = udf_try_read_meta(inode, block, partition, offset); | ||
321 | } | ||
322 | |||
323 | return retblk; | ||
324 | } | ||
diff --git a/fs/udf/super.c b/fs/udf/super.c index f3ac4abfc946..b564fc140fe4 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -55,9 +55,10 @@ | |||
55 | #include <linux/errno.h> | 55 | #include <linux/errno.h> |
56 | #include <linux/mount.h> | 56 | #include <linux/mount.h> |
57 | #include <linux/seq_file.h> | 57 | #include <linux/seq_file.h> |
58 | #include <linux/bitmap.h> | ||
59 | #include <linux/crc-itu-t.h> | ||
58 | #include <asm/byteorder.h> | 60 | #include <asm/byteorder.h> |
59 | 61 | ||
60 | #include <linux/udf_fs.h> | ||
61 | #include "udf_sb.h" | 62 | #include "udf_sb.h" |
62 | #include "udf_i.h" | 63 | #include "udf_i.h" |
63 | 64 | ||
@@ -84,22 +85,19 @@ static void udf_write_super(struct super_block *); | |||
84 | static int udf_remount_fs(struct super_block *, int *, char *); | 85 | static int udf_remount_fs(struct super_block *, int *, char *); |
85 | static int udf_check_valid(struct super_block *, int, int); | 86 | static int udf_check_valid(struct super_block *, int, int); |
86 | static int udf_vrs(struct super_block *sb, int silent); | 87 | static int udf_vrs(struct super_block *sb, int silent); |
87 | static int udf_load_partition(struct super_block *, kernel_lb_addr *); | ||
88 | static int udf_load_logicalvol(struct super_block *, struct buffer_head *, | ||
89 | kernel_lb_addr *); | ||
90 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); | 88 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); |
91 | static void udf_find_anchor(struct super_block *); | 89 | static void udf_find_anchor(struct super_block *); |
92 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, | 90 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, |
93 | kernel_lb_addr *); | 91 | kernel_lb_addr *); |
94 | static void udf_load_pvoldesc(struct super_block *, struct buffer_head *); | ||
95 | static void udf_load_fileset(struct super_block *, struct buffer_head *, | 92 | static void udf_load_fileset(struct super_block *, struct buffer_head *, |
96 | kernel_lb_addr *); | 93 | kernel_lb_addr *); |
97 | static int udf_load_partdesc(struct super_block *, struct buffer_head *); | ||
98 | static void udf_open_lvid(struct super_block *); | 94 | static void udf_open_lvid(struct super_block *); |
99 | static void udf_close_lvid(struct super_block *); | 95 | static void udf_close_lvid(struct super_block *); |
100 | static unsigned int udf_count_free(struct super_block *); | 96 | static unsigned int udf_count_free(struct super_block *); |
101 | static int udf_statfs(struct dentry *, struct kstatfs *); | 97 | static int udf_statfs(struct dentry *, struct kstatfs *); |
102 | static int udf_show_options(struct seq_file *, struct vfsmount *); | 98 | static int udf_show_options(struct seq_file *, struct vfsmount *); |
99 | static void udf_error(struct super_block *sb, const char *function, | ||
100 | const char *fmt, ...); | ||
103 | 101 | ||
104 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi) | 102 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi) |
105 | { | 103 | { |
@@ -587,48 +585,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | |||
587 | return 0; | 585 | return 0; |
588 | } | 586 | } |
589 | 587 | ||
590 | /* | ||
591 | * udf_set_blocksize | ||
592 | * | ||
593 | * PURPOSE | ||
594 | * Set the block size to be used in all transfers. | ||
595 | * | ||
596 | * DESCRIPTION | ||
597 | * To allow room for a DMA transfer, it is best to guess big when unsure. | ||
598 | * This routine picks 2048 bytes as the blocksize when guessing. This | ||
599 | * should be adequate until devices with larger block sizes become common. | ||
600 | * | ||
601 | * Note that the Linux kernel can currently only deal with blocksizes of | ||
602 | * 512, 1024, 2048, 4096, and 8192 bytes. | ||
603 | * | ||
604 | * PRE-CONDITIONS | ||
605 | * sb Pointer to _locked_ superblock. | ||
606 | * | ||
607 | * POST-CONDITIONS | ||
608 | * sb->s_blocksize Blocksize. | ||
609 | * sb->s_blocksize_bits log2 of blocksize. | ||
610 | * <return> 0 Blocksize is valid. | ||
611 | * <return> 1 Blocksize is invalid. | ||
612 | * | ||
613 | * HISTORY | ||
614 | * July 1, 1997 - Andrew E. Mileski | ||
615 | * Written, tested, and released. | ||
616 | */ | ||
617 | static int udf_set_blocksize(struct super_block *sb, int bsize) | ||
618 | { | ||
619 | if (!sb_min_blocksize(sb, bsize)) { | ||
620 | udf_debug("Bad block size (%d)\n", bsize); | ||
621 | printk(KERN_ERR "udf: bad block size (%d)\n", bsize); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | return sb->s_blocksize; | ||
626 | } | ||
627 | |||
628 | static int udf_vrs(struct super_block *sb, int silent) | 588 | static int udf_vrs(struct super_block *sb, int silent) |
629 | { | 589 | { |
630 | struct volStructDesc *vsd = NULL; | 590 | struct volStructDesc *vsd = NULL; |
631 | int sector = 32768; | 591 | loff_t sector = 32768; |
632 | int sectorsize; | 592 | int sectorsize; |
633 | struct buffer_head *bh = NULL; | 593 | struct buffer_head *bh = NULL; |
634 | int iso9660 = 0; | 594 | int iso9660 = 0; |
@@ -649,7 +609,8 @@ static int udf_vrs(struct super_block *sb, int silent) | |||
649 | sector += (sbi->s_session << sb->s_blocksize_bits); | 609 | sector += (sbi->s_session << sb->s_blocksize_bits); |
650 | 610 | ||
651 | udf_debug("Starting at sector %u (%ld byte sectors)\n", | 611 | udf_debug("Starting at sector %u (%ld byte sectors)\n", |
652 | (sector >> sb->s_blocksize_bits), sb->s_blocksize); | 612 | (unsigned int)(sector >> sb->s_blocksize_bits), |
613 | sb->s_blocksize); | ||
653 | /* Process the sequence (if applicable) */ | 614 | /* Process the sequence (if applicable) */ |
654 | for (; !nsr02 && !nsr03; sector += sectorsize) { | 615 | for (; !nsr02 && !nsr03; sector += sectorsize) { |
655 | /* Read a block */ | 616 | /* Read a block */ |
@@ -719,162 +680,140 @@ static int udf_vrs(struct super_block *sb, int silent) | |||
719 | } | 680 | } |
720 | 681 | ||
721 | /* | 682 | /* |
722 | * udf_find_anchor | 683 | * Check whether there is an anchor block in the given block |
723 | * | ||
724 | * PURPOSE | ||
725 | * Find an anchor volume descriptor. | ||
726 | * | ||
727 | * PRE-CONDITIONS | ||
728 | * sb Pointer to _locked_ superblock. | ||
729 | * lastblock Last block on media. | ||
730 | * | ||
731 | * POST-CONDITIONS | ||
732 | * <return> 1 if not found, 0 if ok | ||
733 | * | ||
734 | * HISTORY | ||
735 | * July 1, 1997 - Andrew E. Mileski | ||
736 | * Written, tested, and released. | ||
737 | */ | 684 | */ |
738 | static void udf_find_anchor(struct super_block *sb) | 685 | static int udf_check_anchor_block(struct super_block *sb, sector_t block, |
686 | bool varconv) | ||
739 | { | 687 | { |
740 | int lastblock; | ||
741 | struct buffer_head *bh = NULL; | 688 | struct buffer_head *bh = NULL; |
689 | tag *t; | ||
742 | uint16_t ident; | 690 | uint16_t ident; |
743 | uint32_t location; | 691 | uint32_t location; |
744 | int i; | ||
745 | struct udf_sb_info *sbi; | ||
746 | 692 | ||
747 | sbi = UDF_SB(sb); | 693 | if (varconv) { |
748 | lastblock = sbi->s_last_block; | 694 | if (udf_fixed_to_variable(block) >= |
695 | sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) | ||
696 | return 0; | ||
697 | bh = sb_bread(sb, udf_fixed_to_variable(block)); | ||
698 | } | ||
699 | else | ||
700 | bh = sb_bread(sb, block); | ||
749 | 701 | ||
750 | if (lastblock) { | 702 | if (!bh) |
751 | int varlastblock = udf_variable_to_fixed(lastblock); | 703 | return 0; |
752 | int last[] = { lastblock, lastblock - 2, | ||
753 | lastblock - 150, lastblock - 152, | ||
754 | varlastblock, varlastblock - 2, | ||
755 | varlastblock - 150, varlastblock - 152 }; | ||
756 | |||
757 | lastblock = 0; | ||
758 | |||
759 | /* Search for an anchor volume descriptor pointer */ | ||
760 | |||
761 | /* according to spec, anchor is in either: | ||
762 | * block 256 | ||
763 | * lastblock-256 | ||
764 | * lastblock | ||
765 | * however, if the disc isn't closed, it could be 512 */ | ||
766 | |||
767 | for (i = 0; !lastblock && i < ARRAY_SIZE(last); i++) { | ||
768 | ident = location = 0; | ||
769 | if (last[i] >= 0) { | ||
770 | bh = sb_bread(sb, last[i]); | ||
771 | if (bh) { | ||
772 | tag *t = (tag *)bh->b_data; | ||
773 | ident = le16_to_cpu(t->tagIdent); | ||
774 | location = le32_to_cpu(t->tagLocation); | ||
775 | brelse(bh); | ||
776 | } | ||
777 | } | ||
778 | 704 | ||
779 | if (ident == TAG_IDENT_AVDP) { | 705 | t = (tag *)bh->b_data; |
780 | if (location == last[i] - sbi->s_session) { | 706 | ident = le16_to_cpu(t->tagIdent); |
781 | lastblock = last[i] - sbi->s_session; | 707 | location = le32_to_cpu(t->tagLocation); |
782 | sbi->s_anchor[0] = lastblock; | 708 | brelse(bh); |
783 | sbi->s_anchor[1] = lastblock - 256; | 709 | if (ident != TAG_IDENT_AVDP) |
784 | } else if (location == | 710 | return 0; |
785 | udf_variable_to_fixed(last[i]) - | 711 | return location == block; |
786 | sbi->s_session) { | 712 | } |
787 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
788 | lastblock = | ||
789 | udf_variable_to_fixed(last[i]) - | ||
790 | sbi->s_session; | ||
791 | sbi->s_anchor[0] = lastblock; | ||
792 | sbi->s_anchor[1] = lastblock - 256 - | ||
793 | sbi->s_session; | ||
794 | } else { | ||
795 | udf_debug("Anchor found at block %d, " | ||
796 | "location mismatch %d.\n", | ||
797 | last[i], location); | ||
798 | } | ||
799 | } else if (ident == TAG_IDENT_FE || | ||
800 | ident == TAG_IDENT_EFE) { | ||
801 | lastblock = last[i]; | ||
802 | sbi->s_anchor[3] = 512; | ||
803 | } else { | ||
804 | ident = location = 0; | ||
805 | if (last[i] >= 256) { | ||
806 | bh = sb_bread(sb, last[i] - 256); | ||
807 | if (bh) { | ||
808 | tag *t = (tag *)bh->b_data; | ||
809 | ident = le16_to_cpu( | ||
810 | t->tagIdent); | ||
811 | location = le32_to_cpu( | ||
812 | t->tagLocation); | ||
813 | brelse(bh); | ||
814 | } | ||
815 | } | ||
816 | 713 | ||
817 | if (ident == TAG_IDENT_AVDP && | 714 | /* Search for an anchor volume descriptor pointer */ |
818 | location == last[i] - 256 - | 715 | static sector_t udf_scan_anchors(struct super_block *sb, bool varconv, |
819 | sbi->s_session) { | 716 | sector_t lastblock) |
820 | lastblock = last[i]; | 717 | { |
821 | sbi->s_anchor[1] = last[i] - 256; | 718 | sector_t last[6]; |
822 | } else { | 719 | int i; |
823 | ident = location = 0; | 720 | struct udf_sb_info *sbi = UDF_SB(sb); |
824 | if (last[i] >= 312 + sbi->s_session) { | ||
825 | bh = sb_bread(sb, | ||
826 | last[i] - 312 - | ||
827 | sbi->s_session); | ||
828 | if (bh) { | ||
829 | tag *t = (tag *) | ||
830 | bh->b_data; | ||
831 | ident = le16_to_cpu( | ||
832 | t->tagIdent); | ||
833 | location = le32_to_cpu( | ||
834 | t->tagLocation); | ||
835 | brelse(bh); | ||
836 | } | ||
837 | } | ||
838 | 721 | ||
839 | if (ident == TAG_IDENT_AVDP && | 722 | last[0] = lastblock; |
840 | location == udf_variable_to_fixed(last[i]) - 256) { | 723 | last[1] = last[0] - 1; |
841 | UDF_SET_FLAG(sb, | 724 | last[2] = last[0] + 1; |
842 | UDF_FLAG_VARCONV); | 725 | last[3] = last[0] - 2; |
843 | lastblock = udf_variable_to_fixed(last[i]); | 726 | last[4] = last[0] - 150; |
844 | sbi->s_anchor[1] = lastblock - 256; | 727 | last[5] = last[0] - 152; |
845 | } | 728 | |
846 | } | 729 | /* according to spec, anchor is in either: |
847 | } | 730 | * block 256 |
731 | * lastblock-256 | ||
732 | * lastblock | ||
733 | * however, if the disc isn't closed, it could be 512 */ | ||
734 | |||
735 | for (i = 0; i < ARRAY_SIZE(last); i++) { | ||
736 | if (last[i] < 0) | ||
737 | continue; | ||
738 | if (last[i] >= sb->s_bdev->bd_inode->i_size >> | ||
739 | sb->s_blocksize_bits) | ||
740 | continue; | ||
741 | |||
742 | if (udf_check_anchor_block(sb, last[i], varconv)) { | ||
743 | sbi->s_anchor[0] = last[i]; | ||
744 | sbi->s_anchor[1] = last[i] - 256; | ||
745 | return last[i]; | ||
848 | } | 746 | } |
849 | } | ||
850 | 747 | ||
851 | if (!lastblock) { | 748 | if (last[i] < 256) |
852 | /* We haven't found the lastblock. check 312 */ | 749 | continue; |
853 | bh = sb_bread(sb, 312 + sbi->s_session); | ||
854 | if (bh) { | ||
855 | tag *t = (tag *)bh->b_data; | ||
856 | ident = le16_to_cpu(t->tagIdent); | ||
857 | location = le32_to_cpu(t->tagLocation); | ||
858 | brelse(bh); | ||
859 | 750 | ||
860 | if (ident == TAG_IDENT_AVDP && location == 256) | 751 | if (udf_check_anchor_block(sb, last[i] - 256, varconv)) { |
861 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | 752 | sbi->s_anchor[1] = last[i] - 256; |
753 | return last[i]; | ||
862 | } | 754 | } |
863 | } | 755 | } |
864 | 756 | ||
757 | if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) { | ||
758 | sbi->s_anchor[0] = sbi->s_session + 256; | ||
759 | return last[0]; | ||
760 | } | ||
761 | if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) { | ||
762 | sbi->s_anchor[0] = sbi->s_session + 512; | ||
763 | return last[0]; | ||
764 | } | ||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * Find an anchor volume descriptor. The function expects sbi->s_lastblock to | ||
770 | * be the last block on the media. | ||
771 | * | ||
772 | * Return 1 if not found, 0 if ok | ||
773 | * | ||
774 | */ | ||
775 | static void udf_find_anchor(struct super_block *sb) | ||
776 | { | ||
777 | sector_t lastblock; | ||
778 | struct buffer_head *bh = NULL; | ||
779 | uint16_t ident; | ||
780 | int i; | ||
781 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
782 | |||
783 | lastblock = udf_scan_anchors(sb, 0, sbi->s_last_block); | ||
784 | if (lastblock) | ||
785 | goto check_anchor; | ||
786 | |||
787 | /* No anchor found? Try VARCONV conversion of block numbers */ | ||
788 | /* Firstly, we try to not convert number of the last block */ | ||
789 | lastblock = udf_scan_anchors(sb, 1, | ||
790 | udf_variable_to_fixed(sbi->s_last_block)); | ||
791 | if (lastblock) { | ||
792 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
793 | goto check_anchor; | ||
794 | } | ||
795 | |||
796 | /* Secondly, we try with converted number of the last block */ | ||
797 | lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block); | ||
798 | if (lastblock) | ||
799 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
800 | |||
801 | check_anchor: | ||
802 | /* | ||
803 | * Check located anchors and the anchor block supplied via | ||
804 | * mount options | ||
805 | */ | ||
865 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { | 806 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { |
866 | if (sbi->s_anchor[i]) { | 807 | if (!sbi->s_anchor[i]) |
867 | bh = udf_read_tagged(sb, sbi->s_anchor[i], | 808 | continue; |
868 | sbi->s_anchor[i], &ident); | 809 | bh = udf_read_tagged(sb, sbi->s_anchor[i], |
869 | if (!bh) | 810 | sbi->s_anchor[i], &ident); |
811 | if (!bh) | ||
812 | sbi->s_anchor[i] = 0; | ||
813 | else { | ||
814 | brelse(bh); | ||
815 | if (ident != TAG_IDENT_AVDP) | ||
870 | sbi->s_anchor[i] = 0; | 816 | sbi->s_anchor[i] = 0; |
871 | else { | ||
872 | brelse(bh); | ||
873 | if ((ident != TAG_IDENT_AVDP) && | ||
874 | (i || (ident != TAG_IDENT_FE && | ||
875 | ident != TAG_IDENT_EFE))) | ||
876 | sbi->s_anchor[i] = 0; | ||
877 | } | ||
878 | } | 817 | } |
879 | } | 818 | } |
880 | 819 | ||
@@ -971,27 +910,30 @@ static int udf_find_fileset(struct super_block *sb, | |||
971 | return 1; | 910 | return 1; |
972 | } | 911 | } |
973 | 912 | ||
974 | static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh) | 913 | static int udf_load_pvoldesc(struct super_block *sb, sector_t block) |
975 | { | 914 | { |
976 | struct primaryVolDesc *pvoldesc; | 915 | struct primaryVolDesc *pvoldesc; |
977 | time_t recording; | ||
978 | long recording_usec; | ||
979 | struct ustr instr; | 916 | struct ustr instr; |
980 | struct ustr outstr; | 917 | struct ustr outstr; |
918 | struct buffer_head *bh; | ||
919 | uint16_t ident; | ||
920 | |||
921 | bh = udf_read_tagged(sb, block, block, &ident); | ||
922 | if (!bh) | ||
923 | return 1; | ||
924 | BUG_ON(ident != TAG_IDENT_PVD); | ||
981 | 925 | ||
982 | pvoldesc = (struct primaryVolDesc *)bh->b_data; | 926 | pvoldesc = (struct primaryVolDesc *)bh->b_data; |
983 | 927 | ||
984 | if (udf_stamp_to_time(&recording, &recording_usec, | 928 | if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, |
985 | lets_to_cpu(pvoldesc->recordingDateAndTime))) { | 929 | pvoldesc->recordingDateAndTime)) { |
986 | kernel_timestamp ts; | 930 | #ifdef UDFFS_DEBUG |
987 | ts = lets_to_cpu(pvoldesc->recordingDateAndTime); | 931 | timestamp *ts = &pvoldesc->recordingDateAndTime; |
988 | udf_debug("recording time %ld/%ld, %04u/%02u/%02u" | 932 | udf_debug("recording time %04u/%02u/%02u" |
989 | " %02u:%02u (%x)\n", | 933 | " %02u:%02u (%x)\n", |
990 | recording, recording_usec, | 934 | le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, |
991 | ts.year, ts.month, ts.day, ts.hour, | 935 | ts->minute, le16_to_cpu(ts->typeAndTimezone)); |
992 | ts.minute, ts.typeAndTimezone); | 936 | #endif |
993 | UDF_SB(sb)->s_record_time.tv_sec = recording; | ||
994 | UDF_SB(sb)->s_record_time.tv_nsec = recording_usec * 1000; | ||
995 | } | 937 | } |
996 | 938 | ||
997 | if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32)) | 939 | if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32)) |
@@ -1005,6 +947,104 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh) | |||
1005 | if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) | 947 | if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) |
1006 | if (udf_CS0toUTF8(&outstr, &instr)) | 948 | if (udf_CS0toUTF8(&outstr, &instr)) |
1007 | udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); | 949 | udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); |
950 | |||
951 | brelse(bh); | ||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static int udf_load_metadata_files(struct super_block *sb, int partition) | ||
956 | { | ||
957 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
958 | struct udf_part_map *map; | ||
959 | struct udf_meta_data *mdata; | ||
960 | kernel_lb_addr addr; | ||
961 | int fe_error = 0; | ||
962 | |||
963 | map = &sbi->s_partmaps[partition]; | ||
964 | mdata = &map->s_type_specific.s_metadata; | ||
965 | |||
966 | /* metadata address */ | ||
967 | addr.logicalBlockNum = mdata->s_meta_file_loc; | ||
968 | addr.partitionReferenceNum = map->s_partition_num; | ||
969 | |||
970 | udf_debug("Metadata file location: block = %d part = %d\n", | ||
971 | addr.logicalBlockNum, addr.partitionReferenceNum); | ||
972 | |||
973 | mdata->s_metadata_fe = udf_iget(sb, addr); | ||
974 | |||
975 | if (mdata->s_metadata_fe == NULL) { | ||
976 | udf_warning(sb, __func__, "metadata inode efe not found, " | ||
977 | "will try mirror inode."); | ||
978 | fe_error = 1; | ||
979 | } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type != | ||
980 | ICBTAG_FLAG_AD_SHORT) { | ||
981 | udf_warning(sb, __func__, "metadata inode efe does not have " | ||
982 | "short allocation descriptors!"); | ||
983 | fe_error = 1; | ||
984 | iput(mdata->s_metadata_fe); | ||
985 | mdata->s_metadata_fe = NULL; | ||
986 | } | ||
987 | |||
988 | /* mirror file entry */ | ||
989 | addr.logicalBlockNum = mdata->s_mirror_file_loc; | ||
990 | addr.partitionReferenceNum = map->s_partition_num; | ||
991 | |||
992 | udf_debug("Mirror metadata file location: block = %d part = %d\n", | ||
993 | addr.logicalBlockNum, addr.partitionReferenceNum); | ||
994 | |||
995 | mdata->s_mirror_fe = udf_iget(sb, addr); | ||
996 | |||
997 | if (mdata->s_mirror_fe == NULL) { | ||
998 | if (fe_error) { | ||
999 | udf_error(sb, __func__, "mirror inode efe not found " | ||
1000 | "and metadata inode is missing too, exiting..."); | ||
1001 | goto error_exit; | ||
1002 | } else | ||
1003 | udf_warning(sb, __func__, "mirror inode efe not found," | ||
1004 | " but metadata inode is OK"); | ||
1005 | } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type != | ||
1006 | ICBTAG_FLAG_AD_SHORT) { | ||
1007 | udf_warning(sb, __func__, "mirror inode efe does not have " | ||
1008 | "short allocation descriptors!"); | ||
1009 | iput(mdata->s_mirror_fe); | ||
1010 | mdata->s_mirror_fe = NULL; | ||
1011 | if (fe_error) | ||
1012 | goto error_exit; | ||
1013 | } | ||
1014 | |||
1015 | /* | ||
1016 | * bitmap file entry | ||
1017 | * Note: | ||
1018 | * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102) | ||
1019 | */ | ||
1020 | if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) { | ||
1021 | addr.logicalBlockNum = mdata->s_bitmap_file_loc; | ||
1022 | addr.partitionReferenceNum = map->s_partition_num; | ||
1023 | |||
1024 | udf_debug("Bitmap file location: block = %d part = %d\n", | ||
1025 | addr.logicalBlockNum, addr.partitionReferenceNum); | ||
1026 | |||
1027 | mdata->s_bitmap_fe = udf_iget(sb, addr); | ||
1028 | |||
1029 | if (mdata->s_bitmap_fe == NULL) { | ||
1030 | if (sb->s_flags & MS_RDONLY) | ||
1031 | udf_warning(sb, __func__, "bitmap inode efe " | ||
1032 | "not found but it's ok since the disc" | ||
1033 | " is mounted read-only"); | ||
1034 | else { | ||
1035 | udf_error(sb, __func__, "bitmap inode efe not " | ||
1036 | "found and attempted read-write mount"); | ||
1037 | goto error_exit; | ||
1038 | } | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | udf_debug("udf_load_metadata_files Ok\n"); | ||
1043 | |||
1044 | return 0; | ||
1045 | |||
1046 | error_exit: | ||
1047 | return 1; | ||
1008 | } | 1048 | } |
1009 | 1049 | ||
1010 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | 1050 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, |
@@ -1025,10 +1065,9 @@ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | |||
1025 | int udf_compute_nr_groups(struct super_block *sb, u32 partition) | 1065 | int udf_compute_nr_groups(struct super_block *sb, u32 partition) |
1026 | { | 1066 | { |
1027 | struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; | 1067 | struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
1028 | return (map->s_partition_len + | 1068 | return DIV_ROUND_UP(map->s_partition_len + |
1029 | (sizeof(struct spaceBitmapDesc) << 3) + | 1069 | (sizeof(struct spaceBitmapDesc) << 3), |
1030 | (sb->s_blocksize * 8) - 1) / | 1070 | sb->s_blocksize * 8); |
1031 | (sb->s_blocksize * 8); | ||
1032 | } | 1071 | } |
1033 | 1072 | ||
1034 | static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) | 1073 | static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) |
@@ -1059,134 +1098,241 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) | |||
1059 | return bitmap; | 1098 | return bitmap; |
1060 | } | 1099 | } |
1061 | 1100 | ||
1062 | static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) | 1101 | static int udf_fill_partdesc_info(struct super_block *sb, |
1102 | struct partitionDesc *p, int p_index) | ||
1103 | { | ||
1104 | struct udf_part_map *map; | ||
1105 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1106 | struct partitionHeaderDesc *phd; | ||
1107 | |||
1108 | map = &sbi->s_partmaps[p_index]; | ||
1109 | |||
1110 | map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */ | ||
1111 | map->s_partition_root = le32_to_cpu(p->partitionStartingLocation); | ||
1112 | |||
1113 | if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY)) | ||
1114 | map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY; | ||
1115 | if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE)) | ||
1116 | map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE; | ||
1117 | if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE)) | ||
1118 | map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE; | ||
1119 | if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE)) | ||
1120 | map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE; | ||
1121 | |||
1122 | udf_debug("Partition (%d type %x) starts at physical %d, " | ||
1123 | "block length %d\n", p_index, | ||
1124 | map->s_partition_type, map->s_partition_root, | ||
1125 | map->s_partition_len); | ||
1126 | |||
1127 | if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) && | ||
1128 | strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03)) | ||
1129 | return 0; | ||
1130 | |||
1131 | phd = (struct partitionHeaderDesc *)p->partitionContentsUse; | ||
1132 | if (phd->unallocSpaceTable.extLength) { | ||
1133 | kernel_lb_addr loc = { | ||
1134 | .logicalBlockNum = le32_to_cpu( | ||
1135 | phd->unallocSpaceTable.extPosition), | ||
1136 | .partitionReferenceNum = p_index, | ||
1137 | }; | ||
1138 | |||
1139 | map->s_uspace.s_table = udf_iget(sb, loc); | ||
1140 | if (!map->s_uspace.s_table) { | ||
1141 | udf_debug("cannot load unallocSpaceTable (part %d)\n", | ||
1142 | p_index); | ||
1143 | return 1; | ||
1144 | } | ||
1145 | map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE; | ||
1146 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", | ||
1147 | p_index, map->s_uspace.s_table->i_ino); | ||
1148 | } | ||
1149 | |||
1150 | if (phd->unallocSpaceBitmap.extLength) { | ||
1151 | struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index); | ||
1152 | if (!bitmap) | ||
1153 | return 1; | ||
1154 | map->s_uspace.s_bitmap = bitmap; | ||
1155 | bitmap->s_extLength = le32_to_cpu( | ||
1156 | phd->unallocSpaceBitmap.extLength); | ||
1157 | bitmap->s_extPosition = le32_to_cpu( | ||
1158 | phd->unallocSpaceBitmap.extPosition); | ||
1159 | map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP; | ||
1160 | udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index, | ||
1161 | bitmap->s_extPosition); | ||
1162 | } | ||
1163 | |||
1164 | if (phd->partitionIntegrityTable.extLength) | ||
1165 | udf_debug("partitionIntegrityTable (part %d)\n", p_index); | ||
1166 | |||
1167 | if (phd->freedSpaceTable.extLength) { | ||
1168 | kernel_lb_addr loc = { | ||
1169 | .logicalBlockNum = le32_to_cpu( | ||
1170 | phd->freedSpaceTable.extPosition), | ||
1171 | .partitionReferenceNum = p_index, | ||
1172 | }; | ||
1173 | |||
1174 | map->s_fspace.s_table = udf_iget(sb, loc); | ||
1175 | if (!map->s_fspace.s_table) { | ||
1176 | udf_debug("cannot load freedSpaceTable (part %d)\n", | ||
1177 | p_index); | ||
1178 | return 1; | ||
1179 | } | ||
1180 | |||
1181 | map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; | ||
1182 | udf_debug("freedSpaceTable (part %d) @ %ld\n", | ||
1183 | p_index, map->s_fspace.s_table->i_ino); | ||
1184 | } | ||
1185 | |||
1186 | if (phd->freedSpaceBitmap.extLength) { | ||
1187 | struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index); | ||
1188 | if (!bitmap) | ||
1189 | return 1; | ||
1190 | map->s_fspace.s_bitmap = bitmap; | ||
1191 | bitmap->s_extLength = le32_to_cpu( | ||
1192 | phd->freedSpaceBitmap.extLength); | ||
1193 | bitmap->s_extPosition = le32_to_cpu( | ||
1194 | phd->freedSpaceBitmap.extPosition); | ||
1195 | map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP; | ||
1196 | udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index, | ||
1197 | bitmap->s_extPosition); | ||
1198 | } | ||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | ||
1203 | { | ||
1204 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1205 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | ||
1206 | kernel_lb_addr ino; | ||
1207 | struct buffer_head *bh = NULL; | ||
1208 | struct udf_inode_info *vati; | ||
1209 | uint32_t pos; | ||
1210 | struct virtualAllocationTable20 *vat20; | ||
1211 | |||
1212 | /* VAT file entry is in the last recorded block */ | ||
1213 | ino.partitionReferenceNum = type1_index; | ||
1214 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | ||
1215 | sbi->s_vat_inode = udf_iget(sb, ino); | ||
1216 | if (!sbi->s_vat_inode) | ||
1217 | return 1; | ||
1218 | |||
1219 | if (map->s_partition_type == UDF_VIRTUAL_MAP15) { | ||
1220 | map->s_type_specific.s_virtual.s_start_offset = 0; | ||
1221 | map->s_type_specific.s_virtual.s_num_entries = | ||
1222 | (sbi->s_vat_inode->i_size - 36) >> 2; | ||
1223 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { | ||
1224 | vati = UDF_I(sbi->s_vat_inode); | ||
1225 | if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | ||
1226 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1227 | bh = sb_bread(sb, pos); | ||
1228 | if (!bh) | ||
1229 | return 1; | ||
1230 | vat20 = (struct virtualAllocationTable20 *)bh->b_data; | ||
1231 | } else { | ||
1232 | vat20 = (struct virtualAllocationTable20 *) | ||
1233 | vati->i_ext.i_data; | ||
1234 | } | ||
1235 | |||
1236 | map->s_type_specific.s_virtual.s_start_offset = | ||
1237 | le16_to_cpu(vat20->lengthHeader); | ||
1238 | map->s_type_specific.s_virtual.s_num_entries = | ||
1239 | (sbi->s_vat_inode->i_size - | ||
1240 | map->s_type_specific.s_virtual. | ||
1241 | s_start_offset) >> 2; | ||
1242 | brelse(bh); | ||
1243 | } | ||
1244 | return 0; | ||
1245 | } | ||
1246 | |||
1247 | static int udf_load_partdesc(struct super_block *sb, sector_t block) | ||
1063 | { | 1248 | { |
1249 | struct buffer_head *bh; | ||
1064 | struct partitionDesc *p; | 1250 | struct partitionDesc *p; |
1065 | int i; | ||
1066 | struct udf_part_map *map; | 1251 | struct udf_part_map *map; |
1067 | struct udf_sb_info *sbi; | 1252 | struct udf_sb_info *sbi = UDF_SB(sb); |
1253 | int i, type1_idx; | ||
1254 | uint16_t partitionNumber; | ||
1255 | uint16_t ident; | ||
1256 | int ret = 0; | ||
1257 | |||
1258 | bh = udf_read_tagged(sb, block, block, &ident); | ||
1259 | if (!bh) | ||
1260 | return 1; | ||
1261 | if (ident != TAG_IDENT_PD) | ||
1262 | goto out_bh; | ||
1068 | 1263 | ||
1069 | p = (struct partitionDesc *)bh->b_data; | 1264 | p = (struct partitionDesc *)bh->b_data; |
1070 | sbi = UDF_SB(sb); | 1265 | partitionNumber = le16_to_cpu(p->partitionNumber); |
1071 | 1266 | ||
1267 | /* First scan for TYPE1, SPARABLE and METADATA partitions */ | ||
1072 | for (i = 0; i < sbi->s_partitions; i++) { | 1268 | for (i = 0; i < sbi->s_partitions; i++) { |
1073 | map = &sbi->s_partmaps[i]; | 1269 | map = &sbi->s_partmaps[i]; |
1074 | udf_debug("Searching map: (%d == %d)\n", | 1270 | udf_debug("Searching map: (%d == %d)\n", |
1075 | map->s_partition_num, | 1271 | map->s_partition_num, partitionNumber); |
1076 | le16_to_cpu(p->partitionNumber)); | 1272 | if (map->s_partition_num == partitionNumber && |
1077 | if (map->s_partition_num == | 1273 | (map->s_partition_type == UDF_TYPE1_MAP15 || |
1078 | le16_to_cpu(p->partitionNumber)) { | 1274 | map->s_partition_type == UDF_SPARABLE_MAP15)) |
1079 | map->s_partition_len = | ||
1080 | le32_to_cpu(p->partitionLength); /* blocks */ | ||
1081 | map->s_partition_root = | ||
1082 | le32_to_cpu(p->partitionStartingLocation); | ||
1083 | if (p->accessType == | ||
1084 | cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY)) | ||
1085 | map->s_partition_flags |= | ||
1086 | UDF_PART_FLAG_READ_ONLY; | ||
1087 | if (p->accessType == | ||
1088 | cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE)) | ||
1089 | map->s_partition_flags |= | ||
1090 | UDF_PART_FLAG_WRITE_ONCE; | ||
1091 | if (p->accessType == | ||
1092 | cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE)) | ||
1093 | map->s_partition_flags |= | ||
1094 | UDF_PART_FLAG_REWRITABLE; | ||
1095 | if (p->accessType == | ||
1096 | cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE)) | ||
1097 | map->s_partition_flags |= | ||
1098 | UDF_PART_FLAG_OVERWRITABLE; | ||
1099 | |||
1100 | if (!strcmp(p->partitionContents.ident, | ||
1101 | PD_PARTITION_CONTENTS_NSR02) || | ||
1102 | !strcmp(p->partitionContents.ident, | ||
1103 | PD_PARTITION_CONTENTS_NSR03)) { | ||
1104 | struct partitionHeaderDesc *phd; | ||
1105 | |||
1106 | phd = (struct partitionHeaderDesc *) | ||
1107 | (p->partitionContentsUse); | ||
1108 | if (phd->unallocSpaceTable.extLength) { | ||
1109 | kernel_lb_addr loc = { | ||
1110 | .logicalBlockNum = le32_to_cpu(phd->unallocSpaceTable.extPosition), | ||
1111 | .partitionReferenceNum = i, | ||
1112 | }; | ||
1113 | |||
1114 | map->s_uspace.s_table = | ||
1115 | udf_iget(sb, loc); | ||
1116 | if (!map->s_uspace.s_table) { | ||
1117 | udf_debug("cannot load unallocSpaceTable (part %d)\n", i); | ||
1118 | return 1; | ||
1119 | } | ||
1120 | map->s_partition_flags |= | ||
1121 | UDF_PART_FLAG_UNALLOC_TABLE; | ||
1122 | udf_debug("unallocSpaceTable (part %d) @ %ld\n", | ||
1123 | i, map->s_uspace.s_table->i_ino); | ||
1124 | } | ||
1125 | if (phd->unallocSpaceBitmap.extLength) { | ||
1126 | struct udf_bitmap *bitmap = | ||
1127 | udf_sb_alloc_bitmap(sb, i); | ||
1128 | map->s_uspace.s_bitmap = bitmap; | ||
1129 | if (bitmap != NULL) { | ||
1130 | bitmap->s_extLength = | ||
1131 | le32_to_cpu(phd->unallocSpaceBitmap.extLength); | ||
1132 | bitmap->s_extPosition = | ||
1133 | le32_to_cpu(phd->unallocSpaceBitmap.extPosition); | ||
1134 | map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP; | ||
1135 | udf_debug("unallocSpaceBitmap (part %d) @ %d\n", | ||
1136 | i, bitmap->s_extPosition); | ||
1137 | } | ||
1138 | } | ||
1139 | if (phd->partitionIntegrityTable.extLength) | ||
1140 | udf_debug("partitionIntegrityTable (part %d)\n", i); | ||
1141 | if (phd->freedSpaceTable.extLength) { | ||
1142 | kernel_lb_addr loc = { | ||
1143 | .logicalBlockNum = le32_to_cpu(phd->freedSpaceTable.extPosition), | ||
1144 | .partitionReferenceNum = i, | ||
1145 | }; | ||
1146 | |||
1147 | map->s_fspace.s_table = | ||
1148 | udf_iget(sb, loc); | ||
1149 | if (!map->s_fspace.s_table) { | ||
1150 | udf_debug("cannot load freedSpaceTable (part %d)\n", i); | ||
1151 | return 1; | ||
1152 | } | ||
1153 | map->s_partition_flags |= | ||
1154 | UDF_PART_FLAG_FREED_TABLE; | ||
1155 | udf_debug("freedSpaceTable (part %d) @ %ld\n", | ||
1156 | i, map->s_fspace.s_table->i_ino); | ||
1157 | } | ||
1158 | if (phd->freedSpaceBitmap.extLength) { | ||
1159 | struct udf_bitmap *bitmap = | ||
1160 | udf_sb_alloc_bitmap(sb, i); | ||
1161 | map->s_fspace.s_bitmap = bitmap; | ||
1162 | if (bitmap != NULL) { | ||
1163 | bitmap->s_extLength = | ||
1164 | le32_to_cpu(phd->freedSpaceBitmap.extLength); | ||
1165 | bitmap->s_extPosition = | ||
1166 | le32_to_cpu(phd->freedSpaceBitmap.extPosition); | ||
1167 | map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP; | ||
1168 | udf_debug("freedSpaceBitmap (part %d) @ %d\n", | ||
1169 | i, bitmap->s_extPosition); | ||
1170 | } | ||
1171 | } | ||
1172 | } | ||
1173 | break; | 1275 | break; |
1174 | } | ||
1175 | } | 1276 | } |
1176 | if (i == sbi->s_partitions) | 1277 | |
1278 | if (i >= sbi->s_partitions) { | ||
1177 | udf_debug("Partition (%d) not found in partition map\n", | 1279 | udf_debug("Partition (%d) not found in partition map\n", |
1178 | le16_to_cpu(p->partitionNumber)); | 1280 | partitionNumber); |
1179 | else | 1281 | goto out_bh; |
1180 | udf_debug("Partition (%d:%d type %x) starts at physical %d, " | 1282 | } |
1181 | "block length %d\n", | 1283 | |
1182 | le16_to_cpu(p->partitionNumber), i, | 1284 | ret = udf_fill_partdesc_info(sb, p, i); |
1183 | map->s_partition_type, | 1285 | |
1184 | map->s_partition_root, | 1286 | /* |
1185 | map->s_partition_len); | 1287 | * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and |
1186 | return 0; | 1288 | * PHYSICAL partitions are already set up |
1289 | */ | ||
1290 | type1_idx = i; | ||
1291 | for (i = 0; i < sbi->s_partitions; i++) { | ||
1292 | map = &sbi->s_partmaps[i]; | ||
1293 | |||
1294 | if (map->s_partition_num == partitionNumber && | ||
1295 | (map->s_partition_type == UDF_VIRTUAL_MAP15 || | ||
1296 | map->s_partition_type == UDF_VIRTUAL_MAP20 || | ||
1297 | map->s_partition_type == UDF_METADATA_MAP25)) | ||
1298 | break; | ||
1299 | } | ||
1300 | |||
1301 | if (i >= sbi->s_partitions) | ||
1302 | goto out_bh; | ||
1303 | |||
1304 | ret = udf_fill_partdesc_info(sb, p, i); | ||
1305 | if (ret) | ||
1306 | goto out_bh; | ||
1307 | |||
1308 | if (map->s_partition_type == UDF_METADATA_MAP25) { | ||
1309 | ret = udf_load_metadata_files(sb, i); | ||
1310 | if (ret) { | ||
1311 | printk(KERN_ERR "UDF-fs: error loading MetaData " | ||
1312 | "partition map %d\n", i); | ||
1313 | goto out_bh; | ||
1314 | } | ||
1315 | } else { | ||
1316 | ret = udf_load_vat(sb, i, type1_idx); | ||
1317 | if (ret) | ||
1318 | goto out_bh; | ||
1319 | /* | ||
1320 | * Mark filesystem read-only if we have a partition with | ||
1321 | * virtual map since we don't handle writing to it (we | ||
1322 | * overwrite blocks instead of relocating them). | ||
1323 | */ | ||
1324 | sb->s_flags |= MS_RDONLY; | ||
1325 | printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only " | ||
1326 | "because writing to pseudooverwrite partition is " | ||
1327 | "not implemented.\n"); | ||
1328 | } | ||
1329 | out_bh: | ||
1330 | /* In case loading failed, we handle cleanup in udf_fill_super */ | ||
1331 | brelse(bh); | ||
1332 | return ret; | ||
1187 | } | 1333 | } |
1188 | 1334 | ||
1189 | static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | 1335 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
1190 | kernel_lb_addr *fileset) | 1336 | kernel_lb_addr *fileset) |
1191 | { | 1337 | { |
1192 | struct logicalVolDesc *lvd; | 1338 | struct logicalVolDesc *lvd; |
@@ -1194,12 +1340,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1194 | uint8_t type; | 1340 | uint8_t type; |
1195 | struct udf_sb_info *sbi = UDF_SB(sb); | 1341 | struct udf_sb_info *sbi = UDF_SB(sb); |
1196 | struct genericPartitionMap *gpm; | 1342 | struct genericPartitionMap *gpm; |
1343 | uint16_t ident; | ||
1344 | struct buffer_head *bh; | ||
1345 | int ret = 0; | ||
1197 | 1346 | ||
1347 | bh = udf_read_tagged(sb, block, block, &ident); | ||
1348 | if (!bh) | ||
1349 | return 1; | ||
1350 | BUG_ON(ident != TAG_IDENT_LVD); | ||
1198 | lvd = (struct logicalVolDesc *)bh->b_data; | 1351 | lvd = (struct logicalVolDesc *)bh->b_data; |
1199 | 1352 | ||
1200 | i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); | 1353 | i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); |
1201 | if (i != 0) | 1354 | if (i != 0) { |
1202 | return i; | 1355 | ret = i; |
1356 | goto out_bh; | ||
1357 | } | ||
1203 | 1358 | ||
1204 | for (i = 0, offset = 0; | 1359 | for (i = 0, offset = 0; |
1205 | i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); | 1360 | i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); |
@@ -1223,12 +1378,12 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1223 | u16 suf = | 1378 | u16 suf = |
1224 | le16_to_cpu(((__le16 *)upm2->partIdent. | 1379 | le16_to_cpu(((__le16 *)upm2->partIdent. |
1225 | identSuffix)[0]); | 1380 | identSuffix)[0]); |
1226 | if (suf == 0x0150) { | 1381 | if (suf < 0x0200) { |
1227 | map->s_partition_type = | 1382 | map->s_partition_type = |
1228 | UDF_VIRTUAL_MAP15; | 1383 | UDF_VIRTUAL_MAP15; |
1229 | map->s_partition_func = | 1384 | map->s_partition_func = |
1230 | udf_get_pblock_virt15; | 1385 | udf_get_pblock_virt15; |
1231 | } else if (suf == 0x0200) { | 1386 | } else { |
1232 | map->s_partition_type = | 1387 | map->s_partition_type = |
1233 | UDF_VIRTUAL_MAP20; | 1388 | UDF_VIRTUAL_MAP20; |
1234 | map->s_partition_func = | 1389 | map->s_partition_func = |
@@ -1238,7 +1393,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1238 | UDF_ID_SPARABLE, | 1393 | UDF_ID_SPARABLE, |
1239 | strlen(UDF_ID_SPARABLE))) { | 1394 | strlen(UDF_ID_SPARABLE))) { |
1240 | uint32_t loc; | 1395 | uint32_t loc; |
1241 | uint16_t ident; | ||
1242 | struct sparingTable *st; | 1396 | struct sparingTable *st; |
1243 | struct sparablePartitionMap *spm = | 1397 | struct sparablePartitionMap *spm = |
1244 | (struct sparablePartitionMap *)gpm; | 1398 | (struct sparablePartitionMap *)gpm; |
@@ -1256,22 +1410,64 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1256 | map->s_type_specific.s_sparing. | 1410 | map->s_type_specific.s_sparing. |
1257 | s_spar_map[j] = bh2; | 1411 | s_spar_map[j] = bh2; |
1258 | 1412 | ||
1259 | if (bh2 != NULL) { | 1413 | if (bh2 == NULL) |
1260 | st = (struct sparingTable *) | 1414 | continue; |
1261 | bh2->b_data; | 1415 | |
1262 | if (ident != 0 || strncmp( | 1416 | st = (struct sparingTable *)bh2->b_data; |
1263 | st->sparingIdent.ident, | 1417 | if (ident != 0 || strncmp( |
1264 | UDF_ID_SPARING, | 1418 | st->sparingIdent.ident, |
1265 | strlen(UDF_ID_SPARING))) { | 1419 | UDF_ID_SPARING, |
1266 | brelse(bh2); | 1420 | strlen(UDF_ID_SPARING))) { |
1267 | map->s_type_specific. | 1421 | brelse(bh2); |
1268 | s_sparing. | 1422 | map->s_type_specific.s_sparing. |
1269 | s_spar_map[j] = | 1423 | s_spar_map[j] = NULL; |
1270 | NULL; | ||
1271 | } | ||
1272 | } | 1424 | } |
1273 | } | 1425 | } |
1274 | map->s_partition_func = udf_get_pblock_spar15; | 1426 | map->s_partition_func = udf_get_pblock_spar15; |
1427 | } else if (!strncmp(upm2->partIdent.ident, | ||
1428 | UDF_ID_METADATA, | ||
1429 | strlen(UDF_ID_METADATA))) { | ||
1430 | struct udf_meta_data *mdata = | ||
1431 | &map->s_type_specific.s_metadata; | ||
1432 | struct metadataPartitionMap *mdm = | ||
1433 | (struct metadataPartitionMap *) | ||
1434 | &(lvd->partitionMaps[offset]); | ||
1435 | udf_debug("Parsing Logical vol part %d " | ||
1436 | "type %d id=%s\n", i, type, | ||
1437 | UDF_ID_METADATA); | ||
1438 | |||
1439 | map->s_partition_type = UDF_METADATA_MAP25; | ||
1440 | map->s_partition_func = udf_get_pblock_meta25; | ||
1441 | |||
1442 | mdata->s_meta_file_loc = | ||
1443 | le32_to_cpu(mdm->metadataFileLoc); | ||
1444 | mdata->s_mirror_file_loc = | ||
1445 | le32_to_cpu(mdm->metadataMirrorFileLoc); | ||
1446 | mdata->s_bitmap_file_loc = | ||
1447 | le32_to_cpu(mdm->metadataBitmapFileLoc); | ||
1448 | mdata->s_alloc_unit_size = | ||
1449 | le32_to_cpu(mdm->allocUnitSize); | ||
1450 | mdata->s_align_unit_size = | ||
1451 | le16_to_cpu(mdm->alignUnitSize); | ||
1452 | mdata->s_dup_md_flag = | ||
1453 | mdm->flags & 0x01; | ||
1454 | |||
1455 | udf_debug("Metadata Ident suffix=0x%x\n", | ||
1456 | (le16_to_cpu( | ||
1457 | ((__le16 *) | ||
1458 | mdm->partIdent.identSuffix)[0]))); | ||
1459 | udf_debug("Metadata part num=%d\n", | ||
1460 | le16_to_cpu(mdm->partitionNum)); | ||
1461 | udf_debug("Metadata part alloc unit size=%d\n", | ||
1462 | le32_to_cpu(mdm->allocUnitSize)); | ||
1463 | udf_debug("Metadata file loc=%d\n", | ||
1464 | le32_to_cpu(mdm->metadataFileLoc)); | ||
1465 | udf_debug("Mirror file loc=%d\n", | ||
1466 | le32_to_cpu(mdm->metadataMirrorFileLoc)); | ||
1467 | udf_debug("Bitmap file loc=%d\n", | ||
1468 | le32_to_cpu(mdm->metadataBitmapFileLoc)); | ||
1469 | udf_debug("Duplicate Flag: %d %d\n", | ||
1470 | mdata->s_dup_md_flag, mdm->flags); | ||
1275 | } else { | 1471 | } else { |
1276 | udf_debug("Unknown ident: %s\n", | 1472 | udf_debug("Unknown ident: %s\n", |
1277 | upm2->partIdent.ident); | 1473 | upm2->partIdent.ident); |
@@ -1296,7 +1492,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh, | |||
1296 | if (lvd->integritySeqExt.extLength) | 1492 | if (lvd->integritySeqExt.extLength) |
1297 | udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); | 1493 | udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); |
1298 | 1494 | ||
1299 | return 0; | 1495 | out_bh: |
1496 | brelse(bh); | ||
1497 | return ret; | ||
1300 | } | 1498 | } |
1301 | 1499 | ||
1302 | /* | 1500 | /* |
@@ -1345,7 +1543,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc) | |||
1345 | * July 1, 1997 - Andrew E. Mileski | 1543 | * July 1, 1997 - Andrew E. Mileski |
1346 | * Written, tested, and released. | 1544 | * Written, tested, and released. |
1347 | */ | 1545 | */ |
1348 | static int udf_process_sequence(struct super_block *sb, long block, | 1546 | static noinline int udf_process_sequence(struct super_block *sb, long block, |
1349 | long lastblock, kernel_lb_addr *fileset) | 1547 | long lastblock, kernel_lb_addr *fileset) |
1350 | { | 1548 | { |
1351 | struct buffer_head *bh = NULL; | 1549 | struct buffer_head *bh = NULL; |
@@ -1354,19 +1552,25 @@ static int udf_process_sequence(struct super_block *sb, long block, | |||
1354 | struct generic_desc *gd; | 1552 | struct generic_desc *gd; |
1355 | struct volDescPtr *vdp; | 1553 | struct volDescPtr *vdp; |
1356 | int done = 0; | 1554 | int done = 0; |
1357 | int i, j; | ||
1358 | uint32_t vdsn; | 1555 | uint32_t vdsn; |
1359 | uint16_t ident; | 1556 | uint16_t ident; |
1360 | long next_s = 0, next_e = 0; | 1557 | long next_s = 0, next_e = 0; |
1361 | 1558 | ||
1362 | memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); | 1559 | memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); |
1363 | 1560 | ||
1364 | /* Read the main descriptor sequence */ | 1561 | /* |
1562 | * Read the main descriptor sequence and find which descriptors | ||
1563 | * are in it. | ||
1564 | */ | ||
1365 | for (; (!done && block <= lastblock); block++) { | 1565 | for (; (!done && block <= lastblock); block++) { |
1366 | 1566 | ||
1367 | bh = udf_read_tagged(sb, block, block, &ident); | 1567 | bh = udf_read_tagged(sb, block, block, &ident); |
1368 | if (!bh) | 1568 | if (!bh) { |
1369 | break; | 1569 | printk(KERN_ERR "udf: Block %Lu of volume descriptor " |
1570 | "sequence is corrupted or we could not read " | ||
1571 | "it.\n", (unsigned long long)block); | ||
1572 | return 1; | ||
1573 | } | ||
1370 | 1574 | ||
1371 | /* Process each descriptor (ISO 13346 3/8.3-8.4) */ | 1575 | /* Process each descriptor (ISO 13346 3/8.3-8.4) */ |
1372 | gd = (struct generic_desc *)bh->b_data; | 1576 | gd = (struct generic_desc *)bh->b_data; |
@@ -1432,41 +1636,31 @@ static int udf_process_sequence(struct super_block *sb, long block, | |||
1432 | } | 1636 | } |
1433 | brelse(bh); | 1637 | brelse(bh); |
1434 | } | 1638 | } |
1435 | for (i = 0; i < VDS_POS_LENGTH; i++) { | 1639 | /* |
1436 | if (vds[i].block) { | 1640 | * Now read interesting descriptors again and process them |
1437 | bh = udf_read_tagged(sb, vds[i].block, vds[i].block, | 1641 | * in a suitable order |
1438 | &ident); | 1642 | */ |
1439 | 1643 | if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) { | |
1440 | if (i == VDS_POS_PRIMARY_VOL_DESC) { | 1644 | printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n"); |
1441 | udf_load_pvoldesc(sb, bh); | 1645 | return 1; |
1442 | } else if (i == VDS_POS_LOGICAL_VOL_DESC) { | 1646 | } |
1443 | if (udf_load_logicalvol(sb, bh, fileset)) { | 1647 | if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block)) |
1444 | brelse(bh); | 1648 | return 1; |
1445 | return 1; | 1649 | |
1446 | } | 1650 | if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb, |
1447 | } else if (i == VDS_POS_PARTITION_DESC) { | 1651 | vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset)) |
1448 | struct buffer_head *bh2 = NULL; | 1652 | return 1; |
1449 | if (udf_load_partdesc(sb, bh)) { | 1653 | |
1450 | brelse(bh); | 1654 | if (vds[VDS_POS_PARTITION_DESC].block) { |
1451 | return 1; | 1655 | /* |
1452 | } | 1656 | * We rescan the whole descriptor sequence to find |
1453 | for (j = vds[i].block + 1; | 1657 | * partition descriptor blocks and process them. |
1454 | j < vds[VDS_POS_TERMINATING_DESC].block; | 1658 | */ |
1455 | j++) { | 1659 | for (block = vds[VDS_POS_PARTITION_DESC].block; |
1456 | bh2 = udf_read_tagged(sb, j, j, &ident); | 1660 | block < vds[VDS_POS_TERMINATING_DESC].block; |
1457 | gd = (struct generic_desc *)bh2->b_data; | 1661 | block++) |
1458 | if (ident == TAG_IDENT_PD) | 1662 | if (udf_load_partdesc(sb, block)) |
1459 | if (udf_load_partdesc(sb, | 1663 | return 1; |
1460 | bh2)) { | ||
1461 | brelse(bh); | ||
1462 | brelse(bh2); | ||
1463 | return 1; | ||
1464 | } | ||
1465 | brelse(bh2); | ||
1466 | } | ||
1467 | } | ||
1468 | brelse(bh); | ||
1469 | } | ||
1470 | } | 1664 | } |
1471 | 1665 | ||
1472 | return 0; | 1666 | return 0; |
@@ -1478,6 +1672,7 @@ static int udf_process_sequence(struct super_block *sb, long block, | |||
1478 | static int udf_check_valid(struct super_block *sb, int novrs, int silent) | 1672 | static int udf_check_valid(struct super_block *sb, int novrs, int silent) |
1479 | { | 1673 | { |
1480 | long block; | 1674 | long block; |
1675 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1481 | 1676 | ||
1482 | if (novrs) { | 1677 | if (novrs) { |
1483 | udf_debug("Validity check skipped because of novrs option\n"); | 1678 | udf_debug("Validity check skipped because of novrs option\n"); |
@@ -1485,27 +1680,22 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent) | |||
1485 | } | 1680 | } |
1486 | /* Check that it is NSR02 compliant */ | 1681 | /* Check that it is NSR02 compliant */ |
1487 | /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ | 1682 | /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ |
1488 | else { | 1683 | block = udf_vrs(sb, silent); |
1489 | block = udf_vrs(sb, silent); | 1684 | if (block == -1) |
1490 | if (block == -1) { | 1685 | udf_debug("Failed to read byte 32768. Assuming open " |
1491 | struct udf_sb_info *sbi = UDF_SB(sb); | 1686 | "disc. Skipping validity check\n"); |
1492 | udf_debug("Failed to read byte 32768. Assuming open " | 1687 | if (block && !sbi->s_last_block) |
1493 | "disc. Skipping validity check\n"); | 1688 | sbi->s_last_block = udf_get_last_block(sb); |
1494 | if (!sbi->s_last_block) | 1689 | return !block; |
1495 | sbi->s_last_block = udf_get_last_block(sb); | ||
1496 | return 0; | ||
1497 | } else | ||
1498 | return !block; | ||
1499 | } | ||
1500 | } | 1690 | } |
1501 | 1691 | ||
1502 | static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | 1692 | static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset) |
1503 | { | 1693 | { |
1504 | struct anchorVolDescPtr *anchor; | 1694 | struct anchorVolDescPtr *anchor; |
1505 | uint16_t ident; | 1695 | uint16_t ident; |
1506 | struct buffer_head *bh; | 1696 | struct buffer_head *bh; |
1507 | long main_s, main_e, reserve_s, reserve_e; | 1697 | long main_s, main_e, reserve_s, reserve_e; |
1508 | int i, j; | 1698 | int i; |
1509 | struct udf_sb_info *sbi; | 1699 | struct udf_sb_info *sbi; |
1510 | 1700 | ||
1511 | if (!sb) | 1701 | if (!sb) |
@@ -1515,6 +1705,7 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | |||
1515 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { | 1705 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { |
1516 | if (!sbi->s_anchor[i]) | 1706 | if (!sbi->s_anchor[i]) |
1517 | continue; | 1707 | continue; |
1708 | |||
1518 | bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i], | 1709 | bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i], |
1519 | &ident); | 1710 | &ident); |
1520 | if (!bh) | 1711 | if (!bh) |
@@ -1553,76 +1744,6 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset) | |||
1553 | } | 1744 | } |
1554 | udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); | 1745 | udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); |
1555 | 1746 | ||
1556 | for (i = 0; i < sbi->s_partitions; i++) { | ||
1557 | kernel_lb_addr uninitialized_var(ino); | ||
1558 | struct udf_part_map *map = &sbi->s_partmaps[i]; | ||
1559 | switch (map->s_partition_type) { | ||
1560 | case UDF_VIRTUAL_MAP15: | ||
1561 | case UDF_VIRTUAL_MAP20: | ||
1562 | if (!sbi->s_last_block) { | ||
1563 | sbi->s_last_block = udf_get_last_block(sb); | ||
1564 | udf_find_anchor(sb); | ||
1565 | } | ||
1566 | |||
1567 | if (!sbi->s_last_block) { | ||
1568 | udf_debug("Unable to determine Lastblock (For " | ||
1569 | "Virtual Partition)\n"); | ||
1570 | return 1; | ||
1571 | } | ||
1572 | |||
1573 | for (j = 0; j < sbi->s_partitions; j++) { | ||
1574 | struct udf_part_map *map2 = &sbi->s_partmaps[j]; | ||
1575 | if (j != i && | ||
1576 | map->s_volumeseqnum == | ||
1577 | map2->s_volumeseqnum && | ||
1578 | map->s_partition_num == | ||
1579 | map2->s_partition_num) { | ||
1580 | ino.partitionReferenceNum = j; | ||
1581 | ino.logicalBlockNum = | ||
1582 | sbi->s_last_block - | ||
1583 | map2->s_partition_root; | ||
1584 | break; | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | if (j == sbi->s_partitions) | ||
1589 | return 1; | ||
1590 | |||
1591 | sbi->s_vat_inode = udf_iget(sb, ino); | ||
1592 | if (!sbi->s_vat_inode) | ||
1593 | return 1; | ||
1594 | |||
1595 | if (map->s_partition_type == UDF_VIRTUAL_MAP15) { | ||
1596 | map->s_type_specific.s_virtual.s_start_offset = | ||
1597 | udf_ext0_offset(sbi->s_vat_inode); | ||
1598 | map->s_type_specific.s_virtual.s_num_entries = | ||
1599 | (sbi->s_vat_inode->i_size - 36) >> 2; | ||
1600 | } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) { | ||
1601 | uint32_t pos; | ||
1602 | struct virtualAllocationTable20 *vat20; | ||
1603 | |||
1604 | pos = udf_block_map(sbi->s_vat_inode, 0); | ||
1605 | bh = sb_bread(sb, pos); | ||
1606 | if (!bh) | ||
1607 | return 1; | ||
1608 | vat20 = (struct virtualAllocationTable20 *) | ||
1609 | bh->b_data + | ||
1610 | udf_ext0_offset(sbi->s_vat_inode); | ||
1611 | map->s_type_specific.s_virtual.s_start_offset = | ||
1612 | le16_to_cpu(vat20->lengthHeader) + | ||
1613 | udf_ext0_offset(sbi->s_vat_inode); | ||
1614 | map->s_type_specific.s_virtual.s_num_entries = | ||
1615 | (sbi->s_vat_inode->i_size - | ||
1616 | map->s_type_specific.s_virtual. | ||
1617 | s_start_offset) >> 2; | ||
1618 | brelse(bh); | ||
1619 | } | ||
1620 | map->s_partition_root = udf_get_pblock(sb, 0, i, 0); | ||
1621 | map->s_partition_len = | ||
1622 | sbi->s_partmaps[ino.partitionReferenceNum]. | ||
1623 | s_partition_len; | ||
1624 | } | ||
1625 | } | ||
1626 | return 0; | 1747 | return 0; |
1627 | } | 1748 | } |
1628 | 1749 | ||
@@ -1630,65 +1751,61 @@ static void udf_open_lvid(struct super_block *sb) | |||
1630 | { | 1751 | { |
1631 | struct udf_sb_info *sbi = UDF_SB(sb); | 1752 | struct udf_sb_info *sbi = UDF_SB(sb); |
1632 | struct buffer_head *bh = sbi->s_lvid_bh; | 1753 | struct buffer_head *bh = sbi->s_lvid_bh; |
1633 | if (bh) { | 1754 | struct logicalVolIntegrityDesc *lvid; |
1634 | kernel_timestamp cpu_time; | 1755 | struct logicalVolIntegrityDescImpUse *lvidiu; |
1635 | struct logicalVolIntegrityDesc *lvid = | 1756 | if (!bh) |
1636 | (struct logicalVolIntegrityDesc *)bh->b_data; | 1757 | return; |
1637 | struct logicalVolIntegrityDescImpUse *lvidiu = | ||
1638 | udf_sb_lvidiu(sbi); | ||
1639 | 1758 | ||
1640 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1759 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
1641 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1760 | lvidiu = udf_sb_lvidiu(sbi); |
1642 | if (udf_time_to_stamp(&cpu_time, CURRENT_TIME)) | ||
1643 | lvid->recordingDateAndTime = cpu_to_lets(cpu_time); | ||
1644 | lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; | ||
1645 | 1761 | ||
1646 | lvid->descTag.descCRC = cpu_to_le16( | 1762 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
1647 | udf_crc((char *)lvid + sizeof(tag), | 1763 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
1648 | le16_to_cpu(lvid->descTag.descCRCLength), | 1764 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, |
1649 | 0)); | 1765 | CURRENT_TIME); |
1766 | lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; | ||
1650 | 1767 | ||
1651 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | 1768 | lvid->descTag.descCRC = cpu_to_le16( |
1652 | mark_buffer_dirty(bh); | 1769 | crc_itu_t(0, (char *)lvid + sizeof(tag), |
1653 | } | 1770 | le16_to_cpu(lvid->descTag.descCRCLength))); |
1771 | |||
1772 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | ||
1773 | mark_buffer_dirty(bh); | ||
1654 | } | 1774 | } |
1655 | 1775 | ||
1656 | static void udf_close_lvid(struct super_block *sb) | 1776 | static void udf_close_lvid(struct super_block *sb) |
1657 | { | 1777 | { |
1658 | kernel_timestamp cpu_time; | ||
1659 | struct udf_sb_info *sbi = UDF_SB(sb); | 1778 | struct udf_sb_info *sbi = UDF_SB(sb); |
1660 | struct buffer_head *bh = sbi->s_lvid_bh; | 1779 | struct buffer_head *bh = sbi->s_lvid_bh; |
1661 | struct logicalVolIntegrityDesc *lvid; | 1780 | struct logicalVolIntegrityDesc *lvid; |
1781 | struct logicalVolIntegrityDescImpUse *lvidiu; | ||
1662 | 1782 | ||
1663 | if (!bh) | 1783 | if (!bh) |
1664 | return; | 1784 | return; |
1665 | 1785 | ||
1666 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | 1786 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
1667 | 1787 | ||
1668 | if (lvid->integrityType == LVID_INTEGRITY_TYPE_OPEN) { | 1788 | if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN) |
1669 | struct logicalVolIntegrityDescImpUse *lvidiu = | 1789 | return; |
1670 | udf_sb_lvidiu(sbi); | 1790 | |
1671 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1791 | lvidiu = udf_sb_lvidiu(sbi); |
1672 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1792 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
1673 | if (udf_time_to_stamp(&cpu_time, CURRENT_TIME)) | 1793 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
1674 | lvid->recordingDateAndTime = cpu_to_lets(cpu_time); | 1794 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); |
1675 | if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) | 1795 | if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) |
1676 | lvidiu->maxUDFWriteRev = | 1796 | lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); |
1677 | cpu_to_le16(UDF_MAX_WRITE_VERSION); | 1797 | if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev)) |
1678 | if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev)) | 1798 | lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev); |
1679 | lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev); | 1799 | if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev)) |
1680 | if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev)) | 1800 | lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev); |
1681 | lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev); | 1801 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); |
1682 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); | 1802 | |
1683 | 1803 | lvid->descTag.descCRC = cpu_to_le16( | |
1684 | lvid->descTag.descCRC = cpu_to_le16( | 1804 | crc_itu_t(0, (char *)lvid + sizeof(tag), |
1685 | udf_crc((char *)lvid + sizeof(tag), | 1805 | le16_to_cpu(lvid->descTag.descCRCLength))); |
1686 | le16_to_cpu(lvid->descTag.descCRCLength), | 1806 | |
1687 | 0)); | 1807 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
1688 | 1808 | mark_buffer_dirty(bh); | |
1689 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | ||
1690 | mark_buffer_dirty(bh); | ||
1691 | } | ||
1692 | } | 1809 | } |
1693 | 1810 | ||
1694 | static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) | 1811 | static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) |
@@ -1708,22 +1825,35 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) | |||
1708 | vfree(bitmap); | 1825 | vfree(bitmap); |
1709 | } | 1826 | } |
1710 | 1827 | ||
1711 | /* | 1828 | static void udf_free_partition(struct udf_part_map *map) |
1712 | * udf_read_super | 1829 | { |
1713 | * | 1830 | int i; |
1714 | * PURPOSE | 1831 | struct udf_meta_data *mdata; |
1715 | * Complete the specified super block. | 1832 | |
1716 | * | 1833 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) |
1717 | * PRE-CONDITIONS | 1834 | iput(map->s_uspace.s_table); |
1718 | * sb Pointer to superblock to complete - never NULL. | 1835 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) |
1719 | * sb->s_dev Device to read suberblock from. | 1836 | iput(map->s_fspace.s_table); |
1720 | * options Pointer to mount options. | 1837 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) |
1721 | * silent Silent flag. | 1838 | udf_sb_free_bitmap(map->s_uspace.s_bitmap); |
1722 | * | 1839 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) |
1723 | * HISTORY | 1840 | udf_sb_free_bitmap(map->s_fspace.s_bitmap); |
1724 | * July 1, 1997 - Andrew E. Mileski | 1841 | if (map->s_partition_type == UDF_SPARABLE_MAP15) |
1725 | * Written, tested, and released. | 1842 | for (i = 0; i < 4; i++) |
1726 | */ | 1843 | brelse(map->s_type_specific.s_sparing.s_spar_map[i]); |
1844 | else if (map->s_partition_type == UDF_METADATA_MAP25) { | ||
1845 | mdata = &map->s_type_specific.s_metadata; | ||
1846 | iput(mdata->s_metadata_fe); | ||
1847 | mdata->s_metadata_fe = NULL; | ||
1848 | |||
1849 | iput(mdata->s_mirror_fe); | ||
1850 | mdata->s_mirror_fe = NULL; | ||
1851 | |||
1852 | iput(mdata->s_bitmap_fe); | ||
1853 | mdata->s_bitmap_fe = NULL; | ||
1854 | } | ||
1855 | } | ||
1856 | |||
1727 | static int udf_fill_super(struct super_block *sb, void *options, int silent) | 1857 | static int udf_fill_super(struct super_block *sb, void *options, int silent) |
1728 | { | 1858 | { |
1729 | int i; | 1859 | int i; |
@@ -1776,8 +1906,11 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1776 | sbi->s_nls_map = uopt.nls_map; | 1906 | sbi->s_nls_map = uopt.nls_map; |
1777 | 1907 | ||
1778 | /* Set the block size for all transfers */ | 1908 | /* Set the block size for all transfers */ |
1779 | if (!udf_set_blocksize(sb, uopt.blocksize)) | 1909 | if (!sb_min_blocksize(sb, uopt.blocksize)) { |
1910 | udf_debug("Bad block size (%d)\n", uopt.blocksize); | ||
1911 | printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize); | ||
1780 | goto error_out; | 1912 | goto error_out; |
1913 | } | ||
1781 | 1914 | ||
1782 | if (uopt.session == 0xFFFFFFFF) | 1915 | if (uopt.session == 0xFFFFFFFF) |
1783 | sbi->s_session = udf_get_last_session(sb); | 1916 | sbi->s_session = udf_get_last_session(sb); |
@@ -1789,7 +1922,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1789 | sbi->s_last_block = uopt.lastblock; | 1922 | sbi->s_last_block = uopt.lastblock; |
1790 | sbi->s_anchor[0] = sbi->s_anchor[1] = 0; | 1923 | sbi->s_anchor[0] = sbi->s_anchor[1] = 0; |
1791 | sbi->s_anchor[2] = uopt.anchor; | 1924 | sbi->s_anchor[2] = uopt.anchor; |
1792 | sbi->s_anchor[3] = 256; | ||
1793 | 1925 | ||
1794 | if (udf_check_valid(sb, uopt.novrs, silent)) { | 1926 | if (udf_check_valid(sb, uopt.novrs, silent)) { |
1795 | /* read volume recognition sequences */ | 1927 | /* read volume recognition sequences */ |
@@ -1806,7 +1938,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1806 | sb->s_magic = UDF_SUPER_MAGIC; | 1938 | sb->s_magic = UDF_SUPER_MAGIC; |
1807 | sb->s_time_gran = 1000; | 1939 | sb->s_time_gran = 1000; |
1808 | 1940 | ||
1809 | if (udf_load_partition(sb, &fileset)) { | 1941 | if (udf_load_sequence(sb, &fileset)) { |
1810 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); | 1942 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); |
1811 | goto error_out; | 1943 | goto error_out; |
1812 | } | 1944 | } |
@@ -1856,12 +1988,12 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1856 | } | 1988 | } |
1857 | 1989 | ||
1858 | if (!silent) { | 1990 | if (!silent) { |
1859 | kernel_timestamp ts; | 1991 | timestamp ts; |
1860 | udf_time_to_stamp(&ts, sbi->s_record_time); | 1992 | udf_time_to_disk_stamp(&ts, sbi->s_record_time); |
1861 | udf_info("UDF: Mounting volume '%s', " | 1993 | udf_info("UDF: Mounting volume '%s', " |
1862 | "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", | 1994 | "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", |
1863 | sbi->s_volume_ident, ts.year, ts.month, ts.day, | 1995 | sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day, |
1864 | ts.hour, ts.minute, ts.typeAndTimezone); | 1996 | ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone)); |
1865 | } | 1997 | } |
1866 | if (!(sb->s_flags & MS_RDONLY)) | 1998 | if (!(sb->s_flags & MS_RDONLY)) |
1867 | udf_open_lvid(sb); | 1999 | udf_open_lvid(sb); |
@@ -1890,21 +2022,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1890 | error_out: | 2022 | error_out: |
1891 | if (sbi->s_vat_inode) | 2023 | if (sbi->s_vat_inode) |
1892 | iput(sbi->s_vat_inode); | 2024 | iput(sbi->s_vat_inode); |
1893 | if (sbi->s_partitions) { | 2025 | if (sbi->s_partitions) |
1894 | struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition]; | 2026 | for (i = 0; i < sbi->s_partitions; i++) |
1895 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) | 2027 | udf_free_partition(&sbi->s_partmaps[i]); |
1896 | iput(map->s_uspace.s_table); | ||
1897 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) | ||
1898 | iput(map->s_fspace.s_table); | ||
1899 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) | ||
1900 | udf_sb_free_bitmap(map->s_uspace.s_bitmap); | ||
1901 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) | ||
1902 | udf_sb_free_bitmap(map->s_fspace.s_bitmap); | ||
1903 | if (map->s_partition_type == UDF_SPARABLE_MAP15) | ||
1904 | for (i = 0; i < 4; i++) | ||
1905 | brelse(map->s_type_specific.s_sparing. | ||
1906 | s_spar_map[i]); | ||
1907 | } | ||
1908 | #ifdef CONFIG_UDF_NLS | 2028 | #ifdef CONFIG_UDF_NLS |
1909 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) | 2029 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) |
1910 | unload_nls(sbi->s_nls_map); | 2030 | unload_nls(sbi->s_nls_map); |
@@ -1920,8 +2040,8 @@ error_out: | |||
1920 | return -EINVAL; | 2040 | return -EINVAL; |
1921 | } | 2041 | } |
1922 | 2042 | ||
1923 | void udf_error(struct super_block *sb, const char *function, | 2043 | static void udf_error(struct super_block *sb, const char *function, |
1924 | const char *fmt, ...) | 2044 | const char *fmt, ...) |
1925 | { | 2045 | { |
1926 | va_list args; | 2046 | va_list args; |
1927 | 2047 | ||
@@ -1948,19 +2068,6 @@ void udf_warning(struct super_block *sb, const char *function, | |||
1948 | sb->s_id, function, error_buf); | 2068 | sb->s_id, function, error_buf); |
1949 | } | 2069 | } |
1950 | 2070 | ||
1951 | /* | ||
1952 | * udf_put_super | ||
1953 | * | ||
1954 | * PURPOSE | ||
1955 | * Prepare for destruction of the superblock. | ||
1956 | * | ||
1957 | * DESCRIPTION | ||
1958 | * Called before the filesystem is unmounted. | ||
1959 | * | ||
1960 | * HISTORY | ||
1961 | * July 1, 1997 - Andrew E. Mileski | ||
1962 | * Written, tested, and released. | ||
1963 | */ | ||
1964 | static void udf_put_super(struct super_block *sb) | 2071 | static void udf_put_super(struct super_block *sb) |
1965 | { | 2072 | { |
1966 | int i; | 2073 | int i; |
@@ -1969,21 +2076,9 @@ static void udf_put_super(struct super_block *sb) | |||
1969 | sbi = UDF_SB(sb); | 2076 | sbi = UDF_SB(sb); |
1970 | if (sbi->s_vat_inode) | 2077 | if (sbi->s_vat_inode) |
1971 | iput(sbi->s_vat_inode); | 2078 | iput(sbi->s_vat_inode); |
1972 | if (sbi->s_partitions) { | 2079 | if (sbi->s_partitions) |
1973 | struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition]; | 2080 | for (i = 0; i < sbi->s_partitions; i++) |
1974 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) | 2081 | udf_free_partition(&sbi->s_partmaps[i]); |
1975 | iput(map->s_uspace.s_table); | ||
1976 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) | ||
1977 | iput(map->s_fspace.s_table); | ||
1978 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) | ||
1979 | udf_sb_free_bitmap(map->s_uspace.s_bitmap); | ||
1980 | if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) | ||
1981 | udf_sb_free_bitmap(map->s_fspace.s_bitmap); | ||
1982 | if (map->s_partition_type == UDF_SPARABLE_MAP15) | ||
1983 | for (i = 0; i < 4; i++) | ||
1984 | brelse(map->s_type_specific.s_sparing. | ||
1985 | s_spar_map[i]); | ||
1986 | } | ||
1987 | #ifdef CONFIG_UDF_NLS | 2082 | #ifdef CONFIG_UDF_NLS |
1988 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) | 2083 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) |
1989 | unload_nls(sbi->s_nls_map); | 2084 | unload_nls(sbi->s_nls_map); |
@@ -1996,19 +2091,6 @@ static void udf_put_super(struct super_block *sb) | |||
1996 | sb->s_fs_info = NULL; | 2091 | sb->s_fs_info = NULL; |
1997 | } | 2092 | } |
1998 | 2093 | ||
1999 | /* | ||
2000 | * udf_stat_fs | ||
2001 | * | ||
2002 | * PURPOSE | ||
2003 | * Return info about the filesystem. | ||
2004 | * | ||
2005 | * DESCRIPTION | ||
2006 | * Called by sys_statfs() | ||
2007 | * | ||
2008 | * HISTORY | ||
2009 | * July 1, 1997 - Andrew E. Mileski | ||
2010 | * Written, tested, and released. | ||
2011 | */ | ||
2012 | static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) | 2094 | static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) |
2013 | { | 2095 | { |
2014 | struct super_block *sb = dentry->d_sb; | 2096 | struct super_block *sb = dentry->d_sb; |
@@ -2035,10 +2117,6 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
2035 | return 0; | 2117 | return 0; |
2036 | } | 2118 | } |
2037 | 2119 | ||
2038 | static unsigned char udf_bitmap_lookup[16] = { | ||
2039 | 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 | ||
2040 | }; | ||
2041 | |||
2042 | static unsigned int udf_count_free_bitmap(struct super_block *sb, | 2120 | static unsigned int udf_count_free_bitmap(struct super_block *sb, |
2043 | struct udf_bitmap *bitmap) | 2121 | struct udf_bitmap *bitmap) |
2044 | { | 2122 | { |
@@ -2048,7 +2126,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, | |||
2048 | int block = 0, newblock; | 2126 | int block = 0, newblock; |
2049 | kernel_lb_addr loc; | 2127 | kernel_lb_addr loc; |
2050 | uint32_t bytes; | 2128 | uint32_t bytes; |
2051 | uint8_t value; | ||
2052 | uint8_t *ptr; | 2129 | uint8_t *ptr; |
2053 | uint16_t ident; | 2130 | uint16_t ident; |
2054 | struct spaceBitmapDesc *bm; | 2131 | struct spaceBitmapDesc *bm; |
@@ -2074,13 +2151,10 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, | |||
2074 | ptr = (uint8_t *)bh->b_data; | 2151 | ptr = (uint8_t *)bh->b_data; |
2075 | 2152 | ||
2076 | while (bytes > 0) { | 2153 | while (bytes > 0) { |
2077 | while ((bytes > 0) && (index < sb->s_blocksize)) { | 2154 | u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index); |
2078 | value = ptr[index]; | 2155 | accum += bitmap_weight((const unsigned long *)(ptr + index), |
2079 | accum += udf_bitmap_lookup[value & 0x0f]; | 2156 | cur_bytes * 8); |
2080 | accum += udf_bitmap_lookup[value >> 4]; | 2157 | bytes -= cur_bytes; |
2081 | index++; | ||
2082 | bytes--; | ||
2083 | } | ||
2084 | if (bytes) { | 2158 | if (bytes) { |
2085 | brelse(bh); | 2159 | brelse(bh); |
2086 | newblock = udf_get_lb_pblock(sb, loc, ++block); | 2160 | newblock = udf_get_lb_pblock(sb, loc, ++block); |
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 6ec99221e50c..c3265e1385d4 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/udf_fs.h> | ||
27 | #include <linux/time.h> | 26 | #include <linux/time.h> |
28 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
29 | #include <linux/stat.h> | 28 | #include <linux/stat.h> |
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index fe61be17cdab..65e19b4f9424 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "udfdecl.h" | 22 | #include "udfdecl.h" |
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/udf_fs.h> | ||
26 | #include <linux/buffer_head.h> | 25 | #include <linux/buffer_head.h> |
27 | 26 | ||
28 | #include "udf_i.h" | 27 | #include "udf_i.h" |
@@ -180,6 +179,24 @@ void udf_discard_prealloc(struct inode *inode) | |||
180 | brelse(epos.bh); | 179 | brelse(epos.bh); |
181 | } | 180 | } |
182 | 181 | ||
182 | static void udf_update_alloc_ext_desc(struct inode *inode, | ||
183 | struct extent_position *epos, | ||
184 | u32 lenalloc) | ||
185 | { | ||
186 | struct super_block *sb = inode->i_sb; | ||
187 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
188 | |||
189 | struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data); | ||
190 | int len = sizeof(struct allocExtDesc); | ||
191 | |||
192 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); | ||
193 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201) | ||
194 | len += lenalloc; | ||
195 | |||
196 | udf_update_tag(epos->bh->b_data, len); | ||
197 | mark_buffer_dirty_inode(epos->bh, inode); | ||
198 | } | ||
199 | |||
183 | void udf_truncate_extents(struct inode *inode) | 200 | void udf_truncate_extents(struct inode *inode) |
184 | { | 201 | { |
185 | struct extent_position epos; | 202 | struct extent_position epos; |
@@ -187,7 +204,6 @@ void udf_truncate_extents(struct inode *inode) | |||
187 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; | 204 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; |
188 | int8_t etype; | 205 | int8_t etype; |
189 | struct super_block *sb = inode->i_sb; | 206 | struct super_block *sb = inode->i_sb; |
190 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
191 | sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset; | 207 | sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset; |
192 | loff_t byte_offset; | 208 | loff_t byte_offset; |
193 | int adsize; | 209 | int adsize; |
@@ -224,35 +240,15 @@ void udf_truncate_extents(struct inode *inode) | |||
224 | if (indirect_ext_len) { | 240 | if (indirect_ext_len) { |
225 | /* We managed to free all extents in the | 241 | /* We managed to free all extents in the |
226 | * indirect extent - free it too */ | 242 | * indirect extent - free it too */ |
227 | if (!epos.bh) | 243 | BUG_ON(!epos.bh); |
228 | BUG(); | ||
229 | udf_free_blocks(sb, inode, epos.block, | 244 | udf_free_blocks(sb, inode, epos.block, |
230 | 0, indirect_ext_len); | 245 | 0, indirect_ext_len); |
231 | } else { | 246 | } else if (!epos.bh) { |
232 | if (!epos.bh) { | 247 | iinfo->i_lenAlloc = lenalloc; |
233 | iinfo->i_lenAlloc = | 248 | mark_inode_dirty(inode); |
234 | lenalloc; | 249 | } else |
235 | mark_inode_dirty(inode); | 250 | udf_update_alloc_ext_desc(inode, |
236 | } else { | 251 | &epos, lenalloc); |
237 | struct allocExtDesc *aed = | ||
238 | (struct allocExtDesc *) | ||
239 | (epos.bh->b_data); | ||
240 | int len = | ||
241 | sizeof(struct allocExtDesc); | ||
242 | |||
243 | aed->lengthAllocDescs = | ||
244 | cpu_to_le32(lenalloc); | ||
245 | if (!UDF_QUERY_FLAG(sb, | ||
246 | UDF_FLAG_STRICT) || | ||
247 | sbi->s_udfrev >= 0x0201) | ||
248 | len += lenalloc; | ||
249 | |||
250 | udf_update_tag(epos.bh->b_data, | ||
251 | len); | ||
252 | mark_buffer_dirty_inode( | ||
253 | epos.bh, inode); | ||
254 | } | ||
255 | } | ||
256 | brelse(epos.bh); | 252 | brelse(epos.bh); |
257 | epos.offset = sizeof(struct allocExtDesc); | 253 | epos.offset = sizeof(struct allocExtDesc); |
258 | epos.block = eloc; | 254 | epos.block = eloc; |
@@ -272,29 +268,14 @@ void udf_truncate_extents(struct inode *inode) | |||
272 | } | 268 | } |
273 | 269 | ||
274 | if (indirect_ext_len) { | 270 | if (indirect_ext_len) { |
275 | if (!epos.bh) | 271 | BUG_ON(!epos.bh); |
276 | BUG(); | ||
277 | udf_free_blocks(sb, inode, epos.block, 0, | 272 | udf_free_blocks(sb, inode, epos.block, 0, |
278 | indirect_ext_len); | 273 | indirect_ext_len); |
279 | } else { | 274 | } else if (!epos.bh) { |
280 | if (!epos.bh) { | 275 | iinfo->i_lenAlloc = lenalloc; |
281 | iinfo->i_lenAlloc = lenalloc; | 276 | mark_inode_dirty(inode); |
282 | mark_inode_dirty(inode); | 277 | } else |
283 | } else { | 278 | udf_update_alloc_ext_desc(inode, &epos, lenalloc); |
284 | struct allocExtDesc *aed = | ||
285 | (struct allocExtDesc *)(epos.bh->b_data); | ||
286 | aed->lengthAllocDescs = cpu_to_le32(lenalloc); | ||
287 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || | ||
288 | sbi->s_udfrev >= 0x0201) | ||
289 | udf_update_tag(epos.bh->b_data, | ||
290 | lenalloc + | ||
291 | sizeof(struct allocExtDesc)); | ||
292 | else | ||
293 | udf_update_tag(epos.bh->b_data, | ||
294 | sizeof(struct allocExtDesc)); | ||
295 | mark_buffer_dirty_inode(epos.bh, inode); | ||
296 | } | ||
297 | } | ||
298 | } else if (inode->i_size) { | 279 | } else if (inode->i_size) { |
299 | if (byte_offset) { | 280 | if (byte_offset) { |
300 | kernel_long_ad extent; | 281 | kernel_long_ad extent; |
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index ccc52f16bf7d..4f86b1d98a5d 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h | |||
@@ -1,10 +1,32 @@ | |||
1 | #ifndef __LINUX_UDF_I_H | 1 | #ifndef _UDF_I_H |
2 | #define __LINUX_UDF_I_H | 2 | #define _UDF_I_H |
3 | |||
4 | struct udf_inode_info { | ||
5 | struct timespec i_crtime; | ||
6 | /* Physical address of inode */ | ||
7 | kernel_lb_addr i_location; | ||
8 | __u64 i_unique; | ||
9 | __u32 i_lenEAttr; | ||
10 | __u32 i_lenAlloc; | ||
11 | __u64 i_lenExtents; | ||
12 | __u32 i_next_alloc_block; | ||
13 | __u32 i_next_alloc_goal; | ||
14 | unsigned i_alloc_type : 3; | ||
15 | unsigned i_efe : 1; /* extendedFileEntry */ | ||
16 | unsigned i_use : 1; /* unallocSpaceEntry */ | ||
17 | unsigned i_strat4096 : 1; | ||
18 | unsigned reserved : 26; | ||
19 | union { | ||
20 | short_ad *i_sad; | ||
21 | long_ad *i_lad; | ||
22 | __u8 *i_data; | ||
23 | } i_ext; | ||
24 | struct inode vfs_inode; | ||
25 | }; | ||
3 | 26 | ||
4 | #include <linux/udf_fs_i.h> | ||
5 | static inline struct udf_inode_info *UDF_I(struct inode *inode) | 27 | static inline struct udf_inode_info *UDF_I(struct inode *inode) |
6 | { | 28 | { |
7 | return list_entry(inode, struct udf_inode_info, vfs_inode); | 29 | return list_entry(inode, struct udf_inode_info, vfs_inode); |
8 | } | 30 | } |
9 | 31 | ||
10 | #endif /* !defined(_LINUX_UDF_I_H) */ | 32 | #endif /* _UDF_I_H) */ |
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 737d1c604eea..1c1c514a9725 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h | |||
@@ -1,10 +1,12 @@ | |||
1 | #ifndef __LINUX_UDF_SB_H | 1 | #ifndef __LINUX_UDF_SB_H |
2 | #define __LINUX_UDF_SB_H | 2 | #define __LINUX_UDF_SB_H |
3 | 3 | ||
4 | #include <linux/mutex.h> | ||
5 | |||
4 | /* Since UDF 2.01 is ISO 13346 based... */ | 6 | /* Since UDF 2.01 is ISO 13346 based... */ |
5 | #define UDF_SUPER_MAGIC 0x15013346 | 7 | #define UDF_SUPER_MAGIC 0x15013346 |
6 | 8 | ||
7 | #define UDF_MAX_READ_VERSION 0x0201 | 9 | #define UDF_MAX_READ_VERSION 0x0250 |
8 | #define UDF_MAX_WRITE_VERSION 0x0201 | 10 | #define UDF_MAX_WRITE_VERSION 0x0201 |
9 | 11 | ||
10 | #define UDF_FLAG_USE_EXTENDED_FE 0 | 12 | #define UDF_FLAG_USE_EXTENDED_FE 0 |
@@ -38,6 +40,111 @@ | |||
38 | #define UDF_PART_FLAG_REWRITABLE 0x0040 | 40 | #define UDF_PART_FLAG_REWRITABLE 0x0040 |
39 | #define UDF_PART_FLAG_OVERWRITABLE 0x0080 | 41 | #define UDF_PART_FLAG_OVERWRITABLE 0x0080 |
40 | 42 | ||
43 | #define UDF_MAX_BLOCK_LOADED 8 | ||
44 | |||
45 | #define UDF_TYPE1_MAP15 0x1511U | ||
46 | #define UDF_VIRTUAL_MAP15 0x1512U | ||
47 | #define UDF_VIRTUAL_MAP20 0x2012U | ||
48 | #define UDF_SPARABLE_MAP15 0x1522U | ||
49 | #define UDF_METADATA_MAP25 0x2511U | ||
50 | |||
51 | #pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ | ||
52 | |||
53 | struct udf_meta_data { | ||
54 | __u32 s_meta_file_loc; | ||
55 | __u32 s_mirror_file_loc; | ||
56 | __u32 s_bitmap_file_loc; | ||
57 | __u32 s_alloc_unit_size; | ||
58 | __u16 s_align_unit_size; | ||
59 | __u8 s_dup_md_flag; | ||
60 | struct inode *s_metadata_fe; | ||
61 | struct inode *s_mirror_fe; | ||
62 | struct inode *s_bitmap_fe; | ||
63 | }; | ||
64 | |||
65 | struct udf_sparing_data { | ||
66 | __u16 s_packet_len; | ||
67 | struct buffer_head *s_spar_map[4]; | ||
68 | }; | ||
69 | |||
70 | struct udf_virtual_data { | ||
71 | __u32 s_num_entries; | ||
72 | __u16 s_start_offset; | ||
73 | }; | ||
74 | |||
75 | struct udf_bitmap { | ||
76 | __u32 s_extLength; | ||
77 | __u32 s_extPosition; | ||
78 | __u16 s_nr_groups; | ||
79 | struct buffer_head **s_block_bitmap; | ||
80 | }; | ||
81 | |||
82 | struct udf_part_map { | ||
83 | union { | ||
84 | struct udf_bitmap *s_bitmap; | ||
85 | struct inode *s_table; | ||
86 | } s_uspace; | ||
87 | union { | ||
88 | struct udf_bitmap *s_bitmap; | ||
89 | struct inode *s_table; | ||
90 | } s_fspace; | ||
91 | __u32 s_partition_root; | ||
92 | __u32 s_partition_len; | ||
93 | __u16 s_partition_type; | ||
94 | __u16 s_partition_num; | ||
95 | union { | ||
96 | struct udf_sparing_data s_sparing; | ||
97 | struct udf_virtual_data s_virtual; | ||
98 | struct udf_meta_data s_metadata; | ||
99 | } s_type_specific; | ||
100 | __u32 (*s_partition_func)(struct super_block *, __u32, __u16, __u32); | ||
101 | __u16 s_volumeseqnum; | ||
102 | __u16 s_partition_flags; | ||
103 | }; | ||
104 | |||
105 | #pragma pack() | ||
106 | |||
107 | struct udf_sb_info { | ||
108 | struct udf_part_map *s_partmaps; | ||
109 | __u8 s_volume_ident[32]; | ||
110 | |||
111 | /* Overall info */ | ||
112 | __u16 s_partitions; | ||
113 | __u16 s_partition; | ||
114 | |||
115 | /* Sector headers */ | ||
116 | __s32 s_session; | ||
117 | __u32 s_anchor[3]; | ||
118 | __u32 s_last_block; | ||
119 | |||
120 | struct buffer_head *s_lvid_bh; | ||
121 | |||
122 | /* Default permissions */ | ||
123 | mode_t s_umask; | ||
124 | gid_t s_gid; | ||
125 | uid_t s_uid; | ||
126 | |||
127 | /* Root Info */ | ||
128 | struct timespec s_record_time; | ||
129 | |||
130 | /* Fileset Info */ | ||
131 | __u16 s_serial_number; | ||
132 | |||
133 | /* highest UDF revision we have recorded to this media */ | ||
134 | __u16 s_udfrev; | ||
135 | |||
136 | /* Miscellaneous flags */ | ||
137 | __u32 s_flags; | ||
138 | |||
139 | /* Encoding info */ | ||
140 | struct nls_table *s_nls_map; | ||
141 | |||
142 | /* VAT inode */ | ||
143 | struct inode *s_vat_inode; | ||
144 | |||
145 | struct mutex s_alloc_mutex; | ||
146 | }; | ||
147 | |||
41 | static inline struct udf_sb_info *UDF_SB(struct super_block *sb) | 148 | static inline struct udf_sb_info *UDF_SB(struct super_block *sb) |
42 | { | 149 | { |
43 | return sb->s_fs_info; | 150 | return sb->s_fs_info; |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 681dc2b66cdb..f3f45d029277 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -1,17 +1,37 @@ | |||
1 | #ifndef __UDF_DECL_H | 1 | #ifndef __UDF_DECL_H |
2 | #define __UDF_DECL_H | 2 | #define __UDF_DECL_H |
3 | 3 | ||
4 | #include <linux/udf_fs.h> | ||
5 | #include "ecma_167.h" | 4 | #include "ecma_167.h" |
6 | #include "osta_udf.h" | 5 | #include "osta_udf.h" |
7 | 6 | ||
8 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
9 | #include <linux/types.h> | 8 | #include <linux/types.h> |
10 | #include <linux/udf_fs_i.h> | ||
11 | #include <linux/udf_fs_sb.h> | ||
12 | #include <linux/buffer_head.h> | 9 | #include <linux/buffer_head.h> |
10 | #include <linux/udf_fs_i.h> | ||
13 | 11 | ||
12 | #include "udf_sb.h" | ||
14 | #include "udfend.h" | 13 | #include "udfend.h" |
14 | #include "udf_i.h" | ||
15 | |||
16 | #define UDF_PREALLOCATE | ||
17 | #define UDF_DEFAULT_PREALLOC_BLOCKS 8 | ||
18 | |||
19 | #define UDFFS_DEBUG | ||
20 | |||
21 | #ifdef UDFFS_DEBUG | ||
22 | #define udf_debug(f, a...) \ | ||
23 | do { \ | ||
24 | printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \ | ||
25 | __FILE__, __LINE__, __func__); \ | ||
26 | printk(f, ##a); \ | ||
27 | } while (0) | ||
28 | #else | ||
29 | #define udf_debug(f, a...) /**/ | ||
30 | #endif | ||
31 | |||
32 | #define udf_info(f, a...) \ | ||
33 | printk(KERN_INFO "UDF-fs INFO " f, ##a); | ||
34 | |||
15 | 35 | ||
16 | #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) ) | 36 | #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) ) |
17 | #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) ) | 37 | #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) ) |
@@ -23,16 +43,24 @@ | |||
23 | #define UDF_NAME_LEN 256 | 43 | #define UDF_NAME_LEN 256 |
24 | #define UDF_PATH_LEN 1023 | 44 | #define UDF_PATH_LEN 1023 |
25 | 45 | ||
26 | #define udf_file_entry_alloc_offset(inode)\ | 46 | static inline size_t udf_file_entry_alloc_offset(struct inode *inode) |
27 | (UDF_I(inode)->i_use ?\ | 47 | { |
28 | sizeof(struct unallocSpaceEntry) :\ | 48 | struct udf_inode_info *iinfo = UDF_I(inode); |
29 | ((UDF_I(inode)->i_efe ?\ | 49 | if (iinfo->i_use) |
30 | sizeof(struct extendedFileEntry) :\ | 50 | return sizeof(struct unallocSpaceEntry); |
31 | sizeof(struct fileEntry)) + UDF_I(inode)->i_lenEAttr)) | 51 | else if (iinfo->i_efe) |
32 | 52 | return sizeof(struct extendedFileEntry) + iinfo->i_lenEAttr; | |
33 | #define udf_ext0_offset(inode)\ | 53 | else |
34 | (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ?\ | 54 | return sizeof(struct fileEntry) + iinfo->i_lenEAttr; |
35 | udf_file_entry_alloc_offset(inode) : 0) | 55 | } |
56 | |||
57 | static inline size_t udf_ext0_offset(struct inode *inode) | ||
58 | { | ||
59 | if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | ||
60 | return udf_file_entry_alloc_offset(inode); | ||
61 | else | ||
62 | return 0; | ||
63 | } | ||
36 | 64 | ||
37 | #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset)) | 65 | #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset)) |
38 | 66 | ||
@@ -83,7 +111,6 @@ struct extent_position { | |||
83 | }; | 111 | }; |
84 | 112 | ||
85 | /* super.c */ | 113 | /* super.c */ |
86 | extern void udf_error(struct super_block *, const char *, const char *, ...); | ||
87 | extern void udf_warning(struct super_block *, const char *, const char *, ...); | 114 | extern void udf_warning(struct super_block *, const char *, const char *, ...); |
88 | 115 | ||
89 | /* namei.c */ | 116 | /* namei.c */ |
@@ -150,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t, | |||
150 | uint32_t); | 177 | uint32_t); |
151 | extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t, | 178 | extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t, |
152 | uint32_t); | 179 | uint32_t); |
180 | extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t, | ||
181 | uint32_t); | ||
153 | extern int udf_relocate_blocks(struct super_block *, long, long *); | 182 | extern int udf_relocate_blocks(struct super_block *, long, long *); |
154 | 183 | ||
155 | /* unicode.c */ | 184 | /* unicode.c */ |
@@ -157,7 +186,7 @@ extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); | |||
157 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, | 186 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, |
158 | int); | 187 | int); |
159 | extern int udf_build_ustr(struct ustr *, dstring *, int); | 188 | extern int udf_build_ustr(struct ustr *, dstring *, int); |
160 | extern int udf_CS0toUTF8(struct ustr *, struct ustr *); | 189 | extern int udf_CS0toUTF8(struct ustr *, const struct ustr *); |
161 | 190 | ||
162 | /* ialloc.c */ | 191 | /* ialloc.c */ |
163 | extern void udf_free_inode(struct inode *); | 192 | extern void udf_free_inode(struct inode *); |
@@ -191,11 +220,9 @@ extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, | |||
191 | extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); | 220 | extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); |
192 | extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); | 221 | extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); |
193 | 222 | ||
194 | /* crc.c */ | ||
195 | extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t); | ||
196 | |||
197 | /* udftime.c */ | 223 | /* udftime.c */ |
198 | extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp); | 224 | extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest, |
199 | extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec); | 225 | timestamp src); |
226 | extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src); | ||
200 | 227 | ||
201 | #endif /* __UDF_DECL_H */ | 228 | #endif /* __UDF_DECL_H */ |
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h index c4bd1203f857..489f52fb428c 100644 --- a/fs/udf/udfend.h +++ b/fs/udf/udfend.h | |||
@@ -24,17 +24,6 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in) | |||
24 | return out; | 24 | return out; |
25 | } | 25 | } |
26 | 26 | ||
27 | static inline kernel_timestamp lets_to_cpu(timestamp in) | ||
28 | { | ||
29 | kernel_timestamp out; | ||
30 | |||
31 | memcpy(&out, &in, sizeof(timestamp)); | ||
32 | out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone); | ||
33 | out.year = le16_to_cpu(in.year); | ||
34 | |||
35 | return out; | ||
36 | } | ||
37 | |||
38 | static inline short_ad lesa_to_cpu(short_ad in) | 27 | static inline short_ad lesa_to_cpu(short_ad in) |
39 | { | 28 | { |
40 | short_ad out; | 29 | short_ad out; |
@@ -85,15 +74,4 @@ static inline kernel_extent_ad leea_to_cpu(extent_ad in) | |||
85 | return out; | 74 | return out; |
86 | } | 75 | } |
87 | 76 | ||
88 | static inline timestamp cpu_to_lets(kernel_timestamp in) | ||
89 | { | ||
90 | timestamp out; | ||
91 | |||
92 | memcpy(&out, &in, sizeof(timestamp)); | ||
93 | out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone); | ||
94 | out.year = cpu_to_le16(in.year); | ||
95 | |||
96 | return out; | ||
97 | } | ||
98 | |||
99 | #endif /* __UDF_ENDIAN_H */ | 77 | #endif /* __UDF_ENDIAN_H */ |
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index ce595732ba6f..5f811655c9b5 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c | |||
@@ -85,39 +85,38 @@ extern struct timezone sys_tz; | |||
85 | #define SECS_PER_HOUR (60 * 60) | 85 | #define SECS_PER_HOUR (60 * 60) |
86 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | 86 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) |
87 | 87 | ||
88 | time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src) | 88 | struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src) |
89 | { | 89 | { |
90 | int yday; | 90 | int yday; |
91 | uint8_t type = src.typeAndTimezone >> 12; | 91 | u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); |
92 | u16 year = le16_to_cpu(src.year); | ||
93 | uint8_t type = typeAndTimezone >> 12; | ||
92 | int16_t offset; | 94 | int16_t offset; |
93 | 95 | ||
94 | if (type == 1) { | 96 | if (type == 1) { |
95 | offset = src.typeAndTimezone << 4; | 97 | offset = typeAndTimezone << 4; |
96 | /* sign extent offset */ | 98 | /* sign extent offset */ |
97 | offset = (offset >> 4); | 99 | offset = (offset >> 4); |
98 | if (offset == -2047) /* unspecified offset */ | 100 | if (offset == -2047) /* unspecified offset */ |
99 | offset = 0; | 101 | offset = 0; |
100 | } else { | 102 | } else |
101 | offset = 0; | 103 | offset = 0; |
102 | } | ||
103 | 104 | ||
104 | if ((src.year < EPOCH_YEAR) || | 105 | if ((year < EPOCH_YEAR) || |
105 | (src.year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) { | 106 | (year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) { |
106 | *dest = -1; | ||
107 | *dest_usec = -1; | ||
108 | return NULL; | 107 | return NULL; |
109 | } | 108 | } |
110 | *dest = year_seconds[src.year - EPOCH_YEAR]; | 109 | dest->tv_sec = year_seconds[year - EPOCH_YEAR]; |
111 | *dest -= offset * 60; | 110 | dest->tv_sec -= offset * 60; |
112 | 111 | ||
113 | yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1); | 112 | yday = ((__mon_yday[__isleap(year)][src.month - 1]) + src.day - 1); |
114 | *dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second; | 113 | dest->tv_sec += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second; |
115 | *dest_usec = src.centiseconds * 10000 + | 114 | dest->tv_nsec = 1000 * (src.centiseconds * 10000 + |
116 | src.hundredsOfMicroseconds * 100 + src.microseconds; | 115 | src.hundredsOfMicroseconds * 100 + src.microseconds); |
117 | return dest; | 116 | return dest; |
118 | } | 117 | } |
119 | 118 | ||
120 | kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts) | 119 | timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts) |
121 | { | 120 | { |
122 | long int days, rem, y; | 121 | long int days, rem, y; |
123 | const unsigned short int *ip; | 122 | const unsigned short int *ip; |
@@ -128,7 +127,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts) | |||
128 | if (!dest) | 127 | if (!dest) |
129 | return NULL; | 128 | return NULL; |
130 | 129 | ||
131 | dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF); | 130 | dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF)); |
132 | 131 | ||
133 | ts.tv_sec += offset * 60; | 132 | ts.tv_sec += offset * 60; |
134 | days = ts.tv_sec / SECS_PER_DAY; | 133 | days = ts.tv_sec / SECS_PER_DAY; |
@@ -151,7 +150,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts) | |||
151 | - LEAPS_THRU_END_OF(y - 1)); | 150 | - LEAPS_THRU_END_OF(y - 1)); |
152 | y = yg; | 151 | y = yg; |
153 | } | 152 | } |
154 | dest->year = y; | 153 | dest->year = cpu_to_le16(y); |
155 | ip = __mon_yday[__isleap(y)]; | 154 | ip = __mon_yday[__isleap(y)]; |
156 | for (y = 11; days < (long int)ip[y]; --y) | 155 | for (y = 11; days < (long int)ip[y]; --y) |
157 | continue; | 156 | continue; |
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index e533b11703bf..9fdf8c93c58e 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/string.h> /* for memset */ | 24 | #include <linux/string.h> /* for memset */ |
25 | #include <linux/nls.h> | 25 | #include <linux/nls.h> |
26 | #include <linux/udf_fs.h> | 26 | #include <linux/crc-itu-t.h> |
27 | 27 | ||
28 | #include "udf_sb.h" | 28 | #include "udf_sb.h" |
29 | 29 | ||
@@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size) | |||
49 | { | 49 | { |
50 | int usesize; | 50 | int usesize; |
51 | 51 | ||
52 | if ((!dest) || (!ptr) || (!size)) | 52 | if (!dest || !ptr || !size) |
53 | return -1; | 53 | return -1; |
54 | BUG_ON(size < 2); | ||
54 | 55 | ||
55 | memset(dest, 0, sizeof(struct ustr)); | 56 | usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name)); |
56 | usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size; | 57 | usesize = min(usesize, size - 2); |
57 | dest->u_cmpID = ptr[0]; | 58 | dest->u_cmpID = ptr[0]; |
58 | dest->u_len = ptr[size - 1]; | 59 | dest->u_len = usesize; |
59 | memcpy(dest->u_name, ptr + 1, usesize - 1); | 60 | memcpy(dest->u_name, ptr + 1, usesize); |
61 | memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize); | ||
60 | 62 | ||
61 | return 0; | 63 | return 0; |
62 | } | 64 | } |
@@ -83,9 +85,6 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) | |||
83 | * PURPOSE | 85 | * PURPOSE |
84 | * Convert OSTA Compressed Unicode to the UTF-8 equivalent. | 86 | * Convert OSTA Compressed Unicode to the UTF-8 equivalent. |
85 | * | 87 | * |
86 | * DESCRIPTION | ||
87 | * This routine is only called by udf_filldir(). | ||
88 | * | ||
89 | * PRE-CONDITIONS | 88 | * PRE-CONDITIONS |
90 | * utf Pointer to UTF-8 output buffer. | 89 | * utf Pointer to UTF-8 output buffer. |
91 | * ocu Pointer to OSTA Compressed Unicode input buffer | 90 | * ocu Pointer to OSTA Compressed Unicode input buffer |
@@ -99,43 +98,39 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize) | |||
99 | * November 12, 1997 - Andrew E. Mileski | 98 | * November 12, 1997 - Andrew E. Mileski |
100 | * Written, tested, and released. | 99 | * Written, tested, and released. |
101 | */ | 100 | */ |
102 | int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i) | 101 | int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i) |
103 | { | 102 | { |
104 | uint8_t *ocu; | 103 | const uint8_t *ocu; |
105 | uint32_t c; | ||
106 | uint8_t cmp_id, ocu_len; | 104 | uint8_t cmp_id, ocu_len; |
107 | int i; | 105 | int i; |
108 | 106 | ||
109 | ocu = ocu_i->u_name; | ||
110 | |||
111 | ocu_len = ocu_i->u_len; | 107 | ocu_len = ocu_i->u_len; |
112 | cmp_id = ocu_i->u_cmpID; | ||
113 | utf_o->u_len = 0; | ||
114 | |||
115 | if (ocu_len == 0) { | 108 | if (ocu_len == 0) { |
116 | memset(utf_o, 0, sizeof(struct ustr)); | 109 | memset(utf_o, 0, sizeof(struct ustr)); |
117 | utf_o->u_cmpID = 0; | ||
118 | utf_o->u_len = 0; | ||
119 | return 0; | 110 | return 0; |
120 | } | 111 | } |
121 | 112 | ||
122 | if ((cmp_id != 8) && (cmp_id != 16)) { | 113 | cmp_id = ocu_i->u_cmpID; |
114 | if (cmp_id != 8 && cmp_id != 16) { | ||
115 | memset(utf_o, 0, sizeof(struct ustr)); | ||
123 | printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", | 116 | printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", |
124 | cmp_id, ocu_i->u_name); | 117 | cmp_id, ocu_i->u_name); |
125 | return 0; | 118 | return 0; |
126 | } | 119 | } |
127 | 120 | ||
121 | ocu = ocu_i->u_name; | ||
122 | utf_o->u_len = 0; | ||
128 | for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) { | 123 | for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) { |
129 | 124 | ||
130 | /* Expand OSTA compressed Unicode to Unicode */ | 125 | /* Expand OSTA compressed Unicode to Unicode */ |
131 | c = ocu[i++]; | 126 | uint32_t c = ocu[i++]; |
132 | if (cmp_id == 16) | 127 | if (cmp_id == 16) |
133 | c = (c << 8) | ocu[i++]; | 128 | c = (c << 8) | ocu[i++]; |
134 | 129 | ||
135 | /* Compress Unicode to UTF-8 */ | 130 | /* Compress Unicode to UTF-8 */ |
136 | if (c < 0x80U) { | 131 | if (c < 0x80U) |
137 | utf_o->u_name[utf_o->u_len++] = (uint8_t)c; | 132 | utf_o->u_name[utf_o->u_len++] = (uint8_t)c; |
138 | } else if (c < 0x800U) { | 133 | else if (c < 0x800U) { |
139 | utf_o->u_name[utf_o->u_len++] = | 134 | utf_o->u_name[utf_o->u_len++] = |
140 | (uint8_t)(0xc0 | (c >> 6)); | 135 | (uint8_t)(0xc0 | (c >> 6)); |
141 | utf_o->u_name[utf_o->u_len++] = | 136 | utf_o->u_name[utf_o->u_len++] = |
@@ -255,35 +250,32 @@ error_out: | |||
255 | } | 250 | } |
256 | 251 | ||
257 | static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | 252 | static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, |
258 | struct ustr *ocu_i) | 253 | const struct ustr *ocu_i) |
259 | { | 254 | { |
260 | uint8_t *ocu; | 255 | const uint8_t *ocu; |
261 | uint32_t c; | ||
262 | uint8_t cmp_id, ocu_len; | 256 | uint8_t cmp_id, ocu_len; |
263 | int i; | 257 | int i; |
264 | 258 | ||
265 | ocu = ocu_i->u_name; | ||
266 | 259 | ||
267 | ocu_len = ocu_i->u_len; | 260 | ocu_len = ocu_i->u_len; |
268 | cmp_id = ocu_i->u_cmpID; | ||
269 | utf_o->u_len = 0; | ||
270 | |||
271 | if (ocu_len == 0) { | 261 | if (ocu_len == 0) { |
272 | memset(utf_o, 0, sizeof(struct ustr)); | 262 | memset(utf_o, 0, sizeof(struct ustr)); |
273 | utf_o->u_cmpID = 0; | ||
274 | utf_o->u_len = 0; | ||
275 | return 0; | 263 | return 0; |
276 | } | 264 | } |
277 | 265 | ||
278 | if ((cmp_id != 8) && (cmp_id != 16)) { | 266 | cmp_id = ocu_i->u_cmpID; |
267 | if (cmp_id != 8 && cmp_id != 16) { | ||
268 | memset(utf_o, 0, sizeof(struct ustr)); | ||
279 | printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", | 269 | printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n", |
280 | cmp_id, ocu_i->u_name); | 270 | cmp_id, ocu_i->u_name); |
281 | return 0; | 271 | return 0; |
282 | } | 272 | } |
283 | 273 | ||
274 | ocu = ocu_i->u_name; | ||
275 | utf_o->u_len = 0; | ||
284 | for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) { | 276 | for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) { |
285 | /* Expand OSTA compressed Unicode to Unicode */ | 277 | /* Expand OSTA compressed Unicode to Unicode */ |
286 | c = ocu[i++]; | 278 | uint32_t c = ocu[i++]; |
287 | if (cmp_id == 16) | 279 | if (cmp_id == 16) |
288 | c = (c << 8) | ocu[i++]; | 280 | c = (c << 8) | ocu[i++]; |
289 | 281 | ||
@@ -463,7 +455,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
463 | } else if (newIndex > 250) | 455 | } else if (newIndex > 250) |
464 | newIndex = 250; | 456 | newIndex = 250; |
465 | newName[newIndex++] = CRC_MARK; | 457 | newName[newIndex++] = CRC_MARK; |
466 | valueCRC = udf_crc(fidName, fidNameLen, 0); | 458 | valueCRC = crc_itu_t(0, fidName, fidNameLen); |
467 | newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; | 459 | newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; |
468 | newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8]; | 460 | newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8]; |
469 | newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4]; | 461 | newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4]; |
diff --git a/fs/utimes.c b/fs/utimes.c index b18da9c0b97f..a2bef77dc9c9 100644 --- a/fs/utimes.c +++ b/fs/utimes.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <linux/file.h> | 2 | #include <linux/file.h> |
3 | #include <linux/fs.h> | 3 | #include <linux/fs.h> |
4 | #include <linux/linkage.h> | 4 | #include <linux/linkage.h> |
5 | #include <linux/mount.h> | ||
5 | #include <linux/namei.h> | 6 | #include <linux/namei.h> |
6 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
7 | #include <linux/stat.h> | 8 | #include <linux/stat.h> |
@@ -59,6 +60,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags | |||
59 | struct inode *inode; | 60 | struct inode *inode; |
60 | struct iattr newattrs; | 61 | struct iattr newattrs; |
61 | struct file *f = NULL; | 62 | struct file *f = NULL; |
63 | struct vfsmount *mnt; | ||
62 | 64 | ||
63 | error = -EINVAL; | 65 | error = -EINVAL; |
64 | if (times && (!nsec_valid(times[0].tv_nsec) || | 66 | if (times && (!nsec_valid(times[0].tv_nsec) || |
@@ -79,18 +81,20 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags | |||
79 | if (!f) | 81 | if (!f) |
80 | goto out; | 82 | goto out; |
81 | dentry = f->f_path.dentry; | 83 | dentry = f->f_path.dentry; |
84 | mnt = f->f_path.mnt; | ||
82 | } else { | 85 | } else { |
83 | error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd); | 86 | error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd); |
84 | if (error) | 87 | if (error) |
85 | goto out; | 88 | goto out; |
86 | 89 | ||
87 | dentry = nd.path.dentry; | 90 | dentry = nd.path.dentry; |
91 | mnt = nd.path.mnt; | ||
88 | } | 92 | } |
89 | 93 | ||
90 | inode = dentry->d_inode; | 94 | inode = dentry->d_inode; |
91 | 95 | ||
92 | error = -EROFS; | 96 | error = mnt_want_write(mnt); |
93 | if (IS_RDONLY(inode)) | 97 | if (error) |
94 | goto dput_and_out; | 98 | goto dput_and_out; |
95 | 99 | ||
96 | /* Don't worry, the checks are done in inode_change_ok() */ | 100 | /* Don't worry, the checks are done in inode_change_ok() */ |
@@ -98,7 +102,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags | |||
98 | if (times) { | 102 | if (times) { |
99 | error = -EPERM; | 103 | error = -EPERM; |
100 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 104 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
101 | goto dput_and_out; | 105 | goto mnt_drop_write_and_out; |
102 | 106 | ||
103 | if (times[0].tv_nsec == UTIME_OMIT) | 107 | if (times[0].tv_nsec == UTIME_OMIT) |
104 | newattrs.ia_valid &= ~ATTR_ATIME; | 108 | newattrs.ia_valid &= ~ATTR_ATIME; |
@@ -118,22 +122,24 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags | |||
118 | } else { | 122 | } else { |
119 | error = -EACCES; | 123 | error = -EACCES; |
120 | if (IS_IMMUTABLE(inode)) | 124 | if (IS_IMMUTABLE(inode)) |
121 | goto dput_and_out; | 125 | goto mnt_drop_write_and_out; |
122 | 126 | ||
123 | if (!is_owner_or_cap(inode)) { | 127 | if (!is_owner_or_cap(inode)) { |
124 | if (f) { | 128 | if (f) { |
125 | if (!(f->f_mode & FMODE_WRITE)) | 129 | if (!(f->f_mode & FMODE_WRITE)) |
126 | goto dput_and_out; | 130 | goto mnt_drop_write_and_out; |
127 | } else { | 131 | } else { |
128 | error = vfs_permission(&nd, MAY_WRITE); | 132 | error = vfs_permission(&nd, MAY_WRITE); |
129 | if (error) | 133 | if (error) |
130 | goto dput_and_out; | 134 | goto mnt_drop_write_and_out; |
131 | } | 135 | } |
132 | } | 136 | } |
133 | } | 137 | } |
134 | mutex_lock(&inode->i_mutex); | 138 | mutex_lock(&inode->i_mutex); |
135 | error = notify_change(dentry, &newattrs); | 139 | error = notify_change(dentry, &newattrs); |
136 | mutex_unlock(&inode->i_mutex); | 140 | mutex_unlock(&inode->i_mutex); |
141 | mnt_drop_write_and_out: | ||
142 | mnt_drop_write(mnt); | ||
137 | dput_and_out: | 143 | dput_and_out: |
138 | if (f) | 144 | if (f) |
139 | fput(f); | 145 | fput(f); |
diff --git a/fs/xattr.c b/fs/xattr.c index 3acab1615460..f7062da505d4 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/file.h> | 12 | #include <linux/file.h> |
13 | #include <linux/xattr.h> | 13 | #include <linux/xattr.h> |
14 | #include <linux/mount.h> | ||
14 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
15 | #include <linux/security.h> | 16 | #include <linux/security.h> |
16 | #include <linux/syscalls.h> | 17 | #include <linux/syscalls.h> |
@@ -32,8 +33,6 @@ xattr_permission(struct inode *inode, const char *name, int mask) | |||
32 | * filesystem or on an immutable / append-only inode. | 33 | * filesystem or on an immutable / append-only inode. |
33 | */ | 34 | */ |
34 | if (mask & MAY_WRITE) { | 35 | if (mask & MAY_WRITE) { |
35 | if (IS_RDONLY(inode)) | ||
36 | return -EROFS; | ||
37 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 36 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
38 | return -EPERM; | 37 | return -EPERM; |
39 | } | 38 | } |
@@ -262,7 +261,11 @@ sys_setxattr(char __user *path, char __user *name, void __user *value, | |||
262 | error = user_path_walk(path, &nd); | 261 | error = user_path_walk(path, &nd); |
263 | if (error) | 262 | if (error) |
264 | return error; | 263 | return error; |
265 | error = setxattr(nd.path.dentry, name, value, size, flags); | 264 | error = mnt_want_write(nd.path.mnt); |
265 | if (!error) { | ||
266 | error = setxattr(nd.path.dentry, name, value, size, flags); | ||
267 | mnt_drop_write(nd.path.mnt); | ||
268 | } | ||
266 | path_put(&nd.path); | 269 | path_put(&nd.path); |
267 | return error; | 270 | return error; |
268 | } | 271 | } |
@@ -277,7 +280,11 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value, | |||
277 | error = user_path_walk_link(path, &nd); | 280 | error = user_path_walk_link(path, &nd); |
278 | if (error) | 281 | if (error) |
279 | return error; | 282 | return error; |
280 | error = setxattr(nd.path.dentry, name, value, size, flags); | 283 | error = mnt_want_write(nd.path.mnt); |
284 | if (!error) { | ||
285 | error = setxattr(nd.path.dentry, name, value, size, flags); | ||
286 | mnt_drop_write(nd.path.mnt); | ||
287 | } | ||
281 | path_put(&nd.path); | 288 | path_put(&nd.path); |
282 | return error; | 289 | return error; |
283 | } | 290 | } |
@@ -295,7 +302,12 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
295 | return error; | 302 | return error; |
296 | dentry = f->f_path.dentry; | 303 | dentry = f->f_path.dentry; |
297 | audit_inode(NULL, dentry); | 304 | audit_inode(NULL, dentry); |
298 | error = setxattr(dentry, name, value, size, flags); | 305 | error = mnt_want_write(f->f_path.mnt); |
306 | if (!error) { | ||
307 | error = setxattr(dentry, name, value, size, flags); | ||
308 | mnt_drop_write(f->f_path.mnt); | ||
309 | } | ||
310 | out_fput: | ||
299 | fput(f); | 311 | fput(f); |
300 | return error; | 312 | return error; |
301 | } | 313 | } |
@@ -482,7 +494,11 @@ sys_removexattr(char __user *path, char __user *name) | |||
482 | error = user_path_walk(path, &nd); | 494 | error = user_path_walk(path, &nd); |
483 | if (error) | 495 | if (error) |
484 | return error; | 496 | return error; |
485 | error = removexattr(nd.path.dentry, name); | 497 | error = mnt_want_write(nd.path.mnt); |
498 | if (!error) { | ||
499 | error = removexattr(nd.path.dentry, name); | ||
500 | mnt_drop_write(nd.path.mnt); | ||
501 | } | ||
486 | path_put(&nd.path); | 502 | path_put(&nd.path); |
487 | return error; | 503 | return error; |
488 | } | 504 | } |
@@ -496,7 +512,11 @@ sys_lremovexattr(char __user *path, char __user *name) | |||
496 | error = user_path_walk_link(path, &nd); | 512 | error = user_path_walk_link(path, &nd); |
497 | if (error) | 513 | if (error) |
498 | return error; | 514 | return error; |
499 | error = removexattr(nd.path.dentry, name); | 515 | error = mnt_want_write(nd.path.mnt); |
516 | if (!error) { | ||
517 | error = removexattr(nd.path.dentry, name); | ||
518 | mnt_drop_write(nd.path.mnt); | ||
519 | } | ||
500 | path_put(&nd.path); | 520 | path_put(&nd.path); |
501 | return error; | 521 | return error; |
502 | } | 522 | } |
@@ -513,7 +533,11 @@ sys_fremovexattr(int fd, char __user *name) | |||
513 | return error; | 533 | return error; |
514 | dentry = f->f_path.dentry; | 534 | dentry = f->f_path.dentry; |
515 | audit_inode(NULL, dentry); | 535 | audit_inode(NULL, dentry); |
516 | error = removexattr(dentry, name); | 536 | error = mnt_want_write(f->f_path.mnt); |
537 | if (!error) { | ||
538 | error = removexattr(dentry, name); | ||
539 | mnt_drop_write(f->f_path.mnt); | ||
540 | } | ||
517 | fput(f); | 541 | fput(f); |
518 | return error; | 542 | return error; |
519 | } | 543 | } |
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h index 2009e6d922ce..3abe7e9ceb33 100644 --- a/fs/xfs/linux-2.6/sema.h +++ b/fs/xfs/linux-2.6/sema.h | |||
@@ -20,8 +20,8 @@ | |||
20 | 20 | ||
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
23 | #include <linux/semaphore.h> | ||
23 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
24 | #include <asm/semaphore.h> | ||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * sema_t structure just maps to struct semaphore in Linux kernel. | 27 | * sema_t structure just maps to struct semaphore in Linux kernel. |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index bf7759793856..4ddb86b73c6b 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -535,8 +535,6 @@ xfs_attrmulti_attr_set( | |||
535 | char *kbuf; | 535 | char *kbuf; |
536 | int error = EFAULT; | 536 | int error = EFAULT; |
537 | 537 | ||
538 | if (IS_RDONLY(inode)) | ||
539 | return -EROFS; | ||
540 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 538 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
541 | return EPERM; | 539 | return EPERM; |
542 | if (len > XATTR_SIZE_MAX) | 540 | if (len > XATTR_SIZE_MAX) |
@@ -562,8 +560,6 @@ xfs_attrmulti_attr_remove( | |||
562 | char *name, | 560 | char *name, |
563 | __uint32_t flags) | 561 | __uint32_t flags) |
564 | { | 562 | { |
565 | if (IS_RDONLY(inode)) | ||
566 | return -EROFS; | ||
567 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 563 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
568 | return EPERM; | 564 | return EPERM; |
569 | return xfs_attr_remove(XFS_I(inode), name, flags); | 565 | return xfs_attr_remove(XFS_I(inode), name, flags); |
@@ -573,6 +569,7 @@ STATIC int | |||
573 | xfs_attrmulti_by_handle( | 569 | xfs_attrmulti_by_handle( |
574 | xfs_mount_t *mp, | 570 | xfs_mount_t *mp, |
575 | void __user *arg, | 571 | void __user *arg, |
572 | struct file *parfilp, | ||
576 | struct inode *parinode) | 573 | struct inode *parinode) |
577 | { | 574 | { |
578 | int error; | 575 | int error; |
@@ -626,13 +623,21 @@ xfs_attrmulti_by_handle( | |||
626 | &ops[i].am_length, ops[i].am_flags); | 623 | &ops[i].am_length, ops[i].am_flags); |
627 | break; | 624 | break; |
628 | case ATTR_OP_SET: | 625 | case ATTR_OP_SET: |
626 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | ||
627 | if (ops[i].am_error) | ||
628 | break; | ||
629 | ops[i].am_error = xfs_attrmulti_attr_set(inode, | 629 | ops[i].am_error = xfs_attrmulti_attr_set(inode, |
630 | attr_name, ops[i].am_attrvalue, | 630 | attr_name, ops[i].am_attrvalue, |
631 | ops[i].am_length, ops[i].am_flags); | 631 | ops[i].am_length, ops[i].am_flags); |
632 | mnt_drop_write(parfilp->f_path.mnt); | ||
632 | break; | 633 | break; |
633 | case ATTR_OP_REMOVE: | 634 | case ATTR_OP_REMOVE: |
635 | ops[i].am_error = mnt_want_write(parfilp->f_path.mnt); | ||
636 | if (ops[i].am_error) | ||
637 | break; | ||
634 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, | 638 | ops[i].am_error = xfs_attrmulti_attr_remove(inode, |
635 | attr_name, ops[i].am_flags); | 639 | attr_name, ops[i].am_flags); |
640 | mnt_drop_write(parfilp->f_path.mnt); | ||
636 | break; | 641 | break; |
637 | default: | 642 | default: |
638 | ops[i].am_error = EINVAL; | 643 | ops[i].am_error = EINVAL; |
@@ -1133,7 +1138,7 @@ xfs_ioctl( | |||
1133 | return xfs_attrlist_by_handle(mp, arg, inode); | 1138 | return xfs_attrlist_by_handle(mp, arg, inode); |
1134 | 1139 | ||
1135 | case XFS_IOC_ATTRMULTI_BY_HANDLE: | 1140 | case XFS_IOC_ATTRMULTI_BY_HANDLE: |
1136 | return xfs_attrmulti_by_handle(mp, arg, inode); | 1141 | return xfs_attrmulti_by_handle(mp, arg, filp, inode); |
1137 | 1142 | ||
1138 | case XFS_IOC_SWAPEXT: { | 1143 | case XFS_IOC_SWAPEXT: { |
1139 | error = xfs_swapext((struct xfs_swapext __user *)arg); | 1144 | error = xfs_swapext((struct xfs_swapext __user *)arg); |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 0c958cf77758..a1237dad6430 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -155,13 +155,6 @@ xfs_ichgtime_fast( | |||
155 | */ | 155 | */ |
156 | ASSERT((flags & XFS_ICHGTIME_ACC) == 0); | 156 | ASSERT((flags & XFS_ICHGTIME_ACC) == 0); |
157 | 157 | ||
158 | /* | ||
159 | * We're not supposed to change timestamps in readonly-mounted | ||
160 | * filesystems. Throw it away if anyone asks us. | ||
161 | */ | ||
162 | if (unlikely(IS_RDONLY(inode))) | ||
163 | return; | ||
164 | |||
165 | if (flags & XFS_ICHGTIME_MOD) { | 158 | if (flags & XFS_ICHGTIME_MOD) { |
166 | tvp = &inode->i_mtime; | 159 | tvp = &inode->i_mtime; |
167 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; | 160 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 21c0dbc74093..1ebd8004469c 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "xfs_vnodeops.h" | 51 | #include "xfs_vnodeops.h" |
52 | 52 | ||
53 | #include <linux/capability.h> | 53 | #include <linux/capability.h> |
54 | #include <linux/mount.h> | ||
54 | #include <linux/writeback.h> | 55 | #include <linux/writeback.h> |
55 | 56 | ||
56 | 57 | ||
@@ -670,10 +671,16 @@ start: | |||
670 | if (new_size > xip->i_size) | 671 | if (new_size > xip->i_size) |
671 | xip->i_new_size = new_size; | 672 | xip->i_new_size = new_size; |
672 | 673 | ||
673 | if (likely(!(ioflags & IO_INVIS))) { | 674 | /* |
675 | * We're not supposed to change timestamps in readonly-mounted | ||
676 | * filesystems. Throw it away if anyone asks us. | ||
677 | */ | ||
678 | if (likely(!(ioflags & IO_INVIS) && | ||
679 | !mnt_want_write(file->f_path.mnt))) { | ||
674 | file_update_time(file); | 680 | file_update_time(file); |
675 | xfs_ichgtime_fast(xip, inode, | 681 | xfs_ichgtime_fast(xip, inode, |
676 | XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 682 | XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
683 | mnt_drop_write(file->f_path.mnt); | ||
677 | } | 684 | } |
678 | 685 | ||
679 | /* | 686 | /* |