]> Git Repo - J-linux.git/blobdiff - fs/smb/server/vfs.c
Merge tag 'pull-rename' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[J-linux.git] / fs / smb / server / vfs.c
index 4cf8523ad0381a50eed016607877826899824b59..b6904a9b05f66c63ec86b745847a5feb2b51bb05 100644 (file)
@@ -97,6 +97,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
                return -ENOENT;
        }
 
+       err = mnt_want_write(parent_path->mnt);
+       if (err) {
+               path_put(parent_path);
+               putname(filename);
+               return -ENOENT;
+       }
+
        inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
        d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
        if (IS_ERR(d))
@@ -123,6 +130,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
 
 err_out:
        inode_unlock(d_inode(parent_path->dentry));
+       mnt_drop_write(parent_path->mnt);
        path_put(parent_path);
        putname(filename);
        return -ENOENT;
@@ -451,7 +459,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
                                 fp->stream.name,
                                 (void *)stream_buf,
                                 size,
-                                0);
+                                0,
+                                true);
        if (err < 0)
                goto out;
 
@@ -508,6 +517,9 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
                }
        }
 
+       /* Reserve lease break for parent dir at closing time */
+       fp->reserve_lease_break = true;
+
        /* Do we need to break any of a levelII oplock? */
        smb_break_all_levII_oplock(work, fp, 1);
 
@@ -593,10 +605,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
                goto out_err;
        }
 
-       err = mnt_want_write(path->mnt);
-       if (err)
-               goto out_err;
-
        idmap = mnt_idmap(path->mnt);
        if (S_ISDIR(d_inode(path->dentry)->i_mode)) {
                err = vfs_rmdir(idmap, d_inode(parent), path->dentry);
@@ -607,7 +615,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
                if (err)
                        ksmbd_debug(VFS, "unlink failed, err %d\n", err);
        }
-       mnt_drop_write(path->mnt);
 
 out_err:
        ksmbd_revert_fsids(work);
@@ -719,7 +726,7 @@ retry:
                goto out3;
        }
 
-       parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent));
+       parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent);
        if (parent_fp) {
                if (parent_fp->daccess & FILE_DELETE_LE) {
                        pr_err("parent dir is opened with delete access\n");
@@ -912,18 +919,22 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap,
  * @attr_value:        xattr value to set
  * @attr_size: size of xattr value
  * @flags:     destination buffer length
+ * @get_write: get write access to a mount
  *
  * Return:     0 on success, otherwise error
  */
 int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
                       const struct path *path, const char *attr_name,
-                      void *attr_value, size_t attr_size, int flags)
+                      void *attr_value, size_t attr_size, int flags,
+                      bool get_write)
 {
        int err;
 
-       err = mnt_want_write(path->mnt);
-       if (err)
-               return err;
+       if (get_write == true) {
+               err = mnt_want_write(path->mnt);
+               if (err)
+                       return err;
+       }
 
        err = vfs_setxattr(idmap,
                           path->dentry,
@@ -933,7 +944,8 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap,
                           flags);
        if (err)
                ksmbd_debug(VFS, "setxattr failed, err %d\n", err);
-       mnt_drop_write(path->mnt);
+       if (get_write == true)
+               mnt_drop_write(path->mnt);
        return err;
 }
 
@@ -1257,6 +1269,13 @@ out1:
        }
 
        if (!err) {
+               err = mnt_want_write(parent_path->mnt);
+               if (err) {
+                       path_put(path);
+                       path_put(parent_path);
+                       return err;
+               }
+
                err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
                if (err) {
                        path_put(path);
@@ -1266,6 +1285,14 @@ out1:
        return err;
 }
 
+void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path)
+{
+       inode_unlock(d_inode(parent_path->dentry));
+       mnt_drop_write(parent_path->mnt);
+       path_put(path);
+       path_put(parent_path);
+}
+
 struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
                                          const char *name,
                                          unsigned int flags,
@@ -1420,7 +1447,8 @@ out:
 int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
                           struct mnt_idmap *idmap,
                           const struct path *path,
-                          struct smb_ntsd *pntsd, int len)
+                          struct smb_ntsd *pntsd, int len,
+                          bool get_write)
 {
        int rc;
        struct ndr sd_ndr = {0}, acl_ndr = {0};
@@ -1480,7 +1508,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
 
        rc = ksmbd_vfs_setxattr(idmap, path,
                                XATTR_NAME_SD, sd_ndr.data,
-                               sd_ndr.offset, 0);
+                               sd_ndr.offset, 0, get_write);
        if (rc < 0)
                pr_err("Failed to store XATTR ntacl :%d\n", rc);
 
@@ -1569,7 +1597,8 @@ free_n_data:
 
 int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
                                   const struct path *path,
-                                  struct xattr_dos_attrib *da)
+                                  struct xattr_dos_attrib *da,
+                                  bool get_write)
 {
        struct ndr n;
        int err;
@@ -1579,7 +1608,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap,
                return err;
 
        err = ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE,
-                                (void *)n.data, n.offset, 0);
+                                (void *)n.data, n.offset, 0, get_write);
        if (err)
                ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
        kfree(n.data);
@@ -1851,10 +1880,6 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
        }
        posix_state_to_acl(&acl_state, acls->a_entries);
 
-       rc = mnt_want_write(path->mnt);
-       if (rc)
-               goto out_err;
-
        rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
        if (rc < 0)
                ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1866,9 +1891,7 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
                        ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
                                    rc);
        }
-       mnt_drop_write(path->mnt);
 
-out_err:
        free_acl_state(&acl_state);
        posix_acl_release(acls);
        return rc;
@@ -1898,10 +1921,6 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
                }
        }
 
-       rc = mnt_want_write(path->mnt);
-       if (rc)
-               goto out_err;
-
        rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls);
        if (rc < 0)
                ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
@@ -1913,9 +1932,7 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap,
                        ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
                                    rc);
        }
-       mnt_drop_write(path->mnt);
 
-out_err:
        posix_acl_release(acls);
        return rc;
 }
This page took 0.039476 seconds and 4 git commands to generate.