summaryrefslogtreecommitdiff
path: root/fs/minix/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/minix/namei.c')
-rw-r--r--fs/minix/namei.c186
1 files changed, 101 insertions, 85 deletions
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 8afdc408ca4f..263e4ba8b1c8 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -33,71 +33,64 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un
return d_splice_alias(inode, dentry);
}
-static int minix_mknod(struct user_namespace *mnt_userns, struct inode *dir,
+static int minix_mknod(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode, dev_t rdev)
{
- int error;
struct inode *inode;
if (!old_valid_dev(rdev))
return -EINVAL;
- inode = minix_new_inode(dir, mode, &error);
+ inode = minix_new_inode(dir, mode);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
- if (inode) {
- minix_set_inode(inode, rdev);
- mark_inode_dirty(inode);
- error = add_nondir(dentry, inode);
- }
- return error;
+ minix_set_inode(inode, rdev);
+ mark_inode_dirty(inode);
+ return add_nondir(dentry, inode);
}
-static int minix_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
+static int minix_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
struct file *file, umode_t mode)
{
- int error;
- struct inode *inode = minix_new_inode(dir, mode, &error);
- if (inode) {
- minix_set_inode(inode, 0);
- mark_inode_dirty(inode);
- d_tmpfile(file, inode);
- }
- return finish_open_simple(file, error);
+ struct inode *inode = minix_new_inode(dir, mode);
+
+ if (IS_ERR(inode))
+ return finish_open_simple(file, PTR_ERR(inode));
+ minix_set_inode(inode, 0);
+ mark_inode_dirty(inode);
+ d_tmpfile(file, inode);
+ return finish_open_simple(file, 0);
}
-static int minix_create(struct user_namespace *mnt_userns, struct inode *dir,
+static int minix_create(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl)
{
- return minix_mknod(mnt_userns, dir, dentry, mode, 0);
+ return minix_mknod(&nop_mnt_idmap, dir, dentry, mode, 0);
}
-static int minix_symlink(struct user_namespace *mnt_userns, struct inode *dir,
+static int minix_symlink(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, const char *symname)
{
- int err = -ENAMETOOLONG;
int i = strlen(symname)+1;
struct inode * inode;
+ int err;
if (i > dir->i_sb->s_blocksize)
- goto out;
+ return -ENAMETOOLONG;
- inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
- if (!inode)
- goto out;
+ inode = minix_new_inode(dir, S_IFLNK | 0777);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
minix_set_inode(inode, 0);
err = page_symlink(inode, symname, i);
- if (err)
- goto out_fail;
-
- err = add_nondir(dentry, inode);
-out:
- return err;
-
-out_fail:
- inode_dec_link_count(inode);
- iput(inode);
- goto out;
+ if (unlikely(err)) {
+ inode_dec_link_count(inode);
+ iput(inode);
+ return err;
+ }
+ return add_nondir(dentry, inode);
}
static int minix_link(struct dentry * old_dentry, struct inode * dir,
@@ -105,26 +98,24 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
{
struct inode *inode = d_inode(old_dentry);
- inode->i_ctime = current_time(inode);
+ inode_set_ctime_current(inode);
inode_inc_link_count(inode);
ihold(inode);
return add_nondir(dentry, inode);
}
-static int minix_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
- struct dentry *dentry, umode_t mode)
+static struct dentry *minix_mkdir(struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, umode_t mode)
{
struct inode * inode;
int err;
- inode_inc_link_count(dir);
-
- inode = minix_new_inode(dir, S_IFDIR | mode, &err);
- if (!inode)
- goto out_dir;
+ inode = minix_new_inode(dir, S_IFDIR | mode);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
+ inode_inc_link_count(dir);
minix_set_inode(inode, 0);
-
inode_inc_link_count(inode);
err = minix_make_empty(inode, dir);
@@ -137,94 +128,120 @@ static int minix_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
d_instantiate(dentry, inode);
out:
- return err;
+ return ERR_PTR(err);
out_fail:
inode_dec_link_count(inode);
inode_dec_link_count(inode);
iput(inode);
-out_dir:
inode_dec_link_count(dir);
goto out;
}
static int minix_unlink(struct inode * dir, struct dentry *dentry)
{
- int err = -ENOENT;
struct inode * inode = d_inode(dentry);
- struct page * page;
+ struct folio *folio;
struct minix_dir_entry * de;
+ int err;
- de = minix_find_entry(dentry, &page);
+ if (inode->i_nlink == 0) {
+ minix_error_inode(inode, "inode has corrupted nlink");
+ return -EFSCORRUPTED;
+ }
+
+ de = minix_find_entry(dentry, &folio);
if (!de)
- goto end_unlink;
+ return -ENOENT;
+ err = minix_delete_entry(de, folio);
+ folio_release_kmap(folio, de);
- err = minix_delete_entry(de, page);
if (err)
- goto end_unlink;
-
- inode->i_ctime = dir->i_ctime;
+ return err;
+ inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
inode_dec_link_count(inode);
-end_unlink:
- return err;
+ return 0;
}
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
{
struct inode * inode = d_inode(dentry);
- int err = -ENOTEMPTY;
+ int err = -EFSCORRUPTED;
- if (minix_empty_dir(inode)) {
- err = minix_unlink(dir, dentry);
- if (!err) {
- inode_dec_link_count(dir);
- inode_dec_link_count(inode);
- }
+ if (dir->i_nlink <= 2) {
+ minix_error_inode(dir, "inode has corrupted nlink");
+ goto out;
}
+
+ err = -ENOTEMPTY;
+ if (!minix_empty_dir(inode))
+ goto out;
+
+ err = minix_unlink(dir, dentry);
+ if (!err) {
+ inode_dec_link_count(dir);
+ inode_dec_link_count(inode);
+ }
+
+out:
return err;
}
-static int minix_rename(struct user_namespace *mnt_userns,
+static int minix_rename(struct mnt_idmap *idmap,
struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
struct inode * old_inode = d_inode(old_dentry);
struct inode * new_inode = d_inode(new_dentry);
- struct page * dir_page = NULL;
+ struct folio * dir_folio = NULL;
struct minix_dir_entry * dir_de = NULL;
- struct page * old_page;
+ struct folio *old_folio;
struct minix_dir_entry * old_de;
int err = -ENOENT;
if (flags & ~RENAME_NOREPLACE)
return -EINVAL;
- old_de = minix_find_entry(old_dentry, &old_page);
+ old_de = minix_find_entry(old_dentry, &old_folio);
if (!old_de)
goto out;
if (S_ISDIR(old_inode->i_mode)) {
err = -EIO;
- dir_de = minix_dotdot(old_inode, &dir_page);
+ dir_de = minix_dotdot(old_inode, &dir_folio);
if (!dir_de)
goto out_old;
}
if (new_inode) {
- struct page * new_page;
+ struct folio *new_folio;
struct minix_dir_entry * new_de;
err = -ENOTEMPTY;
if (dir_de && !minix_empty_dir(new_inode))
goto out_dir;
+ err = -EFSCORRUPTED;
+ if (new_inode->i_nlink == 0 || (dir_de && new_inode->i_nlink != 2)) {
+ minix_error_inode(new_inode, "inode has corrupted nlink");
+ goto out_dir;
+ }
+
+ if (dir_de && old_dir->i_nlink <= 2) {
+ minix_error_inode(old_dir, "inode has corrupted nlink");
+ goto out_dir;
+ }
+
err = -ENOENT;
- new_de = minix_find_entry(new_dentry, &new_page);
+ new_de = minix_find_entry(new_dentry, &new_folio);
if (!new_de)
goto out_dir;
- minix_set_link(new_de, new_page, old_inode);
- new_inode->i_ctime = current_time(new_inode);
+ err = minix_set_link(new_de, new_folio, old_inode);
+ folio_release_kmap(new_folio, new_de);
+ if (err)
+ goto out_dir;
+ inode_set_ctime_current(new_inode);
if (dir_de)
drop_nlink(new_inode);
inode_dec_link_count(new_inode);
@@ -236,23 +253,22 @@ static int minix_rename(struct user_namespace *mnt_userns,
inode_inc_link_count(new_dir);
}
- minix_delete_entry(old_de, old_page);
+ err = minix_delete_entry(old_de, old_folio);
+ if (err)
+ goto out_dir;
+
mark_inode_dirty(old_inode);
if (dir_de) {
- minix_set_link(dir_de, dir_page, new_dir);
- inode_dec_link_count(old_dir);
+ err = minix_set_link(dir_de, dir_folio, new_dir);
+ if (!err)
+ inode_dec_link_count(old_dir);
}
- return 0;
-
out_dir:
- if (dir_de) {
- kunmap(dir_page);
- put_page(dir_page);
- }
+ if (dir_de)
+ folio_release_kmap(dir_folio, dir_de);
out_old:
- kunmap(old_page);
- put_page(old_page);
+ folio_release_kmap(old_folio, old_de);
out:
return err;
}