Skip to content

Commit 397aa6b

Browse files
committed
Merge branch 'work.minix' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull minix updates from Al Viro: "Assorted fixes - mostly Christoph's" * 'work.minix' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: minix_rename(): minix_delete_entry() might fail minix: don't flush page immediately for DIRSYNC directories minix: fix error handling in minix_set_link minix: fix error handling in minix_delete_entry minix: move releasing pages into unlink and rename minix: make minix_new_inode() return error as ERR_PTR(-E...)
2 parents 595fa4e + 2cb6a44 commit 397aa6b

File tree

4 files changed

+91
-92
lines changed

4 files changed

+91
-92
lines changed

fs/minix/bitmap.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ void minix_free_inode(struct inode * inode)
210210
mark_buffer_dirty(bh);
211211
}
212212

213-
struct inode *minix_new_inode(const struct inode *dir, umode_t mode, int *error)
213+
struct inode *minix_new_inode(const struct inode *dir, umode_t mode)
214214
{
215215
struct super_block *sb = dir->i_sb;
216216
struct minix_sb_info *sbi = minix_sb(sb);
@@ -220,13 +220,10 @@ struct inode *minix_new_inode(const struct inode *dir, umode_t mode, int *error)
220220
unsigned long j;
221221
int i;
222222

223-
if (!inode) {
224-
*error = -ENOMEM;
225-
return NULL;
226-
}
223+
if (!inode)
224+
return ERR_PTR(-ENOMEM);
227225
j = bits_per_zone;
228226
bh = NULL;
229-
*error = -ENOSPC;
230227
spin_lock(&bitmap_lock);
231228
for (i = 0; i < sbi->s_imap_blocks; i++) {
232229
bh = sbi->s_imap[i];
@@ -237,20 +234,20 @@ struct inode *minix_new_inode(const struct inode *dir, umode_t mode, int *error)
237234
if (!bh || j >= bits_per_zone) {
238235
spin_unlock(&bitmap_lock);
239236
iput(inode);
240-
return NULL;
237+
return ERR_PTR(-ENOSPC);
241238
}
242239
if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */
243240
spin_unlock(&bitmap_lock);
244241
printk("minix_new_inode: bit already set\n");
245242
iput(inode);
246-
return NULL;
243+
return ERR_PTR(-ENOSPC);
247244
}
248245
spin_unlock(&bitmap_lock);
249246
mark_buffer_dirty(bh);
250247
j += i * bits_per_zone;
251248
if (!j || j > sbi->s_ninodes) {
252249
iput(inode);
253-
return NULL;
250+
return ERR_PTR(-ENOSPC);
254251
}
255252
inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
256253
inode->i_ino = j;
@@ -260,7 +257,6 @@ struct inode *minix_new_inode(const struct inode *dir, umode_t mode, int *error)
260257
insert_inode_hash(inode);
261258
mark_inode_dirty(inode);
262259

263-
*error = 0;
264260
return inode;
265261
}
266262

fs/minix/dir.c

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,27 @@ minix_last_byte(struct inode *inode, unsigned long page_nr)
4646
return last_byte;
4747
}
4848

49-
static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
49+
static void dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
5050
{
5151
struct address_space *mapping = page->mapping;
5252
struct inode *dir = mapping->host;
53-
int err = 0;
53+
5454
block_write_end(NULL, mapping, pos, len, len, page, NULL);
5555

5656
if (pos+len > dir->i_size) {
5757
i_size_write(dir, pos+len);
5858
mark_inode_dirty(dir);
5959
}
60-
if (IS_DIRSYNC(dir))
61-
err = write_one_page(page);
62-
else
63-
unlock_page(page);
60+
unlock_page(page);
61+
}
62+
63+
static int minix_handle_dirsync(struct inode *dir)
64+
{
65+
int err;
66+
67+
err = filemap_write_and_wait(dir->i_mapping);
68+
if (!err)
69+
err = sync_inode_metadata(dir, 1);
6470
return err;
6571
}
6672

@@ -274,9 +280,10 @@ int minix_add_link(struct dentry *dentry, struct inode *inode)
274280
memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
275281
de->inode = inode->i_ino;
276282
}
277-
err = dir_commit_chunk(page, pos, sbi->s_dirsize);
283+
dir_commit_chunk(page, pos, sbi->s_dirsize);
278284
dir->i_mtime = dir->i_ctime = current_time(dir);
279285
mark_inode_dirty(dir);
286+
err = minix_handle_dirsync(dir);
280287
out_put:
281288
dir_put_page(page);
282289
out:
@@ -297,19 +304,18 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
297304

298305
lock_page(page);
299306
err = minix_prepare_chunk(page, pos, len);
300-
if (err == 0) {
301-
if (sbi->s_version == MINIX_V3)
302-
((minix3_dirent *) de)->inode = 0;
303-
else
304-
de->inode = 0;
305-
err = dir_commit_chunk(page, pos, len);
306-
} else {
307+
if (err) {
307308
unlock_page(page);
309+
return err;
308310
}
309-
dir_put_page(page);
311+
if (sbi->s_version == MINIX_V3)
312+
((minix3_dirent *)de)->inode = 0;
313+
else
314+
de->inode = 0;
315+
dir_commit_chunk(page, pos, len);
310316
inode->i_ctime = inode->i_mtime = current_time(inode);
311317
mark_inode_dirty(inode);
312-
return err;
318+
return minix_handle_dirsync(inode);
313319
}
314320

315321
int minix_make_empty(struct inode *inode, struct inode *dir)
@@ -349,7 +355,8 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
349355
}
350356
kunmap_atomic(kaddr);
351357

352-
err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
358+
dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
359+
err = minix_handle_dirsync(inode);
353360
fail:
354361
put_page(page);
355362
return err;
@@ -409,8 +416,8 @@ int minix_empty_dir(struct inode * inode)
409416
}
410417

411418
/* Releases the page */
412-
void minix_set_link(struct minix_dir_entry *de, struct page *page,
413-
struct inode *inode)
419+
int minix_set_link(struct minix_dir_entry *de, struct page *page,
420+
struct inode *inode)
414421
{
415422
struct inode *dir = page->mapping->host;
416423
struct minix_sb_info *sbi = minix_sb(dir->i_sb);
@@ -419,20 +426,19 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
419426
int err;
420427

421428
lock_page(page);
422-
423429
err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
424-
if (err == 0) {
425-
if (sbi->s_version == MINIX_V3)
426-
((minix3_dirent *) de)->inode = inode->i_ino;
427-
else
428-
de->inode = inode->i_ino;
429-
err = dir_commit_chunk(page, pos, sbi->s_dirsize);
430-
} else {
430+
if (err) {
431431
unlock_page(page);
432+
return err;
432433
}
433-
dir_put_page(page);
434+
if (sbi->s_version == MINIX_V3)
435+
((minix3_dirent *)de)->inode = inode->i_ino;
436+
else
437+
de->inode = inode->i_ino;
438+
dir_commit_chunk(page, pos, sbi->s_dirsize);
434439
dir->i_mtime = dir->i_ctime = current_time(dir);
435440
mark_inode_dirty(dir);
441+
return minix_handle_dirsync(dir);
436442
}
437443

438444
struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)

fs/minix/minix.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct minix_sb_info {
4545
extern struct inode *minix_iget(struct super_block *, unsigned long);
4646
extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **);
4747
extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);
48-
extern struct inode * minix_new_inode(const struct inode *, umode_t, int *);
48+
extern struct inode * minix_new_inode(const struct inode *, umode_t);
4949
extern void minix_free_inode(struct inode * inode);
5050
extern unsigned long minix_count_free_inodes(struct super_block *sb);
5151
extern int minix_new_block(struct inode * inode);
@@ -69,7 +69,8 @@ extern int minix_add_link(struct dentry*, struct inode*);
6969
extern int minix_delete_entry(struct minix_dir_entry*, struct page*);
7070
extern int minix_make_empty(struct inode*, struct inode*);
7171
extern int minix_empty_dir(struct inode*);
72-
extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
72+
int minix_set_link(struct minix_dir_entry *de, struct page *page,
73+
struct inode *inode);
7374
extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
7475
extern ino_t minix_inode_by_name(struct dentry*);
7576

fs/minix/namei.c

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,31 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un
3636
static int minix_mknod(struct mnt_idmap *idmap, struct inode *dir,
3737
struct dentry *dentry, umode_t mode, dev_t rdev)
3838
{
39-
int error;
4039
struct inode *inode;
4140

4241
if (!old_valid_dev(rdev))
4342
return -EINVAL;
4443

45-
inode = minix_new_inode(dir, mode, &error);
44+
inode = minix_new_inode(dir, mode);
45+
if (IS_ERR(inode))
46+
return PTR_ERR(inode);
4647

47-
if (inode) {
48-
minix_set_inode(inode, rdev);
49-
mark_inode_dirty(inode);
50-
error = add_nondir(dentry, inode);
51-
}
52-
return error;
48+
minix_set_inode(inode, rdev);
49+
mark_inode_dirty(inode);
50+
return add_nondir(dentry, inode);
5351
}
5452

5553
static int minix_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
5654
struct file *file, umode_t mode)
5755
{
58-
int error;
59-
struct inode *inode = minix_new_inode(dir, mode, &error);
60-
if (inode) {
61-
minix_set_inode(inode, 0);
62-
mark_inode_dirty(inode);
63-
d_tmpfile(file, inode);
64-
}
65-
return finish_open_simple(file, error);
56+
struct inode *inode = minix_new_inode(dir, mode);
57+
58+
if (IS_ERR(inode))
59+
return finish_open_simple(file, PTR_ERR(inode));
60+
minix_set_inode(inode, 0);
61+
mark_inode_dirty(inode);
62+
d_tmpfile(file, inode);
63+
return finish_open_simple(file, 0);
6664
}
6765

6866
static int minix_create(struct mnt_idmap *idmap, struct inode *dir,
@@ -74,30 +72,25 @@ static int minix_create(struct mnt_idmap *idmap, struct inode *dir,
7472
static int minix_symlink(struct mnt_idmap *idmap, struct inode *dir,
7573
struct dentry *dentry, const char *symname)
7674
{
77-
int err = -ENAMETOOLONG;
7875
int i = strlen(symname)+1;
7976
struct inode * inode;
77+
int err;
8078

8179
if (i > dir->i_sb->s_blocksize)
82-
goto out;
80+
return -ENAMETOOLONG;
8381

84-
inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
85-
if (!inode)
86-
goto out;
82+
inode = minix_new_inode(dir, S_IFLNK | 0777);
83+
if (IS_ERR(inode))
84+
return PTR_ERR(inode);
8785

8886
minix_set_inode(inode, 0);
8987
err = page_symlink(inode, symname, i);
90-
if (err)
91-
goto out_fail;
92-
93-
err = add_nondir(dentry, inode);
94-
out:
95-
return err;
96-
97-
out_fail:
98-
inode_dec_link_count(inode);
99-
iput(inode);
100-
goto out;
88+
if (unlikely(err)) {
89+
inode_dec_link_count(inode);
90+
iput(inode);
91+
return err;
92+
}
93+
return add_nondir(dentry, inode);
10194
}
10295

10396
static int minix_link(struct dentry * old_dentry, struct inode * dir,
@@ -117,14 +110,12 @@ static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
117110
struct inode * inode;
118111
int err;
119112

120-
inode_inc_link_count(dir);
121-
122-
inode = minix_new_inode(dir, S_IFDIR | mode, &err);
123-
if (!inode)
124-
goto out_dir;
113+
inode = minix_new_inode(dir, S_IFDIR | mode);
114+
if (IS_ERR(inode))
115+
return PTR_ERR(inode);
125116

117+
inode_inc_link_count(dir);
126118
minix_set_inode(inode, 0);
127-
128119
inode_inc_link_count(inode);
129120

130121
err = minix_make_empty(inode, dir);
@@ -143,30 +134,29 @@ static int minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
143134
inode_dec_link_count(inode);
144135
inode_dec_link_count(inode);
145136
iput(inode);
146-
out_dir:
147137
inode_dec_link_count(dir);
148138
goto out;
149139
}
150140

151141
static int minix_unlink(struct inode * dir, struct dentry *dentry)
152142
{
153-
int err = -ENOENT;
154143
struct inode * inode = d_inode(dentry);
155144
struct page * page;
156145
struct minix_dir_entry * de;
146+
int err;
157147

158148
de = minix_find_entry(dentry, &page);
159149
if (!de)
160-
goto end_unlink;
161-
150+
return -ENOENT;
162151
err = minix_delete_entry(de, page);
163-
if (err)
164-
goto end_unlink;
152+
kunmap(page);
153+
put_page(page);
165154

155+
if (err)
156+
return err;
166157
inode->i_ctime = dir->i_ctime;
167158
inode_dec_link_count(inode);
168-
end_unlink:
169-
return err;
159+
return 0;
170160
}
171161

172162
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
@@ -223,7 +213,11 @@ static int minix_rename(struct mnt_idmap *idmap,
223213
new_de = minix_find_entry(new_dentry, &new_page);
224214
if (!new_de)
225215
goto out_dir;
226-
minix_set_link(new_de, new_page, old_inode);
216+
err = minix_set_link(new_de, new_page, old_inode);
217+
kunmap(new_page);
218+
put_page(new_page);
219+
if (err)
220+
goto out_dir;
227221
new_inode->i_ctime = current_time(new_inode);
228222
if (dir_de)
229223
drop_nlink(new_inode);
@@ -236,15 +230,17 @@ static int minix_rename(struct mnt_idmap *idmap,
236230
inode_inc_link_count(new_dir);
237231
}
238232

239-
minix_delete_entry(old_de, old_page);
233+
err = minix_delete_entry(old_de, old_page);
234+
if (err)
235+
goto out_dir;
236+
240237
mark_inode_dirty(old_inode);
241238

242239
if (dir_de) {
243-
minix_set_link(dir_de, dir_page, new_dir);
244-
inode_dec_link_count(old_dir);
240+
err = minix_set_link(dir_de, dir_page, new_dir);
241+
if (!err)
242+
inode_dec_link_count(old_dir);
245243
}
246-
return 0;
247-
248244
out_dir:
249245
if (dir_de) {
250246
kunmap(dir_page);

0 commit comments

Comments
 (0)