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 <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
83005276d3
Коммит
abb7c74239
|
@ -249,10 +249,12 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
|
|||
|
||||
lock_page(page);
|
||||
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
|
||||
BUG_ON(err);
|
||||
if (err) {
|
||||
unlock_page(page);
|
||||
return err;
|
||||
}
|
||||
de->inode = 0;
|
||||
dir_commit_chunk(page, pos, SYSV_DIRSIZE);
|
||||
dir_put_page(page, de);
|
||||
inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
mark_inode_dirty(inode);
|
||||
return sysv_handle_dirsync(inode);
|
||||
|
@ -335,7 +337,7 @@ not_empty:
|
|||
}
|
||||
|
||||
/* Releases the page */
|
||||
void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
|
||||
int sysv_set_link(struct sysv_dir_entry *de, struct page *page,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct inode *dir = page->mapping->host;
|
||||
|
@ -344,13 +346,15 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
|
|||
|
||||
lock_page(page);
|
||||
err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
|
||||
BUG_ON(err);
|
||||
if (err) {
|
||||
unlock_page(page);
|
||||
return err;
|
||||
}
|
||||
de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
|
||||
dir_commit_chunk(page, pos, SYSV_DIRSIZE);
|
||||
dir_put_page(page, de);
|
||||
dir->i_mtime = dir->i_ctime = current_time(dir);
|
||||
mark_inode_dirty(dir);
|
||||
sysv_handle_dirsync(inode);
|
||||
return sysv_handle_dirsync(inode);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -153,19 +153,18 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry)
|
|||
struct inode * inode = d_inode(dentry);
|
||||
struct page * page;
|
||||
struct sysv_dir_entry * de;
|
||||
int err = -ENOENT;
|
||||
int err;
|
||||
|
||||
de = sysv_find_entry(dentry, &page);
|
||||
if (!de)
|
||||
goto out;
|
||||
return -ENOENT;
|
||||
|
||||
err = sysv_delete_entry (de, page);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
inode->i_ctime = dir->i_ctime;
|
||||
inode_dec_link_count(inode);
|
||||
out:
|
||||
err = sysv_delete_entry(de, page);
|
||||
if (!err) {
|
||||
inode->i_ctime = dir->i_ctime;
|
||||
inode_dec_link_count(inode);
|
||||
}
|
||||
dir_put_page(page, de);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -227,7 +226,10 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
new_de = sysv_find_entry(new_dentry, &new_page);
|
||||
if (!new_de)
|
||||
goto out_dir;
|
||||
sysv_set_link(new_de, new_page, old_inode);
|
||||
err = sysv_set_link(new_de, new_page, old_inode);
|
||||
dir_put_page(new_page, new_de);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
new_inode->i_ctime = current_time(new_inode);
|
||||
if (dir_de)
|
||||
drop_nlink(new_inode);
|
||||
|
@ -240,14 +242,17 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
inode_inc_link_count(new_dir);
|
||||
}
|
||||
|
||||
sysv_delete_entry(old_de, old_page);
|
||||
err = sysv_delete_entry(old_de, old_page);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
|
||||
mark_inode_dirty(old_inode);
|
||||
|
||||
if (dir_de) {
|
||||
sysv_set_link(dir_de, dir_page, new_dir);
|
||||
inode_dec_link_count(old_dir);
|
||||
err = sysv_set_link(dir_de, dir_page, new_dir);
|
||||
if (!err)
|
||||
inode_dec_link_count(old_dir);
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_dir:
|
||||
if (dir_de)
|
||||
|
|
|
@ -154,7 +154,7 @@ extern int sysv_add_link(struct dentry *, struct inode *);
|
|||
extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
|
||||
extern int sysv_make_empty(struct inode *, struct inode *);
|
||||
extern int sysv_empty_dir(struct inode *);
|
||||
extern void sysv_set_link(struct sysv_dir_entry *, struct page *,
|
||||
extern int sysv_set_link(struct sysv_dir_entry *, struct page *,
|
||||
struct inode *);
|
||||
extern struct sysv_dir_entry *sysv_dotdot(struct inode *, struct page **);
|
||||
extern ino_t sysv_inode_by_name(struct dentry *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче