Messages in this thread | | | Subject | Re: [PATCH v27 04/10] fs/ntfs3: Add file operations and implementation | From | Christophe JAILLET <> | Date | Fri, 30 Jul 2021 09:40:26 +0200 |
| |
Le 29/07/2021 à 15:49, Konstantin Komarov a écrit : > This adds file operations and implementation > > Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com> > --- > fs/ntfs3/dir.c | 594 +++++++++ > fs/ntfs3/file.c | 1130 ++++++++++++++++ > fs/ntfs3/frecord.c | 3071 ++++++++++++++++++++++++++++++++++++++++++++ > fs/ntfs3/namei.c | 578 +++++++++ > fs/ntfs3/record.c | 609 +++++++++ > fs/ntfs3/run.c | 1111 ++++++++++++++++ > 6 files changed, 7093 insertions(+) > create mode 100644 fs/ntfs3/dir.c > create mode 100644 fs/ntfs3/file.c > create mode 100644 fs/ntfs3/frecord.c > create mode 100644 fs/ntfs3/namei.c > create mode 100644 fs/ntfs3/record.c > create mode 100644 fs/ntfs3/run.c >
[...]
> diff --git a/fs/ntfs3/namei.c b/fs/ntfs3/namei.c > new file mode 100644 > index 000000000..f5db12cd3 > --- /dev/null > +++ b/fs/ntfs3/namei.c
[...]
> +/* > + * ntfs_rename > + * > + * inode_operations::rename > + */ > +static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, > + struct dentry *old_dentry, struct inode *new_dir, > + struct dentry *new_dentry, u32 flags) > +{ > + int err; > + struct super_block *sb = old_dir->i_sb; > + struct ntfs_sb_info *sbi = sb->s_fs_info; > + struct ntfs_inode *old_dir_ni = ntfs_i(old_dir); > + struct ntfs_inode *new_dir_ni = ntfs_i(new_dir); > + struct ntfs_inode *old_ni; > + struct ATTR_FILE_NAME *old_name, *new_name, *fname; > + u8 name_type; > + bool is_same; > + struct inode *old_inode, *new_inode; > + struct NTFS_DE *old_de, *new_de; > + struct ATTRIB *attr; > + struct ATTR_LIST_ENTRY *le; > + u16 new_de_key_size; > + > + static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024); > + static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) < > + 1024); > + static_assert(PATH_MAX >= 4 * 1024); > + > + if (flags & ~RENAME_NOREPLACE) > + return -EINVAL; > + > + old_inode = d_inode(old_dentry); > + new_inode = d_inode(new_dentry); > + > + old_ni = ntfs_i(old_inode); > + > + is_same = old_dentry->d_name.len == new_dentry->d_name.len && > + !memcmp(old_dentry->d_name.name, new_dentry->d_name.name, > + old_dentry->d_name.len); > + > + if (is_same && old_dir == new_dir) { > + /* Nothing to do */ > + err = 0; > + goto out; > + } > + > + if (ntfs_is_meta_file(sbi, old_inode->i_ino)) { > + err = -EINVAL; > + goto out; > + } > + > + if (new_inode) { > + /*target name exists. unlink it*/ > + dget(new_dentry); > + ni_lock_dir(new_dir_ni); > + err = ntfs_unlink_inode(new_dir, new_dentry); > + ni_unlock(new_dir_ni); > + dput(new_dentry); > + if (err) > + goto out; > + } > + > + /* allocate PATH_MAX bytes */ > + old_de = __getname(); > + if (!old_de) { > + err = -ENOMEM; > + goto out; > + } > + > + err = fill_name_de(sbi, old_de, &old_dentry->d_name, NULL); > + if (err < 0) > + goto out1; > + > + old_name = (struct ATTR_FILE_NAME *)(old_de + 1); > + > + if (is_same) { > + new_de = old_de; > + } else { > + new_de = Add2Ptr(old_de, 1024); > + err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL); > + if (err < 0) > + goto out1; > + } > + > + ni_lock_dir(old_dir_ni); > + ni_lock(old_ni); > + > + mi_get_ref(&old_dir_ni->mi, &old_name->home); > + > + /*get pointer to file_name in mft*/ > + fname = ni_fname_name(old_ni, (struct cpu_str *)&old_name->name_len, > + &old_name->home, &le); > + if (!fname) { > + err = -EINVAL; > + goto out2; > + } > + > + /* Copy fname info from record into new fname */ > + new_name = (struct ATTR_FILE_NAME *)(new_de + 1); > + memcpy(&new_name->dup, &fname->dup, sizeof(fname->dup)); > + > + name_type = paired_name(fname->type); > + > + /* remove first name from directory */ > + err = indx_delete_entry(&old_dir_ni->dir, old_dir_ni, old_de + 1, > + le16_to_cpu(old_de->key_size), sbi); > + if (err) > + goto out3; > + > + /* remove first name from mft */ > + err = ni_remove_attr_le(old_ni, attr_from_name(fname), le); > + if (err) > + goto out4; > + > + le16_add_cpu(&old_ni->mi.mrec->hard_links, -1); > + old_ni->mi.dirty = true; > + > + if (name_type != FILE_NAME_POSIX) { > + /* get paired name */ > + fname = ni_fname_type(old_ni, name_type, &le); > + if (fname) { > + /* remove second name from directory */ > + err = indx_delete_entry(&old_dir_ni->dir, old_dir_ni, > + fname, fname_full_size(fname), > + sbi); > + if (err) > + goto out5; > + > + /* remove second name from mft */ > + err = ni_remove_attr_le(old_ni, attr_from_name(fname), > + le); > + if (err) > + goto out6; > + > + le16_add_cpu(&old_ni->mi.mrec->hard_links, -1); > + old_ni->mi.dirty = true; > + } > + } > + > + /* Add new name */ > + mi_get_ref(&old_ni->mi, &new_de->ref); > + mi_get_ref(&ntfs_i(new_dir)->mi, &new_name->home); > + > + new_de_key_size = le16_to_cpu(new_de->key_size); > + > + /* insert new name in mft */ > + err = ni_insert_resident(old_ni, new_de_key_size, ATTR_NAME, NULL, 0, > + &attr, NULL); > + if (err) > + goto out7; > + > + attr->res.flags = RESIDENT_FLAG_INDEXED; > + > + memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), new_name, new_de_key_size); > + > + le16_add_cpu(&old_ni->mi.mrec->hard_links, 1); > + old_ni->mi.dirty = true; > + > + /* insert new name in directory */ > + err = indx_insert_entry(&new_dir_ni->dir, new_dir_ni, new_de, sbi, > + NULL); > + if (err) > + goto out8; > + > + if (IS_DIRSYNC(new_dir)) > + err = ntfs_sync_inode(old_inode);
This value returned by 'ntfs_sync_inode()' is silenced below. Maybe the same should be done here? Anyway, this 'err' is never used and is forced to 0 below
> + else > + mark_inode_dirty(old_inode); > + > + old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); > + if (IS_DIRSYNC(old_dir)) > + (void)ntfs_sync_inode(old_dir);
here
> + else > + mark_inode_dirty(old_dir); > + > + if (old_dir != new_dir) { > + new_dir->i_mtime = new_dir->i_ctime = old_dir->i_ctime; > + mark_inode_dirty(new_dir); > + } > + > + if (old_inode) { > + old_inode->i_ctime = old_dir->i_ctime; > + mark_inode_dirty(old_inode); > + } > + > + err = 0;
and here.
> + /* normal way */ > + goto out2; > + > +out8: > + /* undo > + * ni_insert_resident(old_ni, new_de_key_size, ATTR_NAME, NULL, 0, > + * &attr, NULL); > + */ > + mi_remove_attr(&old_ni->mi, attr); > +out7: > + /* undo > + * ni_remove_attr_le(old_ni, attr_from_name(fname), le); > + */ > +out6: > + /* undo > + * indx_delete_entry(&old_dir_ni->dir, old_dir_ni, > + * fname, fname_full_size(fname), > + * sbi); > + */ > +out5: > + /* undo > + * ni_remove_attr_le(old_ni, attr_from_name(fname), le); > + */ > +out4: > + /* undo: > + * indx_delete_entry(&old_dir_ni->dir, old_dir_ni, old_de + 1, > + * old_de->key_size, NULL); > + */ > +out3: > +out2: > + ni_unlock(old_ni); > + ni_unlock(old_dir_ni); > +out1: > + __putname(old_de); > +out: > + return err; > +}
[...]
| |