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 DBG_DEBUG("[CEPH] calling: ceph_mount\n");
123 ret
= ceph_mount(cmount
, NULL
);
129 * encode mount context/state into our vfs/connection holding structure
130 * cmount is a ceph_mount_t*
132 handle
->data
= cmount
;
136 * Unless we have an async implementation of getxattrat turn this off.
138 lp_do_parameter(SNUM(handle
->conn
), "smbd:async dosmode", "false");
143 ceph_release(cmount
);
147 * Handle the error correctly. Ceph returns -errno.
149 DBG_DEBUG("[CEPH] Error return: %s\n", strerror(-ret
));
153 static void cephwrap_disconnect(struct vfs_handle_struct
*handle
)
158 DBG_ERR("[CEPH] Error, ceph not mounted\n");
162 /* Should we unmount/shutdown? Only if the last disconnect? */
164 DBG_DEBUG("[CEPH] Not shuting down CEPH because still more connections\n");
168 ret
= ceph_unmount(cmount
);
170 DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret
));
173 ret
= ceph_release(cmount
);
175 DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret
));
178 cmount
= NULL
; /* Make it safe */
181 /* Disk operations */
183 static uint64_t cephwrap_disk_free(struct vfs_handle_struct
*handle
,
184 const struct smb_filename
*smb_fname
,
189 struct statvfs statvfs_buf
;
192 if (!(ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
,
195 * Provide all the correct values.
197 *bsize
= statvfs_buf
.f_bsize
;
198 *dfree
= statvfs_buf
.f_bavail
;
199 *dsize
= statvfs_buf
.f_blocks
;
200 DBG_DEBUG("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
201 llu(*bsize
), llu(*dfree
), llu(*dsize
));
204 DBG_DEBUG("[CEPH] ceph_statfs returned %d\n", ret
);
209 static int cephwrap_get_quota(struct vfs_handle_struct
*handle
,
210 const struct smb_filename
*smb_fname
,
211 enum SMB_QUOTA_TYPE qtype
,
215 /* libceph: Ceph does not implement this */
217 /* was ifdef HAVE_SYS_QUOTAS */
220 ret
= ceph_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
234 static int cephwrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
236 /* libceph: Ceph does not implement this */
238 /* was ifdef HAVE_SYS_QUOTAS */
241 ret
= ceph_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
249 WRAP_RETURN(-ENOSYS
);
253 static int cephwrap_statvfs(struct vfs_handle_struct
*handle
,
254 const struct smb_filename
*smb_fname
,
255 vfs_statvfs_struct
*statbuf
)
257 struct statvfs statvfs_buf
;
260 ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
, &statvfs_buf
);
264 statbuf
->OptimalTransferSize
= statvfs_buf
.f_frsize
;
265 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
266 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
267 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
268 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
269 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
270 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
271 statbuf
->FsIdentifier
= statvfs_buf
.f_fsid
;
272 DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
273 (long int)statvfs_buf
.f_bsize
, (long int)statvfs_buf
.f_blocks
,
274 (long int)statvfs_buf
.f_bfree
, (long int)statvfs_buf
.f_bavail
);
279 static uint32_t cephwrap_fs_capabilities(struct vfs_handle_struct
*handle
,
280 enum timestamp_set_resolution
*p_ts_res
)
282 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
284 #ifdef HAVE_CEPH_STATX
285 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
287 *p_ts_res
= TIMESTAMP_SET_MSEC
;
293 /* Directory operations */
295 static DIR *cephwrap_opendir(struct vfs_handle_struct
*handle
,
296 const struct smb_filename
*smb_fname
,
297 const char *mask
, uint32_t attr
)
300 struct ceph_dir_result
*result
;
301 DBG_DEBUG("[CEPH] opendir(%p, %s)\n", handle
, smb_fname
->base_name
);
303 /* Returns NULL if it does not exist or there are problems ? */
304 ret
= ceph_opendir(handle
->data
, smb_fname
->base_name
, &result
);
307 errno
= -ret
; /* We return result which is NULL in this case */
310 DBG_DEBUG("[CEPH] opendir(...) = %d\n", ret
);
311 return (DIR *) result
;
314 static DIR *cephwrap_fdopendir(struct vfs_handle_struct
*handle
,
315 struct files_struct
*fsp
,
320 struct ceph_dir_result
*result
;
321 DBG_DEBUG("[CEPH] fdopendir(%p, %p)\n", handle
, fsp
);
323 ret
= ceph_opendir(handle
->data
, fsp
->fsp_name
->base_name
, &result
);
326 errno
= -ret
; /* We return result which is NULL in this case */
329 DBG_DEBUG("[CEPH] fdopendir(...) = %d\n", ret
);
330 return (DIR *) result
;
333 static struct dirent
*cephwrap_readdir(struct vfs_handle_struct
*handle
,
335 SMB_STRUCT_STAT
*sbuf
)
337 struct dirent
*result
;
339 DBG_DEBUG("[CEPH] readdir(%p, %p)\n", handle
, dirp
);
340 result
= ceph_readdir(handle
->data
, (struct ceph_dir_result
*) dirp
);
341 DBG_DEBUG("[CEPH] readdir(...) = %p\n", result
);
343 /* Default Posix readdir() does not give us stat info.
344 * Set to invalid to indicate we didn't return this info. */
346 SET_STAT_INVALID(*sbuf
);
350 static void cephwrap_seekdir(struct vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
352 DBG_DEBUG("[CEPH] seekdir(%p, %p, %ld)\n", handle
, dirp
, offset
);
353 ceph_seekdir(handle
->data
, (struct ceph_dir_result
*) dirp
, offset
);
356 static long cephwrap_telldir(struct vfs_handle_struct
*handle
, DIR *dirp
)
359 DBG_DEBUG("[CEPH] telldir(%p, %p)\n", handle
, dirp
);
360 ret
= ceph_telldir(handle
->data
, (struct ceph_dir_result
*) dirp
);
361 DBG_DEBUG("[CEPH] telldir(...) = %ld\n", ret
);
365 static void cephwrap_rewinddir(struct vfs_handle_struct
*handle
, DIR *dirp
)
367 DBG_DEBUG("[CEPH] rewinddir(%p, %p)\n", handle
, dirp
);
368 ceph_rewinddir(handle
->data
, (struct ceph_dir_result
*) dirp
);
371 static int cephwrap_mkdir(struct vfs_handle_struct
*handle
,
372 const struct smb_filename
*smb_fname
,
377 const char *path
= smb_fname
->base_name
;
379 DBG_DEBUG("[CEPH] mkdir(%p, %s)\n", handle
, path
);
381 if (lp_inherit_acls(SNUM(handle
->conn
))
382 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
383 && directory_has_default_acl(handle
->conn
, parent
)) {
389 result
= ceph_mkdir(handle
->data
, path
, mode
);
390 return WRAP_RETURN(result
);
393 static int cephwrap_rmdir(struct vfs_handle_struct
*handle
,
394 const struct smb_filename
*smb_fname
)
398 DBG_DEBUG("[CEPH] rmdir(%p, %s)\n", handle
, smb_fname
->base_name
);
399 result
= ceph_rmdir(handle
->data
, smb_fname
->base_name
);
400 DBG_DEBUG("[CEPH] rmdir(...) = %d\n", result
);
404 static int cephwrap_closedir(struct vfs_handle_struct
*handle
, DIR *dirp
)
408 DBG_DEBUG("[CEPH] closedir(%p, %p)\n", handle
, dirp
);
409 result
= ceph_closedir(handle
->data
, (struct ceph_dir_result
*) dirp
);
410 DBG_DEBUG("[CEPH] closedir(...) = %d\n", result
);
414 /* File operations */
416 static int cephwrap_open(struct vfs_handle_struct
*handle
,
417 struct smb_filename
*smb_fname
,
418 files_struct
*fsp
, int flags
, mode_t mode
)
420 int result
= -ENOENT
;
421 DBG_DEBUG("[CEPH] open(%p, %s, %p, %d, %d)\n", handle
,
422 smb_fname_str_dbg(smb_fname
), fsp
, flags
, mode
);
424 if (smb_fname
->stream_name
) {
428 result
= ceph_open(handle
->data
, smb_fname
->base_name
, flags
, mode
);
430 DBG_DEBUG("[CEPH] open(...) = %d\n", result
);
434 static int cephwrap_close(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
438 DBG_DEBUG("[CEPH] close(%p, %p)\n", handle
, fsp
);
439 result
= ceph_close(handle
->data
, fsp
->fh
->fd
);
440 DBG_DEBUG("[CEPH] close(...) = %d\n", result
);
445 static ssize_t
cephwrap_pread(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
446 size_t n
, off_t offset
)
450 DBG_DEBUG("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
452 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
453 DBG_DEBUG("[CEPH] pread(...) = %llu\n", llu(result
));
457 struct cephwrap_pread_state
{
459 struct vfs_aio_state vfs_aio_state
;
463 * Fake up an async ceph read by calling the synchronous API.
465 static struct tevent_req
*cephwrap_pread_send(struct vfs_handle_struct
*handle
,
467 struct tevent_context
*ev
,
468 struct files_struct
*fsp
,
470 size_t n
, off_t offset
)
472 struct tevent_req
*req
= NULL
;
473 struct cephwrap_pread_state
*state
= NULL
;
476 DBG_DEBUG("[CEPH] %s\n", __func__
);
477 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pread_state
);
482 ret
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
484 /* ceph returns -errno on error. */
485 tevent_req_error(req
, -ret
);
486 return tevent_req_post(req
, ev
);
489 state
->bytes_read
= ret
;
490 tevent_req_done(req
);
491 /* Return and schedule the completion of the call. */
492 return tevent_req_post(req
, ev
);
495 static ssize_t
cephwrap_pread_recv(struct tevent_req
*req
,
496 struct vfs_aio_state
*vfs_aio_state
)
498 struct cephwrap_pread_state
*state
=
499 tevent_req_data(req
, struct cephwrap_pread_state
);
501 DBG_DEBUG("[CEPH] %s\n", __func__
);
502 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
505 *vfs_aio_state
= state
->vfs_aio_state
;
506 return state
->bytes_read
;
509 static ssize_t
cephwrap_pwrite(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
510 size_t n
, off_t offset
)
514 DBG_DEBUG("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
515 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
516 DBG_DEBUG("[CEPH] pwrite(...) = %llu\n", llu(result
));
520 struct cephwrap_pwrite_state
{
521 ssize_t bytes_written
;
522 struct vfs_aio_state vfs_aio_state
;
526 * Fake up an async ceph write by calling the synchronous API.
528 static struct tevent_req
*cephwrap_pwrite_send(struct vfs_handle_struct
*handle
,
530 struct tevent_context
*ev
,
531 struct files_struct
*fsp
,
533 size_t n
, off_t offset
)
535 struct tevent_req
*req
= NULL
;
536 struct cephwrap_pwrite_state
*state
= NULL
;
539 DBG_DEBUG("[CEPH] %s\n", __func__
);
540 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pwrite_state
);
545 ret
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
547 /* ceph returns -errno on error. */
548 tevent_req_error(req
, -ret
);
549 return tevent_req_post(req
, ev
);
552 state
->bytes_written
= ret
;
553 tevent_req_done(req
);
554 /* Return and schedule the completion of the call. */
555 return tevent_req_post(req
, ev
);
558 static ssize_t
cephwrap_pwrite_recv(struct tevent_req
*req
,
559 struct vfs_aio_state
*vfs_aio_state
)
561 struct cephwrap_pwrite_state
*state
=
562 tevent_req_data(req
, struct cephwrap_pwrite_state
);
564 DBG_DEBUG("[CEPH] %s\n", __func__
);
565 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
568 *vfs_aio_state
= state
->vfs_aio_state
;
569 return state
->bytes_written
;
572 static off_t
cephwrap_lseek(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
576 DBG_DEBUG("[CEPH] cephwrap_lseek\n");
577 /* Cope with 'stat' file opens. */
578 if (fsp
->fh
->fd
!= -1) {
579 result
= ceph_lseek(handle
->data
, fsp
->fh
->fd
, offset
, whence
);
584 static ssize_t
cephwrap_sendfile(struct vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
585 off_t offset
, size_t n
)
588 * We cannot support sendfile because libceph is in user space.
590 DBG_DEBUG("[CEPH] cephwrap_sendfile\n");
595 static ssize_t
cephwrap_recvfile(struct vfs_handle_struct
*handle
,
602 * We cannot support recvfile because libceph is in user space.
604 DBG_DEBUG("[CEPH] cephwrap_recvfile\n");
609 static int cephwrap_rename(struct vfs_handle_struct
*handle
,
610 const struct smb_filename
*smb_fname_src
,
611 const struct smb_filename
*smb_fname_dst
)
614 DBG_DEBUG("[CEPH] cephwrap_rename\n");
615 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
620 result
= ceph_rename(handle
->data
, smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
625 * Fake up an async ceph fsync by calling the synchronous API.
628 static struct tevent_req
*cephwrap_fsync_send(struct vfs_handle_struct
*handle
,
630 struct tevent_context
*ev
,
633 struct tevent_req
*req
= NULL
;
634 struct vfs_aio_state
*state
= NULL
;
637 DBG_DEBUG("[CEPH] cephwrap_fsync_send\n");
639 req
= tevent_req_create(mem_ctx
, &state
, struct vfs_aio_state
);
644 /* Make sync call. */
645 ret
= ceph_fsync(handle
->data
, fsp
->fh
->fd
, false);
648 /* ceph_fsync returns -errno on error. */
649 tevent_req_error(req
, -ret
);
650 return tevent_req_post(req
, ev
);
653 /* Mark it as done. */
654 tevent_req_done(req
);
655 /* Return and schedule the completion of the call. */
656 return tevent_req_post(req
, ev
);
659 static int cephwrap_fsync_recv(struct tevent_req
*req
,
660 struct vfs_aio_state
*vfs_aio_state
)
662 struct vfs_aio_state
*state
=
663 tevent_req_data(req
, struct vfs_aio_state
);
665 DBG_DEBUG("[CEPH] cephwrap_fsync_recv\n");
667 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
670 *vfs_aio_state
= *state
;
674 #ifdef HAVE_CEPH_STATX
675 #define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
677 static void init_stat_ex_from_ceph_statx(struct stat_ex
*dst
, const struct ceph_statx
*stx
)
679 if ((stx
->stx_mask
& SAMBA_STATX_ATTR_MASK
) != SAMBA_STATX_ATTR_MASK
)
680 DBG_WARNING("%s: stx->stx_mask is incorrect (wanted %x, got %x)",
681 __func__
, SAMBA_STATX_ATTR_MASK
, stx
->stx_mask
);
683 dst
->st_ex_dev
= stx
->stx_dev
;
684 dst
->st_ex_rdev
= stx
->stx_rdev
;
685 dst
->st_ex_ino
= stx
->stx_ino
;
686 dst
->st_ex_mode
= stx
->stx_mode
;
687 dst
->st_ex_uid
= stx
->stx_uid
;
688 dst
->st_ex_gid
= stx
->stx_gid
;
689 dst
->st_ex_size
= stx
->stx_size
;
690 dst
->st_ex_nlink
= stx
->stx_nlink
;
691 dst
->st_ex_atime
= stx
->stx_atime
;
692 dst
->st_ex_btime
= stx
->stx_btime
;
693 dst
->st_ex_ctime
= stx
->stx_ctime
;
694 dst
->st_ex_mtime
= stx
->stx_mtime
;
695 dst
->st_ex_calculated_birthtime
= false;
696 dst
->st_ex_blksize
= stx
->stx_blksize
;
697 dst
->st_ex_blocks
= stx
->stx_blocks
;
700 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
701 struct smb_filename
*smb_fname
)
704 struct ceph_statx stx
;
706 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
708 if (smb_fname
->stream_name
) {
713 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
714 SAMBA_STATX_ATTR_MASK
, 0);
715 DBG_DEBUG("[CEPH] statx(...) = %d\n", result
);
719 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
720 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
721 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
722 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
723 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
724 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
725 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
726 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
728 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
729 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
733 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
736 struct ceph_statx stx
;
738 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
739 result
= ceph_fstatx(handle
->data
, fsp
->fh
->fd
, &stx
,
740 SAMBA_STATX_ATTR_MASK
, 0);
741 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
745 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
746 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
747 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
748 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
749 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
750 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
751 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
752 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
754 init_stat_ex_from_ceph_statx(sbuf
, &stx
);
755 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
759 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
760 struct smb_filename
*smb_fname
)
763 struct ceph_statx stx
;
765 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
767 if (smb_fname
->stream_name
) {
772 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
773 SAMBA_STATX_ATTR_MASK
, AT_SYMLINK_NOFOLLOW
);
774 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
778 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
782 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
783 const struct smb_filename
*smb_fname
,
784 struct smb_file_time
*ft
)
786 struct ceph_statx stx
= { 0 };
790 if (!null_timespec(ft
->atime
)) {
791 stx
.stx_atime
= ft
->atime
;
792 mask
|= CEPH_SETATTR_ATIME
;
794 if (!null_timespec(ft
->mtime
)) {
795 stx
.stx_mtime
= ft
->mtime
;
796 mask
|= CEPH_SETATTR_MTIME
;
798 if (!null_timespec(ft
->create_time
)) {
799 stx
.stx_btime
= ft
->create_time
;
800 mask
|= CEPH_SETATTR_BTIME
;
807 result
= ceph_setattrx(handle
->data
, smb_fname
->base_name
, &stx
, mask
, 0);
808 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
809 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
810 ft
->create_time
.tv_sec
, result
);
814 #else /* HAVE_CEPH_STATX */
816 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
817 struct smb_filename
*smb_fname
)
822 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
824 if (smb_fname
->stream_name
) {
829 result
= ceph_stat(handle
->data
, smb_fname
->base_name
, (struct stat
*) &stbuf
);
830 DBG_DEBUG("[CEPH] stat(...) = %d\n", result
);
834 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
835 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
836 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
837 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
838 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
839 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
841 init_stat_ex_from_stat(
842 &smb_fname
->st
, &stbuf
,
843 lp_fake_directory_create_times(SNUM(handle
->conn
)));
844 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
848 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
853 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
854 result
= ceph_fstat(handle
->data
, fsp
->fh
->fd
, (struct stat
*) &stbuf
);
855 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
859 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
860 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
861 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
862 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
863 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
864 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
867 init_stat_ex_from_stat(
869 lp_fake_directory_create_times(SNUM(handle
->conn
)));
870 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
874 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
875 struct smb_filename
*smb_fname
)
880 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
882 if (smb_fname
->stream_name
) {
887 result
= ceph_lstat(handle
->data
, smb_fname
->base_name
, &stbuf
);
888 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
892 init_stat_ex_from_stat(
893 &smb_fname
->st
, &stbuf
,
894 lp_fake_directory_create_times(SNUM(handle
->conn
)));
898 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
899 const struct smb_filename
*smb_fname
,
900 struct smb_file_time
*ft
)
905 if (null_timespec(ft
->atime
)) {
906 buf
.actime
= smb_fname
->st
.st_ex_atime
.tv_sec
;
908 buf
.actime
= ft
->atime
.tv_sec
;
910 if (null_timespec(ft
->mtime
)) {
911 buf
.modtime
= smb_fname
->st
.st_ex_mtime
.tv_sec
;
913 buf
.modtime
= ft
->mtime
.tv_sec
;
915 if (!null_timespec(ft
->create_time
)) {
916 set_create_timespec_ea(handle
->conn
, smb_fname
,
919 if (buf
.actime
== smb_fname
->st
.st_ex_atime
.tv_sec
&&
920 buf
.modtime
== smb_fname
->st
.st_ex_mtime
.tv_sec
) {
924 result
= ceph_utime(handle
->data
, smb_fname
->base_name
, &buf
);
925 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
926 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
927 ft
->create_time
.tv_sec
, result
);
930 #endif /* HAVE_CEPH_STATX */
932 static int cephwrap_unlink(struct vfs_handle_struct
*handle
,
933 const struct smb_filename
*smb_fname
)
937 DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
938 if (smb_fname
->stream_name
) {
942 result
= ceph_unlink(handle
->data
, smb_fname
->base_name
);
943 DBG_DEBUG("[CEPH] unlink(...) = %d\n", result
);
947 static int cephwrap_chmod(struct vfs_handle_struct
*handle
,
948 const struct smb_filename
*smb_fname
,
953 DBG_DEBUG("[CEPH] chmod(%p, %s, %d)\n", handle
, smb_fname
->base_name
, mode
);
954 result
= ceph_chmod(handle
->data
, smb_fname
->base_name
, mode
);
955 DBG_DEBUG("[CEPH] chmod(...) = %d\n", result
);
959 static int cephwrap_fchmod(struct vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
963 DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle
, fsp
, mode
);
965 #if defined(HAVE_FCHMOD)
966 result
= ceph_fchmod(handle
->data
, fsp
->fh
->fd
, mode
);
967 DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result
);
975 static int cephwrap_chown(struct vfs_handle_struct
*handle
,
976 const struct smb_filename
*smb_fname
,
981 DBG_DEBUG("[CEPH] chown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
982 result
= ceph_chown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
983 DBG_DEBUG("[CEPH] chown(...) = %d\n", result
);
987 static int cephwrap_fchown(struct vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
992 DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle
, fsp
, uid
, gid
);
993 result
= ceph_fchown(handle
->data
, fsp
->fh
->fd
, uid
, gid
);
994 DBG_DEBUG("[CEPH] fchown(...) = %d\n", result
);
1003 static int cephwrap_lchown(struct vfs_handle_struct
*handle
,
1004 const struct smb_filename
*smb_fname
,
1009 DBG_DEBUG("[CEPH] lchown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
1010 result
= ceph_lchown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
1011 DBG_DEBUG("[CEPH] lchown(...) = %d\n", result
);
1012 WRAP_RETURN(result
);
1015 static int cephwrap_chdir(struct vfs_handle_struct
*handle
,
1016 const struct smb_filename
*smb_fname
)
1019 DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle
, smb_fname
->base_name
);
1020 result
= ceph_chdir(handle
->data
, smb_fname
->base_name
);
1021 DBG_DEBUG("[CEPH] chdir(...) = %d\n", result
);
1022 WRAP_RETURN(result
);
1025 static struct smb_filename
*cephwrap_getwd(struct vfs_handle_struct
*handle
,
1028 const char *cwd
= ceph_getcwd(handle
->data
);
1029 DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle
, cwd
);
1030 return synthetic_smb_fname(ctx
,
1037 static int strict_allocate_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1039 off_t space_to_write
;
1040 uint64_t space_avail
;
1041 uint64_t bsize
,dfree
,dsize
;
1044 SMB_STRUCT_STAT
*pst
;
1046 status
= vfs_stat_fsp(fsp
);
1047 if (!NT_STATUS_IS_OK(status
)) {
1050 pst
= &fsp
->fsp_name
->st
;
1053 if (S_ISFIFO(pst
->st_ex_mode
))
1057 if (pst
->st_ex_size
== len
)
1060 /* Shrink - just ftruncate. */
1061 if (pst
->st_ex_size
> len
)
1062 return ftruncate(fsp
->fh
->fd
, len
);
1064 space_to_write
= len
- pst
->st_ex_size
;
1066 /* for allocation try fallocate first. This can fail on some
1067 platforms e.g. when the filesystem doesn't support it and no
1068 emulation is being done by the libc (like on AIX with JFS1). In that
1069 case we do our own emulation. fallocate implementations can
1070 return ENOTSUP or EINVAL in cases like that. */
1071 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
1072 if (ret
== -1 && errno
== ENOSPC
) {
1078 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1079 "error %d. Falling back to slow manual allocation\n", errno
));
1081 /* available disk space is enough or not? */
1083 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
1084 /* space_avail is 1k blocks */
1085 if (space_avail
== (uint64_t)-1 ||
1086 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1091 /* Write out the real space on disk. */
1092 return vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1095 static int cephwrap_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1102 DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle
, fsp
, llu(len
));
1104 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
1105 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1109 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1110 sys_ftruncate if the system supports it. Then I discovered that
1111 you can have some filesystems that support ftruncate
1112 expansion and some that don't! On Linux fat can't do
1113 ftruncate extend but ext2 can. */
1115 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1119 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1120 extend a file with ftruncate. Provide alternate implementation
1122 currpos
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
1123 if (currpos
== -1) {
1127 /* Do an fstat to see if the file is longer than the requested
1128 size in which case the ftruncate above should have
1129 succeeded or shorter, in which case seek to len - 1 and
1130 write 1 byte of zero */
1131 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1136 if (S_ISFIFO(st
.st_ex_mode
)) {
1142 if (st
.st_ex_size
== len
) {
1147 if (st
.st_ex_size
> len
) {
1148 /* the sys_ftruncate should have worked */
1152 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
1163 static bool cephwrap_lock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1165 DBG_DEBUG("[CEPH] lock\n");
1169 static int cephwrap_kernel_flock(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1170 uint32_t share_mode
, uint32_t access_mask
)
1172 DBG_ERR("[CEPH] flock unsupported! Consider setting "
1173 "\"kernel share modes = no\"\n");
1179 static bool cephwrap_getlock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1181 DBG_DEBUG("[CEPH] getlock returning false and errno=0\n");
1188 * We cannot let this fall through to the default, because the file might only
1189 * be accessible from libceph (which is a user-space client) but the fd might
1190 * be for some file the kernel knows about.
1192 static int cephwrap_linux_setlease(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1197 DBG_DEBUG("[CEPH] linux_setlease\n");
1202 static int cephwrap_symlink(struct vfs_handle_struct
*handle
,
1203 const char *link_target
,
1204 const struct smb_filename
*new_smb_fname
)
1207 DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle
,
1209 new_smb_fname
->base_name
);
1210 result
= ceph_symlink(handle
->data
,
1212 new_smb_fname
->base_name
);
1213 DBG_DEBUG("[CEPH] symlink(...) = %d\n", result
);
1214 WRAP_RETURN(result
);
1217 static int cephwrap_readlink(struct vfs_handle_struct
*handle
,
1218 const struct smb_filename
*smb_fname
,
1223 DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle
,
1224 smb_fname
->base_name
, buf
, llu(bufsiz
));
1225 result
= ceph_readlink(handle
->data
, smb_fname
->base_name
, buf
, bufsiz
);
1226 DBG_DEBUG("[CEPH] readlink(...) = %d\n", result
);
1227 WRAP_RETURN(result
);
1230 static int cephwrap_link(struct vfs_handle_struct
*handle
,
1231 const struct smb_filename
*old_smb_fname
,
1232 const struct smb_filename
*new_smb_fname
)
1235 DBG_DEBUG("[CEPH] link(%p, %s, %s)\n", handle
,
1236 old_smb_fname
->base_name
,
1237 new_smb_fname
->base_name
);
1238 result
= ceph_link(handle
->data
,
1239 old_smb_fname
->base_name
,
1240 new_smb_fname
->base_name
);
1241 DBG_DEBUG("[CEPH] link(...) = %d\n", result
);
1242 WRAP_RETURN(result
);
1245 static int cephwrap_mknod(struct vfs_handle_struct
*handle
,
1246 const struct smb_filename
*smb_fname
,
1251 DBG_DEBUG("[CEPH] mknod(%p, %s)\n", handle
, smb_fname
->base_name
);
1252 result
= ceph_mknod(handle
->data
, smb_fname
->base_name
, mode
, dev
);
1253 DBG_DEBUG("[CEPH] mknod(...) = %d\n", result
);
1254 WRAP_RETURN(result
);
1258 * This is a simple version of real-path ... a better version is needed to
1259 * ask libceph about symbolic links.
1261 static struct smb_filename
*cephwrap_realpath(struct vfs_handle_struct
*handle
,
1263 const struct smb_filename
*smb_fname
)
1265 char *result
= NULL
;
1266 const char *path
= smb_fname
->base_name
;
1267 size_t len
= strlen(path
);
1268 struct smb_filename
*result_fname
= NULL
;
1271 if (len
&& (path
[0] == '/')) {
1272 r
= asprintf(&result
, "%s", path
);
1273 } else if ((len
>= 2) && (path
[0] == '.') && (path
[1] == '/')) {
1275 r
= asprintf(&result
, "%s",
1276 handle
->conn
->connectpath
);
1278 r
= asprintf(&result
, "%s/%s",
1279 handle
->conn
->connectpath
, &path
[2]);
1282 r
= asprintf(&result
, "%s/%s",
1283 handle
->conn
->connectpath
, path
);
1290 DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle
, path
, result
);
1291 result_fname
= synthetic_smb_fname(ctx
,
1297 return result_fname
;
1300 static int cephwrap_chflags(struct vfs_handle_struct
*handle
,
1301 const struct smb_filename
*smb_fname
,
1308 static int cephwrap_get_real_filename(struct vfs_handle_struct
*handle
,
1311 TALLOC_CTX
*mem_ctx
,
1315 * Don't fall back to get_real_filename so callers can differentiate
1316 * between a full directory scan and an actual case-insensitive stat.
1322 static const char *cephwrap_connectpath(struct vfs_handle_struct
*handle
,
1323 const struct smb_filename
*smb_fname
)
1325 return handle
->conn
->connectpath
;
1328 /****************************************************************
1329 Extended attribute operations.
1330 *****************************************************************/
1332 static ssize_t
cephwrap_getxattr(struct vfs_handle_struct
*handle
,
1333 const struct smb_filename
*smb_fname
,
1339 DBG_DEBUG("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle
,
1340 smb_fname
->base_name
, name
, value
, llu(size
));
1341 ret
= ceph_getxattr(handle
->data
,
1342 smb_fname
->base_name
, name
, value
, size
);
1343 DBG_DEBUG("[CEPH] getxattr(...) = %d\n", ret
);
1347 return (ssize_t
)ret
;
1351 static ssize_t
cephwrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
1354 DBG_DEBUG("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle
, fsp
, name
, value
, llu(size
));
1355 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1356 ret
= ceph_fgetxattr(handle
->data
, fsp
->fh
->fd
, name
, value
, size
);
1358 ret
= ceph_getxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
);
1360 DBG_DEBUG("[CEPH] fgetxattr(...) = %d\n", ret
);
1364 return (ssize_t
)ret
;
1368 static ssize_t
cephwrap_listxattr(struct vfs_handle_struct
*handle
,
1369 const struct smb_filename
*smb_fname
,
1374 DBG_DEBUG("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle
,
1375 smb_fname
->base_name
, list
, llu(size
));
1376 ret
= ceph_listxattr(handle
->data
, smb_fname
->base_name
, list
, size
);
1377 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1381 return (ssize_t
)ret
;
1385 static ssize_t
cephwrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
1388 DBG_DEBUG("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle
, fsp
, list
, llu(size
));
1389 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1390 ret
= ceph_flistxattr(handle
->data
, fsp
->fh
->fd
, list
, size
);
1392 ret
= ceph_listxattr(handle
->data
, fsp
->fsp_name
->base_name
, list
, size
);
1394 DBG_DEBUG("[CEPH] flistxattr(...) = %d\n", ret
);
1398 return (ssize_t
)ret
;
1402 static int cephwrap_removexattr(struct vfs_handle_struct
*handle
,
1403 const struct smb_filename
*smb_fname
,
1407 DBG_DEBUG("[CEPH] removexattr(%p, %s, %s)\n", handle
,
1408 smb_fname
->base_name
, name
);
1409 ret
= ceph_removexattr(handle
->data
, smb_fname
->base_name
, name
);
1410 DBG_DEBUG("[CEPH] removexattr(...) = %d\n", ret
);
1414 static int cephwrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
1417 DBG_DEBUG("[CEPH] fremovexattr(%p, %p, %s)\n", handle
, fsp
, name
);
1418 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1419 ret
= ceph_fremovexattr(handle
->data
, fsp
->fh
->fd
, name
);
1421 ret
= ceph_removexattr(handle
->data
, fsp
->fsp_name
->base_name
, name
);
1423 DBG_DEBUG("[CEPH] fremovexattr(...) = %d\n", ret
);
1427 static int cephwrap_setxattr(struct vfs_handle_struct
*handle
,
1428 const struct smb_filename
*smb_fname
,
1435 DBG_DEBUG("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle
,
1436 smb_fname
->base_name
, name
, value
, llu(size
), flags
);
1437 ret
= ceph_setxattr(handle
->data
, smb_fname
->base_name
,
1438 name
, value
, size
, flags
);
1439 DBG_DEBUG("[CEPH] setxattr(...) = %d\n", ret
);
1443 static int cephwrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
1446 DBG_DEBUG("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle
, fsp
, name
, value
, llu(size
), flags
);
1447 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1448 ret
= ceph_fsetxattr(handle
->data
, fsp
->fh
->fd
,
1449 name
, value
, size
, flags
);
1451 ret
= ceph_setxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
1453 DBG_DEBUG("[CEPH] fsetxattr(...) = %d\n", ret
);
1457 static bool cephwrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
1461 * We do not support AIO yet.
1464 DBG_DEBUG("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle
, fsp
);
1469 static struct vfs_fn_pointers ceph_fns
= {
1470 /* Disk operations */
1472 .connect_fn
= cephwrap_connect
,
1473 .disconnect_fn
= cephwrap_disconnect
,
1474 .disk_free_fn
= cephwrap_disk_free
,
1475 .get_quota_fn
= cephwrap_get_quota
,
1476 .set_quota_fn
= cephwrap_set_quota
,
1477 .statvfs_fn
= cephwrap_statvfs
,
1478 .fs_capabilities_fn
= cephwrap_fs_capabilities
,
1480 /* Directory operations */
1482 .opendir_fn
= cephwrap_opendir
,
1483 .fdopendir_fn
= cephwrap_fdopendir
,
1484 .readdir_fn
= cephwrap_readdir
,
1485 .seekdir_fn
= cephwrap_seekdir
,
1486 .telldir_fn
= cephwrap_telldir
,
1487 .rewind_dir_fn
= cephwrap_rewinddir
,
1488 .mkdir_fn
= cephwrap_mkdir
,
1489 .rmdir_fn
= cephwrap_rmdir
,
1490 .closedir_fn
= cephwrap_closedir
,
1492 /* File operations */
1494 .open_fn
= cephwrap_open
,
1495 .close_fn
= cephwrap_close
,
1496 .pread_fn
= cephwrap_pread
,
1497 .pread_send_fn
= cephwrap_pread_send
,
1498 .pread_recv_fn
= cephwrap_pread_recv
,
1499 .pwrite_fn
= cephwrap_pwrite
,
1500 .pwrite_send_fn
= cephwrap_pwrite_send
,
1501 .pwrite_recv_fn
= cephwrap_pwrite_recv
,
1502 .lseek_fn
= cephwrap_lseek
,
1503 .sendfile_fn
= cephwrap_sendfile
,
1504 .recvfile_fn
= cephwrap_recvfile
,
1505 .rename_fn
= cephwrap_rename
,
1506 .fsync_send_fn
= cephwrap_fsync_send
,
1507 .fsync_recv_fn
= cephwrap_fsync_recv
,
1508 .stat_fn
= cephwrap_stat
,
1509 .fstat_fn
= cephwrap_fstat
,
1510 .lstat_fn
= cephwrap_lstat
,
1511 .unlink_fn
= cephwrap_unlink
,
1512 .chmod_fn
= cephwrap_chmod
,
1513 .fchmod_fn
= cephwrap_fchmod
,
1514 .chown_fn
= cephwrap_chown
,
1515 .fchown_fn
= cephwrap_fchown
,
1516 .lchown_fn
= cephwrap_lchown
,
1517 .chdir_fn
= cephwrap_chdir
,
1518 .getwd_fn
= cephwrap_getwd
,
1519 .ntimes_fn
= cephwrap_ntimes
,
1520 .ftruncate_fn
= cephwrap_ftruncate
,
1521 .lock_fn
= cephwrap_lock
,
1522 .kernel_flock_fn
= cephwrap_kernel_flock
,
1523 .linux_setlease_fn
= cephwrap_linux_setlease
,
1524 .getlock_fn
= cephwrap_getlock
,
1525 .symlink_fn
= cephwrap_symlink
,
1526 .readlink_fn
= cephwrap_readlink
,
1527 .link_fn
= cephwrap_link
,
1528 .mknod_fn
= cephwrap_mknod
,
1529 .realpath_fn
= cephwrap_realpath
,
1530 .chflags_fn
= cephwrap_chflags
,
1531 .get_real_filename_fn
= cephwrap_get_real_filename
,
1532 .connectpath_fn
= cephwrap_connectpath
,
1534 /* EA operations. */
1535 .getxattr_fn
= cephwrap_getxattr
,
1536 .getxattrat_send_fn
= vfs_not_implemented_getxattrat_send
,
1537 .getxattrat_recv_fn
= vfs_not_implemented_getxattrat_recv
,
1538 .fgetxattr_fn
= cephwrap_fgetxattr
,
1539 .listxattr_fn
= cephwrap_listxattr
,
1540 .flistxattr_fn
= cephwrap_flistxattr
,
1541 .removexattr_fn
= cephwrap_removexattr
,
1542 .fremovexattr_fn
= cephwrap_fremovexattr
,
1543 .setxattr_fn
= cephwrap_setxattr
,
1544 .fsetxattr_fn
= cephwrap_fsetxattr
,
1546 /* Posix ACL Operations */
1547 .sys_acl_get_file_fn
= posixacl_xattr_acl_get_file
,
1548 .sys_acl_get_fd_fn
= posixacl_xattr_acl_get_fd
,
1549 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
1550 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
1551 .sys_acl_set_file_fn
= posixacl_xattr_acl_set_file
,
1552 .sys_acl_set_fd_fn
= posixacl_xattr_acl_set_fd
,
1553 .sys_acl_delete_def_file_fn
= posixacl_xattr_acl_delete_def_file
,
1555 /* aio operations */
1556 .aio_force_fn
= cephwrap_aio_force
,
1560 NTSTATUS
vfs_ceph_init(TALLOC_CTX
*ctx
)
1562 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,