diff options
-rw-r--r-- | fs/Kconfig | 2 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 21 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 17 |
4 files changed, 39 insertions, 3 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index c1ce3d8831d8..f9b6e2979aaa 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -189,6 +189,8 @@ config OCFS2_FS | |||
189 | select CONFIGFS_FS | 189 | select CONFIGFS_FS |
190 | select JBD2 | 190 | select JBD2 |
191 | select CRC32 | 191 | select CRC32 |
192 | select QUOTA | ||
193 | select QUOTA_TREE | ||
192 | help | 194 | help |
193 | OCFS2 is a general purpose extent based shared disk cluster file | 195 | OCFS2 is a general purpose extent based shared disk cluster file |
194 | system with many similarities to ext3. It supports 64 bit inode | 196 | system with many similarities to ext3. It supports 64 bit inode |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index ec3497bafda6..ec25d9984192 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -283,6 +283,8 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
283 | mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino); | 283 | mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino); |
284 | } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) { | 284 | } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) { |
285 | OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; | 285 | OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; |
286 | } else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) { | ||
287 | inode->i_flags |= S_NOQUOTA; | ||
286 | } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) { | 288 | } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) { |
287 | mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino); | 289 | mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino); |
288 | /* we can't actually hit this as read_inode can't | 290 | /* we can't actually hit this as read_inode can't |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 5e0c0d0aef7d..06e3bd632ff3 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -94,7 +94,7 @@ | |||
94 | | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \ | 94 | | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \ |
95 | | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \ | 95 | | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \ |
96 | | OCFS2_FEATURE_INCOMPAT_XATTR) | 96 | | OCFS2_FEATURE_INCOMPAT_XATTR) |
97 | #define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN | 97 | #define OCFS2_FEATURE_RO_COMPAT_SUPP (OCFS2_FEATURE_RO_COMPAT_UNWRITTEN) |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * Heartbeat-only devices are missing journals and other files. The | 100 | * Heartbeat-only devices are missing journals and other files. The |
@@ -163,6 +163,12 @@ | |||
163 | */ | 163 | */ |
164 | #define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001 | 164 | #define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001 |
165 | 165 | ||
166 | /* | ||
167 | * Maintain quota information for this filesystem | ||
168 | */ | ||
169 | #define OCFS2_FEATURE_RO_COMPAT_USRQUOTA 0x0002 | ||
170 | #define OCFS2_FEATURE_RO_COMPAT_GRPQUOTA 0x0004 | ||
171 | |||
166 | /* The byte offset of the first backup block will be 1G. | 172 | /* The byte offset of the first backup block will be 1G. |
167 | * The following will be 4G, 16G, 64G, 256G and 1T. | 173 | * The following will be 4G, 16G, 64G, 256G and 1T. |
168 | */ | 174 | */ |
@@ -192,6 +198,7 @@ | |||
192 | #define OCFS2_HEARTBEAT_FL (0x00000200) /* Heartbeat area */ | 198 | #define OCFS2_HEARTBEAT_FL (0x00000200) /* Heartbeat area */ |
193 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ | 199 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
194 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ | 200 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
201 | #define OCFS2_QUOTA_FL (0x00001000) /* Quota file */ | ||
195 | 202 | ||
196 | /* | 203 | /* |
197 | * Flags on ocfs2_dinode.i_dyn_features | 204 | * Flags on ocfs2_dinode.i_dyn_features |
@@ -329,13 +336,17 @@ enum { | |||
329 | #define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE | 336 | #define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE |
330 | HEARTBEAT_SYSTEM_INODE, | 337 | HEARTBEAT_SYSTEM_INODE, |
331 | GLOBAL_BITMAP_SYSTEM_INODE, | 338 | GLOBAL_BITMAP_SYSTEM_INODE, |
332 | #define OCFS2_LAST_GLOBAL_SYSTEM_INODE GLOBAL_BITMAP_SYSTEM_INODE | 339 | USER_QUOTA_SYSTEM_INODE, |
340 | GROUP_QUOTA_SYSTEM_INODE, | ||
341 | #define OCFS2_LAST_GLOBAL_SYSTEM_INODE GROUP_QUOTA_SYSTEM_INODE | ||
333 | ORPHAN_DIR_SYSTEM_INODE, | 342 | ORPHAN_DIR_SYSTEM_INODE, |
334 | EXTENT_ALLOC_SYSTEM_INODE, | 343 | EXTENT_ALLOC_SYSTEM_INODE, |
335 | INODE_ALLOC_SYSTEM_INODE, | 344 | INODE_ALLOC_SYSTEM_INODE, |
336 | JOURNAL_SYSTEM_INODE, | 345 | JOURNAL_SYSTEM_INODE, |
337 | LOCAL_ALLOC_SYSTEM_INODE, | 346 | LOCAL_ALLOC_SYSTEM_INODE, |
338 | TRUNCATE_LOG_SYSTEM_INODE, | 347 | TRUNCATE_LOG_SYSTEM_INODE, |
348 | LOCAL_USER_QUOTA_SYSTEM_INODE, | ||
349 | LOCAL_GROUP_QUOTA_SYSTEM_INODE, | ||
339 | NUM_SYSTEM_INODES | 350 | NUM_SYSTEM_INODES |
340 | }; | 351 | }; |
341 | 352 | ||
@@ -349,6 +360,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { | |||
349 | [SLOT_MAP_SYSTEM_INODE] = { "slot_map", 0, S_IFREG | 0644 }, | 360 | [SLOT_MAP_SYSTEM_INODE] = { "slot_map", 0, S_IFREG | 0644 }, |
350 | [HEARTBEAT_SYSTEM_INODE] = { "heartbeat", OCFS2_HEARTBEAT_FL, S_IFREG | 0644 }, | 361 | [HEARTBEAT_SYSTEM_INODE] = { "heartbeat", OCFS2_HEARTBEAT_FL, S_IFREG | 0644 }, |
351 | [GLOBAL_BITMAP_SYSTEM_INODE] = { "global_bitmap", 0, S_IFREG | 0644 }, | 362 | [GLOBAL_BITMAP_SYSTEM_INODE] = { "global_bitmap", 0, S_IFREG | 0644 }, |
363 | [USER_QUOTA_SYSTEM_INODE] = { "aquota.user", OCFS2_QUOTA_FL, S_IFREG | 0644 }, | ||
364 | [GROUP_QUOTA_SYSTEM_INODE] = { "aquota.group", OCFS2_QUOTA_FL, S_IFREG | 0644 }, | ||
352 | 365 | ||
353 | /* Slot-specific system inodes (one copy per slot) */ | 366 | /* Slot-specific system inodes (one copy per slot) */ |
354 | [ORPHAN_DIR_SYSTEM_INODE] = { "orphan_dir:%04d", 0, S_IFDIR | 0755 }, | 367 | [ORPHAN_DIR_SYSTEM_INODE] = { "orphan_dir:%04d", 0, S_IFDIR | 0755 }, |
@@ -356,7 +369,9 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { | |||
356 | [INODE_ALLOC_SYSTEM_INODE] = { "inode_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 }, | 369 | [INODE_ALLOC_SYSTEM_INODE] = { "inode_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 }, |
357 | [JOURNAL_SYSTEM_INODE] = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 }, | 370 | [JOURNAL_SYSTEM_INODE] = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 }, |
358 | [LOCAL_ALLOC_SYSTEM_INODE] = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 }, | 371 | [LOCAL_ALLOC_SYSTEM_INODE] = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 }, |
359 | [TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 } | 372 | [TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 }, |
373 | [LOCAL_USER_QUOTA_SYSTEM_INODE] = { "aquota.user:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 }, | ||
374 | [LOCAL_GROUP_QUOTA_SYSTEM_INODE] = { "aquota.group:%04d", OCFS2_QUOTA_FL, S_IFREG | 0644 }, | ||
360 | }; | 375 | }; |
361 | 376 | ||
362 | /* Parameter passed from mount.ocfs2 to module */ | 377 | /* Parameter passed from mount.ocfs2 to module */ |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 9e7accc68b4b..41bb0197cf4c 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -225,6 +225,19 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait) | |||
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int ocfs2_need_system_inode(struct ocfs2_super *osb, int ino) | ||
229 | { | ||
230 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_USRQUOTA) | ||
231 | && (ino == USER_QUOTA_SYSTEM_INODE | ||
232 | || ino == LOCAL_USER_QUOTA_SYSTEM_INODE)) | ||
233 | return 0; | ||
234 | if (!OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, OCFS2_FEATURE_RO_COMPAT_GRPQUOTA) | ||
235 | && (ino == GROUP_QUOTA_SYSTEM_INODE | ||
236 | || ino == LOCAL_GROUP_QUOTA_SYSTEM_INODE)) | ||
237 | return 0; | ||
238 | return 1; | ||
239 | } | ||
240 | |||
228 | static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) | 241 | static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) |
229 | { | 242 | { |
230 | struct inode *new = NULL; | 243 | struct inode *new = NULL; |
@@ -251,6 +264,8 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) | |||
251 | 264 | ||
252 | for (i = OCFS2_FIRST_ONLINE_SYSTEM_INODE; | 265 | for (i = OCFS2_FIRST_ONLINE_SYSTEM_INODE; |
253 | i <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; i++) { | 266 | i <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; i++) { |
267 | if (!ocfs2_need_system_inode(osb, i)) | ||
268 | continue; | ||
254 | new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); | 269 | new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); |
255 | if (!new) { | 270 | if (!new) { |
256 | ocfs2_release_system_inodes(osb); | 271 | ocfs2_release_system_inodes(osb); |
@@ -281,6 +296,8 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) | |||
281 | for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; | 296 | for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; |
282 | i < NUM_SYSTEM_INODES; | 297 | i < NUM_SYSTEM_INODES; |
283 | i++) { | 298 | i++) { |
299 | if (!ocfs2_need_system_inode(osb, i)) | ||
300 | continue; | ||
284 | new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); | 301 | new = ocfs2_get_system_file_inode(osb, i, osb->slot_num); |
285 | if (!new) { | 302 | if (!new) { |
286 | ocfs2_release_system_inodes(osb); | 303 | ocfs2_release_system_inodes(osb); |