diff options
Diffstat (limited to 'fs/ufs/super.c')
-rw-r--r-- | fs/ufs/super.c | 140 |
1 files changed, 103 insertions, 37 deletions
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 3aadbd3167a6..74ef5e9bedff 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -381,24 +381,57 @@ static int ufs_parse_options (char * options, unsigned * mount_options) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* | 383 | /* |
384 | * Read on-disk structures associated with cylinder groups | 384 | * Diffrent types of UFS hold fs_cstotal in different |
385 | * places, and use diffrent data structure for it. | ||
386 | * To make things simplier we just copy fs_cstotal to ufs_sb_private_info | ||
385 | */ | 387 | */ |
386 | static int ufs_read_cylinder_structures (struct super_block *sb) | 388 | static void ufs_setup_cstotal(struct super_block *sb) |
387 | { | 389 | { |
388 | struct ufs_sb_info *sbi = UFS_SB(sb); | 390 | struct ufs_sb_info *sbi = UFS_SB(sb); |
389 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | 391 | struct ufs_sb_private_info *uspi = sbi->s_uspi; |
392 | struct ufs_super_block_first *usb1; | ||
393 | struct ufs_super_block_second *usb2; | ||
390 | struct ufs_super_block_third *usb3; | 394 | struct ufs_super_block_third *usb3; |
395 | unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE; | ||
396 | |||
397 | UFSD("ENTER, mtype=%u\n", mtype); | ||
398 | usb1 = ubh_get_usb_first(uspi); | ||
399 | usb2 = ubh_get_usb_second(uspi); | ||
400 | usb3 = ubh_get_usb_third(uspi); | ||
401 | |||
402 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && | ||
403 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || | ||
404 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { | ||
405 | /*we have statistic in different place, then usual*/ | ||
406 | uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir); | ||
407 | uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree); | ||
408 | uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); | ||
409 | uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); | ||
410 | } else { | ||
411 | uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir); | ||
412 | uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree); | ||
413 | uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); | ||
414 | uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); | ||
415 | } | ||
416 | UFSD("EXIT\n"); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Read on-disk structures associated with cylinder groups | ||
421 | */ | ||
422 | static int ufs_read_cylinder_structures(struct super_block *sb) | ||
423 | { | ||
424 | struct ufs_sb_info *sbi = UFS_SB(sb); | ||
425 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | ||
426 | unsigned flags = sbi->s_flags; | ||
391 | struct ufs_buffer_head * ubh; | 427 | struct ufs_buffer_head * ubh; |
392 | unsigned char * base, * space; | 428 | unsigned char * base, * space; |
393 | unsigned size, blks, i; | 429 | unsigned size, blks, i; |
394 | unsigned flags = 0; | 430 | struct ufs_super_block_third *usb3; |
395 | 431 | ||
396 | UFSD("ENTER\n"); | 432 | UFSD("ENTER\n"); |
397 | |||
398 | usb3 = ubh_get_usb_third(uspi); | ||
399 | 433 | ||
400 | flags = UFS_SB(sb)->s_flags; | 434 | usb3 = ubh_get_usb_third(uspi); |
401 | |||
402 | /* | 435 | /* |
403 | * Read cs structures from (usually) first data block | 436 | * Read cs structures from (usually) first data block |
404 | * on the device. | 437 | * on the device. |
@@ -475,21 +508,64 @@ failed: | |||
475 | } | 508 | } |
476 | 509 | ||
477 | /* | 510 | /* |
478 | * Put on-disk structures associated with cylinder groups and | 511 | * Sync our internal copy of fs_cstotal with disk |
479 | * write them back to disk | ||
480 | */ | 512 | */ |
481 | static void ufs_put_cylinder_structures (struct super_block *sb) | 513 | static void ufs_put_cstotal(struct super_block *sb) |
482 | { | 514 | { |
483 | struct ufs_sb_info * sbi = UFS_SB(sb); | 515 | unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE; |
484 | struct ufs_sb_private_info * uspi; | 516 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
517 | struct ufs_super_block_first *usb1; | ||
518 | struct ufs_super_block_second *usb2; | ||
519 | struct ufs_super_block_third *usb3; | ||
520 | |||
521 | UFSD("ENTER\n"); | ||
522 | usb1 = ubh_get_usb_first(uspi); | ||
523 | usb2 = ubh_get_usb_second(uspi); | ||
524 | usb3 = ubh_get_usb_third(uspi); | ||
525 | |||
526 | if ((mtype == UFS_MOUNT_UFSTYPE_44BSD && | ||
527 | (usb1->fs_flags & UFS_FLAGS_UPDATED)) || | ||
528 | mtype == UFS_MOUNT_UFSTYPE_UFS2) { | ||
529 | /*we have statistic in different place, then usual*/ | ||
530 | usb2->fs_un.fs_u2.cs_ndir = | ||
531 | cpu_to_fs64(sb, uspi->cs_total.cs_ndir); | ||
532 | usb2->fs_un.fs_u2.cs_nbfree = | ||
533 | cpu_to_fs64(sb, uspi->cs_total.cs_nbfree); | ||
534 | usb3->fs_un1.fs_u2.cs_nifree = | ||
535 | cpu_to_fs64(sb, uspi->cs_total.cs_nifree); | ||
536 | usb3->fs_un1.fs_u2.cs_nffree = | ||
537 | cpu_to_fs64(sb, uspi->cs_total.cs_nffree); | ||
538 | } else { | ||
539 | usb1->fs_cstotal.cs_ndir = | ||
540 | cpu_to_fs32(sb, uspi->cs_total.cs_ndir); | ||
541 | usb1->fs_cstotal.cs_nbfree = | ||
542 | cpu_to_fs32(sb, uspi->cs_total.cs_nbfree); | ||
543 | usb1->fs_cstotal.cs_nifree = | ||
544 | cpu_to_fs32(sb, uspi->cs_total.cs_nifree); | ||
545 | usb1->fs_cstotal.cs_nffree = | ||
546 | cpu_to_fs32(sb, uspi->cs_total.cs_nffree); | ||
547 | } | ||
548 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | ||
549 | UFSD("EXIT\n"); | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * ufs_put_super_internal() - put on-disk intrenal structures | ||
554 | * @sb: pointer to super_block structure | ||
555 | * Put on-disk structures associated with cylinder groups | ||
556 | * and write them back to disk, also update cs_total on disk | ||
557 | */ | ||
558 | static void ufs_put_super_internal(struct super_block *sb) | ||
559 | { | ||
560 | struct ufs_sb_info *sbi = UFS_SB(sb); | ||
561 | struct ufs_sb_private_info *uspi = sbi->s_uspi; | ||
485 | struct ufs_buffer_head * ubh; | 562 | struct ufs_buffer_head * ubh; |
486 | unsigned char * base, * space; | 563 | unsigned char * base, * space; |
487 | unsigned blks, size, i; | 564 | unsigned blks, size, i; |
565 | |||
488 | 566 | ||
489 | UFSD("ENTER\n"); | 567 | UFSD("ENTER\n"); |
490 | 568 | ufs_put_cstotal(sb); | |
491 | uspi = sbi->s_uspi; | ||
492 | |||
493 | size = uspi->s_cssize; | 569 | size = uspi->s_cssize; |
494 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; | 570 | blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; |
495 | base = space = (char*) sbi->s_csp; | 571 | base = space = (char*) sbi->s_csp; |
@@ -524,7 +600,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
524 | struct ufs_super_block_first * usb1; | 600 | struct ufs_super_block_first * usb1; |
525 | struct ufs_super_block_second * usb2; | 601 | struct ufs_super_block_second * usb2; |
526 | struct ufs_super_block_third * usb3; | 602 | struct ufs_super_block_third * usb3; |
527 | struct ufs_super_block *usb; | ||
528 | struct ufs_buffer_head * ubh; | 603 | struct ufs_buffer_head * ubh; |
529 | struct inode *inode; | 604 | struct inode *inode; |
530 | unsigned block_size, super_block_size; | 605 | unsigned block_size, super_block_size; |
@@ -728,8 +803,6 @@ again: | |||
728 | usb1 = ubh_get_usb_first(uspi); | 803 | usb1 = ubh_get_usb_first(uspi); |
729 | usb2 = ubh_get_usb_second(uspi); | 804 | usb2 = ubh_get_usb_second(uspi); |
730 | usb3 = ubh_get_usb_third(uspi); | 805 | usb3 = ubh_get_usb_third(uspi); |
731 | usb = (struct ufs_super_block *) | ||
732 | ((struct ufs_buffer_head *)uspi)->bh[0]->b_data ; | ||
733 | 806 | ||
734 | /* | 807 | /* |
735 | * Check ufs magic number | 808 | * Check ufs magic number |
@@ -850,8 +923,7 @@ magic_found: | |||
850 | sb->s_flags |= MS_RDONLY; | 923 | sb->s_flags |= MS_RDONLY; |
851 | break; | 924 | break; |
852 | } | 925 | } |
853 | } | 926 | } else { |
854 | else { | ||
855 | printk("ufs_read_super: fs needs fsck\n"); | 927 | printk("ufs_read_super: fs needs fsck\n"); |
856 | sb->s_flags |= MS_RDONLY; | 928 | sb->s_flags |= MS_RDONLY; |
857 | } | 929 | } |
@@ -952,7 +1024,7 @@ magic_found: | |||
952 | if (!sb->s_root) | 1024 | if (!sb->s_root) |
953 | goto dalloc_failed; | 1025 | goto dalloc_failed; |
954 | 1026 | ||
955 | 1027 | ufs_setup_cstotal(sb); | |
956 | /* | 1028 | /* |
957 | * Read cylinder group structures | 1029 | * Read cylinder group structures |
958 | */ | 1030 | */ |
@@ -1000,7 +1072,7 @@ static void ufs_write_super(struct super_block *sb) | |||
1000 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 1072 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
1001 | ufs_set_fs_state(sb, usb1, usb3, | 1073 | ufs_set_fs_state(sb, usb1, usb3, |
1002 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | 1074 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); |
1003 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 1075 | ufs_put_cstotal(sb); |
1004 | } | 1076 | } |
1005 | sb->s_dirt = 0; | 1077 | sb->s_dirt = 0; |
1006 | UFSD("EXIT\n"); | 1078 | UFSD("EXIT\n"); |
@@ -1014,7 +1086,7 @@ static void ufs_put_super(struct super_block *sb) | |||
1014 | UFSD("ENTER\n"); | 1086 | UFSD("ENTER\n"); |
1015 | 1087 | ||
1016 | if (!(sb->s_flags & MS_RDONLY)) | 1088 | if (!(sb->s_flags & MS_RDONLY)) |
1017 | ufs_put_cylinder_structures (sb); | 1089 | ufs_put_super_internal(sb); |
1018 | 1090 | ||
1019 | ubh_brelse_uspi (sbi->s_uspi); | 1091 | ubh_brelse_uspi (sbi->s_uspi); |
1020 | kfree (sbi->s_uspi); | 1092 | kfree (sbi->s_uspi); |
@@ -1049,8 +1121,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1049 | return -EINVAL; | 1121 | return -EINVAL; |
1050 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { | 1122 | if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) { |
1051 | new_mount_opt |= ufstype; | 1123 | new_mount_opt |= ufstype; |
1052 | } | 1124 | } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { |
1053 | else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { | ||
1054 | printk("ufstype can't be changed during remount\n"); | 1125 | printk("ufstype can't be changed during remount\n"); |
1055 | return -EINVAL; | 1126 | return -EINVAL; |
1056 | } | 1127 | } |
@@ -1064,7 +1135,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1064 | * fs was mouted as rw, remounting ro | 1135 | * fs was mouted as rw, remounting ro |
1065 | */ | 1136 | */ |
1066 | if (*mount_flags & MS_RDONLY) { | 1137 | if (*mount_flags & MS_RDONLY) { |
1067 | ufs_put_cylinder_structures(sb); | 1138 | ufs_put_super_internal(sb); |
1068 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | 1139 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); |
1069 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN | 1140 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN |
1070 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | 1141 | || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) |
@@ -1073,11 +1144,10 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1073 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 1144 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
1074 | sb->s_dirt = 0; | 1145 | sb->s_dirt = 0; |
1075 | sb->s_flags |= MS_RDONLY; | 1146 | sb->s_flags |= MS_RDONLY; |
1076 | } | 1147 | } else { |
1077 | /* | 1148 | /* |
1078 | * fs was mounted as ro, remounting rw | 1149 | * fs was mounted as ro, remounting rw |
1079 | */ | 1150 | */ |
1080 | else { | ||
1081 | #ifndef CONFIG_UFS_FS_WRITE | 1151 | #ifndef CONFIG_UFS_FS_WRITE |
1082 | printk("ufs was compiled with read-only support, " | 1152 | printk("ufs was compiled with read-only support, " |
1083 | "can't be mounted as read-write\n"); | 1153 | "can't be mounted as read-write\n"); |
@@ -1089,7 +1159,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1089 | printk("this ufstype is read-only supported\n"); | 1159 | printk("this ufstype is read-only supported\n"); |
1090 | return -EINVAL; | 1160 | return -EINVAL; |
1091 | } | 1161 | } |
1092 | if (!ufs_read_cylinder_structures (sb)) { | 1162 | if (!ufs_read_cylinder_structures(sb)) { |
1093 | printk("failed during remounting\n"); | 1163 | printk("failed during remounting\n"); |
1094 | return -EPERM; | 1164 | return -EPERM; |
1095 | } | 1165 | } |
@@ -1118,17 +1188,13 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1118 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { | 1188 | if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { |
1119 | buf->f_type = UFS2_MAGIC; | 1189 | buf->f_type = UFS2_MAGIC; |
1120 | buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); | 1190 | buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize); |
1121 | buf->f_bfree = ufs_blkstofrags( | ||
1122 | fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree)) + | ||
1123 | fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree); | ||
1124 | buf->f_ffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree); | ||
1125 | } else { | 1191 | } else { |
1126 | buf->f_type = UFS_MAGIC; | 1192 | buf->f_type = UFS_MAGIC; |
1127 | buf->f_blocks = uspi->s_dsize; | 1193 | buf->f_blocks = uspi->s_dsize; |
1128 | buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) + | ||
1129 | fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree); | ||
1130 | buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree); | ||
1131 | } | 1194 | } |
1195 | buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) + | ||
1196 | uspi->cs_total.cs_nffree; | ||
1197 | buf->f_ffree = uspi->cs_total.cs_nifree; | ||
1132 | buf->f_bsize = sb->s_blocksize; | 1198 | buf->f_bsize = sb->s_blocksize; |
1133 | buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree)) | 1199 | buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree)) |
1134 | ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; | 1200 | ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; |