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"
42 #define DBGC_CLASS DBGC_VFS
44 #ifndef LIBCEPHFS_VERSION
45 #define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
46 #define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0)
50 * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
52 #define llu(_var) ((long long unsigned)_var)
55 * Note, libceph's return code model is to return -errno! So we have to convert
56 * to what Samba expects, with is set errno to -return and return -1
58 #define WRAP_RETURN(_res) \
67 * We mount only one file system and then all shares are assumed to be in that.
68 * FIXME: If we want to support more than one FS, then we have to deal with
71 * So, cmount tells us if we have been this way before and whether
72 * we need to mount ceph and cmount_cnt tells us how many times we have
75 static struct ceph_mount_info
* cmount
= NULL
;
76 static uint32_t cmount_cnt
= 0;
78 /* Check for NULL pointer parameters in cephwrap_* functions */
80 /* We don't want to have NULL function pointers lying around. Someone
81 is sure to try and execute them. These stubs are used to prevent
84 static int cephwrap_connect(struct vfs_handle_struct
*handle
, const char *service
, const char *user
)
89 const char * conf_file
;
92 handle
->data
= cmount
; /* We have been here before */
97 conf_file
= lp_parm_const_string(SNUM(handle
->conn
), "ceph", "config_file", NULL
);
99 DBG_DEBUG( "[CEPH] calling: ceph_create\n" );
100 ret
= ceph_create(&cmount
, NULL
);
105 /* Override the config file */
106 DBG_DEBUG( "[CEPH] calling: ceph_conf_read_file\n" );
107 ret
= ceph_conf_read_file(cmount
, conf_file
);
110 DBG_DEBUG( "[CEPH] calling: ceph_conf_read_file with %s\n", conf_file
);
111 ret
= ceph_conf_read_file(cmount
, NULL
);
118 DBG_DEBUG( "[CEPH] calling: ceph_conf_get\n" );
119 ret
= ceph_conf_get(cmount
, "log file", buf
, sizeof(buf
));
124 DBG_DEBUG("[CEPH] calling: ceph_mount\n");
125 ret
= ceph_mount(cmount
, NULL
);
131 * encode mount context/state into our vfs/connection holding structure
132 * cmount is a ceph_mount_t*
134 handle
->data
= cmount
;
140 ceph_release(cmount
);
144 * Handle the error correctly. Ceph returns -errno.
146 DBG_DEBUG("[CEPH] Error return: %s\n", strerror(-ret
));
150 static void cephwrap_disconnect(struct vfs_handle_struct
*handle
)
155 DBG_ERR("[CEPH] Error, ceph not mounted\n");
159 /* Should we unmount/shutdown? Only if the last disconnect? */
161 DBG_DEBUG("[CEPH] Not shuting down CEPH because still more connections\n");
165 ret
= ceph_unmount(cmount
);
167 DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret
));
170 ret
= ceph_release(cmount
);
172 DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret
));
175 cmount
= NULL
; /* Make it safe */
178 /* Disk operations */
180 static uint64_t cephwrap_disk_free(struct vfs_handle_struct
*handle
,
181 const char *path
, uint64_t *bsize
,
182 uint64_t *dfree
, uint64_t *dsize
)
184 struct statvfs statvfs_buf
;
187 if (!(ret
= ceph_statfs(handle
->data
, path
, &statvfs_buf
))) {
189 * Provide all the correct values.
191 *bsize
= statvfs_buf
.f_bsize
;
192 *dfree
= statvfs_buf
.f_bavail
;
193 *dsize
= statvfs_buf
.f_blocks
;
194 DBG_DEBUG("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
195 llu(*bsize
), llu(*dfree
), llu(*dsize
));
198 DBG_DEBUG("[CEPH] ceph_statfs returned %d\n", ret
);
203 static int cephwrap_get_quota(struct vfs_handle_struct
*handle
,
204 const char *path
, enum SMB_QUOTA_TYPE qtype
,
205 unid_t id
, SMB_DISK_QUOTA
*qt
)
207 /* libceph: Ceph does not implement this */
209 /* was ifdef HAVE_SYS_QUOTAS */
212 ret
= ceph_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
226 static int cephwrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
228 /* libceph: Ceph does not implement this */
230 /* was ifdef HAVE_SYS_QUOTAS */
233 ret
= ceph_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
241 WRAP_RETURN(-ENOSYS
);
245 static int cephwrap_statvfs(struct vfs_handle_struct
*handle
, const char *path
, vfs_statvfs_struct
*statbuf
)
247 struct statvfs statvfs_buf
;
250 ret
= ceph_statfs(handle
->data
, path
, &statvfs_buf
);
254 statbuf
->OptimalTransferSize
= statvfs_buf
.f_frsize
;
255 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
256 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
257 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
258 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
259 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
260 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
261 statbuf
->FsIdentifier
= statvfs_buf
.f_fsid
;
262 DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
263 (long int)statvfs_buf
.f_bsize
, (long int)statvfs_buf
.f_blocks
,
264 (long int)statvfs_buf
.f_bfree
, (long int)statvfs_buf
.f_bavail
);
269 /* Directory operations */
271 static DIR *cephwrap_opendir(struct vfs_handle_struct
*handle
,
272 const struct smb_filename
*smb_fname
,
273 const char *mask
, uint32_t attr
)
276 struct ceph_dir_result
*result
;
277 DBG_DEBUG("[CEPH] opendir(%p, %s)\n", handle
, smb_fname
->base_name
);
279 /* Returns NULL if it does not exist or there are problems ? */
280 ret
= ceph_opendir(handle
->data
, smb_fname
->base_name
, &result
);
283 errno
= -ret
; /* We return result which is NULL in this case */
286 DBG_DEBUG("[CEPH] opendir(...) = %d\n", ret
);
287 return (DIR *) result
;
290 static DIR *cephwrap_fdopendir(struct vfs_handle_struct
*handle
,
291 struct files_struct
*fsp
,
296 struct ceph_dir_result
*result
;
297 DBG_DEBUG("[CEPH] fdopendir(%p, %p)\n", handle
, fsp
);
299 ret
= ceph_opendir(handle
->data
, fsp
->fsp_name
->base_name
, &result
);
302 errno
= -ret
; /* We return result which is NULL in this case */
305 DBG_DEBUG("[CEPH] fdopendir(...) = %d\n", ret
);
306 return (DIR *) result
;
309 static struct dirent
*cephwrap_readdir(struct vfs_handle_struct
*handle
,
311 SMB_STRUCT_STAT
*sbuf
)
313 struct dirent
*result
;
315 DBG_DEBUG("[CEPH] readdir(%p, %p)\n", handle
, dirp
);
316 result
= ceph_readdir(handle
->data
, (struct ceph_dir_result
*) dirp
);
317 DBG_DEBUG("[CEPH] readdir(...) = %p\n", result
);
319 /* Default Posix readdir() does not give us stat info.
320 * Set to invalid to indicate we didn't return this info. */
322 SET_STAT_INVALID(*sbuf
);
326 static void cephwrap_seekdir(struct vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
328 DBG_DEBUG("[CEPH] seekdir(%p, %p, %ld)\n", handle
, dirp
, offset
);
329 ceph_seekdir(handle
->data
, (struct ceph_dir_result
*) dirp
, offset
);
332 static long cephwrap_telldir(struct vfs_handle_struct
*handle
, DIR *dirp
)
335 DBG_DEBUG("[CEPH] telldir(%p, %p)\n", handle
, dirp
);
336 ret
= ceph_telldir(handle
->data
, (struct ceph_dir_result
*) dirp
);
337 DBG_DEBUG("[CEPH] telldir(...) = %ld\n", ret
);
341 static void cephwrap_rewinddir(struct vfs_handle_struct
*handle
, DIR *dirp
)
343 DBG_DEBUG("[CEPH] rewinddir(%p, %p)\n", handle
, dirp
);
344 ceph_rewinddir(handle
->data
, (struct ceph_dir_result
*) dirp
);
347 static int cephwrap_mkdir(struct vfs_handle_struct
*handle
,
348 const struct smb_filename
*smb_fname
,
352 bool has_dacl
= False
;
354 const char *path
= smb_fname
->base_name
;
356 DBG_DEBUG("[CEPH] mkdir(%p, %s)\n", handle
, path
);
358 if (lp_inherit_acls(SNUM(handle
->conn
))
359 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
360 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
)))
365 result
= ceph_mkdir(handle
->data
, path
, mode
);
368 * Note. This order is important
372 } else if (result
== 0 && !has_dacl
) {
374 * We need to do this as the default behavior of POSIX ACLs
375 * is to set the mask to be the requested group permission
376 * bits, not the group permission bits to be the requested
377 * group permission bits. This is not what we want, as it will
378 * mess up any inherited ACL bits that were set. JRA.
380 int saved_errno
= errno
; /* We may get ENOSYS */
381 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, smb_fname
, mode
) == -1) &&
390 static int cephwrap_rmdir(struct vfs_handle_struct
*handle
,
391 const struct smb_filename
*smb_fname
)
395 DBG_DEBUG("[CEPH] rmdir(%p, %s)\n", handle
, smb_fname
->base_name
);
396 result
= ceph_rmdir(handle
->data
, smb_fname
->base_name
);
397 DBG_DEBUG("[CEPH] rmdir(...) = %d\n", result
);
401 static int cephwrap_closedir(struct vfs_handle_struct
*handle
, DIR *dirp
)
405 DBG_DEBUG("[CEPH] closedir(%p, %p)\n", handle
, dirp
);
406 result
= ceph_closedir(handle
->data
, (struct ceph_dir_result
*) dirp
);
407 DBG_DEBUG("[CEPH] closedir(...) = %d\n", result
);
411 /* File operations */
413 static int cephwrap_open(struct vfs_handle_struct
*handle
,
414 struct smb_filename
*smb_fname
,
415 files_struct
*fsp
, int flags
, mode_t mode
)
417 int result
= -ENOENT
;
418 DBG_DEBUG("[CEPH] open(%p, %s, %p, %d, %d)\n", handle
,
419 smb_fname_str_dbg(smb_fname
), fsp
, flags
, mode
);
421 if (smb_fname
->stream_name
) {
425 result
= ceph_open(handle
->data
, smb_fname
->base_name
, flags
, mode
);
427 DBG_DEBUG("[CEPH] open(...) = %d\n", result
);
431 static int cephwrap_close(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
435 DBG_DEBUG("[CEPH] close(%p, %p)\n", handle
, fsp
);
436 result
= ceph_close(handle
->data
, fsp
->fh
->fd
);
437 DBG_DEBUG("[CEPH] close(...) = %d\n", result
);
442 static ssize_t
cephwrap_read(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
446 DBG_DEBUG("[CEPH] read(%p, %p, %p, %llu)\n", handle
, fsp
, data
, llu(n
));
448 /* Using -1 for the offset means read/write rather than pread/pwrite */
449 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, -1);
450 DBG_DEBUG("[CEPH] read(...) = %llu\n", llu(result
));
454 static ssize_t
cephwrap_pread(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
455 size_t n
, off_t offset
)
459 DBG_DEBUG("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
461 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
462 DBG_DEBUG("[CEPH] pread(...) = %llu\n", llu(result
));
467 static ssize_t
cephwrap_write(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
471 DBG_DEBUG("[CEPH] write(%p, %p, %p, %llu)\n", handle
, fsp
, data
, llu(n
));
473 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, -1);
475 DBG_DEBUG("[CEPH] write(...) = %llu\n", llu(result
));
479 fsp
->fh
->pos
+= result
;
483 static ssize_t
cephwrap_pwrite(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
484 size_t n
, off_t offset
)
488 DBG_DEBUG("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
489 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
490 DBG_DEBUG("[CEPH] pwrite(...) = %llu\n", llu(result
));
494 static off_t
cephwrap_lseek(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
498 DBG_DEBUG("[CEPH] cephwrap_lseek\n");
499 /* Cope with 'stat' file opens. */
500 if (fsp
->fh
->fd
!= -1) {
501 result
= ceph_lseek(handle
->data
, fsp
->fh
->fd
, offset
, whence
);
506 static ssize_t
cephwrap_sendfile(struct vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
507 off_t offset
, size_t n
)
510 * We cannot support sendfile because libceph is in user space.
512 DBG_DEBUG("[CEPH] cephwrap_sendfile\n");
517 static ssize_t
cephwrap_recvfile(struct vfs_handle_struct
*handle
,
524 * We cannot support recvfile because libceph is in user space.
526 DBG_DEBUG("[CEPH] cephwrap_recvfile\n");
531 static int cephwrap_rename(struct vfs_handle_struct
*handle
,
532 const struct smb_filename
*smb_fname_src
,
533 const struct smb_filename
*smb_fname_dst
)
536 DBG_DEBUG("[CEPH] cephwrap_rename\n");
537 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
542 result
= ceph_rename(handle
->data
, smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
546 static int cephwrap_fsync(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
549 DBG_DEBUG("[CEPH] cephwrap_fsync\n");
550 result
= ceph_fsync(handle
->data
, fsp
->fh
->fd
, false);
554 #ifdef HAVE_CEPH_STATX
555 #define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
557 static void init_stat_ex_from_ceph_statx(struct stat_ex
*dst
, const struct ceph_statx
*stx
)
559 if ((stx
->stx_mask
& SAMBA_STATX_ATTR_MASK
) != SAMBA_STATX_ATTR_MASK
)
560 DBG_WARNING("%s: stx->stx_mask is incorrect (wanted %x, got %x)",
561 __func__
, SAMBA_STATX_ATTR_MASK
, stx
->stx_mask
);
563 dst
->st_ex_dev
= stx
->stx_dev
;
564 dst
->st_ex_rdev
= stx
->stx_rdev
;
565 dst
->st_ex_ino
= stx
->stx_ino
;
566 dst
->st_ex_mode
= stx
->stx_mode
;
567 dst
->st_ex_uid
= stx
->stx_uid
;
568 dst
->st_ex_gid
= stx
->stx_gid
;
569 dst
->st_ex_size
= stx
->stx_size
;
570 dst
->st_ex_nlink
= stx
->stx_nlink
;
571 dst
->st_ex_atime
= stx
->stx_atime
;
572 dst
->st_ex_btime
= stx
->stx_btime
;
573 dst
->st_ex_ctime
= stx
->stx_ctime
;
574 dst
->st_ex_mtime
= stx
->stx_mtime
;
575 dst
->st_ex_calculated_birthtime
= false;
576 dst
->st_ex_blksize
= stx
->stx_blksize
;
577 dst
->st_ex_blocks
= stx
->stx_blocks
;
580 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
581 struct smb_filename
*smb_fname
)
584 struct ceph_statx stx
;
586 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
588 if (smb_fname
->stream_name
) {
593 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
594 SAMBA_STATX_ATTR_MASK
, 0);
595 DBG_DEBUG("[CEPH] statx(...) = %d\n", result
);
599 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
600 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
601 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
602 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
603 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
604 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
605 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
606 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
608 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
609 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
613 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
616 struct ceph_statx stx
;
618 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
619 result
= ceph_fstatx(handle
->data
, fsp
->fh
->fd
, &stx
,
620 SAMBA_STATX_ATTR_MASK
, 0);
621 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
625 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
626 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
627 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
628 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
629 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
630 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
631 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
632 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
634 init_stat_ex_from_ceph_statx(sbuf
, &stx
);
635 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
639 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
640 struct smb_filename
*smb_fname
)
643 struct ceph_statx stx
;
645 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
647 if (smb_fname
->stream_name
) {
652 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
653 SAMBA_STATX_ATTR_MASK
, AT_SYMLINK_NOFOLLOW
);
654 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
658 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
662 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
663 const struct smb_filename
*smb_fname
,
664 struct smb_file_time
*ft
)
666 struct ceph_statx stx
= { 0 };
670 if (!null_timespec(ft
->atime
)) {
671 stx
.stx_atime
= ft
->atime
;
672 mask
|= CEPH_SETATTR_ATIME
;
674 if (!null_timespec(ft
->mtime
)) {
675 stx
.stx_mtime
= ft
->mtime
;
676 mask
|= CEPH_SETATTR_MTIME
;
678 if (!null_timespec(ft
->create_time
)) {
679 stx
.stx_btime
= ft
->create_time
;
680 mask
|= CEPH_SETATTR_BTIME
;
687 result
= ceph_setattrx(handle
->data
, smb_fname
->base_name
, &stx
, mask
, 0);
688 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
689 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
690 ft
->create_time
.tv_sec
, result
);
694 #else /* HAVE_CEPH_STATX */
696 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
697 struct smb_filename
*smb_fname
)
702 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
704 if (smb_fname
->stream_name
) {
709 result
= ceph_stat(handle
->data
, smb_fname
->base_name
, (struct stat
*) &stbuf
);
710 DBG_DEBUG("[CEPH] stat(...) = %d\n", result
);
714 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
715 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
716 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
717 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
718 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
719 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
721 init_stat_ex_from_stat(
722 &smb_fname
->st
, &stbuf
,
723 lp_fake_directory_create_times(SNUM(handle
->conn
)));
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
)
733 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
734 result
= ceph_fstat(handle
->data
, fsp
->fh
->fd
, (struct stat
*) &stbuf
);
735 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
739 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
740 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
741 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
742 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
743 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
744 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
747 init_stat_ex_from_stat(
749 lp_fake_directory_create_times(SNUM(handle
->conn
)));
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
)
760 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
762 if (smb_fname
->stream_name
) {
767 result
= ceph_lstat(handle
->data
, smb_fname
->base_name
, &stbuf
);
768 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
772 init_stat_ex_from_stat(
773 &smb_fname
->st
, &stbuf
,
774 lp_fake_directory_create_times(SNUM(handle
->conn
)));
778 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
779 const struct smb_filename
*smb_fname
,
780 struct smb_file_time
*ft
)
785 if (null_timespec(ft
->atime
)) {
786 buf
.actime
= smb_fname
->st
.st_ex_atime
.tv_sec
;
788 buf
.actime
= ft
->atime
.tv_sec
;
790 if (null_timespec(ft
->mtime
)) {
791 buf
.modtime
= smb_fname
->st
.st_ex_mtime
.tv_sec
;
793 buf
.modtime
= ft
->mtime
.tv_sec
;
795 if (!null_timespec(ft
->create_time
)) {
796 set_create_timespec_ea(handle
->conn
, smb_fname
,
799 if (buf
.actime
== smb_fname
->st
.st_ex_atime
.tv_sec
&&
800 buf
.modtime
== smb_fname
->st
.st_ex_mtime
.tv_sec
) {
804 result
= ceph_utime(handle
->data
, smb_fname
->base_name
, &buf
);
805 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
806 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
807 ft
->create_time
.tv_sec
, result
);
810 #endif /* HAVE_CEPH_STATX */
812 static int cephwrap_unlink(struct vfs_handle_struct
*handle
,
813 const struct smb_filename
*smb_fname
)
817 DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
818 if (smb_fname
->stream_name
) {
822 result
= ceph_unlink(handle
->data
, smb_fname
->base_name
);
823 DBG_DEBUG("[CEPH] unlink(...) = %d\n", result
);
827 static int cephwrap_chmod(struct vfs_handle_struct
*handle
,
828 const struct smb_filename
*smb_fname
,
833 DBG_DEBUG("[CEPH] chmod(%p, %s, %d)\n", handle
, smb_fname
->base_name
, mode
);
836 * We need to do this due to the fact that the default POSIX ACL
837 * chmod modifies the ACL *mask* for the group owner, not the
838 * group owner bits directly. JRA.
843 int saved_errno
= errno
; /* We might get ENOSYS */
844 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
850 /* Error - return the old errno. */
854 result
= ceph_chmod(handle
->data
, smb_fname
->base_name
, mode
);
855 DBG_DEBUG("[CEPH] chmod(...) = %d\n", result
);
859 static int cephwrap_fchmod(struct vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
863 DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle
, fsp
, mode
);
866 * We need to do this due to the fact that the default POSIX ACL
867 * chmod modifies the ACL *mask* for the group owner, not the
868 * group owner bits directly. JRA.
872 int saved_errno
= errno
; /* We might get ENOSYS */
873 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
876 /* Error - return the old errno. */
880 #if defined(HAVE_FCHMOD)
881 result
= ceph_fchmod(handle
->data
, fsp
->fh
->fd
, mode
);
882 DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result
);
890 static int cephwrap_chown(struct vfs_handle_struct
*handle
,
891 const struct smb_filename
*smb_fname
,
896 DBG_DEBUG("[CEPH] chown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
897 result
= ceph_chown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
898 DBG_DEBUG("[CEPH] chown(...) = %d\n", result
);
902 static int cephwrap_fchown(struct vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
907 DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle
, fsp
, uid
, gid
);
908 result
= ceph_fchown(handle
->data
, fsp
->fh
->fd
, uid
, gid
);
909 DBG_DEBUG("[CEPH] fchown(...) = %d\n", result
);
918 static int cephwrap_lchown(struct vfs_handle_struct
*handle
,
919 const struct smb_filename
*smb_fname
,
924 DBG_DEBUG("[CEPH] lchown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
925 result
= ceph_lchown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
926 DBG_DEBUG("[CEPH] lchown(...) = %d\n", result
);
930 static int cephwrap_chdir(struct vfs_handle_struct
*handle
, const char *path
)
933 DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle
, path
);
935 * If the path is just / use chdir because Ceph is below / and
936 * cannot deal with changing directory above its mount point
938 if (path
&& !strcmp(path
, "/"))
941 result
= ceph_chdir(handle
->data
, path
);
942 DBG_DEBUG("[CEPH] chdir(...) = %d\n", result
);
946 static char *cephwrap_getwd(struct vfs_handle_struct
*handle
)
948 const char *cwd
= ceph_getcwd(handle
->data
);
949 DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle
, cwd
);
950 return SMB_STRDUP(cwd
);
953 static int strict_allocate_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
955 off_t space_to_write
;
956 uint64_t space_avail
;
957 uint64_t bsize
,dfree
,dsize
;
960 SMB_STRUCT_STAT
*pst
;
962 status
= vfs_stat_fsp(fsp
);
963 if (!NT_STATUS_IS_OK(status
)) {
966 pst
= &fsp
->fsp_name
->st
;
969 if (S_ISFIFO(pst
->st_ex_mode
))
973 if (pst
->st_ex_size
== len
)
976 /* Shrink - just ftruncate. */
977 if (pst
->st_ex_size
> len
)
978 return ftruncate(fsp
->fh
->fd
, len
);
980 space_to_write
= len
- pst
->st_ex_size
;
982 /* for allocation try fallocate first. This can fail on some
983 platforms e.g. when the filesystem doesn't support it and no
984 emulation is being done by the libc (like on AIX with JFS1). In that
985 case we do our own emulation. fallocate implementations can
986 return ENOTSUP or EINVAL in cases like that. */
987 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
988 if (ret
== -1 && errno
== ENOSPC
) {
994 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
995 "error %d. Falling back to slow manual allocation\n", errno
));
997 /* available disk space is enough or not? */
999 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
1000 /* space_avail is 1k blocks */
1001 if (space_avail
== (uint64_t)-1 ||
1002 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1007 /* Write out the real space on disk. */
1008 return vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1011 static int cephwrap_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1018 DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle
, fsp
, llu(len
));
1020 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
1021 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1025 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1026 sys_ftruncate if the system supports it. Then I discovered that
1027 you can have some filesystems that support ftruncate
1028 expansion and some that don't! On Linux fat can't do
1029 ftruncate extend but ext2 can. */
1031 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1035 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1036 extend a file with ftruncate. Provide alternate implementation
1038 currpos
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
1039 if (currpos
== -1) {
1043 /* Do an fstat to see if the file is longer than the requested
1044 size in which case the ftruncate above should have
1045 succeeded or shorter, in which case seek to len - 1 and
1046 write 1 byte of zero */
1047 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1052 if (S_ISFIFO(st
.st_ex_mode
)) {
1058 if (st
.st_ex_size
== len
) {
1063 if (st
.st_ex_size
> len
) {
1064 /* the sys_ftruncate should have worked */
1068 if (SMB_VFS_LSEEK(fsp
, len
-1, SEEK_SET
) != len
-1)
1071 if (SMB_VFS_WRITE(fsp
, &c
, 1)!=1)
1074 /* Seek to where we were */
1075 if (SMB_VFS_LSEEK(fsp
, currpos
, SEEK_SET
) != currpos
)
1084 static bool cephwrap_lock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1086 DBG_DEBUG("[CEPH] lock\n");
1090 static int cephwrap_kernel_flock(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1091 uint32_t share_mode
, uint32_t access_mask
)
1093 DBG_DEBUG("[CEPH] kernel_flock\n");
1095 * We must return zero here and pretend all is good.
1096 * One day we might have this in CEPH.
1101 static bool cephwrap_getlock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1103 DBG_DEBUG("[CEPH] getlock returning false and errno=0\n");
1110 * We cannot let this fall through to the default, because the file might only
1111 * be accessible from libceph (which is a user-space client) but the fd might
1112 * be for some file the kernel knows about.
1114 static int cephwrap_linux_setlease(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1119 DBG_DEBUG("[CEPH] linux_setlease\n");
1124 static int cephwrap_symlink(struct vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
1127 DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle
, oldpath
, newpath
);
1128 result
= ceph_symlink(handle
->data
, oldpath
, newpath
);
1129 DBG_DEBUG("[CEPH] symlink(...) = %d\n", result
);
1130 WRAP_RETURN(result
);
1133 static int cephwrap_readlink(struct vfs_handle_struct
*handle
, const char *path
, char *buf
, size_t bufsiz
)
1136 DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle
, path
, buf
, llu(bufsiz
));
1137 result
= ceph_readlink(handle
->data
, path
, buf
, bufsiz
);
1138 DBG_DEBUG("[CEPH] readlink(...) = %d\n", result
);
1139 WRAP_RETURN(result
);
1142 static int cephwrap_link(struct vfs_handle_struct
*handle
, const char *oldpath
, const char *newpath
)
1145 DBG_DEBUG("[CEPH] link(%p, %s, %s)\n", handle
, oldpath
, newpath
);
1146 result
= ceph_link(handle
->data
, oldpath
, newpath
);
1147 DBG_DEBUG("[CEPH] link(...) = %d\n", result
);
1148 WRAP_RETURN(result
);
1151 static int cephwrap_mknod(struct vfs_handle_struct
*handle
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
1154 DBG_DEBUG("[CEPH] mknod(%p, %s)\n", handle
, pathname
);
1155 result
= ceph_mknod(handle
->data
, pathname
, mode
, dev
);
1156 DBG_DEBUG("[CEPH] mknod(...) = %d\n", result
);
1157 WRAP_RETURN(result
);
1161 * This is a simple version of real-path ... a better version is needed to
1162 * ask libceph about symbolic links.
1164 static char *cephwrap_realpath(struct vfs_handle_struct
*handle
, const char *path
)
1167 size_t len
= strlen(path
);
1169 result
= SMB_MALLOC_ARRAY(char, PATH_MAX
+1);
1170 if (len
&& (path
[0] == '/')) {
1171 int r
= asprintf(&result
, "%s", path
);
1172 if (r
< 0) return NULL
;
1173 } else if ((len
>= 2) && (path
[0] == '.') && (path
[1] == '/')) {
1175 int r
= asprintf(&result
, "%s",
1176 handle
->conn
->connectpath
);
1177 if (r
< 0) return NULL
;
1179 int r
= asprintf(&result
, "%s/%s",
1180 handle
->conn
->connectpath
, &path
[2]);
1181 if (r
< 0) return NULL
;
1184 int r
= asprintf(&result
, "%s/%s",
1185 handle
->conn
->connectpath
, path
);
1186 if (r
< 0) return NULL
;
1188 DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle
, path
, result
);
1192 static int cephwrap_chflags(struct vfs_handle_struct
*handle
, const char *path
,
1199 static int cephwrap_get_real_filename(struct vfs_handle_struct
*handle
,
1202 TALLOC_CTX
*mem_ctx
,
1206 * Don't fall back to get_real_filename so callers can differentiate
1207 * between a full directory scan and an actual case-insensitive stat.
1213 static const char *cephwrap_connectpath(struct vfs_handle_struct
*handle
,
1216 return handle
->conn
->connectpath
;
1219 /****************************************************************
1220 Extended attribute operations.
1221 *****************************************************************/
1223 static ssize_t
cephwrap_getxattr(struct vfs_handle_struct
*handle
,const char *path
, const char *name
, void *value
, size_t size
)
1226 DBG_DEBUG("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle
, path
, name
, value
, llu(size
));
1227 ret
= ceph_getxattr(handle
->data
, path
, name
, value
, size
);
1228 DBG_DEBUG("[CEPH] getxattr(...) = %d\n", ret
);
1232 return (ssize_t
)ret
;
1236 static ssize_t
cephwrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
1239 DBG_DEBUG("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle
, fsp
, name
, value
, llu(size
));
1240 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1241 ret
= ceph_fgetxattr(handle
->data
, fsp
->fh
->fd
, name
, value
, size
);
1243 ret
= ceph_getxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
);
1245 DBG_DEBUG("[CEPH] fgetxattr(...) = %d\n", ret
);
1249 return (ssize_t
)ret
;
1253 static ssize_t
cephwrap_listxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
1256 DBG_DEBUG("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle
, path
, list
, llu(size
));
1257 ret
= ceph_listxattr(handle
->data
, path
, list
, size
);
1258 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1262 return (ssize_t
)ret
;
1267 static ssize_t
cephwrap_llistxattr(struct vfs_handle_struct
*handle
, const char *path
, char *list
, size_t size
)
1270 DBG_DEBUG("[CEPH] llistxattr(%p, %s, %p, %llu)\n", handle
, path
, list
, llu(size
));
1271 ret
= ceph_llistxattr(handle
->data
, path
, list
, size
);
1272 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1276 return (ssize_t
)ret
;
1281 static ssize_t
cephwrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
1284 DBG_DEBUG("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle
, fsp
, list
, llu(size
));
1285 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1286 ret
= ceph_flistxattr(handle
->data
, fsp
->fh
->fd
, list
, size
);
1288 ret
= ceph_listxattr(handle
->data
, fsp
->fsp_name
->base_name
, list
, size
);
1290 DBG_DEBUG("[CEPH] flistxattr(...) = %d\n", ret
);
1294 return (ssize_t
)ret
;
1298 static int cephwrap_removexattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
)
1301 DBG_DEBUG("[CEPH] removexattr(%p, %s, %s)\n", handle
, path
, name
);
1302 ret
= ceph_removexattr(handle
->data
, path
, name
);
1303 DBG_DEBUG("[CEPH] removexattr(...) = %d\n", ret
);
1307 static int cephwrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
1310 DBG_DEBUG("[CEPH] fremovexattr(%p, %p, %s)\n", handle
, fsp
, name
);
1311 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1312 ret
= ceph_fremovexattr(handle
->data
, fsp
->fh
->fd
, name
);
1314 ret
= ceph_removexattr(handle
->data
, fsp
->fsp_name
->base_name
, name
);
1316 DBG_DEBUG("[CEPH] fremovexattr(...) = %d\n", ret
);
1320 static int cephwrap_setxattr(struct vfs_handle_struct
*handle
, const char *path
, const char *name
, const void *value
, size_t size
, int flags
)
1323 DBG_DEBUG("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle
, path
, name
, value
, llu(size
), flags
);
1324 ret
= ceph_setxattr(handle
->data
, path
, name
, value
, size
, flags
);
1325 DBG_DEBUG("[CEPH] setxattr(...) = %d\n", ret
);
1329 static int cephwrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
1332 DBG_DEBUG("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle
, fsp
, name
, value
, llu(size
), flags
);
1333 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1334 ret
= ceph_fsetxattr(handle
->data
, fsp
->fh
->fd
,
1335 name
, value
, size
, flags
);
1337 ret
= ceph_setxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
1339 DBG_DEBUG("[CEPH] fsetxattr(...) = %d\n", ret
);
1343 static bool cephwrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
1347 * We do not support AIO yet.
1350 DBG_DEBUG("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle
, fsp
);
1355 static struct vfs_fn_pointers ceph_fns
= {
1356 /* Disk operations */
1358 .connect_fn
= cephwrap_connect
,
1359 .disconnect_fn
= cephwrap_disconnect
,
1360 .disk_free_fn
= cephwrap_disk_free
,
1361 .get_quota_fn
= cephwrap_get_quota
,
1362 .set_quota_fn
= cephwrap_set_quota
,
1363 .statvfs_fn
= cephwrap_statvfs
,
1365 /* Directory operations */
1367 .opendir_fn
= cephwrap_opendir
,
1368 .fdopendir_fn
= cephwrap_fdopendir
,
1369 .readdir_fn
= cephwrap_readdir
,
1370 .seekdir_fn
= cephwrap_seekdir
,
1371 .telldir_fn
= cephwrap_telldir
,
1372 .rewind_dir_fn
= cephwrap_rewinddir
,
1373 .mkdir_fn
= cephwrap_mkdir
,
1374 .rmdir_fn
= cephwrap_rmdir
,
1375 .closedir_fn
= cephwrap_closedir
,
1377 /* File operations */
1379 .open_fn
= cephwrap_open
,
1380 .close_fn
= cephwrap_close
,
1381 .read_fn
= cephwrap_read
,
1382 .pread_fn
= cephwrap_pread
,
1383 .write_fn
= cephwrap_write
,
1384 .pwrite_fn
= cephwrap_pwrite
,
1385 .lseek_fn
= cephwrap_lseek
,
1386 .sendfile_fn
= cephwrap_sendfile
,
1387 .recvfile_fn
= cephwrap_recvfile
,
1388 .rename_fn
= cephwrap_rename
,
1389 .fsync_fn
= cephwrap_fsync
,
1390 .stat_fn
= cephwrap_stat
,
1391 .fstat_fn
= cephwrap_fstat
,
1392 .lstat_fn
= cephwrap_lstat
,
1393 .unlink_fn
= cephwrap_unlink
,
1394 .chmod_fn
= cephwrap_chmod
,
1395 .fchmod_fn
= cephwrap_fchmod
,
1396 .chown_fn
= cephwrap_chown
,
1397 .fchown_fn
= cephwrap_fchown
,
1398 .lchown_fn
= cephwrap_lchown
,
1399 .chdir_fn
= cephwrap_chdir
,
1400 .getwd_fn
= cephwrap_getwd
,
1401 .ntimes_fn
= cephwrap_ntimes
,
1402 .ftruncate_fn
= cephwrap_ftruncate
,
1403 .lock_fn
= cephwrap_lock
,
1404 .kernel_flock_fn
= cephwrap_kernel_flock
,
1405 .linux_setlease_fn
= cephwrap_linux_setlease
,
1406 .getlock_fn
= cephwrap_getlock
,
1407 .symlink_fn
= cephwrap_symlink
,
1408 .readlink_fn
= cephwrap_readlink
,
1409 .link_fn
= cephwrap_link
,
1410 .mknod_fn
= cephwrap_mknod
,
1411 .realpath_fn
= cephwrap_realpath
,
1412 .chflags_fn
= cephwrap_chflags
,
1413 .get_real_filename_fn
= cephwrap_get_real_filename
,
1414 .connectpath_fn
= cephwrap_connectpath
,
1416 /* EA operations. */
1417 .getxattr_fn
= cephwrap_getxattr
,
1418 .fgetxattr_fn
= cephwrap_fgetxattr
,
1419 .listxattr_fn
= cephwrap_listxattr
,
1420 .flistxattr_fn
= cephwrap_flistxattr
,
1421 .removexattr_fn
= cephwrap_removexattr
,
1422 .fremovexattr_fn
= cephwrap_fremovexattr
,
1423 .setxattr_fn
= cephwrap_setxattr
,
1424 .fsetxattr_fn
= cephwrap_fsetxattr
,
1426 /* Posix ACL Operations */
1427 .sys_acl_get_file_fn
= posixacl_xattr_acl_get_file
,
1428 .sys_acl_get_fd_fn
= posixacl_xattr_acl_get_fd
,
1429 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
1430 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
1431 .sys_acl_set_file_fn
= posixacl_xattr_acl_set_file
,
1432 .sys_acl_set_fd_fn
= posixacl_xattr_acl_set_fd
,
1433 .sys_acl_delete_def_file_fn
= posixacl_xattr_acl_delete_def_file
,
1435 /* aio operations */
1436 .aio_force_fn
= cephwrap_aio_force
,
1439 NTSTATUS
vfs_ceph_init(void);
1440 NTSTATUS
vfs_ceph_init(void)
1442 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,