]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_ceph_new: use low-level APIs for fchown/fchmod
authorShachar Sharon <ssharon@redhat.com>
Wed, 19 Jun 2024 09:48:14 +0000 (12:48 +0300)
committerGünther Deschner <gd@samba.org>
Mon, 29 Jul 2024 14:51:37 +0000 (14:51 +0000)
Use libcephfs' low-level APIs to implement 'fchown' and 'fchmod' using
open file-handle. If fsp does not have an open cephfs Fh reference,
set errno to EBADF and return -1 to VFS.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15686

Signed-off-by: Shachar Sharon <ssharon@redhat.com>
Reviewed-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Anoop C S <anoopcs@samba.org>
source3/modules/vfs_ceph_new.c

index e106a9bb4cb925ca97796666ec6c3480db9701e1..20cd95ef16c3e6cfc3c7799c1f257fa38a240597 100644 (file)
@@ -485,6 +485,14 @@ static int vfs_ceph_fetch_fh(struct vfs_handle_struct *handle,
        return (*out_cfh == NULL) ? -EBADF : 0;
 }
 
+static int vfs_ceph_fetch_io_fh(struct vfs_handle_struct *handle,
+                               const struct files_struct *fsp,
+                               struct vfs_ceph_fh **out_cfh)
+{
+       *out_cfh = VFS_FETCH_FSP_EXTENSION(handle, fsp);
+       return (*out_cfh == NULL) || ((*out_cfh)->fh == NULL) ? -EBADF : 0;
+}
+
 static void vfs_ceph_assign_fh_fd(struct vfs_ceph_fh *cfh)
 {
        cfh->fd = cephmount_next_fd(cfh->cme); /* debug only */
@@ -593,6 +601,33 @@ static int vfs_ceph_ll_chown(struct vfs_handle_struct *handle,
        return ret;
 }
 
+static int vfs_ceph_ll_fchown(struct vfs_handle_struct *handle,
+                             const struct vfs_ceph_fh *cfh,
+                             uid_t uid,
+                             gid_t gid)
+{
+       struct ceph_statx stx = {.stx_uid = uid, .stx_gid = gid};
+
+       return ceph_ll_setattr(cmount_of(handle),
+                              cfh->iref.inode,
+                              &stx,
+                              CEPH_STATX_UID | CEPH_STATX_GID,
+                              cfh->uperm);
+}
+
+static int vfs_ceph_ll_fchmod(struct vfs_handle_struct *handle,
+                             const struct vfs_ceph_fh *cfh,
+                             mode_t mode)
+{
+       struct ceph_statx stx = {.stx_mode = mode};
+
+       return ceph_ll_setattr(cmount_of(handle),
+                              cfh->iref.inode,
+                              &stx,
+                              CEPH_STATX_MODE,
+                              cfh->uperm);
+}
+
 static int vfs_ceph_ll_releasedir(const struct vfs_handle_struct *handle,
                                  const struct vfs_ceph_fh *dircfh)
 {
@@ -1712,23 +1747,16 @@ static int vfs_ceph_fchmod(struct vfs_handle_struct *handle,
                           mode_t mode)
 {
        int result;
+       struct vfs_ceph_fh *cfh = NULL;
 
        DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle, fsp, mode);
-       if (!fsp->fsp_flags.is_pathref) {
-               /*
-                * We can use an io_fd to change permissions.
-                */
-               result = ceph_fchmod(cmount_of(handle),
-                                    fsp_get_io_fd(fsp),
-                                    mode);
-       } else {
-               /*
-                * This is no longer a handle based call.
-                */
-               result = ceph_chmod(cmount_of(handle),
-                                   fsp->fsp_name->base_name,
-                                   mode);
+       result = vfs_ceph_fetch_io_fh(handle, fsp, &cfh);
+       if (result != 0) {
+               goto out;
        }
+
+       result = vfs_ceph_ll_fchmod(handle, cfh, mode);
+out:
        DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result);
        return status_code(result);
 }
@@ -1739,26 +1767,15 @@ static int vfs_ceph_fchown(struct vfs_handle_struct *handle,
                           gid_t gid)
 {
        int result;
+       struct vfs_ceph_fh *cfh = NULL;
 
        DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle, fsp, uid, gid);
-       if (!fsp->fsp_flags.is_pathref) {
-               /*
-                * We can use an io_fd to change ownership.
-                */
-               result = ceph_fchown(cmount_of(handle),
-                                    fsp_get_io_fd(fsp),
-                                    uid,
-                                    gid);
-       } else {
-               /*
-                * This is no longer a handle based call.
-                */
-               result = ceph_chown(cmount_of(handle),
-                                   fsp->fsp_name->base_name,
-                                   uid,
-                                   gid);
+       result = vfs_ceph_fetch_io_fh(handle, fsp, &cfh);
+       if (result != 0) {
+               goto out;
        }
-
+       result = vfs_ceph_ll_fchown(handle, cfh, uid, gid);
+out:
        DBG_DEBUG("[CEPH] fchown(...) = %d\n", result);
        return status_code(result);
 }