s4:dsdb/password_hash: split out a password_hash_needed() function
[Samba.git] / source3 / modules / vfs_ceph.c
blobb609d72bff9a359786c2e42a3f4bb9adfa7930ae
1 /*
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
28 * Ceph:
30 * vfs objects = ceph [any others you need go here]
33 #include "includes.h"
34 #include "smbd/smbd.h"
35 #include <dirent.h>
36 #include <sys/statvfs.h>
37 #include "cephfs/libcephfs.h"
38 #include "smbprofile.h"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_VFS
43 #ifndef LIBCEPHFS_VERSION
44 #define LIBCEPHFS_VERSION(maj, min, extra) ((maj << 16) + (min << 8) + extra)
45 #define LIBCEPHFS_VERSION_CODE LIBCEPHFS_VERSION(0, 0, 0)
46 #endif
49 * Use %llu whenever we have a 64bit unsigned int, and cast to (long long unsigned)
51 #define llu(_var) ((long long unsigned)_var)
54 * Note, libceph's return code model is to return -errno! So we have to convert
55 * to what Samba expects, with is set errno to -return and return -1
57 #define WRAP_RETURN(_res) \
58 errno = 0; \
59 if (_res < 0) { \
60 errno = -_res; \
61 return -1; \
62 } \
63 return _res \
66 * We mount only one file system and then all shares are assumed to be in that.
67 * FIXME: If we want to support more than one FS, then we have to deal with
68 * this differently.
70 * So, cmount tells us if we have been this way before and whether
71 * we need to mount ceph and cmount_cnt tells us how many times we have
72 * connected
74 static struct ceph_mount_info * cmount = NULL;
75 static uint32_t cmount_cnt = 0;
77 /* Check for NULL pointer parameters in cephwrap_* functions */
79 /* We don't want to have NULL function pointers lying around. Someone
80 is sure to try and execute them. These stubs are used to prevent
81 this possibility. */
83 static int cephwrap_connect(struct vfs_handle_struct *handle, const char *service, const char *user)
85 int ret;
86 char buf[256];
88 const char * conf_file;
90 if (cmount) {
91 handle->data = cmount; /* We have been here before */
92 cmount_cnt++;
93 return 0;
96 conf_file = lp_parm_const_string(SNUM(handle->conn), "ceph", "config_file", NULL);
98 DEBUG(2, ( "[CEPH] calling: ceph_create\n" ));
99 ret = ceph_create(&cmount, NULL);
100 if (ret)
101 goto err_out;
103 if (conf_file) {
104 /* Override the config file */
105 DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file\n" ));
106 ret = ceph_conf_read_file(cmount, conf_file);
107 } else {
109 DEBUG(2, ( "[CEPH] calling: ceph_conf_read_file with %s\n", conf_file));
110 ret = ceph_conf_read_file(cmount, NULL);
113 if (ret)
114 goto err_out;
116 DEBUG(2, ( "[CEPH] calling: ceph_conf_get\n" ));
117 ret = ceph_conf_get(cmount, "log file", buf, sizeof(buf));
118 if (ret < 0)
119 goto err_out;
121 DEBUG(2, ("[CEPH] calling: ceph_mount\n"));
122 ret = ceph_mount(cmount, NULL);
123 if (ret < 0)
124 goto err_out;
128 * encode mount context/state into our vfs/connection holding structure
129 * cmount is a ceph_mount_t*
131 handle->data = cmount;
132 cmount_cnt++;
134 return 0;
136 err_out:
138 * Handle the error correctly. Ceph returns -errno.
140 DEBUG(2, ("[CEPH] Error return: %s\n", strerror(-ret)));
141 WRAP_RETURN(ret);
144 static void cephwrap_disconnect(struct vfs_handle_struct *handle)
146 if (!cmount) {
147 DEBUG(0, ("[CEPH] Error, ceph not mounted\n"));
148 return;
151 /* Should we unmount/shutdown? Only if the last disconnect? */
152 if (--cmount_cnt) {
153 DEBUG(10, ("[CEPH] Not shuting down CEPH because still more connections\n"));
154 return;
157 ceph_shutdown(cmount);
159 cmount = NULL; /* Make it safe */
162 /* Disk operations */
164 static uint64_t cephwrap_disk_free(struct vfs_handle_struct *handle,
165 const char *path, uint64_t *bsize,
166 uint64_t *dfree, uint64_t *dsize)
168 struct statvfs statvfs_buf;
169 int ret;
171 if (!(ret = ceph_statfs(handle->data, path, &statvfs_buf))) {
173 * Provide all the correct values.
175 *bsize = statvfs_buf.f_bsize;
176 *dfree = statvfs_buf.f_bavail;
177 *dsize = statvfs_buf.f_blocks;
178 DEBUG(10, ("[CEPH] bsize: %llu, dfree: %llu, dsize: %llu\n",
179 llu(*bsize), llu(*dfree), llu(*dsize)));
180 return *dfree;
181 } else {
182 DEBUG(10, ("[CEPH] ceph_statfs returned %d\n", ret));
183 WRAP_RETURN(ret);
187 static int cephwrap_get_quota(struct vfs_handle_struct *handle,
188 const char *path, enum SMB_QUOTA_TYPE qtype,
189 unid_t id, SMB_DISK_QUOTA *qt)
191 /* libceph: Ceph does not implement this */
192 #if 0
193 /* was ifdef HAVE_SYS_QUOTAS */
194 int ret;
196 ret = ceph_get_quota(handle->conn->connectpath, qtype, id, qt);
198 if (ret) {
199 errno = -ret;
200 ret = -1;
203 return ret;
204 #else
205 errno = ENOSYS;
206 return -1;
207 #endif
210 static int cephwrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
212 /* libceph: Ceph does not implement this */
213 #if 0
214 /* was ifdef HAVE_SYS_QUOTAS */
215 int ret;
217 ret = ceph_set_quota(handle->conn->connectpath, qtype, id, qt);
218 if (ret) {
219 errno = -ret;
220 ret = -1;
223 return ret;
224 #else
225 WRAP_RETURN(-ENOSYS);
226 #endif
229 static int cephwrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
231 struct statvfs statvfs_buf;
232 int ret;
234 ret = ceph_statfs(handle->data, path, &statvfs_buf);
235 if (ret < 0) {
236 WRAP_RETURN(ret);
237 } else {
238 statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
239 statbuf->BlockSize = statvfs_buf.f_bsize;
240 statbuf->TotalBlocks = statvfs_buf.f_blocks;
241 statbuf->BlocksAvail = statvfs_buf.f_bfree;
242 statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
243 statbuf->TotalFileNodes = statvfs_buf.f_files;
244 statbuf->FreeFileNodes = statvfs_buf.f_ffree;
245 statbuf->FsIdentifier = statvfs_buf.f_fsid;
246 DEBUG(10, ("[CEPH] f_bsize: %ld, f_blocks: %ld, f_bfree: %ld, f_bavail: %ld\n",
247 (long int)statvfs_buf.f_bsize, (long int)statvfs_buf.f_blocks,
248 (long int)statvfs_buf.f_bfree, (long int)statvfs_buf.f_bavail));
250 return ret;
253 /* Directory operations */
255 static DIR *cephwrap_opendir(struct vfs_handle_struct *handle,
256 const struct smb_filename *smb_fname,
257 const char *mask, uint32_t attr)
259 int ret = 0;
260 struct ceph_dir_result *result;
261 DEBUG(10, ("[CEPH] opendir(%p, %s)\n", handle, smb_fname->base_name));
263 /* Returns NULL if it does not exist or there are problems ? */
264 ret = ceph_opendir(handle->data, smb_fname->base_name, &result);
265 if (ret < 0) {
266 result = NULL;
267 errno = -ret; /* We return result which is NULL in this case */
270 DEBUG(10, ("[CEPH] opendir(...) = %d\n", ret));
271 return (DIR *) result;
274 static DIR *cephwrap_fdopendir(struct vfs_handle_struct *handle,
275 struct files_struct *fsp,
276 const char *mask,
277 uint32_t attributes)
279 int ret = 0;
280 struct ceph_dir_result *result;
281 DEBUG(10, ("[CEPH] fdopendir(%p, %p)\n", handle, fsp));
283 ret = ceph_opendir(handle->data, fsp->fsp_name->base_name, &result);
284 if (ret < 0) {
285 result = NULL;
286 errno = -ret; /* We return result which is NULL in this case */
289 DEBUG(10, ("[CEPH] fdopendir(...) = %d\n", ret));
290 return (DIR *) result;
293 static struct dirent *cephwrap_readdir(struct vfs_handle_struct *handle,
294 DIR *dirp,
295 SMB_STRUCT_STAT *sbuf)
297 struct dirent *result;
299 DEBUG(10, ("[CEPH] readdir(%p, %p)\n", handle, dirp));
300 result = ceph_readdir(handle->data, (struct ceph_dir_result *) dirp);
301 DEBUG(10, ("[CEPH] readdir(...) = %p\n", result));
303 /* Default Posix readdir() does not give us stat info.
304 * Set to invalid to indicate we didn't return this info. */
305 if (sbuf)
306 SET_STAT_INVALID(*sbuf);
307 return result;
310 static void cephwrap_seekdir(struct vfs_handle_struct *handle, DIR *dirp, long offset)
312 DEBUG(10, ("[CEPH] seekdir(%p, %p, %ld)\n", handle, dirp, offset));
313 ceph_seekdir(handle->data, (struct ceph_dir_result *) dirp, offset);
316 static long cephwrap_telldir(struct vfs_handle_struct *handle, DIR *dirp)
318 long ret;
319 DEBUG(10, ("[CEPH] telldir(%p, %p)\n", handle, dirp));
320 ret = ceph_telldir(handle->data, (struct ceph_dir_result *) dirp);
321 DEBUG(10, ("[CEPH] telldir(...) = %ld\n", ret));
322 WRAP_RETURN(ret);
325 static void cephwrap_rewinddir(struct vfs_handle_struct *handle, DIR *dirp)
327 DEBUG(10, ("[CEPH] rewinddir(%p, %p)\n", handle, dirp));
328 ceph_rewinddir(handle->data, (struct ceph_dir_result *) dirp);
331 static int cephwrap_mkdir(struct vfs_handle_struct *handle,
332 const struct smb_filename *smb_fname,
333 mode_t mode)
335 int result;
336 bool has_dacl = False;
337 char *parent = NULL;
338 const char *path = smb_fname->base_name;
340 DEBUG(10, ("[CEPH] mkdir(%p, %s)\n", handle, path));
342 if (lp_inherit_acls(SNUM(handle->conn))
343 && parent_dirname(talloc_tos(), path, &parent, NULL)
344 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
345 mode = 0777;
347 TALLOC_FREE(parent);
349 result = ceph_mkdir(handle->data, path, mode);
352 * Note. This order is important
354 if (result) {
355 WRAP_RETURN(result);
356 } else if (result == 0 && !has_dacl) {
358 * We need to do this as the default behavior of POSIX ACLs
359 * is to set the mask to be the requested group permission
360 * bits, not the group permission bits to be the requested
361 * group permission bits. This is not what we want, as it will
362 * mess up any inherited ACL bits that were set. JRA.
364 int saved_errno = errno; /* We may get ENOSYS */
365 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
366 (errno == ENOSYS)) {
367 errno = saved_errno;
371 return result;
374 static int cephwrap_rmdir(struct vfs_handle_struct *handle,
375 const struct smb_filename *smb_fname)
377 int result;
379 DEBUG(10, ("[CEPH] rmdir(%p, %s)\n", handle, smb_fname->base_name));
380 result = ceph_rmdir(handle->data, smb_fname->base_name);
381 DEBUG(10, ("[CEPH] rmdir(...) = %d\n", result));
382 WRAP_RETURN(result);
385 static int cephwrap_closedir(struct vfs_handle_struct *handle, DIR *dirp)
387 int result;
389 DEBUG(10, ("[CEPH] closedir(%p, %p)\n", handle, dirp));
390 result = ceph_closedir(handle->data, (struct ceph_dir_result *) dirp);
391 DEBUG(10, ("[CEPH] closedir(...) = %d\n", result));
392 WRAP_RETURN(result);
395 /* File operations */
397 static int cephwrap_open(struct vfs_handle_struct *handle,
398 struct smb_filename *smb_fname,
399 files_struct *fsp, int flags, mode_t mode)
401 int result = -ENOENT;
402 DEBUG(10, ("[CEPH] open(%p, %s, %p, %d, %d)\n", handle, smb_fname_str_dbg(smb_fname), fsp, flags, mode));
404 if (smb_fname->stream_name) {
405 goto out;
408 result = ceph_open(handle->data, smb_fname->base_name, flags, mode);
409 out:
410 DEBUG(10, ("[CEPH] open(...) = %d\n", result));
411 WRAP_RETURN(result);
414 static int cephwrap_close(struct vfs_handle_struct *handle, files_struct *fsp)
416 int result;
418 DEBUG(10, ("[CEPH] close(%p, %p)\n", handle, fsp));
419 result = ceph_close(handle->data, fsp->fh->fd);
420 DEBUG(10, ("[CEPH] close(...) = %d\n", result));
422 WRAP_RETURN(result);
425 static ssize_t cephwrap_read(struct vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
427 ssize_t result;
429 DEBUG(10, ("[CEPH] read(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
431 /* Using -1 for the offset means read/write rather than pread/pwrite */
432 result = ceph_read(handle->data, fsp->fh->fd, data, n, -1);
433 DEBUG(10, ("[CEPH] read(...) = %llu\n", llu(result)));
434 WRAP_RETURN(result);
437 static ssize_t cephwrap_pread(struct vfs_handle_struct *handle, files_struct *fsp, void *data,
438 size_t n, off_t offset)
440 ssize_t result;
442 DEBUG(10, ("[CEPH] pread(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
444 result = ceph_read(handle->data, fsp->fh->fd, data, n, offset);
445 DEBUG(10, ("[CEPH] pread(...) = %llu\n", llu(result)));
446 WRAP_RETURN(result);
450 static ssize_t cephwrap_write(struct vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
452 ssize_t result;
454 DEBUG(10, ("[CEPH] write(%p, %p, %p, %llu)\n", handle, fsp, data, llu(n)));
456 result = ceph_write(handle->data, fsp->fh->fd, data, n, -1);
458 DEBUG(10, ("[CEPH] write(...) = %llu\n", llu(result)));
459 if (result < 0) {
460 WRAP_RETURN(result);
462 fsp->fh->pos += result;
463 return result;
466 static ssize_t cephwrap_pwrite(struct vfs_handle_struct *handle, files_struct *fsp, const void *data,
467 size_t n, off_t offset)
469 ssize_t result;
471 DEBUG(10, ("[CEPH] pwrite(%p, %p, %p, %llu, %llu)\n", handle, fsp, data, llu(n), llu(offset)));
472 result = ceph_write(handle->data, fsp->fh->fd, data, n, offset);
473 DEBUG(10, ("[CEPH] pwrite(...) = %llu\n", llu(result)));
474 WRAP_RETURN(result);
477 static off_t cephwrap_lseek(struct vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
479 off_t result = 0;
481 DEBUG(10, ("[CEPH] cephwrap_lseek\n"));
482 /* Cope with 'stat' file opens. */
483 if (fsp->fh->fd != -1) {
484 result = ceph_lseek(handle->data, fsp->fh->fd, offset, whence);
486 WRAP_RETURN(result);
489 static ssize_t cephwrap_sendfile(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
490 off_t offset, size_t n)
493 * We cannot support sendfile because libceph is in user space.
495 DEBUG(10, ("[CEPH] cephwrap_sendfile\n"));
496 errno = ENOTSUP;
497 return -1;
500 static ssize_t cephwrap_recvfile(struct vfs_handle_struct *handle,
501 int fromfd,
502 files_struct *tofsp,
503 off_t offset,
504 size_t n)
507 * We cannot support recvfile because libceph is in user space.
509 DEBUG(10, ("[CEPH] cephwrap_recvfile\n"));
510 errno=ENOTSUP;
511 return -1;
514 static int cephwrap_rename(struct vfs_handle_struct *handle,
515 const struct smb_filename *smb_fname_src,
516 const struct smb_filename *smb_fname_dst)
518 int result = -1;
519 DEBUG(10, ("[CEPH] cephwrap_rename\n"));
520 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
521 errno = ENOENT;
522 return result;
525 result = ceph_rename(handle->data, smb_fname_src->base_name, smb_fname_dst->base_name);
526 WRAP_RETURN(result);
529 static int cephwrap_fsync(struct vfs_handle_struct *handle, files_struct *fsp)
531 int result;
532 DEBUG(10, ("[CEPH] cephwrap_fsync\n"));
533 result = ceph_fsync(handle->data, fsp->fh->fd, false);
534 WRAP_RETURN(result);
537 static int cephwrap_stat(struct vfs_handle_struct *handle,
538 struct smb_filename *smb_fname)
540 int result = -1;
541 struct stat stbuf;
543 DEBUG(10, ("[CEPH] stat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
545 if (smb_fname->stream_name) {
546 errno = ENOENT;
547 return result;
550 result = ceph_stat(handle->data, smb_fname->base_name, (struct stat *) &stbuf);
551 DEBUG(10, ("[CEPH] stat(...) = %d\n", result));
552 if (result < 0) {
553 WRAP_RETURN(result);
554 } else {
555 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
556 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
557 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
558 llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
559 stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
560 llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
562 init_stat_ex_from_stat(
563 &smb_fname->st, &stbuf,
564 lp_fake_directory_create_times(SNUM(handle->conn)));
565 DEBUG(10, ("[CEPH] mode = 0x%x\n", smb_fname->st.st_ex_mode));
566 return result;
569 static int cephwrap_fstat(struct vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
571 int result = -1;
572 struct stat stbuf;
574 DEBUG(10, ("[CEPH] fstat(%p, %d)\n", handle, fsp->fh->fd));
575 result = ceph_fstat(handle->data, fsp->fh->fd, (struct stat *) &stbuf);
576 DEBUG(10, ("[CEPH] fstat(...) = %d\n", result));
577 if (result < 0) {
578 WRAP_RETURN(result);
579 } else {
580 DEBUG(10, ("[CEPH]\tstbuf = {dev = %llu, ino = %llu, mode = 0x%x, nlink = %llu, "
581 "uid = %d, gid = %d, rdev = %llu, size = %llu, blksize = %llu, "
582 "blocks = %llu, atime = %llu, mtime = %llu, ctime = %llu}\n",
583 llu(stbuf.st_dev), llu(stbuf.st_ino), stbuf.st_mode, llu(stbuf.st_nlink),
584 stbuf.st_uid, stbuf.st_gid, llu(stbuf.st_rdev), llu(stbuf.st_size), llu(stbuf.st_blksize),
585 llu(stbuf.st_blocks), llu(stbuf.st_atime), llu(stbuf.st_mtime), llu(stbuf.st_ctime)));
588 init_stat_ex_from_stat(
589 sbuf, &stbuf,
590 lp_fake_directory_create_times(SNUM(handle->conn)));
591 DEBUG(10, ("[CEPH] mode = 0x%x\n", sbuf->st_ex_mode));
592 return result;
595 static int cephwrap_lstat(struct vfs_handle_struct *handle,
596 struct smb_filename *smb_fname)
598 int result = -1;
599 struct stat stbuf;
601 DEBUG(10, ("[CEPH] lstat(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
603 if (smb_fname->stream_name) {
604 errno = ENOENT;
605 return result;
608 result = ceph_lstat(handle->data, smb_fname->base_name, &stbuf);
609 DEBUG(10, ("[CEPH] lstat(...) = %d\n", result));
610 if (result < 0) {
611 WRAP_RETURN(result);
613 init_stat_ex_from_stat(
614 &smb_fname->st, &stbuf,
615 lp_fake_directory_create_times(SNUM(handle->conn)));
616 return result;
619 static int cephwrap_unlink(struct vfs_handle_struct *handle,
620 const struct smb_filename *smb_fname)
622 int result = -1;
624 DEBUG(10, ("[CEPH] unlink(%p, %s)\n", handle, smb_fname_str_dbg(smb_fname)));
625 if (smb_fname->stream_name) {
626 errno = ENOENT;
627 return result;
629 result = ceph_unlink(handle->data, smb_fname->base_name);
630 DEBUG(10, ("[CEPH] unlink(...) = %d\n", result));
631 WRAP_RETURN(result);
634 static int cephwrap_chmod(struct vfs_handle_struct *handle,
635 const struct smb_filename *smb_fname,
636 mode_t mode)
638 int result;
640 DEBUG(10, ("[CEPH] chmod(%p, %s, %d)\n",
641 handle,
642 smb_fname->base_name,
643 mode));
646 * We need to do this due to the fact that the default POSIX ACL
647 * chmod modifies the ACL *mask* for the group owner, not the
648 * group owner bits directly. JRA.
653 int saved_errno = errno; /* We might get ENOSYS */
654 result = SMB_VFS_CHMOD_ACL(handle->conn,
655 smb_fname,
656 mode);
657 if (result == 0) {
658 return result;
660 /* Error - return the old errno. */
661 errno = saved_errno;
664 result = ceph_chmod(handle->data, smb_fname->base_name, mode);
665 DEBUG(10, ("[CEPH] chmod(...) = %d\n", result));
666 WRAP_RETURN(result);
669 static int cephwrap_fchmod(struct vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
671 int result;
673 DEBUG(10, ("[CEPH] fchmod(%p, %p, %d)\n", handle, fsp, mode));
676 * We need to do this due to the fact that the default POSIX ACL
677 * chmod modifies the ACL *mask* for the group owner, not the
678 * group owner bits directly. JRA.
682 int saved_errno = errno; /* We might get ENOSYS */
683 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
684 return result;
686 /* Error - return the old errno. */
687 errno = saved_errno;
690 #if defined(HAVE_FCHMOD)
691 result = ceph_fchmod(handle->data, fsp->fh->fd, mode);
692 DEBUG(10, ("[CEPH] fchmod(...) = %d\n", result));
693 WRAP_RETURN(result);
694 #else
695 errno = ENOSYS;
696 #endif
697 return -1;
700 static int cephwrap_chown(struct vfs_handle_struct *handle,
701 const struct smb_filename *smb_fname,
702 uid_t uid,
703 gid_t gid)
705 int result;
706 DEBUG(10, ("[CEPH] chown(%p, %s, %d, %d)\n",
707 handle,
708 smb_fname->base_name,
709 uid,
710 gid));
711 result = ceph_chown(handle->data, smb_fname->base_name, uid, gid);
712 DEBUG(10, ("[CEPH] chown(...) = %d\n", result));
713 WRAP_RETURN(result);
716 static int cephwrap_fchown(struct vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
718 int result;
719 #ifdef HAVE_FCHOWN
721 DEBUG(10, ("[CEPH] fchown(%p, %p, %d, %d)\n", handle, fsp, uid, gid));
722 result = ceph_fchown(handle->data, fsp->fh->fd, uid, gid);
723 DEBUG(10, ("[CEPH] fchown(...) = %d\n", result));
724 WRAP_RETURN(result);
725 #else
726 errno = ENOSYS;
727 result = -1;
728 #endif
729 return result;
732 static int cephwrap_lchown(struct vfs_handle_struct *handle,
733 const struct smb_filename *smb_fname,
734 uid_t uid,
735 gid_t gid)
737 int result;
738 DEBUG(10, ("[CEPH] lchown(%p, %s, %d, %d)\n",
739 handle,
740 smb_fname->base_name,
741 uid,
742 gid));
743 result = ceph_lchown(handle->data, smb_fname->base_name, uid, gid);
744 DEBUG(10, ("[CEPH] lchown(...) = %d\n", result));
745 WRAP_RETURN(result);
748 static int cephwrap_chdir(struct vfs_handle_struct *handle, const char *path)
750 int result = -1;
751 DEBUG(10, ("[CEPH] chdir(%p, %s)\n", handle, path));
753 * If the path is just / use chdir because Ceph is below / and
754 * cannot deal with changing directory above its mount point
756 if (path && !strcmp(path, "/"))
757 return chdir(path);
759 result = ceph_chdir(handle->data, path);
760 DEBUG(10, ("[CEPH] chdir(...) = %d\n", result));
761 WRAP_RETURN(result);
764 static char *cephwrap_getwd(struct vfs_handle_struct *handle)
766 const char *cwd = ceph_getcwd(handle->data);
767 DEBUG(10, ("[CEPH] getwd(%p) = %s\n", handle, cwd));
768 return SMB_STRDUP(cwd);
771 static int cephwrap_ntimes(struct vfs_handle_struct *handle,
772 const struct smb_filename *smb_fname,
773 struct smb_file_time *ft)
775 struct utimbuf buf;
776 int result;
778 if (null_timespec(ft->atime)) {
779 buf.actime = smb_fname->st.st_ex_atime.tv_sec;
780 } else {
781 buf.actime = ft->atime.tv_sec;
783 if (null_timespec(ft->mtime)) {
784 buf.modtime = smb_fname->st.st_ex_mtime.tv_sec;
785 } else {
786 buf.modtime = ft->mtime.tv_sec;
788 if (!null_timespec(ft->create_time)) {
789 set_create_timespec_ea(handle->conn, smb_fname,
790 ft->create_time);
792 if (buf.actime == smb_fname->st.st_ex_atime.tv_sec &&
793 buf.modtime == smb_fname->st.st_ex_mtime.tv_sec) {
794 return 0;
797 result = ceph_utime(handle->data, smb_fname->base_name, &buf);
798 DEBUG(10, ("[CEPH] ntimes(%p, %s, {%ld, %ld, %ld, %ld}) = %d\n", handle, smb_fname_str_dbg(smb_fname),
799 ft->mtime.tv_sec, ft->atime.tv_sec, ft->ctime.tv_sec,
800 ft->create_time.tv_sec, result));
801 return result;
804 static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
806 off_t space_to_write;
807 uint64_t space_avail;
808 uint64_t bsize,dfree,dsize;
809 int ret;
810 NTSTATUS status;
811 SMB_STRUCT_STAT *pst;
813 status = vfs_stat_fsp(fsp);
814 if (!NT_STATUS_IS_OK(status)) {
815 return -1;
817 pst = &fsp->fsp_name->st;
819 #ifdef S_ISFIFO
820 if (S_ISFIFO(pst->st_ex_mode))
821 return 0;
822 #endif
824 if (pst->st_ex_size == len)
825 return 0;
827 /* Shrink - just ftruncate. */
828 if (pst->st_ex_size > len)
829 return ftruncate(fsp->fh->fd, len);
831 space_to_write = len - pst->st_ex_size;
833 /* for allocation try fallocate first. This can fail on some
834 platforms e.g. when the filesystem doesn't support it and no
835 emulation is being done by the libc (like on AIX with JFS1). In that
836 case we do our own emulation. fallocate implementations can
837 return ENOTSUP or EINVAL in cases like that. */
838 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
839 if (ret == -1 && errno == ENOSPC) {
840 return -1;
842 if (ret == 0) {
843 return 0;
845 DEBUG(10,("[CEPH] strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
846 "error %d. Falling back to slow manual allocation\n", errno));
848 /* available disk space is enough or not? */
849 space_avail = get_dfree_info(fsp->conn,
850 fsp->fsp_name->base_name,
851 &bsize, &dfree, &dsize);
852 /* space_avail is 1k blocks */
853 if (space_avail == (uint64_t)-1 ||
854 ((uint64_t)space_to_write/1024 > space_avail) ) {
855 errno = ENOSPC;
856 return -1;
859 /* Write out the real space on disk. */
860 return vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
863 static int cephwrap_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
865 int result = -1;
866 SMB_STRUCT_STAT st;
867 char c = 0;
868 off_t currpos;
870 DEBUG(10, ("[CEPH] ftruncate(%p, %p, %llu\n", handle, fsp, llu(len)));
872 if (lp_strict_allocate(SNUM(fsp->conn))) {
873 result = strict_allocate_ftruncate(handle, fsp, len);
874 return result;
877 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
878 sys_ftruncate if the system supports it. Then I discovered that
879 you can have some filesystems that support ftruncate
880 expansion and some that don't! On Linux fat can't do
881 ftruncate extend but ext2 can. */
883 result = ceph_ftruncate(handle->data, fsp->fh->fd, len);
884 if (result == 0)
885 goto done;
887 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
888 extend a file with ftruncate. Provide alternate implementation
889 for this */
890 currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
891 if (currpos == -1) {
892 goto done;
895 /* Do an fstat to see if the file is longer than the requested
896 size in which case the ftruncate above should have
897 succeeded or shorter, in which case seek to len - 1 and
898 write 1 byte of zero */
899 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
900 goto done;
903 #ifdef S_ISFIFO
904 if (S_ISFIFO(st.st_ex_mode)) {
905 result = 0;
906 goto done;
908 #endif
910 if (st.st_ex_size == len) {
911 result = 0;
912 goto done;
915 if (st.st_ex_size > len) {
916 /* the sys_ftruncate should have worked */
917 goto done;
920 if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
921 goto done;
923 if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
924 goto done;
926 /* Seek to where we were */
927 if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
928 goto done;
929 result = 0;
931 done:
933 return result;
936 static bool cephwrap_lock(struct vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
938 DEBUG(10, ("[CEPH] lock\n"));
939 return true;
942 static int cephwrap_kernel_flock(struct vfs_handle_struct *handle, files_struct *fsp,
943 uint32_t share_mode, uint32_t access_mask)
945 DEBUG(10, ("[CEPH] kernel_flock\n"));
947 * We must return zero here and pretend all is good.
948 * One day we might have this in CEPH.
950 return 0;
953 static bool cephwrap_getlock(struct vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
955 DEBUG(10, ("[CEPH] getlock returning false and errno=0\n"));
957 errno = 0;
958 return false;
962 * We cannot let this fall through to the default, because the file might only
963 * be accessible from libceph (which is a user-space client) but the fd might
964 * be for some file the kernel knows about.
966 static int cephwrap_linux_setlease(struct vfs_handle_struct *handle, files_struct *fsp,
967 int leasetype)
969 int result = -1;
971 DEBUG(10, ("[CEPH] linux_setlease\n"));
972 errno = ENOSYS;
973 return result;
976 static int cephwrap_symlink(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
978 int result = -1;
979 DEBUG(10, ("[CEPH] symlink(%p, %s, %s)\n", handle, oldpath, newpath));
980 result = ceph_symlink(handle->data, oldpath, newpath);
981 DEBUG(10, ("[CEPH] symlink(...) = %d\n", result));
982 WRAP_RETURN(result);
985 static int cephwrap_readlink(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
987 int result = -1;
988 DEBUG(10, ("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz)));
989 result = ceph_readlink(handle->data, path, buf, bufsiz);
990 DEBUG(10, ("[CEPH] readlink(...) = %d\n", result));
991 WRAP_RETURN(result);
994 static int cephwrap_link(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath)
996 int result = -1;
997 DEBUG(10, ("[CEPH] link(%p, %s, %s)\n", handle, oldpath, newpath));
998 result = ceph_link(handle->data, oldpath, newpath);
999 DEBUG(10, ("[CEPH] link(...) = %d\n", result));
1000 WRAP_RETURN(result);
1003 static int cephwrap_mknod(struct vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
1005 int result = -1;
1006 DEBUG(10, ("[CEPH] mknod(%p, %s)\n", handle, pathname));
1007 result = ceph_mknod(handle->data, pathname, mode, dev);
1008 DEBUG(10, ("[CEPH] mknod(...) = %d\n", result));
1009 WRAP_RETURN(result);
1013 * This is a simple version of real-path ... a better version is needed to
1014 * ask libceph about symbolic links.
1016 static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path)
1018 char *result;
1019 size_t len = strlen(path);
1021 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
1022 if (len && (path[0] == '/')) {
1023 int r = asprintf(&result, "%s", path);
1024 if (r < 0) return NULL;
1025 } else if ((len >= 2) && (path[0] == '.') && (path[1] == '/')) {
1026 if (len == 2) {
1027 int r = asprintf(&result, "%s",
1028 handle->conn->connectpath);
1029 if (r < 0) return NULL;
1030 } else {
1031 int r = asprintf(&result, "%s/%s",
1032 handle->conn->connectpath, &path[2]);
1033 if (r < 0) return NULL;
1035 } else {
1036 int r = asprintf(&result, "%s/%s",
1037 handle->conn->connectpath, path);
1038 if (r < 0) return NULL;
1040 DEBUG(10, ("[CEPH] realpath(%p, %s) = %s\n", handle, path, result));
1041 return result;
1044 static int cephwrap_chflags(struct vfs_handle_struct *handle, const char *path,
1045 unsigned int flags)
1047 errno = ENOSYS;
1048 return -1;
1051 static int cephwrap_get_real_filename(struct vfs_handle_struct *handle,
1052 const char *path,
1053 const char *name,
1054 TALLOC_CTX *mem_ctx,
1055 char **found_name)
1058 * Don't fall back to get_real_filename so callers can differentiate
1059 * between a full directory scan and an actual case-insensitive stat.
1061 errno = EOPNOTSUPP;
1062 return -1;
1065 static const char *cephwrap_connectpath(struct vfs_handle_struct *handle,
1066 const char *fname)
1068 return handle->conn->connectpath;
1071 /****************************************************************
1072 Extended attribute operations.
1073 *****************************************************************/
1075 static ssize_t cephwrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1077 int ret;
1078 DEBUG(10, ("[CEPH] getxattr(%p, %s, %s, %p, %llu)\n", handle, path, name, value, llu(size)));
1079 ret = ceph_getxattr(handle->data, path, name, value, size);
1080 DEBUG(10, ("[CEPH] getxattr(...) = %d\n", ret));
1081 if (ret < 0) {
1082 WRAP_RETURN(ret);
1083 } else {
1084 return (ssize_t)ret;
1088 static ssize_t cephwrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1090 int ret;
1091 DEBUG(10, ("[CEPH] fgetxattr(%p, %p, %s, %p, %llu)\n", handle, fsp, name, value, llu(size)));
1092 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1093 ret = ceph_fgetxattr(handle->data, fsp->fh->fd, name, value, size);
1094 #else
1095 ret = ceph_getxattr(handle->data, fsp->fsp_name->base_name, name, value, size);
1096 #endif
1097 DEBUG(10, ("[CEPH] fgetxattr(...) = %d\n", ret));
1098 if (ret < 0) {
1099 WRAP_RETURN(ret);
1100 } else {
1101 return (ssize_t)ret;
1105 static ssize_t cephwrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1107 int ret;
1108 DEBUG(10, ("[CEPH] listxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1109 ret = ceph_listxattr(handle->data, path, list, size);
1110 DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1111 if (ret < 0) {
1112 WRAP_RETURN(ret);
1113 } else {
1114 return (ssize_t)ret;
1118 #if 0
1119 static ssize_t cephwrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1121 int ret;
1122 DEBUG(10, ("[CEPH] llistxattr(%p, %s, %p, %llu)\n", handle, path, list, llu(size)));
1123 ret = ceph_llistxattr(handle->data, path, list, size);
1124 DEBUG(10, ("[CEPH] listxattr(...) = %d\n", ret));
1125 if (ret < 0) {
1126 WRAP_RETURN(ret);
1127 } else {
1128 return (ssize_t)ret;
1131 #endif
1133 static ssize_t cephwrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1135 int ret;
1136 DEBUG(10, ("[CEPH] flistxattr(%p, %p, %s, %llu)\n", handle, fsp, list, llu(size)));
1137 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1138 ret = ceph_flistxattr(handle->data, fsp->fh->fd, list, size);
1139 #else
1140 ret = ceph_listxattr(handle->data, fsp->fsp_name->base_name, list, size);
1141 #endif
1142 DEBUG(10, ("[CEPH] flistxattr(...) = %d\n", ret));
1143 if (ret < 0) {
1144 WRAP_RETURN(ret);
1145 } else {
1146 return (ssize_t)ret;
1150 static int cephwrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1152 int ret;
1153 DEBUG(10, ("[CEPH] removexattr(%p, %s, %s)\n", handle, path, name));
1154 ret = ceph_removexattr(handle->data, path, name);
1155 DEBUG(10, ("[CEPH] removexattr(...) = %d\n", ret));
1156 WRAP_RETURN(ret);
1159 static int cephwrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1161 int ret;
1162 DEBUG(10, ("[CEPH] fremovexattr(%p, %p, %s)\n", handle, fsp, name));
1163 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1164 ret = ceph_fremovexattr(handle->data, fsp->fh->fd, name);
1165 #else
1166 ret = ceph_removexattr(handle->data, fsp->fsp_name->base_name, name);
1167 #endif
1168 DEBUG(10, ("[CEPH] fremovexattr(...) = %d\n", ret));
1169 WRAP_RETURN(ret);
1172 static int cephwrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1174 int ret;
1175 DEBUG(10, ("[CEPH] setxattr(%p, %s, %s, %p, %llu, %d)\n", handle, path, name, value, llu(size), flags));
1176 ret = ceph_setxattr(handle->data, path, name, value, size, flags);
1177 DEBUG(10, ("[CEPH] setxattr(...) = %d\n", ret));
1178 WRAP_RETURN(ret);
1181 static int cephwrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1183 int ret;
1184 DEBUG(10, ("[CEPH] fsetxattr(%p, %p, %s, %p, %llu, %d)\n", handle, fsp, name, value, llu(size), flags));
1185 #if LIBCEPHFS_VERSION_CODE >= LIBCEPHFS_VERSION(0, 94, 0)
1186 ret = ceph_fsetxattr(handle->data, fsp->fh->fd,
1187 name, value, size, flags);
1188 #else
1189 ret = ceph_setxattr(handle->data, fsp->fsp_name->base_name, name, value, size, flags);
1190 #endif
1191 DEBUG(10, ("[CEPH] fsetxattr(...) = %d\n", ret));
1192 WRAP_RETURN(ret);
1195 static bool cephwrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1199 * We do not support AIO yet.
1202 DEBUG(10, ("[CEPH] cephwrap_aio_force(%p, %p) = false (errno = ENOTSUP)\n", handle, fsp));
1203 errno = ENOTSUP;
1204 return false;
1207 static bool cephwrap_is_offline(struct vfs_handle_struct *handle,
1208 const struct smb_filename *fname,
1209 SMB_STRUCT_STAT *sbuf)
1211 return false;
1214 static int cephwrap_set_offline(struct vfs_handle_struct *handle,
1215 const struct smb_filename *fname)
1217 errno = ENOTSUP;
1218 return -1;
1221 static SMB_ACL_T cephwrap_sys_acl_get_file(struct vfs_handle_struct *handle,
1222 const char *path_p,
1223 SMB_ACL_TYPE_T type,
1224 TALLOC_CTX *mem_ctx)
1226 errno = ENOTSUP;
1227 return NULL;
1230 static SMB_ACL_T cephwrap_sys_acl_get_fd(struct vfs_handle_struct *handle,
1231 struct files_struct *fsp,
1232 TALLOC_CTX *mem_ctx)
1234 errno = ENOTSUP;
1235 return NULL;
1238 static int cephwrap_sys_acl_set_file(struct vfs_handle_struct *handle,
1239 const char *name,
1240 SMB_ACL_TYPE_T acltype,
1241 SMB_ACL_T theacl)
1243 errno = ENOTSUP;
1244 return -1;
1247 static int cephwrap_sys_acl_set_fd(struct vfs_handle_struct *handle,
1248 struct files_struct *fsp,
1249 SMB_ACL_T theacl)
1251 errno = ENOTSUP;
1252 return -1;
1255 static int cephwrap_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
1256 const char *path)
1258 errno = ENOTSUP;
1259 return -1;
1262 static struct vfs_fn_pointers ceph_fns = {
1263 /* Disk operations */
1265 .connect_fn = cephwrap_connect,
1266 .disconnect_fn = cephwrap_disconnect,
1267 .disk_free_fn = cephwrap_disk_free,
1268 .get_quota_fn = cephwrap_get_quota,
1269 .set_quota_fn = cephwrap_set_quota,
1270 .statvfs_fn = cephwrap_statvfs,
1272 /* Directory operations */
1274 .opendir_fn = cephwrap_opendir,
1275 .fdopendir_fn = cephwrap_fdopendir,
1276 .readdir_fn = cephwrap_readdir,
1277 .seekdir_fn = cephwrap_seekdir,
1278 .telldir_fn = cephwrap_telldir,
1279 .rewind_dir_fn = cephwrap_rewinddir,
1280 .mkdir_fn = cephwrap_mkdir,
1281 .rmdir_fn = cephwrap_rmdir,
1282 .closedir_fn = cephwrap_closedir,
1284 /* File operations */
1286 .open_fn = cephwrap_open,
1287 .close_fn = cephwrap_close,
1288 .read_fn = cephwrap_read,
1289 .pread_fn = cephwrap_pread,
1290 .write_fn = cephwrap_write,
1291 .pwrite_fn = cephwrap_pwrite,
1292 .lseek_fn = cephwrap_lseek,
1293 .sendfile_fn = cephwrap_sendfile,
1294 .recvfile_fn = cephwrap_recvfile,
1295 .rename_fn = cephwrap_rename,
1296 .fsync_fn = cephwrap_fsync,
1297 .stat_fn = cephwrap_stat,
1298 .fstat_fn = cephwrap_fstat,
1299 .lstat_fn = cephwrap_lstat,
1300 .unlink_fn = cephwrap_unlink,
1301 .chmod_fn = cephwrap_chmod,
1302 .fchmod_fn = cephwrap_fchmod,
1303 .chown_fn = cephwrap_chown,
1304 .fchown_fn = cephwrap_fchown,
1305 .lchown_fn = cephwrap_lchown,
1306 .chdir_fn = cephwrap_chdir,
1307 .getwd_fn = cephwrap_getwd,
1308 .ntimes_fn = cephwrap_ntimes,
1309 .ftruncate_fn = cephwrap_ftruncate,
1310 .lock_fn = cephwrap_lock,
1311 .kernel_flock_fn = cephwrap_kernel_flock,
1312 .linux_setlease_fn = cephwrap_linux_setlease,
1313 .getlock_fn = cephwrap_getlock,
1314 .symlink_fn = cephwrap_symlink,
1315 .readlink_fn = cephwrap_readlink,
1316 .link_fn = cephwrap_link,
1317 .mknod_fn = cephwrap_mknod,
1318 .realpath_fn = cephwrap_realpath,
1319 .chflags_fn = cephwrap_chflags,
1320 .get_real_filename_fn = cephwrap_get_real_filename,
1321 .connectpath_fn = cephwrap_connectpath,
1323 /* EA operations. */
1324 .getxattr_fn = cephwrap_getxattr,
1325 .fgetxattr_fn = cephwrap_fgetxattr,
1326 .listxattr_fn = cephwrap_listxattr,
1327 .flistxattr_fn = cephwrap_flistxattr,
1328 .removexattr_fn = cephwrap_removexattr,
1329 .fremovexattr_fn = cephwrap_fremovexattr,
1330 .setxattr_fn = cephwrap_setxattr,
1331 .fsetxattr_fn = cephwrap_fsetxattr,
1333 /* Posix ACL Operations */
1334 .sys_acl_get_file_fn = cephwrap_sys_acl_get_file,
1335 .sys_acl_get_fd_fn = cephwrap_sys_acl_get_fd,
1336 .sys_acl_set_file_fn = cephwrap_sys_acl_set_file,
1337 .sys_acl_set_fd_fn = cephwrap_sys_acl_set_fd,
1338 .sys_acl_delete_def_file_fn = cephwrap_sys_acl_delete_def_file,
1340 /* aio operations */
1341 .aio_force_fn = cephwrap_aio_force,
1343 /* offline operations */
1344 .is_offline_fn = cephwrap_is_offline,
1345 .set_offline_fn = cephwrap_set_offline
1348 NTSTATUS vfs_ceph_init(void);
1349 NTSTATUS vfs_ceph_init(void)
1351 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1352 "ceph", &ceph_fns);