2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
6 Copyright (C) Brian Chrisman 2011 <bchrisman@gmail.com>
7 Copyright (C) Richard Sharpe 2011 <realrichardsharpe@gmail.com>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * This VFS only works with the libceph.so user-space client. It is not needed
25 * if you are using the kernel client or the FUSE client.
27 * Add the following smb.conf parameter to each share that will be hosted on
30 * vfs objects = ceph [any others you need go here]
34 #include "smbd/smbd.h"
36 #include <sys/statvfs.h>
37 #include "cephfs/libcephfs.h"
38 #include "smbprofile.h"
39 #include "modules/posixacl_xattr.h"
40 #include "lib/util/tevent_unix.h"
43 #define DBGC_CLASS DBGC_VFS
45 #ifndef LIBCEPHFS_VERSION
46 #define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
47 #define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0)
51 * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
53 #define llu(_var) ((long long unsigned)_var)
56 * Note, libceph's return code model is to return -errno! So we have to convert
57 * to what Samba expects, with is set errno to -return and return -1
59 #define WRAP_RETURN(_res) \
68 * We mount only one file system and then all shares are assumed to be in that.
69 * FIXME: If we want to support more than one FS, then we have to deal with
72 * So, cmount tells us if we have been this way before and whether
73 * we need to mount ceph and cmount_cnt tells us how many times we have
76 static struct ceph_mount_info
* cmount
= NULL
;
77 static uint32_t cmount_cnt
= 0;
79 /* Check for NULL pointer parameters in cephwrap_* functions */
81 /* We don't want to have NULL function pointers lying around. Someone
82 is sure to try and execute them. These stubs are used to prevent
85 static int cephwrap_connect(struct vfs_handle_struct
*handle
, const char *service
, const char *user
)
89 int snum
= SNUM(handle
->conn
);
90 const char *conf_file
;
94 handle
->data
= cmount
; /* We have been here before */
99 /* if config_file and/or user_id are NULL, ceph will use defaults */
100 conf_file
= lp_parm_const_string(snum
, "ceph", "config_file", NULL
);
101 user_id
= lp_parm_const_string(snum
, "ceph", "user_id", NULL
);
103 DBG_DEBUG("[CEPH] calling: ceph_create\n");
104 ret
= ceph_create(&cmount
, user_id
);
109 DBG_DEBUG("[CEPH] calling: ceph_conf_read_file with %s\n",
110 (conf_file
== NULL
? "default path" : conf_file
));
111 ret
= ceph_conf_read_file(cmount
, conf_file
);
116 DBG_DEBUG("[CEPH] calling: ceph_conf_get\n");
117 ret
= ceph_conf_get(cmount
, "log file", buf
, sizeof(buf
));
122 /* libcephfs disables POSIX ACL support by default, enable it... */
123 ret
= ceph_conf_set(cmount
, "client_acl_type", "posix_acl");
127 /* tell libcephfs to perform local permission checks */
128 ret
= ceph_conf_set(cmount
, "fuse_default_permissions", "false");
133 DBG_DEBUG("[CEPH] calling: ceph_mount\n");
134 ret
= ceph_mount(cmount
, NULL
);
140 * encode mount context/state into our vfs/connection holding structure
141 * cmount is a ceph_mount_t*
143 handle
->data
= cmount
;
147 * Unless we have an async implementation of getxattrat turn this off.
149 lp_do_parameter(SNUM(handle
->conn
), "smbd:async dosmode", "false");
154 ceph_release(cmount
);
158 * Handle the error correctly. Ceph returns -errno.
160 DBG_DEBUG("[CEPH] Error return: %s\n", strerror(-ret
));
164 static void cephwrap_disconnect(struct vfs_handle_struct
*handle
)
169 DBG_ERR("[CEPH] Error, ceph not mounted\n");
173 /* Should we unmount/shutdown? Only if the last disconnect? */
175 DBG_DEBUG("[CEPH] Not shuting down CEPH because still more connections\n");
179 ret
= ceph_unmount(cmount
);
181 DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret
));
184 ret
= ceph_release(cmount
);
186 DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret
));
189 cmount
= NULL
; /* Make it safe */
192 /* Disk operations */
194 static uint64_t cephwrap_disk_free(struct vfs_handle_struct
*handle
,
195 const struct smb_filename
*smb_fname
,
200 struct statvfs statvfs_buf
;
203 if (!(ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
,
206 * Provide all the correct values.
208 *bsize
= statvfs_buf
.f_bsize
;
209 *dfree
= statvfs_buf
.f_bavail
;
210 *dsize
= statvfs_buf
.f_blocks
;
211 DBG_DEBUG("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
212 llu(*bsize
), llu(*dfree
), llu(*dsize
));
215 DBG_DEBUG("[CEPH] ceph_statfs returned %d\n", ret
);
220 static int cephwrap_get_quota(struct vfs_handle_struct
*handle
,
221 const struct smb_filename
*smb_fname
,
222 enum SMB_QUOTA_TYPE qtype
,
226 /* libceph: Ceph does not implement this */
228 /* was ifdef HAVE_SYS_QUOTAS */
231 ret
= ceph_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
245 static int cephwrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
247 /* libceph: Ceph does not implement this */
249 /* was ifdef HAVE_SYS_QUOTAS */
252 ret
= ceph_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
260 WRAP_RETURN(-ENOSYS
);
264 static int cephwrap_statvfs(struct vfs_handle_struct
*handle
,
265 const struct smb_filename
*smb_fname
,
266 vfs_statvfs_struct
*statbuf
)
268 struct statvfs statvfs_buf
;
271 ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
, &statvfs_buf
);
276 statbuf
->OptimalTransferSize
= statvfs_buf
.f_frsize
;
277 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
278 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
279 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
280 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
281 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
282 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
283 statbuf
->FsIdentifier
= statvfs_buf
.f_fsid
;
284 DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
285 (long int)statvfs_buf
.f_bsize
, (long int)statvfs_buf
.f_blocks
,
286 (long int)statvfs_buf
.f_bfree
, (long int)statvfs_buf
.f_bavail
);
291 static uint32_t cephwrap_fs_capabilities(struct vfs_handle_struct
*handle
,
292 enum timestamp_set_resolution
*p_ts_res
)
294 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
296 #ifdef HAVE_CEPH_STATX
297 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
299 *p_ts_res
= TIMESTAMP_SET_MSEC
;
305 /* Directory operations */
307 static DIR *cephwrap_opendir(struct vfs_handle_struct
*handle
,
308 const struct smb_filename
*smb_fname
,
309 const char *mask
, uint32_t attr
)
312 struct ceph_dir_result
*result
;
313 DBG_DEBUG("[CEPH] opendir(%p, %s)\n", handle
, smb_fname
->base_name
);
315 /* Returns NULL if it does not exist or there are problems ? */
316 ret
= ceph_opendir(handle
->data
, smb_fname
->base_name
, &result
);
319 errno
= -ret
; /* We return result which is NULL in this case */
322 DBG_DEBUG("[CEPH] opendir(...) = %d\n", ret
);
323 return (DIR *) result
;
326 static DIR *cephwrap_fdopendir(struct vfs_handle_struct
*handle
,
327 struct files_struct
*fsp
,
332 struct ceph_dir_result
*result
;
333 DBG_DEBUG("[CEPH] fdopendir(%p, %p)\n", handle
, fsp
);
335 ret
= ceph_opendir(handle
->data
, fsp
->fsp_name
->base_name
, &result
);
338 errno
= -ret
; /* We return result which is NULL in this case */
341 DBG_DEBUG("[CEPH] fdopendir(...) = %d\n", ret
);
342 return (DIR *) result
;
345 static struct dirent
*cephwrap_readdir(struct vfs_handle_struct
*handle
,
347 SMB_STRUCT_STAT
*sbuf
)
349 struct dirent
*result
;
351 DBG_DEBUG("[CEPH] readdir(%p, %p)\n", handle
, dirp
);
352 result
= ceph_readdir(handle
->data
, (struct ceph_dir_result
*) dirp
);
353 DBG_DEBUG("[CEPH] readdir(...) = %p\n", result
);
355 /* Default Posix readdir() does not give us stat info.
356 * Set to invalid to indicate we didn't return this info. */
358 SET_STAT_INVALID(*sbuf
);
362 static void cephwrap_seekdir(struct vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
364 DBG_DEBUG("[CEPH] seekdir(%p, %p, %ld)\n", handle
, dirp
, offset
);
365 ceph_seekdir(handle
->data
, (struct ceph_dir_result
*) dirp
, offset
);
368 static long cephwrap_telldir(struct vfs_handle_struct
*handle
, DIR *dirp
)
371 DBG_DEBUG("[CEPH] telldir(%p, %p)\n", handle
, dirp
);
372 ret
= ceph_telldir(handle
->data
, (struct ceph_dir_result
*) dirp
);
373 DBG_DEBUG("[CEPH] telldir(...) = %ld\n", ret
);
377 static void cephwrap_rewinddir(struct vfs_handle_struct
*handle
, DIR *dirp
)
379 DBG_DEBUG("[CEPH] rewinddir(%p, %p)\n", handle
, dirp
);
380 ceph_rewinddir(handle
->data
, (struct ceph_dir_result
*) dirp
);
383 static int cephwrap_mkdir(struct vfs_handle_struct
*handle
,
384 const struct smb_filename
*smb_fname
,
389 const char *path
= smb_fname
->base_name
;
391 DBG_DEBUG("[CEPH] mkdir(%p, %s)\n", handle
, path
);
393 if (lp_inherit_acls(SNUM(handle
->conn
))
394 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
395 && directory_has_default_acl(handle
->conn
, parent
)) {
401 result
= ceph_mkdir(handle
->data
, path
, mode
);
402 return WRAP_RETURN(result
);
405 static int cephwrap_rmdir(struct vfs_handle_struct
*handle
,
406 const struct smb_filename
*smb_fname
)
410 DBG_DEBUG("[CEPH] rmdir(%p, %s)\n", handle
, smb_fname
->base_name
);
411 result
= ceph_rmdir(handle
->data
, smb_fname
->base_name
);
412 DBG_DEBUG("[CEPH] rmdir(...) = %d\n", result
);
416 static int cephwrap_closedir(struct vfs_handle_struct
*handle
, DIR *dirp
)
420 DBG_DEBUG("[CEPH] closedir(%p, %p)\n", handle
, dirp
);
421 result
= ceph_closedir(handle
->data
, (struct ceph_dir_result
*) dirp
);
422 DBG_DEBUG("[CEPH] closedir(...) = %d\n", result
);
426 /* File operations */
428 static int cephwrap_open(struct vfs_handle_struct
*handle
,
429 struct smb_filename
*smb_fname
,
430 files_struct
*fsp
, int flags
, mode_t mode
)
432 int result
= -ENOENT
;
433 DBG_DEBUG("[CEPH] open(%p, %s, %p, %d, %d)\n", handle
,
434 smb_fname_str_dbg(smb_fname
), fsp
, flags
, mode
);
436 if (smb_fname
->stream_name
) {
440 result
= ceph_open(handle
->data
, smb_fname
->base_name
, flags
, mode
);
442 DBG_DEBUG("[CEPH] open(...) = %d\n", result
);
446 static int cephwrap_close(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
450 DBG_DEBUG("[CEPH] close(%p, %p)\n", handle
, fsp
);
451 result
= ceph_close(handle
->data
, fsp
->fh
->fd
);
452 DBG_DEBUG("[CEPH] close(...) = %d\n", result
);
457 static ssize_t
cephwrap_pread(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
458 size_t n
, off_t offset
)
462 DBG_DEBUG("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
464 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
465 DBG_DEBUG("[CEPH] pread(...) = %llu\n", llu(result
));
469 struct cephwrap_pread_state
{
471 struct vfs_aio_state vfs_aio_state
;
475 * Fake up an async ceph read by calling the synchronous API.
477 static struct tevent_req
*cephwrap_pread_send(struct vfs_handle_struct
*handle
,
479 struct tevent_context
*ev
,
480 struct files_struct
*fsp
,
482 size_t n
, off_t offset
)
484 struct tevent_req
*req
= NULL
;
485 struct cephwrap_pread_state
*state
= NULL
;
488 DBG_DEBUG("[CEPH] %s\n", __func__
);
489 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pread_state
);
494 ret
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
496 /* ceph returns -errno on error. */
497 tevent_req_error(req
, -ret
);
498 return tevent_req_post(req
, ev
);
501 state
->bytes_read
= ret
;
502 tevent_req_done(req
);
503 /* Return and schedule the completion of the call. */
504 return tevent_req_post(req
, ev
);
507 static ssize_t
cephwrap_pread_recv(struct tevent_req
*req
,
508 struct vfs_aio_state
*vfs_aio_state
)
510 struct cephwrap_pread_state
*state
=
511 tevent_req_data(req
, struct cephwrap_pread_state
);
513 DBG_DEBUG("[CEPH] %s\n", __func__
);
514 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
517 *vfs_aio_state
= state
->vfs_aio_state
;
518 return state
->bytes_read
;
521 static ssize_t
cephwrap_pwrite(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
522 size_t n
, off_t offset
)
526 DBG_DEBUG("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
527 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
528 DBG_DEBUG("[CEPH] pwrite(...) = %llu\n", llu(result
));
532 struct cephwrap_pwrite_state
{
533 ssize_t bytes_written
;
534 struct vfs_aio_state vfs_aio_state
;
538 * Fake up an async ceph write by calling the synchronous API.
540 static struct tevent_req
*cephwrap_pwrite_send(struct vfs_handle_struct
*handle
,
542 struct tevent_context
*ev
,
543 struct files_struct
*fsp
,
545 size_t n
, off_t offset
)
547 struct tevent_req
*req
= NULL
;
548 struct cephwrap_pwrite_state
*state
= NULL
;
551 DBG_DEBUG("[CEPH] %s\n", __func__
);
552 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pwrite_state
);
557 ret
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
559 /* ceph returns -errno on error. */
560 tevent_req_error(req
, -ret
);
561 return tevent_req_post(req
, ev
);
564 state
->bytes_written
= ret
;
565 tevent_req_done(req
);
566 /* Return and schedule the completion of the call. */
567 return tevent_req_post(req
, ev
);
570 static ssize_t
cephwrap_pwrite_recv(struct tevent_req
*req
,
571 struct vfs_aio_state
*vfs_aio_state
)
573 struct cephwrap_pwrite_state
*state
=
574 tevent_req_data(req
, struct cephwrap_pwrite_state
);
576 DBG_DEBUG("[CEPH] %s\n", __func__
);
577 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
580 *vfs_aio_state
= state
->vfs_aio_state
;
581 return state
->bytes_written
;
584 static off_t
cephwrap_lseek(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
588 DBG_DEBUG("[CEPH] cephwrap_lseek\n");
589 result
= ceph_lseek(handle
->data
, fsp
->fh
->fd
, offset
, whence
);
593 static ssize_t
cephwrap_sendfile(struct vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
594 off_t offset
, size_t n
)
597 * We cannot support sendfile because libceph is in user space.
599 DBG_DEBUG("[CEPH] cephwrap_sendfile\n");
604 static ssize_t
cephwrap_recvfile(struct vfs_handle_struct
*handle
,
611 * We cannot support recvfile because libceph is in user space.
613 DBG_DEBUG("[CEPH] cephwrap_recvfile\n");
618 static int cephwrap_rename(struct vfs_handle_struct
*handle
,
619 const struct smb_filename
*smb_fname_src
,
620 const struct smb_filename
*smb_fname_dst
)
623 DBG_DEBUG("[CEPH] cephwrap_rename\n");
624 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
629 result
= ceph_rename(handle
->data
, smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
634 * Fake up an async ceph fsync by calling the synchronous API.
637 static struct tevent_req
*cephwrap_fsync_send(struct vfs_handle_struct
*handle
,
639 struct tevent_context
*ev
,
642 struct tevent_req
*req
= NULL
;
643 struct vfs_aio_state
*state
= NULL
;
646 DBG_DEBUG("[CEPH] cephwrap_fsync_send\n");
648 req
= tevent_req_create(mem_ctx
, &state
, struct vfs_aio_state
);
653 /* Make sync call. */
654 ret
= ceph_fsync(handle
->data
, fsp
->fh
->fd
, false);
657 /* ceph_fsync returns -errno on error. */
658 tevent_req_error(req
, -ret
);
659 return tevent_req_post(req
, ev
);
662 /* Mark it as done. */
663 tevent_req_done(req
);
664 /* Return and schedule the completion of the call. */
665 return tevent_req_post(req
, ev
);
668 static int cephwrap_fsync_recv(struct tevent_req
*req
,
669 struct vfs_aio_state
*vfs_aio_state
)
671 struct vfs_aio_state
*state
=
672 tevent_req_data(req
, struct vfs_aio_state
);
674 DBG_DEBUG("[CEPH] cephwrap_fsync_recv\n");
676 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
679 *vfs_aio_state
= *state
;
683 #ifdef HAVE_CEPH_STATX
684 #define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
686 static void init_stat_ex_from_ceph_statx(struct stat_ex
*dst
, const struct ceph_statx
*stx
)
688 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, "
689 "nlink = %llu, uid = %d, gid = %d, rdev = %llx, size = %llu, "
690 "blksize = %llu, blocks = %llu, atime = %llu, mtime = %llu, "
691 "ctime = %llu, btime = %llu}\n",
692 llu(stx
->stx_dev
), llu(stx
->stx_ino
), stx
->stx_mode
,
693 llu(stx
->stx_nlink
), stx
->stx_uid
, stx
->stx_gid
,
694 llu(stx
->stx_rdev
), llu(stx
->stx_size
), llu(stx
->stx_blksize
),
695 llu(stx
->stx_blocks
), llu(stx
->stx_atime
.tv_sec
),
696 llu(stx
->stx_mtime
.tv_sec
), llu(stx
->stx_ctime
.tv_sec
),
697 llu(stx
->stx_btime
.tv_sec
));
699 if ((stx
->stx_mask
& SAMBA_STATX_ATTR_MASK
) != SAMBA_STATX_ATTR_MASK
) {
700 DBG_WARNING("%s: stx->stx_mask is incorrect (wanted %x, got %x)",
701 __func__
, SAMBA_STATX_ATTR_MASK
, stx
->stx_mask
);
704 dst
->st_ex_dev
= stx
->stx_dev
;
705 dst
->st_ex_rdev
= stx
->stx_rdev
;
706 dst
->st_ex_ino
= stx
->stx_ino
;
707 dst
->st_ex_mode
= stx
->stx_mode
;
708 dst
->st_ex_uid
= stx
->stx_uid
;
709 dst
->st_ex_gid
= stx
->stx_gid
;
710 dst
->st_ex_size
= stx
->stx_size
;
711 dst
->st_ex_nlink
= stx
->stx_nlink
;
712 dst
->st_ex_atime
= stx
->stx_atime
;
713 dst
->st_ex_btime
= stx
->stx_btime
;
714 dst
->st_ex_ctime
= stx
->stx_ctime
;
715 dst
->st_ex_mtime
= stx
->stx_mtime
;
716 dst
->st_ex_calculated_birthtime
= false;
717 dst
->st_ex_blksize
= stx
->stx_blksize
;
718 dst
->st_ex_blocks
= stx
->stx_blocks
;
721 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
722 struct smb_filename
*smb_fname
)
725 struct ceph_statx stx
;
727 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
729 if (smb_fname
->stream_name
) {
734 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
735 SAMBA_STATX_ATTR_MASK
, 0);
736 DBG_DEBUG("[CEPH] statx(...) = %d\n", result
);
741 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
742 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
746 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
749 struct ceph_statx stx
;
751 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
752 result
= ceph_fstatx(handle
->data
, fsp
->fh
->fd
, &stx
,
753 SAMBA_STATX_ATTR_MASK
, 0);
754 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
759 init_stat_ex_from_ceph_statx(sbuf
, &stx
);
760 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
764 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
765 struct smb_filename
*smb_fname
)
768 struct ceph_statx stx
;
770 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
772 if (smb_fname
->stream_name
) {
777 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
778 SAMBA_STATX_ATTR_MASK
, AT_SYMLINK_NOFOLLOW
);
779 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
784 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
788 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
789 const struct smb_filename
*smb_fname
,
790 struct smb_file_time
*ft
)
792 struct ceph_statx stx
= { 0 };
796 if (!null_timespec(ft
->atime
)) {
797 stx
.stx_atime
= ft
->atime
;
798 mask
|= CEPH_SETATTR_ATIME
;
800 if (!null_timespec(ft
->mtime
)) {
801 stx
.stx_mtime
= ft
->mtime
;
802 mask
|= CEPH_SETATTR_MTIME
;
804 if (!null_timespec(ft
->create_time
)) {
805 stx
.stx_btime
= ft
->create_time
;
806 mask
|= CEPH_SETATTR_BTIME
;
813 result
= ceph_setattrx(handle
->data
, smb_fname
->base_name
, &stx
, mask
, 0);
814 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
815 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
816 ft
->create_time
.tv_sec
, result
);
820 #else /* HAVE_CEPH_STATX */
822 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
823 struct smb_filename
*smb_fname
)
828 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
830 if (smb_fname
->stream_name
) {
835 result
= ceph_stat(handle
->data
, smb_fname
->base_name
, (struct stat
*) &stbuf
);
836 DBG_DEBUG("[CEPH] stat(...) = %d\n", result
);
841 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
842 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
843 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
844 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
845 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
846 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
848 init_stat_ex_from_stat(
849 &smb_fname
->st
, &stbuf
,
850 lp_fake_directory_create_times(SNUM(handle
->conn
)));
851 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
855 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
860 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
861 result
= ceph_fstat(handle
->data
, fsp
->fh
->fd
, (struct stat
*) &stbuf
);
862 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
867 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
868 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
869 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
870 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
871 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
872 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
874 init_stat_ex_from_stat(
876 lp_fake_directory_create_times(SNUM(handle
->conn
)));
877 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
881 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
882 struct smb_filename
*smb_fname
)
887 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
889 if (smb_fname
->stream_name
) {
894 result
= ceph_lstat(handle
->data
, smb_fname
->base_name
, &stbuf
);
895 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
900 init_stat_ex_from_stat(
901 &smb_fname
->st
, &stbuf
,
902 lp_fake_directory_create_times(SNUM(handle
->conn
)));
906 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
907 const struct smb_filename
*smb_fname
,
908 struct smb_file_time
*ft
)
913 if (null_timespec(ft
->atime
)) {
914 buf
.actime
= smb_fname
->st
.st_ex_atime
.tv_sec
;
916 buf
.actime
= ft
->atime
.tv_sec
;
918 if (null_timespec(ft
->mtime
)) {
919 buf
.modtime
= smb_fname
->st
.st_ex_mtime
.tv_sec
;
921 buf
.modtime
= ft
->mtime
.tv_sec
;
923 if (!null_timespec(ft
->create_time
)) {
924 set_create_timespec_ea(handle
->conn
, smb_fname
,
927 if (buf
.actime
== smb_fname
->st
.st_ex_atime
.tv_sec
&&
928 buf
.modtime
== smb_fname
->st
.st_ex_mtime
.tv_sec
) {
932 result
= ceph_utime(handle
->data
, smb_fname
->base_name
, &buf
);
933 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
934 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
935 ft
->create_time
.tv_sec
, result
);
938 #endif /* HAVE_CEPH_STATX */
940 static int cephwrap_unlink(struct vfs_handle_struct
*handle
,
941 const struct smb_filename
*smb_fname
)
945 DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
946 if (smb_fname
->stream_name
) {
950 result
= ceph_unlink(handle
->data
, smb_fname
->base_name
);
951 DBG_DEBUG("[CEPH] unlink(...) = %d\n", result
);
955 static int cephwrap_chmod(struct vfs_handle_struct
*handle
,
956 const struct smb_filename
*smb_fname
,
961 DBG_DEBUG("[CEPH] chmod(%p, %s, %d)\n", handle
, smb_fname
->base_name
, mode
);
962 result
= ceph_chmod(handle
->data
, smb_fname
->base_name
, mode
);
963 DBG_DEBUG("[CEPH] chmod(...) = %d\n", result
);
967 static int cephwrap_fchmod(struct vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
971 DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle
, fsp
, mode
);
972 result
= ceph_fchmod(handle
->data
, fsp
->fh
->fd
, mode
);
973 DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result
);
977 static int cephwrap_chown(struct vfs_handle_struct
*handle
,
978 const struct smb_filename
*smb_fname
,
983 DBG_DEBUG("[CEPH] chown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
984 result
= ceph_chown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
985 DBG_DEBUG("[CEPH] chown(...) = %d\n", result
);
989 static int cephwrap_fchown(struct vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
993 DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle
, fsp
, uid
, gid
);
994 result
= ceph_fchown(handle
->data
, fsp
->fh
->fd
, uid
, gid
);
995 DBG_DEBUG("[CEPH] fchown(...) = %d\n", result
);
999 static int cephwrap_lchown(struct vfs_handle_struct
*handle
,
1000 const struct smb_filename
*smb_fname
,
1005 DBG_DEBUG("[CEPH] lchown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
1006 result
= ceph_lchown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
1007 DBG_DEBUG("[CEPH] lchown(...) = %d\n", result
);
1008 WRAP_RETURN(result
);
1011 static int cephwrap_chdir(struct vfs_handle_struct
*handle
,
1012 const struct smb_filename
*smb_fname
)
1015 DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle
, smb_fname
->base_name
);
1016 result
= ceph_chdir(handle
->data
, smb_fname
->base_name
);
1017 DBG_DEBUG("[CEPH] chdir(...) = %d\n", result
);
1018 WRAP_RETURN(result
);
1021 static struct smb_filename
*cephwrap_getwd(struct vfs_handle_struct
*handle
,
1024 const char *cwd
= ceph_getcwd(handle
->data
);
1025 DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle
, cwd
);
1026 return synthetic_smb_fname(ctx
,
1033 static int strict_allocate_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1035 off_t space_to_write
;
1038 SMB_STRUCT_STAT
*pst
;
1040 status
= vfs_stat_fsp(fsp
);
1041 if (!NT_STATUS_IS_OK(status
)) {
1044 pst
= &fsp
->fsp_name
->st
;
1047 if (S_ISFIFO(pst
->st_ex_mode
))
1051 if (pst
->st_ex_size
== len
)
1054 /* Shrink - just ftruncate. */
1055 if (pst
->st_ex_size
> len
) {
1056 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1057 WRAP_RETURN(result
);
1060 space_to_write
= len
- pst
->st_ex_size
;
1061 result
= ceph_fallocate(handle
->data
, fsp
->fh
->fd
, 0, pst
->st_ex_size
,
1063 WRAP_RETURN(result
);
1066 static int cephwrap_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1070 DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle
, fsp
, llu(len
));
1072 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
1073 return strict_allocate_ftruncate(handle
, fsp
, len
);
1076 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1077 WRAP_RETURN(result
);
1080 static int cephwrap_fallocate(struct vfs_handle_struct
*handle
,
1081 struct files_struct
*fsp
,
1088 DBG_DEBUG("[CEPH] fallocate(%p, %p, %u, %llu, %llu\n",
1089 handle
, fsp
, mode
, llu(offset
), llu(len
));
1090 /* unsupported mode flags are rejected by libcephfs */
1091 result
= ceph_fallocate(handle
->data
, fsp
->fh
->fd
, mode
, offset
, len
);
1092 DBG_DEBUG("[CEPH] fallocate(...) = %d\n", result
);
1093 WRAP_RETURN(result
);
1096 static bool cephwrap_lock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1098 DBG_DEBUG("[CEPH] lock\n");
1102 static int cephwrap_kernel_flock(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1103 uint32_t share_mode
, uint32_t access_mask
)
1105 DBG_ERR("[CEPH] flock unsupported! Consider setting "
1106 "\"kernel share modes = no\"\n");
1112 static bool cephwrap_getlock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1114 DBG_DEBUG("[CEPH] getlock returning false and errno=0\n");
1121 * We cannot let this fall through to the default, because the file might only
1122 * be accessible from libceph (which is a user-space client) but the fd might
1123 * be for some file the kernel knows about.
1125 static int cephwrap_linux_setlease(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1130 DBG_DEBUG("[CEPH] linux_setlease\n");
1135 static int cephwrap_symlink(struct vfs_handle_struct
*handle
,
1136 const char *link_target
,
1137 const struct smb_filename
*new_smb_fname
)
1140 DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle
,
1142 new_smb_fname
->base_name
);
1143 result
= ceph_symlink(handle
->data
,
1145 new_smb_fname
->base_name
);
1146 DBG_DEBUG("[CEPH] symlink(...) = %d\n", result
);
1147 WRAP_RETURN(result
);
1150 static int cephwrap_readlink(struct vfs_handle_struct
*handle
,
1151 const struct smb_filename
*smb_fname
,
1156 DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle
,
1157 smb_fname
->base_name
, buf
, llu(bufsiz
));
1158 result
= ceph_readlink(handle
->data
, smb_fname
->base_name
, buf
, bufsiz
);
1159 DBG_DEBUG("[CEPH] readlink(...) = %d\n", result
);
1160 WRAP_RETURN(result
);
1163 static int cephwrap_link(struct vfs_handle_struct
*handle
,
1164 const struct smb_filename
*old_smb_fname
,
1165 const struct smb_filename
*new_smb_fname
)
1168 DBG_DEBUG("[CEPH] link(%p, %s, %s)\n", handle
,
1169 old_smb_fname
->base_name
,
1170 new_smb_fname
->base_name
);
1171 result
= ceph_link(handle
->data
,
1172 old_smb_fname
->base_name
,
1173 new_smb_fname
->base_name
);
1174 DBG_DEBUG("[CEPH] link(...) = %d\n", result
);
1175 WRAP_RETURN(result
);
1178 static int cephwrap_mknod(struct vfs_handle_struct
*handle
,
1179 const struct smb_filename
*smb_fname
,
1184 DBG_DEBUG("[CEPH] mknod(%p, %s)\n", handle
, smb_fname
->base_name
);
1185 result
= ceph_mknod(handle
->data
, smb_fname
->base_name
, mode
, dev
);
1186 DBG_DEBUG("[CEPH] mknod(...) = %d\n", result
);
1187 WRAP_RETURN(result
);
1191 * This is a simple version of real-path ... a better version is needed to
1192 * ask libceph about symbolic links.
1194 static struct smb_filename
*cephwrap_realpath(struct vfs_handle_struct
*handle
,
1196 const struct smb_filename
*smb_fname
)
1198 char *result
= NULL
;
1199 const char *path
= smb_fname
->base_name
;
1200 size_t len
= strlen(path
);
1201 struct smb_filename
*result_fname
= NULL
;
1204 if (len
&& (path
[0] == '/')) {
1205 r
= asprintf(&result
, "%s", path
);
1206 } else if ((len
>= 2) && (path
[0] == '.') && (path
[1] == '/')) {
1208 r
= asprintf(&result
, "%s",
1209 handle
->conn
->cwd_fname
->base_name
);
1211 r
= asprintf(&result
, "%s/%s",
1212 handle
->conn
->cwd_fname
->base_name
, &path
[2]);
1215 r
= asprintf(&result
, "%s/%s",
1216 handle
->conn
->cwd_fname
->base_name
, path
);
1223 DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle
, path
, result
);
1224 result_fname
= synthetic_smb_fname(ctx
,
1230 return result_fname
;
1233 static int cephwrap_chflags(struct vfs_handle_struct
*handle
,
1234 const struct smb_filename
*smb_fname
,
1241 static int cephwrap_get_real_filename(struct vfs_handle_struct
*handle
,
1244 TALLOC_CTX
*mem_ctx
,
1248 * Don't fall back to get_real_filename so callers can differentiate
1249 * between a full directory scan and an actual case-insensitive stat.
1255 static const char *cephwrap_connectpath(struct vfs_handle_struct
*handle
,
1256 const struct smb_filename
*smb_fname
)
1258 return handle
->conn
->connectpath
;
1261 /****************************************************************
1262 Extended attribute operations.
1263 *****************************************************************/
1265 static ssize_t
cephwrap_getxattr(struct vfs_handle_struct
*handle
,
1266 const struct smb_filename
*smb_fname
,
1272 DBG_DEBUG("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle
,
1273 smb_fname
->base_name
, name
, value
, llu(size
));
1274 ret
= ceph_getxattr(handle
->data
,
1275 smb_fname
->base_name
, name
, value
, size
);
1276 DBG_DEBUG("[CEPH] getxattr(...) = %d\n", ret
);
1280 return (ssize_t
)ret
;
1283 static ssize_t
cephwrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
1286 DBG_DEBUG("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle
, fsp
, name
, value
, llu(size
));
1287 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1288 ret
= ceph_fgetxattr(handle
->data
, fsp
->fh
->fd
, name
, value
, size
);
1290 ret
= ceph_getxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
);
1292 DBG_DEBUG("[CEPH] fgetxattr(...) = %d\n", ret
);
1296 return (ssize_t
)ret
;
1299 static ssize_t
cephwrap_listxattr(struct vfs_handle_struct
*handle
,
1300 const struct smb_filename
*smb_fname
,
1305 DBG_DEBUG("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle
,
1306 smb_fname
->base_name
, list
, llu(size
));
1307 ret
= ceph_listxattr(handle
->data
, smb_fname
->base_name
, list
, size
);
1308 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1312 return (ssize_t
)ret
;
1315 static ssize_t
cephwrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
1318 DBG_DEBUG("[CEPH] flistxattr(%p, %p, %p, %llu)\n",
1319 handle
, fsp
, list
, llu(size
));
1320 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1321 ret
= ceph_flistxattr(handle
->data
, fsp
->fh
->fd
, list
, size
);
1323 ret
= ceph_listxattr(handle
->data
, fsp
->fsp_name
->base_name
, list
, size
);
1325 DBG_DEBUG("[CEPH] flistxattr(...) = %d\n", ret
);
1329 return (ssize_t
)ret
;
1332 static int cephwrap_removexattr(struct vfs_handle_struct
*handle
,
1333 const struct smb_filename
*smb_fname
,
1337 DBG_DEBUG("[CEPH] removexattr(%p, %s, %s)\n", handle
,
1338 smb_fname
->base_name
, name
);
1339 ret
= ceph_removexattr(handle
->data
, smb_fname
->base_name
, name
);
1340 DBG_DEBUG("[CEPH] removexattr(...) = %d\n", ret
);
1344 static int cephwrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
1347 DBG_DEBUG("[CEPH] fremovexattr(%p, %p, %s)\n", handle
, fsp
, name
);
1348 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1349 ret
= ceph_fremovexattr(handle
->data
, fsp
->fh
->fd
, name
);
1351 ret
= ceph_removexattr(handle
->data
, fsp
->fsp_name
->base_name
, name
);
1353 DBG_DEBUG("[CEPH] fremovexattr(...) = %d\n", ret
);
1357 static int cephwrap_setxattr(struct vfs_handle_struct
*handle
,
1358 const struct smb_filename
*smb_fname
,
1365 DBG_DEBUG("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle
,
1366 smb_fname
->base_name
, name
, value
, llu(size
), flags
);
1367 ret
= ceph_setxattr(handle
->data
, smb_fname
->base_name
,
1368 name
, value
, size
, flags
);
1369 DBG_DEBUG("[CEPH] setxattr(...) = %d\n", ret
);
1373 static int cephwrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
1376 DBG_DEBUG("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle
, fsp
, name
, value
, llu(size
), flags
);
1377 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1378 ret
= ceph_fsetxattr(handle
->data
, fsp
->fh
->fd
,
1379 name
, value
, size
, flags
);
1381 ret
= ceph_setxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
1383 DBG_DEBUG("[CEPH] fsetxattr(...) = %d\n", ret
);
1387 static bool cephwrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
1391 * We do not support AIO yet.
1394 DBG_DEBUG("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle
, fsp
);
1399 static struct vfs_fn_pointers ceph_fns
= {
1400 /* Disk operations */
1402 .connect_fn
= cephwrap_connect
,
1403 .disconnect_fn
= cephwrap_disconnect
,
1404 .disk_free_fn
= cephwrap_disk_free
,
1405 .get_quota_fn
= cephwrap_get_quota
,
1406 .set_quota_fn
= cephwrap_set_quota
,
1407 .statvfs_fn
= cephwrap_statvfs
,
1408 .fs_capabilities_fn
= cephwrap_fs_capabilities
,
1410 /* Directory operations */
1412 .opendir_fn
= cephwrap_opendir
,
1413 .fdopendir_fn
= cephwrap_fdopendir
,
1414 .readdir_fn
= cephwrap_readdir
,
1415 .seekdir_fn
= cephwrap_seekdir
,
1416 .telldir_fn
= cephwrap_telldir
,
1417 .rewind_dir_fn
= cephwrap_rewinddir
,
1418 .mkdir_fn
= cephwrap_mkdir
,
1419 .rmdir_fn
= cephwrap_rmdir
,
1420 .closedir_fn
= cephwrap_closedir
,
1422 /* File operations */
1424 .open_fn
= cephwrap_open
,
1425 .close_fn
= cephwrap_close
,
1426 .pread_fn
= cephwrap_pread
,
1427 .pread_send_fn
= cephwrap_pread_send
,
1428 .pread_recv_fn
= cephwrap_pread_recv
,
1429 .pwrite_fn
= cephwrap_pwrite
,
1430 .pwrite_send_fn
= cephwrap_pwrite_send
,
1431 .pwrite_recv_fn
= cephwrap_pwrite_recv
,
1432 .lseek_fn
= cephwrap_lseek
,
1433 .sendfile_fn
= cephwrap_sendfile
,
1434 .recvfile_fn
= cephwrap_recvfile
,
1435 .rename_fn
= cephwrap_rename
,
1436 .fsync_send_fn
= cephwrap_fsync_send
,
1437 .fsync_recv_fn
= cephwrap_fsync_recv
,
1438 .stat_fn
= cephwrap_stat
,
1439 .fstat_fn
= cephwrap_fstat
,
1440 .lstat_fn
= cephwrap_lstat
,
1441 .unlink_fn
= cephwrap_unlink
,
1442 .chmod_fn
= cephwrap_chmod
,
1443 .fchmod_fn
= cephwrap_fchmod
,
1444 .chown_fn
= cephwrap_chown
,
1445 .fchown_fn
= cephwrap_fchown
,
1446 .lchown_fn
= cephwrap_lchown
,
1447 .chdir_fn
= cephwrap_chdir
,
1448 .getwd_fn
= cephwrap_getwd
,
1449 .ntimes_fn
= cephwrap_ntimes
,
1450 .ftruncate_fn
= cephwrap_ftruncate
,
1451 .fallocate_fn
= cephwrap_fallocate
,
1452 .lock_fn
= cephwrap_lock
,
1453 .kernel_flock_fn
= cephwrap_kernel_flock
,
1454 .linux_setlease_fn
= cephwrap_linux_setlease
,
1455 .getlock_fn
= cephwrap_getlock
,
1456 .symlink_fn
= cephwrap_symlink
,
1457 .readlink_fn
= cephwrap_readlink
,
1458 .link_fn
= cephwrap_link
,
1459 .mknod_fn
= cephwrap_mknod
,
1460 .realpath_fn
= cephwrap_realpath
,
1461 .chflags_fn
= cephwrap_chflags
,
1462 .get_real_filename_fn
= cephwrap_get_real_filename
,
1463 .connectpath_fn
= cephwrap_connectpath
,
1465 /* EA operations. */
1466 .getxattr_fn
= cephwrap_getxattr
,
1467 .getxattrat_send_fn
= vfs_not_implemented_getxattrat_send
,
1468 .getxattrat_recv_fn
= vfs_not_implemented_getxattrat_recv
,
1469 .fgetxattr_fn
= cephwrap_fgetxattr
,
1470 .listxattr_fn
= cephwrap_listxattr
,
1471 .flistxattr_fn
= cephwrap_flistxattr
,
1472 .removexattr_fn
= cephwrap_removexattr
,
1473 .fremovexattr_fn
= cephwrap_fremovexattr
,
1474 .setxattr_fn
= cephwrap_setxattr
,
1475 .fsetxattr_fn
= cephwrap_fsetxattr
,
1477 /* Posix ACL Operations */
1478 .sys_acl_get_file_fn
= posixacl_xattr_acl_get_file
,
1479 .sys_acl_get_fd_fn
= posixacl_xattr_acl_get_fd
,
1480 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
1481 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
1482 .sys_acl_set_file_fn
= posixacl_xattr_acl_set_file
,
1483 .sys_acl_set_fd_fn
= posixacl_xattr_acl_set_fd
,
1484 .sys_acl_delete_def_file_fn
= posixacl_xattr_acl_delete_def_file
,
1486 /* aio operations */
1487 .aio_force_fn
= cephwrap_aio_force
,
1491 NTSTATUS
vfs_ceph_init(TALLOC_CTX
*ctx
)
1493 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,