]>
Commit | Line | Data |
---|---|---|
624e4a64 AK |
1 | /* |
2 | * quota.c --- code for handling ext4 quota inodes | |
3 | * | |
4 | */ | |
5 | ||
d1154eb4 | 6 | #include "config.h" |
624e4a64 AK |
7 | #ifdef HAVE_SYS_MOUNT_H |
8 | #include <sys/param.h> | |
9 | #include <sys/mount.h> | |
10 | #define MNT_FL (MS_MGC_VAL | MS_RDONLY) | |
11 | #endif | |
12 | #ifdef HAVE_SYS_STAT_H | |
13 | #include <sys/stat.h> | |
14 | #endif | |
15 | ||
16 | #include "e2fsck.h" | |
17 | #include "problem.h" | |
624e4a64 | 18 | |
ccbca299 TT |
19 | static errcode_t move_quota_inode(ext2_filsys fs, ext2_ino_t from_ino, |
20 | ext2_ino_t to_ino, enum quota_type qtype) | |
624e4a64 | 21 | { |
624e4a64 | 22 | struct ext2_inode inode; |
340493b6 | 23 | errcode_t retval; |
2f7d855c | 24 | char qf_name[QUOTA_NAME_LEN]; |
624e4a64 | 25 | |
ec7686e3 | 26 | /* We need the inode bitmap to be loaded */ |
ccbca299 TT |
27 | retval = ext2fs_read_bitmaps(fs); |
28 | if (retval) { | |
29 | com_err("ext2fs_read_bitmaps", retval, "%s", | |
30 | _("in move_quota_inode")); | |
31 | return retval; | |
32 | } | |
ec7686e3 | 33 | |
340493b6 TT |
34 | retval = ext2fs_read_inode(fs, from_ino, &inode); |
35 | if (retval) { | |
4d46e6c7 AD |
36 | com_err("ext2fs_read_inode", retval, "%s", |
37 | _("in move_quota_inode")); | |
ccbca299 | 38 | return retval; |
340493b6 | 39 | } |
624e4a64 AK |
40 | |
41 | inode.i_links_count = 1; | |
42 | inode.i_mode = LINUX_S_IFREG | 0600; | |
43 | inode.i_flags = EXT2_IMMUTABLE_FL; | |
86f3b6cf | 44 | if (ext2fs_has_feature_extents(fs->super)) |
624e4a64 AK |
45 | inode.i_flags |= EXT4_EXTENTS_FL; |
46 | ||
340493b6 TT |
47 | retval = ext2fs_write_new_inode(fs, to_ino, &inode); |
48 | if (retval) { | |
4d46e6c7 | 49 | com_err("ext2fs_write_new_inode", retval, "%s", |
340493b6 | 50 | _("in move_quota_inode")); |
ccbca299 | 51 | return retval; |
340493b6 TT |
52 | } |
53 | ||
624e4a64 | 54 | /* unlink the old inode */ |
a86d55da | 55 | quota_get_qf_name(qtype, QFMT_VFS_V1, qf_name); |
ccbca299 TT |
56 | retval = ext2fs_unlink(fs, EXT2_ROOT_INO, qf_name, from_ino, 0); |
57 | if (retval) { | |
58 | com_err("ext2fs_unlink", retval, "%s", | |
59 | _("in move_quota_inode")); | |
60 | return retval; | |
61 | } | |
624e4a64 | 62 | ext2fs_inode_alloc_stats(fs, from_ino, -1); |
ec7686e3 AK |
63 | /* Clear out the original inode in the inode-table block. */ |
64 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
65 | ext2fs_write_inode(fs, from_ino, &inode); | |
ccbca299 | 66 | return 0; |
624e4a64 AK |
67 | } |
68 | ||
69 | void e2fsck_hide_quota(e2fsck_t ctx) | |
70 | { | |
71 | struct ext2_super_block *sb = ctx->fs->super; | |
72 | struct problem_context pctx; | |
73 | ext2_filsys fs = ctx->fs; | |
2d2d799c LX |
74 | enum quota_type qtype; |
75 | ext2_ino_t quota_ino; | |
624e4a64 AK |
76 | |
77 | clear_problem_context(&pctx); | |
78 | ||
79 | if ((ctx->options & E2F_OPT_READONLY) || | |
86f3b6cf | 80 | !ext2fs_has_feature_quota(sb)) |
624e4a64 AK |
81 | return; |
82 | ||
2d2d799c | 83 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { |
27755289 | 84 | pctx.dir = 2; /* This is a guess, but it's a good one */ |
2d2d799c | 85 | pctx.ino = *quota_sb_inump(sb, qtype); |
27755289 | 86 | pctx.num = qtype; |
2d2d799c LX |
87 | quota_ino = quota_type2inum(qtype, fs->super); |
88 | if (pctx.ino && (pctx.ino != quota_ino) && | |
89 | fix_problem(ctx, PR_0_HIDE_QUOTA, &pctx)) { | |
ccbca299 TT |
90 | if (move_quota_inode(fs, pctx.ino, quota_ino, qtype)) |
91 | continue; | |
2d2d799c | 92 | *quota_sb_inump(sb, qtype) = quota_ino; |
d202f46d | 93 | ext2fs_mark_super_dirty(fs); |
2d2d799c | 94 | } |
624e4a64 AK |
95 | } |
96 | ||
97 | return; | |
98 | } | |
d202f46d TT |
99 | |
100 | void e2fsck_validate_quota_inodes(e2fsck_t ctx) | |
101 | { | |
102 | struct ext2_super_block *sb = ctx->fs->super; | |
103 | struct problem_context pctx; | |
104 | ext2_filsys fs = ctx->fs; | |
105 | enum quota_type qtype; | |
d202f46d TT |
106 | |
107 | clear_problem_context(&pctx); | |
108 | ||
109 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { | |
110 | pctx.ino = *quota_sb_inump(sb, qtype); | |
111 | pctx.num = qtype; | |
112 | if (pctx.ino && | |
113 | ((pctx.ino == EXT2_BAD_INO) || | |
114 | (pctx.ino == EXT2_ROOT_INO) || | |
115 | (pctx.ino == EXT2_BOOT_LOADER_INO) || | |
116 | (pctx.ino == EXT2_UNDEL_DIR_INO) || | |
117 | (pctx.ino == EXT2_RESIZE_INO) || | |
118 | (pctx.ino == EXT2_JOURNAL_INO) || | |
119 | (pctx.ino == EXT2_EXCLUDE_INO) || | |
120 | (pctx.ino == EXT4_REPLICA_INO) || | |
121 | (pctx.ino > fs->super->s_inodes_count)) && | |
122 | fix_problem(ctx, PR_0_INVALID_QUOTA_INO, &pctx)) { | |
123 | *quota_sb_inump(sb, qtype) = 0; | |
124 | ext2fs_mark_super_dirty(fs); | |
125 | } | |
126 | } | |
127 | } |