1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-01 04:58:35 +03:00

vfs_ceph_new: use low-level APIs for stat

Start migrating to libcephfs' low-level APIs, using explicit Inode*
reference. Implement the VFS 'stat' hook using a ceph_ll_getattr
function, encapsulated with a pair of iget/iput to hold a
pinned-to-cache Inode* instance.

Upon calling to libcephfs this new code crates and destroys on-the-fly
a Ceph UserPerm instance based on the uig, gid and groups from
'handle->conn->session_info->unix_token'. This logic ensures that the
correct caller-credentials are passed-on to cephfs (instead of those
set upon connection-creation in legacy 'vfs_ceph.c').

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>
This commit is contained in:
Shachar Sharon 2024-06-17 12:11:18 +03:00 committed by Günther Deschner
parent 192b0cf871
commit 1b78d79663

View File

@ -335,6 +335,175 @@ static void vfs_ceph_disconnect(struct vfs_handle_struct *handle)
handle->data = NULL;
}
/* Ceph user-credentials */
static struct UserPerm *vfs_ceph_userperm_new(
const struct vfs_handle_struct *handle)
{
const struct security_unix_token *unix_token = NULL;
unix_token = get_current_utok(handle->conn);
return ceph_userperm_new(unix_token->uid,
unix_token->gid,
unix_token->ngroups,
unix_token->groups);
}
static void vfs_ceph_userperm_del(struct UserPerm *uperm)
{
if (uperm != NULL) {
ceph_userperm_destroy(uperm);
}
}
/* Ceph's statx to Samba's stat_ex */
#define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS | CEPH_STATX_BTIME)
static void smb_stat_from_ceph_statx(SMB_STRUCT_STAT *st,
const struct ceph_statx *stx)
{
ZERO_STRUCTP(st);
st->st_ex_dev = stx->stx_dev;
st->st_ex_rdev = stx->stx_rdev;
st->st_ex_ino = stx->stx_ino;
st->st_ex_mode = stx->stx_mode;
st->st_ex_uid = stx->stx_uid;
st->st_ex_gid = stx->stx_gid;
st->st_ex_size = stx->stx_size;
st->st_ex_nlink = stx->stx_nlink;
st->st_ex_atime = stx->stx_atime;
st->st_ex_btime = stx->stx_btime;
st->st_ex_ctime = stx->stx_ctime;
st->st_ex_mtime = stx->stx_mtime;
st->st_ex_blksize = stx->stx_blksize;
st->st_ex_blocks = stx->stx_blocks;
}
/* Ceph's inode + ino-number */
struct vfs_ceph_iref {
struct Inode *inode;
uint64_t ino; /* for debug printing */
};
/* Ceph low-level wrappers */
static int vfs_ceph_ll_lookup_inode(const struct vfs_handle_struct *handle,
uint64_t inoval,
Inode **pout)
{
struct inodeno_t ino = {.val = inoval};
return ceph_ll_lookup_inode(handle->data, ino, pout);
}
static int vfs_ceph_ll_walk(const struct vfs_handle_struct *handle,
const char *name,
struct Inode **pin,
struct ceph_statx *stx,
unsigned int want,
unsigned int flags)
{
struct UserPerm *uperm = NULL;
int ret = -1;
uperm = vfs_ceph_userperm_new(handle);
if (uperm == NULL) {
return -ENOMEM;
}
ret = ceph_ll_walk(handle->data, name, pin, stx, want, flags, uperm);
vfs_ceph_userperm_del(uperm);
return ret;
}
static int vfs_ceph_ll_getattr(const struct vfs_handle_struct *handle,
const struct vfs_ceph_iref *iref,
SMB_STRUCT_STAT *st)
{
struct ceph_statx stx = {0};
struct UserPerm *uperm = NULL;
int ret = -1;
uperm = vfs_ceph_userperm_new(handle);
if (uperm == NULL) {
return -ENOMEM;
}
ret = ceph_ll_getattr(handle->data,
iref->inode,
&stx,
SAMBA_STATX_ATTR_MASK,
0,
uperm);
if (ret == 0) {
smb_stat_from_ceph_statx(st, &stx);
}
vfs_ceph_userperm_del(uperm);
return ret;
}
/* Ceph Inode-refernce get/put wrappers */
static int vfs_ceph_iget(const struct vfs_handle_struct *handle,
uint64_t ino,
const char *name,
unsigned int flags,
struct vfs_ceph_iref *iref)
{
struct Inode *inode = NULL;
int ret = -1;
if (ino > CEPH_INO_ROOT) {
/* get-by-ino */
ret = vfs_ceph_ll_lookup_inode(handle, ino, &inode);
if (ret != 0) {
return ret;
}
} else {
/* get-by-path */
struct ceph_statx stx = {.stx_ino = 0};
ret = vfs_ceph_ll_walk(handle,
name,
&inode,
&stx,
CEPH_STATX_INO,
flags);
if (ret != 0) {
return ret;
}
ino = stx.stx_ino;
}
iref->inode = inode;
iref->ino = ino;
DBG_DEBUG("[CEPH] get-inode: %s ino=%" PRIu64 "\n", name, iref->ino);
return 0;
}
static int vfs_ceph_iget_by_fname(const struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
struct vfs_ceph_iref *iref)
{
const char *name = smb_fname->base_name;
const char *cwd = ceph_getcwd(handle->data);
int ret = -1;
if (!strcmp(name, cwd)) {
ret = vfs_ceph_iget(handle, 0, "./", 0, iref);
} else {
ret = vfs_ceph_iget(handle, 0, name, 0, iref);
}
return ret;
}
static void vfs_ceph_iput(const struct vfs_handle_struct *handle,
struct vfs_ceph_iref *iref)
{
if ((iref != NULL) && (iref->inode != NULL)) {
DBG_DEBUG("[CEPH] put-inode: ino=%" PRIu64 "\n", iref->ino);
ceph_ll_put(handle->data, iref->inode);
iref->inode = NULL;
}
}
/* Disk operations */
static uint64_t vfs_ceph_disk_free(struct vfs_handle_struct *handle,
@ -876,8 +1045,6 @@ static int vfs_ceph_fsync_recv(struct tevent_req *req,
return 0;
}
#define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
static void init_stat_ex_from_ceph_statx(struct stat_ex *dst,
const struct ceph_statx *stx)
{
@ -920,7 +1087,7 @@ static int vfs_ceph_stat(struct vfs_handle_struct *handle,
struct smb_filename *smb_fname)
{
int result = -1;
struct ceph_statx stx = { 0 };
struct vfs_ceph_iref iref = {0};
DBG_DEBUG("[CEPH] stat(%p, %s)\n",
handle,
@ -931,16 +1098,20 @@ static int vfs_ceph_stat(struct vfs_handle_struct *handle,
return result;
}
result = ceph_statx(handle->data, smb_fname->base_name, &stx,
SAMBA_STATX_ATTR_MASK, 0);
DBG_DEBUG("[CEPH] statx(...) = %d\n", result);
if (result < 0) {
return status_code(result);
result = vfs_ceph_iget_by_fname(handle, smb_fname, &iref);
if (result != 0) {
goto out;
}
init_stat_ex_from_ceph_statx(&smb_fname->st, &stx);
DBG_DEBUG("[CEPH] stat: ino=%" PRIu64 "\n", iref.ino);
result = vfs_ceph_ll_getattr(handle, &iref, &smb_fname->st);
if (result != 0) {
goto out;
}
DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname->st.st_ex_mode);
return result;
out:
vfs_ceph_iput(handle, &iref);
return status_code(result);
}
static int vfs_ceph_fstat(struct vfs_handle_struct *handle,