1 Index: linux-2.6.7/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.6.7.orig/fs/ext3/ialloc.c 2004-08-27 14:28:16.000000000 +0800
4 +++ linux-2.6.7/fs/ext3/ialloc.c 2004-08-27 14:29:21.000000000 +0800
6 * the free blocks count in the block.
10 + * this is very simple policy: files with O_INRESERVE goes to last group;
11 + * files with no O_INRESERVE goes to all groups, but last. probably we'll
12 + * specify group for O_INRESERVE files later -bzzz */
13 +static inline int ext3_group_allowed(struct super_block *sb, int mode, int group)
15 + if (!test_opt(sb, INRESERVE) || EXT3_SB(sb)->s_groups_count == 1)
18 + if (mode & EXT3_S_INRESERVE) {
19 + if (group != EXT3_SB(sb)->s_groups_count - 1)
22 + if (group == EXT3_SB(sb)->s_groups_count -1 )
29 * Read the inode allocation bitmap for a given block_group, reading
31 * For other inodes, search forward from the parent directory\'s block
32 * group to find a free inode.
34 -static int find_group_dir(struct super_block *sb, struct inode *parent)
35 +static int find_group_dir(struct super_block *sb, struct inode *parent, int mode)
37 int ngroups = EXT3_SB(sb)->s_groups_count;
40 avefreei = freei / ngroups;
42 for (group = 0; group < ngroups; group++) {
43 + if (!ext3_group_allowed(sb, mode, group))
45 desc = ext3_get_group_desc (sb, group, &bh);
46 if (!desc || !desc->bg_free_inodes_count)
50 #define BLOCK_COST 256
52 -static int find_group_orlov(struct super_block *sb, struct inode *parent)
53 +static int find_group_orlov(struct super_block *sb, struct inode *parent, int mode)
55 int parent_group = EXT3_I(parent)->i_block_group;
56 struct ext3_sb_info *sbi = EXT3_SB(sb);
58 parent_group = (unsigned)group % ngroups;
59 for (i = 0; i < ngroups; i++) {
60 group = (parent_group + i) % ngroups;
61 + if (!ext3_group_allowed(sb, mode, group))
63 desc = ext3_get_group_desc (sb, group, &bh);
64 if (!desc || !desc->bg_free_inodes_count)
70 -static int find_group_other(struct super_block *sb, struct inode *parent)
71 +static int find_group_other(struct super_block *sb, struct inode *parent, int mode)
73 int parent_group = EXT3_I(parent)->i_block_group;
74 int ngroups = EXT3_SB(sb)->s_groups_count;
79 + if (!ext3_group_allowed(sb, mode, group))
81 desc = ext3_get_group_desc (sb, group, &bh);
82 if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
83 le16_to_cpu(desc->bg_free_blocks_count))
85 for (i = 0; i < ngroups; i++) {
86 if (++group >= ngroups)
88 + if (!ext3_group_allowed(sb, mode, group))
90 desc = ext3_get_group_desc (sb, group, &bh);
91 if (desc && le16_to_cpu(desc->bg_free_inodes_count))
96 if (test_opt (sb, OLDALLOC))
97 - group = find_group_dir(sb, dir);
98 + group = find_group_dir(sb, dir, mode);
100 - group = find_group_orlov(sb, dir);
101 + group = find_group_orlov(sb, dir, mode);
103 - group = find_group_other(sb, dir);
104 + group = find_group_other(sb, dir, mode);
110 for (i = 0; i < sbi->s_groups_count; i++) {
111 - gdp = ext3_get_group_desc(sb, group, &bh2);
112 + if (ext3_group_allowed(sb, mode, group)) {
113 + gdp = ext3_get_group_desc(sb, group, &bh2);
117 - bitmap_bh = read_inode_bitmap(sb, group);
122 + bitmap_bh = read_inode_bitmap(sb, group);
128 + repeat_in_this_group:
129 + ino = ext3_find_next_zero_bit((unsigned long *)
130 + bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
131 + if (ino < EXT3_INODES_PER_GROUP(sb)) {
132 + if (ext3_test_allocatable(ino, bitmap_bh)) {
135 + J_ASSERT_BH(bitmap_bh, bh2jh(bitmap_bh)->b_committed_data);
139 -repeat_in_this_group:
140 - ino = ext3_find_next_zero_bit((unsigned long *)
141 - bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
142 - if (ino < EXT3_INODES_PER_GROUP(sb)) {
143 - if (ext3_test_allocatable(ino, bitmap_bh)) {
145 + if (++ino < EXT3_INODES_PER_GROUP(sb))
146 + goto repeat_in_this_group;
148 - J_ASSERT_BH(bitmap_bh, bh2jh(bitmap_bh)->b_committed_data);
150 - if (++ino < EXT3_INODES_PER_GROUP(sb))
151 - goto repeat_in_this_group;
155 * This case is possible in concurrent environment. It is very
156 * rare. We cannot repeat the find_group_xxx() call because
163 BUFFER_TRACE(bitmap_bh, "get_undo_access");
164 err = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
166 if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data)
167 J_ASSERT_BH(bitmap_bh, !ext3_test_bit(ino, bh2jh(bitmap_bh)->b_committed_data));
169 + J_ASSERT(ext3_group_allowed(sb, mode, group));
170 ino += group * EXT3_INODES_PER_GROUP(sb) + 1;
171 if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
172 ext3_error (sb, "ext3_new_inode",
176 inode->i_gid = current->fsgid;
177 - inode->i_mode = mode;
178 + inode->i_mode = mode & ~EXT3_S_INRESERVE;
181 /* This is the optimal IO size (for stat), not the fs block size */
182 Index: linux-2.6.7/fs/ext3/super.c
183 ===================================================================
184 --- linux-2.6.7.orig/fs/ext3/super.c 2004-08-27 12:04:38.000000000 +0800
185 +++ linux-2.6.7/fs/ext3/super.c 2004-08-27 14:28:22.000000000 +0800
187 {Opt_iopen_nopriv, "iopen_nopriv"},
188 {Opt_extents, "extents"},
189 {Opt_extdebug, "extdebug"},
190 + {Opt_inrsv, "inrsv"},
196 set_opt (sbi->s_mount_opt, EXTDEBUG);
199 + set_opt (sbi->s_mount_opt, INRESERVE);
200 + J_ASSERT((EXT3_S_INRESERVE & S_IALLUGO) == 0);
204 "EXT3-fs: Unrecognized mount option \"%s\" "
205 Index: linux-2.6.7/fs/ext3/namei.c
206 ===================================================================
207 --- linux-2.6.7.orig/fs/ext3/namei.c 2004-08-27 13:03:21.000000000 +0800
208 +++ linux-2.6.7/fs/ext3/namei.c 2004-08-27 14:36:09.000000000 +0800
209 @@ -1701,6 +1701,36 @@
213 +static int ext3_create_it (struct inode * dir, struct dentry * dentry, int mode,
214 + struct lookup_intent *it)
217 + struct inode * inode;
220 + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
221 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
222 + if (IS_ERR(handle)) {
223 + return PTR_ERR(handle);
227 + handle->h_sync = 1;
229 + if (it && it->it_flags & O_INRESERVE)
230 + mode |= EXT3_S_INRESERVE;
231 + inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
232 + err = PTR_ERR(inode);
233 + if (!IS_ERR(inode)) {
234 + inode->i_op = &ext3_file_inode_operations;
235 + inode->i_fop = &ext3_file_operations;
236 + ext3_set_aops(inode);
237 + err = ext3_add_nondir(handle, dentry, inode);
239 + ext3_journal_stop(handle, dir);
243 static int ext3_mknod (struct inode * dir, struct dentry *dentry,
244 int mode, dev_t rdev)
246 @@ -2462,6 +2492,7 @@
248 struct inode_operations ext3_dir_inode_operations = {
249 .create = ext3_create,
250 + .create_it = ext3_create_it, /* BKL held */
251 .lookup = ext3_lookup,
253 .unlink = ext3_unlink,
254 Index: linux-2.6.7/include/asm-i386/fcntl.h
255 ===================================================================
256 --- linux-2.6.7.orig/include/asm-i386/fcntl.h 2004-06-16 13:19:35.000000000 +0800
257 +++ linux-2.6.7/include/asm-i386/fcntl.h 2004-08-27 14:28:22.000000000 +0800
259 #define O_LARGEFILE 0100000
260 #define O_DIRECTORY 0200000 /* must be a directory */
261 #define O_NOFOLLOW 0400000 /* don't follow links */
262 +#define O_INRESERVE 01000000 /* allocate inodes in reserved space */
264 #define F_DUPFD 0 /* dup */
265 #define F_GETFD 1 /* get close_on_exec */
266 Index: linux-2.6.7/include/linux/ext3_fs.h
267 ===================================================================
268 --- linux-2.6.7.orig/include/linux/ext3_fs.h 2004-08-27 13:03:21.000000000 +0800
269 +++ linux-2.6.7/include/linux/ext3_fs.h 2004-08-27 14:28:22.000000000 +0800
271 #define EXT3_MOUNT_EXTDEBUG 0x20000 /* Extents debug */
272 #define EXT3_MOUNT_IOPEN 0x40000 /* Allow access via iopen */
273 #define EXT3_MOUNT_IOPEN_NOPRIV 0x80000 /* Make iopen world-readable */
274 +#define EXT3_MOUNT_INRESERVE 0x400000/* reserve one group for O_INRESERVE */
276 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
280 #define EXT3_GOOD_OLD_INODE_SIZE 128
282 +#define EXT3_S_INRESERVE 01000000
285 * Feature set definitions