diff options
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r-- | fs/ocfs2/super.c | 147 |
1 files changed, 109 insertions, 38 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index dee03197a494..fa1be1b304d1 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -94,7 +94,9 @@ struct mount_options | |||
94 | unsigned long mount_opt; | 94 | unsigned long mount_opt; |
95 | unsigned int atime_quantum; | 95 | unsigned int atime_quantum; |
96 | signed short slot; | 96 | signed short slot; |
97 | unsigned int localalloc_opt; | 97 | int localalloc_opt; |
98 | unsigned int resv_level; | ||
99 | int dir_resv_level; | ||
98 | char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; | 100 | char cluster_stack[OCFS2_STACK_LABEL_LEN + 1]; |
99 | }; | 101 | }; |
100 | 102 | ||
@@ -143,8 +145,7 @@ static const struct super_operations ocfs2_sops = { | |||
143 | .alloc_inode = ocfs2_alloc_inode, | 145 | .alloc_inode = ocfs2_alloc_inode, |
144 | .destroy_inode = ocfs2_destroy_inode, | 146 | .destroy_inode = ocfs2_destroy_inode, |
145 | .drop_inode = ocfs2_drop_inode, | 147 | .drop_inode = ocfs2_drop_inode, |
146 | .clear_inode = ocfs2_clear_inode, | 148 | .evict_inode = ocfs2_evict_inode, |
147 | .delete_inode = ocfs2_delete_inode, | ||
148 | .sync_fs = ocfs2_sync_fs, | 149 | .sync_fs = ocfs2_sync_fs, |
149 | .put_super = ocfs2_put_super, | 150 | .put_super = ocfs2_put_super, |
150 | .remount_fs = ocfs2_remount, | 151 | .remount_fs = ocfs2_remount, |
@@ -176,6 +177,8 @@ enum { | |||
176 | Opt_noacl, | 177 | Opt_noacl, |
177 | Opt_usrquota, | 178 | Opt_usrquota, |
178 | Opt_grpquota, | 179 | Opt_grpquota, |
180 | Opt_resv_level, | ||
181 | Opt_dir_resv_level, | ||
179 | Opt_err, | 182 | Opt_err, |
180 | }; | 183 | }; |
181 | 184 | ||
@@ -202,6 +205,8 @@ static const match_table_t tokens = { | |||
202 | {Opt_noacl, "noacl"}, | 205 | {Opt_noacl, "noacl"}, |
203 | {Opt_usrquota, "usrquota"}, | 206 | {Opt_usrquota, "usrquota"}, |
204 | {Opt_grpquota, "grpquota"}, | 207 | {Opt_grpquota, "grpquota"}, |
208 | {Opt_resv_level, "resv_level=%u"}, | ||
209 | {Opt_dir_resv_level, "dir_resv_level=%u"}, | ||
205 | {Opt_err, NULL} | 210 | {Opt_err, NULL} |
206 | }; | 211 | }; |
207 | 212 | ||
@@ -873,13 +878,15 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend) | |||
873 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) | 878 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) |
874 | continue; | 879 | continue; |
875 | if (unsuspend) | 880 | if (unsuspend) |
876 | status = vfs_quota_enable( | 881 | status = dquot_resume(sb, type); |
877 | sb_dqopt(sb)->files[type], | 882 | else { |
878 | type, QFMT_OCFS2, | 883 | struct ocfs2_mem_dqinfo *oinfo; |
879 | DQUOT_SUSPENDED); | 884 | |
880 | else | 885 | /* Cancel periodic syncing before suspending */ |
881 | status = vfs_quota_disable(sb, type, | 886 | oinfo = sb_dqinfo(sb, type)->dqi_priv; |
882 | DQUOT_SUSPENDED); | 887 | cancel_delayed_work_sync(&oinfo->dqi_sync_work); |
888 | status = dquot_suspend(sb, type); | ||
889 | } | ||
883 | if (status < 0) | 890 | if (status < 0) |
884 | break; | 891 | break; |
885 | } | 892 | } |
@@ -910,8 +917,8 @@ static int ocfs2_enable_quotas(struct ocfs2_super *osb) | |||
910 | status = -ENOENT; | 917 | status = -ENOENT; |
911 | goto out_quota_off; | 918 | goto out_quota_off; |
912 | } | 919 | } |
913 | status = vfs_quota_enable(inode[type], type, QFMT_OCFS2, | 920 | status = dquot_enable(inode[type], type, QFMT_OCFS2, |
914 | DQUOT_USAGE_ENABLED); | 921 | DQUOT_USAGE_ENABLED); |
915 | if (status < 0) | 922 | if (status < 0) |
916 | goto out_quota_off; | 923 | goto out_quota_off; |
917 | } | 924 | } |
@@ -932,18 +939,22 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) | |||
932 | int type; | 939 | int type; |
933 | struct inode *inode; | 940 | struct inode *inode; |
934 | struct super_block *sb = osb->sb; | 941 | struct super_block *sb = osb->sb; |
942 | struct ocfs2_mem_dqinfo *oinfo; | ||
935 | 943 | ||
936 | /* We mostly ignore errors in this function because there's not much | 944 | /* We mostly ignore errors in this function because there's not much |
937 | * we can do when we see them */ | 945 | * we can do when we see them */ |
938 | for (type = 0; type < MAXQUOTAS; type++) { | 946 | for (type = 0; type < MAXQUOTAS; type++) { |
939 | if (!sb_has_quota_loaded(sb, type)) | 947 | if (!sb_has_quota_loaded(sb, type)) |
940 | continue; | 948 | continue; |
949 | /* Cancel periodic syncing before we grab dqonoff_mutex */ | ||
950 | oinfo = sb_dqinfo(sb, type)->dqi_priv; | ||
951 | cancel_delayed_work_sync(&oinfo->dqi_sync_work); | ||
941 | inode = igrab(sb->s_dquot.files[type]); | 952 | inode = igrab(sb->s_dquot.files[type]); |
942 | /* Turn off quotas. This will remove all dquot structures from | 953 | /* Turn off quotas. This will remove all dquot structures from |
943 | * memory and so they will be automatically synced to global | 954 | * memory and so they will be automatically synced to global |
944 | * quota files */ | 955 | * quota files */ |
945 | vfs_quota_disable(sb, type, DQUOT_USAGE_ENABLED | | 956 | dquot_disable(sb, type, DQUOT_USAGE_ENABLED | |
946 | DQUOT_LIMITS_ENABLED); | 957 | DQUOT_LIMITS_ENABLED); |
947 | if (!inode) | 958 | if (!inode) |
948 | continue; | 959 | continue; |
949 | iput(inode); | 960 | iput(inode); |
@@ -952,7 +963,7 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) | |||
952 | 963 | ||
953 | /* Handle quota on quotactl */ | 964 | /* Handle quota on quotactl */ |
954 | static int ocfs2_quota_on(struct super_block *sb, int type, int format_id, | 965 | static int ocfs2_quota_on(struct super_block *sb, int type, int format_id, |
955 | char *path, int remount) | 966 | char *path) |
956 | { | 967 | { |
957 | unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, | 968 | unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA, |
958 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; | 969 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA}; |
@@ -960,30 +971,24 @@ static int ocfs2_quota_on(struct super_block *sb, int type, int format_id, | |||
960 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) | 971 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type])) |
961 | return -EINVAL; | 972 | return -EINVAL; |
962 | 973 | ||
963 | if (remount) | 974 | return dquot_enable(sb_dqopt(sb)->files[type], type, |
964 | return 0; /* Just ignore it has been handled in | 975 | format_id, DQUOT_LIMITS_ENABLED); |
965 | * ocfs2_remount() */ | ||
966 | return vfs_quota_enable(sb_dqopt(sb)->files[type], type, | ||
967 | format_id, DQUOT_LIMITS_ENABLED); | ||
968 | } | 976 | } |
969 | 977 | ||
970 | /* Handle quota off quotactl */ | 978 | /* Handle quota off quotactl */ |
971 | static int ocfs2_quota_off(struct super_block *sb, int type, int remount) | 979 | static int ocfs2_quota_off(struct super_block *sb, int type) |
972 | { | 980 | { |
973 | if (remount) | 981 | return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED); |
974 | return 0; /* Ignore now and handle later in | ||
975 | * ocfs2_remount() */ | ||
976 | return vfs_quota_disable(sb, type, DQUOT_LIMITS_ENABLED); | ||
977 | } | 982 | } |
978 | 983 | ||
979 | static const struct quotactl_ops ocfs2_quotactl_ops = { | 984 | static const struct quotactl_ops ocfs2_quotactl_ops = { |
980 | .quota_on = ocfs2_quota_on, | 985 | .quota_on = ocfs2_quota_on, |
981 | .quota_off = ocfs2_quota_off, | 986 | .quota_off = ocfs2_quota_off, |
982 | .quota_sync = vfs_quota_sync, | 987 | .quota_sync = dquot_quota_sync, |
983 | .get_info = vfs_get_dqinfo, | 988 | .get_info = dquot_get_dqinfo, |
984 | .set_info = vfs_set_dqinfo, | 989 | .set_info = dquot_set_dqinfo, |
985 | .get_dqblk = vfs_get_dqblk, | 990 | .get_dqblk = dquot_get_dqblk, |
986 | .set_dqblk = vfs_set_dqblk, | 991 | .set_dqblk = dquot_set_dqblk, |
987 | }; | 992 | }; |
988 | 993 | ||
989 | static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | 994 | static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) |
@@ -1028,8 +1033,14 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
1028 | osb->s_atime_quantum = parsed_options.atime_quantum; | 1033 | osb->s_atime_quantum = parsed_options.atime_quantum; |
1029 | osb->preferred_slot = parsed_options.slot; | 1034 | osb->preferred_slot = parsed_options.slot; |
1030 | osb->osb_commit_interval = parsed_options.commit_interval; | 1035 | osb->osb_commit_interval = parsed_options.commit_interval; |
1031 | osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt); | 1036 | |
1032 | osb->local_alloc_bits = osb->local_alloc_default_bits; | 1037 | ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt); |
1038 | osb->osb_resv_level = parsed_options.resv_level; | ||
1039 | osb->osb_dir_resv_level = parsed_options.resv_level; | ||
1040 | if (parsed_options.dir_resv_level == -1) | ||
1041 | osb->osb_dir_resv_level = parsed_options.resv_level; | ||
1042 | else | ||
1043 | osb->osb_dir_resv_level = parsed_options.dir_resv_level; | ||
1033 | 1044 | ||
1034 | status = ocfs2_verify_userspace_stack(osb, &parsed_options); | 1045 | status = ocfs2_verify_userspace_stack(osb, &parsed_options); |
1035 | if (status) | 1046 | if (status) |
@@ -1285,11 +1296,13 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1285 | options ? options : "(none)"); | 1296 | options ? options : "(none)"); |
1286 | 1297 | ||
1287 | mopt->commit_interval = 0; | 1298 | mopt->commit_interval = 0; |
1288 | mopt->mount_opt = 0; | 1299 | mopt->mount_opt = OCFS2_MOUNT_NOINTR; |
1289 | mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; | 1300 | mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM; |
1290 | mopt->slot = OCFS2_INVALID_SLOT; | 1301 | mopt->slot = OCFS2_INVALID_SLOT; |
1291 | mopt->localalloc_opt = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE; | 1302 | mopt->localalloc_opt = -1; |
1292 | mopt->cluster_stack[0] = '\0'; | 1303 | mopt->cluster_stack[0] = '\0'; |
1304 | mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL; | ||
1305 | mopt->dir_resv_level = -1; | ||
1293 | 1306 | ||
1294 | if (!options) { | 1307 | if (!options) { |
1295 | status = 1; | 1308 | status = 1; |
@@ -1380,7 +1393,7 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1380 | status = 0; | 1393 | status = 0; |
1381 | goto bail; | 1394 | goto bail; |
1382 | } | 1395 | } |
1383 | if (option >= 0 && (option <= ocfs2_local_alloc_size(sb) * 8)) | 1396 | if (option >= 0) |
1384 | mopt->localalloc_opt = option; | 1397 | mopt->localalloc_opt = option; |
1385 | break; | 1398 | break; |
1386 | case Opt_localflocks: | 1399 | case Opt_localflocks: |
@@ -1433,6 +1446,28 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1433 | mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL; | 1446 | mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL; |
1434 | mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL; | 1447 | mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL; |
1435 | break; | 1448 | break; |
1449 | case Opt_resv_level: | ||
1450 | if (is_remount) | ||
1451 | break; | ||
1452 | if (match_int(&args[0], &option)) { | ||
1453 | status = 0; | ||
1454 | goto bail; | ||
1455 | } | ||
1456 | if (option >= OCFS2_MIN_RESV_LEVEL && | ||
1457 | option < OCFS2_MAX_RESV_LEVEL) | ||
1458 | mopt->resv_level = option; | ||
1459 | break; | ||
1460 | case Opt_dir_resv_level: | ||
1461 | if (is_remount) | ||
1462 | break; | ||
1463 | if (match_int(&args[0], &option)) { | ||
1464 | status = 0; | ||
1465 | goto bail; | ||
1466 | } | ||
1467 | if (option >= OCFS2_MIN_RESV_LEVEL && | ||
1468 | option < OCFS2_MAX_RESV_LEVEL) | ||
1469 | mopt->dir_resv_level = option; | ||
1470 | break; | ||
1436 | default: | 1471 | default: |
1437 | mlog(ML_ERROR, | 1472 | mlog(ML_ERROR, |
1438 | "Unrecognized mount option \"%s\" " | 1473 | "Unrecognized mount option \"%s\" " |
@@ -1487,7 +1522,7 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1487 | (unsigned) (osb->osb_commit_interval / HZ)); | 1522 | (unsigned) (osb->osb_commit_interval / HZ)); |
1488 | 1523 | ||
1489 | local_alloc_megs = osb->local_alloc_bits >> (20 - osb->s_clustersize_bits); | 1524 | local_alloc_megs = osb->local_alloc_bits >> (20 - osb->s_clustersize_bits); |
1490 | if (local_alloc_megs != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE) | 1525 | if (local_alloc_megs != ocfs2_la_default_mb(osb)) |
1491 | seq_printf(s, ",localalloc=%d", local_alloc_megs); | 1526 | seq_printf(s, ",localalloc=%d", local_alloc_megs); |
1492 | 1527 | ||
1493 | if (opts & OCFS2_MOUNT_LOCALFLOCKS) | 1528 | if (opts & OCFS2_MOUNT_LOCALFLOCKS) |
@@ -1514,6 +1549,12 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1514 | else | 1549 | else |
1515 | seq_printf(s, ",noacl"); | 1550 | seq_printf(s, ",noacl"); |
1516 | 1551 | ||
1552 | if (osb->osb_resv_level != OCFS2_DEFAULT_RESV_LEVEL) | ||
1553 | seq_printf(s, ",resv_level=%d", osb->osb_resv_level); | ||
1554 | |||
1555 | if (osb->osb_dir_resv_level != osb->osb_resv_level) | ||
1556 | seq_printf(s, ",dir_resv_level=%d", osb->osb_resv_level); | ||
1557 | |||
1517 | return 0; | 1558 | return 0; |
1518 | } | 1559 | } |
1519 | 1560 | ||
@@ -1688,6 +1729,8 @@ static void ocfs2_inode_init_once(void *data) | |||
1688 | oi->ip_blkno = 0ULL; | 1729 | oi->ip_blkno = 0ULL; |
1689 | oi->ip_clusters = 0; | 1730 | oi->ip_clusters = 0; |
1690 | 1731 | ||
1732 | ocfs2_resv_init_once(&oi->ip_la_data_resv); | ||
1733 | |||
1691 | ocfs2_lock_res_init_once(&oi->ip_rw_lockres); | 1734 | ocfs2_lock_res_init_once(&oi->ip_rw_lockres); |
1692 | ocfs2_lock_res_init_once(&oi->ip_inode_lockres); | 1735 | ocfs2_lock_res_init_once(&oi->ip_inode_lockres); |
1693 | ocfs2_lock_res_init_once(&oi->ip_open_lockres); | 1736 | ocfs2_lock_res_init_once(&oi->ip_open_lockres); |
@@ -2042,6 +2085,12 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2042 | 2085 | ||
2043 | init_waitqueue_head(&osb->osb_mount_event); | 2086 | init_waitqueue_head(&osb->osb_mount_event); |
2044 | 2087 | ||
2088 | status = ocfs2_resmap_init(osb, &osb->osb_la_resmap); | ||
2089 | if (status) { | ||
2090 | mlog_errno(status); | ||
2091 | goto bail; | ||
2092 | } | ||
2093 | |||
2045 | osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); | 2094 | osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); |
2046 | if (!osb->vol_label) { | 2095 | if (!osb->vol_label) { |
2047 | mlog(ML_ERROR, "unable to alloc vol label\n"); | 2096 | mlog(ML_ERROR, "unable to alloc vol label\n"); |
@@ -2224,9 +2273,11 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
2224 | } | 2273 | } |
2225 | 2274 | ||
2226 | osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno; | 2275 | osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno; |
2276 | osb->osb_clusters_at_boot = OCFS2_I(inode)->ip_clusters; | ||
2227 | iput(inode); | 2277 | iput(inode); |
2228 | 2278 | ||
2229 | osb->bitmap_cpg = ocfs2_group_bitmap_size(sb) * 8; | 2279 | osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0, |
2280 | osb->s_feature_incompat) * 8; | ||
2230 | 2281 | ||
2231 | status = ocfs2_init_slot_info(osb); | 2282 | status = ocfs2_init_slot_info(osb); |
2232 | if (status < 0) { | 2283 | if (status < 0) { |
@@ -2420,7 +2471,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) | |||
2420 | kfree(osb->slot_recovery_generations); | 2471 | kfree(osb->slot_recovery_generations); |
2421 | /* FIXME | 2472 | /* FIXME |
2422 | * This belongs in journal shutdown, but because we have to | 2473 | * This belongs in journal shutdown, but because we have to |
2423 | * allocate osb->journal at the start of ocfs2_initalize_osb(), | 2474 | * allocate osb->journal at the start of ocfs2_initialize_osb(), |
2424 | * we free it here. | 2475 | * we free it here. |
2425 | */ | 2476 | */ |
2426 | kfree(osb->journal); | 2477 | kfree(osb->journal); |
@@ -2509,5 +2560,25 @@ void __ocfs2_abort(struct super_block* sb, | |||
2509 | ocfs2_handle_error(sb); | 2560 | ocfs2_handle_error(sb); |
2510 | } | 2561 | } |
2511 | 2562 | ||
2563 | /* | ||
2564 | * Void signal blockers, because in-kernel sigprocmask() only fails | ||
2565 | * when SIG_* is wrong. | ||
2566 | */ | ||
2567 | void ocfs2_block_signals(sigset_t *oldset) | ||
2568 | { | ||
2569 | int rc; | ||
2570 | sigset_t blocked; | ||
2571 | |||
2572 | sigfillset(&blocked); | ||
2573 | rc = sigprocmask(SIG_BLOCK, &blocked, oldset); | ||
2574 | BUG_ON(rc); | ||
2575 | } | ||
2576 | |||
2577 | void ocfs2_unblock_signals(sigset_t *oldset) | ||
2578 | { | ||
2579 | int rc = sigprocmask(SIG_SETMASK, oldset, NULL); | ||
2580 | BUG_ON(rc); | ||
2581 | } | ||
2582 | |||
2512 | module_init(ocfs2_init); | 2583 | module_init(ocfs2_init); |
2513 | module_exit(ocfs2_exit); | 2584 | module_exit(ocfs2_exit); |