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
;
138 ceph_release(cmount
);
142 * Handle the error correctly. Ceph returns -errno.
144 DBG_DEBUG("[CEPH] Error return: %s\n", strerror(-ret
));
148 static void cephwrap_disconnect(struct vfs_handle_struct
*handle
)
153 DBG_ERR("[CEPH] Error, ceph not mounted\n");
157 /* Should we unmount/shutdown? Only if the last disconnect? */
159 DBG_DEBUG("[CEPH] Not shuting down CEPH because still more connections\n");
163 ret
= ceph_unmount(cmount
);
165 DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret
));
168 ret
= ceph_release(cmount
);
170 DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret
));
173 cmount
= NULL
; /* Make it safe */
176 /* Disk operations */
178 static uint64_t cephwrap_disk_free(struct vfs_handle_struct
*handle
,
179 const struct smb_filename
*smb_fname
,
184 struct statvfs statvfs_buf
;
187 if (!(ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
,
190 * Provide all the correct values.
192 *bsize
= statvfs_buf
.f_bsize
;
193 *dfree
= statvfs_buf
.f_bavail
;
194 *dsize
= statvfs_buf
.f_blocks
;
195 DBG_DEBUG("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
196 llu(*bsize
), llu(*dfree
), llu(*dsize
));
199 DBG_DEBUG("[CEPH] ceph_statfs returned %d\n", ret
);
204 static int cephwrap_get_quota(struct vfs_handle_struct
*handle
,
205 const struct smb_filename
*smb_fname
,
206 enum SMB_QUOTA_TYPE qtype
,
210 /* libceph: Ceph does not implement this */
212 /* was ifdef HAVE_SYS_QUOTAS */
215 ret
= ceph_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
229 static int cephwrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
231 /* libceph: Ceph does not implement this */
233 /* was ifdef HAVE_SYS_QUOTAS */
236 ret
= ceph_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
244 WRAP_RETURN(-ENOSYS
);
248 static int cephwrap_statvfs(struct vfs_handle_struct
*handle
,
249 const struct smb_filename
*smb_fname
,
250 vfs_statvfs_struct
*statbuf
)
252 struct statvfs statvfs_buf
;
255 ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
, &statvfs_buf
);
259 statbuf
->OptimalTransferSize
= statvfs_buf
.f_frsize
;
260 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
261 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
262 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
263 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
264 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
265 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
266 statbuf
->FsIdentifier
= statvfs_buf
.f_fsid
;
267 DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
268 (long int)statvfs_buf
.f_bsize
, (long int)statvfs_buf
.f_blocks
,
269 (long int)statvfs_buf
.f_bfree
, (long int)statvfs_buf
.f_bavail
);
274 static uint32_t cephwrap_fs_capabilities(struct vfs_handle_struct
*handle
,
275 enum timestamp_set_resolution
*p_ts_res
)
277 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
279 #ifdef HAVE_CEPH_STATX
280 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
282 *p_ts_res
= TIMESTAMP_SET_MSEC
;
288 /* Directory operations */
290 static DIR *cephwrap_opendir(struct vfs_handle_struct
*handle
,
291 const struct smb_filename
*smb_fname
,
292 const char *mask
, uint32_t attr
)
295 struct ceph_dir_result
*result
;
296 DBG_DEBUG("[CEPH] opendir(%p, %s)\n", handle
, smb_fname
->base_name
);
298 /* Returns NULL if it does not exist or there are problems ? */
299 ret
= ceph_opendir(handle
->data
, smb_fname
->base_name
, &result
);
302 errno
= -ret
; /* We return result which is NULL in this case */
305 DBG_DEBUG("[CEPH] opendir(...) = %d\n", ret
);
306 return (DIR *) result
;
309 static DIR *cephwrap_fdopendir(struct vfs_handle_struct
*handle
,
310 struct files_struct
*fsp
,
315 struct ceph_dir_result
*result
;
316 DBG_DEBUG("[CEPH] fdopendir(%p, %p)\n", handle
, fsp
);
318 ret
= ceph_opendir(handle
->data
, fsp
->fsp_name
->base_name
, &result
);
321 errno
= -ret
; /* We return result which is NULL in this case */
324 DBG_DEBUG("[CEPH] fdopendir(...) = %d\n", ret
);
325 return (DIR *) result
;
328 static struct dirent
*cephwrap_readdir(struct vfs_handle_struct
*handle
,
330 SMB_STRUCT_STAT
*sbuf
)
332 struct dirent
*result
;
334 DBG_DEBUG("[CEPH] readdir(%p, %p)\n", handle
, dirp
);
335 result
= ceph_readdir(handle
->data
, (struct ceph_dir_result
*) dirp
);
336 DBG_DEBUG("[CEPH] readdir(...) = %p\n", result
);
338 /* Default Posix readdir() does not give us stat info.
339 * Set to invalid to indicate we didn't return this info. */
341 SET_STAT_INVALID(*sbuf
);
345 static void cephwrap_seekdir(struct vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
347 DBG_DEBUG("[CEPH] seekdir(%p, %p, %ld)\n", handle
, dirp
, offset
);
348 ceph_seekdir(handle
->data
, (struct ceph_dir_result
*) dirp
, offset
);
351 static long cephwrap_telldir(struct vfs_handle_struct
*handle
, DIR *dirp
)
354 DBG_DEBUG("[CEPH] telldir(%p, %p)\n", handle
, dirp
);
355 ret
= ceph_telldir(handle
->data
, (struct ceph_dir_result
*) dirp
);
356 DBG_DEBUG("[CEPH] telldir(...) = %ld\n", ret
);
360 static void cephwrap_rewinddir(struct vfs_handle_struct
*handle
, DIR *dirp
)
362 DBG_DEBUG("[CEPH] rewinddir(%p, %p)\n", handle
, dirp
);
363 ceph_rewinddir(handle
->data
, (struct ceph_dir_result
*) dirp
);
366 static int cephwrap_mkdir(struct vfs_handle_struct
*handle
,
367 const struct smb_filename
*smb_fname
,
372 const char *path
= smb_fname
->base_name
;
374 DBG_DEBUG("[CEPH] mkdir(%p, %s)\n", handle
, path
);
376 if (lp_inherit_acls(SNUM(handle
->conn
))
377 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
378 && directory_has_default_acl(handle
->conn
, parent
)) {
384 result
= ceph_mkdir(handle
->data
, path
, mode
);
385 return WRAP_RETURN(result
);
388 static int cephwrap_rmdir(struct vfs_handle_struct
*handle
,
389 const struct smb_filename
*smb_fname
)
393 DBG_DEBUG("[CEPH] rmdir(%p, %s)\n", handle
, smb_fname
->base_name
);
394 result
= ceph_rmdir(handle
->data
, smb_fname
->base_name
);
395 DBG_DEBUG("[CEPH] rmdir(...) = %d\n", result
);
399 static int cephwrap_closedir(struct vfs_handle_struct
*handle
, DIR *dirp
)
403 DBG_DEBUG("[CEPH] closedir(%p, %p)\n", handle
, dirp
);
404 result
= ceph_closedir(handle
->data
, (struct ceph_dir_result
*) dirp
);
405 DBG_DEBUG("[CEPH] closedir(...) = %d\n", result
);
409 /* File operations */
411 static int cephwrap_open(struct vfs_handle_struct
*handle
,
412 struct smb_filename
*smb_fname
,
413 files_struct
*fsp
, int flags
, mode_t mode
)
415 int result
= -ENOENT
;
416 DBG_DEBUG("[CEPH] open(%p, %s, %p, %d, %d)\n", handle
,
417 smb_fname_str_dbg(smb_fname
), fsp
, flags
, mode
);
419 if (smb_fname
->stream_name
) {
423 result
= ceph_open(handle
->data
, smb_fname
->base_name
, flags
, mode
);
425 DBG_DEBUG("[CEPH] open(...) = %d\n", result
);
429 static int cephwrap_close(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
433 DBG_DEBUG("[CEPH] close(%p, %p)\n", handle
, fsp
);
434 result
= ceph_close(handle
->data
, fsp
->fh
->fd
);
435 DBG_DEBUG("[CEPH] close(...) = %d\n", result
);
440 static ssize_t
cephwrap_pread(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
441 size_t n
, off_t offset
)
445 DBG_DEBUG("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
447 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
448 DBG_DEBUG("[CEPH] pread(...) = %llu\n", llu(result
));
452 struct cephwrap_pread_state
{
454 struct vfs_aio_state vfs_aio_state
;
458 * Fake up an async ceph read by calling the synchronous API.
460 static struct tevent_req
*cephwrap_pread_send(struct vfs_handle_struct
*handle
,
462 struct tevent_context
*ev
,
463 struct files_struct
*fsp
,
465 size_t n
, off_t offset
)
467 struct tevent_req
*req
= NULL
;
468 struct cephwrap_pread_state
*state
= NULL
;
471 DBG_DEBUG("[CEPH] %s\n", __func__
);
472 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pread_state
);
477 ret
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
479 /* ceph returns -errno on error. */
480 tevent_req_error(req
, -ret
);
481 return tevent_req_post(req
, ev
);
484 state
->bytes_read
= ret
;
485 tevent_req_done(req
);
486 /* Return and schedule the completion of the call. */
487 return tevent_req_post(req
, ev
);
490 static ssize_t
cephwrap_pread_recv(struct tevent_req
*req
,
491 struct vfs_aio_state
*vfs_aio_state
)
493 struct cephwrap_pread_state
*state
=
494 tevent_req_data(req
, struct cephwrap_pread_state
);
496 DBG_DEBUG("[CEPH] %s\n", __func__
);
497 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
500 *vfs_aio_state
= state
->vfs_aio_state
;
501 return state
->bytes_read
;
504 static ssize_t
cephwrap_pwrite(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
505 size_t n
, off_t offset
)
509 DBG_DEBUG("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
510 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
511 DBG_DEBUG("[CEPH] pwrite(...) = %llu\n", llu(result
));
515 struct cephwrap_pwrite_state
{
516 ssize_t bytes_written
;
517 struct vfs_aio_state vfs_aio_state
;
521 * Fake up an async ceph write by calling the synchronous API.
523 static struct tevent_req
*cephwrap_pwrite_send(struct vfs_handle_struct
*handle
,
525 struct tevent_context
*ev
,
526 struct files_struct
*fsp
,
528 size_t n
, off_t offset
)
530 struct tevent_req
*req
= NULL
;
531 struct cephwrap_pwrite_state
*state
= NULL
;
534 DBG_DEBUG("[CEPH] %s\n", __func__
);
535 req
= tevent_req_create(mem_ctx
, &state
, struct cephwrap_pwrite_state
);
540 ret
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
542 /* ceph returns -errno on error. */
543 tevent_req_error(req
, -ret
);
544 return tevent_req_post(req
, ev
);
547 state
->bytes_written
= ret
;
548 tevent_req_done(req
);
549 /* Return and schedule the completion of the call. */
550 return tevent_req_post(req
, ev
);
553 static ssize_t
cephwrap_pwrite_recv(struct tevent_req
*req
,
554 struct vfs_aio_state
*vfs_aio_state
)
556 struct cephwrap_pwrite_state
*state
=
557 tevent_req_data(req
, struct cephwrap_pwrite_state
);
559 DBG_DEBUG("[CEPH] %s\n", __func__
);
560 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
563 *vfs_aio_state
= state
->vfs_aio_state
;
564 return state
->bytes_written
;
567 static off_t
cephwrap_lseek(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
571 DBG_DEBUG("[CEPH] cephwrap_lseek\n");
572 /* Cope with 'stat' file opens. */
573 if (fsp
->fh
->fd
!= -1) {
574 result
= ceph_lseek(handle
->data
, fsp
->fh
->fd
, offset
, whence
);
579 static ssize_t
cephwrap_sendfile(struct vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
580 off_t offset
, size_t n
)
583 * We cannot support sendfile because libceph is in user space.
585 DBG_DEBUG("[CEPH] cephwrap_sendfile\n");
590 static ssize_t
cephwrap_recvfile(struct vfs_handle_struct
*handle
,
597 * We cannot support recvfile because libceph is in user space.
599 DBG_DEBUG("[CEPH] cephwrap_recvfile\n");
604 static int cephwrap_rename(struct vfs_handle_struct
*handle
,
605 const struct smb_filename
*smb_fname_src
,
606 const struct smb_filename
*smb_fname_dst
)
609 DBG_DEBUG("[CEPH] cephwrap_rename\n");
610 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
615 result
= ceph_rename(handle
->data
, smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
620 * Fake up an async ceph fsync by calling the synchronous API.
623 static struct tevent_req
*cephwrap_fsync_send(struct vfs_handle_struct
*handle
,
625 struct tevent_context
*ev
,
628 struct tevent_req
*req
= NULL
;
629 struct vfs_aio_state
*state
= NULL
;
632 DBG_DEBUG("[CEPH] cephwrap_fsync_send\n");
634 req
= tevent_req_create(mem_ctx
, &state
, struct vfs_aio_state
);
639 /* Make sync call. */
640 ret
= ceph_fsync(handle
->data
, fsp
->fh
->fd
, false);
643 /* ceph_fsync returns -errno on error. */
644 tevent_req_error(req
, -ret
);
645 return tevent_req_post(req
, ev
);
648 /* Mark it as done. */
649 tevent_req_done(req
);
650 /* Return and schedule the completion of the call. */
651 return tevent_req_post(req
, ev
);
654 static int cephwrap_fsync_recv(struct tevent_req
*req
,
655 struct vfs_aio_state
*vfs_aio_state
)
657 struct vfs_aio_state
*state
=
658 tevent_req_data(req
, struct vfs_aio_state
);
660 DBG_DEBUG("[CEPH] cephwrap_fsync_recv\n");
662 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
665 *vfs_aio_state
= *state
;
669 #ifdef HAVE_CEPH_STATX
670 #define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
672 static void init_stat_ex_from_ceph_statx(struct stat_ex
*dst
, const struct ceph_statx
*stx
)
674 if ((stx
->stx_mask
& SAMBA_STATX_ATTR_MASK
) != SAMBA_STATX_ATTR_MASK
)
675 DBG_WARNING("%s: stx->stx_mask is incorrect (wanted %x, got %x)",
676 __func__
, SAMBA_STATX_ATTR_MASK
, stx
->stx_mask
);
678 dst
->st_ex_dev
= stx
->stx_dev
;
679 dst
->st_ex_rdev
= stx
->stx_rdev
;
680 dst
->st_ex_ino
= stx
->stx_ino
;
681 dst
->st_ex_mode
= stx
->stx_mode
;
682 dst
->st_ex_uid
= stx
->stx_uid
;
683 dst
->st_ex_gid
= stx
->stx_gid
;
684 dst
->st_ex_size
= stx
->stx_size
;
685 dst
->st_ex_nlink
= stx
->stx_nlink
;
686 dst
->st_ex_atime
= stx
->stx_atime
;
687 dst
->st_ex_btime
= stx
->stx_btime
;
688 dst
->st_ex_ctime
= stx
->stx_ctime
;
689 dst
->st_ex_mtime
= stx
->stx_mtime
;
690 dst
->st_ex_calculated_birthtime
= false;
691 dst
->st_ex_blksize
= stx
->stx_blksize
;
692 dst
->st_ex_blocks
= stx
->stx_blocks
;
695 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
696 struct smb_filename
*smb_fname
)
699 struct ceph_statx stx
;
701 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
703 if (smb_fname
->stream_name
) {
708 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
709 SAMBA_STATX_ATTR_MASK
, 0);
710 DBG_DEBUG("[CEPH] statx(...) = %d\n", result
);
714 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
715 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
716 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
717 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
718 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
719 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
720 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
721 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
723 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
724 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
728 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
731 struct ceph_statx stx
;
733 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
734 result
= ceph_fstatx(handle
->data
, fsp
->fh
->fd
, &stx
,
735 SAMBA_STATX_ATTR_MASK
, 0);
736 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
740 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
741 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
742 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
743 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
744 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
745 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
746 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
747 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
749 init_stat_ex_from_ceph_statx(sbuf
, &stx
);
750 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
754 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
755 struct smb_filename
*smb_fname
)
758 struct ceph_statx stx
;
760 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
762 if (smb_fname
->stream_name
) {
767 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
768 SAMBA_STATX_ATTR_MASK
, AT_SYMLINK_NOFOLLOW
);
769 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
773 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
777 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
778 const struct smb_filename
*smb_fname
,
779 struct smb_file_time
*ft
)
781 struct ceph_statx stx
= { 0 };
785 if (!null_timespec(ft
->atime
)) {
786 stx
.stx_atime
= ft
->atime
;
787 mask
|= CEPH_SETATTR_ATIME
;
789 if (!null_timespec(ft
->mtime
)) {
790 stx
.stx_mtime
= ft
->mtime
;
791 mask
|= CEPH_SETATTR_MTIME
;
793 if (!null_timespec(ft
->create_time
)) {
794 stx
.stx_btime
= ft
->create_time
;
795 mask
|= CEPH_SETATTR_BTIME
;
802 result
= ceph_setattrx(handle
->data
, smb_fname
->base_name
, &stx
, mask
, 0);
803 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
804 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
805 ft
->create_time
.tv_sec
, result
);
809 #else /* HAVE_CEPH_STATX */
811 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
812 struct smb_filename
*smb_fname
)
817 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
819 if (smb_fname
->stream_name
) {
824 result
= ceph_stat(handle
->data
, smb_fname
->base_name
, (struct stat
*) &stbuf
);
825 DBG_DEBUG("[CEPH] stat(...) = %d\n", result
);
829 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
830 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
831 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
832 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
833 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
834 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
836 init_stat_ex_from_stat(
837 &smb_fname
->st
, &stbuf
,
838 lp_fake_directory_create_times(SNUM(handle
->conn
)));
839 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
843 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
848 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
849 result
= ceph_fstat(handle
->data
, fsp
->fh
->fd
, (struct stat
*) &stbuf
);
850 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
854 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
855 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
856 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
857 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
858 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
859 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
862 init_stat_ex_from_stat(
864 lp_fake_directory_create_times(SNUM(handle
->conn
)));
865 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
869 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
870 struct smb_filename
*smb_fname
)
875 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
877 if (smb_fname
->stream_name
) {
882 result
= ceph_lstat(handle
->data
, smb_fname
->base_name
, &stbuf
);
883 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
887 init_stat_ex_from_stat(
888 &smb_fname
->st
, &stbuf
,
889 lp_fake_directory_create_times(SNUM(handle
->conn
)));
893 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
894 const struct smb_filename
*smb_fname
,
895 struct smb_file_time
*ft
)
900 if (null_timespec(ft
->atime
)) {
901 buf
.actime
= smb_fname
->st
.st_ex_atime
.tv_sec
;
903 buf
.actime
= ft
->atime
.tv_sec
;
905 if (null_timespec(ft
->mtime
)) {
906 buf
.modtime
= smb_fname
->st
.st_ex_mtime
.tv_sec
;
908 buf
.modtime
= ft
->mtime
.tv_sec
;
910 if (!null_timespec(ft
->create_time
)) {
911 set_create_timespec_ea(handle
->conn
, smb_fname
,
914 if (buf
.actime
== smb_fname
->st
.st_ex_atime
.tv_sec
&&
915 buf
.modtime
== smb_fname
->st
.st_ex_mtime
.tv_sec
) {
919 result
= ceph_utime(handle
->data
, smb_fname
->base_name
, &buf
);
920 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
921 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
922 ft
->create_time
.tv_sec
, result
);
925 #endif /* HAVE_CEPH_STATX */
927 static int cephwrap_unlink(struct vfs_handle_struct
*handle
,
928 const struct smb_filename
*smb_fname
)
932 DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
933 if (smb_fname
->stream_name
) {
937 result
= ceph_unlink(handle
->data
, smb_fname
->base_name
);
938 DBG_DEBUG("[CEPH] unlink(...) = %d\n", result
);
942 static int cephwrap_chmod(struct vfs_handle_struct
*handle
,
943 const struct smb_filename
*smb_fname
,
948 DBG_DEBUG("[CEPH] chmod(%p, %s, %d)\n", handle
, smb_fname
->base_name
, mode
);
949 result
= ceph_chmod(handle
->data
, smb_fname
->base_name
, mode
);
950 DBG_DEBUG("[CEPH] chmod(...) = %d\n", result
);
954 static int cephwrap_fchmod(struct vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
958 DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle
, fsp
, mode
);
960 #if defined(HAVE_FCHMOD)
961 result
= ceph_fchmod(handle
->data
, fsp
->fh
->fd
, mode
);
962 DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result
);
970 static int cephwrap_chown(struct vfs_handle_struct
*handle
,
971 const struct smb_filename
*smb_fname
,
976 DBG_DEBUG("[CEPH] chown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
977 result
= ceph_chown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
978 DBG_DEBUG("[CEPH] chown(...) = %d\n", result
);
982 static int cephwrap_fchown(struct vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
987 DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle
, fsp
, uid
, gid
);
988 result
= ceph_fchown(handle
->data
, fsp
->fh
->fd
, uid
, gid
);
989 DBG_DEBUG("[CEPH] fchown(...) = %d\n", result
);
998 static int cephwrap_lchown(struct vfs_handle_struct
*handle
,
999 const struct smb_filename
*smb_fname
,
1004 DBG_DEBUG("[CEPH] lchown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
1005 result
= ceph_lchown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
1006 DBG_DEBUG("[CEPH] lchown(...) = %d\n", result
);
1007 WRAP_RETURN(result
);
1010 static int cephwrap_chdir(struct vfs_handle_struct
*handle
,
1011 const struct smb_filename
*smb_fname
)
1014 DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle
, smb_fname
->base_name
);
1015 result
= ceph_chdir(handle
->data
, smb_fname
->base_name
);
1016 DBG_DEBUG("[CEPH] chdir(...) = %d\n", result
);
1017 WRAP_RETURN(result
);
1020 static struct smb_filename
*cephwrap_getwd(struct vfs_handle_struct
*handle
,
1023 const char *cwd
= ceph_getcwd(handle
->data
);
1024 DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle
, cwd
);
1025 return synthetic_smb_fname(ctx
,
1032 static int strict_allocate_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1034 off_t space_to_write
;
1035 uint64_t space_avail
;
1036 uint64_t bsize
,dfree
,dsize
;
1039 SMB_STRUCT_STAT
*pst
;
1041 status
= vfs_stat_fsp(fsp
);
1042 if (!NT_STATUS_IS_OK(status
)) {
1045 pst
= &fsp
->fsp_name
->st
;
1048 if (S_ISFIFO(pst
->st_ex_mode
))
1052 if (pst
->st_ex_size
== len
)
1055 /* Shrink - just ftruncate. */
1056 if (pst
->st_ex_size
> len
)
1057 return ftruncate(fsp
->fh
->fd
, len
);
1059 space_to_write
= len
- pst
->st_ex_size
;
1061 /* for allocation try fallocate first. This can fail on some
1062 platforms e.g. when the filesystem doesn't support it and no
1063 emulation is being done by the libc (like on AIX with JFS1). In that
1064 case we do our own emulation. fallocate implementations can
1065 return ENOTSUP or EINVAL in cases like that. */
1066 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
1067 if (ret
== -1 && errno
== ENOSPC
) {
1073 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1074 "error %d. Falling back to slow manual allocation\n", errno
));
1076 /* available disk space is enough or not? */
1078 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
1079 /* space_avail is 1k blocks */
1080 if (space_avail
== (uint64_t)-1 ||
1081 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1086 /* Write out the real space on disk. */
1087 return vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1090 static int cephwrap_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1097 DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle
, fsp
, llu(len
));
1099 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
1100 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1104 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1105 sys_ftruncate if the system supports it. Then I discovered that
1106 you can have some filesystems that support ftruncate
1107 expansion and some that don't! On Linux fat can't do
1108 ftruncate extend but ext2 can. */
1110 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1114 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1115 extend a file with ftruncate. Provide alternate implementation
1117 currpos
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
1118 if (currpos
== -1) {
1122 /* Do an fstat to see if the file is longer than the requested
1123 size in which case the ftruncate above should have
1124 succeeded or shorter, in which case seek to len - 1 and
1125 write 1 byte of zero */
1126 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1131 if (S_ISFIFO(st
.st_ex_mode
)) {
1137 if (st
.st_ex_size
== len
) {
1142 if (st
.st_ex_size
> len
) {
1143 /* the sys_ftruncate should have worked */
1147 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
1158 static bool cephwrap_lock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1160 DBG_DEBUG("[CEPH] lock\n");
1164 static int cephwrap_kernel_flock(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1165 uint32_t share_mode
, uint32_t access_mask
)
1167 DBG_ERR("[CEPH] flock unsupported! Consider setting "
1168 "\"kernel share modes = no\"\n");
1174 static bool cephwrap_getlock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1176 DBG_DEBUG("[CEPH] getlock returning false and errno=0\n");
1183 * We cannot let this fall through to the default, because the file might only
1184 * be accessible from libceph (which is a user-space client) but the fd might
1185 * be for some file the kernel knows about.
1187 static int cephwrap_linux_setlease(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1192 DBG_DEBUG("[CEPH] linux_setlease\n");
1197 static int cephwrap_symlink(struct vfs_handle_struct
*handle
,
1198 const char *link_target
,
1199 const struct smb_filename
*new_smb_fname
)
1202 DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle
,
1204 new_smb_fname
->base_name
);
1205 result
= ceph_symlink(handle
->data
,
1207 new_smb_fname
->base_name
);
1208 DBG_DEBUG("[CEPH] symlink(...) = %d\n", result
);
1209 WRAP_RETURN(result
);
1212 static int cephwrap_readlink(struct vfs_handle_struct
*handle
,
1213 const struct smb_filename
*smb_fname
,
1218 DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle
,
1219 smb_fname
->base_name
, buf
, llu(bufsiz
));
1220 result
= ceph_readlink(handle
->data
, smb_fname
->base_name
, buf
, bufsiz
);
1221 DBG_DEBUG("[CEPH] readlink(...) = %d\n", result
);
1222 WRAP_RETURN(result
);
1225 static int cephwrap_link(struct vfs_handle_struct
*handle
,
1226 const struct smb_filename
*old_smb_fname
,
1227 const struct smb_filename
*new_smb_fname
)
1230 DBG_DEBUG("[CEPH] link(%p, %s, %s)\n", handle
,
1231 old_smb_fname
->base_name
,
1232 new_smb_fname
->base_name
);
1233 result
= ceph_link(handle
->data
,
1234 old_smb_fname
->base_name
,
1235 new_smb_fname
->base_name
);
1236 DBG_DEBUG("[CEPH] link(...) = %d\n", result
);
1237 WRAP_RETURN(result
);
1240 static int cephwrap_mknod(struct vfs_handle_struct
*handle
,
1241 const struct smb_filename
*smb_fname
,
1246 DBG_DEBUG("[CEPH] mknod(%p, %s)\n", handle
, smb_fname
->base_name
);
1247 result
= ceph_mknod(handle
->data
, smb_fname
->base_name
, mode
, dev
);
1248 DBG_DEBUG("[CEPH] mknod(...) = %d\n", result
);
1249 WRAP_RETURN(result
);
1253 * This is a simple version of real-path ... a better version is needed to
1254 * ask libceph about symbolic links.
1256 static struct smb_filename
*cephwrap_realpath(struct vfs_handle_struct
*handle
,
1258 const struct smb_filename
*smb_fname
)
1260 char *result
= NULL
;
1261 const char *path
= smb_fname
->base_name
;
1262 size_t len
= strlen(path
);
1263 struct smb_filename
*result_fname
= NULL
;
1266 if (len
&& (path
[0] == '/')) {
1267 r
= asprintf(&result
, "%s", path
);
1268 } else if ((len
>= 2) && (path
[0] == '.') && (path
[1] == '/')) {
1270 r
= asprintf(&result
, "%s",
1271 handle
->conn
->connectpath
);
1273 r
= asprintf(&result
, "%s/%s",
1274 handle
->conn
->connectpath
, &path
[2]);
1277 r
= asprintf(&result
, "%s/%s",
1278 handle
->conn
->connectpath
, path
);
1285 DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle
, path
, result
);
1286 result_fname
= synthetic_smb_fname(ctx
,
1292 return result_fname
;
1295 static int cephwrap_chflags(struct vfs_handle_struct
*handle
,
1296 const struct smb_filename
*smb_fname
,
1303 static int cephwrap_get_real_filename(struct vfs_handle_struct
*handle
,
1306 TALLOC_CTX
*mem_ctx
,
1310 * Don't fall back to get_real_filename so callers can differentiate
1311 * between a full directory scan and an actual case-insensitive stat.
1317 static const char *cephwrap_connectpath(struct vfs_handle_struct
*handle
,
1318 const struct smb_filename
*smb_fname
)
1320 return handle
->conn
->connectpath
;
1323 /****************************************************************
1324 Extended attribute operations.
1325 *****************************************************************/
1327 static ssize_t
cephwrap_getxattr(struct vfs_handle_struct
*handle
,
1328 const struct smb_filename
*smb_fname
,
1334 DBG_DEBUG("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle
,
1335 smb_fname
->base_name
, name
, value
, llu(size
));
1336 ret
= ceph_getxattr(handle
->data
,
1337 smb_fname
->base_name
, name
, value
, size
);
1338 DBG_DEBUG("[CEPH] getxattr(...) = %d\n", ret
);
1342 return (ssize_t
)ret
;
1346 static ssize_t
cephwrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
1349 DBG_DEBUG("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle
, fsp
, name
, value
, llu(size
));
1350 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1351 ret
= ceph_fgetxattr(handle
->data
, fsp
->fh
->fd
, name
, value
, size
);
1353 ret
= ceph_getxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
);
1355 DBG_DEBUG("[CEPH] fgetxattr(...) = %d\n", ret
);
1359 return (ssize_t
)ret
;
1363 static ssize_t
cephwrap_listxattr(struct vfs_handle_struct
*handle
,
1364 const struct smb_filename
*smb_fname
,
1369 DBG_DEBUG("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle
,
1370 smb_fname
->base_name
, list
, llu(size
));
1371 ret
= ceph_listxattr(handle
->data
, smb_fname
->base_name
, list
, size
);
1372 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1376 return (ssize_t
)ret
;
1380 static ssize_t
cephwrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
1383 DBG_DEBUG("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle
, fsp
, list
, llu(size
));
1384 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1385 ret
= ceph_flistxattr(handle
->data
, fsp
->fh
->fd
, list
, size
);
1387 ret
= ceph_listxattr(handle
->data
, fsp
->fsp_name
->base_name
, list
, size
);
1389 DBG_DEBUG("[CEPH] flistxattr(...) = %d\n", ret
);
1393 return (ssize_t
)ret
;
1397 static int cephwrap_removexattr(struct vfs_handle_struct
*handle
,
1398 const struct smb_filename
*smb_fname
,
1402 DBG_DEBUG("[CEPH] removexattr(%p, %s, %s)\n", handle
,
1403 smb_fname
->base_name
, name
);
1404 ret
= ceph_removexattr(handle
->data
, smb_fname
->base_name
, name
);
1405 DBG_DEBUG("[CEPH] removexattr(...) = %d\n", ret
);
1409 static int cephwrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
1412 DBG_DEBUG("[CEPH] fremovexattr(%p, %p, %s)\n", handle
, fsp
, name
);
1413 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1414 ret
= ceph_fremovexattr(handle
->data
, fsp
->fh
->fd
, name
);
1416 ret
= ceph_removexattr(handle
->data
, fsp
->fsp_name
->base_name
, name
);
1418 DBG_DEBUG("[CEPH] fremovexattr(...) = %d\n", ret
);
1422 static int cephwrap_setxattr(struct vfs_handle_struct
*handle
,
1423 const struct smb_filename
*smb_fname
,
1430 DBG_DEBUG("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle
,
1431 smb_fname
->base_name
, name
, value
, llu(size
), flags
);
1432 ret
= ceph_setxattr(handle
->data
, smb_fname
->base_name
,
1433 name
, value
, size
, flags
);
1434 DBG_DEBUG("[CEPH] setxattr(...) = %d\n", ret
);
1438 static int cephwrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
1441 DBG_DEBUG("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle
, fsp
, name
, value
, llu(size
), flags
);
1442 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1443 ret
= ceph_fsetxattr(handle
->data
, fsp
->fh
->fd
,
1444 name
, value
, size
, flags
);
1446 ret
= ceph_setxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
1448 DBG_DEBUG("[CEPH] fsetxattr(...) = %d\n", ret
);
1452 static bool cephwrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
1456 * We do not support AIO yet.
1459 DBG_DEBUG("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle
, fsp
);
1464 static struct vfs_fn_pointers ceph_fns
= {
1465 /* Disk operations */
1467 .connect_fn
= cephwrap_connect
,
1468 .disconnect_fn
= cephwrap_disconnect
,
1469 .disk_free_fn
= cephwrap_disk_free
,
1470 .get_quota_fn
= cephwrap_get_quota
,
1471 .set_quota_fn
= cephwrap_set_quota
,
1472 .statvfs_fn
= cephwrap_statvfs
,
1473 .fs_capabilities_fn
= cephwrap_fs_capabilities
,
1475 /* Directory operations */
1477 .opendir_fn
= cephwrap_opendir
,
1478 .fdopendir_fn
= cephwrap_fdopendir
,
1479 .readdir_fn
= cephwrap_readdir
,
1480 .seekdir_fn
= cephwrap_seekdir
,
1481 .telldir_fn
= cephwrap_telldir
,
1482 .rewind_dir_fn
= cephwrap_rewinddir
,
1483 .mkdir_fn
= cephwrap_mkdir
,
1484 .rmdir_fn
= cephwrap_rmdir
,
1485 .closedir_fn
= cephwrap_closedir
,
1487 /* File operations */
1489 .open_fn
= cephwrap_open
,
1490 .close_fn
= cephwrap_close
,
1491 .pread_fn
= cephwrap_pread
,
1492 .pread_send_fn
= cephwrap_pread_send
,
1493 .pread_recv_fn
= cephwrap_pread_recv
,
1494 .pwrite_fn
= cephwrap_pwrite
,
1495 .pwrite_send_fn
= cephwrap_pwrite_send
,
1496 .pwrite_recv_fn
= cephwrap_pwrite_recv
,
1497 .lseek_fn
= cephwrap_lseek
,
1498 .sendfile_fn
= cephwrap_sendfile
,
1499 .recvfile_fn
= cephwrap_recvfile
,
1500 .rename_fn
= cephwrap_rename
,
1501 .fsync_send_fn
= cephwrap_fsync_send
,
1502 .fsync_recv_fn
= cephwrap_fsync_recv
,
1503 .stat_fn
= cephwrap_stat
,
1504 .fstat_fn
= cephwrap_fstat
,
1505 .lstat_fn
= cephwrap_lstat
,
1506 .unlink_fn
= cephwrap_unlink
,
1507 .chmod_fn
= cephwrap_chmod
,
1508 .fchmod_fn
= cephwrap_fchmod
,
1509 .chown_fn
= cephwrap_chown
,
1510 .fchown_fn
= cephwrap_fchown
,
1511 .lchown_fn
= cephwrap_lchown
,
1512 .chdir_fn
= cephwrap_chdir
,
1513 .getwd_fn
= cephwrap_getwd
,
1514 .ntimes_fn
= cephwrap_ntimes
,
1515 .ftruncate_fn
= cephwrap_ftruncate
,
1516 .lock_fn
= cephwrap_lock
,
1517 .kernel_flock_fn
= cephwrap_kernel_flock
,
1518 .linux_setlease_fn
= cephwrap_linux_setlease
,
1519 .getlock_fn
= cephwrap_getlock
,
1520 .symlink_fn
= cephwrap_symlink
,
1521 .readlink_fn
= cephwrap_readlink
,
1522 .link_fn
= cephwrap_link
,
1523 .mknod_fn
= cephwrap_mknod
,
1524 .realpath_fn
= cephwrap_realpath
,
1525 .chflags_fn
= cephwrap_chflags
,
1526 .get_real_filename_fn
= cephwrap_get_real_filename
,
1527 .connectpath_fn
= cephwrap_connectpath
,
1529 /* EA operations. */
1530 .getxattr_fn
= cephwrap_getxattr
,
1531 .fgetxattr_fn
= cephwrap_fgetxattr
,
1532 .listxattr_fn
= cephwrap_listxattr
,
1533 .flistxattr_fn
= cephwrap_flistxattr
,
1534 .removexattr_fn
= cephwrap_removexattr
,
1535 .fremovexattr_fn
= cephwrap_fremovexattr
,
1536 .setxattr_fn
= cephwrap_setxattr
,
1537 .fsetxattr_fn
= cephwrap_fsetxattr
,
1539 /* Posix ACL Operations */
1540 .sys_acl_get_file_fn
= posixacl_xattr_acl_get_file
,
1541 .sys_acl_get_fd_fn
= posixacl_xattr_acl_get_fd
,
1542 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
1543 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
1544 .sys_acl_set_file_fn
= posixacl_xattr_acl_set_file
,
1545 .sys_acl_set_fd_fn
= posixacl_xattr_acl_set_fd
,
1546 .sys_acl_delete_def_file_fn
= posixacl_xattr_acl_delete_def_file
,
1548 /* aio operations */
1549 .aio_force_fn
= cephwrap_aio_force
,
1553 NTSTATUS
vfs_ceph_init(TALLOC_CTX
*ctx
)
1555 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,