1 Index: linux-2.4.24/fs/ext3/ialloc.c
2 ===================================================================
3 --- linux-2.4.24.orig/fs/ext3/ialloc.c 2004-08-02 22:13:13.000000000 +0400
4 +++ linux-2.4.24/fs/ext3/ialloc.c 2004-08-04 01:10:30.000000000 +0400
6 * when a file system is mounted (see ext3_read_super).
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 return !ext3_test_bit(nr, bh2jh(bh)->b_committed_data);
34 -int ext3_find_group_dir(const struct inode *dir,
35 +int ext3_find_group_dir(const struct inode *dir, int mode,
36 struct ext3_group_desc **gdp,
37 struct buffer_head **bh)
39 struct super_block *sb = dir->i_sb;
40 struct ext3_super_block *es;
41 struct ext3_group_desc *tmp;
42 - int i = 0, j, avefreei;
43 + int i = 0, j, ifree, avefreei;
45 es = EXT3_SB(sb)->s_es;
46 - avefreei = le32_to_cpu(es->s_free_inodes_count) /
47 - sb->u.ext3_sb.s_groups_count;
48 + ifree = le32_to_cpu(es->s_free_inodes_count);
49 + j = sb->u.ext3_sb.s_groups_count;
50 + if (test_opt(sb, INRESERVE) && EXT3_SB(sb)->s_groups_count > 1) {
51 + tmp = ext3_get_group_desc(sb, EXT3_SB(sb)->s_groups_count-1, NULL);
52 + if (mode & EXT3_S_INRESERVE) {
53 + ifree = le16_to_cpu(tmp->bg_free_blocks_count);
56 + ifree -= le16_to_cpu(tmp->bg_free_blocks_count);
60 + avefreei = ifree / j;
61 for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
62 struct buffer_head *temp_buffer;
63 + if (!ext3_group_allowed(sb, mode, j))
65 tmp = ext3_get_group_desc(sb, j, &temp_buffer);
66 if (tmp && le16_to_cpu(tmp->bg_free_inodes_count) &&
67 le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
72 -int ext3_find_group_other(const struct inode *dir,
73 +int ext3_find_group_other(const struct inode *dir, int mode,
74 struct ext3_group_desc **gdp,
75 struct buffer_head **bh)
79 i = dir->u.ext3_i.i_block_group;
80 tmp = ext3_get_group_desc(sb, i, bh);
81 - if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
82 + if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)
83 + && ext3_group_allowed(sb, mode, i))
89 if (i >= sb->u.ext3_sb.s_groups_count)
90 i -= sb->u.ext3_sb.s_groups_count;
91 + if (!ext3_group_allowed(sb, mode, i))
93 tmp = ext3_get_group_desc (sb, i, bh);
94 if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) {
97 for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
98 if (++i >= sb->u.ext3_sb.s_groups_count)
100 + if (!ext3_group_allowed(sb, mode, i))
102 tmp = ext3_get_group_desc (sb, i, bh);
103 if (tmp && le16_to_cpu(tmp->bg_free_inodes_count)) {
106 struct buffer_head **bh)
109 - return ext3_find_group_dir(dir, gdp, bh);
110 - return ext3_find_group_other(dir, gdp, bh);
111 + return ext3_find_group_dir(dir, mode, gdp, bh);
112 + return ext3_find_group_other(dir, mode, gdp, bh);
115 static int ext3_find_usable_inode(struct super_block *sb,
117 for (i = i + 1; i != k; i++) {
118 if (i >= sb->u.ext3_sb.s_groups_count)
120 + if (!ext3_group_allowed(sb, mode, i))
122 tmp = ext3_get_group_desc(sb, i, &bh2);
123 if (le16_to_cpu(tmp->bg_free_inodes_count) == 0)
126 if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data)
127 J_ASSERT_BH(bh, !ext3_test_bit(j, bh2jh(bh)->b_committed_data));
129 + J_ASSERT(ext3_group_allowed(sb, mode, i));
130 j += i * EXT3_INODES_PER_GROUP(sb) + 1;
131 if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
132 ext3_error (sb, "ext3_new_inode",
136 inode->i_gid = current->fsgid;
137 - inode->i_mode = mode;
138 + inode->i_mode = mode & ~EXT3_S_INRESERVE;
141 /* This is the optimal IO size (for stat), not the fs block size */
142 Index: linux-2.4.24/fs/ext3/super.c
143 ===================================================================
144 --- linux-2.4.24.orig/fs/ext3/super.c 2004-08-02 22:13:12.000000000 +0400
145 +++ linux-2.4.24/fs/ext3/super.c 2004-08-04 00:10:07.000000000 +0400
150 + else if (!strcmp (this_char, "inrsv")) {
151 + set_opt (*mount_options, INRESERVE);
152 + J_ASSERT((EXT3_S_INRESERVE & S_IALLUGO) == 0);
154 else if (!strcmp (this_char, "resuid")) {
156 if (want_numeric(value, "resuid", &v))
157 Index: linux-2.4.24/fs/ext3/namei.c
158 ===================================================================
159 --- linux-2.4.24.orig/fs/ext3/namei.c 2004-08-02 22:13:13.000000000 +0400
160 +++ linux-2.4.24/fs/ext3/namei.c 2004-08-03 03:21:09.000000000 +0400
161 @@ -1971,6 +1971,36 @@
165 +static int ext3_create_it (struct inode * dir, struct dentry * dentry, int mode,
166 + struct lookup_intent *it)
169 + struct inode * inode;
172 + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
173 + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
174 + if (IS_ERR(handle)) {
175 + return PTR_ERR(handle);
179 + handle->h_sync = 1;
181 + if (it && it->it_flags & O_INRESERVE)
182 + mode |= EXT3_S_INRESERVE;
183 + inode = ext3_new_inode_wantedi (handle, dir, mode, dentry);
184 + err = PTR_ERR(inode);
185 + if (!IS_ERR(inode)) {
186 + inode->i_op = &ext3_file_inode_operations;
187 + inode->i_fop = &ext3_file_operations;
188 + inode->i_mapping->a_ops = &ext3_aops;
189 + err = ext3_add_nondir(handle, dentry, inode);
191 + ext3_journal_stop(handle, dir);
195 static int ext3_mknod (struct inode * dir, struct dentry *dentry,
198 @@ -2803,6 +2833,7 @@
200 struct inode_operations ext3_dir_inode_operations = {
201 create: ext3_create, /* BKL held */
202 + create_it: ext3_create_it, /* BKL held */
203 lookup: ext3_lookup, /* BKL held */
204 lookup_raw: ext3_lookup_raw, /* BKL held */
205 link: ext3_link, /* BKL held */
206 Index: linux-2.4.24/include/asm-i386/fcntl.h
207 ===================================================================
208 --- linux-2.4.24.orig/include/asm-i386/fcntl.h 2001-09-18 00:16:30.000000000 +0400
209 +++ linux-2.4.24/include/asm-i386/fcntl.h 2004-08-03 01:20:55.000000000 +0400
211 #define O_LARGEFILE 0100000
212 #define O_DIRECTORY 0200000 /* must be a directory */
213 #define O_NOFOLLOW 0400000 /* don't follow links */
214 +#define O_INRESERVE 01000000 /* allocate inodes in reserved space */
216 #define F_DUPFD 0 /* dup */
217 #define F_GETFD 1 /* get close_on_exec */
218 Index: linux-2.4.24/include/linux/ext3_fs.h
219 ===================================================================
220 --- linux-2.4.24.orig/include/linux/ext3_fs.h 2004-08-02 22:13:12.000000000 +0400
221 +++ linux-2.4.24/include/linux/ext3_fs.h 2004-08-03 01:03:39.000000000 +0400
223 #define EXT3_MOUNT_ASYNCDEL 0x20000 /* Delayed deletion */
224 #define EXT3_MOUNT_EXTENTS 0x100000/* Extents support */
225 #define EXT3_MOUNT_EXTDEBUG 0x200000/* Extents debug */
226 +#define EXT3_MOUNT_INRESERVE 0x400000/* reserve one group for O_INRESERVE */
228 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
229 #ifndef _LINUX_EXT2_FS_H
232 #define EXT3_GOOD_OLD_INODE_SIZE 128
234 +#define EXT3_S_INRESERVE 01000000
237 * Feature set definitions