From: Shachar Sharon Date: Mon, 5 Jan 2026 10:11:17 +0000 (+0530) Subject: vfs_ceph_rgw: Add fntimes, fcntl and ftruncate methods X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7e958a2364f4146ba1f2bb498dcf2271ce5d74c;p=thirdparty%2Fsamba.git vfs_ceph_rgw: Add fntimes, fcntl and ftruncate methods Signed-off-by: Shachar Sharon Reviewed-by: Vinit Agnihotri Reviewed-by: Anoop C S Reviewed-by: Guenther Deschner --- diff --git a/source3/modules/vfs_ceph_rgw.c b/source3/modules/vfs_ceph_rgw.c index 803068b3559..602bdc310fa 100644 --- a/source3/modules/vfs_ceph_rgw.c +++ b/source3/modules/vfs_ceph_rgw.c @@ -1034,6 +1034,165 @@ out: return res; } +static void vfs_ceph_rgw_fill_stat_mask_from_ft(struct smb_file_time *ft, + struct stat *st, + uint32_t *mask) +{ + struct timespec time_now = timespec_current(); + + if (!is_omit_timespec(&ft->atime)) { + if (ft->atime.tv_nsec == UTIME_NOW) { + ft->atime = time_now; + } + st->st_atim = ft->atime; + *mask |= RGW_SETATTR_ATIME; + } + if (!is_omit_timespec(&ft->mtime)) { + if (ft->mtime.tv_nsec == UTIME_NOW) { + ft->mtime = time_now; + } + st->st_mtim = ft->mtime; + *mask |= RGW_SETATTR_MTIME; + } + if (!is_omit_timespec(&ft->ctime)) { + if (ft->ctime.tv_nsec == UTIME_NOW) { + ft->ctime = time_now; + } + st->st_ctim = ft->ctime; + *mask |= RGW_SETATTR_CTIME; + } +} + +static int vfs_ceph_rgw_setattr(struct vfs_handle_struct *handle, + files_struct *fsp, + uint32_t mask, + struct stat *st) +{ + int rc = -ENOMEM; + struct vfs_ceph_rgw_config *config = NULL; + struct vfs_ceph_rgw_fh *fh = NULL; + + SMB_VFS_HANDLE_GET_DATA(handle, + config, + struct vfs_ceph_rgw_config, + goto out); + + rc = vfs_ceph_rgw_fetch_fh(handle, fsp, &fh); + if (rc != 0) { + DBG_ERR("[CEPH_RGW] Unable to fetch handle\n"); + goto out; + } + + rc = rgw_setattr(config->rgw_root_fs, + fh->rgw_fh, + st, + mask, + RGW_SETATTR_FLAG_NONE); + if (rc < 0) { + DBG_ERR("[CEPH_RGW] Unable to set attributes\n"); + goto out; + } + +out: + return rc; +} + +static int vfs_ceph_rgw_fntimes(struct vfs_handle_struct *handle, + files_struct *fsp, + struct smb_file_time *ft) +{ + int rc = -ENOMEM; + uint32_t mask = 0; + struct stat st = {0}; + + START_PROFILE_X(SNUM(handle->conn), syscall_fntimes); + + vfs_ceph_rgw_fill_stat_mask_from_ft(ft, &st, &mask); + if (mask == 0) { + rc = 0; + goto out; + } + + rc = vfs_ceph_rgw_setattr(handle, fsp, mask, &st); + if (rc < 0) { + DBG_ERR("[CEPH_RGW] Unable to set fntimes. rc = %d\n", rc); + goto out; + } + + if (!is_omit_timespec(&ft->create_time)) { + set_create_timespec_ea(fsp, ft->create_time); + } + +out: + END_PROFILE_X(syscall_fntimes); + return status_code(rc); +} + +static int vfs_ceph_rgw_fcntl(vfs_handle_struct *handle, + files_struct *fsp, + int cmd, + va_list cmd_arg) +{ + int result = 0; + + START_PROFILE_X(SNUM(handle->conn), syscall_fcntl); + /* + * SMB_VFS_FCNTL() is currently only called by vfs_set_blocking() to + * clear O_NONBLOCK, etc for LOCK_MAND and FIFOs. Ignore it. + */ + if (cmd == F_GETFL || cmd == F_SETFL) { + goto out; + } + DBG_ERR("[CEPH_RGW] unexpected fcntl: %d\n", cmd); + result = -1; + errno = EINVAL; +out: + END_PROFILE_X(syscall_fcntl); + return result; +} + +static int vfs_ceph_rgw_ftruncate(struct vfs_handle_struct *handle, + files_struct *fsp, + off_t len) +{ + int rc = -ENOMEM; + struct vfs_ceph_rgw_fh *fh = NULL; + struct vfs_ceph_rgw_config *config = NULL; + + START_PROFILE_X(SNUM(handle->conn), syscall_ftruncate); + + DBG_DEBUG("[CEPH_RGW] ftruncate: name='%s' len=%jd\n", + fsp_str_dbg(fsp), + (intmax_t)len); + + SMB_VFS_HANDLE_GET_DATA(handle, + config, + struct vfs_ceph_rgw_config, + goto out); + + rc = vfs_ceph_rgw_fetch_fh(handle, fsp, &fh); + if (rc != 0) { + goto out; + } + + if (len < 0) { + rc = -EINVAL; + goto out; + } + + rc = rgw_truncate(config->rgw_root_fs, + fh->rgw_fh, + (uint64_t)len, + RGW_TRUNCATE_FLAG_NONE); +out: + DBG_DEBUG("[CEPH_RGW] ftruncate: name=%s len=%jd rc=%d\n", + fsp_str_dbg(fsp), + (intmax_t)len, + rc); + END_PROFILE_X(syscall_ftruncate); + return status_code(rc); +} + static bool vfs_ceph_rgw_mount_bucket(struct vfs_ceph_rgw_config *config) { int rc = 0; @@ -1294,12 +1453,12 @@ static struct vfs_fn_pointers ceph_rgw_fns = { .fchown_fn = vfs_not_implemented_fchown, .lchown_fn = vfs_not_implemented_lchown, .chdir_fn = vfs_ceph_rgw_chdir, - .fntimes_fn = vfs_not_implemented_fntimes, - .ftruncate_fn = vfs_not_implemented_ftruncate, + .fntimes_fn = vfs_ceph_rgw_fntimes, + .ftruncate_fn = vfs_ceph_rgw_ftruncate, .fallocate_fn = vfs_not_implemented_fallocate, .lock_fn = vfs_not_implemented_lock, .filesystem_sharemode_fn = vfs_not_implemented_filesystem_sharemode, - .fcntl_fn = vfs_not_implemented_fcntl, + .fcntl_fn = vfs_ceph_rgw_fcntl, .linux_setlease_fn = vfs_not_implemented_linux_setlease, .getlock_fn = vfs_not_implemented_getlock, .symlinkat_fn = vfs_not_implemented_symlinkat,