cifsd: get parent dentry from child in ksmbd_vfs_remove_file()
authorNamjae Jeon <namjae.jeon@samsung.com>
Tue, 13 Apr 2021 04:20:52 +0000 (13:20 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 11 May 2021 00:15:40 +0000 (19:15 -0500)
To remove the file, We have parsed full pathname to divide parent path and
filename. It is a better way to get parent dentry from child dentry that
obtained by lookup with given pathname.

Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifsd/vfs.c

index f818aef..010dfdd 100644 (file)
@@ -578,31 +578,28 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
  */
 int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
 {
-       struct path parent;
-       struct dentry *dentry;
-       char *last;
+       struct path path;
+       struct dentry *dentry, *parent;
        int err;
 
-       last = extract_last_component(name);
-       if (!last)
-               return -EINVAL;
-
        if (ksmbd_override_fsids(work))
                return -ENOMEM;
 
-       err = kern_path(name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &parent);
+       err = kern_path(name, LOOKUP_FOLLOW, &path);
        if (err) {
                ksmbd_debug(VFS, "can't get %s, err %d\n", name, err);
                ksmbd_revert_fsids(work);
-               rollback_path_modification(last);
                return err;
        }
 
-       inode_lock_nested(d_inode(parent.dentry), I_MUTEX_PARENT);
-       dentry = lookup_one_len(last, parent.dentry, strlen(last));
+       parent = dget_parent(path.dentry);
+       inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
+       dentry = lookup_one_len(path.dentry->d_name.name, parent,
+                       strlen(path.dentry->d_name.name));
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
-               ksmbd_debug(VFS, "%s: lookup failed, err %d\n", last, err);
+               ksmbd_debug(VFS, "%s: lookup failed, err %d\n",
+                               path.dentry->d_name.name, err);
                goto out_err;
        }
 
@@ -613,12 +610,12 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
        }
 
        if (S_ISDIR(d_inode(dentry)->i_mode)) {
-               err = vfs_rmdir(&init_user_ns, d_inode(parent.dentry), dentry);
+               err = vfs_rmdir(&init_user_ns, d_inode(parent), dentry);
                if (err && err != -ENOTEMPTY)
                        ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
                                err);
        } else {
-               err = vfs_unlink(&init_user_ns, d_inode(parent.dentry), dentry, NULL);
+               err = vfs_unlink(&init_user_ns, d_inode(parent), dentry, NULL);
                if (err)
                        ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
                                err);
@@ -626,9 +623,9 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
 
        dput(dentry);
 out_err:
-       inode_unlock(d_inode(parent.dentry));
-       rollback_path_modification(last);
-       path_put(&parent);
+       inode_unlock(d_inode(parent));
+       dput(parent);
+       path_put(&path);
        ksmbd_revert_fsids(work);
        return err;
 }