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
)
88 int snum
= SNUM(handle
->conn
);
89 const char *conf_file
;
93 handle
->data
= cmount
; /* We have been here before */
98 /* if config_file and/or user_id are NULL, ceph will use defaults */
99 conf_file
= lp_parm_const_string(snum
, "ceph", "config_file", NULL
);
100 user_id
= lp_parm_const_string(snum
, "ceph", "user_id", NULL
);
102 DBG_DEBUG("[CEPH] calling: ceph_create\n");
103 ret
= ceph_create(&cmount
, user_id
);
108 DBG_DEBUG("[CEPH] calling: ceph_conf_read_file with %s\n",
109 (conf_file
== NULL
? "default path" : conf_file
));
110 ret
= ceph_conf_read_file(cmount
, conf_file
);
115 DBG_DEBUG("[CEPH] calling: ceph_conf_get\n");
116 ret
= ceph_conf_get(cmount
, "log file", buf
, sizeof(buf
));
121 DBG_DEBUG("[CEPH] calling: ceph_mount\n");
122 ret
= ceph_mount(cmount
, NULL
);
128 * encode mount context/state into our vfs/connection holding structure
129 * cmount is a ceph_mount_t*
131 handle
->data
= cmount
;
137 ceph_release(cmount
);
141 * Handle the error correctly. Ceph returns -errno.
143 DBG_DEBUG("[CEPH] Error return: %s\n", strerror(-ret
));
147 static void cephwrap_disconnect(struct vfs_handle_struct
*handle
)
152 DBG_ERR("[CEPH] Error, ceph not mounted\n");
156 /* Should we unmount/shutdown? Only if the last disconnect? */
158 DBG_DEBUG("[CEPH] Not shuting down CEPH because still more connections\n");
162 ret
= ceph_unmount(cmount
);
164 DBG_ERR("[CEPH] failed to unmount: %s\n", strerror(-ret
));
167 ret
= ceph_release(cmount
);
169 DBG_ERR("[CEPH] failed to release: %s\n", strerror(-ret
));
172 cmount
= NULL
; /* Make it safe */
175 /* Disk operations */
177 static uint64_t cephwrap_disk_free(struct vfs_handle_struct
*handle
,
178 const struct smb_filename
*smb_fname
,
183 struct statvfs statvfs_buf
;
186 if (!(ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
,
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 struct smb_filename
*smb_fname
,
205 enum SMB_QUOTA_TYPE qtype
,
209 /* libceph: Ceph does not implement this */
211 /* was ifdef HAVE_SYS_QUOTAS */
214 ret
= ceph_get_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
228 static int cephwrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
230 /* libceph: Ceph does not implement this */
232 /* was ifdef HAVE_SYS_QUOTAS */
235 ret
= ceph_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
243 WRAP_RETURN(-ENOSYS
);
247 static int cephwrap_statvfs(struct vfs_handle_struct
*handle
,
248 const struct smb_filename
*smb_fname
,
249 vfs_statvfs_struct
*statbuf
)
251 struct statvfs statvfs_buf
;
254 ret
= ceph_statfs(handle
->data
, smb_fname
->base_name
, &statvfs_buf
);
258 statbuf
->OptimalTransferSize
= statvfs_buf
.f_frsize
;
259 statbuf
->BlockSize
= statvfs_buf
.f_bsize
;
260 statbuf
->TotalBlocks
= statvfs_buf
.f_blocks
;
261 statbuf
->BlocksAvail
= statvfs_buf
.f_bfree
;
262 statbuf
->UserBlocksAvail
= statvfs_buf
.f_bavail
;
263 statbuf
->TotalFileNodes
= statvfs_buf
.f_files
;
264 statbuf
->FreeFileNodes
= statvfs_buf
.f_ffree
;
265 statbuf
->FsIdentifier
= statvfs_buf
.f_fsid
;
266 DBG_DEBUG("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
267 (long int)statvfs_buf
.f_bsize
, (long int)statvfs_buf
.f_blocks
,
268 (long int)statvfs_buf
.f_bfree
, (long int)statvfs_buf
.f_bavail
);
273 /* Directory operations */
275 static DIR *cephwrap_opendir(struct vfs_handle_struct
*handle
,
276 const struct smb_filename
*smb_fname
,
277 const char *mask
, uint32_t attr
)
280 struct ceph_dir_result
*result
;
281 DBG_DEBUG("[CEPH] opendir(%p, %s)\n", handle
, smb_fname
->base_name
);
283 /* Returns NULL if it does not exist or there are problems ? */
284 ret
= ceph_opendir(handle
->data
, smb_fname
->base_name
, &result
);
287 errno
= -ret
; /* We return result which is NULL in this case */
290 DBG_DEBUG("[CEPH] opendir(...) = %d\n", ret
);
291 return (DIR *) result
;
294 static DIR *cephwrap_fdopendir(struct vfs_handle_struct
*handle
,
295 struct files_struct
*fsp
,
300 struct ceph_dir_result
*result
;
301 DBG_DEBUG("[CEPH] fdopendir(%p, %p)\n", handle
, fsp
);
303 ret
= ceph_opendir(handle
->data
, fsp
->fsp_name
->base_name
, &result
);
306 errno
= -ret
; /* We return result which is NULL in this case */
309 DBG_DEBUG("[CEPH] fdopendir(...) = %d\n", ret
);
310 return (DIR *) result
;
313 static struct dirent
*cephwrap_readdir(struct vfs_handle_struct
*handle
,
315 SMB_STRUCT_STAT
*sbuf
)
317 struct dirent
*result
;
319 DBG_DEBUG("[CEPH] readdir(%p, %p)\n", handle
, dirp
);
320 result
= ceph_readdir(handle
->data
, (struct ceph_dir_result
*) dirp
);
321 DBG_DEBUG("[CEPH] readdir(...) = %p\n", result
);
323 /* Default Posix readdir() does not give us stat info.
324 * Set to invalid to indicate we didn't return this info. */
326 SET_STAT_INVALID(*sbuf
);
330 static void cephwrap_seekdir(struct vfs_handle_struct
*handle
, DIR *dirp
, long offset
)
332 DBG_DEBUG("[CEPH] seekdir(%p, %p, %ld)\n", handle
, dirp
, offset
);
333 ceph_seekdir(handle
->data
, (struct ceph_dir_result
*) dirp
, offset
);
336 static long cephwrap_telldir(struct vfs_handle_struct
*handle
, DIR *dirp
)
339 DBG_DEBUG("[CEPH] telldir(%p, %p)\n", handle
, dirp
);
340 ret
= ceph_telldir(handle
->data
, (struct ceph_dir_result
*) dirp
);
341 DBG_DEBUG("[CEPH] telldir(...) = %ld\n", ret
);
345 static void cephwrap_rewinddir(struct vfs_handle_struct
*handle
, DIR *dirp
)
347 DBG_DEBUG("[CEPH] rewinddir(%p, %p)\n", handle
, dirp
);
348 ceph_rewinddir(handle
->data
, (struct ceph_dir_result
*) dirp
);
351 static int cephwrap_mkdir(struct vfs_handle_struct
*handle
,
352 const struct smb_filename
*smb_fname
,
356 bool has_dacl
= False
;
358 const char *path
= smb_fname
->base_name
;
360 DBG_DEBUG("[CEPH] mkdir(%p, %s)\n", handle
, path
);
362 if (lp_inherit_acls(SNUM(handle
->conn
))
363 && parent_dirname(talloc_tos(), path
, &parent
, NULL
)
364 && (has_dacl
= directory_has_default_acl(handle
->conn
, parent
)))
369 result
= ceph_mkdir(handle
->data
, path
, mode
);
372 * Note. This order is important
376 } else if (result
== 0 && !has_dacl
) {
378 * We need to do this as the default behavior of POSIX ACLs
379 * is to set the mask to be the requested group permission
380 * bits, not the group permission bits to be the requested
381 * group permission bits. This is not what we want, as it will
382 * mess up any inherited ACL bits that were set. JRA.
384 int saved_errno
= errno
; /* We may get ENOSYS */
385 if ((SMB_VFS_CHMOD_ACL(handle
->conn
, smb_fname
, mode
) == -1) &&
394 static int cephwrap_rmdir(struct vfs_handle_struct
*handle
,
395 const struct smb_filename
*smb_fname
)
399 DBG_DEBUG("[CEPH] rmdir(%p, %s)\n", handle
, smb_fname
->base_name
);
400 result
= ceph_rmdir(handle
->data
, smb_fname
->base_name
);
401 DBG_DEBUG("[CEPH] rmdir(...) = %d\n", result
);
405 static int cephwrap_closedir(struct vfs_handle_struct
*handle
, DIR *dirp
)
409 DBG_DEBUG("[CEPH] closedir(%p, %p)\n", handle
, dirp
);
410 result
= ceph_closedir(handle
->data
, (struct ceph_dir_result
*) dirp
);
411 DBG_DEBUG("[CEPH] closedir(...) = %d\n", result
);
415 /* File operations */
417 static int cephwrap_open(struct vfs_handle_struct
*handle
,
418 struct smb_filename
*smb_fname
,
419 files_struct
*fsp
, int flags
, mode_t mode
)
421 int result
= -ENOENT
;
422 DBG_DEBUG("[CEPH] open(%p, %s, %p, %d, %d)\n", handle
,
423 smb_fname_str_dbg(smb_fname
), fsp
, flags
, mode
);
425 if (smb_fname
->stream_name
) {
429 result
= ceph_open(handle
->data
, smb_fname
->base_name
, flags
, mode
);
431 DBG_DEBUG("[CEPH] open(...) = %d\n", result
);
435 static int cephwrap_close(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
439 DBG_DEBUG("[CEPH] close(%p, %p)\n", handle
, fsp
);
440 result
= ceph_close(handle
->data
, fsp
->fh
->fd
);
441 DBG_DEBUG("[CEPH] close(...) = %d\n", result
);
446 static ssize_t
cephwrap_read(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
, size_t n
)
450 DBG_DEBUG("[CEPH] read(%p, %p, %p, %llu)\n", handle
, fsp
, data
, llu(n
));
452 /* Using -1 for the offset means read/write rather than pread/pwrite */
453 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, -1);
454 DBG_DEBUG("[CEPH] read(...) = %llu\n", llu(result
));
458 static ssize_t
cephwrap_pread(struct vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
459 size_t n
, off_t offset
)
463 DBG_DEBUG("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
465 result
= ceph_read(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
466 DBG_DEBUG("[CEPH] pread(...) = %llu\n", llu(result
));
471 static ssize_t
cephwrap_write(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
, size_t n
)
475 DBG_DEBUG("[CEPH] write(%p, %p, %p, %llu)\n", handle
, fsp
, data
, llu(n
));
477 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, -1);
479 DBG_DEBUG("[CEPH] write(...) = %llu\n", llu(result
));
483 fsp
->fh
->pos
+= result
;
487 static ssize_t
cephwrap_pwrite(struct vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
488 size_t n
, off_t offset
)
492 DBG_DEBUG("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle
, fsp
, data
, llu(n
), llu(offset
));
493 result
= ceph_write(handle
->data
, fsp
->fh
->fd
, data
, n
, offset
);
494 DBG_DEBUG("[CEPH] pwrite(...) = %llu\n", llu(result
));
498 static off_t
cephwrap_lseek(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
502 DBG_DEBUG("[CEPH] cephwrap_lseek\n");
503 /* Cope with 'stat' file opens. */
504 if (fsp
->fh
->fd
!= -1) {
505 result
= ceph_lseek(handle
->data
, fsp
->fh
->fd
, offset
, whence
);
510 static ssize_t
cephwrap_sendfile(struct vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
511 off_t offset
, size_t n
)
514 * We cannot support sendfile because libceph is in user space.
516 DBG_DEBUG("[CEPH] cephwrap_sendfile\n");
521 static ssize_t
cephwrap_recvfile(struct vfs_handle_struct
*handle
,
528 * We cannot support recvfile because libceph is in user space.
530 DBG_DEBUG("[CEPH] cephwrap_recvfile\n");
535 static int cephwrap_rename(struct vfs_handle_struct
*handle
,
536 const struct smb_filename
*smb_fname_src
,
537 const struct smb_filename
*smb_fname_dst
)
540 DBG_DEBUG("[CEPH] cephwrap_rename\n");
541 if (smb_fname_src
->stream_name
|| smb_fname_dst
->stream_name
) {
546 result
= ceph_rename(handle
->data
, smb_fname_src
->base_name
, smb_fname_dst
->base_name
);
550 static int cephwrap_fsync(struct vfs_handle_struct
*handle
, files_struct
*fsp
)
553 DBG_DEBUG("[CEPH] cephwrap_fsync\n");
554 result
= ceph_fsync(handle
->data
, fsp
->fh
->fd
, false);
558 #ifdef HAVE_CEPH_STATX
559 #define SAMBA_STATX_ATTR_MASK (CEPH_STATX_BASIC_STATS|CEPH_STATX_BTIME)
561 static void init_stat_ex_from_ceph_statx(struct stat_ex
*dst
, const struct ceph_statx
*stx
)
563 if ((stx
->stx_mask
& SAMBA_STATX_ATTR_MASK
) != SAMBA_STATX_ATTR_MASK
)
564 DBG_WARNING("%s: stx->stx_mask is incorrect (wanted %x, got %x)",
565 __func__
, SAMBA_STATX_ATTR_MASK
, stx
->stx_mask
);
567 dst
->st_ex_dev
= stx
->stx_dev
;
568 dst
->st_ex_rdev
= stx
->stx_rdev
;
569 dst
->st_ex_ino
= stx
->stx_ino
;
570 dst
->st_ex_mode
= stx
->stx_mode
;
571 dst
->st_ex_uid
= stx
->stx_uid
;
572 dst
->st_ex_gid
= stx
->stx_gid
;
573 dst
->st_ex_size
= stx
->stx_size
;
574 dst
->st_ex_nlink
= stx
->stx_nlink
;
575 dst
->st_ex_atime
= stx
->stx_atime
;
576 dst
->st_ex_btime
= stx
->stx_btime
;
577 dst
->st_ex_ctime
= stx
->stx_ctime
;
578 dst
->st_ex_mtime
= stx
->stx_mtime
;
579 dst
->st_ex_calculated_birthtime
= false;
580 dst
->st_ex_blksize
= stx
->stx_blksize
;
581 dst
->st_ex_blocks
= stx
->stx_blocks
;
584 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
585 struct smb_filename
*smb_fname
)
588 struct ceph_statx stx
;
590 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
592 if (smb_fname
->stream_name
) {
597 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
598 SAMBA_STATX_ATTR_MASK
, 0);
599 DBG_DEBUG("[CEPH] statx(...) = %d\n", result
);
603 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
604 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
605 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
606 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
607 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
608 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
609 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
610 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
612 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
613 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
617 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
620 struct ceph_statx stx
;
622 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
623 result
= ceph_fstatx(handle
->data
, fsp
->fh
->fd
, &stx
,
624 SAMBA_STATX_ATTR_MASK
, 0);
625 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
629 DBG_DEBUG("[CEPH]\tstx = {dev = %llx, ino = %llu, mode = 0x%x, nlink = %llu, "
630 "uid = %d, gid = %d, rdev = %llx, size = %llu, blksize = %llu, "
631 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu, btime = %llu}\n",
632 llu(stx
.stx_dev
), llu(stx
.stx_ino
), stx
.stx_mode
,
633 llu(stx
.stx_nlink
), stx
.stx_uid
, stx
.stx_gid
, llu(stx
.stx_rdev
),
634 llu(stx
.stx_size
), llu(stx
.stx_blksize
),
635 llu(stx
.stx_blocks
), llu(stx
.stx_atime
.tv_sec
), llu(stx
.stx_mtime
.tv_sec
),
636 llu(stx
.stx_ctime
.tv_sec
), llu(stx
.stx_btime
.tv_sec
));
638 init_stat_ex_from_ceph_statx(sbuf
, &stx
);
639 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
643 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
644 struct smb_filename
*smb_fname
)
647 struct ceph_statx stx
;
649 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
651 if (smb_fname
->stream_name
) {
656 result
= ceph_statx(handle
->data
, smb_fname
->base_name
, &stx
,
657 SAMBA_STATX_ATTR_MASK
, AT_SYMLINK_NOFOLLOW
);
658 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
662 init_stat_ex_from_ceph_statx(&smb_fname
->st
, &stx
);
666 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
667 const struct smb_filename
*smb_fname
,
668 struct smb_file_time
*ft
)
670 struct ceph_statx stx
= { 0 };
674 if (!null_timespec(ft
->atime
)) {
675 stx
.stx_atime
= ft
->atime
;
676 mask
|= CEPH_SETATTR_ATIME
;
678 if (!null_timespec(ft
->mtime
)) {
679 stx
.stx_mtime
= ft
->mtime
;
680 mask
|= CEPH_SETATTR_MTIME
;
682 if (!null_timespec(ft
->create_time
)) {
683 stx
.stx_btime
= ft
->create_time
;
684 mask
|= CEPH_SETATTR_BTIME
;
691 result
= ceph_setattrx(handle
->data
, smb_fname
->base_name
, &stx
, mask
, 0);
692 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
693 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
694 ft
->create_time
.tv_sec
, result
);
698 #else /* HAVE_CEPH_STATX */
700 static int cephwrap_stat(struct vfs_handle_struct
*handle
,
701 struct smb_filename
*smb_fname
)
706 DBG_DEBUG("[CEPH] stat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
708 if (smb_fname
->stream_name
) {
713 result
= ceph_stat(handle
->data
, smb_fname
->base_name
, (struct stat
*) &stbuf
);
714 DBG_DEBUG("[CEPH] stat(...) = %d\n", result
);
718 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
719 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
720 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
721 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
722 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
723 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
725 init_stat_ex_from_stat(
726 &smb_fname
->st
, &stbuf
,
727 lp_fake_directory_create_times(SNUM(handle
->conn
)));
728 DBG_DEBUG("[CEPH] mode = 0x%x\n", smb_fname
->st
.st_ex_mode
);
732 static int cephwrap_fstat(struct vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
737 DBG_DEBUG("[CEPH] fstat(%p, %d)\n", handle
, fsp
->fh
->fd
);
738 result
= ceph_fstat(handle
->data
, fsp
->fh
->fd
, (struct stat
*) &stbuf
);
739 DBG_DEBUG("[CEPH] fstat(...) = %d\n", result
);
743 DBG_DEBUG("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
744 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
745 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
746 llu(stbuf
.st_dev
), llu(stbuf
.st_ino
), stbuf
.st_mode
, llu(stbuf
.st_nlink
),
747 stbuf
.st_uid
, stbuf
.st_gid
, llu(stbuf
.st_rdev
), llu(stbuf
.st_size
), llu(stbuf
.st_blksize
),
748 llu(stbuf
.st_blocks
), llu(stbuf
.st_atime
), llu(stbuf
.st_mtime
), llu(stbuf
.st_ctime
));
751 init_stat_ex_from_stat(
753 lp_fake_directory_create_times(SNUM(handle
->conn
)));
754 DBG_DEBUG("[CEPH] mode = 0x%x\n", sbuf
->st_ex_mode
);
758 static int cephwrap_lstat(struct vfs_handle_struct
*handle
,
759 struct smb_filename
*smb_fname
)
764 DBG_DEBUG("[CEPH] lstat(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
766 if (smb_fname
->stream_name
) {
771 result
= ceph_lstat(handle
->data
, smb_fname
->base_name
, &stbuf
);
772 DBG_DEBUG("[CEPH] lstat(...) = %d\n", result
);
776 init_stat_ex_from_stat(
777 &smb_fname
->st
, &stbuf
,
778 lp_fake_directory_create_times(SNUM(handle
->conn
)));
782 static int cephwrap_ntimes(struct vfs_handle_struct
*handle
,
783 const struct smb_filename
*smb_fname
,
784 struct smb_file_time
*ft
)
789 if (null_timespec(ft
->atime
)) {
790 buf
.actime
= smb_fname
->st
.st_ex_atime
.tv_sec
;
792 buf
.actime
= ft
->atime
.tv_sec
;
794 if (null_timespec(ft
->mtime
)) {
795 buf
.modtime
= smb_fname
->st
.st_ex_mtime
.tv_sec
;
797 buf
.modtime
= ft
->mtime
.tv_sec
;
799 if (!null_timespec(ft
->create_time
)) {
800 set_create_timespec_ea(handle
->conn
, smb_fname
,
803 if (buf
.actime
== smb_fname
->st
.st_ex_atime
.tv_sec
&&
804 buf
.modtime
== smb_fname
->st
.st_ex_mtime
.tv_sec
) {
808 result
= ceph_utime(handle
->data
, smb_fname
->base_name
, &buf
);
809 DBG_DEBUG("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle
, smb_fname_str_dbg(smb_fname
),
810 ft
->mtime
.tv_sec
, ft
->atime
.tv_sec
, ft
->ctime
.tv_sec
,
811 ft
->create_time
.tv_sec
, result
);
814 #endif /* HAVE_CEPH_STATX */
816 static int cephwrap_unlink(struct vfs_handle_struct
*handle
,
817 const struct smb_filename
*smb_fname
)
821 DBG_DEBUG("[CEPH] unlink(%p, %s)\n", handle
, smb_fname_str_dbg(smb_fname
));
822 if (smb_fname
->stream_name
) {
826 result
= ceph_unlink(handle
->data
, smb_fname
->base_name
);
827 DBG_DEBUG("[CEPH] unlink(...) = %d\n", result
);
831 static int cephwrap_chmod(struct vfs_handle_struct
*handle
,
832 const struct smb_filename
*smb_fname
,
837 DBG_DEBUG("[CEPH] chmod(%p, %s, %d)\n", handle
, smb_fname
->base_name
, mode
);
840 * We need to do this due to the fact that the default POSIX ACL
841 * chmod modifies the ACL *mask* for the group owner, not the
842 * group owner bits directly. JRA.
847 int saved_errno
= errno
; /* We might get ENOSYS */
848 result
= SMB_VFS_CHMOD_ACL(handle
->conn
,
854 /* Error - return the old errno. */
858 result
= ceph_chmod(handle
->data
, smb_fname
->base_name
, mode
);
859 DBG_DEBUG("[CEPH] chmod(...) = %d\n", result
);
863 static int cephwrap_fchmod(struct vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
867 DBG_DEBUG("[CEPH] fchmod(%p, %p, %d)\n", handle
, fsp
, mode
);
870 * We need to do this due to the fact that the default POSIX ACL
871 * chmod modifies the ACL *mask* for the group owner, not the
872 * group owner bits directly. JRA.
876 int saved_errno
= errno
; /* We might get ENOSYS */
877 if ((result
= SMB_VFS_FCHMOD_ACL(fsp
, mode
)) == 0) {
880 /* Error - return the old errno. */
884 #if defined(HAVE_FCHMOD)
885 result
= ceph_fchmod(handle
->data
, fsp
->fh
->fd
, mode
);
886 DBG_DEBUG("[CEPH] fchmod(...) = %d\n", result
);
894 static int cephwrap_chown(struct vfs_handle_struct
*handle
,
895 const struct smb_filename
*smb_fname
,
900 DBG_DEBUG("[CEPH] chown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
901 result
= ceph_chown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
902 DBG_DEBUG("[CEPH] chown(...) = %d\n", result
);
906 static int cephwrap_fchown(struct vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
911 DBG_DEBUG("[CEPH] fchown(%p, %p, %d, %d)\n", handle
, fsp
, uid
, gid
);
912 result
= ceph_fchown(handle
->data
, fsp
->fh
->fd
, uid
, gid
);
913 DBG_DEBUG("[CEPH] fchown(...) = %d\n", result
);
922 static int cephwrap_lchown(struct vfs_handle_struct
*handle
,
923 const struct smb_filename
*smb_fname
,
928 DBG_DEBUG("[CEPH] lchown(%p, %s, %d, %d)\n", handle
, smb_fname
->base_name
, uid
, gid
);
929 result
= ceph_lchown(handle
->data
, smb_fname
->base_name
, uid
, gid
);
930 DBG_DEBUG("[CEPH] lchown(...) = %d\n", result
);
934 static int cephwrap_chdir(struct vfs_handle_struct
*handle
,
935 const struct smb_filename
*smb_fname
)
938 DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle
, smb_fname
->base_name
);
939 result
= ceph_chdir(handle
->data
, smb_fname
->base_name
);
940 DBG_DEBUG("[CEPH] chdir(...) = %d\n", result
);
944 static struct smb_filename
*cephwrap_getwd(struct vfs_handle_struct
*handle
,
947 const char *cwd
= ceph_getcwd(handle
->data
);
948 DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle
, cwd
);
949 return synthetic_smb_fname(ctx
,
956 static int strict_allocate_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
958 off_t space_to_write
;
959 uint64_t space_avail
;
960 uint64_t bsize
,dfree
,dsize
;
963 SMB_STRUCT_STAT
*pst
;
965 status
= vfs_stat_fsp(fsp
);
966 if (!NT_STATUS_IS_OK(status
)) {
969 pst
= &fsp
->fsp_name
->st
;
972 if (S_ISFIFO(pst
->st_ex_mode
))
976 if (pst
->st_ex_size
== len
)
979 /* Shrink - just ftruncate. */
980 if (pst
->st_ex_size
> len
)
981 return ftruncate(fsp
->fh
->fd
, len
);
983 space_to_write
= len
- pst
->st_ex_size
;
985 /* for allocation try fallocate first. This can fail on some
986 platforms e.g. when the filesystem doesn't support it and no
987 emulation is being done by the libc (like on AIX with JFS1). In that
988 case we do our own emulation. fallocate implementations can
989 return ENOTSUP or EINVAL in cases like that. */
990 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
991 if (ret
== -1 && errno
== ENOSPC
) {
997 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
998 "error %d. Falling back to slow manual allocation\n", errno
));
1000 /* available disk space is enough or not? */
1002 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
1003 /* space_avail is 1k blocks */
1004 if (space_avail
== (uint64_t)-1 ||
1005 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
1010 /* Write out the real space on disk. */
1011 return vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
1014 static int cephwrap_ftruncate(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
1021 DBG_DEBUG("[CEPH] ftruncate(%p, %p, %llu\n", handle
, fsp
, llu(len
));
1023 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
1024 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
1028 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1029 sys_ftruncate if the system supports it. Then I discovered that
1030 you can have some filesystems that support ftruncate
1031 expansion and some that don't! On Linux fat can't do
1032 ftruncate extend but ext2 can. */
1034 result
= ceph_ftruncate(handle
->data
, fsp
->fh
->fd
, len
);
1038 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1039 extend a file with ftruncate. Provide alternate implementation
1041 currpos
= SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
);
1042 if (currpos
== -1) {
1046 /* Do an fstat to see if the file is longer than the requested
1047 size in which case the ftruncate above should have
1048 succeeded or shorter, in which case seek to len - 1 and
1049 write 1 byte of zero */
1050 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1055 if (S_ISFIFO(st
.st_ex_mode
)) {
1061 if (st
.st_ex_size
== len
) {
1066 if (st
.st_ex_size
> len
) {
1067 /* the sys_ftruncate should have worked */
1071 if (SMB_VFS_LSEEK(fsp
, len
-1, SEEK_SET
) != len
-1)
1074 if (SMB_VFS_WRITE(fsp
, &c
, 1)!=1)
1077 /* Seek to where we were */
1078 if (SMB_VFS_LSEEK(fsp
, currpos
, SEEK_SET
) != currpos
)
1087 static bool cephwrap_lock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
1089 DBG_DEBUG("[CEPH] lock\n");
1093 static int cephwrap_kernel_flock(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1094 uint32_t share_mode
, uint32_t access_mask
)
1096 DBG_DEBUG("[CEPH] kernel_flock\n");
1098 * We must return zero here and pretend all is good.
1099 * One day we might have this in CEPH.
1104 static bool cephwrap_getlock(struct vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
1106 DBG_DEBUG("[CEPH] getlock returning false and errno=0\n");
1113 * We cannot let this fall through to the default, because the file might only
1114 * be accessible from libceph (which is a user-space client) but the fd might
1115 * be for some file the kernel knows about.
1117 static int cephwrap_linux_setlease(struct vfs_handle_struct
*handle
, files_struct
*fsp
,
1122 DBG_DEBUG("[CEPH] linux_setlease\n");
1127 static int cephwrap_symlink(struct vfs_handle_struct
*handle
,
1128 const char *link_target
,
1129 const struct smb_filename
*new_smb_fname
)
1132 DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle
,
1134 new_smb_fname
->base_name
);
1135 result
= ceph_symlink(handle
->data
,
1137 new_smb_fname
->base_name
);
1138 DBG_DEBUG("[CEPH] symlink(...) = %d\n", result
);
1139 WRAP_RETURN(result
);
1142 static int cephwrap_readlink(struct vfs_handle_struct
*handle
,
1143 const struct smb_filename
*smb_fname
,
1148 DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle
,
1149 smb_fname
->base_name
, buf
, llu(bufsiz
));
1150 result
= ceph_readlink(handle
->data
, smb_fname
->base_name
, buf
, bufsiz
);
1151 DBG_DEBUG("[CEPH] readlink(...) = %d\n", result
);
1152 WRAP_RETURN(result
);
1155 static int cephwrap_link(struct vfs_handle_struct
*handle
,
1156 const struct smb_filename
*old_smb_fname
,
1157 const struct smb_filename
*new_smb_fname
)
1160 DBG_DEBUG("[CEPH] link(%p, %s, %s)\n", handle
,
1161 old_smb_fname
->base_name
,
1162 new_smb_fname
->base_name
);
1163 result
= ceph_link(handle
->data
,
1164 old_smb_fname
->base_name
,
1165 new_smb_fname
->base_name
);
1166 DBG_DEBUG("[CEPH] link(...) = %d\n", result
);
1167 WRAP_RETURN(result
);
1170 static int cephwrap_mknod(struct vfs_handle_struct
*handle
,
1171 const struct smb_filename
*smb_fname
,
1176 DBG_DEBUG("[CEPH] mknod(%p, %s)\n", handle
, smb_fname
->base_name
);
1177 result
= ceph_mknod(handle
->data
, smb_fname
->base_name
, mode
, dev
);
1178 DBG_DEBUG("[CEPH] mknod(...) = %d\n", result
);
1179 WRAP_RETURN(result
);
1183 * This is a simple version of real-path ... a better version is needed to
1184 * ask libceph about symbolic links.
1186 static struct smb_filename
*cephwrap_realpath(struct vfs_handle_struct
*handle
,
1188 const struct smb_filename
*smb_fname
)
1191 const char *path
= smb_fname
->base_name
;
1192 size_t len
= strlen(path
);
1193 struct smb_filename
*result_fname
= NULL
;
1195 result
= SMB_MALLOC_ARRAY(char, PATH_MAX
+1);
1196 if (len
&& (path
[0] == '/')) {
1197 int r
= asprintf(&result
, "%s", path
);
1198 if (r
< 0) return NULL
;
1199 } else if ((len
>= 2) && (path
[0] == '.') && (path
[1] == '/')) {
1201 int r
= asprintf(&result
, "%s",
1202 handle
->conn
->connectpath
);
1203 if (r
< 0) return NULL
;
1205 int r
= asprintf(&result
, "%s/%s",
1206 handle
->conn
->connectpath
, &path
[2]);
1207 if (r
< 0) return NULL
;
1210 int r
= asprintf(&result
, "%s/%s",
1211 handle
->conn
->connectpath
, path
);
1212 if (r
< 0) return NULL
;
1214 DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle
, path
, result
);
1215 result_fname
= synthetic_smb_fname(ctx
,
1221 return result_fname
;
1224 static int cephwrap_chflags(struct vfs_handle_struct
*handle
,
1225 const struct smb_filename
*smb_fname
,
1232 static int cephwrap_get_real_filename(struct vfs_handle_struct
*handle
,
1235 TALLOC_CTX
*mem_ctx
,
1239 * Don't fall back to get_real_filename so callers can differentiate
1240 * between a full directory scan and an actual case-insensitive stat.
1246 static const char *cephwrap_connectpath(struct vfs_handle_struct
*handle
,
1247 const struct smb_filename
*smb_fname
)
1249 return handle
->conn
->connectpath
;
1252 /****************************************************************
1253 Extended attribute operations.
1254 *****************************************************************/
1256 static ssize_t
cephwrap_getxattr(struct vfs_handle_struct
*handle
,
1257 const struct smb_filename
*smb_fname
,
1263 DBG_DEBUG("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle
,
1264 smb_fname
->base_name
, name
, value
, llu(size
));
1265 ret
= ceph_getxattr(handle
->data
,
1266 smb_fname
->base_name
, name
, value
, size
);
1267 DBG_DEBUG("[CEPH] getxattr(...) = %d\n", ret
);
1271 return (ssize_t
)ret
;
1275 static ssize_t
cephwrap_fgetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, void *value
, size_t size
)
1278 DBG_DEBUG("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle
, fsp
, name
, value
, llu(size
));
1279 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1280 ret
= ceph_fgetxattr(handle
->data
, fsp
->fh
->fd
, name
, value
, size
);
1282 ret
= ceph_getxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
);
1284 DBG_DEBUG("[CEPH] fgetxattr(...) = %d\n", ret
);
1288 return (ssize_t
)ret
;
1292 static ssize_t
cephwrap_listxattr(struct vfs_handle_struct
*handle
,
1293 const struct smb_filename
*smb_fname
,
1298 DBG_DEBUG("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle
,
1299 smb_fname
->base_name
, list
, llu(size
));
1300 ret
= ceph_listxattr(handle
->data
, smb_fname
->base_name
, list
, size
);
1301 DBG_DEBUG("[CEPH] listxattr(...) = %d\n", ret
);
1305 return (ssize_t
)ret
;
1309 static ssize_t
cephwrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
1312 DBG_DEBUG("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle
, fsp
, list
, llu(size
));
1313 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1314 ret
= ceph_flistxattr(handle
->data
, fsp
->fh
->fd
, list
, size
);
1316 ret
= ceph_listxattr(handle
->data
, fsp
->fsp_name
->base_name
, list
, size
);
1318 DBG_DEBUG("[CEPH] flistxattr(...) = %d\n", ret
);
1322 return (ssize_t
)ret
;
1326 static int cephwrap_removexattr(struct vfs_handle_struct
*handle
,
1327 const struct smb_filename
*smb_fname
,
1331 DBG_DEBUG("[CEPH] removexattr(%p, %s, %s)\n", handle
,
1332 smb_fname
->base_name
, name
);
1333 ret
= ceph_removexattr(handle
->data
, smb_fname
->base_name
, name
);
1334 DBG_DEBUG("[CEPH] removexattr(...) = %d\n", ret
);
1338 static int cephwrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
1341 DBG_DEBUG("[CEPH] fremovexattr(%p, %p, %s)\n", handle
, fsp
, name
);
1342 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1343 ret
= ceph_fremovexattr(handle
->data
, fsp
->fh
->fd
, name
);
1345 ret
= ceph_removexattr(handle
->data
, fsp
->fsp_name
->base_name
, name
);
1347 DBG_DEBUG("[CEPH] fremovexattr(...) = %d\n", ret
);
1351 static int cephwrap_setxattr(struct vfs_handle_struct
*handle
,
1352 const struct smb_filename
*smb_fname
,
1359 DBG_DEBUG("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle
,
1360 smb_fname
->base_name
, name
, value
, llu(size
), flags
);
1361 ret
= ceph_setxattr(handle
->data
, smb_fname
->base_name
,
1362 name
, value
, size
, flags
);
1363 DBG_DEBUG("[CEPH] setxattr(...) = %d\n", ret
);
1367 static int cephwrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
1370 DBG_DEBUG("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle
, fsp
, name
, value
, llu(size
), flags
);
1371 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1372 ret
= ceph_fsetxattr(handle
->data
, fsp
->fh
->fd
,
1373 name
, value
, size
, flags
);
1375 ret
= ceph_setxattr(handle
->data
, fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
1377 DBG_DEBUG("[CEPH] fsetxattr(...) = %d\n", ret
);
1381 static bool cephwrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
1385 * We do not support AIO yet.
1388 DBG_DEBUG("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle
, fsp
);
1393 static struct vfs_fn_pointers ceph_fns
= {
1394 /* Disk operations */
1396 .connect_fn
= cephwrap_connect
,
1397 .disconnect_fn
= cephwrap_disconnect
,
1398 .disk_free_fn
= cephwrap_disk_free
,
1399 .get_quota_fn
= cephwrap_get_quota
,
1400 .set_quota_fn
= cephwrap_set_quota
,
1401 .statvfs_fn
= cephwrap_statvfs
,
1403 /* Directory operations */
1405 .opendir_fn
= cephwrap_opendir
,
1406 .fdopendir_fn
= cephwrap_fdopendir
,
1407 .readdir_fn
= cephwrap_readdir
,
1408 .seekdir_fn
= cephwrap_seekdir
,
1409 .telldir_fn
= cephwrap_telldir
,
1410 .rewind_dir_fn
= cephwrap_rewinddir
,
1411 .mkdir_fn
= cephwrap_mkdir
,
1412 .rmdir_fn
= cephwrap_rmdir
,
1413 .closedir_fn
= cephwrap_closedir
,
1415 /* File operations */
1417 .open_fn
= cephwrap_open
,
1418 .close_fn
= cephwrap_close
,
1419 .read_fn
= cephwrap_read
,
1420 .pread_fn
= cephwrap_pread
,
1421 .write_fn
= cephwrap_write
,
1422 .pwrite_fn
= cephwrap_pwrite
,
1423 .lseek_fn
= cephwrap_lseek
,
1424 .sendfile_fn
= cephwrap_sendfile
,
1425 .recvfile_fn
= cephwrap_recvfile
,
1426 .rename_fn
= cephwrap_rename
,
1427 .fsync_fn
= cephwrap_fsync
,
1428 .stat_fn
= cephwrap_stat
,
1429 .fstat_fn
= cephwrap_fstat
,
1430 .lstat_fn
= cephwrap_lstat
,
1431 .unlink_fn
= cephwrap_unlink
,
1432 .chmod_fn
= cephwrap_chmod
,
1433 .fchmod_fn
= cephwrap_fchmod
,
1434 .chown_fn
= cephwrap_chown
,
1435 .fchown_fn
= cephwrap_fchown
,
1436 .lchown_fn
= cephwrap_lchown
,
1437 .chdir_fn
= cephwrap_chdir
,
1438 .getwd_fn
= cephwrap_getwd
,
1439 .ntimes_fn
= cephwrap_ntimes
,
1440 .ftruncate_fn
= cephwrap_ftruncate
,
1441 .lock_fn
= cephwrap_lock
,
1442 .kernel_flock_fn
= cephwrap_kernel_flock
,
1443 .linux_setlease_fn
= cephwrap_linux_setlease
,
1444 .getlock_fn
= cephwrap_getlock
,
1445 .symlink_fn
= cephwrap_symlink
,
1446 .readlink_fn
= cephwrap_readlink
,
1447 .link_fn
= cephwrap_link
,
1448 .mknod_fn
= cephwrap_mknod
,
1449 .realpath_fn
= cephwrap_realpath
,
1450 .chflags_fn
= cephwrap_chflags
,
1451 .get_real_filename_fn
= cephwrap_get_real_filename
,
1452 .connectpath_fn
= cephwrap_connectpath
,
1454 /* EA operations. */
1455 .getxattr_fn
= cephwrap_getxattr
,
1456 .fgetxattr_fn
= cephwrap_fgetxattr
,
1457 .listxattr_fn
= cephwrap_listxattr
,
1458 .flistxattr_fn
= cephwrap_flistxattr
,
1459 .removexattr_fn
= cephwrap_removexattr
,
1460 .fremovexattr_fn
= cephwrap_fremovexattr
,
1461 .setxattr_fn
= cephwrap_setxattr
,
1462 .fsetxattr_fn
= cephwrap_fsetxattr
,
1464 /* Posix ACL Operations */
1465 .sys_acl_get_file_fn
= posixacl_xattr_acl_get_file
,
1466 .sys_acl_get_fd_fn
= posixacl_xattr_acl_get_fd
,
1467 .sys_acl_blob_get_file_fn
= posix_sys_acl_blob_get_file
,
1468 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
1469 .sys_acl_set_file_fn
= posixacl_xattr_acl_set_file
,
1470 .sys_acl_set_fd_fn
= posixacl_xattr_acl_set_fd
,
1471 .sys_acl_delete_def_file_fn
= posixacl_xattr_acl_delete_def_file
,
1473 /* aio operations */
1474 .aio_force_fn
= cephwrap_aio_force
,
1477 NTSTATUS
vfs_ceph_init(TALLOC_CTX
*);
1478 NTSTATUS
vfs_ceph_init(TALLOC_CTX
*ctx
)
1480 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,