Commit 2d1a9d59 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro
Browse files

minix: fix error handling in minix_set_link



If minix_prepare_chunk fails, updating c/mtime and marking the
dir inode dirty is wrong, as the inode hasn't been modified.  Also
propagate the error to the caller.

Note that this moves the dir_put_page call later, but that matches
other uses of this helper in the directory code.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b61d15d5
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -410,7 +410,7 @@ int minix_empty_dir(struct inode * inode)
}

/* Releases the page */
void minix_set_link(struct minix_dir_entry *de, struct page *page,
int minix_set_link(struct minix_dir_entry *de, struct page *page,
		struct inode *inode)
{
	struct inode *dir = page->mapping->host;
@@ -420,19 +420,21 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
	int err;

	lock_page(page);

	err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
	if (err == 0) {
	if (err) {
		unlock_page(page);
		return err;
	}
	if (sbi->s_version == MINIX_V3)
		((minix3_dirent *)de)->inode = inode->i_ino;
	else
		de->inode = inode->i_ino;
	err = dir_commit_chunk(page, pos, sbi->s_dirsize);
	} else {
		unlock_page(page);
	}
	if (err)
		return err;
	dir->i_mtime = dir->i_ctime = current_time(dir);
	mark_inode_dirty(dir);
	return 0;
}

struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
+2 −1
Original line number Diff line number Diff line
@@ -69,7 +69,8 @@ extern int minix_add_link(struct dentry*, struct inode*);
extern int minix_delete_entry(struct minix_dir_entry*, struct page*);
extern int minix_make_empty(struct inode*, struct inode*);
extern int minix_empty_dir(struct inode*);
extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
int minix_set_link(struct minix_dir_entry *de, struct page *page,
		struct inode *inode);
extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
extern ino_t minix_inode_by_name(struct dentry*);

+6 −4
Original line number Diff line number Diff line
@@ -213,10 +213,11 @@ static int minix_rename(struct user_namespace *mnt_userns,
		new_de = minix_find_entry(new_dentry, &new_page);
		if (!new_de)
			goto out_dir;
		err = 0;
		minix_set_link(new_de, new_page, old_inode);
		err = minix_set_link(new_de, new_page, old_inode);
		kunmap(new_page);
		put_page(new_page);
		if (err)
			goto out_dir;
		new_inode->i_ctime = current_time(new_inode);
		if (dir_de)
			drop_nlink(new_inode);
@@ -233,7 +234,8 @@ static int minix_rename(struct user_namespace *mnt_userns,
	mark_inode_dirty(old_inode);

	if (dir_de) {
		minix_set_link(dir_de, dir_page, new_dir);
		err = minix_set_link(dir_de, dir_page, new_dir);
		if (!err)
			inode_dec_link_count(old_dir);
	}
out_dir: