Skip to content

Commit abb7c74

Browse files
author
Al Viro
committed
sysv: fix handling of delete_entry and set_link failures
similar to minixfs series - make sysv_set_link() report failures, lift dir_put_page() into the callers of sysv_set_link() and sysv_delete_entry(), make sysv_rename() handle failures in both. Signed-off-by: Al Viro <[email protected]>
1 parent 8300527 commit abb7c74

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

fs/sysv/dir.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,12 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
249249

250250
lock_page(page);
251251
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
252-
BUG_ON(err);
252+
if (err) {
253+
unlock_page(page);
254+
return err;
255+
}
253256
de->inode = 0;
254257
dir_commit_chunk(page, pos, SYSV_DIRSIZE);
255-
dir_put_page(page, de);
256258
inode->i_ctime = inode->i_mtime = current_time(inode);
257259
mark_inode_dirty(inode);
258260
return sysv_handle_dirsync(inode);
@@ -335,7 +337,7 @@ int sysv_empty_dir(struct inode * inode)
335337
}
336338

337339
/* Releases the page */
338-
void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
340+
int sysv_set_link(struct sysv_dir_entry *de, struct page *page,
339341
struct inode *inode)
340342
{
341343
struct inode *dir = page->mapping->host;
@@ -344,13 +346,15 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
344346

345347
lock_page(page);
346348
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
347-
BUG_ON(err);
349+
if (err) {
350+
unlock_page(page);
351+
return err;
352+
}
348353
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
349354
dir_commit_chunk(page, pos, SYSV_DIRSIZE);
350-
dir_put_page(page, de);
351355
dir->i_mtime = dir->i_ctime = current_time(dir);
352356
mark_inode_dirty(dir);
353-
sysv_handle_dirsync(inode);
357+
return sysv_handle_dirsync(inode);
354358
}
355359

356360
/*

fs/sysv/namei.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,18 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry)
153153
struct inode * inode = d_inode(dentry);
154154
struct page * page;
155155
struct sysv_dir_entry * de;
156-
int err = -ENOENT;
156+
int err;
157157

158158
de = sysv_find_entry(dentry, &page);
159159
if (!de)
160-
goto out;
161-
162-
err = sysv_delete_entry (de, page);
163-
if (err)
164-
goto out;
160+
return -ENOENT;
165161

166-
inode->i_ctime = dir->i_ctime;
167-
inode_dec_link_count(inode);
168-
out:
162+
err = sysv_delete_entry(de, page);
163+
if (!err) {
164+
inode->i_ctime = dir->i_ctime;
165+
inode_dec_link_count(inode);
166+
}
167+
dir_put_page(page, de);
169168
return err;
170169
}
171170

@@ -227,7 +226,10 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
227226
new_de = sysv_find_entry(new_dentry, &new_page);
228227
if (!new_de)
229228
goto out_dir;
230-
sysv_set_link(new_de, new_page, old_inode);
229+
err = sysv_set_link(new_de, new_page, old_inode);
230+
dir_put_page(new_page, new_de);
231+
if (err)
232+
goto out_dir;
231233
new_inode->i_ctime = current_time(new_inode);
232234
if (dir_de)
233235
drop_nlink(new_inode);
@@ -240,14 +242,17 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
240242
inode_inc_link_count(new_dir);
241243
}
242244

243-
sysv_delete_entry(old_de, old_page);
245+
err = sysv_delete_entry(old_de, old_page);
246+
if (err)
247+
goto out_dir;
248+
244249
mark_inode_dirty(old_inode);
245250

246251
if (dir_de) {
247-
sysv_set_link(dir_de, dir_page, new_dir);
248-
inode_dec_link_count(old_dir);
252+
err = sysv_set_link(dir_de, dir_page, new_dir);
253+
if (!err)
254+
inode_dec_link_count(old_dir);
249255
}
250-
return 0;
251256

252257
out_dir:
253258
if (dir_de)

fs/sysv/sysv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ extern int sysv_add_link(struct dentry *, struct inode *);
154154
extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
155155
extern int sysv_make_empty(struct inode *, struct inode *);
156156
extern int sysv_empty_dir(struct inode *);
157-
extern void sysv_set_link(struct sysv_dir_entry *, struct page *,
157+
extern int sysv_set_link(struct sysv_dir_entry *, struct page *,
158158
struct inode *);
159159
extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **);
160160
extern ino_t sysv_inode_by_name(struct dentry *);

0 commit comments

Comments
 (0)