summaryrefslogtreecommitdiff
path: root/fs/udf/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/namei.c')
-rw-r--r--fs/udf/namei.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 1bb6ed948927..2cb49b6b0716 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -59,7 +59,7 @@ static int udf_fiiter_find_entry(struct inode *dir, const struct qstr *child,
child->name[0] == '.' && child->name[1] == '.';
int ret;
- fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+ fname = kmalloc(UDF_NAME_LEN, GFP_KERNEL);
if (!fname)
return -ENOMEM;
@@ -517,7 +517,11 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_nlink);
clear_nlink(inode);
inode->i_size = 0;
- inode_dec_link_count(dir);
+ if (dir->i_nlink >= 3)
+ inode_dec_link_count(dir);
+ else
+ udf_warn(inode->i_sb, "parent dir link count too low (%u)\n",
+ dir->i_nlink);
udf_add_fid_counter(dir->i_sb, true, -1);
inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
@@ -566,7 +570,7 @@ out:
static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, const char *symname)
{
- struct inode *inode = udf_new_inode(dir, S_IFLNK | 0777);
+ struct inode *inode;
struct pathComponent *pc;
const char *compstart;
struct extent_position epos = {};
@@ -579,17 +583,20 @@ static int udf_symlink(struct mnt_idmap *idmap, struct inode *dir,
struct udf_inode_info *iinfo;
struct super_block *sb = dir->i_sb;
- if (IS_ERR(inode))
- return PTR_ERR(inode);
-
- iinfo = UDF_I(inode);
- down_write(&iinfo->i_data_sem);
- name = kmalloc(UDF_NAME_LEN_CS0, GFP_NOFS);
+ name = kmalloc(UDF_NAME_LEN_CS0, GFP_KERNEL);
if (!name) {
err = -ENOMEM;
- goto out_no_entry;
+ goto out;
}
+ inode = udf_new_inode(dir, S_IFLNK | 0777);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ goto out;
+ }
+
+ iinfo = UDF_I(inode);
+ down_write(&iinfo->i_data_sem);
inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &udf_symlink_inode_operations;
inode_nohighmem(inode);
@@ -784,8 +791,18 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto out_oiter;
+ retval = -EFSCORRUPTED;
+ if (new_inode->i_nlink != 2)
+ goto out_oiter;
}
+ retval = -EFSCORRUPTED;
+ if (old_dir->i_nlink < 3)
+ goto out_oiter;
is_dir = true;
+ } else if (new_inode) {
+ retval = -EFSCORRUPTED;
+ if (new_inode->i_nlink < 1)
+ goto out_oiter;
}
if (is_dir && old_dir != new_dir) {
retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
@@ -873,8 +890,6 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
if (has_diriter) {
diriter.fi.icb.extLocation =
cpu_to_lelb(UDF_I(new_dir)->i_location);
- udf_update_tag((char *)&diriter.fi,
- udf_dir_entry_len(&diriter.fi));
udf_fiiter_write_fi(&diriter, NULL);
udf_fiiter_release(&diriter);
}